blob: 812f23321087b1e88419181598367e7662e4e5a1 [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 *
Jesus Ceaca3939c2008-05-22 15:27:38 +000053 * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>.
Jesus Ceaef9764f2008-05-13 18:45:46 +000054 * 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
Gregory P. Smith572226c2008-05-26 19:03:35 +0000107#if (PY_VERSION_HEX < 0x02060000) /* really: before python trunk r63675 */
108/* This code now uses PyBytes* API function names instead of PyString*.
109 * These #defines map to their equivalent on earlier python versions. */
110#define PyBytes_FromStringAndSize PyString_FromStringAndSize
111#define PyBytes_FromString PyString_FromString
112#define PyBytes_AsStringAndSize PyString_AsStringAndSize
113#define PyBytes_Check PyString_Check
114#define PyBytes_GET_SIZE PyString_GET_SIZE
115#define PyBytes_AS_STRING PyString_AS_STRING
116#endif
117
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000118#ifdef WITH_THREAD
119
120/* These are for when calling Python --> C */
121#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
122#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
123
Mark Hammonda69d4092003-04-22 23:13:27 +0000124/* For 2.3, use the PyGILState_ calls */
125#if (PY_VERSION_HEX >= 0x02030000)
126#define MYDB_USE_GILSTATE
127#endif
128
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000129/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000130#if defined(MYDB_USE_GILSTATE)
131#define MYDB_BEGIN_BLOCK_THREADS \
132 PyGILState_STATE __savestate = PyGILState_Ensure();
133#define MYDB_END_BLOCK_THREADS \
134 PyGILState_Release(__savestate);
135#else /* MYDB_USE_GILSTATE */
136/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000137static PyInterpreterState* _db_interpreterState = NULL;
138#define MYDB_BEGIN_BLOCK_THREADS { \
139 PyThreadState* prevState; \
140 PyThreadState* newState; \
141 PyEval_AcquireLock(); \
142 newState = PyThreadState_New(_db_interpreterState); \
143 prevState = PyThreadState_Swap(newState);
144
145#define MYDB_END_BLOCK_THREADS \
146 newState = PyThreadState_Swap(prevState); \
147 PyThreadState_Clear(newState); \
148 PyEval_ReleaseLock(); \
149 PyThreadState_Delete(newState); \
150 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000151#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000152
153#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000154/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000155#define MYDB_BEGIN_ALLOW_THREADS
156#define MYDB_END_ALLOW_THREADS
157#define MYDB_BEGIN_BLOCK_THREADS
158#define MYDB_END_BLOCK_THREADS
159
160#endif
161
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162/* Should DB_INCOMPLETE be turned into a warning or an exception? */
163#define INCOMPLETE_IS_WARNING 1
164
165/* --------------------------------------------------------------------- */
166/* Exceptions */
167
168static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000169static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000170static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000171static PyObject* DBKeyExistError; /* DB_KEYEXIST */
172static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
173static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
174static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
175static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
176static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
177static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
178static PyObject* DBNoServerError; /* DB_NOSERVER */
179static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
180static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
181#if (DBVER >= 33)
182static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
183static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
184#endif
185
186#if !INCOMPLETE_IS_WARNING
187static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
188#endif
189
190static PyObject* DBInvalidArgError; /* EINVAL */
191static PyObject* DBAccessError; /* EACCES */
192static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000193static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000194static PyObject* DBAgainError; /* EAGAIN */
195static PyObject* DBBusyError; /* EBUSY */
196static PyObject* DBFileExistsError; /* EEXIST */
197static PyObject* DBNoSuchFileError; /* ENOENT */
198static PyObject* DBPermissionsError; /* EPERM */
199
Jesus Ceaef9764f2008-05-13 18:45:46 +0000200#if (DBVER >= 42)
201static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
202#endif
203
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000204#if (DBVER < 43)
205#define DB_BUFFER_SMALL ENOMEM
206#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000207
208
209/* --------------------------------------------------------------------- */
210/* Structure definitions */
211
Gregory P. Smith39250532007-10-09 06:02:21 +0000212#if PYTHON_API_VERSION < 1010
213#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000214#endif
215
Gregory P. Smith31c50652004-06-28 01:20:40 +0000216
Gregory P. Smith39250532007-10-09 06:02:21 +0000217/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000218#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000219#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000220
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000221
222staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000223#if (DBVER >= 43)
224staticforward PyTypeObject DBSequence_Type;
225#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000226
Martin v. Löwis83c92012008-04-24 13:17:24 +0000227#ifndef Py_TYPE
Gregory P. Smithfc006692007-11-05 09:06:28 +0000228/* for compatibility with Python 2.5 and earlier */
Christian Heimese93237d2007-12-19 02:37:44 +0000229#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
Gregory P. Smithfc006692007-11-05 09:06:28 +0000230#endif
231
Christian Heimese93237d2007-12-19 02:37:44 +0000232#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
233#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
234#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
235#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
236#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000237#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +0000238#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000239#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000240
Jesus Ceaef9764f2008-05-13 18:45:46 +0000241#if (DBVER < 46)
242 #define _DBC_close(dbc) dbc->c_close(dbc)
243 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
244 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
245 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
246 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
247 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
248 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
249#else
250 #define _DBC_close(dbc) dbc->close(dbc)
251 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
252 #define _DBC_del(dbc,a) dbc->del(dbc,a)
253 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
254 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
255 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
256 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
257#endif
258
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000259
260/* --------------------------------------------------------------------- */
261/* Utility macros and functions */
262
Jesus Ceaef9764f2008-05-13 18:45:46 +0000263#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
264 { \
265 object->sibling_next=backlink; \
266 object->sibling_prev_p=&(backlink); \
267 backlink=object; \
268 if (object->sibling_next) { \
269 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
270 } \
271 }
272
273#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
274 { \
275 if (object->sibling_next) { \
276 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
277 } \
278 *(object->sibling_prev_p)=object->sibling_next; \
279 }
280
281#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
282 { \
283 if (object->sibling_next) { \
284 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
285 } \
286 if (object->sibling_prev_p) { \
287 *(object->sibling_prev_p)=object->sibling_next; \
288 } \
289 }
290
291#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
292 { \
293 object->sibling_next_txn=backlink; \
294 object->sibling_prev_p_txn=&(backlink); \
295 backlink=object; \
296 if (object->sibling_next_txn) { \
297 object->sibling_next_txn->sibling_prev_p_txn= \
298 &(object->sibling_next_txn); \
299 } \
300 }
301
302#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
303 { \
304 if (object->sibling_next_txn) { \
305 object->sibling_next_txn->sibling_prev_p_txn= \
306 object->sibling_prev_p_txn; \
307 } \
308 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
309 }
310
311
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000312#define RETURN_IF_ERR() \
313 if (makeDBError(err)) { \
314 return NULL; \
315 }
316
317#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
318
Gregory P. Smithe2767172003-11-02 08:06:29 +0000319#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
320 if ((nonNull) == NULL) { \
321 PyObject *errTuple = NULL; \
322 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
323 PyErr_SetObject((pyErrObj), errTuple); \
324 Py_DECREF(errTuple); \
325 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000326 }
327
Gregory P. Smithe2767172003-11-02 08:06:29 +0000328#define CHECK_DB_NOT_CLOSED(dbobj) \
329 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
330
331#define CHECK_ENV_NOT_CLOSED(env) \
332 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000333
334#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000335 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000336
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000337#if (DBVER >= 43)
338#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
339 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
340#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000341
342#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
343 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
344
345#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
346
347#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000348 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000349
350
351static int makeDBError(int err);
352
353
354/* Return the access method type of the DBObject */
355static int _DB_get_type(DBObject* self)
356{
357#if (DBVER >= 33)
358 DBTYPE type;
359 int err;
360 err = self->db->get_type(self->db, &type);
361 if (makeDBError(err)) {
362 return -1;
363 }
364 return type;
365#else
366 return self->db->get_type(self->db);
367#endif
368}
369
370
371/* Create a DBT structure (containing key and data values) from Python
372 strings. Returns 1 on success, 0 on an error. */
373static int make_dbt(PyObject* obj, DBT* dbt)
374{
375 CLEAR_DBT(*dbt);
376 if (obj == Py_None) {
377 /* no need to do anything, the structure has already been zeroed */
378 }
379 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
380 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000381 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000382 return 0;
383 }
384 return 1;
385}
386
387
388/* Recno and Queue DBs can have integer keys. This function figures out
389 what's been given, verifies that it's allowed, and then makes the DBT.
390
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000391 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000392static int
393make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000394{
395 db_recno_t recno;
396 int type;
397
398 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000399 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000400 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000401 if (type == -1)
402 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000403 if (type == DB_RECNO || type == DB_QUEUE) {
404 PyErr_SetString(
405 PyExc_TypeError,
406 "None keys not allowed for Recno and Queue DB's");
407 return 0;
408 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000409 /* no need to do anything, the structure has already been zeroed */
410 }
411
Christian Heimes593daf52008-05-26 12:51:38 +0000412 else if (PyBytes_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000413 /* verify access method type */
414 type = _DB_get_type(self);
415 if (type == -1)
416 return 0;
417 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000418 PyErr_SetString(
419 PyExc_TypeError,
420 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000421 return 0;
422 }
423
Gregory P. Smith10bed542007-10-09 06:50:43 +0000424 /*
425 * NOTE(gps): I don't like doing a data copy here, it seems
426 * wasteful. But without a clean way to tell FREE_DBT if it
427 * should free key->data or not we have to. Other places in
428 * the code check for DB_THREAD and forceably set DBT_MALLOC
429 * when we otherwise would leave flags 0 to indicate that.
430 */
Christian Heimes593daf52008-05-26 12:51:38 +0000431 key->data = malloc(PyBytes_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000432 if (key->data == NULL) {
433 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
434 return 0;
435 }
Christian Heimes593daf52008-05-26 12:51:38 +0000436 memcpy(key->data, PyBytes_AS_STRING(keyobj),
437 PyBytes_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000438 key->flags = DB_DBT_REALLOC;
Christian Heimes593daf52008-05-26 12:51:38 +0000439 key->size = PyBytes_GET_SIZE(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000440 }
441
442 else if (PyInt_Check(keyobj)) {
443 /* verify access method type */
444 type = _DB_get_type(self);
445 if (type == -1)
446 return 0;
447 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000448 /* if BTREE then an Integer key is allowed with the
449 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000450 *pflags |= DB_SET_RECNO;
451 }
452 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000453 PyErr_SetString(
454 PyExc_TypeError,
455 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000456 return 0;
457 }
458
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000459 /* Make a key out of the requested recno, use allocated space so DB
460 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000461 recno = PyInt_AS_LONG(keyobj);
462 key->data = malloc(sizeof(db_recno_t));
463 if (key->data == NULL) {
464 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
465 return 0;
466 }
467 key->ulen = key->size = sizeof(db_recno_t);
468 memcpy(key->data, &recno, sizeof(db_recno_t));
469 key->flags = DB_DBT_REALLOC;
470 }
471 else {
472 PyErr_Format(PyExc_TypeError,
473 "String or Integer object expected for key, %s found",
Christian Heimese93237d2007-12-19 02:37:44 +0000474 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000475 return 0;
476 }
477
478 return 1;
479}
480
481
482/* Add partial record access to an existing DBT data struct.
483 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
484 and the data storage/retrieval will be done using dlen and doff. */
485static int add_partial_dbt(DBT* d, int dlen, int doff) {
486 /* if neither were set we do nothing (-1 is the default value) */
487 if ((dlen == -1) && (doff == -1)) {
488 return 1;
489 }
490
491 if ((dlen < 0) || (doff < 0)) {
492 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
493 return 0;
494 }
495
496 d->flags = d->flags | DB_DBT_PARTIAL;
497 d->dlen = (unsigned int) dlen;
498 d->doff = (unsigned int) doff;
499 return 1;
500}
501
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000502/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
503/* TODO: make this use the native libc strlcpy() when available (BSD) */
504unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
505{
506 unsigned int srclen, copylen;
507
508 srclen = strlen(src);
509 if (n <= 0)
510 return srclen;
511 copylen = (srclen > n-1) ? n-1 : srclen;
512 /* populate dest[0] thru dest[copylen-1] */
513 memcpy(dest, src, copylen);
514 /* guarantee null termination */
515 dest[copylen] = 0;
516
517 return srclen;
518}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000519
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000520/* Callback used to save away more information about errors from the DB
521 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000522static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000523#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000524static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000525#else
526static void _db_errorCallback(const DB_ENV *db_env,
527 const char* prefix, const char* msg)
528#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000529{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000530 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000531}
532
533
Jesus Ceaef9764f2008-05-13 18:45:46 +0000534/*
535** We need these functions because some results
536** are undefined if pointer is NULL. Some other
537** give None instead of "".
538**
539** This functions are static and will be
540** -I hope- inlined.
541*/
542static const char *DummyString = "This string is a simple placeholder";
543static PyObject *Build_PyString(const char *p,int s)
544{
545 if (!p) {
546 p=DummyString;
547 assert(s==0);
548 }
Christian Heimes593daf52008-05-26 12:51:38 +0000549 return PyBytes_FromStringAndSize(p,s);
Jesus Ceaef9764f2008-05-13 18:45:46 +0000550}
551
552static PyObject *BuildValue_S(const void *p,int s)
553{
554 if (!p) {
555 p=DummyString;
556 assert(s==0);
557 }
558 return Py_BuildValue("s#",p,s);
559}
560
561static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
562{
563 if (!p1) {
564 p1=DummyString;
565 assert(s1==0);
566 }
567 if (!p2) {
568 p2=DummyString;
569 assert(s2==0);
570 }
571 return Py_BuildValue("s#s#",p1,s1,p2,s2);
572}
573
574static PyObject *BuildValue_IS(int i,const void *p,int s)
575{
576 if (!p) {
577 p=DummyString;
578 assert(s==0);
579 }
580 return Py_BuildValue("is#",i,p,s);
581}
582
583static PyObject *BuildValue_LS(long i,const void *p,int s)
584{
585 if (!p) {
586 p=DummyString;
587 assert(s==0);
588 }
589 return Py_BuildValue("ls#",i,p,s);
590}
591
592
593
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000594/* make a nice exception object to raise for errors. */
595static int makeDBError(int err)
596{
597 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000598 PyObject *errObj = NULL;
599 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000600 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000601 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000602
603 switch (err) {
604 case 0: /* successful, no error */ break;
605
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000606#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000607 case DB_INCOMPLETE:
608#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000609 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
610 /* Ensure that bytes_left never goes negative */
611 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
612 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
613 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000614 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000615 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000616 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000617 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000618 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000619
620#else /* do an exception instead */
621 errObj = DBIncompleteError;
622#endif
623 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000624#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000625
626 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
627 case DB_KEYEXIST: errObj = DBKeyExistError; break;
628 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
629 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
630 case DB_NOTFOUND: errObj = DBNotFoundError; break;
631 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
632 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
633 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
634 case DB_NOSERVER: errObj = DBNoServerError; break;
635 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
636 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
637#if (DBVER >= 33)
638 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
639 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
640#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000641 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000642
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000643#if (DBVER >= 43)
644 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
645 case ENOMEM: errObj = PyExc_MemoryError; break;
646#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000647 case EINVAL: errObj = DBInvalidArgError; break;
648 case EACCES: errObj = DBAccessError; break;
649 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000650 case EAGAIN: errObj = DBAgainError; break;
651 case EBUSY : errObj = DBBusyError; break;
652 case EEXIST: errObj = DBFileExistsError; break;
653 case ENOENT: errObj = DBNoSuchFileError; break;
654 case EPERM : errObj = DBPermissionsError; break;
655
Jesus Ceaef9764f2008-05-13 18:45:46 +0000656#if (DBVER >= 42)
657 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
658#endif
659
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000660 default: errObj = DBError; break;
661 }
662
663 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000664 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
665 /* Ensure that bytes_left never goes negative */
666 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
667 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
668 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000669 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000670 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000671 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000672 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000673
674 errTuple = Py_BuildValue("(is)", err, errTxt);
675 PyErr_SetObject(errObj, errTuple);
676 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000677 }
678
679 return ((errObj != NULL) || exceptionRaised);
680}
681
682
683
684/* set a type exception */
685static void makeTypeError(char* expected, PyObject* found)
686{
687 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimese93237d2007-12-19 02:37:44 +0000688 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000689}
690
691
692/* verify that an obj is either None or a DBTxn, and set the txn pointer */
693static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
694{
695 if (txnobj == Py_None || txnobj == NULL) {
696 *txn = NULL;
697 return 1;
698 }
699 if (DBTxnObject_Check(txnobj)) {
700 *txn = ((DBTxnObject*)txnobj)->txn;
701 return 1;
702 }
703 else
704 makeTypeError("DBTxn", txnobj);
705 return 0;
706}
707
708
709/* Delete a key from a database
710 Returns 0 on success, -1 on an error. */
711static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
712{
713 int err;
714
715 MYDB_BEGIN_ALLOW_THREADS;
716 err = self->db->del(self->db, txn, key, 0);
717 MYDB_END_ALLOW_THREADS;
718 if (makeDBError(err)) {
719 return -1;
720 }
721 self->haveStat = 0;
722 return 0;
723}
724
725
726/* Store a key into a database
727 Returns 0 on success, -1 on an error. */
728static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
729{
730 int err;
731
732 MYDB_BEGIN_ALLOW_THREADS;
733 err = self->db->put(self->db, txn, key, data, flags);
734 MYDB_END_ALLOW_THREADS;
735 if (makeDBError(err)) {
736 return -1;
737 }
738 self->haveStat = 0;
739 return 0;
740}
741
742/* Get a key/data pair from a cursor */
743static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
744 PyObject *args, PyObject *kwargs, char *format)
745{
746 int err;
747 PyObject* retval = NULL;
748 DBT key, data;
749 int dlen = -1;
750 int doff = -1;
751 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000752 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000753
754 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
755 &flags, &dlen, &doff))
756 return NULL;
757
758 CHECK_CURSOR_NOT_CLOSED(self);
759
760 flags |= extra_flags;
761 CLEAR_DBT(key);
762 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000763 if (!add_partial_dbt(&data, dlen, doff))
764 return NULL;
765
766 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000767 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000768 MYDB_END_ALLOW_THREADS;
769
Gregory P. Smithe9477062005-06-04 06:46:59 +0000770 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
771 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000772 Py_INCREF(Py_None);
773 retval = Py_None;
774 }
775 else if (makeDBError(err)) {
776 retval = NULL;
777 }
778 else { /* otherwise, success! */
779
780 /* if Recno or Queue, return the key as an Int */
781 switch (_DB_get_type(self->mydb)) {
782 case -1:
783 retval = NULL;
784 break;
785
786 case DB_RECNO:
787 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000788 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000789 break;
790 case DB_HASH:
791 case DB_BTREE:
792 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000793 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000794 break;
795 }
796 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000797 return retval;
798}
799
800
801/* add an integer to a dictionary using the given name as a key */
802static void _addIntToDict(PyObject* dict, char *name, int value)
803{
804 PyObject* v = PyInt_FromLong((long) value);
805 if (!v || PyDict_SetItemString(dict, name, v))
806 PyErr_Clear();
807
808 Py_XDECREF(v);
809}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000810
811/* The same, when the value is a time_t */
812static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
813{
814 PyObject* v;
815 /* if the value fits in regular int, use that. */
Jesus Ceaef9764f2008-05-13 18:45:46 +0000816#ifdef PY_LONG_LONG
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000817 if (sizeof(time_t) > sizeof(long))
818 v = PyLong_FromLongLong((PY_LONG_LONG) value);
819 else
820#endif
821 v = PyInt_FromLong((long) value);
822 if (!v || PyDict_SetItemString(dict, name, v))
823 PyErr_Clear();
824
825 Py_XDECREF(v);
826}
827
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000828#if (DBVER >= 43)
829/* add an db_seq_t to a dictionary using the given name as a key */
830static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
831{
832 PyObject* v = PyLong_FromLongLong(value);
833 if (!v || PyDict_SetItemString(dict, name, v))
834 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000836 Py_XDECREF(v);
837}
838#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000839
Jesus Ceaef9764f2008-05-13 18:45:46 +0000840#if (DBVER >= 40)
841static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
842{
843 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
844 if (!v || PyDict_SetItemString(dict, name, v))
845 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000846
Jesus Ceaef9764f2008-05-13 18:45:46 +0000847 Py_XDECREF(v);
848}
849#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850
851/* --------------------------------------------------------------------- */
852/* Allocators and deallocators */
853
854static DBObject*
855newDBObject(DBEnvObject* arg, int flags)
856{
857 DBObject* self;
858 DB_ENV* db_env = NULL;
859 int err;
860
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000861 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000862 if (self == NULL)
863 return NULL;
864
865 self->haveStat = 0;
866 self->flags = 0;
867 self->setflags = 0;
868 self->myenvobj = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000869 self->children_cursors = NULL;
870#if (DBVER >=43)
871 self->children_sequences = NULL;
872#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000873#if (DBVER >= 33)
874 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000875 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000876 self->primaryDBType = 0;
877#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000878 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000879
880 /* keep a reference to our python DBEnv object */
881 if (arg) {
882 Py_INCREF(arg);
883 self->myenvobj = arg;
884 db_env = arg->db_env;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000885 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
886 } else {
887 self->sibling_prev_p=NULL;
888 self->sibling_next=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000889 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000890 self->txn=NULL;
891 self->sibling_prev_p_txn=NULL;
892 self->sibling_next_txn=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000893
894 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000895 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000896 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000897 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
898 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000899
900 MYDB_BEGIN_ALLOW_THREADS;
901 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000902 if (self->db != NULL) {
903 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000904#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000905 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000906#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000907 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000908 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000909 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
910 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000911 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000912 if (makeDBError(err)) {
913 if (self->myenvobj) {
914 Py_DECREF(self->myenvobj);
915 self->myenvobj = NULL;
916 }
Gregory P. Smith664782e2008-05-17 06:12:02 +0000917 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000918 self = NULL;
919 }
920 return self;
921}
922
923
Jesus Ceaef9764f2008-05-13 18:45:46 +0000924/* Forward declaration */
925static PyObject *DB_close_internal(DBObject* self, int flags);
926
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000927static void
928DB_dealloc(DBObject* self)
929{
Jesus Ceaef9764f2008-05-13 18:45:46 +0000930 PyObject *dummy;
931
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000932 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +0000933 dummy=DB_close_internal(self,0);
934 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000935 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000936 if (self->in_weakreflist != NULL) {
937 PyObject_ClearWeakRefs((PyObject *) self);
938 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000939 if (self->myenvobj) {
940 Py_DECREF(self->myenvobj);
941 self->myenvobj = NULL;
942 }
943#if (DBVER >= 33)
944 if (self->associateCallback != NULL) {
945 Py_DECREF(self->associateCallback);
946 self->associateCallback = NULL;
947 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000948 if (self->btCompareCallback != NULL) {
949 Py_DECREF(self->btCompareCallback);
950 self->btCompareCallback = NULL;
951 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000952#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000953 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000954}
955
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000956static DBCursorObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +0000957newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000958{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000959 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000960 if (self == NULL)
961 return NULL;
962
963 self->dbc = dbc;
964 self->mydb = db;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000965
966 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
967 if (txn && ((PyObject *)txn!=Py_None)) {
968 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
969 self->txn=txn;
970 } else {
971 self->txn=NULL;
972 }
973
Gregory P. Smitha703a212003-11-03 01:04:41 +0000974 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000975 Py_INCREF(self->mydb);
976 return self;
977}
978
979
Jesus Ceaef9764f2008-05-13 18:45:46 +0000980/* Forward declaration */
981static PyObject *DBC_close_internal(DBCursorObject* self);
982
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000983static void
984DBCursor_dealloc(DBCursorObject* self)
985{
Jesus Ceaef9764f2008-05-13 18:45:46 +0000986 PyObject *dummy;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000987
Jesus Ceaef9764f2008-05-13 18:45:46 +0000988 if (self->dbc != NULL) {
989 dummy=DBC_close_internal(self);
990 Py_XDECREF(dummy);
991 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000992 if (self->in_weakreflist != NULL) {
993 PyObject_ClearWeakRefs((PyObject *) self);
994 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000995 Py_DECREF(self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000996 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000997}
998
999
1000static DBEnvObject*
1001newDBEnvObject(int flags)
1002{
1003 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001004 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001005 if (self == NULL)
1006 return NULL;
1007
1008 self->closed = 1;
1009 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001010 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1011 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001012 self->children_dbs = NULL;
1013 self->children_txns = NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001014 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001015
Jesus Ceaef9764f2008-05-13 18:45:46 +00001016#if (DBVER >= 40)
1017 self->event_notifyCallback = NULL;
1018#endif
1019
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001020 MYDB_BEGIN_ALLOW_THREADS;
1021 err = db_env_create(&self->db_env, flags);
1022 MYDB_END_ALLOW_THREADS;
1023 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001024 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001025 self = NULL;
1026 }
1027 else {
1028 self->db_env->set_errcall(self->db_env, _db_errorCallback);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001029 self->db_env->app_private=self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001030 }
1031 return self;
1032}
1033
Jesus Ceaef9764f2008-05-13 18:45:46 +00001034/* Forward declaration */
1035static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001036
1037static void
1038DBEnv_dealloc(DBEnvObject* self)
1039{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001040 PyObject *dummy;
1041
1042 if (self->db_env && !self->closed) {
1043 dummy=DBEnv_close_internal(self,0);
1044 Py_XDECREF(dummy);
1045 }
1046
1047#if (DBVER >= 40)
1048 Py_XDECREF(self->event_notifyCallback);
1049 self->event_notifyCallback = NULL;
1050#endif
1051
Gregory P. Smith31c50652004-06-28 01:20:40 +00001052 if (self->in_weakreflist != NULL) {
1053 PyObject_ClearWeakRefs((PyObject *) self);
1054 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001055
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001057}
1058
1059
1060static DBTxnObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001061newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001062{
1063 int err;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001064 DB_TXN *parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001065
Neal Norwitzb4a55812004-07-09 23:30:57 +00001066 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001067 if (self == NULL)
1068 return NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001069
Gregory P. Smith31c50652004-06-28 01:20:40 +00001070 self->in_weakreflist = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001071 self->children_txns = NULL;
1072 self->children_dbs = NULL;
1073 self->children_cursors = NULL;
1074 self->children_sequences = NULL;
1075 self->flag_prepare = 0;
1076 self->parent_txn = NULL;
1077 self->env = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001078
Jesus Ceaef9764f2008-05-13 18:45:46 +00001079 if (parent && ((PyObject *)parent!=Py_None)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001080 parent_txn = parent->txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001081 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001082
1083 if (txn) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001084 self->txn = txn;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001085 } else {
1086 MYDB_BEGIN_ALLOW_THREADS;
1087#if (DBVER >= 40)
1088 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
1089#else
1090 err = txn_begin(myenv->db_env, parent->txn, &(self_txn), flags);
1091#endif
1092 MYDB_END_ALLOW_THREADS;
1093
1094 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001095 Py_DECREF(self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001096 return NULL;
1097 }
1098 }
1099
Gregory P. Smith664782e2008-05-17 06:12:02 +00001100 /* Can't use 'parent' because could be 'parent==Py_None' */
1101 if (parent_txn) {
1102 self->parent_txn = parent;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001103 Py_INCREF(parent);
1104 self->env = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001105 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001106 } else {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001107 self->parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001108 Py_INCREF(myenv);
1109 self->env = myenv;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001110 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001111 }
1112
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001113 return self;
1114}
1115
Jesus Ceaef9764f2008-05-13 18:45:46 +00001116/* Forward declaration */
1117static PyObject *
1118DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001119
1120static void
1121DBTxn_dealloc(DBTxnObject* self)
1122{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001123 PyObject *dummy;
1124
1125 if (self->txn) {
1126 int flag_prepare = self->flag_prepare;
1127 dummy=DBTxn_abort_discard_internal(self,0);
1128 Py_XDECREF(dummy);
1129 if (!flag_prepare) {
1130 PyErr_Warn(PyExc_RuntimeWarning,
1131 "DBTxn aborted in destructor. No prior commit() or abort().");
1132 }
1133 }
1134
Gregory P. Smith31c50652004-06-28 01:20:40 +00001135 if (self->in_weakreflist != NULL) {
1136 PyObject_ClearWeakRefs((PyObject *) self);
1137 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001138
Jesus Ceaef9764f2008-05-13 18:45:46 +00001139 if (self->env) {
1140 Py_DECREF(self->env);
1141 } else {
1142 Py_DECREF(self->parent_txn);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001143 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001144 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001145}
1146
1147
1148static DBLockObject*
1149newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1150 db_lockmode_t lock_mode, int flags)
1151{
1152 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001153 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001154 if (self == NULL)
1155 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001156 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001157
1158 MYDB_BEGIN_ALLOW_THREADS;
1159#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001160 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1161 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001162#else
1163 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1164#endif
1165 MYDB_END_ALLOW_THREADS;
1166 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001167 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001168 self = NULL;
1169 }
1170
1171 return self;
1172}
1173
1174
1175static void
1176DBLock_dealloc(DBLockObject* self)
1177{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001178 if (self->in_weakreflist != NULL) {
1179 PyObject_ClearWeakRefs((PyObject *) self);
1180 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001181 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001182
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001183 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001184}
1185
1186
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001187#if (DBVER >= 43)
1188static DBSequenceObject*
1189newDBSequenceObject(DBObject* mydb, int flags)
1190{
1191 int err;
1192 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1193 if (self == NULL)
1194 return NULL;
1195 Py_INCREF(mydb);
1196 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001197
Jesus Ceaef9764f2008-05-13 18:45:46 +00001198 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
Gregory P. Smith664782e2008-05-17 06:12:02 +00001199 self->txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001200
1201 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001202
1203 MYDB_BEGIN_ALLOW_THREADS;
1204 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1205 MYDB_END_ALLOW_THREADS;
1206 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001207 Py_DECREF(self);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001208 self = NULL;
1209 }
1210
1211 return self;
1212}
1213
Jesus Ceaef9764f2008-05-13 18:45:46 +00001214/* Forward declaration */
1215static PyObject
1216*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001217
1218static void
1219DBSequence_dealloc(DBSequenceObject* self)
1220{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001221 PyObject *dummy;
1222
1223 if (self->sequence != NULL) {
1224 dummy=DBSequence_close_internal(self,0,0);
1225 Py_XDECREF(dummy);
1226 }
1227
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001228 if (self->in_weakreflist != NULL) {
1229 PyObject_ClearWeakRefs((PyObject *) self);
1230 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001231
1232 Py_DECREF(self->mydb);
1233 PyObject_Del(self);
1234}
1235#endif
1236
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001237/* --------------------------------------------------------------------- */
1238/* DB methods */
1239
1240static PyObject*
1241DB_append(DBObject* self, PyObject* args)
1242{
1243 PyObject* txnobj = NULL;
1244 PyObject* dataobj;
1245 db_recno_t recno;
1246 DBT key, data;
1247 DB_TXN *txn = NULL;
1248
Georg Brandl96a8c392006-05-29 21:04:52 +00001249 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001250 return NULL;
1251
1252 CHECK_DB_NOT_CLOSED(self);
1253
1254 /* make a dummy key out of a recno */
1255 recno = 0;
1256 CLEAR_DBT(key);
1257 key.data = &recno;
1258 key.size = sizeof(recno);
1259 key.ulen = key.size;
1260 key.flags = DB_DBT_USERMEM;
1261
1262 if (!make_dbt(dataobj, &data)) return NULL;
1263 if (!checkTxnObj(txnobj, &txn)) return NULL;
1264
1265 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1266 return NULL;
1267
1268 return PyInt_FromLong(recno);
1269}
1270
1271
1272#if (DBVER >= 33)
1273
1274static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001275_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1276 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001277{
1278 int retval = DB_DONOTINDEX;
1279 DBObject* secondaryDB = (DBObject*)db->app_private;
1280 PyObject* callback = secondaryDB->associateCallback;
1281 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001282 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001283 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001284
1285
1286 if (callback != NULL) {
1287 MYDB_BEGIN_BLOCK_THREADS;
1288
Thomas Woutersb3153832006-03-08 01:47:19 +00001289 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceaef9764f2008-05-13 18:45:46 +00001290 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
Thomas Woutersb3153832006-03-08 01:47:19 +00001291 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001292 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001293 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001294 result = PyEval_CallObject(callback, args);
1295 }
1296 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001297 PyErr_Print();
1298 }
1299 else if (result == Py_None) {
1300 retval = DB_DONOTINDEX;
1301 }
1302 else if (PyInt_Check(result)) {
1303 retval = PyInt_AsLong(result);
1304 }
Christian Heimes593daf52008-05-26 12:51:38 +00001305 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001306 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001307 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001308
1309 CLEAR_DBT(*secKey);
Christian Heimes593daf52008-05-26 12:51:38 +00001310 PyBytes_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001311 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1312 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001313 if (secKey->data) {
1314 memcpy(secKey->data, data, size);
1315 secKey->size = size;
1316 retval = 0;
1317 }
1318 else {
1319 PyErr_SetString(PyExc_MemoryError,
1320 "malloc failed in _db_associateCallback");
1321 PyErr_Print();
1322 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001323 }
1324 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001325 PyErr_SetString(
1326 PyExc_TypeError,
1327 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001328 PyErr_Print();
1329 }
1330
Thomas Woutersb3153832006-03-08 01:47:19 +00001331 Py_XDECREF(args);
1332 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001333
1334 MYDB_END_BLOCK_THREADS;
1335 }
1336 return retval;
1337}
1338
1339
1340static PyObject*
1341DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1342{
1343 int err, flags=0;
1344 DBObject* secondaryDB;
1345 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001346#if (DBVER >= 41)
1347 PyObject *txnobj = NULL;
1348 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001349 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001350 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001351#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001352 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001353#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001354
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001355#if (DBVER >= 41)
1356 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1357 &secondaryDB, &callback, &flags,
1358 &txnobj)) {
1359#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001360 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001361 &secondaryDB, &callback, &flags)) {
1362#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001363 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001364 }
1365
1366#if (DBVER >= 41)
1367 if (!checkTxnObj(txnobj, &txn)) return NULL;
1368#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001369
1370 CHECK_DB_NOT_CLOSED(self);
1371 if (!DBObject_Check(secondaryDB)) {
1372 makeTypeError("DB", (PyObject*)secondaryDB);
1373 return NULL;
1374 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001375 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001376 if (callback == Py_None) {
1377 callback = NULL;
1378 }
1379 else if (!PyCallable_Check(callback)) {
1380 makeTypeError("Callable", callback);
1381 return NULL;
1382 }
1383
1384 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001385 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001386 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001387 secondaryDB->associateCallback = callback;
1388 secondaryDB->primaryDBType = _DB_get_type(self);
1389
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001390 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1391 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1392 * The global interepreter lock is not initialized until the first
1393 * thread is created using thread.start_new_thread() or fork() is
1394 * called. that would cause the ALLOW_THREADS here to segfault due
1395 * to a null pointer reference if no threads or child processes
1396 * have been created. This works around that and is a no-op if
1397 * threads have already been initialized.
1398 * (see pybsddb-users mailing list post on 2002-08-07)
1399 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001400#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001401 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001402#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001403 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001404#if (DBVER >= 41)
1405 err = self->db->associate(self->db,
1406 txn,
1407 secondaryDB->db,
1408 _db_associateCallback,
1409 flags);
1410#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001411 err = self->db->associate(self->db,
1412 secondaryDB->db,
1413 _db_associateCallback,
1414 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001415#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001416 MYDB_END_ALLOW_THREADS;
1417
1418 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001419 Py_XDECREF(secondaryDB->associateCallback);
1420 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001421 secondaryDB->primaryDBType = 0;
1422 }
1423
1424 RETURN_IF_ERR();
1425 RETURN_NONE();
1426}
1427
1428
1429#endif
1430
1431
1432static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001433DB_close_internal(DBObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001434{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001435 PyObject *dummy;
1436 int err;
1437
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001438 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001439 /* Can be NULL if db is not in an environment */
1440 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
1441 if (self->txn) {
1442 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1443 self->txn=NULL;
1444 }
1445
1446 while(self->children_cursors) {
1447 dummy=DBC_close_internal(self->children_cursors);
1448 Py_XDECREF(dummy);
1449 }
1450
1451#if (DBVER >= 43)
1452 while(self->children_sequences) {
1453 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1454 Py_XDECREF(dummy);
1455 }
1456#endif
1457
1458 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001459 err = self->db->close(self->db, flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001460 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001461 self->db = NULL;
1462 RETURN_IF_ERR();
1463 }
1464 RETURN_NONE();
1465}
1466
Jesus Ceaef9764f2008-05-13 18:45:46 +00001467static PyObject*
1468DB_close(DBObject* self, PyObject* args)
1469{
1470 int flags=0;
1471 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1472 return NULL;
1473 return DB_close_internal(self,flags);
1474}
1475
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001476
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001477static PyObject*
1478_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1479{
1480 int err, flags=0, type;
1481 PyObject* txnobj = NULL;
1482 PyObject* retval = NULL;
1483 DBT key, data;
1484 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001485 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001486
1487 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1488 &txnobj, &flags))
1489 return NULL;
1490
1491 CHECK_DB_NOT_CLOSED(self);
1492 type = _DB_get_type(self);
1493 if (type == -1)
1494 return NULL;
1495 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001496 PyErr_SetString(PyExc_TypeError,
1497 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001498 return NULL;
1499 }
1500 if (!checkTxnObj(txnobj, &txn))
1501 return NULL;
1502
1503 CLEAR_DBT(key);
1504 CLEAR_DBT(data);
1505 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001506 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001507 data.flags = DB_DBT_MALLOC;
1508 key.flags = DB_DBT_MALLOC;
1509 }
1510
1511 MYDB_BEGIN_ALLOW_THREADS;
1512 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1513 MYDB_END_ALLOW_THREADS;
1514
Gregory P. Smithe9477062005-06-04 06:46:59 +00001515 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1516 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001517 err = 0;
1518 Py_INCREF(Py_None);
1519 retval = Py_None;
1520 }
1521 else if (!err) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001522 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001523 FREE_DBT(key);
1524 FREE_DBT(data);
1525 }
1526
1527 RETURN_IF_ERR();
1528 return retval;
1529}
1530
1531static PyObject*
1532DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1533{
1534 return _DB_consume(self, args, kwargs, DB_CONSUME);
1535}
1536
1537static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001538DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1539 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001540{
1541 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1542}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001543
1544
1545static PyObject*
1546DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1547{
1548 int err, flags=0;
1549 DBC* dbc;
1550 PyObject* txnobj = NULL;
1551 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001552 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001553
1554 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1555 &txnobj, &flags))
1556 return NULL;
1557 CHECK_DB_NOT_CLOSED(self);
1558 if (!checkTxnObj(txnobj, &txn))
1559 return NULL;
1560
1561 MYDB_BEGIN_ALLOW_THREADS;
1562 err = self->db->cursor(self->db, txn, &dbc, flags);
1563 MYDB_END_ALLOW_THREADS;
1564 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001565 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001566}
1567
1568
1569static PyObject*
1570DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1571{
1572 PyObject* txnobj = NULL;
1573 int flags = 0;
1574 PyObject* keyobj;
1575 DBT key;
1576 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001577 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001578
1579 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1580 &keyobj, &txnobj, &flags))
1581 return NULL;
1582 CHECK_DB_NOT_CLOSED(self);
1583 if (!make_key_dbt(self, keyobj, &key, NULL))
1584 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001585 if (!checkTxnObj(txnobj, &txn)) {
1586 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001587 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001588 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001589
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001590 if (-1 == _DB_delete(self, txn, &key, 0)) {
1591 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001592 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001593 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001594
1595 FREE_DBT(key);
1596 RETURN_NONE();
1597}
1598
1599
1600static PyObject*
1601DB_fd(DBObject* self, PyObject* args)
1602{
1603 int err, the_fd;
1604
1605 if (!PyArg_ParseTuple(args,":fd"))
1606 return NULL;
1607 CHECK_DB_NOT_CLOSED(self);
1608
1609 MYDB_BEGIN_ALLOW_THREADS;
1610 err = self->db->fd(self->db, &the_fd);
1611 MYDB_END_ALLOW_THREADS;
1612 RETURN_IF_ERR();
1613 return PyInt_FromLong(the_fd);
1614}
1615
1616
1617static PyObject*
1618DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1619{
1620 int err, flags=0;
1621 PyObject* txnobj = NULL;
1622 PyObject* keyobj;
1623 PyObject* dfltobj = NULL;
1624 PyObject* retval = NULL;
1625 int dlen = -1;
1626 int doff = -1;
1627 DBT key, data;
1628 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001629 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001630 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001631
1632 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001633 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1634 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001635 return NULL;
1636
1637 CHECK_DB_NOT_CLOSED(self);
1638 if (!make_key_dbt(self, keyobj, &key, &flags))
1639 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001640 if (!checkTxnObj(txnobj, &txn)) {
1641 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001642 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001643 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001644
1645 CLEAR_DBT(data);
1646 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001647 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001648 data.flags = DB_DBT_MALLOC;
1649 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001650 if (!add_partial_dbt(&data, dlen, doff)) {
1651 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001652 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001653 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001654
1655 MYDB_BEGIN_ALLOW_THREADS;
1656 err = self->db->get(self->db, txn, &key, &data, flags);
1657 MYDB_END_ALLOW_THREADS;
1658
Gregory P. Smithe9477062005-06-04 06:46:59 +00001659 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001660 err = 0;
1661 Py_INCREF(dfltobj);
1662 retval = dfltobj;
1663 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001664 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1665 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001666 err = 0;
1667 Py_INCREF(Py_None);
1668 retval = Py_None;
1669 }
1670 else if (!err) {
1671 if (flags & DB_SET_RECNO) /* return both key and data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001672 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001673 else /* return just the data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001674 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001675 FREE_DBT(data);
1676 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001677 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001678
1679 RETURN_IF_ERR();
1680 return retval;
1681}
1682
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001683#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001684static PyObject*
1685DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1686{
1687 int err, flags=0;
1688 PyObject* txnobj = NULL;
1689 PyObject* keyobj;
1690 PyObject* dfltobj = NULL;
1691 PyObject* retval = NULL;
1692 int dlen = -1;
1693 int doff = -1;
1694 DBT key, pkey, data;
1695 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001696 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001697 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001698
1699 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1700 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1701 &doff))
1702 return NULL;
1703
1704 CHECK_DB_NOT_CLOSED(self);
1705 if (!make_key_dbt(self, keyobj, &key, &flags))
1706 return NULL;
1707 if (!checkTxnObj(txnobj, &txn)) {
1708 FREE_DBT(key);
1709 return NULL;
1710 }
1711
1712 CLEAR_DBT(data);
1713 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001714 /* Tell Berkeley DB to malloc the return value (thread safe) */
Gregory P. Smith19699a92004-06-28 04:06:49 +00001715 data.flags = DB_DBT_MALLOC;
1716 }
1717 if (!add_partial_dbt(&data, dlen, doff)) {
1718 FREE_DBT(key);
1719 return NULL;
1720 }
1721
1722 CLEAR_DBT(pkey);
1723 pkey.flags = DB_DBT_MALLOC;
1724
1725 MYDB_BEGIN_ALLOW_THREADS;
1726 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1727 MYDB_END_ALLOW_THREADS;
1728
Gregory P. Smithe9477062005-06-04 06:46:59 +00001729 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001730 err = 0;
1731 Py_INCREF(dfltobj);
1732 retval = dfltobj;
1733 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001734 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1735 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001736 err = 0;
1737 Py_INCREF(Py_None);
1738 retval = Py_None;
1739 }
1740 else if (!err) {
1741 PyObject *pkeyObj;
1742 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001743 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001744
1745 if (self->primaryDBType == DB_RECNO ||
1746 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001747 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001748 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001749 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001750
1751 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1752 {
1753 PyObject *keyObj;
1754 int type = _DB_get_type(self);
1755 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001756 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001757 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001758 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001759#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001760 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001761#else
1762 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1763#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001764 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001765 }
1766 else /* return just the pkey and data */
1767 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001768#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001769 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001770#else
1771 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1772#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001773 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001774 Py_DECREF(dataObj);
1775 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001776 FREE_DBT(pkey);
1777 FREE_DBT(data);
1778 }
1779 FREE_DBT(key);
1780
1781 RETURN_IF_ERR();
1782 return retval;
1783}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001784#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001785
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001786
1787/* Return size of entry */
1788static PyObject*
1789DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1790{
1791 int err, flags=0;
1792 PyObject* txnobj = NULL;
1793 PyObject* keyobj;
1794 PyObject* retval = NULL;
1795 DBT key, data;
1796 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001797 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001798
1799 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1800 &keyobj, &txnobj))
1801 return NULL;
1802 CHECK_DB_NOT_CLOSED(self);
1803 if (!make_key_dbt(self, keyobj, &key, &flags))
1804 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001805 if (!checkTxnObj(txnobj, &txn)) {
1806 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001807 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001808 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001809 CLEAR_DBT(data);
1810
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001811 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1812 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001813 data.flags = DB_DBT_USERMEM;
1814 data.ulen = 0;
1815 MYDB_BEGIN_ALLOW_THREADS;
1816 err = self->db->get(self->db, txn, &key, &data, flags);
1817 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001818 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001819 retval = PyInt_FromLong((long)data.size);
1820 err = 0;
1821 }
1822
1823 FREE_DBT(key);
1824 FREE_DBT(data);
1825 RETURN_IF_ERR();
1826 return retval;
1827}
1828
1829
1830static PyObject*
1831DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1832{
1833 int err, flags=0;
1834 PyObject* txnobj = NULL;
1835 PyObject* keyobj;
1836 PyObject* dataobj;
1837 PyObject* retval = NULL;
1838 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001839 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001840 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001841 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001842
1843
1844 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1845 &keyobj, &dataobj, &txnobj, &flags))
1846 return NULL;
1847
1848 CHECK_DB_NOT_CLOSED(self);
1849 if (!make_key_dbt(self, keyobj, &key, NULL))
1850 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001851 if ( !make_dbt(dataobj, &data) ||
1852 !checkTxnObj(txnobj, &txn) )
1853 {
1854 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001855 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001856 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001857
1858 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001859 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001860
1861 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001862 /* Tell Berkeley DB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001863 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001864 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001865 }
1866
1867 MYDB_BEGIN_ALLOW_THREADS;
1868 err = self->db->get(self->db, txn, &key, &data, flags);
1869 MYDB_END_ALLOW_THREADS;
1870
Gregory P. Smithe9477062005-06-04 06:46:59 +00001871 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1872 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001873 err = 0;
1874 Py_INCREF(Py_None);
1875 retval = Py_None;
1876 }
1877 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001878 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001879 retval = Build_PyString(data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001880
1881 /* Even though the flags require DB_DBT_MALLOC, data is not always
1882 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1883 if (data.data != orig_data)
1884 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001885 }
1886
1887 FREE_DBT(key);
1888 RETURN_IF_ERR();
1889 return retval;
1890}
1891
1892
1893static PyObject*
1894DB_get_byteswapped(DBObject* self, PyObject* args)
1895{
1896#if (DBVER >= 33)
1897 int err = 0;
1898#endif
1899 int retval = -1;
1900
1901 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1902 return NULL;
1903 CHECK_DB_NOT_CLOSED(self);
1904
1905#if (DBVER >= 33)
1906 MYDB_BEGIN_ALLOW_THREADS;
1907 err = self->db->get_byteswapped(self->db, &retval);
1908 MYDB_END_ALLOW_THREADS;
1909 RETURN_IF_ERR();
1910#else
1911 MYDB_BEGIN_ALLOW_THREADS;
1912 retval = self->db->get_byteswapped(self->db);
1913 MYDB_END_ALLOW_THREADS;
1914#endif
1915 return PyInt_FromLong(retval);
1916}
1917
1918
1919static PyObject*
1920DB_get_type(DBObject* self, PyObject* args)
1921{
1922 int type;
1923
1924 if (!PyArg_ParseTuple(args,":get_type"))
1925 return NULL;
1926 CHECK_DB_NOT_CLOSED(self);
1927
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001928 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001929 if (type == -1)
1930 return NULL;
1931 return PyInt_FromLong(type);
1932}
1933
1934
1935static PyObject*
1936DB_join(DBObject* self, PyObject* args)
1937{
1938 int err, flags=0;
1939 int length, x;
1940 PyObject* cursorsObj;
1941 DBC** cursors;
1942 DBC* dbc;
1943
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001944 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1945 return NULL;
1946
1947 CHECK_DB_NOT_CLOSED(self);
1948
1949 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001950 PyErr_SetString(PyExc_TypeError,
1951 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001952 return NULL;
1953 }
1954
1955 length = PyObject_Length(cursorsObj);
1956 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001957 if (!cursors) {
1958 PyErr_NoMemory();
1959 return NULL;
1960 }
1961
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001962 cursors[length] = NULL;
1963 for (x=0; x<length; x++) {
1964 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001965 if (item == NULL) {
1966 free(cursors);
1967 return NULL;
1968 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001969 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001970 PyErr_SetString(PyExc_TypeError,
1971 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001972 free(cursors);
1973 return NULL;
1974 }
1975 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001976 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001977 }
1978
1979 MYDB_BEGIN_ALLOW_THREADS;
1980 err = self->db->join(self->db, cursors, &dbc, flags);
1981 MYDB_END_ALLOW_THREADS;
1982 free(cursors);
1983 RETURN_IF_ERR();
1984
Gregory P. Smith7441e652003-11-03 21:35:31 +00001985 /* FIXME: this is a buggy interface. The returned cursor
1986 contains internal references to the passed in cursors
1987 but does not hold python references to them or prevent
1988 them from being closed prematurely. This can cause
1989 python to crash when things are done in the wrong order. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001990 return (PyObject*) newDBCursorObject(dbc, NULL, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001991}
1992
1993
1994static PyObject*
1995DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1996{
1997 int err, flags=0;
1998 PyObject* txnobj = NULL;
1999 PyObject* keyobj;
2000 DBT key;
2001 DB_TXN *txn = NULL;
2002 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002003 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002004
2005 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
2006 &keyobj, &txnobj, &flags))
2007 return NULL;
2008 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002009 if (!make_dbt(keyobj, &key))
2010 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002011 return NULL;
2012 if (!checkTxnObj(txnobj, &txn))
2013 return NULL;
2014
2015 MYDB_BEGIN_ALLOW_THREADS;
2016 err = self->db->key_range(self->db, txn, &key, &range, flags);
2017 MYDB_END_ALLOW_THREADS;
2018
2019 RETURN_IF_ERR();
2020 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2021}
2022
2023
2024static PyObject*
2025DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2026{
2027 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2028 char* filename = NULL;
2029 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002030#if (DBVER >= 41)
2031 PyObject *txnobj = NULL;
2032 DB_TXN *txn = NULL;
2033 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002034 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002035 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2036 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00002037 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002038 "filename", "dbtype", "flags", "mode", "txn", NULL};
2039#else
2040 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002041 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002042 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2043 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002044 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002045 "filename", "dbtype", "flags", "mode", NULL};
2046#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002047
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002048#if (DBVER >= 41)
2049 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2050 &filename, &dbname, &type, &flags, &mode,
2051 &txnobj))
2052#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002053 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002054 &filename, &dbname, &type, &flags,
2055 &mode))
2056#endif
2057 {
2058 PyErr_Clear();
2059 type = DB_UNKNOWN; flags = 0; mode = 0660;
2060 filename = NULL; dbname = NULL;
2061#if (DBVER >= 41)
2062 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2063 kwnames_basic,
2064 &filename, &type, &flags, &mode,
2065 &txnobj))
2066 return NULL;
2067#else
2068 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2069 kwnames_basic,
2070 &filename, &type, &flags, &mode))
2071 return NULL;
2072#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002073 }
2074
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002075#if (DBVER >= 41)
2076 if (!checkTxnObj(txnobj, &txn)) return NULL;
2077#endif
2078
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002079 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002080 PyObject *t = Py_BuildValue("(is)", 0,
2081 "Cannot call open() twice for DB object");
2082 PyErr_SetObject(DBError, t);
2083 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002084 return NULL;
2085 }
2086
Jesus Ceaef9764f2008-05-13 18:45:46 +00002087#if (DBVER >= 41)
2088 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2089 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2090 self->txn=(DBTxnObject *)txnobj;
2091 } else {
2092 self->txn=NULL;
2093 }
2094#else
2095 self->txn=NULL;
2096#endif
2097
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002098 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002099#if (DBVER >= 41)
2100 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2101#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002102 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002103#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002104 MYDB_END_ALLOW_THREADS;
2105 if (makeDBError(err)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002106 PyObject *dummy;
2107
2108 dummy=DB_close_internal(self,0);
2109 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002110 return NULL;
2111 }
2112
Gregory P. Smithfc006692007-11-05 09:06:28 +00002113#if (DBVER >= 42)
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002114 self->db->get_flags(self->db, &self->setflags);
Gregory P. Smithfc006692007-11-05 09:06:28 +00002115#endif
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002116
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002117 self->flags = flags;
Jesus Ceaef9764f2008-05-13 18:45:46 +00002118
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002119 RETURN_NONE();
2120}
2121
2122
2123static PyObject*
2124DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2125{
2126 int flags=0;
2127 PyObject* txnobj = NULL;
2128 int dlen = -1;
2129 int doff = -1;
2130 PyObject* keyobj, *dataobj, *retval;
2131 DBT key, data;
2132 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002133 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002134 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002135
2136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2137 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2138 return NULL;
2139
2140 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002141 if (!make_key_dbt(self, keyobj, &key, NULL))
2142 return NULL;
2143 if ( !make_dbt(dataobj, &data) ||
2144 !add_partial_dbt(&data, dlen, doff) ||
2145 !checkTxnObj(txnobj, &txn) )
2146 {
2147 FREE_DBT(key);
2148 return NULL;
2149 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002150
2151 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2152 FREE_DBT(key);
2153 return NULL;
2154 }
2155
2156 if (flags & DB_APPEND)
2157 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2158 else {
2159 retval = Py_None;
2160 Py_INCREF(retval);
2161 }
2162 FREE_DBT(key);
2163 return retval;
2164}
2165
2166
2167
2168static PyObject*
2169DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2170{
2171 char* filename;
2172 char* database = NULL;
2173 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002174 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002175
2176 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2177 &filename, &database, &flags))
2178 return NULL;
2179 CHECK_DB_NOT_CLOSED(self);
2180
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002181 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002182 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002183 RETURN_IF_ERR();
2184 RETURN_NONE();
2185}
2186
2187
2188
2189static PyObject*
2190DB_rename(DBObject* self, PyObject* args)
2191{
2192 char* filename;
2193 char* database;
2194 char* newname;
2195 int err, flags=0;
2196
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002197 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2198 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002199 return NULL;
2200 CHECK_DB_NOT_CLOSED(self);
2201
2202 MYDB_BEGIN_ALLOW_THREADS;
2203 err = self->db->rename(self->db, filename, database, newname, flags);
2204 MYDB_END_ALLOW_THREADS;
2205 RETURN_IF_ERR();
2206 RETURN_NONE();
2207}
2208
2209
2210static PyObject*
2211DB_set_bt_minkey(DBObject* self, PyObject* args)
2212{
2213 int err, minkey;
2214
2215 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2216 return NULL;
2217 CHECK_DB_NOT_CLOSED(self);
2218
2219 MYDB_BEGIN_ALLOW_THREADS;
2220 err = self->db->set_bt_minkey(self->db, minkey);
2221 MYDB_END_ALLOW_THREADS;
2222 RETURN_IF_ERR();
2223 RETURN_NONE();
2224}
2225
Neal Norwitz84562352005-10-20 04:30:15 +00002226#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002227static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002228_default_cmp(const DBT *leftKey,
2229 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002230{
2231 int res;
2232 int lsize = leftKey->size, rsize = rightKey->size;
2233
Georg Brandlef1701f2006-03-07 14:57:48 +00002234 res = memcmp(leftKey->data, rightKey->data,
2235 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002236
2237 if (res == 0) {
2238 if (lsize < rsize) {
2239 res = -1;
2240 }
2241 else if (lsize > rsize) {
2242 res = 1;
2243 }
2244 }
2245 return res;
2246}
2247
2248static int
Jesus Ceaef9764f2008-05-13 18:45:46 +00002249_db_compareCallback(DB* db,
Georg Brandlef1701f2006-03-07 14:57:48 +00002250 const DBT *leftKey,
2251 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002252{
2253 int res = 0;
2254 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002255 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002256 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002257
2258 if (self == NULL || self->btCompareCallback == NULL) {
2259 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002260 PyErr_SetString(PyExc_TypeError,
2261 (self == 0
2262 ? "DB_bt_compare db is NULL."
2263 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002264 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002265 PyErr_Print();
2266 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002267 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002268 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002269 MYDB_BEGIN_BLOCK_THREADS;
2270
Jesus Ceaef9764f2008-05-13 18:45:46 +00002271 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002272 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002273 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002274 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002275 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002276 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002277 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002278 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002279 PyErr_Print();
2280 res = _default_cmp(leftKey, rightKey);
2281 } else if (PyInt_Check(result)) {
2282 res = PyInt_AsLong(result);
2283 } else {
2284 PyErr_SetString(PyExc_TypeError,
2285 "DB_bt_compare callback MUST return an int.");
2286 /* we're in a callback within the DB code, we can't raise */
2287 PyErr_Print();
2288 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002289 }
2290
Thomas Woutersb3153832006-03-08 01:47:19 +00002291 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002292 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002293
2294 MYDB_END_BLOCK_THREADS;
2295 }
2296 return res;
2297}
2298
2299static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002300DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002301{
2302 int err;
2303 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002304 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002305
Georg Brandlef1701f2006-03-07 14:57:48 +00002306 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002307 return NULL;
2308
Georg Brandlef1701f2006-03-07 14:57:48 +00002309 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002310
Georg Brandlef1701f2006-03-07 14:57:48 +00002311 if (!PyCallable_Check(comparator)) {
2312 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002313 return NULL;
2314 }
2315
2316 /*
2317 * Perform a test call of the comparator function with two empty
2318 * string objects here. verify that it returns an int (0).
2319 * err if not.
2320 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002321 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002322 result = PyEval_CallObject(comparator, tuple);
2323 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002324 if (result == NULL)
2325 return NULL;
2326 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002327 PyErr_SetString(PyExc_TypeError,
2328 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002329 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002330 } else if (PyInt_AsLong(result) != 0) {
2331 PyErr_SetString(PyExc_TypeError,
2332 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002333 return NULL;
2334 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002335 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002336
2337 /* We don't accept multiple set_bt_compare operations, in order to
2338 * simplify the code. This would have no real use, as one cannot
2339 * change the function once the db is opened anyway */
2340 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002341 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002342 return NULL;
2343 }
2344
Georg Brandlef1701f2006-03-07 14:57:48 +00002345 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002346 self->btCompareCallback = comparator;
2347
2348 /* This is to workaround a problem with un-initialized threads (see
2349 comment in DB_associate) */
2350#ifdef WITH_THREAD
2351 PyEval_InitThreads();
2352#endif
2353
Thomas Woutersb3153832006-03-08 01:47:19 +00002354 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002355
2356 if (err) {
2357 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002358 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002359 self->btCompareCallback = NULL;
2360 }
2361
Georg Brandlef1701f2006-03-07 14:57:48 +00002362 RETURN_IF_ERR();
2363 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002364}
Neal Norwitz84562352005-10-20 04:30:15 +00002365#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002366
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002367
2368static PyObject*
2369DB_set_cachesize(DBObject* self, PyObject* args)
2370{
2371 int err;
2372 int gbytes = 0, bytes = 0, ncache = 0;
2373
2374 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2375 &gbytes,&bytes,&ncache))
2376 return NULL;
2377 CHECK_DB_NOT_CLOSED(self);
2378
2379 MYDB_BEGIN_ALLOW_THREADS;
2380 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2381 MYDB_END_ALLOW_THREADS;
2382 RETURN_IF_ERR();
2383 RETURN_NONE();
2384}
2385
2386
2387static PyObject*
2388DB_set_flags(DBObject* self, PyObject* args)
2389{
2390 int err, flags;
2391
2392 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2393 return NULL;
2394 CHECK_DB_NOT_CLOSED(self);
2395
2396 MYDB_BEGIN_ALLOW_THREADS;
2397 err = self->db->set_flags(self->db, flags);
2398 MYDB_END_ALLOW_THREADS;
2399 RETURN_IF_ERR();
2400
2401 self->setflags |= flags;
2402 RETURN_NONE();
2403}
2404
2405
2406static PyObject*
2407DB_set_h_ffactor(DBObject* self, PyObject* args)
2408{
2409 int err, ffactor;
2410
2411 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2412 return NULL;
2413 CHECK_DB_NOT_CLOSED(self);
2414
2415 MYDB_BEGIN_ALLOW_THREADS;
2416 err = self->db->set_h_ffactor(self->db, ffactor);
2417 MYDB_END_ALLOW_THREADS;
2418 RETURN_IF_ERR();
2419 RETURN_NONE();
2420}
2421
2422
2423static PyObject*
2424DB_set_h_nelem(DBObject* self, PyObject* args)
2425{
2426 int err, nelem;
2427
2428 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2429 return NULL;
2430 CHECK_DB_NOT_CLOSED(self);
2431
2432 MYDB_BEGIN_ALLOW_THREADS;
2433 err = self->db->set_h_nelem(self->db, nelem);
2434 MYDB_END_ALLOW_THREADS;
2435 RETURN_IF_ERR();
2436 RETURN_NONE();
2437}
2438
2439
2440static PyObject*
2441DB_set_lorder(DBObject* self, PyObject* args)
2442{
2443 int err, lorder;
2444
2445 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2446 return NULL;
2447 CHECK_DB_NOT_CLOSED(self);
2448
2449 MYDB_BEGIN_ALLOW_THREADS;
2450 err = self->db->set_lorder(self->db, lorder);
2451 MYDB_END_ALLOW_THREADS;
2452 RETURN_IF_ERR();
2453 RETURN_NONE();
2454}
2455
2456
2457static PyObject*
2458DB_set_pagesize(DBObject* self, PyObject* args)
2459{
2460 int err, pagesize;
2461
2462 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2463 return NULL;
2464 CHECK_DB_NOT_CLOSED(self);
2465
2466 MYDB_BEGIN_ALLOW_THREADS;
2467 err = self->db->set_pagesize(self->db, pagesize);
2468 MYDB_END_ALLOW_THREADS;
2469 RETURN_IF_ERR();
2470 RETURN_NONE();
2471}
2472
2473
2474static PyObject*
2475DB_set_re_delim(DBObject* self, PyObject* args)
2476{
2477 int err;
2478 char delim;
2479
2480 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2481 PyErr_Clear();
2482 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2483 return NULL;
2484 }
2485
2486 CHECK_DB_NOT_CLOSED(self);
2487
2488 MYDB_BEGIN_ALLOW_THREADS;
2489 err = self->db->set_re_delim(self->db, delim);
2490 MYDB_END_ALLOW_THREADS;
2491 RETURN_IF_ERR();
2492 RETURN_NONE();
2493}
2494
2495static PyObject*
2496DB_set_re_len(DBObject* self, PyObject* args)
2497{
2498 int err, len;
2499
2500 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2501 return NULL;
2502 CHECK_DB_NOT_CLOSED(self);
2503
2504 MYDB_BEGIN_ALLOW_THREADS;
2505 err = self->db->set_re_len(self->db, len);
2506 MYDB_END_ALLOW_THREADS;
2507 RETURN_IF_ERR();
2508 RETURN_NONE();
2509}
2510
2511
2512static PyObject*
2513DB_set_re_pad(DBObject* self, PyObject* args)
2514{
2515 int err;
2516 char pad;
2517
2518 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2519 PyErr_Clear();
2520 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2521 return NULL;
2522 }
2523 CHECK_DB_NOT_CLOSED(self);
2524
2525 MYDB_BEGIN_ALLOW_THREADS;
2526 err = self->db->set_re_pad(self->db, pad);
2527 MYDB_END_ALLOW_THREADS;
2528 RETURN_IF_ERR();
2529 RETURN_NONE();
2530}
2531
2532
2533static PyObject*
2534DB_set_re_source(DBObject* self, PyObject* args)
2535{
2536 int err;
2537 char *re_source;
2538
2539 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2540 return NULL;
2541 CHECK_DB_NOT_CLOSED(self);
2542
2543 MYDB_BEGIN_ALLOW_THREADS;
2544 err = self->db->set_re_source(self->db, re_source);
2545 MYDB_END_ALLOW_THREADS;
2546 RETURN_IF_ERR();
2547 RETURN_NONE();
2548}
2549
2550
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002551static PyObject*
2552DB_set_q_extentsize(DBObject* self, PyObject* args)
2553{
2554 int err;
2555 int extentsize;
2556
2557 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2558 return NULL;
2559 CHECK_DB_NOT_CLOSED(self);
2560
2561 MYDB_BEGIN_ALLOW_THREADS;
2562 err = self->db->set_q_extentsize(self->db, extentsize);
2563 MYDB_END_ALLOW_THREADS;
2564 RETURN_IF_ERR();
2565 RETURN_NONE();
2566}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002567
2568static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002569DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002570{
2571 int err, flags = 0, type;
2572 void* sp;
2573 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002574#if (DBVER >= 43)
2575 PyObject* txnobj = NULL;
2576 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002577 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002578#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002579 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002580#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002581
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002582#if (DBVER >= 43)
2583 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2584 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002585 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002586 if (!checkTxnObj(txnobj, &txn))
2587 return NULL;
2588#else
2589 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2590 return NULL;
2591#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002592 CHECK_DB_NOT_CLOSED(self);
2593
2594 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002595#if (DBVER >= 43)
2596 err = self->db->stat(self->db, txn, &sp, flags);
2597#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002598 err = self->db->stat(self->db, &sp, flags);
2599#else
2600 err = self->db->stat(self->db, &sp, NULL, flags);
2601#endif
2602 MYDB_END_ALLOW_THREADS;
2603 RETURN_IF_ERR();
2604
2605 self->haveStat = 1;
2606
2607 /* Turn the stat structure into a dictionary */
2608 type = _DB_get_type(self);
2609 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2610 free(sp);
2611 return NULL;
2612 }
2613
2614#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2615#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2616#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2617
2618 switch (type) {
2619 case DB_HASH:
2620 MAKE_HASH_ENTRY(magic);
2621 MAKE_HASH_ENTRY(version);
2622 MAKE_HASH_ENTRY(nkeys);
2623 MAKE_HASH_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002624#if (DBVER >= 46)
2625 MAKE_HASH_ENTRY(pagecnt);
2626#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002627 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002628#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002629 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002630#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002631 MAKE_HASH_ENTRY(ffactor);
2632 MAKE_HASH_ENTRY(buckets);
2633 MAKE_HASH_ENTRY(free);
2634 MAKE_HASH_ENTRY(bfree);
2635 MAKE_HASH_ENTRY(bigpages);
2636 MAKE_HASH_ENTRY(big_bfree);
2637 MAKE_HASH_ENTRY(overflows);
2638 MAKE_HASH_ENTRY(ovfl_free);
2639 MAKE_HASH_ENTRY(dup);
2640 MAKE_HASH_ENTRY(dup_free);
2641 break;
2642
2643 case DB_BTREE:
2644 case DB_RECNO:
2645 MAKE_BT_ENTRY(magic);
2646 MAKE_BT_ENTRY(version);
2647 MAKE_BT_ENTRY(nkeys);
2648 MAKE_BT_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002649#if (DBVER >= 46)
2650 MAKE_BT_ENTRY(pagecnt);
2651#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002652 MAKE_BT_ENTRY(pagesize);
2653 MAKE_BT_ENTRY(minkey);
2654 MAKE_BT_ENTRY(re_len);
2655 MAKE_BT_ENTRY(re_pad);
2656 MAKE_BT_ENTRY(levels);
2657 MAKE_BT_ENTRY(int_pg);
2658 MAKE_BT_ENTRY(leaf_pg);
2659 MAKE_BT_ENTRY(dup_pg);
2660 MAKE_BT_ENTRY(over_pg);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002661#if (DBVER >= 43)
2662 MAKE_BT_ENTRY(empty_pg);
2663#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002664 MAKE_BT_ENTRY(free);
2665 MAKE_BT_ENTRY(int_pgfree);
2666 MAKE_BT_ENTRY(leaf_pgfree);
2667 MAKE_BT_ENTRY(dup_pgfree);
2668 MAKE_BT_ENTRY(over_pgfree);
2669 break;
2670
2671 case DB_QUEUE:
2672 MAKE_QUEUE_ENTRY(magic);
2673 MAKE_QUEUE_ENTRY(version);
2674 MAKE_QUEUE_ENTRY(nkeys);
2675 MAKE_QUEUE_ENTRY(ndata);
2676 MAKE_QUEUE_ENTRY(pagesize);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002677#if (DBVER > 40)
2678 MAKE_QUEUE_ENTRY(extentsize);
2679#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002680 MAKE_QUEUE_ENTRY(pages);
2681 MAKE_QUEUE_ENTRY(re_len);
2682 MAKE_QUEUE_ENTRY(re_pad);
2683 MAKE_QUEUE_ENTRY(pgfree);
2684#if (DBVER == 31)
2685 MAKE_QUEUE_ENTRY(start);
2686#endif
2687 MAKE_QUEUE_ENTRY(first_recno);
2688 MAKE_QUEUE_ENTRY(cur_recno);
2689 break;
2690
2691 default:
2692 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2693 Py_DECREF(d);
2694 d = NULL;
2695 }
2696
2697#undef MAKE_HASH_ENTRY
2698#undef MAKE_BT_ENTRY
2699#undef MAKE_QUEUE_ENTRY
2700
2701 free(sp);
2702 return d;
2703}
2704
2705static PyObject*
2706DB_sync(DBObject* self, PyObject* args)
2707{
2708 int err;
2709 int flags = 0;
2710
2711 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2712 return NULL;
2713 CHECK_DB_NOT_CLOSED(self);
2714
2715 MYDB_BEGIN_ALLOW_THREADS;
2716 err = self->db->sync(self->db, flags);
2717 MYDB_END_ALLOW_THREADS;
2718 RETURN_IF_ERR();
2719 RETURN_NONE();
2720}
2721
2722
2723#if (DBVER >= 33)
2724static PyObject*
2725DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2726{
2727 int err, flags=0;
2728 u_int32_t count=0;
2729 PyObject* txnobj = NULL;
2730 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002731 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002732
2733 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2734 &txnobj, &flags))
2735 return NULL;
2736 CHECK_DB_NOT_CLOSED(self);
2737 if (!checkTxnObj(txnobj, &txn))
2738 return NULL;
2739
2740 MYDB_BEGIN_ALLOW_THREADS;
2741 err = self->db->truncate(self->db, txn, &count, flags);
2742 MYDB_END_ALLOW_THREADS;
2743 RETURN_IF_ERR();
2744 return PyInt_FromLong(count);
2745}
2746#endif
2747
2748
2749static PyObject*
2750DB_upgrade(DBObject* self, PyObject* args)
2751{
2752 int err, flags=0;
2753 char *filename;
2754
2755 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2756 return NULL;
2757 CHECK_DB_NOT_CLOSED(self);
2758
2759 MYDB_BEGIN_ALLOW_THREADS;
2760 err = self->db->upgrade(self->db, filename, flags);
2761 MYDB_END_ALLOW_THREADS;
2762 RETURN_IF_ERR();
2763 RETURN_NONE();
2764}
2765
2766
2767static PyObject*
2768DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2769{
2770 int err, flags=0;
2771 char* fileName;
2772 char* dbName=NULL;
2773 char* outFileName=NULL;
2774 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002775 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002776 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002777
2778 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2779 &fileName, &dbName, &outFileName, &flags))
2780 return NULL;
2781
2782 CHECK_DB_NOT_CLOSED(self);
2783 if (outFileName)
2784 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002785 /* XXX(nnorwitz): it should probably be an exception if outFile
2786 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002787
2788 MYDB_BEGIN_ALLOW_THREADS;
2789 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2790 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002791 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002792 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002793
Jesus Ceaef9764f2008-05-13 18:45:46 +00002794 { /* DB.verify acts as a DB handle destructor (like close) */
2795 PyObject *error;
2796
2797 error=DB_close_internal(self,0);
2798 if (error ) {
2799 return error;
2800 }
2801 }
Gregory P. Smith41631e82003-09-21 00:08:14 +00002802
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002803 RETURN_IF_ERR();
2804 RETURN_NONE();
2805}
2806
2807
2808static PyObject*
2809DB_set_get_returns_none(DBObject* self, PyObject* args)
2810{
2811 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002812 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002813
2814 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2815 return NULL;
2816 CHECK_DB_NOT_CLOSED(self);
2817
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002818 if (self->moduleFlags.getReturnsNone)
2819 ++oldValue;
2820 if (self->moduleFlags.cursorSetReturnsNone)
2821 ++oldValue;
2822 self->moduleFlags.getReturnsNone = (flags >= 1);
2823 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002824 return PyInt_FromLong(oldValue);
2825}
2826
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002827#if (DBVER >= 41)
2828static PyObject*
2829DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2830{
2831 int err;
2832 u_int32_t flags=0;
2833 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002834 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002835
2836 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2837 &passwd, &flags)) {
2838 return NULL;
2839 }
2840
2841 MYDB_BEGIN_ALLOW_THREADS;
2842 err = self->db->set_encrypt(self->db, passwd, flags);
2843 MYDB_END_ALLOW_THREADS;
2844
2845 RETURN_IF_ERR();
2846 RETURN_NONE();
2847}
2848#endif /* DBVER >= 41 */
2849
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850
2851/*-------------------------------------------------------------- */
2852/* Mapping and Dictionary-like access routines */
2853
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002854Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002855{
2856 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002857 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858 int flags = 0;
2859 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002860 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002861
2862 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002863 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2864 PyErr_SetObject(DBError, t);
2865 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002866 return -1;
2867 }
2868
2869 if (self->haveStat) { /* Has the stat function been called recently? If
2870 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002871 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002872 }
2873
2874 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002875redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002876#if (DBVER >= 43)
2877 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2878#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002879 err = self->db->stat(self->db, &sp, flags);
2880#else
2881 err = self->db->stat(self->db, &sp, NULL, flags);
2882#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002883
2884 /* All the stat structures have matching fields upto the ndata field,
2885 so we can use any of them for the type cast */
2886 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2887
Jesus Ceaef9764f2008-05-13 18:45:46 +00002888 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002889 * redo a full stat to make sure.
2890 * Fixes SF python bug 1493322, pybsddb bug 1184012
2891 */
2892 if (size == 0 && (flags & DB_FAST_STAT)) {
2893 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002894 if (!err)
2895 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002896 goto redo_stat_for_length;
2897 }
2898
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002899 MYDB_END_ALLOW_THREADS;
2900
2901 if (err)
2902 return -1;
2903
2904 self->haveStat = 1;
2905
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002906 free(sp);
2907 return size;
2908}
2909
2910
2911PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2912{
2913 int err;
2914 PyObject* retval;
2915 DBT key;
2916 DBT data;
2917
2918 CHECK_DB_NOT_CLOSED(self);
2919 if (!make_key_dbt(self, keyobj, &key, NULL))
2920 return NULL;
2921
2922 CLEAR_DBT(data);
2923 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002924 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002925 data.flags = DB_DBT_MALLOC;
2926 }
2927 MYDB_BEGIN_ALLOW_THREADS;
2928 err = self->db->get(self->db, NULL, &key, &data, 0);
2929 MYDB_END_ALLOW_THREADS;
2930 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2931 PyErr_SetObject(PyExc_KeyError, keyobj);
2932 retval = NULL;
2933 }
2934 else if (makeDBError(err)) {
2935 retval = NULL;
2936 }
2937 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002938 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002939 FREE_DBT(data);
2940 }
2941
2942 FREE_DBT(key);
2943 return retval;
2944}
2945
2946
2947static int
2948DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2949{
2950 DBT key, data;
2951 int retval;
2952 int flags = 0;
2953
2954 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002955 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2956 PyErr_SetObject(DBError, t);
2957 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002958 return -1;
2959 }
2960
2961 if (!make_key_dbt(self, keyobj, &key, NULL))
2962 return -1;
2963
2964 if (dataobj != NULL) {
2965 if (!make_dbt(dataobj, &data))
2966 retval = -1;
2967 else {
2968 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002969 /* dictionaries shouldn't have duplicate keys */
2970 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002971 retval = _DB_put(self, NULL, &key, &data, flags);
2972
2973 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002974 /* try deleting any old record that matches and then PUT it
2975 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002976 _DB_delete(self, NULL, &key, 0);
2977 PyErr_Clear();
2978 retval = _DB_put(self, NULL, &key, &data, flags);
2979 }
2980 }
2981 }
2982 else {
2983 /* dataobj == NULL, so delete the key */
2984 retval = _DB_delete(self, NULL, &key, 0);
2985 }
2986 FREE_DBT(key);
2987 return retval;
2988}
2989
2990
2991static PyObject*
2992DB_has_key(DBObject* self, PyObject* args)
2993{
2994 int err;
2995 PyObject* keyobj;
2996 DBT key, data;
2997 PyObject* txnobj = NULL;
2998 DB_TXN *txn = NULL;
2999
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003000 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003001 return NULL;
3002 CHECK_DB_NOT_CLOSED(self);
3003 if (!make_key_dbt(self, keyobj, &key, NULL))
3004 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003005 if (!checkTxnObj(txnobj, &txn)) {
3006 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003007 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003008 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003009
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003010 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003011 it has a record but can't allocate a buffer for the data. This saves
3012 having to deal with data we won't be using.
3013 */
3014 CLEAR_DBT(data);
3015 data.flags = DB_DBT_USERMEM;
3016
3017 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00003018 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003019 MYDB_END_ALLOW_THREADS;
3020 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003021
3022 if (err == DB_BUFFER_SMALL || err == 0) {
3023 return PyInt_FromLong(1);
3024 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3025 return PyInt_FromLong(0);
3026 }
3027
3028 makeDBError(err);
3029 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003030}
3031
3032
3033#define _KEYS_LIST 1
3034#define _VALUES_LIST 2
3035#define _ITEMS_LIST 3
3036
3037static PyObject*
3038_DB_make_list(DBObject* self, DB_TXN* txn, int type)
3039{
3040 int err, dbtype;
3041 DBT key;
3042 DBT data;
3043 DBC *cursor;
3044 PyObject* list;
3045 PyObject* item = NULL;
3046
3047 CHECK_DB_NOT_CLOSED(self);
3048 CLEAR_DBT(key);
3049 CLEAR_DBT(data);
3050
3051 dbtype = _DB_get_type(self);
3052 if (dbtype == -1)
3053 return NULL;
3054
3055 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00003056 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003057 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003058
3059 /* get a cursor */
3060 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00003061 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003062 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00003063 if (makeDBError(err)) {
3064 Py_DECREF(list);
3065 return NULL;
3066 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003067
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003068 while (1) { /* use the cursor to traverse the DB, collecting items */
3069 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003070 err = _DBC_get(cursor, &key, &data, DB_NEXT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003071 MYDB_END_ALLOW_THREADS;
3072
3073 if (err) {
3074 /* for any error, break out of the loop */
3075 break;
3076 }
3077
3078 switch (type) {
3079 case _KEYS_LIST:
3080 switch(dbtype) {
3081 case DB_BTREE:
3082 case DB_HASH:
3083 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003084 item = Build_PyString(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003085 break;
3086 case DB_RECNO:
3087 case DB_QUEUE:
3088 item = PyInt_FromLong(*((db_recno_t*)key.data));
3089 break;
3090 }
3091 break;
3092
3093 case _VALUES_LIST:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003094 item = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003095 break;
3096
3097 case _ITEMS_LIST:
3098 switch(dbtype) {
3099 case DB_BTREE:
3100 case DB_HASH:
3101 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003102 item = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003103 break;
3104 case DB_RECNO:
3105 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003106 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003107 break;
3108 }
3109 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00003110 default:
3111 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3112 item = NULL;
3113 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003114 }
3115 if (item == NULL) {
3116 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003117 list = NULL;
3118 goto done;
3119 }
3120 PyList_Append(list, item);
3121 Py_DECREF(item);
3122 }
3123
Gregory P. Smithe9477062005-06-04 06:46:59 +00003124 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3125 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003126 Py_DECREF(list);
3127 list = NULL;
3128 }
3129
3130 done:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003131 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003132 _DBC_close(cursor);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003133 MYDB_END_ALLOW_THREADS;
3134 return list;
3135}
3136
3137
3138static PyObject*
3139DB_keys(DBObject* self, PyObject* args)
3140{
3141 PyObject* txnobj = NULL;
3142 DB_TXN *txn = NULL;
3143
Georg Brandl96a8c392006-05-29 21:04:52 +00003144 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003145 return NULL;
3146 if (!checkTxnObj(txnobj, &txn))
3147 return NULL;
3148 return _DB_make_list(self, txn, _KEYS_LIST);
3149}
3150
3151
3152static PyObject*
3153DB_items(DBObject* self, PyObject* args)
3154{
3155 PyObject* txnobj = NULL;
3156 DB_TXN *txn = NULL;
3157
Georg Brandl96a8c392006-05-29 21:04:52 +00003158 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003159 return NULL;
3160 if (!checkTxnObj(txnobj, &txn))
3161 return NULL;
3162 return _DB_make_list(self, txn, _ITEMS_LIST);
3163}
3164
3165
3166static PyObject*
3167DB_values(DBObject* self, PyObject* args)
3168{
3169 PyObject* txnobj = NULL;
3170 DB_TXN *txn = NULL;
3171
Georg Brandl96a8c392006-05-29 21:04:52 +00003172 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173 return NULL;
3174 if (!checkTxnObj(txnobj, &txn))
3175 return NULL;
3176 return _DB_make_list(self, txn, _VALUES_LIST);
3177}
3178
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003179/* --------------------------------------------------------------------- */
3180/* DBCursor methods */
3181
3182
3183static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003184DBC_close_internal(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003185{
3186 int err = 0;
3187
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003188 if (self->dbc != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003189 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3190 if (self->txn) {
3191 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3192 self->txn=NULL;
3193 }
3194
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003195 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003196 err = _DBC_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003197 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003198 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003199 }
3200 RETURN_IF_ERR();
3201 RETURN_NONE();
3202}
3203
Jesus Ceaef9764f2008-05-13 18:45:46 +00003204static PyObject*
3205DBC_close(DBCursorObject* self, PyObject* args)
3206{
3207 if (!PyArg_ParseTuple(args, ":close"))
3208 return NULL;
3209
3210 return DBC_close_internal(self);
3211}
3212
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003213
3214static PyObject*
3215DBC_count(DBCursorObject* self, PyObject* args)
3216{
3217 int err = 0;
3218 db_recno_t count;
3219 int flags = 0;
3220
3221 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3222 return NULL;
3223
3224 CHECK_CURSOR_NOT_CLOSED(self);
3225
3226 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003227 err = _DBC_count(self->dbc, &count, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003228 MYDB_END_ALLOW_THREADS;
3229 RETURN_IF_ERR();
3230
3231 return PyInt_FromLong(count);
3232}
3233
3234
3235static PyObject*
3236DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3237{
3238 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3239}
3240
3241
3242static PyObject*
3243DBC_delete(DBCursorObject* self, PyObject* args)
3244{
3245 int err, flags=0;
3246
3247 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3248 return NULL;
3249
3250 CHECK_CURSOR_NOT_CLOSED(self);
3251
3252 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003253 err = _DBC_del(self->dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003254 MYDB_END_ALLOW_THREADS;
3255 RETURN_IF_ERR();
3256
3257 self->mydb->haveStat = 0;
3258 RETURN_NONE();
3259}
3260
3261
3262static PyObject*
3263DBC_dup(DBCursorObject* self, PyObject* args)
3264{
3265 int err, flags =0;
3266 DBC* dbc = NULL;
3267
3268 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3269 return NULL;
3270
3271 CHECK_CURSOR_NOT_CLOSED(self);
3272
3273 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003274 err = _DBC_dup(self->dbc, &dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003275 MYDB_END_ALLOW_THREADS;
3276 RETURN_IF_ERR();
3277
Jesus Ceaef9764f2008-05-13 18:45:46 +00003278 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003279}
3280
3281static PyObject*
3282DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3283{
3284 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3285}
3286
3287
3288static PyObject*
3289DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3290{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003291 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003292 PyObject* keyobj = NULL;
3293 PyObject* dataobj = NULL;
3294 PyObject* retval = NULL;
3295 int dlen = -1;
3296 int doff = -1;
3297 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003298 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003299 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003300
3301 CLEAR_DBT(key);
3302 CLEAR_DBT(data);
3303 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003304 &flags, &dlen, &doff))
3305 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003306 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003307 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3308 &kwnames[1],
3309 &keyobj, &flags, &dlen, &doff))
3310 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003311 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003312 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3313 kwnames, &keyobj, &dataobj,
3314 &flags, &dlen, &doff))
3315 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003316 return NULL;
3317 }
3318 }
3319 }
3320
3321 CHECK_CURSOR_NOT_CLOSED(self);
3322
3323 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3324 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003325 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3326 (!add_partial_dbt(&data, dlen, doff)) )
3327 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003328 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003329 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003330 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003331
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003332 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003333 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003334 MYDB_END_ALLOW_THREADS;
3335
Gregory P. Smithe9477062005-06-04 06:46:59 +00003336 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3337 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003338 Py_INCREF(Py_None);
3339 retval = Py_None;
3340 }
3341 else if (makeDBError(err)) {
3342 retval = NULL;
3343 }
3344 else {
3345 switch (_DB_get_type(self->mydb)) {
3346 case -1:
3347 retval = NULL;
3348 break;
3349 case DB_BTREE:
3350 case DB_HASH:
3351 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003352 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003353 break;
3354 case DB_RECNO:
3355 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003356 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003357 break;
3358 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003359 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003360 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003361 return retval;
3362}
3363
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003364#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003365static PyObject*
3366DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3367{
3368 int err, flags=0;
3369 PyObject* keyobj = NULL;
3370 PyObject* dataobj = NULL;
3371 PyObject* retval = NULL;
3372 int dlen = -1;
3373 int doff = -1;
3374 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003375 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3376 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003377
3378 CLEAR_DBT(key);
3379 CLEAR_DBT(data);
3380 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3381 &flags, &dlen, &doff))
3382 {
3383 PyErr_Clear();
3384 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003385 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003386 &keyobj, &flags, &dlen, &doff))
3387 {
3388 PyErr_Clear();
3389 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3390 kwnames, &keyobj, &dataobj,
3391 &flags, &dlen, &doff))
3392 {
3393 return NULL;
3394 }
3395 }
3396 }
3397
3398 CHECK_CURSOR_NOT_CLOSED(self);
3399
3400 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3401 return NULL;
3402 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3403 (!add_partial_dbt(&data, dlen, doff)) ) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003404 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003405 return NULL;
3406 }
3407
Gregory P. Smith19699a92004-06-28 04:06:49 +00003408 CLEAR_DBT(pkey);
3409 pkey.flags = DB_DBT_MALLOC;
3410
3411 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003412 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003413 MYDB_END_ALLOW_THREADS;
3414
Gregory P. Smithe9477062005-06-04 06:46:59 +00003415 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3416 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003417 Py_INCREF(Py_None);
3418 retval = Py_None;
3419 }
3420 else if (makeDBError(err)) {
3421 retval = NULL;
3422 }
3423 else {
3424 PyObject *pkeyObj;
3425 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003426 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003427
3428 if (self->mydb->primaryDBType == DB_RECNO ||
3429 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003430 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003431 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003432 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003433
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003434 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003435 {
3436 PyObject *keyObj;
3437 int type = _DB_get_type(self->mydb);
3438 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003439 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003440 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003441 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003442#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003443 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003444#else
3445 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3446#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003447 Py_DECREF(keyObj);
Jesus Ceaef9764f2008-05-13 18:45:46 +00003448 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003449 }
3450 else /* return just the pkey and data */
3451 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003452#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003453 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003454#else
3455 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3456#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003457 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003458 Py_DECREF(dataObj);
3459 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003460 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003461 }
3462 /* the only time REALLOC should be set is if we used an integer
3463 * key that make_key_dbt malloc'd for us. always free these. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003464 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003465 FREE_DBT(key);
3466 }
3467 return retval;
3468}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003469#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003470
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003471
3472static PyObject*
3473DBC_get_recno(DBCursorObject* self, PyObject* args)
3474{
3475 int err;
3476 db_recno_t recno;
3477 DBT key;
3478 DBT data;
3479
3480 if (!PyArg_ParseTuple(args, ":get_recno"))
3481 return NULL;
3482
3483 CHECK_CURSOR_NOT_CLOSED(self);
3484
3485 CLEAR_DBT(key);
3486 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003487
3488 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003489 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003490 MYDB_END_ALLOW_THREADS;
3491 RETURN_IF_ERR();
3492
3493 recno = *((db_recno_t*)data.data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003494 return PyInt_FromLong(recno);
3495}
3496
3497
3498static PyObject*
3499DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3500{
3501 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3502}
3503
3504
3505static PyObject*
3506DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3507{
3508 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3509}
3510
3511
3512static PyObject*
3513DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3514{
3515 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3516}
3517
3518
3519static PyObject*
3520DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3521{
3522 int err, flags = 0;
3523 PyObject* keyobj, *dataobj;
3524 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003525 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003526 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003527 int dlen = -1;
3528 int doff = -1;
3529
3530 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3531 &keyobj, &dataobj, &flags, &dlen, &doff))
3532 return NULL;
3533
3534 CHECK_CURSOR_NOT_CLOSED(self);
3535
3536 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3537 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003538 if (!make_dbt(dataobj, &data) ||
3539 !add_partial_dbt(&data, dlen, doff) )
3540 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003541 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003542 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003543 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003544
3545 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003546 err = _DBC_put(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003547 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003548 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003549 RETURN_IF_ERR();
3550 self->mydb->haveStat = 0;
3551 RETURN_NONE();
3552}
3553
3554
3555static PyObject*
3556DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3557{
3558 int err, flags = 0;
3559 DBT key, data;
3560 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003561 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003562 int dlen = -1;
3563 int doff = -1;
3564
3565 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3566 &keyobj, &flags, &dlen, &doff))
3567 return NULL;
3568
3569 CHECK_CURSOR_NOT_CLOSED(self);
3570
3571 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3572 return NULL;
3573
3574 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003575 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003576 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003577 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003578 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003579
3580 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003581 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003582 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003583 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3584 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003585 Py_INCREF(Py_None);
3586 retval = Py_None;
3587 }
3588 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003589 retval = NULL;
3590 }
3591 else {
3592 switch (_DB_get_type(self->mydb)) {
3593 case -1:
3594 retval = NULL;
3595 break;
3596 case DB_BTREE:
3597 case DB_HASH:
3598 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003599 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003600 break;
3601 case DB_RECNO:
3602 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003603 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003604 break;
3605 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003606 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003607 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003608 /* the only time REALLOC should be set is if we used an integer
3609 * key that make_key_dbt malloc'd for us. always free these. */
3610 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003611 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003612 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003613
3614 return retval;
3615}
3616
3617
3618static PyObject*
3619DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3620{
3621 int err, flags = 0;
3622 DBT key, data;
3623 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003624 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003625 int dlen = -1;
3626 int doff = -1;
3627
3628 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3629 &keyobj, &flags, &dlen, &doff))
3630 return NULL;
3631
3632 CHECK_CURSOR_NOT_CLOSED(self);
3633
3634 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3635 return NULL;
3636
3637 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003638 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003639 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003640 return NULL;
3641 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003642 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003643 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003644 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003645 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3646 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003647 Py_INCREF(Py_None);
3648 retval = Py_None;
3649 }
3650 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003651 retval = NULL;
3652 }
3653 else {
3654 switch (_DB_get_type(self->mydb)) {
3655 case -1:
3656 retval = NULL;
3657 break;
3658 case DB_BTREE:
3659 case DB_HASH:
3660 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003661 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003662 break;
3663 case DB_RECNO:
3664 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003665 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003666 break;
3667 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003668 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003669 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003670 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003671 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003672 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003673 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003674 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003675
3676 return retval;
3677}
3678
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003679static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003680_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3681 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003682{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003683 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003684 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003685 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003686
Gregory P. Smith7441e652003-11-03 21:35:31 +00003687 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003688 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3689 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003690 if (!make_dbt(dataobj, &data)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003691 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003692 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003693 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003694
3695 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003696 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003697 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003698 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003699 Py_INCREF(Py_None);
3700 retval = Py_None;
3701 }
3702 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003703 retval = NULL;
3704 }
3705 else {
3706 switch (_DB_get_type(self->mydb)) {
3707 case -1:
3708 retval = NULL;
3709 break;
3710 case DB_BTREE:
3711 case DB_HASH:
3712 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003713 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003714 break;
3715 case DB_RECNO:
3716 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003717 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003718 break;
3719 }
3720 }
3721
Jesus Ceaef9764f2008-05-13 18:45:46 +00003722 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003723 return retval;
3724}
3725
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003726static PyObject*
3727DBC_get_both(DBCursorObject* self, PyObject* args)
3728{
3729 int flags=0;
3730 PyObject *keyobj, *dataobj;
3731
3732 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3733 return NULL;
3734
Gregory P. Smith7441e652003-11-03 21:35:31 +00003735 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003736 CHECK_CURSOR_NOT_CLOSED(self);
3737
3738 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3739 self->mydb->moduleFlags.getReturnsNone);
3740}
3741
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003742/* Return size of entry */
3743static PyObject*
3744DBC_get_current_size(DBCursorObject* self, PyObject* args)
3745{
3746 int err, flags=DB_CURRENT;
3747 PyObject* retval = NULL;
3748 DBT key, data;
3749
3750 if (!PyArg_ParseTuple(args, ":get_current_size"))
3751 return NULL;
3752 CHECK_CURSOR_NOT_CLOSED(self);
3753 CLEAR_DBT(key);
3754 CLEAR_DBT(data);
3755
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003756 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003757 getting the record size. */
3758 data.flags = DB_DBT_USERMEM;
3759 data.ulen = 0;
3760 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003761 err = _DBC_get(self->dbc, &key, &data, flags);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003762 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003763 if (err == DB_BUFFER_SMALL || !err) {
3764 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003765 retval = PyInt_FromLong((long)data.size);
3766 err = 0;
3767 }
3768
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003769 RETURN_IF_ERR();
3770 return retval;
3771}
3772
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003773static PyObject*
3774DBC_set_both(DBCursorObject* self, PyObject* args)
3775{
3776 int flags=0;
3777 PyObject *keyobj, *dataobj;
3778
3779 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3780 return NULL;
3781
Gregory P. Smith7441e652003-11-03 21:35:31 +00003782 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003783 CHECK_CURSOR_NOT_CLOSED(self);
3784
3785 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3786 self->mydb->moduleFlags.cursorSetReturnsNone);
3787}
3788
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003789
3790static PyObject*
3791DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3792{
3793 int err, irecno, flags=0;
3794 db_recno_t recno;
3795 DBT key, data;
3796 PyObject* retval;
3797 int dlen = -1;
3798 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003799 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003800
3801 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3802 &irecno, &flags, &dlen, &doff))
3803 return NULL;
3804
3805 CHECK_CURSOR_NOT_CLOSED(self);
3806
3807 CLEAR_DBT(key);
3808 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003809 /* use allocated space so DB will be able to realloc room for the real
3810 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003811 key.data = malloc(sizeof(db_recno_t));
3812 if (key.data == NULL) {
3813 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3814 return NULL;
3815 }
3816 key.size = sizeof(db_recno_t);
3817 key.ulen = key.size;
3818 memcpy(key.data, &recno, sizeof(db_recno_t));
3819 key.flags = DB_DBT_REALLOC;
3820
3821 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003822 if (!add_partial_dbt(&data, dlen, doff)) {
3823 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003824 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003825 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003826
3827 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003828 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003829 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003830 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3831 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003832 Py_INCREF(Py_None);
3833 retval = Py_None;
3834 }
3835 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003836 retval = NULL;
3837 }
3838 else { /* Can only be used for BTrees, so no need to return int key */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003839 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003840 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003841 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003842
3843 return retval;
3844}
3845
3846
3847static PyObject*
3848DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3849{
3850 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3851}
3852
3853
3854static PyObject*
3855DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3856{
3857 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3858}
3859
3860
3861static PyObject*
3862DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3863{
3864 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3865}
3866
3867
3868static PyObject*
3869DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3870{
3871 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3872}
3873
3874
3875static PyObject*
3876DBC_join_item(DBCursorObject* self, PyObject* args)
3877{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003878 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003879 DBT key, data;
3880 PyObject* retval;
3881
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003882 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003883 return NULL;
3884
3885 CHECK_CURSOR_NOT_CLOSED(self);
3886
3887 CLEAR_DBT(key);
3888 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003889
3890 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003891 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003892 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003893 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3894 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003895 Py_INCREF(Py_None);
3896 retval = Py_None;
3897 }
3898 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003899 retval = NULL;
3900 }
3901 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003902 retval = BuildValue_S(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003903 }
3904
3905 return retval;
3906}
3907
3908
3909
3910/* --------------------------------------------------------------------- */
3911/* DBEnv methods */
3912
3913
3914static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003915DBEnv_close_internal(DBEnvObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003916{
Jesus Ceaef9764f2008-05-13 18:45:46 +00003917 PyObject *dummy;
3918 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003919
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003920 if (!self->closed) { /* Don't close more than once */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003921 while(self->children_txns) {
3922 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
3923 Py_XDECREF(dummy);
3924 }
3925 while(self->children_dbs) {
3926 dummy=DB_close_internal(self->children_dbs,0);
3927 Py_XDECREF(dummy);
3928 }
3929
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003930 MYDB_BEGIN_ALLOW_THREADS;
3931 err = self->db_env->close(self->db_env, flags);
3932 MYDB_END_ALLOW_THREADS;
3933 /* after calling DBEnv->close, regardless of error, this DBEnv
Jesus Ceaef9764f2008-05-13 18:45:46 +00003934 * may not be accessed again (Berkeley DB docs). */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003935 self->closed = 1;
3936 self->db_env = NULL;
3937 RETURN_IF_ERR();
3938 }
3939 RETURN_NONE();
3940}
3941
Jesus Ceaef9764f2008-05-13 18:45:46 +00003942static PyObject*
3943DBEnv_close(DBEnvObject* self, PyObject* args)
3944{
3945 int flags = 0;
3946
3947 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3948 return NULL;
3949 return DBEnv_close_internal(self,flags);
3950}
3951
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003952
3953static PyObject*
3954DBEnv_open(DBEnvObject* self, PyObject* args)
3955{
3956 int err, flags=0, mode=0660;
3957 char *db_home;
3958
3959 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3960 return NULL;
3961
3962 CHECK_ENV_NOT_CLOSED(self);
3963
3964 MYDB_BEGIN_ALLOW_THREADS;
3965 err = self->db_env->open(self->db_env, db_home, flags, mode);
3966 MYDB_END_ALLOW_THREADS;
3967 RETURN_IF_ERR();
3968 self->closed = 0;
3969 self->flags = flags;
3970 RETURN_NONE();
3971}
3972
3973
3974static PyObject*
3975DBEnv_remove(DBEnvObject* self, PyObject* args)
3976{
3977 int err, flags=0;
3978 char *db_home;
3979
3980 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3981 return NULL;
3982 CHECK_ENV_NOT_CLOSED(self);
3983 MYDB_BEGIN_ALLOW_THREADS;
3984 err = self->db_env->remove(self->db_env, db_home, flags);
3985 MYDB_END_ALLOW_THREADS;
3986 RETURN_IF_ERR();
3987 RETURN_NONE();
3988}
3989
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003990#if (DBVER >= 41)
3991static PyObject*
3992DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3993{
3994 int err;
3995 u_int32_t flags=0;
3996 char *file = NULL;
3997 char *database = NULL;
3998 PyObject *txnobj = NULL;
3999 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004000 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004001 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004002
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004003 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004004 &file, &database, &txnobj, &flags)) {
4005 return NULL;
4006 }
4007 if (!checkTxnObj(txnobj, &txn)) {
4008 return NULL;
4009 }
4010 CHECK_ENV_NOT_CLOSED(self);
4011 MYDB_BEGIN_ALLOW_THREADS;
4012 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4013 MYDB_END_ALLOW_THREADS;
4014 RETURN_IF_ERR();
4015 RETURN_NONE();
4016}
4017
4018static PyObject*
4019DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4020{
4021 int err;
4022 u_int32_t flags=0;
4023 char *file = NULL;
4024 char *database = NULL;
4025 char *newname = NULL;
4026 PyObject *txnobj = NULL;
4027 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004028 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004029 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004030
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004031 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004032 &file, &database, &newname, &txnobj, &flags)) {
4033 return NULL;
4034 }
4035 if (!checkTxnObj(txnobj, &txn)) {
4036 return NULL;
4037 }
4038 CHECK_ENV_NOT_CLOSED(self);
4039 MYDB_BEGIN_ALLOW_THREADS;
4040 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4041 flags);
4042 MYDB_END_ALLOW_THREADS;
4043 RETURN_IF_ERR();
4044 RETURN_NONE();
4045}
4046
4047static PyObject*
4048DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4049{
4050 int err;
4051 u_int32_t flags=0;
4052 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004053 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004054
4055 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4056 &passwd, &flags)) {
4057 return NULL;
4058 }
4059
4060 MYDB_BEGIN_ALLOW_THREADS;
4061 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4062 MYDB_END_ALLOW_THREADS;
4063
4064 RETURN_IF_ERR();
4065 RETURN_NONE();
4066}
4067#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004068
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004069#if (DBVER >= 40)
4070static PyObject*
4071DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4072{
4073 int err;
4074 u_int32_t flags=0;
4075 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004076 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004077
4078 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4079 &timeout, &flags)) {
4080 return NULL;
4081 }
4082
4083 MYDB_BEGIN_ALLOW_THREADS;
4084 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4085 MYDB_END_ALLOW_THREADS;
4086
4087 RETURN_IF_ERR();
4088 RETURN_NONE();
4089}
4090#endif /* DBVER >= 40 */
4091
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004092static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004093DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4094{
4095 int err;
4096 long shm_key = 0;
4097
4098 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4099 return NULL;
4100 CHECK_ENV_NOT_CLOSED(self);
4101
4102 err = self->db_env->set_shm_key(self->db_env, shm_key);
4103 RETURN_IF_ERR();
4104 RETURN_NONE();
4105}
4106
4107static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004108DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4109{
4110 int err, gbytes=0, bytes=0, ncache=0;
4111
4112 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4113 &gbytes, &bytes, &ncache))
4114 return NULL;
4115 CHECK_ENV_NOT_CLOSED(self);
4116
4117 MYDB_BEGIN_ALLOW_THREADS;
4118 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4119 MYDB_END_ALLOW_THREADS;
4120 RETURN_IF_ERR();
4121 RETURN_NONE();
4122}
4123
4124
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004125static PyObject*
4126DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4127{
4128 int err, flags=0, onoff=0;
4129
4130 if (!PyArg_ParseTuple(args, "ii:set_flags",
4131 &flags, &onoff))
4132 return NULL;
4133 CHECK_ENV_NOT_CLOSED(self);
4134
4135 MYDB_BEGIN_ALLOW_THREADS;
4136 err = self->db_env->set_flags(self->db_env, flags, onoff);
4137 MYDB_END_ALLOW_THREADS;
4138 RETURN_IF_ERR();
4139 RETURN_NONE();
4140}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004141
4142
Jesus Ceaca3939c2008-05-22 15:27:38 +00004143#if (DBVER >= 47)
4144static PyObject*
4145DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
4146{
4147 int err, flags, onoff;
4148
4149 if (!PyArg_ParseTuple(args, "ii:log_set_config",
4150 &flags, &onoff))
4151 return NULL;
4152 CHECK_ENV_NOT_CLOSED(self);
4153
4154 MYDB_BEGIN_ALLOW_THREADS;
4155 err = self->db_env->log_set_config(self->db_env, flags, onoff);
4156 MYDB_END_ALLOW_THREADS;
4157 RETURN_IF_ERR();
4158 RETURN_NONE();
4159}
4160#endif /* DBVER >= 47 */
4161
4162
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004163static PyObject*
4164DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4165{
4166 int err;
4167 char *dir;
4168
4169 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4170 return NULL;
4171 CHECK_ENV_NOT_CLOSED(self);
4172
4173 MYDB_BEGIN_ALLOW_THREADS;
4174 err = self->db_env->set_data_dir(self->db_env, dir);
4175 MYDB_END_ALLOW_THREADS;
4176 RETURN_IF_ERR();
4177 RETURN_NONE();
4178}
4179
4180
4181static PyObject*
4182DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4183{
4184 int err, lg_bsize;
4185
4186 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4187 return NULL;
4188 CHECK_ENV_NOT_CLOSED(self);
4189
4190 MYDB_BEGIN_ALLOW_THREADS;
4191 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4192 MYDB_END_ALLOW_THREADS;
4193 RETURN_IF_ERR();
4194 RETURN_NONE();
4195}
4196
4197
4198static PyObject*
4199DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4200{
4201 int err;
4202 char *dir;
4203
4204 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4205 return NULL;
4206 CHECK_ENV_NOT_CLOSED(self);
4207
4208 MYDB_BEGIN_ALLOW_THREADS;
4209 err = self->db_env->set_lg_dir(self->db_env, dir);
4210 MYDB_END_ALLOW_THREADS;
4211 RETURN_IF_ERR();
4212 RETURN_NONE();
4213}
4214
4215static PyObject*
4216DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4217{
4218 int err, lg_max;
4219
4220 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4221 return NULL;
4222 CHECK_ENV_NOT_CLOSED(self);
4223
4224 MYDB_BEGIN_ALLOW_THREADS;
4225 err = self->db_env->set_lg_max(self->db_env, lg_max);
4226 MYDB_END_ALLOW_THREADS;
4227 RETURN_IF_ERR();
4228 RETURN_NONE();
4229}
4230
Jesus Ceaef9764f2008-05-13 18:45:46 +00004231#if (DBVER >= 42)
4232static PyObject*
4233DBEnv_get_lg_max(DBEnvObject* self, PyObject* args)
4234{
4235 int err;
4236 u_int32_t lg_max;
4237
4238 if (!PyArg_ParseTuple(args, ":get_lg_max"))
4239 return NULL;
4240 CHECK_ENV_NOT_CLOSED(self);
4241
4242 MYDB_BEGIN_ALLOW_THREADS;
4243 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4244 MYDB_END_ALLOW_THREADS;
4245 RETURN_IF_ERR();
4246 return PyInt_FromLong(lg_max);
4247}
4248#endif
4249
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004250
Neal Norwitz84562352005-10-20 04:30:15 +00004251#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004252static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004253DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4254{
4255 int err, lg_max;
4256
4257 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4258 return NULL;
4259 CHECK_ENV_NOT_CLOSED(self);
4260
4261 MYDB_BEGIN_ALLOW_THREADS;
4262 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4263 MYDB_END_ALLOW_THREADS;
4264 RETURN_IF_ERR();
4265 RETURN_NONE();
4266}
Neal Norwitz84562352005-10-20 04:30:15 +00004267#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004268
4269
4270static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004271DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4272{
4273 int err, lk_detect;
4274
4275 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4276 return NULL;
4277 CHECK_ENV_NOT_CLOSED(self);
4278
4279 MYDB_BEGIN_ALLOW_THREADS;
4280 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4281 MYDB_END_ALLOW_THREADS;
4282 RETURN_IF_ERR();
4283 RETURN_NONE();
4284}
4285
4286
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004287#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004288static PyObject*
4289DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4290{
4291 int err, max;
4292
4293 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4294 return NULL;
4295 CHECK_ENV_NOT_CLOSED(self);
4296
4297 MYDB_BEGIN_ALLOW_THREADS;
4298 err = self->db_env->set_lk_max(self->db_env, max);
4299 MYDB_END_ALLOW_THREADS;
4300 RETURN_IF_ERR();
4301 RETURN_NONE();
4302}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004303#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004304
4305
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004306
4307static PyObject*
4308DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4309{
4310 int err, max;
4311
4312 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4313 return NULL;
4314 CHECK_ENV_NOT_CLOSED(self);
4315
4316 MYDB_BEGIN_ALLOW_THREADS;
4317 err = self->db_env->set_lk_max_locks(self->db_env, max);
4318 MYDB_END_ALLOW_THREADS;
4319 RETURN_IF_ERR();
4320 RETURN_NONE();
4321}
4322
4323
4324static PyObject*
4325DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4326{
4327 int err, max;
4328
4329 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4330 return NULL;
4331 CHECK_ENV_NOT_CLOSED(self);
4332
4333 MYDB_BEGIN_ALLOW_THREADS;
4334 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4335 MYDB_END_ALLOW_THREADS;
4336 RETURN_IF_ERR();
4337 RETURN_NONE();
4338}
4339
4340
4341static PyObject*
4342DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4343{
4344 int err, max;
4345
4346 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4347 return NULL;
4348 CHECK_ENV_NOT_CLOSED(self);
4349
4350 MYDB_BEGIN_ALLOW_THREADS;
4351 err = self->db_env->set_lk_max_objects(self->db_env, max);
4352 MYDB_END_ALLOW_THREADS;
4353 RETURN_IF_ERR();
4354 RETURN_NONE();
4355}
4356
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004357
4358static PyObject*
4359DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4360{
4361 int err, mp_mmapsize;
4362
4363 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4364 return NULL;
4365 CHECK_ENV_NOT_CLOSED(self);
4366
4367 MYDB_BEGIN_ALLOW_THREADS;
4368 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4369 MYDB_END_ALLOW_THREADS;
4370 RETURN_IF_ERR();
4371 RETURN_NONE();
4372}
4373
4374
4375static PyObject*
4376DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4377{
4378 int err;
4379 char *dir;
4380
4381 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4382 return NULL;
4383 CHECK_ENV_NOT_CLOSED(self);
4384
4385 MYDB_BEGIN_ALLOW_THREADS;
4386 err = self->db_env->set_tmp_dir(self->db_env, dir);
4387 MYDB_END_ALLOW_THREADS;
4388 RETURN_IF_ERR();
4389 RETURN_NONE();
4390}
4391
4392
Jesus Ceaef9764f2008-05-13 18:45:46 +00004393#if (DBVER >= 40)
4394static PyObject*
4395DBEnv_txn_recover(DBEnvObject* self, PyObject* args)
4396{
4397 int flags = DB_FIRST;
4398 int err, i;
4399 PyObject *list, *tuple, *gid;
4400 DBTxnObject *txn;
4401#define PREPLIST_LEN 16
4402 DB_PREPLIST preplist[PREPLIST_LEN];
4403 long retp;
4404
4405 if (!PyArg_ParseTuple(args, ":txn_recover"))
4406 return NULL;
4407
4408 CHECK_ENV_NOT_CLOSED(self);
4409
4410 list=PyList_New(0);
4411 if (!list)
4412 return NULL;
4413 while (!0) {
4414 MYDB_BEGIN_ALLOW_THREADS
4415 err=self->db_env->txn_recover(self->db_env,
4416 preplist, PREPLIST_LEN, &retp, flags);
4417#undef PREPLIST_LEN
4418 MYDB_END_ALLOW_THREADS
4419 if (err) {
4420 Py_DECREF(list);
4421 RETURN_IF_ERR();
4422 }
4423 if (!retp) break;
4424 flags=DB_NEXT; /* Prepare for next loop pass */
4425 for (i=0; i<retp; i++) {
Christian Heimes593daf52008-05-26 12:51:38 +00004426 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
Jesus Ceaef9764f2008-05-13 18:45:46 +00004427 DB_XIDDATASIZE);
4428 if (!gid) {
4429 Py_DECREF(list);
4430 return NULL;
4431 }
4432 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4433 if (!txn) {
4434 Py_DECREF(list);
4435 Py_DECREF(gid);
4436 return NULL;
4437 }
4438 txn->flag_prepare=1; /* Recover state */
4439 tuple=PyTuple_New(2);
4440 if (!tuple) {
4441 Py_DECREF(list);
4442 Py_DECREF(gid);
4443 Py_DECREF(txn);
4444 return NULL;
4445 }
4446 if (PyTuple_SetItem(tuple, 0, gid)) {
4447 Py_DECREF(list);
4448 Py_DECREF(gid);
4449 Py_DECREF(txn);
4450 Py_DECREF(tuple);
4451 return NULL;
4452 }
4453 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4454 Py_DECREF(list);
4455 Py_DECREF(txn);
4456 Py_DECREF(tuple); /* This delete the "gid" also */
4457 return NULL;
4458 }
4459 if (PyList_Append(list, tuple)) {
4460 Py_DECREF(list);
4461 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4462 return NULL;
4463 }
4464 Py_DECREF(tuple);
4465 }
4466 }
4467 return list;
4468}
4469#endif
4470
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004471static PyObject*
4472DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4473{
4474 int flags = 0;
4475 PyObject* txnobj = NULL;
4476 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004477 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004478
4479 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4480 &txnobj, &flags))
4481 return NULL;
4482
4483 if (!checkTxnObj(txnobj, &txn))
4484 return NULL;
4485 CHECK_ENV_NOT_CLOSED(self);
4486
Jesus Ceaef9764f2008-05-13 18:45:46 +00004487 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004488}
4489
4490
4491static PyObject*
4492DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4493{
4494 int err, kbyte=0, min=0, flags=0;
4495
4496 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4497 return NULL;
4498 CHECK_ENV_NOT_CLOSED(self);
4499
4500 MYDB_BEGIN_ALLOW_THREADS;
4501#if (DBVER >= 40)
4502 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4503#else
4504 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4505#endif
4506 MYDB_END_ALLOW_THREADS;
4507 RETURN_IF_ERR();
4508 RETURN_NONE();
4509}
4510
4511
4512static PyObject*
4513DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4514{
4515 int err, max;
4516
4517 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4518 return NULL;
4519 CHECK_ENV_NOT_CLOSED(self);
4520
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004521 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004522 RETURN_IF_ERR();
4523 RETURN_NONE();
4524}
4525
4526
4527static PyObject*
4528DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4529{
4530 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004531 long stamp;
4532 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004533
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004534 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004535 return NULL;
4536 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004537 timestamp = (time_t)stamp;
4538 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004539 RETURN_IF_ERR();
4540 RETURN_NONE();
4541}
4542
4543
4544static PyObject*
4545DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4546{
4547 int err, atype, flags=0;
4548 int aborted = 0;
4549
4550 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4551 return NULL;
4552 CHECK_ENV_NOT_CLOSED(self);
4553
4554 MYDB_BEGIN_ALLOW_THREADS;
4555#if (DBVER >= 40)
4556 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4557#else
4558 err = lock_detect(self->db_env, flags, atype, &aborted);
4559#endif
4560 MYDB_END_ALLOW_THREADS;
4561 RETURN_IF_ERR();
4562 return PyInt_FromLong(aborted);
4563}
4564
4565
4566static PyObject*
4567DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4568{
4569 int flags=0;
4570 int locker, lock_mode;
4571 DBT obj;
4572 PyObject* objobj;
4573
4574 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4575 return NULL;
4576
4577
4578 if (!make_dbt(objobj, &obj))
4579 return NULL;
4580
4581 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4582}
4583
4584
4585static PyObject*
4586DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4587{
4588 int err;
4589 u_int32_t theID;
4590
4591 if (!PyArg_ParseTuple(args, ":lock_id"))
4592 return NULL;
4593
4594 CHECK_ENV_NOT_CLOSED(self);
4595 MYDB_BEGIN_ALLOW_THREADS;
4596#if (DBVER >= 40)
4597 err = self->db_env->lock_id(self->db_env, &theID);
4598#else
4599 err = lock_id(self->db_env, &theID);
4600#endif
4601 MYDB_END_ALLOW_THREADS;
4602 RETURN_IF_ERR();
4603
4604 return PyInt_FromLong((long)theID);
4605}
4606
Gregory P. Smithac11e022007-11-05 02:56:31 +00004607#if (DBVER >= 40)
4608static PyObject*
4609DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4610{
4611 int err;
4612 u_int32_t theID;
4613
4614 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4615 return NULL;
4616
4617 CHECK_ENV_NOT_CLOSED(self);
4618 MYDB_BEGIN_ALLOW_THREADS;
4619 err = self->db_env->lock_id_free(self->db_env, theID);
4620 MYDB_END_ALLOW_THREADS;
4621 RETURN_IF_ERR();
4622 RETURN_NONE();
4623}
4624#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004625
4626static PyObject*
4627DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4628{
4629 int err;
4630 DBLockObject* dblockobj;
4631
4632 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4633 return NULL;
4634
4635 CHECK_ENV_NOT_CLOSED(self);
4636 MYDB_BEGIN_ALLOW_THREADS;
4637#if (DBVER >= 40)
4638 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4639#else
4640 err = lock_put(self->db_env, &dblockobj->lock);
4641#endif
4642 MYDB_END_ALLOW_THREADS;
4643 RETURN_IF_ERR();
4644 RETURN_NONE();
4645}
4646
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004647#if (DBVER >= 44)
4648static PyObject*
4649DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4650{
4651 int err;
4652 char *file;
4653 u_int32_t flags = 0;
4654 static char* kwnames[] = { "file", "flags", NULL};
4655
4656 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4657 &file, &flags))
4658 return NULL;
4659 CHECK_ENV_NOT_CLOSED(self);
4660
4661 MYDB_BEGIN_ALLOW_THREADS;
4662 err = self->db_env->lsn_reset(self->db_env, file, flags);
4663 MYDB_END_ALLOW_THREADS;
4664 RETURN_IF_ERR();
4665 RETURN_NONE();
4666}
4667#endif /* DBVER >= 4.4 */
4668
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004669#if (DBVER >= 40)
4670static PyObject*
4671DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4672{
4673 int err;
4674 DB_LOG_STAT* statp = NULL;
4675 PyObject* d = NULL;
4676 u_int32_t flags = 0;
4677
4678 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4679 return NULL;
4680 CHECK_ENV_NOT_CLOSED(self);
4681
4682 MYDB_BEGIN_ALLOW_THREADS;
4683 err = self->db_env->log_stat(self->db_env, &statp, flags);
4684 MYDB_END_ALLOW_THREADS;
4685 RETURN_IF_ERR();
4686
4687 /* Turn the stat structure into a dictionary */
4688 d = PyDict_New();
4689 if (d == NULL) {
4690 if (statp)
4691 free(statp);
4692 return NULL;
4693 }
4694
4695#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4696
4697 MAKE_ENTRY(magic);
4698 MAKE_ENTRY(version);
4699 MAKE_ENTRY(mode);
4700 MAKE_ENTRY(lg_bsize);
4701#if (DBVER >= 44)
4702 MAKE_ENTRY(lg_size);
4703 MAKE_ENTRY(record);
4704#endif
4705#if (DBVER <= 40)
4706 MAKE_ENTRY(lg_max);
4707#endif
4708 MAKE_ENTRY(w_mbytes);
4709 MAKE_ENTRY(w_bytes);
4710 MAKE_ENTRY(wc_mbytes);
4711 MAKE_ENTRY(wc_bytes);
4712 MAKE_ENTRY(wcount);
4713 MAKE_ENTRY(wcount_fill);
4714#if (DBVER >= 44)
4715 MAKE_ENTRY(rcount);
4716#endif
4717 MAKE_ENTRY(scount);
4718 MAKE_ENTRY(cur_file);
4719 MAKE_ENTRY(cur_offset);
4720 MAKE_ENTRY(disk_file);
4721 MAKE_ENTRY(disk_offset);
4722 MAKE_ENTRY(maxcommitperflush);
4723 MAKE_ENTRY(mincommitperflush);
4724 MAKE_ENTRY(regsize);
4725 MAKE_ENTRY(region_wait);
4726 MAKE_ENTRY(region_nowait);
4727
4728#undef MAKE_ENTRY
4729 free(statp);
4730 return d;
4731} /* DBEnv_log_stat */
4732#endif /* DBVER >= 4.0 for log_stat method */
4733
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004734
4735static PyObject*
4736DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4737{
4738 int err;
4739 DB_LOCK_STAT* sp;
4740 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004741 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004742
4743 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4744 return NULL;
4745 CHECK_ENV_NOT_CLOSED(self);
4746
4747 MYDB_BEGIN_ALLOW_THREADS;
4748#if (DBVER >= 40)
4749 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4750#else
4751#if (DBVER >= 33)
4752 err = lock_stat(self->db_env, &sp);
4753#else
4754 err = lock_stat(self->db_env, &sp, NULL);
4755#endif
4756#endif
4757 MYDB_END_ALLOW_THREADS;
4758 RETURN_IF_ERR();
4759
4760 /* Turn the stat structure into a dictionary */
4761 d = PyDict_New();
4762 if (d == NULL) {
4763 free(sp);
4764 return NULL;
4765 }
4766
4767#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4768
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004769#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004770 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004771#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004772#if (DBVER >=41)
4773 MAKE_ENTRY(id);
4774 MAKE_ENTRY(cur_maxid);
4775#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004776 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004777 MAKE_ENTRY(maxlocks);
4778 MAKE_ENTRY(maxlockers);
4779 MAKE_ENTRY(maxobjects);
4780 MAKE_ENTRY(nlocks);
4781 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004782 MAKE_ENTRY(nlockers);
4783 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004784 MAKE_ENTRY(nobjects);
4785 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004786 MAKE_ENTRY(nrequests);
4787 MAKE_ENTRY(nreleases);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004788#if (DBVER >= 44)
4789 MAKE_ENTRY(nupgrade);
4790 MAKE_ENTRY(ndowngrade);
4791#endif
Gregory P. Smith29602d22006-01-24 09:46:48 +00004792#if (DBVER < 44)
4793 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004794 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004795#else
4796 MAKE_ENTRY(lock_nowait);
4797 MAKE_ENTRY(lock_wait);
4798#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004799 MAKE_ENTRY(ndeadlocks);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004800#if (DBVER >= 41)
4801 MAKE_ENTRY(locktimeout);
4802 MAKE_ENTRY(txntimeout);
4803#endif
4804#if (DBVER >= 40)
4805 MAKE_ENTRY(nlocktimeouts);
4806 MAKE_ENTRY(ntxntimeouts);
4807#endif
4808#if (DBVER >= 46)
4809 MAKE_ENTRY(objs_wait);
4810 MAKE_ENTRY(objs_nowait);
4811 MAKE_ENTRY(lockers_wait);
4812 MAKE_ENTRY(lockers_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004813#if (DBVER >= 47)
4814 MAKE_ENTRY(lock_wait);
4815 MAKE_ENTRY(lock_nowait);
4816#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00004817 MAKE_ENTRY(locks_wait);
4818 MAKE_ENTRY(locks_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004819#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004820 MAKE_ENTRY(hash_len);
4821#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004822 MAKE_ENTRY(regsize);
4823 MAKE_ENTRY(region_wait);
4824 MAKE_ENTRY(region_nowait);
4825
4826#undef MAKE_ENTRY
4827 free(sp);
4828 return d;
4829}
4830
Jesus Ceaef9764f2008-05-13 18:45:46 +00004831#if (DBVER >= 40)
4832static PyObject*
4833DBEnv_log_flush(DBEnvObject* self, PyObject* args)
4834{
4835 int err;
4836
4837 if (!PyArg_ParseTuple(args, ":log_flush"))
4838 return NULL;
4839 CHECK_ENV_NOT_CLOSED(self);
4840
4841 MYDB_BEGIN_ALLOW_THREADS
4842 err = self->db_env->log_flush(self->db_env, NULL);
4843 MYDB_END_ALLOW_THREADS
4844
4845 RETURN_IF_ERR();
4846 RETURN_NONE();
4847}
4848#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004849
4850static PyObject*
4851DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4852{
4853 int flags=0;
4854 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004855 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004856 PyObject* list;
4857 PyObject* item = NULL;
4858
4859 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4860 return NULL;
4861
4862 CHECK_ENV_NOT_CLOSED(self);
4863 MYDB_BEGIN_ALLOW_THREADS;
4864#if (DBVER >= 40)
4865 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4866#elif (DBVER == 33)
4867 err = log_archive(self->db_env, &log_list, flags);
4868#else
4869 err = log_archive(self->db_env, &log_list, flags, NULL);
4870#endif
4871 MYDB_END_ALLOW_THREADS;
4872 RETURN_IF_ERR();
4873
Gregory P. Smithbad47452006-06-05 00:33:35 +00004874 list = PyList_New(0);
4875 if (list == NULL) {
4876 if (log_list)
4877 free(log_list);
4878 return NULL;
4879 }
4880
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004881 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004882 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004883 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Christian Heimes593daf52008-05-26 12:51:38 +00004884 item = PyBytes_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004885 if (item == NULL) {
4886 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004887 list = NULL;
4888 break;
4889 }
4890 PyList_Append(list, item);
4891 Py_DECREF(item);
4892 }
4893 free(log_list_start);
4894 }
4895 return list;
4896}
4897
4898
4899static PyObject*
4900DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4901{
4902 int err;
4903 DB_TXN_STAT* sp;
4904 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004905 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004906
4907 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4908 return NULL;
4909 CHECK_ENV_NOT_CLOSED(self);
4910
4911 MYDB_BEGIN_ALLOW_THREADS;
4912#if (DBVER >= 40)
4913 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4914#elif (DBVER == 33)
4915 err = txn_stat(self->db_env, &sp);
4916#else
4917 err = txn_stat(self->db_env, &sp, NULL);
4918#endif
4919 MYDB_END_ALLOW_THREADS;
4920 RETURN_IF_ERR();
4921
4922 /* Turn the stat structure into a dictionary */
4923 d = PyDict_New();
4924 if (d == NULL) {
4925 free(sp);
4926 return NULL;
4927 }
4928
Jesus Ceaef9764f2008-05-13 18:45:46 +00004929#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4930#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4931#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004932
Jesus Ceaef9764f2008-05-13 18:45:46 +00004933#if (DBVER >= 40)
4934 MAKE_DB_LSN_ENTRY(last_ckp);
4935#endif
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004936 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004937 MAKE_ENTRY(last_txnid);
4938 MAKE_ENTRY(maxtxns);
4939 MAKE_ENTRY(nactive);
4940 MAKE_ENTRY(maxnactive);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004941#if (DBVER >= 45)
4942 MAKE_ENTRY(nsnapshot);
4943 MAKE_ENTRY(maxnsnapshot);
4944#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004945 MAKE_ENTRY(nbegins);
4946 MAKE_ENTRY(naborts);
4947 MAKE_ENTRY(ncommits);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004948#if (DBVER >= 40)
4949 MAKE_ENTRY(nrestores);
4950#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004951 MAKE_ENTRY(regsize);
4952 MAKE_ENTRY(region_wait);
4953 MAKE_ENTRY(region_nowait);
4954
Jesus Ceaef9764f2008-05-13 18:45:46 +00004955#undef MAKE_DB_LSN_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004956#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004957#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004958 free(sp);
4959 return d;
4960}
4961
4962
4963static PyObject*
4964DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4965{
4966 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004967 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004968
4969 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4970 return NULL;
4971 CHECK_ENV_NOT_CLOSED(self);
4972
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004973 if (self->moduleFlags.getReturnsNone)
4974 ++oldValue;
4975 if (self->moduleFlags.cursorSetReturnsNone)
4976 ++oldValue;
4977 self->moduleFlags.getReturnsNone = (flags >= 1);
4978 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004979 return PyInt_FromLong(oldValue);
4980}
4981
Jesus Ceaef9764f2008-05-13 18:45:46 +00004982#if (DBVER >= 40)
4983static PyObject*
Jesus Ceaca3939c2008-05-22 15:27:38 +00004984DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4985{
4986 int err;
4987 char *host;
4988 long cl_timeout=0, sv_timeout=0;
4989
4990 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
4991
4992 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
4993 &host, &cl_timeout, &sv_timeout))
4994 return NULL;
4995 CHECK_ENV_NOT_CLOSED(self);
4996
4997 MYDB_BEGIN_ALLOW_THREADS;
4998 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
4999 sv_timeout, 0);
5000 MYDB_END_ALLOW_THREADS;
5001 RETURN_IF_ERR();
5002 RETURN_NONE();
5003}
5004#endif
5005
5006#if (DBVER >= 40)
5007static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005008DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
5009{
5010 int err;
5011 int which, onoff;
5012
5013 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
5014 return NULL;
5015 }
5016 CHECK_ENV_NOT_CLOSED(self);
5017 MYDB_BEGIN_ALLOW_THREADS;
5018 err = self->db_env->set_verbose(self->db_env, which, onoff);
5019 MYDB_END_ALLOW_THREADS;
5020 RETURN_IF_ERR();
5021 RETURN_NONE();
5022}
5023
5024#if (DBVER >= 42)
5025static PyObject*
5026DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
5027{
5028 int err;
5029 int which;
5030 int verbose;
5031
5032 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
5033 return NULL;
5034 }
5035 CHECK_ENV_NOT_CLOSED(self);
5036 MYDB_BEGIN_ALLOW_THREADS;
5037 err = self->db_env->get_verbose(self->db_env, which, &verbose);
5038 MYDB_END_ALLOW_THREADS;
5039 RETURN_IF_ERR();
5040 return PyBool_FromLong(verbose);
5041}
5042#endif
5043#endif
5044
5045#if (DBVER >= 45)
5046static void
5047_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
5048{
5049 DBEnvObject *dbenv;
5050 PyObject* callback;
5051 PyObject* args;
5052 PyObject* result = NULL;
5053
5054 MYDB_BEGIN_BLOCK_THREADS;
5055 dbenv = (DBEnvObject *)db_env->app_private;
5056 callback = dbenv->event_notifyCallback;
5057 if (callback) {
5058 if (event == DB_EVENT_REP_NEWMASTER) {
5059 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
5060 } else {
5061 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5062 }
5063 if (args) {
5064 result = PyEval_CallObject(callback, args);
5065 }
5066 if ((!args) || (!result)) {
5067 PyErr_Print();
5068 }
5069 Py_XDECREF(args);
5070 Py_XDECREF(result);
5071 }
5072 MYDB_END_BLOCK_THREADS;
5073}
5074#endif
5075
5076#if (DBVER >= 45)
5077static PyObject*
5078DBEnv_set_event_notify(DBEnvObject* self, PyObject* args)
5079{
5080 int err;
5081 PyObject *notifyFunc;
5082
5083 if (!PyArg_ParseTuple(args, "O:set_event_notify", &notifyFunc)) {
5084 return NULL;
5085 }
5086
5087 CHECK_ENV_NOT_CLOSED(self);
5088
5089 if (!PyCallable_Check(notifyFunc)) {
5090 makeTypeError("Callable", notifyFunc);
5091 return NULL;
5092 }
5093
5094 Py_XDECREF(self->event_notifyCallback);
5095 Py_INCREF(notifyFunc);
5096 self->event_notifyCallback = notifyFunc;
5097
5098 MYDB_BEGIN_ALLOW_THREADS;
5099 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5100 MYDB_END_ALLOW_THREADS;
5101
5102 if (err) {
5103 Py_DECREF(notifyFunc);
5104 self->event_notifyCallback = NULL;
5105 }
5106
5107 RETURN_IF_ERR();
5108 RETURN_NONE();
5109}
5110#endif
5111
5112
5113/* --------------------------------------------------------------------- */
5114/* REPLICATION METHODS: Base Replication */
5115
5116#if (DBVER >= 45)
5117static PyObject*
5118DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5119{
5120 int err;
5121 int nsites;
5122
5123 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5124 return NULL;
5125 }
5126 CHECK_ENV_NOT_CLOSED(self);
5127 MYDB_BEGIN_ALLOW_THREADS;
5128 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5129 MYDB_END_ALLOW_THREADS;
5130 RETURN_IF_ERR();
5131 RETURN_NONE();
5132}
5133
5134static PyObject*
5135DBEnv_rep_get_nsites(DBEnvObject* self, PyObject* args)
5136{
5137 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005138#if (DBVER >= 47)
5139 u_int32_t nsites;
5140#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005141 int nsites;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005142#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005143
5144 if (!PyArg_ParseTuple(args, ":rep_get_nsites")) {
5145 return NULL;
5146 }
5147 CHECK_ENV_NOT_CLOSED(self);
5148 MYDB_BEGIN_ALLOW_THREADS;
5149 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5150 MYDB_END_ALLOW_THREADS;
5151 RETURN_IF_ERR();
5152 return PyInt_FromLong(nsites);
5153}
5154
5155static PyObject*
5156DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5157{
5158 int err;
5159 int priority;
5160
5161 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5162 return NULL;
5163 }
5164 CHECK_ENV_NOT_CLOSED(self);
5165 MYDB_BEGIN_ALLOW_THREADS;
5166 err = self->db_env->rep_set_priority(self->db_env, priority);
5167 MYDB_END_ALLOW_THREADS;
5168 RETURN_IF_ERR();
5169 RETURN_NONE();
5170}
5171
5172static PyObject*
5173DBEnv_rep_get_priority(DBEnvObject* self, PyObject* args)
5174{
5175 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005176#if (DBVER >= 47)
5177 u_int32_t priority;
5178#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005179 int priority;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005180#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005181
5182 if (!PyArg_ParseTuple(args, ":rep_get_priority")) {
5183 return NULL;
5184 }
5185 CHECK_ENV_NOT_CLOSED(self);
5186 MYDB_BEGIN_ALLOW_THREADS;
5187 err = self->db_env->rep_get_priority(self->db_env, &priority);
5188 MYDB_END_ALLOW_THREADS;
5189 RETURN_IF_ERR();
5190 return PyInt_FromLong(priority);
5191}
5192
5193static PyObject*
5194DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5195{
5196 int err;
5197 int which, timeout;
5198
5199 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5200 return NULL;
5201 }
5202 CHECK_ENV_NOT_CLOSED(self);
5203 MYDB_BEGIN_ALLOW_THREADS;
5204 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5205 MYDB_END_ALLOW_THREADS;
5206 RETURN_IF_ERR();
5207 RETURN_NONE();
5208}
5209
5210static PyObject*
5211DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5212{
5213 int err;
5214 int which;
5215 u_int32_t timeout;
5216
5217 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5218 return NULL;
5219 }
5220 CHECK_ENV_NOT_CLOSED(self);
5221 MYDB_BEGIN_ALLOW_THREADS;
5222 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5223 MYDB_END_ALLOW_THREADS;
5224 RETURN_IF_ERR();
5225 return PyInt_FromLong(timeout);
5226}
5227#endif
5228
5229/* --------------------------------------------------------------------- */
5230/* REPLICATION METHODS: Replication Manager */
5231
5232#if (DBVER >= 45)
5233static PyObject*
5234DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5235 kwargs)
5236{
5237 int err;
5238 int nthreads, flags;
5239 static char* kwnames[] = {"nthreads","flags", NULL};
5240
5241 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5242 "ii:repmgr_start", kwnames, &nthreads, &flags))
5243 {
5244 return NULL;
5245 }
5246 CHECK_ENV_NOT_CLOSED(self);
5247 MYDB_BEGIN_ALLOW_THREADS;
5248 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5249 MYDB_END_ALLOW_THREADS;
5250 RETURN_IF_ERR();
5251 RETURN_NONE();
5252}
5253
5254static PyObject*
5255DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5256 kwargs)
5257{
5258 int err;
5259 char *host;
5260 int port;
5261 int flags = 0;
5262 static char* kwnames[] = {"host", "port", "flags", NULL};
5263
5264 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5265 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5266 {
5267 return NULL;
5268 }
5269 CHECK_ENV_NOT_CLOSED(self);
5270 MYDB_BEGIN_ALLOW_THREADS;
5271 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5272 MYDB_END_ALLOW_THREADS;
5273 RETURN_IF_ERR();
5274 RETURN_NONE();
5275}
5276
5277static PyObject*
5278DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5279 kwargs)
5280{
5281 int err;
5282 char *host;
5283 int port;
5284 int flags = 0;
5285 int eidp;
5286 static char* kwnames[] = {"host", "port", "flags", NULL};
5287
5288 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5289 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5290 {
5291 return NULL;
5292 }
5293 CHECK_ENV_NOT_CLOSED(self);
5294 MYDB_BEGIN_ALLOW_THREADS;
5295 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5296 MYDB_END_ALLOW_THREADS;
5297 RETURN_IF_ERR();
5298 return PyInt_FromLong(eidp);
5299}
5300
5301static PyObject*
5302DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5303{
5304 int err;
5305 int ack_policy;
5306
5307 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5308 {
5309 return NULL;
5310 }
5311 CHECK_ENV_NOT_CLOSED(self);
5312 MYDB_BEGIN_ALLOW_THREADS;
5313 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5314 MYDB_END_ALLOW_THREADS;
5315 RETURN_IF_ERR();
5316 RETURN_NONE();
5317}
5318
5319static PyObject*
5320DBEnv_repmgr_get_ack_policy(DBEnvObject* self, PyObject* args)
5321{
5322 int err;
5323 int ack_policy;
5324
5325 if (!PyArg_ParseTuple(args, ":repmgr_get_ack_policy"))
5326 {
5327 return NULL;
5328 }
5329 CHECK_ENV_NOT_CLOSED(self);
5330 MYDB_BEGIN_ALLOW_THREADS;
5331 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5332 MYDB_END_ALLOW_THREADS;
5333 RETURN_IF_ERR();
5334 return PyInt_FromLong(ack_policy);
5335}
5336
5337static PyObject*
5338DBEnv_repmgr_site_list(DBEnvObject* self, PyObject* args)
5339{
5340 int err;
5341 unsigned int countp;
5342 DB_REPMGR_SITE *listp;
5343 PyObject *stats, *key, *tuple;
5344
5345 if (!PyArg_ParseTuple(args, ":repmgr_site_list"))
5346 {
5347 return NULL;
5348 }
5349 CHECK_ENV_NOT_CLOSED(self);
5350 MYDB_BEGIN_ALLOW_THREADS;
5351 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5352 MYDB_END_ALLOW_THREADS;
5353 RETURN_IF_ERR();
5354
5355 stats=PyDict_New();
5356 if (stats == NULL) {
5357 free(listp);
5358 return NULL;
5359 }
5360
5361 for(;countp--;) {
5362 key=PyInt_FromLong(listp[countp].eid);
5363 if(!key) {
5364 Py_DECREF(stats);
5365 free(listp);
5366 return NULL;
5367 }
5368#if (PY_VERSION_HEX >= 0x02040000)
5369 tuple=Py_BuildValue("(sII)", listp[countp].host,
5370 listp[countp].port, listp[countp].status);
5371#else
5372 tuple=Py_BuildValue("(sii)", listp[countp].host,
5373 listp[countp].port, listp[countp].status);
5374#endif
5375 if(!tuple) {
5376 Py_DECREF(key);
5377 Py_DECREF(stats);
5378 free(listp);
5379 return NULL;
5380 }
5381 if(PyDict_SetItem(stats, key, tuple)) {
5382 Py_DECREF(key);
5383 Py_DECREF(tuple);
5384 Py_DECREF(stats);
5385 free(listp);
5386 return NULL;
5387 }
5388 }
5389 free(listp);
5390 return stats;
5391}
5392#endif
5393
5394#if (DBVER >= 46)
5395static PyObject*
5396DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5397{
5398 int err;
5399 int flags=0;
5400 static char* kwnames[] = { "flags", NULL };
5401
5402 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5403 kwnames, &flags))
5404 {
5405 return NULL;
5406 }
5407 CHECK_ENV_NOT_CLOSED(self);
5408 MYDB_BEGIN_ALLOW_THREADS;
5409 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5410 MYDB_END_ALLOW_THREADS;
5411 RETURN_IF_ERR();
5412 RETURN_NONE();
5413}
5414
5415static PyObject*
5416DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5417{
5418 int err;
5419 int flags=0;
5420 DB_REPMGR_STAT *statp;
5421 PyObject *stats;
5422 static char* kwnames[] = { "flags", NULL };
5423
5424 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5425 kwnames, &flags))
5426 {
5427 return NULL;
5428 }
5429 CHECK_ENV_NOT_CLOSED(self);
5430 MYDB_BEGIN_ALLOW_THREADS;
5431 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5432 MYDB_END_ALLOW_THREADS;
5433 RETURN_IF_ERR();
5434
5435 stats=PyDict_New();
5436 if (stats == NULL) {
5437 free(statp);
5438 return NULL;
5439 }
5440
5441#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5442
5443 MAKE_ENTRY(perm_failed);
5444 MAKE_ENTRY(msgs_queued);
5445 MAKE_ENTRY(msgs_dropped);
5446 MAKE_ENTRY(connection_drop);
5447 MAKE_ENTRY(connect_fail);
5448
5449#undef MAKE_ENTRY
5450
5451 free(statp);
5452 return stats;
5453}
5454#endif
5455
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005456
5457/* --------------------------------------------------------------------- */
5458/* DBTxn methods */
5459
5460
Jesus Ceaef9764f2008-05-13 18:45:46 +00005461static void _close_transaction_cursors(DBTxnObject* txn)
5462{
5463 PyObject *dummy;
5464
5465 while(txn->children_cursors) {
5466 PyErr_Warn(PyExc_RuntimeWarning,
5467 "Must close cursors before resolving a transaction.");
5468 dummy=DBC_close_internal(txn->children_cursors);
5469 Py_XDECREF(dummy);
5470 }
5471}
5472
5473static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5474{
5475 DBObject *db;
5476#if (DBVER >= 43)
5477 DBSequenceObject *dbs;
5478#endif
5479
5480 while (txn->children_dbs) {
5481 db=txn->children_dbs;
5482 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5483 if (txn->parent_txn) {
5484 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5485 db->txn=txn->parent_txn;
5486 } else {
5487 /* The db is already linked to its environment,
5488 ** so nothing to do.
5489 */
5490 db->txn=NULL;
5491 }
5492 }
5493
5494#if (DBVER >= 43)
5495 while (txn->children_sequences) {
5496 dbs=txn->children_sequences;
5497 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5498 if (txn->parent_txn) {
5499 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5500 dbs->txn=txn->parent_txn;
5501 } else {
5502 /* The sequence is already linked to its
5503 ** parent db. Nothing to do.
5504 */
5505 dbs->txn=NULL;
5506 }
5507 }
5508#endif
5509}
5510
5511
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005512static PyObject*
5513DBTxn_commit(DBTxnObject* self, PyObject* args)
5514{
5515 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005516 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005517
5518 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5519 return NULL;
5520
Jesus Ceaef9764f2008-05-13 18:45:46 +00005521 _close_transaction_cursors(self);
5522
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005523 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005524 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005525 "after txn_commit, txn_abort "
5526 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005527 PyErr_SetObject(DBError, t);
5528 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005529 return NULL;
5530 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005531 self->flag_prepare=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005532 txn = self->txn;
5533 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005534
5535 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5536
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005537 MYDB_BEGIN_ALLOW_THREADS;
5538#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005539 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005540#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005541 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005542#endif
5543 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005544
5545 _promote_transaction_dbs_and_sequences(self);
5546
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005547 RETURN_IF_ERR();
5548 RETURN_NONE();
5549}
5550
5551static PyObject*
5552DBTxn_prepare(DBTxnObject* self, PyObject* args)
5553{
5554#if (DBVER >= 33)
5555 int err;
5556 char* gid=NULL;
5557 int gid_size=0;
5558
5559 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
5560 return NULL;
5561
5562 if (gid_size != DB_XIDDATASIZE) {
5563 PyErr_SetString(PyExc_TypeError,
5564 "gid must be DB_XIDDATASIZE bytes long");
5565 return NULL;
5566 }
5567
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005568 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005569 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005570 "after txn_commit, txn_abort "
5571 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005572 PyErr_SetObject(DBError, t);
5573 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005574 return NULL;
5575 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005576 self->flag_prepare=1; /* Prepare state */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005577 MYDB_BEGIN_ALLOW_THREADS;
5578#if (DBVER >= 40)
5579 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
5580#else
5581 err = txn_prepare(self->txn, (u_int8_t*)gid);
5582#endif
5583 MYDB_END_ALLOW_THREADS;
5584 RETURN_IF_ERR();
5585 RETURN_NONE();
5586#else
5587 int err;
5588
5589 if (!PyArg_ParseTuple(args, ":prepare"))
5590 return NULL;
5591
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005592 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005593 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005594 "after txn_commit, txn_abort "
5595 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005596 PyErr_SetObject(DBError, t);
5597 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005598 return NULL;
5599 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005600 MYDB_BEGIN_ALLOW_THREADS;
5601 err = txn_prepare(self->txn);
5602 MYDB_END_ALLOW_THREADS;
5603 RETURN_IF_ERR();
5604 RETURN_NONE();
5605#endif
5606}
5607
5608
5609static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005610DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005611{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005612 PyObject *dummy;
5613 int err=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005614 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005615
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005616 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005617 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005618 "after txn_commit, txn_abort "
5619 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005620 PyErr_SetObject(DBError, t);
5621 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005622 return NULL;
5623 }
5624 txn = self->txn;
5625 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005626
5627 _close_transaction_cursors(self);
5628#if (DBVER >= 43)
5629 while (self->children_sequences) {
5630 dummy=DBSequence_close_internal(self->children_sequences,0,0);
5631 Py_XDECREF(dummy);
5632 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005633#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005634 while (self->children_dbs) {
5635 dummy=DB_close_internal(self->children_dbs,0);
5636 Py_XDECREF(dummy);
5637 }
5638
5639 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5640
5641 MYDB_BEGIN_ALLOW_THREADS;
5642 if (discard) {
5643 assert(!self->flag_prepare);
5644#if (DBVER >= 40)
5645 err = txn->discard(txn,0);
5646#else
5647 err = txn_discard(txn);
5648#endif
5649 } else {
5650 /*
5651 ** If the transaction is in the "prepare" or "recover" state,
5652 ** we better do not implicitly abort it.
5653 */
5654 if (!self->flag_prepare) {
5655#if (DBVER >= 40)
5656 err = txn->abort(txn);
5657#else
5658 err = txn_abort(txn);
5659#endif
5660 }
5661 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005662 MYDB_END_ALLOW_THREADS;
5663 RETURN_IF_ERR();
5664 RETURN_NONE();
5665}
5666
Jesus Ceaef9764f2008-05-13 18:45:46 +00005667static PyObject*
5668DBTxn_abort(DBTxnObject* self, PyObject* args)
5669{
5670 if (!PyArg_ParseTuple(args, ":abort"))
5671 return NULL;
5672
5673 self->flag_prepare=0;
5674 _close_transaction_cursors(self);
5675
5676 return DBTxn_abort_discard_internal(self,0);
5677}
5678
5679static PyObject*
5680DBTxn_discard(DBTxnObject* self, PyObject* args)
5681{
5682 if (!PyArg_ParseTuple(args, ":discard"))
5683 return NULL;
5684
5685 self->flag_prepare=0;
5686 _close_transaction_cursors(self);
5687
5688 return DBTxn_abort_discard_internal(self,1);
5689}
5690
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005691
5692static PyObject*
5693DBTxn_id(DBTxnObject* self, PyObject* args)
5694{
5695 int id;
5696
5697 if (!PyArg_ParseTuple(args, ":id"))
5698 return NULL;
5699
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005700 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005701 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005702 "after txn_commit, txn_abort "
5703 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005704 PyErr_SetObject(DBError, t);
5705 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005706 return NULL;
5707 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005708 MYDB_BEGIN_ALLOW_THREADS;
5709#if (DBVER >= 40)
5710 id = self->txn->id(self->txn);
5711#else
5712 id = txn_id(self->txn);
5713#endif
5714 MYDB_END_ALLOW_THREADS;
5715 return PyInt_FromLong(id);
5716}
5717
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005718#if (DBVER >= 43)
5719/* --------------------------------------------------------------------- */
5720/* DBSequence methods */
5721
5722
5723static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005724DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005725{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005726 int err=0;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005727
Jesus Ceaef9764f2008-05-13 18:45:46 +00005728 if (self->sequence!=NULL) {
5729 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5730 if (self->txn) {
5731 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
5732 self->txn=NULL;
5733 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005734
Jesus Ceaef9764f2008-05-13 18:45:46 +00005735 if (!do_not_close) {
5736 MYDB_BEGIN_ALLOW_THREADS
5737 err = self->sequence->close(self->sequence, flags);
5738 MYDB_END_ALLOW_THREADS
5739 }
5740 self->sequence = NULL;
5741
5742 RETURN_IF_ERR();
5743 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005744
5745 RETURN_NONE();
5746}
5747
5748static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005749DBSequence_close(DBSequenceObject* self, PyObject* args)
5750{
5751 int flags=0;
5752 if (!PyArg_ParseTuple(args,"|i:close", &flags))
5753 return NULL;
5754
5755 return DBSequence_close_internal(self,flags,0);
5756}
5757
5758static PyObject*
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005759DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5760{
5761 int err, flags = 0;
5762 int delta = 1;
5763 db_seq_t value;
5764 PyObject *txnobj = NULL;
5765 DB_TXN *txn = NULL;
5766 static char* kwnames[] = {"delta", "txn", "flags", NULL };
5767 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
5768 return NULL;
5769 CHECK_SEQUENCE_NOT_CLOSED(self)
5770
5771 if (!checkTxnObj(txnobj, &txn))
5772 return NULL;
5773
5774 MYDB_BEGIN_ALLOW_THREADS
5775 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
5776 MYDB_END_ALLOW_THREADS
5777
5778 RETURN_IF_ERR();
5779 return PyLong_FromLongLong(value);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005780}
5781
5782static PyObject*
5783DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
5784{
5785 if (!PyArg_ParseTuple(args,":get_dbp"))
5786 return NULL;
5787 CHECK_SEQUENCE_NOT_CLOSED(self)
5788 Py_INCREF(self->mydb);
5789 return (PyObject* )self->mydb;
5790}
5791
5792static PyObject*
5793DBSequence_get_key(DBSequenceObject* self, PyObject* args)
5794{
5795 int err;
5796 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00005797 PyObject *retval = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005798
5799 if (!PyArg_ParseTuple(args,":get_key"))
5800 return NULL;
5801
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005802 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005803 CHECK_SEQUENCE_NOT_CLOSED(self)
5804 MYDB_BEGIN_ALLOW_THREADS
5805 err = self->sequence->get_key(self->sequence, &key);
5806 MYDB_END_ALLOW_THREADS
5807
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005808 if (!err)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005809 retval = Build_PyString(key.data, key.size);
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005810
5811 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005812 RETURN_IF_ERR();
5813
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005814 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005815}
5816
5817static PyObject*
5818DBSequence_init_value(DBSequenceObject* self, PyObject* args)
5819{
5820 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005821 PY_LONG_LONG value;
5822 db_seq_t value2;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005823 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005824 return NULL;
5825 CHECK_SEQUENCE_NOT_CLOSED(self)
5826
Jesus Ceaef9764f2008-05-13 18:45:46 +00005827 value2=value; /* If truncation, compiler should show a warning */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005828 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005829 err = self->sequence->initial_value(self->sequence, value2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005830 MYDB_END_ALLOW_THREADS
5831
5832 RETURN_IF_ERR();
5833
5834 RETURN_NONE();
5835}
5836
5837static PyObject*
5838DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5839{
5840 int err, flags = 0;
5841 PyObject* keyobj;
5842 PyObject *txnobj = NULL;
5843 DB_TXN *txn = NULL;
5844 DBT key;
5845
5846 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005847 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005848 return NULL;
5849
5850 if (!checkTxnObj(txnobj, &txn))
5851 return NULL;
5852
5853 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
5854 return NULL;
5855
5856 MYDB_BEGIN_ALLOW_THREADS
5857 err = self->sequence->open(self->sequence, txn, &key, flags);
5858 MYDB_END_ALLOW_THREADS
5859
5860 CLEAR_DBT(key);
5861 RETURN_IF_ERR();
5862
Jesus Ceaef9764f2008-05-13 18:45:46 +00005863 if (txn) {
5864 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
5865 self->txn=(DBTxnObject *)txnobj;
5866 }
5867
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005868 RETURN_NONE();
5869}
5870
5871static PyObject*
5872DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5873{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005874 PyObject *dummy;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005875 int err, flags = 0;
5876 PyObject *txnobj = NULL;
5877 DB_TXN *txn = NULL;
5878
5879 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005880 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005881 return NULL;
5882
5883 if (!checkTxnObj(txnobj, &txn))
5884 return NULL;
5885
5886 CHECK_SEQUENCE_NOT_CLOSED(self)
5887
5888 MYDB_BEGIN_ALLOW_THREADS
5889 err = self->sequence->remove(self->sequence, txn, flags);
5890 MYDB_END_ALLOW_THREADS
5891
Jesus Ceaef9764f2008-05-13 18:45:46 +00005892 dummy=DBSequence_close_internal(self,flags,1);
5893 Py_XDECREF(dummy);
5894
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005895 RETURN_IF_ERR();
5896 RETURN_NONE();
5897}
5898
5899static PyObject*
5900DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
5901{
5902 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005903 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005904 return NULL;
5905 CHECK_SEQUENCE_NOT_CLOSED(self)
5906
5907 MYDB_BEGIN_ALLOW_THREADS
5908 err = self->sequence->set_cachesize(self->sequence, size);
5909 MYDB_END_ALLOW_THREADS
5910
5911 RETURN_IF_ERR();
5912 RETURN_NONE();
5913}
5914
5915static PyObject*
5916DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5917{
5918 int err, size;
5919 if (!PyArg_ParseTuple(args,":get_cachesize"))
5920 return NULL;
5921 CHECK_SEQUENCE_NOT_CLOSED(self)
5922
5923 MYDB_BEGIN_ALLOW_THREADS
5924 err = self->sequence->get_cachesize(self->sequence, &size);
5925 MYDB_END_ALLOW_THREADS
5926
5927 RETURN_IF_ERR();
5928 return PyInt_FromLong(size);
5929}
5930
5931static PyObject*
5932DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5933{
5934 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005935 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005936 return NULL;
5937 CHECK_SEQUENCE_NOT_CLOSED(self)
5938
5939 MYDB_BEGIN_ALLOW_THREADS
5940 err = self->sequence->set_flags(self->sequence, flags);
5941 MYDB_END_ALLOW_THREADS
5942
5943 RETURN_IF_ERR();
5944 RETURN_NONE();
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005945}
5946
5947static PyObject*
5948DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5949{
5950 unsigned int flags;
5951 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005952 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005953 return NULL;
5954 CHECK_SEQUENCE_NOT_CLOSED(self)
5955
5956 MYDB_BEGIN_ALLOW_THREADS
5957 err = self->sequence->get_flags(self->sequence, &flags);
5958 MYDB_END_ALLOW_THREADS
5959
5960 RETURN_IF_ERR();
5961 return PyInt_FromLong((int)flags);
5962}
5963
5964static PyObject*
5965DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5966{
5967 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005968 PY_LONG_LONG min, max;
5969 db_seq_t min2, max2;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005970 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005971 return NULL;
5972 CHECK_SEQUENCE_NOT_CLOSED(self)
5973
Jesus Ceaef9764f2008-05-13 18:45:46 +00005974 min2=min; /* If truncation, compiler should show a warning */
5975 max2=max;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005976 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005977 err = self->sequence->set_range(self->sequence, min2, max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005978 MYDB_END_ALLOW_THREADS
5979
5980 RETURN_IF_ERR();
5981 RETURN_NONE();
5982}
5983
5984static PyObject*
5985DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5986{
5987 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005988 PY_LONG_LONG min, max;
5989 db_seq_t min2, max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005990 if (!PyArg_ParseTuple(args,":get_range"))
5991 return NULL;
5992 CHECK_SEQUENCE_NOT_CLOSED(self)
5993
5994 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005995 err = self->sequence->get_range(self->sequence, &min2, &max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005996 MYDB_END_ALLOW_THREADS
5997
5998 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00005999 min=min2; /* If truncation, compiler should show a warning */
6000 max=max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006001 return Py_BuildValue("(LL)", min, max);
6002}
6003
6004static PyObject*
6005DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6006{
6007 int err, flags = 0;
6008 DB_SEQUENCE_STAT* sp = NULL;
6009 PyObject* dict_stat;
6010 static char* kwnames[] = {"flags", NULL };
6011 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
6012 return NULL;
6013 CHECK_SEQUENCE_NOT_CLOSED(self);
6014
6015 MYDB_BEGIN_ALLOW_THREADS;
6016 err = self->sequence->stat(self->sequence, &sp, flags);
6017 MYDB_END_ALLOW_THREADS;
6018 RETURN_IF_ERR();
6019
6020 if ((dict_stat = PyDict_New()) == NULL) {
6021 free(sp);
6022 return NULL;
6023 }
6024
6025
6026#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
6027#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
6028
6029 MAKE_INT_ENTRY(wait);
6030 MAKE_INT_ENTRY(nowait);
6031 MAKE_LONG_LONG_ENTRY(current);
6032 MAKE_LONG_LONG_ENTRY(value);
6033 MAKE_LONG_LONG_ENTRY(last_value);
6034 MAKE_LONG_LONG_ENTRY(min);
6035 MAKE_LONG_LONG_ENTRY(max);
6036 MAKE_INT_ENTRY(cache_size);
6037 MAKE_INT_ENTRY(flags);
6038
6039#undef MAKE_INT_ENTRY
6040#undef MAKE_LONG_LONG_ENTRY
6041
6042 free(sp);
6043 return dict_stat;
6044}
6045#endif
6046
6047
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006048/* --------------------------------------------------------------------- */
6049/* Method definition tables and type objects */
6050
6051static PyMethodDef DB_methods[] = {
6052 {"append", (PyCFunction)DB_append, METH_VARARGS},
6053#if (DBVER >= 33)
6054 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
6055#endif
6056 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006057 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
6058 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006059 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
6060 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
6061 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
6062 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006063#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00006064 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006065#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006066 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
6067 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
6068 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
6069 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
6070 {"join", (PyCFunction)DB_join, METH_VARARGS},
6071 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
6072 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
6073 {"items", (PyCFunction)DB_items, METH_VARARGS},
6074 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6075 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6076 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6077 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6078 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6079 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006080#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00006081 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006082#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006083 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006084#if (DBVER >= 41)
6085 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6086#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006087 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6088 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6089 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6090 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6091 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6092 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6093 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6094 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6095 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006096 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006097 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006098 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
6099#if (DBVER >= 33)
6100 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
6101#endif
6102 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
6103 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6104 {"values", (PyCFunction)DB_values, METH_VARARGS},
6105 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6106 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6107 {NULL, NULL} /* sentinel */
6108};
6109
6110
6111static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00006112 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006113 (binaryfunc)DB_subscript, /*mp_subscript*/
6114 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6115};
6116
6117
6118static PyMethodDef DBCursor_methods[] = {
6119 {"close", (PyCFunction)DBC_close, METH_VARARGS},
6120 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6121 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6122 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6123 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6124 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6125 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006126#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00006127 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006128#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006129 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
6130 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6131 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6132 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6133 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6134 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6135 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6136 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00006137 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00006138 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006139 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6140 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6141 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6142 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6143 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6144 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6145 {NULL, NULL} /* sentinel */
6146};
6147
6148
6149static PyMethodDef DBEnv_methods[] = {
6150 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6151 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6152 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006153#if (DBVER >= 41)
6154 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6155 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6156 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6157#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00006158#if (DBVER >= 40)
6159 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
6160#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00006161 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006162 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6163 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006164 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Jesus Ceaca3939c2008-05-22 15:27:38 +00006165#if (DBVER >= 47)
6166 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
6167#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006168 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6169 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6170 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006171#if (DBVER >= 42)
6172 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_VARARGS},
6173#endif
Neal Norwitz84562352005-10-20 04:30:15 +00006174#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00006175 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006176#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006177 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006178#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006179 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006180#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006181 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6182 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6183 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006184 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6185 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6186 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6187 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6188 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6189 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00006190 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006191 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6192 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
6193 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Gregory P. Smithac11e022007-11-05 02:56:31 +00006194#if (DBVER >= 40)
6195 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
6196#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006197 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6198 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6199 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006200#if (DBVER >= 40)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006201 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_VARARGS},
6202#endif
6203#if (DBVER >= 40)
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006204 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
6205#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00006206#if (DBVER >= 44)
6207 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6208#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006209 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006210#if (DBVER >= 40)
6211 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_VARARGS},
6212#endif
6213#if (DBVER >= 40)
Jesus Ceaca3939c2008-05-22 15:27:38 +00006214 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
6215 METH_VARARGS||METH_KEYWORDS},
6216#endif
6217#if (DBVER >= 40)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006218 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6219#if (DBVER >= 42)
6220 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6221#endif
6222#endif
6223#if (DBVER >= 45)
6224 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_VARARGS},
6225#endif
6226#if (DBVER >= 45)
6227 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
6228 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_VARARGS},
6229 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
6230 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_VARARGS},
6231 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6232 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6233#endif
6234#if (DBVER >= 45)
6235 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6236 METH_VARARGS|METH_KEYWORDS},
6237 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6238 METH_VARARGS|METH_KEYWORDS},
6239 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6240 METH_VARARGS|METH_KEYWORDS},
6241 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6242 METH_VARARGS},
6243 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
6244 METH_VARARGS},
6245 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
6246 METH_VARARGS},
6247#endif
6248#if (DBVER >= 46)
6249 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6250 METH_VARARGS|METH_KEYWORDS},
6251 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6252 METH_VARARGS|METH_KEYWORDS},
6253#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006254 {NULL, NULL} /* sentinel */
6255};
6256
6257
6258static PyMethodDef DBTxn_methods[] = {
6259 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6260 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006261 {"discard", (PyCFunction)DBTxn_discard, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006262 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
6263 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
6264 {NULL, NULL} /* sentinel */
6265};
6266
6267
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006268#if (DBVER >= 43)
6269static PyMethodDef DBSequence_methods[] = {
6270 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6271 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
6272 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
6273 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006274 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6275 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6276 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6277 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
6278 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
6279 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
6280 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
6281 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
6282 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
6283 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6284 {NULL, NULL} /* sentinel */
6285};
6286#endif
6287
6288
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006289static PyObject*
6290DB_getattr(DBObject* self, char *name)
6291{
6292 return Py_FindMethod(DB_methods, (PyObject* )self, name);
6293}
6294
6295
6296static PyObject*
6297DBEnv_getattr(DBEnvObject* self, char *name)
6298{
6299 if (!strcmp(name, "db_home")) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00006300 const char *home = NULL;
6301 CHECK_ENV_NOT_CLOSED(self);
6302#if (DBVER >= 42)
6303 self->db_env->get_home(self->db_env, &home);
6304#else
6305 home=self->db_env->db_home;
6306#endif
6307 if (home == NULL) {
6308 RETURN_NONE();
6309 }
Christian Heimes593daf52008-05-26 12:51:38 +00006310 return PyBytes_FromString(home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006311 }
6312
6313 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
6314}
6315
6316
6317static PyObject*
6318DBCursor_getattr(DBCursorObject* self, char *name)
6319{
6320 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
6321}
6322
6323static PyObject*
6324DBTxn_getattr(DBTxnObject* self, char *name)
6325{
6326 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
6327}
6328
6329static PyObject*
6330DBLock_getattr(DBLockObject* self, char *name)
6331{
6332 return NULL;
6333}
6334
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006335#if (DBVER >= 43)
6336static PyObject*
6337DBSequence_getattr(DBSequenceObject* self, char *name)
6338{
6339 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
6340}
6341#endif
6342
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006343statichere PyTypeObject DB_Type = {
6344 PyObject_HEAD_INIT(NULL)
6345 0, /*ob_size*/
6346 "DB", /*tp_name*/
6347 sizeof(DBObject), /*tp_basicsize*/
6348 0, /*tp_itemsize*/
6349 /* methods */
6350 (destructor)DB_dealloc, /*tp_dealloc*/
6351 0, /*tp_print*/
6352 (getattrfunc)DB_getattr, /*tp_getattr*/
6353 0, /*tp_setattr*/
6354 0, /*tp_compare*/
6355 0, /*tp_repr*/
6356 0, /*tp_as_number*/
6357 0, /*tp_as_sequence*/
6358 &DB_mapping,/*tp_as_mapping*/
6359 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006360 0, /* tp_call */
6361 0, /* tp_str */
6362 0, /* tp_getattro */
6363 0, /* tp_setattro */
6364 0, /* tp_as_buffer */
6365 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6366 0, /* tp_doc */
6367 0, /* tp_traverse */
6368 0, /* tp_clear */
6369 0, /* tp_richcompare */
6370 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006371};
6372
6373
6374statichere PyTypeObject DBCursor_Type = {
6375 PyObject_HEAD_INIT(NULL)
6376 0, /*ob_size*/
6377 "DBCursor", /*tp_name*/
6378 sizeof(DBCursorObject), /*tp_basicsize*/
6379 0, /*tp_itemsize*/
6380 /* methods */
6381 (destructor)DBCursor_dealloc,/*tp_dealloc*/
6382 0, /*tp_print*/
6383 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
6384 0, /*tp_setattr*/
6385 0, /*tp_compare*/
6386 0, /*tp_repr*/
6387 0, /*tp_as_number*/
6388 0, /*tp_as_sequence*/
6389 0, /*tp_as_mapping*/
6390 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00006391 0, /* tp_call */
6392 0, /* tp_str */
6393 0, /* tp_getattro */
6394 0, /* tp_setattro */
6395 0, /* tp_as_buffer */
6396 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6397 0, /* tp_doc */
6398 0, /* tp_traverse */
6399 0, /* tp_clear */
6400 0, /* tp_richcompare */
6401 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006402};
6403
6404
6405statichere PyTypeObject DBEnv_Type = {
6406 PyObject_HEAD_INIT(NULL)
6407 0, /*ob_size*/
6408 "DBEnv", /*tp_name*/
6409 sizeof(DBEnvObject), /*tp_basicsize*/
6410 0, /*tp_itemsize*/
6411 /* methods */
6412 (destructor)DBEnv_dealloc, /*tp_dealloc*/
6413 0, /*tp_print*/
6414 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
6415 0, /*tp_setattr*/
6416 0, /*tp_compare*/
6417 0, /*tp_repr*/
6418 0, /*tp_as_number*/
6419 0, /*tp_as_sequence*/
6420 0, /*tp_as_mapping*/
6421 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006422 0, /* tp_call */
6423 0, /* tp_str */
6424 0, /* tp_getattro */
6425 0, /* tp_setattro */
6426 0, /* tp_as_buffer */
6427 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6428 0, /* tp_doc */
6429 0, /* tp_traverse */
6430 0, /* tp_clear */
6431 0, /* tp_richcompare */
6432 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006433};
6434
6435statichere PyTypeObject DBTxn_Type = {
6436 PyObject_HEAD_INIT(NULL)
6437 0, /*ob_size*/
6438 "DBTxn", /*tp_name*/
6439 sizeof(DBTxnObject), /*tp_basicsize*/
6440 0, /*tp_itemsize*/
6441 /* methods */
6442 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6443 0, /*tp_print*/
6444 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
6445 0, /*tp_setattr*/
6446 0, /*tp_compare*/
6447 0, /*tp_repr*/
6448 0, /*tp_as_number*/
6449 0, /*tp_as_sequence*/
6450 0, /*tp_as_mapping*/
6451 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006452 0, /* tp_call */
6453 0, /* tp_str */
6454 0, /* tp_getattro */
6455 0, /* tp_setattro */
6456 0, /* tp_as_buffer */
6457 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6458 0, /* tp_doc */
6459 0, /* tp_traverse */
6460 0, /* tp_clear */
6461 0, /* tp_richcompare */
6462 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006463};
6464
6465
6466statichere PyTypeObject DBLock_Type = {
6467 PyObject_HEAD_INIT(NULL)
6468 0, /*ob_size*/
6469 "DBLock", /*tp_name*/
6470 sizeof(DBLockObject), /*tp_basicsize*/
6471 0, /*tp_itemsize*/
6472 /* methods */
6473 (destructor)DBLock_dealloc, /*tp_dealloc*/
6474 0, /*tp_print*/
6475 (getattrfunc)DBLock_getattr, /*tp_getattr*/
6476 0, /*tp_setattr*/
6477 0, /*tp_compare*/
6478 0, /*tp_repr*/
6479 0, /*tp_as_number*/
6480 0, /*tp_as_sequence*/
6481 0, /*tp_as_mapping*/
6482 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006483 0, /* tp_call */
6484 0, /* tp_str */
6485 0, /* tp_getattro */
6486 0, /* tp_setattro */
6487 0, /* tp_as_buffer */
6488 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6489 0, /* tp_doc */
6490 0, /* tp_traverse */
6491 0, /* tp_clear */
6492 0, /* tp_richcompare */
6493 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006494};
6495
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006496#if (DBVER >= 43)
6497statichere PyTypeObject DBSequence_Type = {
6498 PyObject_HEAD_INIT(NULL)
6499 0, /*ob_size*/
6500 "DBSequence", /*tp_name*/
6501 sizeof(DBSequenceObject), /*tp_basicsize*/
6502 0, /*tp_itemsize*/
6503 /* methods */
6504 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6505 0, /*tp_print*/
6506 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
6507 0, /*tp_setattr*/
6508 0, /*tp_compare*/
6509 0, /*tp_repr*/
6510 0, /*tp_as_number*/
6511 0, /*tp_as_sequence*/
6512 0, /*tp_as_mapping*/
6513 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006514 0, /* tp_call */
6515 0, /* tp_str */
6516 0, /* tp_getattro */
6517 0, /* tp_setattro */
6518 0, /* tp_as_buffer */
6519 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6520 0, /* tp_doc */
6521 0, /* tp_traverse */
6522 0, /* tp_clear */
6523 0, /* tp_richcompare */
6524 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006525};
6526#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006527
6528/* --------------------------------------------------------------------- */
6529/* Module-level functions */
6530
6531static PyObject*
6532DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6533{
6534 PyObject* dbenvobj = NULL;
6535 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00006536 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006537
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006538 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6539 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006540 return NULL;
6541 if (dbenvobj == Py_None)
6542 dbenvobj = NULL;
6543 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6544 makeTypeError("DBEnv", dbenvobj);
6545 return NULL;
6546 }
6547
6548 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6549}
6550
6551
6552static PyObject*
6553DBEnv_construct(PyObject* self, PyObject* args)
6554{
6555 int flags = 0;
6556 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6557 return (PyObject* )newDBEnvObject(flags);
6558}
6559
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006560#if (DBVER >= 43)
6561static PyObject*
6562DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6563{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006564 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006565 int flags = 0;
6566 static char* kwnames[] = { "db", "flags", NULL};
6567
6568 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6569 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006570 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006571 makeTypeError("DB", dbobj);
6572 return NULL;
6573 }
6574 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6575}
6576#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006577
6578static char bsddb_version_doc[] =
6579"Returns a tuple of major, minor, and patch release numbers of the\n\
6580underlying DB library.";
6581
6582static PyObject*
6583bsddb_version(PyObject* self, PyObject* args)
6584{
6585 int major, minor, patch;
6586
6587 if (!PyArg_ParseTuple(args, ":version"))
6588 return NULL;
6589 db_version(&major, &minor, &patch);
6590 return Py_BuildValue("(iii)", major, minor, patch);
6591}
6592
6593
6594/* List of functions defined in the module */
6595
6596static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006597 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6598 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
6599#if (DBVER >= 43)
6600 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
6601#endif
6602 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006603 {NULL, NULL} /* sentinel */
6604};
6605
Gregory P. Smith39250532007-10-09 06:02:21 +00006606/* API structure */
6607static BSDDB_api bsddb_api;
6608
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006609
6610/* --------------------------------------------------------------------- */
6611/* Module initialization */
6612
6613
6614/* Convenience routine to export an integer value.
6615 * Errors are silently ignored, for better or for worse...
6616 */
6617#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
6618
Gregory P. Smith41631e82003-09-21 00:08:14 +00006619#define MODULE_NAME_MAX_LEN 11
6620static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006621
6622DL_EXPORT(void) init_bsddb(void)
6623{
6624 PyObject* m;
6625 PyObject* d;
Christian Heimes593daf52008-05-26 12:51:38 +00006626 PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
6627 PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
6628 PyObject* cvsid_s = PyBytes_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00006629 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006630
6631 /* Initialize the type of the new type objects here; doing it here
6632 is required for portability to Windows without requiring C++. */
Christian Heimese93237d2007-12-19 02:37:44 +00006633 Py_TYPE(&DB_Type) = &PyType_Type;
6634 Py_TYPE(&DBCursor_Type) = &PyType_Type;
6635 Py_TYPE(&DBEnv_Type) = &PyType_Type;
6636 Py_TYPE(&DBTxn_Type) = &PyType_Type;
6637 Py_TYPE(&DBLock_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006638#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +00006639 Py_TYPE(&DBSequence_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006640#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006641
6642
Mark Hammonda69d4092003-04-22 23:13:27 +00006643#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006644 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00006645 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006646#endif
6647
6648 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00006649 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00006650 if (m == NULL)
6651 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006652
6653 /* Add some symbolic constants to the module */
6654 d = PyModule_GetDict(m);
6655 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
6656 PyDict_SetItemString(d, "cvsid", cvsid_s);
6657 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
6658 Py_DECREF(pybsddb_version_s);
6659 pybsddb_version_s = NULL;
6660 Py_DECREF(cvsid_s);
6661 cvsid_s = NULL;
6662 Py_DECREF(db_version_s);
6663 db_version_s = NULL;
6664
6665 ADD_INT(d, DB_VERSION_MAJOR);
6666 ADD_INT(d, DB_VERSION_MINOR);
6667 ADD_INT(d, DB_VERSION_PATCH);
6668
6669 ADD_INT(d, DB_MAX_PAGES);
6670 ADD_INT(d, DB_MAX_RECORDS);
6671
Gregory P. Smith41631e82003-09-21 00:08:14 +00006672#if (DBVER >= 42)
6673 ADD_INT(d, DB_RPCCLIENT);
6674#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006675 ADD_INT(d, DB_CLIENT);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006676 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
Gregory P. Smith41631e82003-09-21 00:08:14 +00006677 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
6678#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006679 ADD_INT(d, DB_XA_CREATE);
6680
6681 ADD_INT(d, DB_CREATE);
6682 ADD_INT(d, DB_NOMMAP);
6683 ADD_INT(d, DB_THREAD);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006684#if (DBVER >= 45)
6685 ADD_INT(d, DB_MULTIVERSION);
6686#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006687
6688 ADD_INT(d, DB_FORCE);
6689 ADD_INT(d, DB_INIT_CDB);
6690 ADD_INT(d, DB_INIT_LOCK);
6691 ADD_INT(d, DB_INIT_LOG);
6692 ADD_INT(d, DB_INIT_MPOOL);
6693 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006694 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006695
Jesus Ceaef9764f2008-05-13 18:45:46 +00006696#if (DBVER >= 40)
6697 ADD_INT(d, DB_XIDDATASIZE);
6698#endif
6699
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006700 ADD_INT(d, DB_RECOVER);
6701 ADD_INT(d, DB_RECOVER_FATAL);
6702 ADD_INT(d, DB_TXN_NOSYNC);
6703 ADD_INT(d, DB_USE_ENVIRON);
6704 ADD_INT(d, DB_USE_ENVIRON_ROOT);
6705
6706 ADD_INT(d, DB_LOCKDOWN);
6707 ADD_INT(d, DB_PRIVATE);
6708 ADD_INT(d, DB_SYSTEM_MEM);
6709
6710 ADD_INT(d, DB_TXN_SYNC);
6711 ADD_INT(d, DB_TXN_NOWAIT);
6712
6713 ADD_INT(d, DB_EXCL);
6714 ADD_INT(d, DB_FCNTL_LOCKING);
6715 ADD_INT(d, DB_ODDFILESIZE);
6716 ADD_INT(d, DB_RDWRMASTER);
6717 ADD_INT(d, DB_RDONLY);
6718 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006719 ADD_INT(d, DB_EXTENT);
6720 ADD_INT(d, DB_CDB_ALLDB);
6721 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006722 ADD_INT(d, DB_UPGRADE);
6723
6724 ADD_INT(d, DB_AGGRESSIVE);
6725 ADD_INT(d, DB_NOORDERCHK);
6726 ADD_INT(d, DB_ORDERCHKONLY);
6727 ADD_INT(d, DB_PR_PAGE);
6728#if ! (DBVER >= 33)
6729 ADD_INT(d, DB_VRFY_FLAGMASK);
6730 ADD_INT(d, DB_PR_HEADERS);
6731#endif
6732 ADD_INT(d, DB_PR_RECOVERYTEST);
6733 ADD_INT(d, DB_SALVAGE);
6734
6735 ADD_INT(d, DB_LOCK_NORUN);
6736 ADD_INT(d, DB_LOCK_DEFAULT);
6737 ADD_INT(d, DB_LOCK_OLDEST);
6738 ADD_INT(d, DB_LOCK_RANDOM);
6739 ADD_INT(d, DB_LOCK_YOUNGEST);
6740#if (DBVER >= 33)
6741 ADD_INT(d, DB_LOCK_MAXLOCKS);
6742 ADD_INT(d, DB_LOCK_MINLOCKS);
6743 ADD_INT(d, DB_LOCK_MINWRITE);
6744#endif
6745
Jesus Ceaef9764f2008-05-13 18:45:46 +00006746#if (DBVER >= 40)
6747 ADD_INT(d, DB_LOCK_EXPIRE);
6748#endif
6749#if (DBVER >= 43)
6750 ADD_INT(d, DB_LOCK_MAXWRITE);
6751#endif
6752
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006753
6754#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006755 /* docs say to use zero instead */
6756 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006757#else
6758 ADD_INT(d, DB_LOCK_CONFLICT);
6759#endif
6760
6761 ADD_INT(d, DB_LOCK_DUMP);
6762 ADD_INT(d, DB_LOCK_GET);
6763 ADD_INT(d, DB_LOCK_INHERIT);
6764 ADD_INT(d, DB_LOCK_PUT);
6765 ADD_INT(d, DB_LOCK_PUT_ALL);
6766 ADD_INT(d, DB_LOCK_PUT_OBJ);
6767
6768 ADD_INT(d, DB_LOCK_NG);
6769 ADD_INT(d, DB_LOCK_READ);
6770 ADD_INT(d, DB_LOCK_WRITE);
6771 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006772 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006773 ADD_INT(d, DB_LOCK_IWRITE);
6774 ADD_INT(d, DB_LOCK_IREAD);
6775 ADD_INT(d, DB_LOCK_IWR);
6776#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00006777#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006778 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00006779#else
6780 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
6781#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006782 ADD_INT(d, DB_LOCK_WWRITE);
6783#endif
6784
6785 ADD_INT(d, DB_LOCK_RECORD);
6786 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006787 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006788#if (DBVER >= 33)
6789 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
6790#endif
6791
6792 ADD_INT(d, DB_LOCK_NOWAIT);
6793 ADD_INT(d, DB_LOCK_RECORD);
6794 ADD_INT(d, DB_LOCK_UPGRADE);
6795
6796#if (DBVER >= 33)
6797 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006798#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006799 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006800#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006801 ADD_INT(d, DB_LSTAT_FREE);
6802 ADD_INT(d, DB_LSTAT_HELD);
6803#if (DBVER == 33)
6804 ADD_INT(d, DB_LSTAT_NOGRANT);
6805#endif
6806 ADD_INT(d, DB_LSTAT_PENDING);
6807 ADD_INT(d, DB_LSTAT_WAITING);
6808#endif
6809
6810 ADD_INT(d, DB_ARCH_ABS);
6811 ADD_INT(d, DB_ARCH_DATA);
6812 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00006813#if (DBVER >= 42)
6814 ADD_INT(d, DB_ARCH_REMOVE);
6815#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006816
6817 ADD_INT(d, DB_BTREE);
6818 ADD_INT(d, DB_HASH);
6819 ADD_INT(d, DB_RECNO);
6820 ADD_INT(d, DB_QUEUE);
6821 ADD_INT(d, DB_UNKNOWN);
6822
6823 ADD_INT(d, DB_DUP);
6824 ADD_INT(d, DB_DUPSORT);
6825 ADD_INT(d, DB_RECNUM);
6826 ADD_INT(d, DB_RENUMBER);
6827 ADD_INT(d, DB_REVSPLITOFF);
6828 ADD_INT(d, DB_SNAPSHOT);
6829
6830 ADD_INT(d, DB_JOIN_NOSORT);
6831
6832 ADD_INT(d, DB_AFTER);
6833 ADD_INT(d, DB_APPEND);
6834 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006835#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006836 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006837#endif
Jesus Ceaca3939c2008-05-22 15:27:38 +00006838
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006839#if (DBVER >= 41)
6840 _addIntToDict(d, "DB_CHECKPOINT", 0);
6841#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006842 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006843 ADD_INT(d, DB_CURLSN);
6844#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00006845#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006846 ADD_INT(d, DB_COMMIT);
6847#endif
6848 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006849 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006850 ADD_INT(d, DB_CURRENT);
6851#if (DBVER >= 33)
6852 ADD_INT(d, DB_FAST_STAT);
6853#endif
6854 ADD_INT(d, DB_FIRST);
6855 ADD_INT(d, DB_FLUSH);
6856 ADD_INT(d, DB_GET_BOTH);
6857 ADD_INT(d, DB_GET_RECNO);
6858 ADD_INT(d, DB_JOIN_ITEM);
6859 ADD_INT(d, DB_KEYFIRST);
6860 ADD_INT(d, DB_KEYLAST);
6861 ADD_INT(d, DB_LAST);
6862 ADD_INT(d, DB_NEXT);
6863 ADD_INT(d, DB_NEXT_DUP);
6864 ADD_INT(d, DB_NEXT_NODUP);
6865 ADD_INT(d, DB_NODUPDATA);
6866 ADD_INT(d, DB_NOOVERWRITE);
6867 ADD_INT(d, DB_NOSYNC);
6868 ADD_INT(d, DB_POSITION);
6869 ADD_INT(d, DB_PREV);
6870 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006871#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006872 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006873#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006874 ADD_INT(d, DB_SET);
6875 ADD_INT(d, DB_SET_RANGE);
6876 ADD_INT(d, DB_SET_RECNO);
6877 ADD_INT(d, DB_WRITECURSOR);
6878
6879 ADD_INT(d, DB_OPFLAGS_MASK);
6880 ADD_INT(d, DB_RMW);
6881#if (DBVER >= 33)
6882 ADD_INT(d, DB_DIRTY_READ);
6883 ADD_INT(d, DB_MULTIPLE);
6884 ADD_INT(d, DB_MULTIPLE_KEY);
6885#endif
6886
Gregory P. Smith29602d22006-01-24 09:46:48 +00006887#if (DBVER >= 44)
6888 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
6889 ADD_INT(d, DB_READ_COMMITTED);
6890#endif
6891
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006892#if (DBVER >= 33)
6893 ADD_INT(d, DB_DONOTINDEX);
6894#endif
6895
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006896#if (DBVER >= 41)
6897 _addIntToDict(d, "DB_INCOMPLETE", 0);
6898#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006899 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006900#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006901 ADD_INT(d, DB_KEYEMPTY);
6902 ADD_INT(d, DB_KEYEXIST);
6903 ADD_INT(d, DB_LOCK_DEADLOCK);
6904 ADD_INT(d, DB_LOCK_NOTGRANTED);
6905 ADD_INT(d, DB_NOSERVER);
6906 ADD_INT(d, DB_NOSERVER_HOME);
6907 ADD_INT(d, DB_NOSERVER_ID);
6908 ADD_INT(d, DB_NOTFOUND);
6909 ADD_INT(d, DB_OLD_VERSION);
6910 ADD_INT(d, DB_RUNRECOVERY);
6911 ADD_INT(d, DB_VERIFY_BAD);
6912#if (DBVER >= 33)
6913 ADD_INT(d, DB_PAGE_NOTFOUND);
6914 ADD_INT(d, DB_SECONDARY_BAD);
6915#endif
6916#if (DBVER >= 40)
6917 ADD_INT(d, DB_STAT_CLEAR);
6918 ADD_INT(d, DB_REGION_INIT);
6919 ADD_INT(d, DB_NOLOCKING);
6920 ADD_INT(d, DB_YIELDCPU);
6921 ADD_INT(d, DB_PANIC_ENVIRONMENT);
6922 ADD_INT(d, DB_NOPANIC);
6923#endif
6924
Jesus Ceaef9764f2008-05-13 18:45:46 +00006925#if (DBVER >= 41)
6926 ADD_INT(d, DB_OVERWRITE);
6927#endif
6928
Gregory P. Smithaae141a2007-11-01 21:08:14 +00006929#ifdef DB_REGISTER
6930 ADD_INT(d, DB_REGISTER);
6931#endif
6932
Gregory P. Smith41631e82003-09-21 00:08:14 +00006933#if (DBVER >= 42)
6934 ADD_INT(d, DB_TIME_NOTGRANTED);
6935 ADD_INT(d, DB_TXN_NOT_DURABLE);
6936 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
Gregory P. Smith41631e82003-09-21 00:08:14 +00006937 ADD_INT(d, DB_DIRECT_DB);
6938 ADD_INT(d, DB_INIT_REP);
6939 ADD_INT(d, DB_ENCRYPT);
6940 ADD_INT(d, DB_CHKSUM);
6941#endif
6942
Jesus Ceaca3939c2008-05-22 15:27:38 +00006943#if (DBVER >= 42) && (DBVER < 47)
6944 ADD_INT(d, DB_LOG_AUTOREMOVE);
6945 ADD_INT(d, DB_DIRECT_LOG);
6946#endif
6947
6948#if (DBVER >= 47)
6949 ADD_INT(d, DB_LOG_DIRECT);
6950 ADD_INT(d, DB_LOG_DSYNC);
6951 ADD_INT(d, DB_LOG_IN_MEMORY);
6952 ADD_INT(d, DB_LOG_AUTO_REMOVE);
6953 ADD_INT(d, DB_LOG_ZERO);
6954#endif
6955
Jesus Ceaef9764f2008-05-13 18:45:46 +00006956#if (DBVER >= 44)
6957 ADD_INT(d, DB_DSYNC_DB);
6958#endif
6959
6960#if (DBVER >= 45)
6961 ADD_INT(d, DB_TXN_SNAPSHOT);
6962#endif
6963
6964#if (DBVER >= 40)
6965 ADD_INT(d, DB_VERB_DEADLOCK);
6966#if (DBVER >= 46)
6967 ADD_INT(d, DB_VERB_FILEOPS);
6968 ADD_INT(d, DB_VERB_FILEOPS_ALL);
6969#endif
6970 ADD_INT(d, DB_VERB_RECOVERY);
6971#if (DBVER >= 44)
6972 ADD_INT(d, DB_VERB_REGISTER);
6973#endif
6974 ADD_INT(d, DB_VERB_REPLICATION);
6975 ADD_INT(d, DB_VERB_WAITSFOR);
6976#endif
6977
6978#if (DBVER >= 45)
6979 ADD_INT(d, DB_EVENT_PANIC);
6980 ADD_INT(d, DB_EVENT_REP_CLIENT);
6981#if (DBVER >= 46)
6982 ADD_INT(d, DB_EVENT_REP_ELECTED);
6983#endif
6984 ADD_INT(d, DB_EVENT_REP_MASTER);
6985 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
6986#if (DBVER >= 46)
6987 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
6988#endif
6989 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
6990 ADD_INT(d, DB_EVENT_WRITE_FAILED);
6991#endif
6992
6993#if (DBVER >= 40)
6994 ADD_INT(d, DB_REP_MASTER);
6995 ADD_INT(d, DB_REP_CLIENT);
6996#if (DBVER >= 45)
6997 ADD_INT(d, DB_REP_ELECTION);
6998
6999 ADD_INT(d, DB_REP_ACK_TIMEOUT);
7000 ADD_INT(d, DB_REP_CONNECTION_RETRY);
7001 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
7002 ADD_INT(d, DB_REP_ELECTION_RETRY);
7003#endif
7004#if (DBVER >= 46)
7005 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
7006 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
7007#endif
7008#endif
7009
7010#if (DBVER >= 45)
7011 ADD_INT(d, DB_REPMGR_PEER);
7012 ADD_INT(d, DB_REPMGR_ACKS_ALL);
7013 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
7014 ADD_INT(d, DB_REPMGR_ACKS_NONE);
7015 ADD_INT(d, DB_REPMGR_ACKS_ONE);
7016 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
7017 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
7018 ADD_INT(d, DB_REPMGR_CONNECTED);
7019 ADD_INT(d, DB_REPMGR_DISCONNECTED);
7020 ADD_INT(d, DB_STAT_CLEAR);
7021 ADD_INT(d, DB_STAT_ALL);
7022#endif
7023
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007024#if (DBVER >= 43)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007025 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00007026 ADD_INT(d, DB_SEQ_DEC);
7027 ADD_INT(d, DB_SEQ_INC);
7028 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007029#endif
7030
Jesus Ceaca3939c2008-05-22 15:27:38 +00007031#if (DBVER >= 43) && (DBVER < 47)
7032 ADD_INT(d, DB_LOG_INMEMORY);
7033 ADD_INT(d, DB_DSYNC_LOG);
7034#endif
7035
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007036#if (DBVER >= 41)
7037 ADD_INT(d, DB_ENCRYPT_AES);
7038 ADD_INT(d, DB_AUTO_COMMIT);
7039#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00007040 /* allow Berkeley DB 4.1 aware apps to run on older versions */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007041 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
7042#endif
7043
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007044 ADD_INT(d, EINVAL);
7045 ADD_INT(d, EACCES);
7046 ADD_INT(d, ENOSPC);
7047 ADD_INT(d, ENOMEM);
7048 ADD_INT(d, EAGAIN);
7049 ADD_INT(d, EBUSY);
7050 ADD_INT(d, EEXIST);
7051 ADD_INT(d, ENOENT);
7052 ADD_INT(d, EPERM);
7053
Barry Warsaw1baa9822003-03-31 19:51:29 +00007054#if (DBVER >= 40)
7055 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
7056 ADD_INT(d, DB_SET_TXN_TIMEOUT);
7057#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007058
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007059 /* The exception name must be correct for pickled exception *
7060 * objects to unpickle properly. */
7061#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
7062#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
7063#else
7064#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
7065#endif
7066
7067 /* All the rest of the exceptions derive only from DBError */
7068#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
7069 PyDict_SetItemString(d, #name, name)
7070
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007071 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007072 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
7073 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007074
Gregory P. Smithe9477062005-06-04 06:46:59 +00007075 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
7076 * from both DBError and KeyError, since the API only supports
7077 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007078 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00007079 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
7080 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007081 Py_file_input, d, d);
7082 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00007083 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007084 PyDict_DelItemString(d, "KeyError");
7085
7086
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007087#if !INCOMPLETE_IS_WARNING
7088 MAKE_EX(DBIncompleteError);
7089#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00007090 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007091 MAKE_EX(DBKeyEmptyError);
7092 MAKE_EX(DBKeyExistError);
7093 MAKE_EX(DBLockDeadlockError);
7094 MAKE_EX(DBLockNotGrantedError);
7095 MAKE_EX(DBOldVersionError);
7096 MAKE_EX(DBRunRecoveryError);
7097 MAKE_EX(DBVerifyBadError);
7098 MAKE_EX(DBNoServerError);
7099 MAKE_EX(DBNoServerHomeError);
7100 MAKE_EX(DBNoServerIDError);
7101#if (DBVER >= 33)
7102 MAKE_EX(DBPageNotFoundError);
7103 MAKE_EX(DBSecondaryBadError);
7104#endif
7105
7106 MAKE_EX(DBInvalidArgError);
7107 MAKE_EX(DBAccessError);
7108 MAKE_EX(DBNoSpaceError);
7109 MAKE_EX(DBNoMemoryError);
7110 MAKE_EX(DBAgainError);
7111 MAKE_EX(DBBusyError);
7112 MAKE_EX(DBFileExistsError);
7113 MAKE_EX(DBNoSuchFileError);
7114 MAKE_EX(DBPermissionsError);
7115
Jesus Ceaef9764f2008-05-13 18:45:46 +00007116#if (DBVER >= 42)
7117 MAKE_EX(DBRepHandleDeadError);
7118#endif
7119
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007120#undef MAKE_EX
7121
Gregory P. Smith39250532007-10-09 06:02:21 +00007122 /* Initiliase the C API structure and add it to the module */
7123 bsddb_api.db_type = &DB_Type;
7124 bsddb_api.dbcursor_type = &DBCursor_Type;
7125 bsddb_api.dbenv_type = &DBEnv_Type;
7126 bsddb_api.dbtxn_type = &DBTxn_Type;
7127 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007128#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00007129 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007130#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00007131 bsddb_api.makeDBError = makeDBError;
7132
7133 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7134 PyDict_SetItemString(d, "api", py_api);
7135 Py_DECREF(py_api);
7136
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007137 /* Check for errors */
7138 if (PyErr_Occurred()) {
7139 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007140 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007141 }
7142}
Gregory P. Smith41631e82003-09-21 00:08:14 +00007143
7144/* allow this module to be named _pybsddb so that it can be installed
7145 * and imported on top of python >= 2.3 that includes its own older
7146 * copy of the library named _bsddb without importing the old version. */
7147DL_EXPORT(void) init_pybsddb(void)
7148{
7149 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
7150 init_bsddb();
7151}