blob: 04c7155ea1cd0f2c0b342ef1bf105ce9157c8f57 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Jesus Ceaef9764f2008-05-13 18:45:46 +000039 * to compile with Berkeley DB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
Gregory P. Smithf8057852007-09-09 20:25:00 +000042 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * Berkeley DB 2.7.x.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000045 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
Jesus Ceaef9764f2008-05-13 18:45:46 +000051 * Gregory P. Smith <greg@krypto.org> was once again the maintainer.
52 *
53 * Since January 2008, new maintainer is Jesus Cea <jcea@argo.es>.
54 * Jesus Cea licenses this code to PSF under a Contributor Agreement.
Barry Warsaw9a0d7792002-12-30 20:53:52 +000055 *
56 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000057 * Things can change faster than the header of this file is updated. This
58 * file is shared with the PyBSDDB project at SourceForge:
59 *
60 * http://pybsddb.sf.net
61 *
62 * This file should remain backward compatible with Python 2.1, but see PEP
63 * 291 for the most current backward compatibility requirements:
64 *
65 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000066 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000067 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000068 *
69 * DB (Database)
70 * DBCursor (Database Cursor)
71 * DBEnv (database environment)
72 * DBTxn (An explicit database transaction)
73 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000074 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000075 *
76 */
77
78/* --------------------------------------------------------------------- */
79
80/*
81 * Portions of this module, associated unit tests and build scripts are the
82 * result of a contract with The Written Word (http://thewrittenword.com/)
83 * Many thanks go out to them for causing me to raise the bar on quality and
84 * functionality, resulting in a better bsddb3 package for all of us to use.
85 *
86 * --Robin
87 */
88
89/* --------------------------------------------------------------------- */
90
Gregory P. Smitha703a212003-11-03 01:04:41 +000091#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000092#include <Python.h>
Gregory P. Smith39250532007-10-09 06:02:21 +000093
94#define COMPILING_BSDDB_C
95#include "bsddb.h"
96#undef COMPILING_BSDDB_C
97
98static char *rcs_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000099
100/* --------------------------------------------------------------------- */
101/* Various macro definitions */
102
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000103#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000104typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#endif
106
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000107#ifdef WITH_THREAD
108
109/* These are for when calling Python --> C */
110#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
111#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
112
Mark Hammonda69d4092003-04-22 23:13:27 +0000113/* For 2.3, use the PyGILState_ calls */
114#if (PY_VERSION_HEX >= 0x02030000)
115#define MYDB_USE_GILSTATE
116#endif
117
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000118/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000119#if defined(MYDB_USE_GILSTATE)
120#define MYDB_BEGIN_BLOCK_THREADS \
121 PyGILState_STATE __savestate = PyGILState_Ensure();
122#define MYDB_END_BLOCK_THREADS \
123 PyGILState_Release(__savestate);
124#else /* MYDB_USE_GILSTATE */
125/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000126static PyInterpreterState* _db_interpreterState = NULL;
127#define MYDB_BEGIN_BLOCK_THREADS { \
128 PyThreadState* prevState; \
129 PyThreadState* newState; \
130 PyEval_AcquireLock(); \
131 newState = PyThreadState_New(_db_interpreterState); \
132 prevState = PyThreadState_Swap(newState);
133
134#define MYDB_END_BLOCK_THREADS \
135 newState = PyThreadState_Swap(prevState); \
136 PyThreadState_Clear(newState); \
137 PyEval_ReleaseLock(); \
138 PyThreadState_Delete(newState); \
139 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000140#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000141
142#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000143/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000144#define MYDB_BEGIN_ALLOW_THREADS
145#define MYDB_END_ALLOW_THREADS
146#define MYDB_BEGIN_BLOCK_THREADS
147#define MYDB_END_BLOCK_THREADS
148
149#endif
150
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000151/* Should DB_INCOMPLETE be turned into a warning or an exception? */
152#define INCOMPLETE_IS_WARNING 1
153
154/* --------------------------------------------------------------------- */
155/* Exceptions */
156
157static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000158static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000159static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000160static PyObject* DBKeyExistError; /* DB_KEYEXIST */
161static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
162static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
163static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
164static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
165static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
166static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
167static PyObject* DBNoServerError; /* DB_NOSERVER */
168static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
169static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
170#if (DBVER >= 33)
171static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
172static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
173#endif
174
175#if !INCOMPLETE_IS_WARNING
176static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
177#endif
178
179static PyObject* DBInvalidArgError; /* EINVAL */
180static PyObject* DBAccessError; /* EACCES */
181static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000182static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000183static PyObject* DBAgainError; /* EAGAIN */
184static PyObject* DBBusyError; /* EBUSY */
185static PyObject* DBFileExistsError; /* EEXIST */
186static PyObject* DBNoSuchFileError; /* ENOENT */
187static PyObject* DBPermissionsError; /* EPERM */
188
Jesus Ceaef9764f2008-05-13 18:45:46 +0000189#if (DBVER >= 42)
190static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
191#endif
192
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000193#if (DBVER < 43)
194#define DB_BUFFER_SMALL ENOMEM
195#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000196
197
198/* --------------------------------------------------------------------- */
199/* Structure definitions */
200
Gregory P. Smith39250532007-10-09 06:02:21 +0000201#if PYTHON_API_VERSION < 1010
202#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205
Gregory P. Smith39250532007-10-09 06:02:21 +0000206/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000207#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000208#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000209
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000210
211staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000212#if (DBVER >= 43)
213staticforward PyTypeObject DBSequence_Type;
214#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000215
Martin v. Löwis83c92012008-04-24 13:17:24 +0000216#ifndef Py_TYPE
Gregory P. Smithfc006692007-11-05 09:06:28 +0000217/* for compatibility with Python 2.5 and earlier */
Christian Heimese93237d2007-12-19 02:37:44 +0000218#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
Gregory P. Smithfc006692007-11-05 09:06:28 +0000219#endif
220
Christian Heimese93237d2007-12-19 02:37:44 +0000221#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
222#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
223#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
224#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
225#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000226#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +0000227#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000228#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000229
Jesus Ceaef9764f2008-05-13 18:45:46 +0000230#if (DBVER < 46)
231 #define _DBC_close(dbc) dbc->c_close(dbc)
232 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
233 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
234 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
235 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
236 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
237 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
238#else
239 #define _DBC_close(dbc) dbc->close(dbc)
240 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
241 #define _DBC_del(dbc,a) dbc->del(dbc,a)
242 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
243 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
244 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
245 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
246#endif
247
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248
249/* --------------------------------------------------------------------- */
250/* Utility macros and functions */
251
Jesus Ceaef9764f2008-05-13 18:45:46 +0000252#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
253 { \
254 object->sibling_next=backlink; \
255 object->sibling_prev_p=&(backlink); \
256 backlink=object; \
257 if (object->sibling_next) { \
258 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
259 } \
260 }
261
262#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
263 { \
264 if (object->sibling_next) { \
265 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
266 } \
267 *(object->sibling_prev_p)=object->sibling_next; \
268 }
269
270#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
271 { \
272 if (object->sibling_next) { \
273 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
274 } \
275 if (object->sibling_prev_p) { \
276 *(object->sibling_prev_p)=object->sibling_next; \
277 } \
278 }
279
280#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
281 { \
282 object->sibling_next_txn=backlink; \
283 object->sibling_prev_p_txn=&(backlink); \
284 backlink=object; \
285 if (object->sibling_next_txn) { \
286 object->sibling_next_txn->sibling_prev_p_txn= \
287 &(object->sibling_next_txn); \
288 } \
289 }
290
291#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
292 { \
293 if (object->sibling_next_txn) { \
294 object->sibling_next_txn->sibling_prev_p_txn= \
295 object->sibling_prev_p_txn; \
296 } \
297 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
298 }
299
300
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000301#define RETURN_IF_ERR() \
302 if (makeDBError(err)) { \
303 return NULL; \
304 }
305
306#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
307
Gregory P. Smithe2767172003-11-02 08:06:29 +0000308#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
309 if ((nonNull) == NULL) { \
310 PyObject *errTuple = NULL; \
311 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
312 PyErr_SetObject((pyErrObj), errTuple); \
313 Py_DECREF(errTuple); \
314 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000315 }
316
Gregory P. Smithe2767172003-11-02 08:06:29 +0000317#define CHECK_DB_NOT_CLOSED(dbobj) \
318 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
319
320#define CHECK_ENV_NOT_CLOSED(env) \
321 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000322
323#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000324 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000325
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000326#if (DBVER >= 43)
327#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
328 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
329#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330
331#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
332 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
333
334#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
335
336#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000337 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000338
339
340static int makeDBError(int err);
341
342
343/* Return the access method type of the DBObject */
344static int _DB_get_type(DBObject* self)
345{
346#if (DBVER >= 33)
347 DBTYPE type;
348 int err;
349 err = self->db->get_type(self->db, &type);
350 if (makeDBError(err)) {
351 return -1;
352 }
353 return type;
354#else
355 return self->db->get_type(self->db);
356#endif
357}
358
359
360/* Create a DBT structure (containing key and data values) from Python
361 strings. Returns 1 on success, 0 on an error. */
362static int make_dbt(PyObject* obj, DBT* dbt)
363{
364 CLEAR_DBT(*dbt);
365 if (obj == Py_None) {
366 /* no need to do anything, the structure has already been zeroed */
367 }
368 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
369 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000370 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000371 return 0;
372 }
373 return 1;
374}
375
376
377/* Recno and Queue DBs can have integer keys. This function figures out
378 what's been given, verifies that it's allowed, and then makes the DBT.
379
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000380 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000381static int
382make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000383{
384 db_recno_t recno;
385 int type;
386
387 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000388 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000389 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000390 if (type == -1)
391 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000392 if (type == DB_RECNO || type == DB_QUEUE) {
393 PyErr_SetString(
394 PyExc_TypeError,
395 "None keys not allowed for Recno and Queue DB's");
396 return 0;
397 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398 /* no need to do anything, the structure has already been zeroed */
399 }
400
401 else if (PyString_Check(keyobj)) {
402 /* verify access method type */
403 type = _DB_get_type(self);
404 if (type == -1)
405 return 0;
406 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000407 PyErr_SetString(
408 PyExc_TypeError,
409 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000410 return 0;
411 }
412
Gregory P. Smith10bed542007-10-09 06:50:43 +0000413 /*
414 * NOTE(gps): I don't like doing a data copy here, it seems
415 * wasteful. But without a clean way to tell FREE_DBT if it
416 * should free key->data or not we have to. Other places in
417 * the code check for DB_THREAD and forceably set DBT_MALLOC
418 * when we otherwise would leave flags 0 to indicate that.
419 */
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000420 key->data = malloc(PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000421 if (key->data == NULL) {
422 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
423 return 0;
424 }
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000425 memcpy(key->data, PyString_AS_STRING(keyobj),
426 PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000427 key->flags = DB_DBT_REALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000428 key->size = PyString_GET_SIZE(keyobj);
429 }
430
431 else if (PyInt_Check(keyobj)) {
432 /* verify access method type */
433 type = _DB_get_type(self);
434 if (type == -1)
435 return 0;
436 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000437 /* if BTREE then an Integer key is allowed with the
438 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000439 *pflags |= DB_SET_RECNO;
440 }
441 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000442 PyErr_SetString(
443 PyExc_TypeError,
444 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000445 return 0;
446 }
447
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000448 /* Make a key out of the requested recno, use allocated space so DB
449 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000450 recno = PyInt_AS_LONG(keyobj);
451 key->data = malloc(sizeof(db_recno_t));
452 if (key->data == NULL) {
453 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
454 return 0;
455 }
456 key->ulen = key->size = sizeof(db_recno_t);
457 memcpy(key->data, &recno, sizeof(db_recno_t));
458 key->flags = DB_DBT_REALLOC;
459 }
460 else {
461 PyErr_Format(PyExc_TypeError,
462 "String or Integer object expected for key, %s found",
Christian Heimese93237d2007-12-19 02:37:44 +0000463 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000464 return 0;
465 }
466
467 return 1;
468}
469
470
471/* Add partial record access to an existing DBT data struct.
472 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
473 and the data storage/retrieval will be done using dlen and doff. */
474static int add_partial_dbt(DBT* d, int dlen, int doff) {
475 /* if neither were set we do nothing (-1 is the default value) */
476 if ((dlen == -1) && (doff == -1)) {
477 return 1;
478 }
479
480 if ((dlen < 0) || (doff < 0)) {
481 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
482 return 0;
483 }
484
485 d->flags = d->flags | DB_DBT_PARTIAL;
486 d->dlen = (unsigned int) dlen;
487 d->doff = (unsigned int) doff;
488 return 1;
489}
490
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000491/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
492/* TODO: make this use the native libc strlcpy() when available (BSD) */
493unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
494{
495 unsigned int srclen, copylen;
496
497 srclen = strlen(src);
498 if (n <= 0)
499 return srclen;
500 copylen = (srclen > n-1) ? n-1 : srclen;
501 /* populate dest[0] thru dest[copylen-1] */
502 memcpy(dest, src, copylen);
503 /* guarantee null termination */
504 dest[copylen] = 0;
505
506 return srclen;
507}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000508
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000509/* Callback used to save away more information about errors from the DB
510 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000511static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000512#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000513static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000514#else
515static void _db_errorCallback(const DB_ENV *db_env,
516 const char* prefix, const char* msg)
517#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000518{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000519 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000520}
521
522
Jesus Ceaef9764f2008-05-13 18:45:46 +0000523/*
524** We need these functions because some results
525** are undefined if pointer is NULL. Some other
526** give None instead of "".
527**
528** This functions are static and will be
529** -I hope- inlined.
530*/
531static const char *DummyString = "This string is a simple placeholder";
532static PyObject *Build_PyString(const char *p,int s)
533{
534 if (!p) {
535 p=DummyString;
536 assert(s==0);
537 }
538 return PyString_FromStringAndSize(p,s);
539}
540
541static PyObject *BuildValue_S(const void *p,int s)
542{
543 if (!p) {
544 p=DummyString;
545 assert(s==0);
546 }
547 return Py_BuildValue("s#",p,s);
548}
549
550static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
551{
552 if (!p1) {
553 p1=DummyString;
554 assert(s1==0);
555 }
556 if (!p2) {
557 p2=DummyString;
558 assert(s2==0);
559 }
560 return Py_BuildValue("s#s#",p1,s1,p2,s2);
561}
562
563static PyObject *BuildValue_IS(int i,const void *p,int s)
564{
565 if (!p) {
566 p=DummyString;
567 assert(s==0);
568 }
569 return Py_BuildValue("is#",i,p,s);
570}
571
572static PyObject *BuildValue_LS(long i,const void *p,int s)
573{
574 if (!p) {
575 p=DummyString;
576 assert(s==0);
577 }
578 return Py_BuildValue("ls#",i,p,s);
579}
580
581
582
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000583/* make a nice exception object to raise for errors. */
584static int makeDBError(int err)
585{
586 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000587 PyObject *errObj = NULL;
588 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000589 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000590 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000591
592 switch (err) {
593 case 0: /* successful, no error */ break;
594
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000595#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000596 case DB_INCOMPLETE:
597#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000598 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
599 /* Ensure that bytes_left never goes negative */
600 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
601 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
602 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000603 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000604 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000605 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000606 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000607 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000608
609#else /* do an exception instead */
610 errObj = DBIncompleteError;
611#endif
612 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000613#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000614
615 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
616 case DB_KEYEXIST: errObj = DBKeyExistError; break;
617 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
618 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
619 case DB_NOTFOUND: errObj = DBNotFoundError; break;
620 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
621 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
622 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
623 case DB_NOSERVER: errObj = DBNoServerError; break;
624 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
625 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
626#if (DBVER >= 33)
627 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
628 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
629#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000630 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000631
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000632#if (DBVER >= 43)
633 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
634 case ENOMEM: errObj = PyExc_MemoryError; break;
635#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000636 case EINVAL: errObj = DBInvalidArgError; break;
637 case EACCES: errObj = DBAccessError; break;
638 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000639 case EAGAIN: errObj = DBAgainError; break;
640 case EBUSY : errObj = DBBusyError; break;
641 case EEXIST: errObj = DBFileExistsError; break;
642 case ENOENT: errObj = DBNoSuchFileError; break;
643 case EPERM : errObj = DBPermissionsError; break;
644
Jesus Ceaef9764f2008-05-13 18:45:46 +0000645#if (DBVER >= 42)
646 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
647#endif
648
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000649 default: errObj = DBError; break;
650 }
651
652 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000653 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
654 /* Ensure that bytes_left never goes negative */
655 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
656 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
657 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000658 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000659 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000660 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000661 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000662
663 errTuple = Py_BuildValue("(is)", err, errTxt);
664 PyErr_SetObject(errObj, errTuple);
665 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000666 }
667
668 return ((errObj != NULL) || exceptionRaised);
669}
670
671
672
673/* set a type exception */
674static void makeTypeError(char* expected, PyObject* found)
675{
676 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimese93237d2007-12-19 02:37:44 +0000677 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000678}
679
680
681/* verify that an obj is either None or a DBTxn, and set the txn pointer */
682static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
683{
684 if (txnobj == Py_None || txnobj == NULL) {
685 *txn = NULL;
686 return 1;
687 }
688 if (DBTxnObject_Check(txnobj)) {
689 *txn = ((DBTxnObject*)txnobj)->txn;
690 return 1;
691 }
692 else
693 makeTypeError("DBTxn", txnobj);
694 return 0;
695}
696
697
698/* Delete a key from a database
699 Returns 0 on success, -1 on an error. */
700static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
701{
702 int err;
703
704 MYDB_BEGIN_ALLOW_THREADS;
705 err = self->db->del(self->db, txn, key, 0);
706 MYDB_END_ALLOW_THREADS;
707 if (makeDBError(err)) {
708 return -1;
709 }
710 self->haveStat = 0;
711 return 0;
712}
713
714
715/* Store a key into a database
716 Returns 0 on success, -1 on an error. */
717static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
718{
719 int err;
720
721 MYDB_BEGIN_ALLOW_THREADS;
722 err = self->db->put(self->db, txn, key, data, flags);
723 MYDB_END_ALLOW_THREADS;
724 if (makeDBError(err)) {
725 return -1;
726 }
727 self->haveStat = 0;
728 return 0;
729}
730
731/* Get a key/data pair from a cursor */
732static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
733 PyObject *args, PyObject *kwargs, char *format)
734{
735 int err;
736 PyObject* retval = NULL;
737 DBT key, data;
738 int dlen = -1;
739 int doff = -1;
740 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000741 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000742
743 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
744 &flags, &dlen, &doff))
745 return NULL;
746
747 CHECK_CURSOR_NOT_CLOSED(self);
748
749 flags |= extra_flags;
750 CLEAR_DBT(key);
751 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000752 if (!add_partial_dbt(&data, dlen, doff))
753 return NULL;
754
755 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000756 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000757 MYDB_END_ALLOW_THREADS;
758
Gregory P. Smithe9477062005-06-04 06:46:59 +0000759 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
760 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000761 Py_INCREF(Py_None);
762 retval = Py_None;
763 }
764 else if (makeDBError(err)) {
765 retval = NULL;
766 }
767 else { /* otherwise, success! */
768
769 /* if Recno or Queue, return the key as an Int */
770 switch (_DB_get_type(self->mydb)) {
771 case -1:
772 retval = NULL;
773 break;
774
775 case DB_RECNO:
776 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000777 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000778 break;
779 case DB_HASH:
780 case DB_BTREE:
781 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000782 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000783 break;
784 }
785 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000786 return retval;
787}
788
789
790/* add an integer to a dictionary using the given name as a key */
791static void _addIntToDict(PyObject* dict, char *name, int value)
792{
793 PyObject* v = PyInt_FromLong((long) value);
794 if (!v || PyDict_SetItemString(dict, name, v))
795 PyErr_Clear();
796
797 Py_XDECREF(v);
798}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000799
800/* The same, when the value is a time_t */
801static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
802{
803 PyObject* v;
804 /* if the value fits in regular int, use that. */
Jesus Ceaef9764f2008-05-13 18:45:46 +0000805#ifdef PY_LONG_LONG
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000806 if (sizeof(time_t) > sizeof(long))
807 v = PyLong_FromLongLong((PY_LONG_LONG) value);
808 else
809#endif
810 v = PyInt_FromLong((long) value);
811 if (!v || PyDict_SetItemString(dict, name, v))
812 PyErr_Clear();
813
814 Py_XDECREF(v);
815}
816
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000817#if (DBVER >= 43)
818/* add an db_seq_t to a dictionary using the given name as a key */
819static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
820{
821 PyObject* v = PyLong_FromLongLong(value);
822 if (!v || PyDict_SetItemString(dict, name, v))
823 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000824
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000825 Py_XDECREF(v);
826}
827#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828
Jesus Ceaef9764f2008-05-13 18:45:46 +0000829#if (DBVER >= 40)
830static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
831{
832 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
833 if (!v || PyDict_SetItemString(dict, name, v))
834 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835
Jesus Ceaef9764f2008-05-13 18:45:46 +0000836 Py_XDECREF(v);
837}
838#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000839
840/* --------------------------------------------------------------------- */
841/* Allocators and deallocators */
842
843static DBObject*
844newDBObject(DBEnvObject* arg, int flags)
845{
846 DBObject* self;
847 DB_ENV* db_env = NULL;
848 int err;
849
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000851 if (self == NULL)
852 return NULL;
853
854 self->haveStat = 0;
855 self->flags = 0;
856 self->setflags = 0;
857 self->myenvobj = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000858 self->children_cursors = NULL;
859#if (DBVER >=43)
860 self->children_sequences = NULL;
861#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000862#if (DBVER >= 33)
863 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000864 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000865 self->primaryDBType = 0;
866#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000867 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000868
869 /* keep a reference to our python DBEnv object */
870 if (arg) {
871 Py_INCREF(arg);
872 self->myenvobj = arg;
873 db_env = arg->db_env;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000874 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
875 } else {
876 self->sibling_prev_p=NULL;
877 self->sibling_next=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000878 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000879 self->txn=NULL;
880 self->sibling_prev_p_txn=NULL;
881 self->sibling_next_txn=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000882
883 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000884 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000886 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
887 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000888
889 MYDB_BEGIN_ALLOW_THREADS;
890 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000891 if (self->db != NULL) {
892 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000893#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000894 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000895#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000896 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000897 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000898 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
899 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000900 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000901 if (makeDBError(err)) {
902 if (self->myenvobj) {
903 Py_DECREF(self->myenvobj);
904 self->myenvobj = NULL;
905 }
Thomas Woutersb3153832006-03-08 01:47:19 +0000906 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000907 self = NULL;
908 }
909 return self;
910}
911
912
Jesus Ceaef9764f2008-05-13 18:45:46 +0000913/* Forward declaration */
914static PyObject *DB_close_internal(DBObject* self, int flags);
915
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916static void
917DB_dealloc(DBObject* self)
918{
Jesus Ceaef9764f2008-05-13 18:45:46 +0000919 PyObject *dummy;
920
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000921 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +0000922 dummy=DB_close_internal(self,0);
923 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000924 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000925 if (self->in_weakreflist != NULL) {
926 PyObject_ClearWeakRefs((PyObject *) self);
927 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000928 if (self->myenvobj) {
929 Py_DECREF(self->myenvobj);
930 self->myenvobj = NULL;
931 }
932#if (DBVER >= 33)
933 if (self->associateCallback != NULL) {
934 Py_DECREF(self->associateCallback);
935 self->associateCallback = NULL;
936 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000937 if (self->btCompareCallback != NULL) {
938 Py_DECREF(self->btCompareCallback);
939 self->btCompareCallback = NULL;
940 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000941#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000943}
944
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000945static DBCursorObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +0000946newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000947{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000948 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000949 if (self == NULL)
950 return NULL;
951
952 self->dbc = dbc;
953 self->mydb = db;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000954
955 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
956 if (txn && ((PyObject *)txn!=Py_None)) {
957 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
958 self->txn=txn;
959 } else {
960 self->txn=NULL;
961 }
962
Gregory P. Smitha703a212003-11-03 01:04:41 +0000963 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000964 Py_INCREF(self->mydb);
965 return self;
966}
967
968
Jesus Ceaef9764f2008-05-13 18:45:46 +0000969/* Forward declaration */
970static PyObject *DBC_close_internal(DBCursorObject* self);
971
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000972static void
973DBCursor_dealloc(DBCursorObject* self)
974{
Jesus Ceaef9764f2008-05-13 18:45:46 +0000975 PyObject *dummy;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000976
Jesus Ceaef9764f2008-05-13 18:45:46 +0000977 if (self->dbc != NULL) {
978 dummy=DBC_close_internal(self);
979 Py_XDECREF(dummy);
980 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000981 if (self->in_weakreflist != NULL) {
982 PyObject_ClearWeakRefs((PyObject *) self);
983 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000984 Py_DECREF(self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000985 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000986}
987
988
989static DBEnvObject*
990newDBEnvObject(int flags)
991{
992 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000993 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000994 if (self == NULL)
995 return NULL;
996
997 self->closed = 1;
998 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000999 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1000 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001001 self->children_dbs = NULL;
1002 self->children_txns = NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001003 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001004
Jesus Ceaef9764f2008-05-13 18:45:46 +00001005#if (DBVER >= 40)
1006 self->event_notifyCallback = NULL;
1007#endif
1008
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001009 MYDB_BEGIN_ALLOW_THREADS;
1010 err = db_env_create(&self->db_env, flags);
1011 MYDB_END_ALLOW_THREADS;
1012 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001013 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001014 self = NULL;
1015 }
1016 else {
1017 self->db_env->set_errcall(self->db_env, _db_errorCallback);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001018 self->db_env->app_private=self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001019 }
1020 return self;
1021}
1022
Jesus Ceaef9764f2008-05-13 18:45:46 +00001023/* Forward declaration */
1024static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001025
1026static void
1027DBEnv_dealloc(DBEnvObject* self)
1028{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001029 PyObject *dummy;
1030
1031 if (self->db_env && !self->closed) {
1032 dummy=DBEnv_close_internal(self,0);
1033 Py_XDECREF(dummy);
1034 }
1035
1036#if (DBVER >= 40)
1037 Py_XDECREF(self->event_notifyCallback);
1038 self->event_notifyCallback = NULL;
1039#endif
1040
Gregory P. Smith31c50652004-06-28 01:20:40 +00001041 if (self->in_weakreflist != NULL) {
1042 PyObject_ClearWeakRefs((PyObject *) self);
1043 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001044
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001045 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001046}
1047
1048
1049static DBTxnObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001050newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001051{
1052 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001053 DB_TXN *parent_txn=NULL;
1054
Neal Norwitzb4a55812004-07-09 23:30:57 +00001055 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056 if (self == NULL)
1057 return NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001058
Gregory P. Smith31c50652004-06-28 01:20:40 +00001059 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001060
Jesus Ceaef9764f2008-05-13 18:45:46 +00001061 if (parent && ((PyObject *)parent!=Py_None)) {
1062 parent_txn=parent->txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001063 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001064
1065 if (txn) {
1066 self->txn=txn;
1067 } else {
1068 MYDB_BEGIN_ALLOW_THREADS;
1069#if (DBVER >= 40)
1070 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
1071#else
1072 err = txn_begin(myenv->db_env, parent->txn, &(self_txn), flags);
1073#endif
1074 MYDB_END_ALLOW_THREADS;
1075
1076 if (makeDBError(err)) {
1077 PyObject_Del(self);
1078 return NULL;
1079 }
1080 }
1081
1082 if (parent_txn) { /* Can't use 'parent' because could be 'parent==Py_None' */
1083 self->parent_txn=parent;
1084 Py_INCREF(parent);
1085 self->env = NULL;
1086 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns,self);
1087 } else {
1088 self->parent_txn=NULL;
1089 Py_INCREF(myenv);
1090 self->env = myenv;
1091 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns,self);
1092 }
1093
1094 self->children_txns=NULL;
1095 self->children_dbs=NULL;
1096 self->children_cursors=NULL;
1097 self->children_sequences=NULL;
1098 self->flag_prepare=0;
1099
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001100 return self;
1101}
1102
Jesus Ceaef9764f2008-05-13 18:45:46 +00001103/* Forward declaration */
1104static PyObject *
1105DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001106
1107static void
1108DBTxn_dealloc(DBTxnObject* self)
1109{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001110 PyObject *dummy;
1111
1112 if (self->txn) {
1113 int flag_prepare = self->flag_prepare;
1114 dummy=DBTxn_abort_discard_internal(self,0);
1115 Py_XDECREF(dummy);
1116 if (!flag_prepare) {
1117 PyErr_Warn(PyExc_RuntimeWarning,
1118 "DBTxn aborted in destructor. No prior commit() or abort().");
1119 }
1120 }
1121
Gregory P. Smith31c50652004-06-28 01:20:40 +00001122 if (self->in_weakreflist != NULL) {
1123 PyObject_ClearWeakRefs((PyObject *) self);
1124 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001125
Jesus Ceaef9764f2008-05-13 18:45:46 +00001126 if (self->env) {
1127 Py_DECREF(self->env);
1128 } else {
1129 Py_DECREF(self->parent_txn);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001130 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001131 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001132}
1133
1134
1135static DBLockObject*
1136newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1137 db_lockmode_t lock_mode, int flags)
1138{
1139 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001140 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001141 if (self == NULL)
1142 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001143 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001144
1145 MYDB_BEGIN_ALLOW_THREADS;
1146#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001147 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1148 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001149#else
1150 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1151#endif
1152 MYDB_END_ALLOW_THREADS;
1153 if (makeDBError(err)) {
Thomas Woutersb3153832006-03-08 01:47:19 +00001154 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001155 self = NULL;
1156 }
1157
1158 return self;
1159}
1160
1161
1162static void
1163DBLock_dealloc(DBLockObject* self)
1164{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001165 if (self->in_weakreflist != NULL) {
1166 PyObject_ClearWeakRefs((PyObject *) self);
1167 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001168 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001169
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001170 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001171}
1172
1173
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001174#if (DBVER >= 43)
1175static DBSequenceObject*
1176newDBSequenceObject(DBObject* mydb, int flags)
1177{
1178 int err;
1179 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1180 if (self == NULL)
1181 return NULL;
1182 Py_INCREF(mydb);
1183 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001184
Jesus Ceaef9764f2008-05-13 18:45:46 +00001185 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
1186 self->txn=NULL;
1187
1188 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001189
1190 MYDB_BEGIN_ALLOW_THREADS;
1191 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1192 MYDB_END_ALLOW_THREADS;
1193 if (makeDBError(err)) {
1194 Py_DECREF(self->mydb);
1195 PyObject_Del(self);
1196 self = NULL;
1197 }
1198
1199 return self;
1200}
1201
Jesus Ceaef9764f2008-05-13 18:45:46 +00001202/* Forward declaration */
1203static PyObject
1204*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001205
1206static void
1207DBSequence_dealloc(DBSequenceObject* self)
1208{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001209 PyObject *dummy;
1210
1211 if (self->sequence != NULL) {
1212 dummy=DBSequence_close_internal(self,0,0);
1213 Py_XDECREF(dummy);
1214 }
1215
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001216 if (self->in_weakreflist != NULL) {
1217 PyObject_ClearWeakRefs((PyObject *) self);
1218 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001219
1220 Py_DECREF(self->mydb);
1221 PyObject_Del(self);
1222}
1223#endif
1224
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001225/* --------------------------------------------------------------------- */
1226/* DB methods */
1227
1228static PyObject*
1229DB_append(DBObject* self, PyObject* args)
1230{
1231 PyObject* txnobj = NULL;
1232 PyObject* dataobj;
1233 db_recno_t recno;
1234 DBT key, data;
1235 DB_TXN *txn = NULL;
1236
Georg Brandl96a8c392006-05-29 21:04:52 +00001237 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001238 return NULL;
1239
1240 CHECK_DB_NOT_CLOSED(self);
1241
1242 /* make a dummy key out of a recno */
1243 recno = 0;
1244 CLEAR_DBT(key);
1245 key.data = &recno;
1246 key.size = sizeof(recno);
1247 key.ulen = key.size;
1248 key.flags = DB_DBT_USERMEM;
1249
1250 if (!make_dbt(dataobj, &data)) return NULL;
1251 if (!checkTxnObj(txnobj, &txn)) return NULL;
1252
1253 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1254 return NULL;
1255
1256 return PyInt_FromLong(recno);
1257}
1258
1259
1260#if (DBVER >= 33)
1261
1262static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001263_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1264 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001265{
1266 int retval = DB_DONOTINDEX;
1267 DBObject* secondaryDB = (DBObject*)db->app_private;
1268 PyObject* callback = secondaryDB->associateCallback;
1269 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001270 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001271 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001272
1273
1274 if (callback != NULL) {
1275 MYDB_BEGIN_BLOCK_THREADS;
1276
Thomas Woutersb3153832006-03-08 01:47:19 +00001277 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceaef9764f2008-05-13 18:45:46 +00001278 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
Thomas Woutersb3153832006-03-08 01:47:19 +00001279 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001280 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001281 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001282 result = PyEval_CallObject(callback, args);
1283 }
1284 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001285 PyErr_Print();
1286 }
1287 else if (result == Py_None) {
1288 retval = DB_DONOTINDEX;
1289 }
1290 else if (PyInt_Check(result)) {
1291 retval = PyInt_AsLong(result);
1292 }
1293 else if (PyString_Check(result)) {
1294 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001295 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001296
1297 CLEAR_DBT(*secKey);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001298 PyString_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001299 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1300 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001301 if (secKey->data) {
1302 memcpy(secKey->data, data, size);
1303 secKey->size = size;
1304 retval = 0;
1305 }
1306 else {
1307 PyErr_SetString(PyExc_MemoryError,
1308 "malloc failed in _db_associateCallback");
1309 PyErr_Print();
1310 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001311 }
1312 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001313 PyErr_SetString(
1314 PyExc_TypeError,
1315 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001316 PyErr_Print();
1317 }
1318
Thomas Woutersb3153832006-03-08 01:47:19 +00001319 Py_XDECREF(args);
1320 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001321
1322 MYDB_END_BLOCK_THREADS;
1323 }
1324 return retval;
1325}
1326
1327
1328static PyObject*
1329DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1330{
1331 int err, flags=0;
1332 DBObject* secondaryDB;
1333 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001334#if (DBVER >= 41)
1335 PyObject *txnobj = NULL;
1336 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001337 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001338 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001339#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001340 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001341#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001342
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001343#if (DBVER >= 41)
1344 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1345 &secondaryDB, &callback, &flags,
1346 &txnobj)) {
1347#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001348 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001349 &secondaryDB, &callback, &flags)) {
1350#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001351 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001352 }
1353
1354#if (DBVER >= 41)
1355 if (!checkTxnObj(txnobj, &txn)) return NULL;
1356#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001357
1358 CHECK_DB_NOT_CLOSED(self);
1359 if (!DBObject_Check(secondaryDB)) {
1360 makeTypeError("DB", (PyObject*)secondaryDB);
1361 return NULL;
1362 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001363 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001364 if (callback == Py_None) {
1365 callback = NULL;
1366 }
1367 else if (!PyCallable_Check(callback)) {
1368 makeTypeError("Callable", callback);
1369 return NULL;
1370 }
1371
1372 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001373 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001374 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001375 secondaryDB->associateCallback = callback;
1376 secondaryDB->primaryDBType = _DB_get_type(self);
1377
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001378 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1379 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1380 * The global interepreter lock is not initialized until the first
1381 * thread is created using thread.start_new_thread() or fork() is
1382 * called. that would cause the ALLOW_THREADS here to segfault due
1383 * to a null pointer reference if no threads or child processes
1384 * have been created. This works around that and is a no-op if
1385 * threads have already been initialized.
1386 * (see pybsddb-users mailing list post on 2002-08-07)
1387 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001388#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001389 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001390#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001391 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001392#if (DBVER >= 41)
1393 err = self->db->associate(self->db,
1394 txn,
1395 secondaryDB->db,
1396 _db_associateCallback,
1397 flags);
1398#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001399 err = self->db->associate(self->db,
1400 secondaryDB->db,
1401 _db_associateCallback,
1402 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001403#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001404 MYDB_END_ALLOW_THREADS;
1405
1406 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001407 Py_XDECREF(secondaryDB->associateCallback);
1408 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001409 secondaryDB->primaryDBType = 0;
1410 }
1411
1412 RETURN_IF_ERR();
1413 RETURN_NONE();
1414}
1415
1416
1417#endif
1418
1419
1420static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001421DB_close_internal(DBObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001422{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001423 PyObject *dummy;
1424 int err;
1425
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001426 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001427 /* Can be NULL if db is not in an environment */
1428 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
1429 if (self->txn) {
1430 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1431 self->txn=NULL;
1432 }
1433
1434 while(self->children_cursors) {
1435 dummy=DBC_close_internal(self->children_cursors);
1436 Py_XDECREF(dummy);
1437 }
1438
1439#if (DBVER >= 43)
1440 while(self->children_sequences) {
1441 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1442 Py_XDECREF(dummy);
1443 }
1444#endif
1445
1446 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001447 err = self->db->close(self->db, flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001448 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001449 self->db = NULL;
1450 RETURN_IF_ERR();
1451 }
1452 RETURN_NONE();
1453}
1454
Jesus Ceaef9764f2008-05-13 18:45:46 +00001455static PyObject*
1456DB_close(DBObject* self, PyObject* args)
1457{
1458 int flags=0;
1459 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1460 return NULL;
1461 return DB_close_internal(self,flags);
1462}
1463
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001464
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001465static PyObject*
1466_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1467{
1468 int err, flags=0, type;
1469 PyObject* txnobj = NULL;
1470 PyObject* retval = NULL;
1471 DBT key, data;
1472 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001473 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001474
1475 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1476 &txnobj, &flags))
1477 return NULL;
1478
1479 CHECK_DB_NOT_CLOSED(self);
1480 type = _DB_get_type(self);
1481 if (type == -1)
1482 return NULL;
1483 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001484 PyErr_SetString(PyExc_TypeError,
1485 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001486 return NULL;
1487 }
1488 if (!checkTxnObj(txnobj, &txn))
1489 return NULL;
1490
1491 CLEAR_DBT(key);
1492 CLEAR_DBT(data);
1493 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001494 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001495 data.flags = DB_DBT_MALLOC;
1496 key.flags = DB_DBT_MALLOC;
1497 }
1498
1499 MYDB_BEGIN_ALLOW_THREADS;
1500 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1501 MYDB_END_ALLOW_THREADS;
1502
Gregory P. Smithe9477062005-06-04 06:46:59 +00001503 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1504 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001505 err = 0;
1506 Py_INCREF(Py_None);
1507 retval = Py_None;
1508 }
1509 else if (!err) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001510 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001511 FREE_DBT(key);
1512 FREE_DBT(data);
1513 }
1514
1515 RETURN_IF_ERR();
1516 return retval;
1517}
1518
1519static PyObject*
1520DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1521{
1522 return _DB_consume(self, args, kwargs, DB_CONSUME);
1523}
1524
1525static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001526DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1527 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001528{
1529 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1530}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001531
1532
1533static PyObject*
1534DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1535{
1536 int err, flags=0;
1537 DBC* dbc;
1538 PyObject* txnobj = NULL;
1539 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001540 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001541
1542 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1543 &txnobj, &flags))
1544 return NULL;
1545 CHECK_DB_NOT_CLOSED(self);
1546 if (!checkTxnObj(txnobj, &txn))
1547 return NULL;
1548
1549 MYDB_BEGIN_ALLOW_THREADS;
1550 err = self->db->cursor(self->db, txn, &dbc, flags);
1551 MYDB_END_ALLOW_THREADS;
1552 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001553 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001554}
1555
1556
1557static PyObject*
1558DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1559{
1560 PyObject* txnobj = NULL;
1561 int flags = 0;
1562 PyObject* keyobj;
1563 DBT key;
1564 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001565 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001566
1567 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1568 &keyobj, &txnobj, &flags))
1569 return NULL;
1570 CHECK_DB_NOT_CLOSED(self);
1571 if (!make_key_dbt(self, keyobj, &key, NULL))
1572 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001573 if (!checkTxnObj(txnobj, &txn)) {
1574 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001575 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001576 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001577
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001578 if (-1 == _DB_delete(self, txn, &key, 0)) {
1579 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001580 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001581 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001582
1583 FREE_DBT(key);
1584 RETURN_NONE();
1585}
1586
1587
1588static PyObject*
1589DB_fd(DBObject* self, PyObject* args)
1590{
1591 int err, the_fd;
1592
1593 if (!PyArg_ParseTuple(args,":fd"))
1594 return NULL;
1595 CHECK_DB_NOT_CLOSED(self);
1596
1597 MYDB_BEGIN_ALLOW_THREADS;
1598 err = self->db->fd(self->db, &the_fd);
1599 MYDB_END_ALLOW_THREADS;
1600 RETURN_IF_ERR();
1601 return PyInt_FromLong(the_fd);
1602}
1603
1604
1605static PyObject*
1606DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1607{
1608 int err, flags=0;
1609 PyObject* txnobj = NULL;
1610 PyObject* keyobj;
1611 PyObject* dfltobj = NULL;
1612 PyObject* retval = NULL;
1613 int dlen = -1;
1614 int doff = -1;
1615 DBT key, data;
1616 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001617 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001618 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001619
1620 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001621 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1622 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001623 return NULL;
1624
1625 CHECK_DB_NOT_CLOSED(self);
1626 if (!make_key_dbt(self, keyobj, &key, &flags))
1627 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001628 if (!checkTxnObj(txnobj, &txn)) {
1629 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001630 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001631 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001632
1633 CLEAR_DBT(data);
1634 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001635 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001636 data.flags = DB_DBT_MALLOC;
1637 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001638 if (!add_partial_dbt(&data, dlen, doff)) {
1639 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001640 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001641 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001642
1643 MYDB_BEGIN_ALLOW_THREADS;
1644 err = self->db->get(self->db, txn, &key, &data, flags);
1645 MYDB_END_ALLOW_THREADS;
1646
Gregory P. Smithe9477062005-06-04 06:46:59 +00001647 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001648 err = 0;
1649 Py_INCREF(dfltobj);
1650 retval = dfltobj;
1651 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001652 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1653 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001654 err = 0;
1655 Py_INCREF(Py_None);
1656 retval = Py_None;
1657 }
1658 else if (!err) {
1659 if (flags & DB_SET_RECNO) /* return both key and data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001660 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001661 else /* return just the data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001662 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001663 FREE_DBT(data);
1664 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001665 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001666
1667 RETURN_IF_ERR();
1668 return retval;
1669}
1670
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001671#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001672static PyObject*
1673DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1674{
1675 int err, flags=0;
1676 PyObject* txnobj = NULL;
1677 PyObject* keyobj;
1678 PyObject* dfltobj = NULL;
1679 PyObject* retval = NULL;
1680 int dlen = -1;
1681 int doff = -1;
1682 DBT key, pkey, data;
1683 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001684 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001685 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001686
1687 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1688 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1689 &doff))
1690 return NULL;
1691
1692 CHECK_DB_NOT_CLOSED(self);
1693 if (!make_key_dbt(self, keyobj, &key, &flags))
1694 return NULL;
1695 if (!checkTxnObj(txnobj, &txn)) {
1696 FREE_DBT(key);
1697 return NULL;
1698 }
1699
1700 CLEAR_DBT(data);
1701 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001702 /* Tell Berkeley DB to malloc the return value (thread safe) */
Gregory P. Smith19699a92004-06-28 04:06:49 +00001703 data.flags = DB_DBT_MALLOC;
1704 }
1705 if (!add_partial_dbt(&data, dlen, doff)) {
1706 FREE_DBT(key);
1707 return NULL;
1708 }
1709
1710 CLEAR_DBT(pkey);
1711 pkey.flags = DB_DBT_MALLOC;
1712
1713 MYDB_BEGIN_ALLOW_THREADS;
1714 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1715 MYDB_END_ALLOW_THREADS;
1716
Gregory P. Smithe9477062005-06-04 06:46:59 +00001717 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001718 err = 0;
1719 Py_INCREF(dfltobj);
1720 retval = dfltobj;
1721 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001722 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1723 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001724 err = 0;
1725 Py_INCREF(Py_None);
1726 retval = Py_None;
1727 }
1728 else if (!err) {
1729 PyObject *pkeyObj;
1730 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001731 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001732
1733 if (self->primaryDBType == DB_RECNO ||
1734 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001735 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001736 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001737 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001738
1739 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1740 {
1741 PyObject *keyObj;
1742 int type = _DB_get_type(self);
1743 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001744 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001745 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001746 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001747#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001748 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001749#else
1750 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1751#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001752 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001753 }
1754 else /* return just the pkey and data */
1755 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001756#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001757 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001758#else
1759 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1760#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001761 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001762 Py_DECREF(dataObj);
1763 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001764 FREE_DBT(pkey);
1765 FREE_DBT(data);
1766 }
1767 FREE_DBT(key);
1768
1769 RETURN_IF_ERR();
1770 return retval;
1771}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001772#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001773
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001774
1775/* Return size of entry */
1776static PyObject*
1777DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1778{
1779 int err, flags=0;
1780 PyObject* txnobj = NULL;
1781 PyObject* keyobj;
1782 PyObject* retval = NULL;
1783 DBT key, data;
1784 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001785 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001786
1787 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1788 &keyobj, &txnobj))
1789 return NULL;
1790 CHECK_DB_NOT_CLOSED(self);
1791 if (!make_key_dbt(self, keyobj, &key, &flags))
1792 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001793 if (!checkTxnObj(txnobj, &txn)) {
1794 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001795 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001796 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001797 CLEAR_DBT(data);
1798
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001799 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1800 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001801 data.flags = DB_DBT_USERMEM;
1802 data.ulen = 0;
1803 MYDB_BEGIN_ALLOW_THREADS;
1804 err = self->db->get(self->db, txn, &key, &data, flags);
1805 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001806 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001807 retval = PyInt_FromLong((long)data.size);
1808 err = 0;
1809 }
1810
1811 FREE_DBT(key);
1812 FREE_DBT(data);
1813 RETURN_IF_ERR();
1814 return retval;
1815}
1816
1817
1818static PyObject*
1819DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1820{
1821 int err, flags=0;
1822 PyObject* txnobj = NULL;
1823 PyObject* keyobj;
1824 PyObject* dataobj;
1825 PyObject* retval = NULL;
1826 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001827 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001828 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001829 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001830
1831
1832 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1833 &keyobj, &dataobj, &txnobj, &flags))
1834 return NULL;
1835
1836 CHECK_DB_NOT_CLOSED(self);
1837 if (!make_key_dbt(self, keyobj, &key, NULL))
1838 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001839 if ( !make_dbt(dataobj, &data) ||
1840 !checkTxnObj(txnobj, &txn) )
1841 {
1842 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001843 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001844 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001845
1846 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001847 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001848
1849 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001850 /* Tell Berkeley DB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001851 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001852 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001853 }
1854
1855 MYDB_BEGIN_ALLOW_THREADS;
1856 err = self->db->get(self->db, txn, &key, &data, flags);
1857 MYDB_END_ALLOW_THREADS;
1858
Gregory P. Smithe9477062005-06-04 06:46:59 +00001859 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1860 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001861 err = 0;
1862 Py_INCREF(Py_None);
1863 retval = Py_None;
1864 }
1865 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001866 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001867 retval = Build_PyString(data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001868
1869 /* Even though the flags require DB_DBT_MALLOC, data is not always
1870 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1871 if (data.data != orig_data)
1872 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001873 }
1874
1875 FREE_DBT(key);
1876 RETURN_IF_ERR();
1877 return retval;
1878}
1879
1880
1881static PyObject*
1882DB_get_byteswapped(DBObject* self, PyObject* args)
1883{
1884#if (DBVER >= 33)
1885 int err = 0;
1886#endif
1887 int retval = -1;
1888
1889 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1890 return NULL;
1891 CHECK_DB_NOT_CLOSED(self);
1892
1893#if (DBVER >= 33)
1894 MYDB_BEGIN_ALLOW_THREADS;
1895 err = self->db->get_byteswapped(self->db, &retval);
1896 MYDB_END_ALLOW_THREADS;
1897 RETURN_IF_ERR();
1898#else
1899 MYDB_BEGIN_ALLOW_THREADS;
1900 retval = self->db->get_byteswapped(self->db);
1901 MYDB_END_ALLOW_THREADS;
1902#endif
1903 return PyInt_FromLong(retval);
1904}
1905
1906
1907static PyObject*
1908DB_get_type(DBObject* self, PyObject* args)
1909{
1910 int type;
1911
1912 if (!PyArg_ParseTuple(args,":get_type"))
1913 return NULL;
1914 CHECK_DB_NOT_CLOSED(self);
1915
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001916 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001917 if (type == -1)
1918 return NULL;
1919 return PyInt_FromLong(type);
1920}
1921
1922
1923static PyObject*
1924DB_join(DBObject* self, PyObject* args)
1925{
1926 int err, flags=0;
1927 int length, x;
1928 PyObject* cursorsObj;
1929 DBC** cursors;
1930 DBC* dbc;
1931
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001932 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1933 return NULL;
1934
1935 CHECK_DB_NOT_CLOSED(self);
1936
1937 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001938 PyErr_SetString(PyExc_TypeError,
1939 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001940 return NULL;
1941 }
1942
1943 length = PyObject_Length(cursorsObj);
1944 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001945 if (!cursors) {
1946 PyErr_NoMemory();
1947 return NULL;
1948 }
1949
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001950 cursors[length] = NULL;
1951 for (x=0; x<length; x++) {
1952 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001953 if (item == NULL) {
1954 free(cursors);
1955 return NULL;
1956 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001957 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001958 PyErr_SetString(PyExc_TypeError,
1959 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001960 free(cursors);
1961 return NULL;
1962 }
1963 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001964 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001965 }
1966
1967 MYDB_BEGIN_ALLOW_THREADS;
1968 err = self->db->join(self->db, cursors, &dbc, flags);
1969 MYDB_END_ALLOW_THREADS;
1970 free(cursors);
1971 RETURN_IF_ERR();
1972
Gregory P. Smith7441e652003-11-03 21:35:31 +00001973 /* FIXME: this is a buggy interface. The returned cursor
1974 contains internal references to the passed in cursors
1975 but does not hold python references to them or prevent
1976 them from being closed prematurely. This can cause
1977 python to crash when things are done in the wrong order. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001978 return (PyObject*) newDBCursorObject(dbc, NULL, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001979}
1980
1981
1982static PyObject*
1983DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1984{
1985 int err, flags=0;
1986 PyObject* txnobj = NULL;
1987 PyObject* keyobj;
1988 DBT key;
1989 DB_TXN *txn = NULL;
1990 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001991 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001992
1993 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1994 &keyobj, &txnobj, &flags))
1995 return NULL;
1996 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001997 if (!make_dbt(keyobj, &key))
1998 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001999 return NULL;
2000 if (!checkTxnObj(txnobj, &txn))
2001 return NULL;
2002
2003 MYDB_BEGIN_ALLOW_THREADS;
2004 err = self->db->key_range(self->db, txn, &key, &range, flags);
2005 MYDB_END_ALLOW_THREADS;
2006
2007 RETURN_IF_ERR();
2008 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2009}
2010
2011
2012static PyObject*
2013DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2014{
2015 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2016 char* filename = NULL;
2017 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002018#if (DBVER >= 41)
2019 PyObject *txnobj = NULL;
2020 DB_TXN *txn = NULL;
2021 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002022 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002023 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2024 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00002025 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002026 "filename", "dbtype", "flags", "mode", "txn", NULL};
2027#else
2028 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002029 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002030 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2031 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002032 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002033 "filename", "dbtype", "flags", "mode", NULL};
2034#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002035
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002036#if (DBVER >= 41)
2037 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2038 &filename, &dbname, &type, &flags, &mode,
2039 &txnobj))
2040#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002041 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002042 &filename, &dbname, &type, &flags,
2043 &mode))
2044#endif
2045 {
2046 PyErr_Clear();
2047 type = DB_UNKNOWN; flags = 0; mode = 0660;
2048 filename = NULL; dbname = NULL;
2049#if (DBVER >= 41)
2050 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2051 kwnames_basic,
2052 &filename, &type, &flags, &mode,
2053 &txnobj))
2054 return NULL;
2055#else
2056 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2057 kwnames_basic,
2058 &filename, &type, &flags, &mode))
2059 return NULL;
2060#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002061 }
2062
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002063#if (DBVER >= 41)
2064 if (!checkTxnObj(txnobj, &txn)) return NULL;
2065#endif
2066
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002067 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002068 PyObject *t = Py_BuildValue("(is)", 0,
2069 "Cannot call open() twice for DB object");
2070 PyErr_SetObject(DBError, t);
2071 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002072 return NULL;
2073 }
2074
Jesus Ceaef9764f2008-05-13 18:45:46 +00002075#if (DBVER >= 41)
2076 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2077 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2078 self->txn=(DBTxnObject *)txnobj;
2079 } else {
2080 self->txn=NULL;
2081 }
2082#else
2083 self->txn=NULL;
2084#endif
2085
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002086 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002087#if (DBVER >= 41)
2088 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2089#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002090 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002091#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002092 MYDB_END_ALLOW_THREADS;
2093 if (makeDBError(err)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002094 PyObject *dummy;
2095
2096 dummy=DB_close_internal(self,0);
2097 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002098 return NULL;
2099 }
2100
Gregory P. Smithfc006692007-11-05 09:06:28 +00002101#if (DBVER >= 42)
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002102 self->db->get_flags(self->db, &self->setflags);
Gregory P. Smithfc006692007-11-05 09:06:28 +00002103#endif
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002104
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002105 self->flags = flags;
Jesus Ceaef9764f2008-05-13 18:45:46 +00002106
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002107 RETURN_NONE();
2108}
2109
2110
2111static PyObject*
2112DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2113{
2114 int flags=0;
2115 PyObject* txnobj = NULL;
2116 int dlen = -1;
2117 int doff = -1;
2118 PyObject* keyobj, *dataobj, *retval;
2119 DBT key, data;
2120 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002121 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002122 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002123
2124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2125 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2126 return NULL;
2127
2128 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002129 if (!make_key_dbt(self, keyobj, &key, NULL))
2130 return NULL;
2131 if ( !make_dbt(dataobj, &data) ||
2132 !add_partial_dbt(&data, dlen, doff) ||
2133 !checkTxnObj(txnobj, &txn) )
2134 {
2135 FREE_DBT(key);
2136 return NULL;
2137 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002138
2139 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2140 FREE_DBT(key);
2141 return NULL;
2142 }
2143
2144 if (flags & DB_APPEND)
2145 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2146 else {
2147 retval = Py_None;
2148 Py_INCREF(retval);
2149 }
2150 FREE_DBT(key);
2151 return retval;
2152}
2153
2154
2155
2156static PyObject*
2157DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2158{
2159 char* filename;
2160 char* database = NULL;
2161 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002162 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002163
2164 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2165 &filename, &database, &flags))
2166 return NULL;
2167 CHECK_DB_NOT_CLOSED(self);
2168
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002169 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002170 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002171 RETURN_IF_ERR();
2172 RETURN_NONE();
2173}
2174
2175
2176
2177static PyObject*
2178DB_rename(DBObject* self, PyObject* args)
2179{
2180 char* filename;
2181 char* database;
2182 char* newname;
2183 int err, flags=0;
2184
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002185 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2186 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002187 return NULL;
2188 CHECK_DB_NOT_CLOSED(self);
2189
2190 MYDB_BEGIN_ALLOW_THREADS;
2191 err = self->db->rename(self->db, filename, database, newname, flags);
2192 MYDB_END_ALLOW_THREADS;
2193 RETURN_IF_ERR();
2194 RETURN_NONE();
2195}
2196
2197
2198static PyObject*
2199DB_set_bt_minkey(DBObject* self, PyObject* args)
2200{
2201 int err, minkey;
2202
2203 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2204 return NULL;
2205 CHECK_DB_NOT_CLOSED(self);
2206
2207 MYDB_BEGIN_ALLOW_THREADS;
2208 err = self->db->set_bt_minkey(self->db, minkey);
2209 MYDB_END_ALLOW_THREADS;
2210 RETURN_IF_ERR();
2211 RETURN_NONE();
2212}
2213
Neal Norwitz84562352005-10-20 04:30:15 +00002214#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002215static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002216_default_cmp(const DBT *leftKey,
2217 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002218{
2219 int res;
2220 int lsize = leftKey->size, rsize = rightKey->size;
2221
Georg Brandlef1701f2006-03-07 14:57:48 +00002222 res = memcmp(leftKey->data, rightKey->data,
2223 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002224
2225 if (res == 0) {
2226 if (lsize < rsize) {
2227 res = -1;
2228 }
2229 else if (lsize > rsize) {
2230 res = 1;
2231 }
2232 }
2233 return res;
2234}
2235
2236static int
Jesus Ceaef9764f2008-05-13 18:45:46 +00002237_db_compareCallback(DB* db,
Georg Brandlef1701f2006-03-07 14:57:48 +00002238 const DBT *leftKey,
2239 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002240{
2241 int res = 0;
2242 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002243 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002244 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002245
2246 if (self == NULL || self->btCompareCallback == NULL) {
2247 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002248 PyErr_SetString(PyExc_TypeError,
2249 (self == 0
2250 ? "DB_bt_compare db is NULL."
2251 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002252 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002253 PyErr_Print();
2254 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002255 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002256 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002257 MYDB_BEGIN_BLOCK_THREADS;
2258
Jesus Ceaef9764f2008-05-13 18:45:46 +00002259 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002260 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002261 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002262 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002263 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002264 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002265 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002266 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002267 PyErr_Print();
2268 res = _default_cmp(leftKey, rightKey);
2269 } else if (PyInt_Check(result)) {
2270 res = PyInt_AsLong(result);
2271 } else {
2272 PyErr_SetString(PyExc_TypeError,
2273 "DB_bt_compare callback MUST return an int.");
2274 /* we're in a callback within the DB code, we can't raise */
2275 PyErr_Print();
2276 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002277 }
2278
Thomas Woutersb3153832006-03-08 01:47:19 +00002279 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002280 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002281
2282 MYDB_END_BLOCK_THREADS;
2283 }
2284 return res;
2285}
2286
2287static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002288DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002289{
2290 int err;
2291 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002292 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002293
Georg Brandlef1701f2006-03-07 14:57:48 +00002294 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002295 return NULL;
2296
Georg Brandlef1701f2006-03-07 14:57:48 +00002297 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002298
Georg Brandlef1701f2006-03-07 14:57:48 +00002299 if (!PyCallable_Check(comparator)) {
2300 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002301 return NULL;
2302 }
2303
2304 /*
2305 * Perform a test call of the comparator function with two empty
2306 * string objects here. verify that it returns an int (0).
2307 * err if not.
2308 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002309 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002310 result = PyEval_CallObject(comparator, tuple);
2311 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002312 if (result == NULL)
2313 return NULL;
2314 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002315 PyErr_SetString(PyExc_TypeError,
2316 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002317 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002318 } else if (PyInt_AsLong(result) != 0) {
2319 PyErr_SetString(PyExc_TypeError,
2320 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002321 return NULL;
2322 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002323 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002324
2325 /* We don't accept multiple set_bt_compare operations, in order to
2326 * simplify the code. This would have no real use, as one cannot
2327 * change the function once the db is opened anyway */
2328 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002329 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002330 return NULL;
2331 }
2332
Georg Brandlef1701f2006-03-07 14:57:48 +00002333 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002334 self->btCompareCallback = comparator;
2335
2336 /* This is to workaround a problem with un-initialized threads (see
2337 comment in DB_associate) */
2338#ifdef WITH_THREAD
2339 PyEval_InitThreads();
2340#endif
2341
Thomas Woutersb3153832006-03-08 01:47:19 +00002342 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002343
2344 if (err) {
2345 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002346 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002347 self->btCompareCallback = NULL;
2348 }
2349
Georg Brandlef1701f2006-03-07 14:57:48 +00002350 RETURN_IF_ERR();
2351 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002352}
Neal Norwitz84562352005-10-20 04:30:15 +00002353#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002354
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002355
2356static PyObject*
2357DB_set_cachesize(DBObject* self, PyObject* args)
2358{
2359 int err;
2360 int gbytes = 0, bytes = 0, ncache = 0;
2361
2362 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2363 &gbytes,&bytes,&ncache))
2364 return NULL;
2365 CHECK_DB_NOT_CLOSED(self);
2366
2367 MYDB_BEGIN_ALLOW_THREADS;
2368 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2369 MYDB_END_ALLOW_THREADS;
2370 RETURN_IF_ERR();
2371 RETURN_NONE();
2372}
2373
2374
2375static PyObject*
2376DB_set_flags(DBObject* self, PyObject* args)
2377{
2378 int err, flags;
2379
2380 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2381 return NULL;
2382 CHECK_DB_NOT_CLOSED(self);
2383
2384 MYDB_BEGIN_ALLOW_THREADS;
2385 err = self->db->set_flags(self->db, flags);
2386 MYDB_END_ALLOW_THREADS;
2387 RETURN_IF_ERR();
2388
2389 self->setflags |= flags;
2390 RETURN_NONE();
2391}
2392
2393
2394static PyObject*
2395DB_set_h_ffactor(DBObject* self, PyObject* args)
2396{
2397 int err, ffactor;
2398
2399 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2400 return NULL;
2401 CHECK_DB_NOT_CLOSED(self);
2402
2403 MYDB_BEGIN_ALLOW_THREADS;
2404 err = self->db->set_h_ffactor(self->db, ffactor);
2405 MYDB_END_ALLOW_THREADS;
2406 RETURN_IF_ERR();
2407 RETURN_NONE();
2408}
2409
2410
2411static PyObject*
2412DB_set_h_nelem(DBObject* self, PyObject* args)
2413{
2414 int err, nelem;
2415
2416 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2417 return NULL;
2418 CHECK_DB_NOT_CLOSED(self);
2419
2420 MYDB_BEGIN_ALLOW_THREADS;
2421 err = self->db->set_h_nelem(self->db, nelem);
2422 MYDB_END_ALLOW_THREADS;
2423 RETURN_IF_ERR();
2424 RETURN_NONE();
2425}
2426
2427
2428static PyObject*
2429DB_set_lorder(DBObject* self, PyObject* args)
2430{
2431 int err, lorder;
2432
2433 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2434 return NULL;
2435 CHECK_DB_NOT_CLOSED(self);
2436
2437 MYDB_BEGIN_ALLOW_THREADS;
2438 err = self->db->set_lorder(self->db, lorder);
2439 MYDB_END_ALLOW_THREADS;
2440 RETURN_IF_ERR();
2441 RETURN_NONE();
2442}
2443
2444
2445static PyObject*
2446DB_set_pagesize(DBObject* self, PyObject* args)
2447{
2448 int err, pagesize;
2449
2450 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2451 return NULL;
2452 CHECK_DB_NOT_CLOSED(self);
2453
2454 MYDB_BEGIN_ALLOW_THREADS;
2455 err = self->db->set_pagesize(self->db, pagesize);
2456 MYDB_END_ALLOW_THREADS;
2457 RETURN_IF_ERR();
2458 RETURN_NONE();
2459}
2460
2461
2462static PyObject*
2463DB_set_re_delim(DBObject* self, PyObject* args)
2464{
2465 int err;
2466 char delim;
2467
2468 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2469 PyErr_Clear();
2470 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2471 return NULL;
2472 }
2473
2474 CHECK_DB_NOT_CLOSED(self);
2475
2476 MYDB_BEGIN_ALLOW_THREADS;
2477 err = self->db->set_re_delim(self->db, delim);
2478 MYDB_END_ALLOW_THREADS;
2479 RETURN_IF_ERR();
2480 RETURN_NONE();
2481}
2482
2483static PyObject*
2484DB_set_re_len(DBObject* self, PyObject* args)
2485{
2486 int err, len;
2487
2488 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2489 return NULL;
2490 CHECK_DB_NOT_CLOSED(self);
2491
2492 MYDB_BEGIN_ALLOW_THREADS;
2493 err = self->db->set_re_len(self->db, len);
2494 MYDB_END_ALLOW_THREADS;
2495 RETURN_IF_ERR();
2496 RETURN_NONE();
2497}
2498
2499
2500static PyObject*
2501DB_set_re_pad(DBObject* self, PyObject* args)
2502{
2503 int err;
2504 char pad;
2505
2506 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2507 PyErr_Clear();
2508 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2509 return NULL;
2510 }
2511 CHECK_DB_NOT_CLOSED(self);
2512
2513 MYDB_BEGIN_ALLOW_THREADS;
2514 err = self->db->set_re_pad(self->db, pad);
2515 MYDB_END_ALLOW_THREADS;
2516 RETURN_IF_ERR();
2517 RETURN_NONE();
2518}
2519
2520
2521static PyObject*
2522DB_set_re_source(DBObject* self, PyObject* args)
2523{
2524 int err;
2525 char *re_source;
2526
2527 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2528 return NULL;
2529 CHECK_DB_NOT_CLOSED(self);
2530
2531 MYDB_BEGIN_ALLOW_THREADS;
2532 err = self->db->set_re_source(self->db, re_source);
2533 MYDB_END_ALLOW_THREADS;
2534 RETURN_IF_ERR();
2535 RETURN_NONE();
2536}
2537
2538
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002539static PyObject*
2540DB_set_q_extentsize(DBObject* self, PyObject* args)
2541{
2542 int err;
2543 int extentsize;
2544
2545 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2546 return NULL;
2547 CHECK_DB_NOT_CLOSED(self);
2548
2549 MYDB_BEGIN_ALLOW_THREADS;
2550 err = self->db->set_q_extentsize(self->db, extentsize);
2551 MYDB_END_ALLOW_THREADS;
2552 RETURN_IF_ERR();
2553 RETURN_NONE();
2554}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002555
2556static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002557DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002558{
2559 int err, flags = 0, type;
2560 void* sp;
2561 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002562#if (DBVER >= 43)
2563 PyObject* txnobj = NULL;
2564 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002565 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002566#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002567 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002568#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002569
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002570#if (DBVER >= 43)
2571 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2572 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002573 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002574 if (!checkTxnObj(txnobj, &txn))
2575 return NULL;
2576#else
2577 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2578 return NULL;
2579#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002580 CHECK_DB_NOT_CLOSED(self);
2581
2582 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002583#if (DBVER >= 43)
2584 err = self->db->stat(self->db, txn, &sp, flags);
2585#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002586 err = self->db->stat(self->db, &sp, flags);
2587#else
2588 err = self->db->stat(self->db, &sp, NULL, flags);
2589#endif
2590 MYDB_END_ALLOW_THREADS;
2591 RETURN_IF_ERR();
2592
2593 self->haveStat = 1;
2594
2595 /* Turn the stat structure into a dictionary */
2596 type = _DB_get_type(self);
2597 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2598 free(sp);
2599 return NULL;
2600 }
2601
2602#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2603#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2604#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2605
2606 switch (type) {
2607 case DB_HASH:
2608 MAKE_HASH_ENTRY(magic);
2609 MAKE_HASH_ENTRY(version);
2610 MAKE_HASH_ENTRY(nkeys);
2611 MAKE_HASH_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002612#if (DBVER >= 46)
2613 MAKE_HASH_ENTRY(pagecnt);
2614#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002615 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002616#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002617 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002618#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002619 MAKE_HASH_ENTRY(ffactor);
2620 MAKE_HASH_ENTRY(buckets);
2621 MAKE_HASH_ENTRY(free);
2622 MAKE_HASH_ENTRY(bfree);
2623 MAKE_HASH_ENTRY(bigpages);
2624 MAKE_HASH_ENTRY(big_bfree);
2625 MAKE_HASH_ENTRY(overflows);
2626 MAKE_HASH_ENTRY(ovfl_free);
2627 MAKE_HASH_ENTRY(dup);
2628 MAKE_HASH_ENTRY(dup_free);
2629 break;
2630
2631 case DB_BTREE:
2632 case DB_RECNO:
2633 MAKE_BT_ENTRY(magic);
2634 MAKE_BT_ENTRY(version);
2635 MAKE_BT_ENTRY(nkeys);
2636 MAKE_BT_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002637#if (DBVER >= 46)
2638 MAKE_BT_ENTRY(pagecnt);
2639#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002640 MAKE_BT_ENTRY(pagesize);
2641 MAKE_BT_ENTRY(minkey);
2642 MAKE_BT_ENTRY(re_len);
2643 MAKE_BT_ENTRY(re_pad);
2644 MAKE_BT_ENTRY(levels);
2645 MAKE_BT_ENTRY(int_pg);
2646 MAKE_BT_ENTRY(leaf_pg);
2647 MAKE_BT_ENTRY(dup_pg);
2648 MAKE_BT_ENTRY(over_pg);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002649#if (DBVER >= 43)
2650 MAKE_BT_ENTRY(empty_pg);
2651#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002652 MAKE_BT_ENTRY(free);
2653 MAKE_BT_ENTRY(int_pgfree);
2654 MAKE_BT_ENTRY(leaf_pgfree);
2655 MAKE_BT_ENTRY(dup_pgfree);
2656 MAKE_BT_ENTRY(over_pgfree);
2657 break;
2658
2659 case DB_QUEUE:
2660 MAKE_QUEUE_ENTRY(magic);
2661 MAKE_QUEUE_ENTRY(version);
2662 MAKE_QUEUE_ENTRY(nkeys);
2663 MAKE_QUEUE_ENTRY(ndata);
2664 MAKE_QUEUE_ENTRY(pagesize);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002665#if (DBVER > 40)
2666 MAKE_QUEUE_ENTRY(extentsize);
2667#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002668 MAKE_QUEUE_ENTRY(pages);
2669 MAKE_QUEUE_ENTRY(re_len);
2670 MAKE_QUEUE_ENTRY(re_pad);
2671 MAKE_QUEUE_ENTRY(pgfree);
2672#if (DBVER == 31)
2673 MAKE_QUEUE_ENTRY(start);
2674#endif
2675 MAKE_QUEUE_ENTRY(first_recno);
2676 MAKE_QUEUE_ENTRY(cur_recno);
2677 break;
2678
2679 default:
2680 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2681 Py_DECREF(d);
2682 d = NULL;
2683 }
2684
2685#undef MAKE_HASH_ENTRY
2686#undef MAKE_BT_ENTRY
2687#undef MAKE_QUEUE_ENTRY
2688
2689 free(sp);
2690 return d;
2691}
2692
2693static PyObject*
2694DB_sync(DBObject* self, PyObject* args)
2695{
2696 int err;
2697 int flags = 0;
2698
2699 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2700 return NULL;
2701 CHECK_DB_NOT_CLOSED(self);
2702
2703 MYDB_BEGIN_ALLOW_THREADS;
2704 err = self->db->sync(self->db, flags);
2705 MYDB_END_ALLOW_THREADS;
2706 RETURN_IF_ERR();
2707 RETURN_NONE();
2708}
2709
2710
2711#if (DBVER >= 33)
2712static PyObject*
2713DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2714{
2715 int err, flags=0;
2716 u_int32_t count=0;
2717 PyObject* txnobj = NULL;
2718 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002719 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002720
2721 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2722 &txnobj, &flags))
2723 return NULL;
2724 CHECK_DB_NOT_CLOSED(self);
2725 if (!checkTxnObj(txnobj, &txn))
2726 return NULL;
2727
2728 MYDB_BEGIN_ALLOW_THREADS;
2729 err = self->db->truncate(self->db, txn, &count, flags);
2730 MYDB_END_ALLOW_THREADS;
2731 RETURN_IF_ERR();
2732 return PyInt_FromLong(count);
2733}
2734#endif
2735
2736
2737static PyObject*
2738DB_upgrade(DBObject* self, PyObject* args)
2739{
2740 int err, flags=0;
2741 char *filename;
2742
2743 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2744 return NULL;
2745 CHECK_DB_NOT_CLOSED(self);
2746
2747 MYDB_BEGIN_ALLOW_THREADS;
2748 err = self->db->upgrade(self->db, filename, flags);
2749 MYDB_END_ALLOW_THREADS;
2750 RETURN_IF_ERR();
2751 RETURN_NONE();
2752}
2753
2754
2755static PyObject*
2756DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2757{
2758 int err, flags=0;
2759 char* fileName;
2760 char* dbName=NULL;
2761 char* outFileName=NULL;
2762 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002763 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002764 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002765
2766 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2767 &fileName, &dbName, &outFileName, &flags))
2768 return NULL;
2769
2770 CHECK_DB_NOT_CLOSED(self);
2771 if (outFileName)
2772 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002773 /* XXX(nnorwitz): it should probably be an exception if outFile
2774 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002775
2776 MYDB_BEGIN_ALLOW_THREADS;
2777 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2778 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002779 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002780 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002781
Jesus Ceaef9764f2008-05-13 18:45:46 +00002782 { /* DB.verify acts as a DB handle destructor (like close) */
2783 PyObject *error;
2784
2785 error=DB_close_internal(self,0);
2786 if (error ) {
2787 return error;
2788 }
2789 }
Gregory P. Smith41631e82003-09-21 00:08:14 +00002790
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002791 RETURN_IF_ERR();
2792 RETURN_NONE();
2793}
2794
2795
2796static PyObject*
2797DB_set_get_returns_none(DBObject* self, PyObject* args)
2798{
2799 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002800 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002801
2802 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2803 return NULL;
2804 CHECK_DB_NOT_CLOSED(self);
2805
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002806 if (self->moduleFlags.getReturnsNone)
2807 ++oldValue;
2808 if (self->moduleFlags.cursorSetReturnsNone)
2809 ++oldValue;
2810 self->moduleFlags.getReturnsNone = (flags >= 1);
2811 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002812 return PyInt_FromLong(oldValue);
2813}
2814
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002815#if (DBVER >= 41)
2816static PyObject*
2817DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2818{
2819 int err;
2820 u_int32_t flags=0;
2821 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002822 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002823
2824 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2825 &passwd, &flags)) {
2826 return NULL;
2827 }
2828
2829 MYDB_BEGIN_ALLOW_THREADS;
2830 err = self->db->set_encrypt(self->db, passwd, flags);
2831 MYDB_END_ALLOW_THREADS;
2832
2833 RETURN_IF_ERR();
2834 RETURN_NONE();
2835}
2836#endif /* DBVER >= 41 */
2837
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002838
2839/*-------------------------------------------------------------- */
2840/* Mapping and Dictionary-like access routines */
2841
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002842Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002843{
2844 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002845 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002846 int flags = 0;
2847 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002848 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002849
2850 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002851 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2852 PyErr_SetObject(DBError, t);
2853 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002854 return -1;
2855 }
2856
2857 if (self->haveStat) { /* Has the stat function been called recently? If
2858 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002859 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002860 }
2861
2862 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002863redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002864#if (DBVER >= 43)
2865 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2866#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002867 err = self->db->stat(self->db, &sp, flags);
2868#else
2869 err = self->db->stat(self->db, &sp, NULL, flags);
2870#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002871
2872 /* All the stat structures have matching fields upto the ndata field,
2873 so we can use any of them for the type cast */
2874 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2875
Jesus Ceaef9764f2008-05-13 18:45:46 +00002876 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002877 * redo a full stat to make sure.
2878 * Fixes SF python bug 1493322, pybsddb bug 1184012
2879 */
2880 if (size == 0 && (flags & DB_FAST_STAT)) {
2881 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002882 if (!err)
2883 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002884 goto redo_stat_for_length;
2885 }
2886
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002887 MYDB_END_ALLOW_THREADS;
2888
2889 if (err)
2890 return -1;
2891
2892 self->haveStat = 1;
2893
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002894 free(sp);
2895 return size;
2896}
2897
2898
2899PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2900{
2901 int err;
2902 PyObject* retval;
2903 DBT key;
2904 DBT data;
2905
2906 CHECK_DB_NOT_CLOSED(self);
2907 if (!make_key_dbt(self, keyobj, &key, NULL))
2908 return NULL;
2909
2910 CLEAR_DBT(data);
2911 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002912 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002913 data.flags = DB_DBT_MALLOC;
2914 }
2915 MYDB_BEGIN_ALLOW_THREADS;
2916 err = self->db->get(self->db, NULL, &key, &data, 0);
2917 MYDB_END_ALLOW_THREADS;
2918 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2919 PyErr_SetObject(PyExc_KeyError, keyobj);
2920 retval = NULL;
2921 }
2922 else if (makeDBError(err)) {
2923 retval = NULL;
2924 }
2925 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002926 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002927 FREE_DBT(data);
2928 }
2929
2930 FREE_DBT(key);
2931 return retval;
2932}
2933
2934
2935static int
2936DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2937{
2938 DBT key, data;
2939 int retval;
2940 int flags = 0;
2941
2942 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002943 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2944 PyErr_SetObject(DBError, t);
2945 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002946 return -1;
2947 }
2948
2949 if (!make_key_dbt(self, keyobj, &key, NULL))
2950 return -1;
2951
2952 if (dataobj != NULL) {
2953 if (!make_dbt(dataobj, &data))
2954 retval = -1;
2955 else {
2956 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002957 /* dictionaries shouldn't have duplicate keys */
2958 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002959 retval = _DB_put(self, NULL, &key, &data, flags);
2960
2961 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002962 /* try deleting any old record that matches and then PUT it
2963 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002964 _DB_delete(self, NULL, &key, 0);
2965 PyErr_Clear();
2966 retval = _DB_put(self, NULL, &key, &data, flags);
2967 }
2968 }
2969 }
2970 else {
2971 /* dataobj == NULL, so delete the key */
2972 retval = _DB_delete(self, NULL, &key, 0);
2973 }
2974 FREE_DBT(key);
2975 return retval;
2976}
2977
2978
2979static PyObject*
2980DB_has_key(DBObject* self, PyObject* args)
2981{
2982 int err;
2983 PyObject* keyobj;
2984 DBT key, data;
2985 PyObject* txnobj = NULL;
2986 DB_TXN *txn = NULL;
2987
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002988 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002989 return NULL;
2990 CHECK_DB_NOT_CLOSED(self);
2991 if (!make_key_dbt(self, keyobj, &key, NULL))
2992 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002993 if (!checkTxnObj(txnobj, &txn)) {
2994 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002995 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002996 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002997
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002998 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002999 it has a record but can't allocate a buffer for the data. This saves
3000 having to deal with data we won't be using.
3001 */
3002 CLEAR_DBT(data);
3003 data.flags = DB_DBT_USERMEM;
3004
3005 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00003006 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003007 MYDB_END_ALLOW_THREADS;
3008 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003009
3010 if (err == DB_BUFFER_SMALL || err == 0) {
3011 return PyInt_FromLong(1);
3012 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3013 return PyInt_FromLong(0);
3014 }
3015
3016 makeDBError(err);
3017 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003018}
3019
3020
3021#define _KEYS_LIST 1
3022#define _VALUES_LIST 2
3023#define _ITEMS_LIST 3
3024
3025static PyObject*
3026_DB_make_list(DBObject* self, DB_TXN* txn, int type)
3027{
3028 int err, dbtype;
3029 DBT key;
3030 DBT data;
3031 DBC *cursor;
3032 PyObject* list;
3033 PyObject* item = NULL;
3034
3035 CHECK_DB_NOT_CLOSED(self);
3036 CLEAR_DBT(key);
3037 CLEAR_DBT(data);
3038
3039 dbtype = _DB_get_type(self);
3040 if (dbtype == -1)
3041 return NULL;
3042
3043 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00003044 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003045 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003046
3047 /* get a cursor */
3048 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00003049 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003050 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00003051 if (makeDBError(err)) {
3052 Py_DECREF(list);
3053 return NULL;
3054 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003055
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003056 while (1) { /* use the cursor to traverse the DB, collecting items */
3057 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003058 err = _DBC_get(cursor, &key, &data, DB_NEXT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003059 MYDB_END_ALLOW_THREADS;
3060
3061 if (err) {
3062 /* for any error, break out of the loop */
3063 break;
3064 }
3065
3066 switch (type) {
3067 case _KEYS_LIST:
3068 switch(dbtype) {
3069 case DB_BTREE:
3070 case DB_HASH:
3071 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003072 item = Build_PyString(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003073 break;
3074 case DB_RECNO:
3075 case DB_QUEUE:
3076 item = PyInt_FromLong(*((db_recno_t*)key.data));
3077 break;
3078 }
3079 break;
3080
3081 case _VALUES_LIST:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003082 item = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003083 break;
3084
3085 case _ITEMS_LIST:
3086 switch(dbtype) {
3087 case DB_BTREE:
3088 case DB_HASH:
3089 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003090 item = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003091 break;
3092 case DB_RECNO:
3093 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003094 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003095 break;
3096 }
3097 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00003098 default:
3099 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3100 item = NULL;
3101 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003102 }
3103 if (item == NULL) {
3104 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003105 list = NULL;
3106 goto done;
3107 }
3108 PyList_Append(list, item);
3109 Py_DECREF(item);
3110 }
3111
Gregory P. Smithe9477062005-06-04 06:46:59 +00003112 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3113 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003114 Py_DECREF(list);
3115 list = NULL;
3116 }
3117
3118 done:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003119 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003120 _DBC_close(cursor);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003121 MYDB_END_ALLOW_THREADS;
3122 return list;
3123}
3124
3125
3126static PyObject*
3127DB_keys(DBObject* self, PyObject* args)
3128{
3129 PyObject* txnobj = NULL;
3130 DB_TXN *txn = NULL;
3131
Georg Brandl96a8c392006-05-29 21:04:52 +00003132 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003133 return NULL;
3134 if (!checkTxnObj(txnobj, &txn))
3135 return NULL;
3136 return _DB_make_list(self, txn, _KEYS_LIST);
3137}
3138
3139
3140static PyObject*
3141DB_items(DBObject* self, PyObject* args)
3142{
3143 PyObject* txnobj = NULL;
3144 DB_TXN *txn = NULL;
3145
Georg Brandl96a8c392006-05-29 21:04:52 +00003146 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003147 return NULL;
3148 if (!checkTxnObj(txnobj, &txn))
3149 return NULL;
3150 return _DB_make_list(self, txn, _ITEMS_LIST);
3151}
3152
3153
3154static PyObject*
3155DB_values(DBObject* self, PyObject* args)
3156{
3157 PyObject* txnobj = NULL;
3158 DB_TXN *txn = NULL;
3159
Georg Brandl96a8c392006-05-29 21:04:52 +00003160 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003161 return NULL;
3162 if (!checkTxnObj(txnobj, &txn))
3163 return NULL;
3164 return _DB_make_list(self, txn, _VALUES_LIST);
3165}
3166
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003167/* --------------------------------------------------------------------- */
3168/* DBCursor methods */
3169
3170
3171static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003172DBC_close_internal(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173{
3174 int err = 0;
3175
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003176 if (self->dbc != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003177 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3178 if (self->txn) {
3179 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3180 self->txn=NULL;
3181 }
3182
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003183 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003184 err = _DBC_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003185 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003186 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003187 }
3188 RETURN_IF_ERR();
3189 RETURN_NONE();
3190}
3191
Jesus Ceaef9764f2008-05-13 18:45:46 +00003192static PyObject*
3193DBC_close(DBCursorObject* self, PyObject* args)
3194{
3195 if (!PyArg_ParseTuple(args, ":close"))
3196 return NULL;
3197
3198 return DBC_close_internal(self);
3199}
3200
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003201
3202static PyObject*
3203DBC_count(DBCursorObject* self, PyObject* args)
3204{
3205 int err = 0;
3206 db_recno_t count;
3207 int flags = 0;
3208
3209 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3210 return NULL;
3211
3212 CHECK_CURSOR_NOT_CLOSED(self);
3213
3214 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003215 err = _DBC_count(self->dbc, &count, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003216 MYDB_END_ALLOW_THREADS;
3217 RETURN_IF_ERR();
3218
3219 return PyInt_FromLong(count);
3220}
3221
3222
3223static PyObject*
3224DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3225{
3226 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3227}
3228
3229
3230static PyObject*
3231DBC_delete(DBCursorObject* self, PyObject* args)
3232{
3233 int err, flags=0;
3234
3235 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3236 return NULL;
3237
3238 CHECK_CURSOR_NOT_CLOSED(self);
3239
3240 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003241 err = _DBC_del(self->dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003242 MYDB_END_ALLOW_THREADS;
3243 RETURN_IF_ERR();
3244
3245 self->mydb->haveStat = 0;
3246 RETURN_NONE();
3247}
3248
3249
3250static PyObject*
3251DBC_dup(DBCursorObject* self, PyObject* args)
3252{
3253 int err, flags =0;
3254 DBC* dbc = NULL;
3255
3256 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3257 return NULL;
3258
3259 CHECK_CURSOR_NOT_CLOSED(self);
3260
3261 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003262 err = _DBC_dup(self->dbc, &dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003263 MYDB_END_ALLOW_THREADS;
3264 RETURN_IF_ERR();
3265
Jesus Ceaef9764f2008-05-13 18:45:46 +00003266 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003267}
3268
3269static PyObject*
3270DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3271{
3272 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3273}
3274
3275
3276static PyObject*
3277DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3278{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003279 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003280 PyObject* keyobj = NULL;
3281 PyObject* dataobj = NULL;
3282 PyObject* retval = NULL;
3283 int dlen = -1;
3284 int doff = -1;
3285 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003286 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003287 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003288
3289 CLEAR_DBT(key);
3290 CLEAR_DBT(data);
3291 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003292 &flags, &dlen, &doff))
3293 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003294 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003295 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3296 &kwnames[1],
3297 &keyobj, &flags, &dlen, &doff))
3298 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003299 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003300 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3301 kwnames, &keyobj, &dataobj,
3302 &flags, &dlen, &doff))
3303 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003304 return NULL;
3305 }
3306 }
3307 }
3308
3309 CHECK_CURSOR_NOT_CLOSED(self);
3310
3311 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3312 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003313 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3314 (!add_partial_dbt(&data, dlen, doff)) )
3315 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003316 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003317 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003318 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003319
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003320 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003321 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003322 MYDB_END_ALLOW_THREADS;
3323
Gregory P. Smithe9477062005-06-04 06:46:59 +00003324 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3325 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003326 Py_INCREF(Py_None);
3327 retval = Py_None;
3328 }
3329 else if (makeDBError(err)) {
3330 retval = NULL;
3331 }
3332 else {
3333 switch (_DB_get_type(self->mydb)) {
3334 case -1:
3335 retval = NULL;
3336 break;
3337 case DB_BTREE:
3338 case DB_HASH:
3339 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003340 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003341 break;
3342 case DB_RECNO:
3343 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003344 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003345 break;
3346 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003347 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003348 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003349 return retval;
3350}
3351
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003352#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003353static PyObject*
3354DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3355{
3356 int err, flags=0;
3357 PyObject* keyobj = NULL;
3358 PyObject* dataobj = NULL;
3359 PyObject* retval = NULL;
3360 int dlen = -1;
3361 int doff = -1;
3362 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003363 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3364 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003365
3366 CLEAR_DBT(key);
3367 CLEAR_DBT(data);
3368 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3369 &flags, &dlen, &doff))
3370 {
3371 PyErr_Clear();
3372 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003373 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003374 &keyobj, &flags, &dlen, &doff))
3375 {
3376 PyErr_Clear();
3377 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3378 kwnames, &keyobj, &dataobj,
3379 &flags, &dlen, &doff))
3380 {
3381 return NULL;
3382 }
3383 }
3384 }
3385
3386 CHECK_CURSOR_NOT_CLOSED(self);
3387
3388 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3389 return NULL;
3390 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3391 (!add_partial_dbt(&data, dlen, doff)) ) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003392 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003393 return NULL;
3394 }
3395
Gregory P. Smith19699a92004-06-28 04:06:49 +00003396 CLEAR_DBT(pkey);
3397 pkey.flags = DB_DBT_MALLOC;
3398
3399 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003400 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003401 MYDB_END_ALLOW_THREADS;
3402
Gregory P. Smithe9477062005-06-04 06:46:59 +00003403 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3404 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003405 Py_INCREF(Py_None);
3406 retval = Py_None;
3407 }
3408 else if (makeDBError(err)) {
3409 retval = NULL;
3410 }
3411 else {
3412 PyObject *pkeyObj;
3413 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003414 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003415
3416 if (self->mydb->primaryDBType == DB_RECNO ||
3417 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003418 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003419 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003420 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003421
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003422 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003423 {
3424 PyObject *keyObj;
3425 int type = _DB_get_type(self->mydb);
3426 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003427 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003428 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003429 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003430#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003431 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003432#else
3433 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3434#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003435 Py_DECREF(keyObj);
Jesus Ceaef9764f2008-05-13 18:45:46 +00003436 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003437 }
3438 else /* return just the pkey and data */
3439 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003440#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003441 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003442#else
3443 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3444#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003445 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003446 Py_DECREF(dataObj);
3447 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003448 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003449 }
3450 /* the only time REALLOC should be set is if we used an integer
3451 * key that make_key_dbt malloc'd for us. always free these. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003452 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003453 FREE_DBT(key);
3454 }
3455 return retval;
3456}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003457#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003458
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003459
3460static PyObject*
3461DBC_get_recno(DBCursorObject* self, PyObject* args)
3462{
3463 int err;
3464 db_recno_t recno;
3465 DBT key;
3466 DBT data;
3467
3468 if (!PyArg_ParseTuple(args, ":get_recno"))
3469 return NULL;
3470
3471 CHECK_CURSOR_NOT_CLOSED(self);
3472
3473 CLEAR_DBT(key);
3474 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003475
3476 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003477 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003478 MYDB_END_ALLOW_THREADS;
3479 RETURN_IF_ERR();
3480
3481 recno = *((db_recno_t*)data.data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003482 return PyInt_FromLong(recno);
3483}
3484
3485
3486static PyObject*
3487DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3488{
3489 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3490}
3491
3492
3493static PyObject*
3494DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3495{
3496 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3497}
3498
3499
3500static PyObject*
3501DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3502{
3503 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3504}
3505
3506
3507static PyObject*
3508DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3509{
3510 int err, flags = 0;
3511 PyObject* keyobj, *dataobj;
3512 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003513 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003514 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003515 int dlen = -1;
3516 int doff = -1;
3517
3518 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3519 &keyobj, &dataobj, &flags, &dlen, &doff))
3520 return NULL;
3521
3522 CHECK_CURSOR_NOT_CLOSED(self);
3523
3524 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3525 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003526 if (!make_dbt(dataobj, &data) ||
3527 !add_partial_dbt(&data, dlen, doff) )
3528 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003529 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003530 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003531 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003532
3533 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003534 err = _DBC_put(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003535 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003536 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003537 RETURN_IF_ERR();
3538 self->mydb->haveStat = 0;
3539 RETURN_NONE();
3540}
3541
3542
3543static PyObject*
3544DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3545{
3546 int err, flags = 0;
3547 DBT key, data;
3548 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003549 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003550 int dlen = -1;
3551 int doff = -1;
3552
3553 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3554 &keyobj, &flags, &dlen, &doff))
3555 return NULL;
3556
3557 CHECK_CURSOR_NOT_CLOSED(self);
3558
3559 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3560 return NULL;
3561
3562 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003563 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003564 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003565 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003566 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003567
3568 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003569 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003570 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003571 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3572 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003573 Py_INCREF(Py_None);
3574 retval = Py_None;
3575 }
3576 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003577 retval = NULL;
3578 }
3579 else {
3580 switch (_DB_get_type(self->mydb)) {
3581 case -1:
3582 retval = NULL;
3583 break;
3584 case DB_BTREE:
3585 case DB_HASH:
3586 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003587 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003588 break;
3589 case DB_RECNO:
3590 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003591 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003592 break;
3593 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003594 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003595 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003596 /* the only time REALLOC should be set is if we used an integer
3597 * key that make_key_dbt malloc'd for us. always free these. */
3598 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003599 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003600 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003601
3602 return retval;
3603}
3604
3605
3606static PyObject*
3607DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3608{
3609 int err, flags = 0;
3610 DBT key, data;
3611 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003612 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003613 int dlen = -1;
3614 int doff = -1;
3615
3616 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3617 &keyobj, &flags, &dlen, &doff))
3618 return NULL;
3619
3620 CHECK_CURSOR_NOT_CLOSED(self);
3621
3622 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3623 return NULL;
3624
3625 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003626 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003627 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003628 return NULL;
3629 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003630 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003631 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003632 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003633 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3634 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003635 Py_INCREF(Py_None);
3636 retval = Py_None;
3637 }
3638 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003639 retval = NULL;
3640 }
3641 else {
3642 switch (_DB_get_type(self->mydb)) {
3643 case -1:
3644 retval = NULL;
3645 break;
3646 case DB_BTREE:
3647 case DB_HASH:
3648 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003649 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003650 break;
3651 case DB_RECNO:
3652 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003653 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003654 break;
3655 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003656 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003657 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003658 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003659 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003660 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003661 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003662 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003663
3664 return retval;
3665}
3666
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003667static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003668_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3669 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003670{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003671 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003672 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003673 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003674
Gregory P. Smith7441e652003-11-03 21:35:31 +00003675 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003676 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3677 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003678 if (!make_dbt(dataobj, &data)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003679 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003680 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003681 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003682
3683 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003684 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003685 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003686 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003687 Py_INCREF(Py_None);
3688 retval = Py_None;
3689 }
3690 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003691 retval = NULL;
3692 }
3693 else {
3694 switch (_DB_get_type(self->mydb)) {
3695 case -1:
3696 retval = NULL;
3697 break;
3698 case DB_BTREE:
3699 case DB_HASH:
3700 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003701 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003702 break;
3703 case DB_RECNO:
3704 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003705 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003706 break;
3707 }
3708 }
3709
Jesus Ceaef9764f2008-05-13 18:45:46 +00003710 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003711 return retval;
3712}
3713
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003714static PyObject*
3715DBC_get_both(DBCursorObject* self, PyObject* args)
3716{
3717 int flags=0;
3718 PyObject *keyobj, *dataobj;
3719
3720 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3721 return NULL;
3722
Gregory P. Smith7441e652003-11-03 21:35:31 +00003723 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003724 CHECK_CURSOR_NOT_CLOSED(self);
3725
3726 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3727 self->mydb->moduleFlags.getReturnsNone);
3728}
3729
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003730/* Return size of entry */
3731static PyObject*
3732DBC_get_current_size(DBCursorObject* self, PyObject* args)
3733{
3734 int err, flags=DB_CURRENT;
3735 PyObject* retval = NULL;
3736 DBT key, data;
3737
3738 if (!PyArg_ParseTuple(args, ":get_current_size"))
3739 return NULL;
3740 CHECK_CURSOR_NOT_CLOSED(self);
3741 CLEAR_DBT(key);
3742 CLEAR_DBT(data);
3743
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003744 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003745 getting the record size. */
3746 data.flags = DB_DBT_USERMEM;
3747 data.ulen = 0;
3748 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003749 err = _DBC_get(self->dbc, &key, &data, flags);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003750 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003751 if (err == DB_BUFFER_SMALL || !err) {
3752 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003753 retval = PyInt_FromLong((long)data.size);
3754 err = 0;
3755 }
3756
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003757 RETURN_IF_ERR();
3758 return retval;
3759}
3760
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003761static PyObject*
3762DBC_set_both(DBCursorObject* self, PyObject* args)
3763{
3764 int flags=0;
3765 PyObject *keyobj, *dataobj;
3766
3767 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3768 return NULL;
3769
Gregory P. Smith7441e652003-11-03 21:35:31 +00003770 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003771 CHECK_CURSOR_NOT_CLOSED(self);
3772
3773 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3774 self->mydb->moduleFlags.cursorSetReturnsNone);
3775}
3776
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003777
3778static PyObject*
3779DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3780{
3781 int err, irecno, flags=0;
3782 db_recno_t recno;
3783 DBT key, data;
3784 PyObject* retval;
3785 int dlen = -1;
3786 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003787 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003788
3789 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3790 &irecno, &flags, &dlen, &doff))
3791 return NULL;
3792
3793 CHECK_CURSOR_NOT_CLOSED(self);
3794
3795 CLEAR_DBT(key);
3796 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003797 /* use allocated space so DB will be able to realloc room for the real
3798 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003799 key.data = malloc(sizeof(db_recno_t));
3800 if (key.data == NULL) {
3801 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3802 return NULL;
3803 }
3804 key.size = sizeof(db_recno_t);
3805 key.ulen = key.size;
3806 memcpy(key.data, &recno, sizeof(db_recno_t));
3807 key.flags = DB_DBT_REALLOC;
3808
3809 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003810 if (!add_partial_dbt(&data, dlen, doff)) {
3811 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003812 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003813 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003814
3815 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003816 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003817 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003818 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3819 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003820 Py_INCREF(Py_None);
3821 retval = Py_None;
3822 }
3823 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003824 retval = NULL;
3825 }
3826 else { /* Can only be used for BTrees, so no need to return int key */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003827 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003828 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003829 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003830
3831 return retval;
3832}
3833
3834
3835static PyObject*
3836DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3837{
3838 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3839}
3840
3841
3842static PyObject*
3843DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3844{
3845 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3846}
3847
3848
3849static PyObject*
3850DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3851{
3852 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3853}
3854
3855
3856static PyObject*
3857DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3858{
3859 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3860}
3861
3862
3863static PyObject*
3864DBC_join_item(DBCursorObject* self, PyObject* args)
3865{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003866 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003867 DBT key, data;
3868 PyObject* retval;
3869
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003870 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003871 return NULL;
3872
3873 CHECK_CURSOR_NOT_CLOSED(self);
3874
3875 CLEAR_DBT(key);
3876 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003877
3878 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003879 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003880 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003881 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3882 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003883 Py_INCREF(Py_None);
3884 retval = Py_None;
3885 }
3886 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003887 retval = NULL;
3888 }
3889 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003890 retval = BuildValue_S(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003891 }
3892
3893 return retval;
3894}
3895
3896
3897
3898/* --------------------------------------------------------------------- */
3899/* DBEnv methods */
3900
3901
3902static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003903DBEnv_close_internal(DBEnvObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003904{
Jesus Ceaef9764f2008-05-13 18:45:46 +00003905 PyObject *dummy;
3906 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003907
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003908 if (!self->closed) { /* Don't close more than once */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003909 while(self->children_txns) {
3910 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
3911 Py_XDECREF(dummy);
3912 }
3913 while(self->children_dbs) {
3914 dummy=DB_close_internal(self->children_dbs,0);
3915 Py_XDECREF(dummy);
3916 }
3917
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003918 MYDB_BEGIN_ALLOW_THREADS;
3919 err = self->db_env->close(self->db_env, flags);
3920 MYDB_END_ALLOW_THREADS;
3921 /* after calling DBEnv->close, regardless of error, this DBEnv
Jesus Ceaef9764f2008-05-13 18:45:46 +00003922 * may not be accessed again (Berkeley DB docs). */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003923 self->closed = 1;
3924 self->db_env = NULL;
3925 RETURN_IF_ERR();
3926 }
3927 RETURN_NONE();
3928}
3929
Jesus Ceaef9764f2008-05-13 18:45:46 +00003930static PyObject*
3931DBEnv_close(DBEnvObject* self, PyObject* args)
3932{
3933 int flags = 0;
3934
3935 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3936 return NULL;
3937 return DBEnv_close_internal(self,flags);
3938}
3939
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003940
3941static PyObject*
3942DBEnv_open(DBEnvObject* self, PyObject* args)
3943{
3944 int err, flags=0, mode=0660;
3945 char *db_home;
3946
3947 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3948 return NULL;
3949
3950 CHECK_ENV_NOT_CLOSED(self);
3951
3952 MYDB_BEGIN_ALLOW_THREADS;
3953 err = self->db_env->open(self->db_env, db_home, flags, mode);
3954 MYDB_END_ALLOW_THREADS;
3955 RETURN_IF_ERR();
3956 self->closed = 0;
3957 self->flags = flags;
3958 RETURN_NONE();
3959}
3960
3961
3962static PyObject*
3963DBEnv_remove(DBEnvObject* self, PyObject* args)
3964{
3965 int err, flags=0;
3966 char *db_home;
3967
3968 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3969 return NULL;
3970 CHECK_ENV_NOT_CLOSED(self);
3971 MYDB_BEGIN_ALLOW_THREADS;
3972 err = self->db_env->remove(self->db_env, db_home, flags);
3973 MYDB_END_ALLOW_THREADS;
3974 RETURN_IF_ERR();
3975 RETURN_NONE();
3976}
3977
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003978#if (DBVER >= 41)
3979static PyObject*
3980DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3981{
3982 int err;
3983 u_int32_t flags=0;
3984 char *file = NULL;
3985 char *database = NULL;
3986 PyObject *txnobj = NULL;
3987 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003988 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003989 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003990
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003991 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003992 &file, &database, &txnobj, &flags)) {
3993 return NULL;
3994 }
3995 if (!checkTxnObj(txnobj, &txn)) {
3996 return NULL;
3997 }
3998 CHECK_ENV_NOT_CLOSED(self);
3999 MYDB_BEGIN_ALLOW_THREADS;
4000 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4001 MYDB_END_ALLOW_THREADS;
4002 RETURN_IF_ERR();
4003 RETURN_NONE();
4004}
4005
4006static PyObject*
4007DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4008{
4009 int err;
4010 u_int32_t flags=0;
4011 char *file = NULL;
4012 char *database = NULL;
4013 char *newname = NULL;
4014 PyObject *txnobj = NULL;
4015 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004016 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004017 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004018
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004019 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004020 &file, &database, &newname, &txnobj, &flags)) {
4021 return NULL;
4022 }
4023 if (!checkTxnObj(txnobj, &txn)) {
4024 return NULL;
4025 }
4026 CHECK_ENV_NOT_CLOSED(self);
4027 MYDB_BEGIN_ALLOW_THREADS;
4028 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4029 flags);
4030 MYDB_END_ALLOW_THREADS;
4031 RETURN_IF_ERR();
4032 RETURN_NONE();
4033}
4034
4035static PyObject*
4036DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4037{
4038 int err;
4039 u_int32_t flags=0;
4040 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004041 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004042
4043 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4044 &passwd, &flags)) {
4045 return NULL;
4046 }
4047
4048 MYDB_BEGIN_ALLOW_THREADS;
4049 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4050 MYDB_END_ALLOW_THREADS;
4051
4052 RETURN_IF_ERR();
4053 RETURN_NONE();
4054}
4055#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004056
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004057#if (DBVER >= 40)
4058static PyObject*
4059DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4060{
4061 int err;
4062 u_int32_t flags=0;
4063 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004064 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004065
4066 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4067 &timeout, &flags)) {
4068 return NULL;
4069 }
4070
4071 MYDB_BEGIN_ALLOW_THREADS;
4072 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4073 MYDB_END_ALLOW_THREADS;
4074
4075 RETURN_IF_ERR();
4076 RETURN_NONE();
4077}
4078#endif /* DBVER >= 40 */
4079
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004080static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004081DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4082{
4083 int err;
4084 long shm_key = 0;
4085
4086 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4087 return NULL;
4088 CHECK_ENV_NOT_CLOSED(self);
4089
4090 err = self->db_env->set_shm_key(self->db_env, shm_key);
4091 RETURN_IF_ERR();
4092 RETURN_NONE();
4093}
4094
4095static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004096DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4097{
4098 int err, gbytes=0, bytes=0, ncache=0;
4099
4100 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4101 &gbytes, &bytes, &ncache))
4102 return NULL;
4103 CHECK_ENV_NOT_CLOSED(self);
4104
4105 MYDB_BEGIN_ALLOW_THREADS;
4106 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4107 MYDB_END_ALLOW_THREADS;
4108 RETURN_IF_ERR();
4109 RETURN_NONE();
4110}
4111
4112
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004113static PyObject*
4114DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4115{
4116 int err, flags=0, onoff=0;
4117
4118 if (!PyArg_ParseTuple(args, "ii:set_flags",
4119 &flags, &onoff))
4120 return NULL;
4121 CHECK_ENV_NOT_CLOSED(self);
4122
4123 MYDB_BEGIN_ALLOW_THREADS;
4124 err = self->db_env->set_flags(self->db_env, flags, onoff);
4125 MYDB_END_ALLOW_THREADS;
4126 RETURN_IF_ERR();
4127 RETURN_NONE();
4128}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004129
4130
4131static PyObject*
4132DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4133{
4134 int err;
4135 char *dir;
4136
4137 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4138 return NULL;
4139 CHECK_ENV_NOT_CLOSED(self);
4140
4141 MYDB_BEGIN_ALLOW_THREADS;
4142 err = self->db_env->set_data_dir(self->db_env, dir);
4143 MYDB_END_ALLOW_THREADS;
4144 RETURN_IF_ERR();
4145 RETURN_NONE();
4146}
4147
4148
4149static PyObject*
4150DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4151{
4152 int err, lg_bsize;
4153
4154 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4155 return NULL;
4156 CHECK_ENV_NOT_CLOSED(self);
4157
4158 MYDB_BEGIN_ALLOW_THREADS;
4159 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4160 MYDB_END_ALLOW_THREADS;
4161 RETURN_IF_ERR();
4162 RETURN_NONE();
4163}
4164
4165
4166static PyObject*
4167DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4168{
4169 int err;
4170 char *dir;
4171
4172 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4173 return NULL;
4174 CHECK_ENV_NOT_CLOSED(self);
4175
4176 MYDB_BEGIN_ALLOW_THREADS;
4177 err = self->db_env->set_lg_dir(self->db_env, dir);
4178 MYDB_END_ALLOW_THREADS;
4179 RETURN_IF_ERR();
4180 RETURN_NONE();
4181}
4182
4183static PyObject*
4184DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4185{
4186 int err, lg_max;
4187
4188 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4189 return NULL;
4190 CHECK_ENV_NOT_CLOSED(self);
4191
4192 MYDB_BEGIN_ALLOW_THREADS;
4193 err = self->db_env->set_lg_max(self->db_env, lg_max);
4194 MYDB_END_ALLOW_THREADS;
4195 RETURN_IF_ERR();
4196 RETURN_NONE();
4197}
4198
Jesus Ceaef9764f2008-05-13 18:45:46 +00004199#if (DBVER >= 42)
4200static PyObject*
4201DBEnv_get_lg_max(DBEnvObject* self, PyObject* args)
4202{
4203 int err;
4204 u_int32_t lg_max;
4205
4206 if (!PyArg_ParseTuple(args, ":get_lg_max"))
4207 return NULL;
4208 CHECK_ENV_NOT_CLOSED(self);
4209
4210 MYDB_BEGIN_ALLOW_THREADS;
4211 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4212 MYDB_END_ALLOW_THREADS;
4213 RETURN_IF_ERR();
4214 return PyInt_FromLong(lg_max);
4215}
4216#endif
4217
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004218
Neal Norwitz84562352005-10-20 04:30:15 +00004219#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004220static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004221DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4222{
4223 int err, lg_max;
4224
4225 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4226 return NULL;
4227 CHECK_ENV_NOT_CLOSED(self);
4228
4229 MYDB_BEGIN_ALLOW_THREADS;
4230 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4231 MYDB_END_ALLOW_THREADS;
4232 RETURN_IF_ERR();
4233 RETURN_NONE();
4234}
Neal Norwitz84562352005-10-20 04:30:15 +00004235#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004236
4237
4238static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004239DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4240{
4241 int err, lk_detect;
4242
4243 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4244 return NULL;
4245 CHECK_ENV_NOT_CLOSED(self);
4246
4247 MYDB_BEGIN_ALLOW_THREADS;
4248 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4249 MYDB_END_ALLOW_THREADS;
4250 RETURN_IF_ERR();
4251 RETURN_NONE();
4252}
4253
4254
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004255#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004256static PyObject*
4257DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4258{
4259 int err, max;
4260
4261 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4262 return NULL;
4263 CHECK_ENV_NOT_CLOSED(self);
4264
4265 MYDB_BEGIN_ALLOW_THREADS;
4266 err = self->db_env->set_lk_max(self->db_env, max);
4267 MYDB_END_ALLOW_THREADS;
4268 RETURN_IF_ERR();
4269 RETURN_NONE();
4270}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004271#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004272
4273
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004274
4275static PyObject*
4276DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4277{
4278 int err, max;
4279
4280 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4281 return NULL;
4282 CHECK_ENV_NOT_CLOSED(self);
4283
4284 MYDB_BEGIN_ALLOW_THREADS;
4285 err = self->db_env->set_lk_max_locks(self->db_env, max);
4286 MYDB_END_ALLOW_THREADS;
4287 RETURN_IF_ERR();
4288 RETURN_NONE();
4289}
4290
4291
4292static PyObject*
4293DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4294{
4295 int err, max;
4296
4297 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4298 return NULL;
4299 CHECK_ENV_NOT_CLOSED(self);
4300
4301 MYDB_BEGIN_ALLOW_THREADS;
4302 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4303 MYDB_END_ALLOW_THREADS;
4304 RETURN_IF_ERR();
4305 RETURN_NONE();
4306}
4307
4308
4309static PyObject*
4310DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4311{
4312 int err, max;
4313
4314 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4315 return NULL;
4316 CHECK_ENV_NOT_CLOSED(self);
4317
4318 MYDB_BEGIN_ALLOW_THREADS;
4319 err = self->db_env->set_lk_max_objects(self->db_env, max);
4320 MYDB_END_ALLOW_THREADS;
4321 RETURN_IF_ERR();
4322 RETURN_NONE();
4323}
4324
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004325
4326static PyObject*
4327DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4328{
4329 int err, mp_mmapsize;
4330
4331 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4332 return NULL;
4333 CHECK_ENV_NOT_CLOSED(self);
4334
4335 MYDB_BEGIN_ALLOW_THREADS;
4336 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4337 MYDB_END_ALLOW_THREADS;
4338 RETURN_IF_ERR();
4339 RETURN_NONE();
4340}
4341
4342
4343static PyObject*
4344DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4345{
4346 int err;
4347 char *dir;
4348
4349 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4350 return NULL;
4351 CHECK_ENV_NOT_CLOSED(self);
4352
4353 MYDB_BEGIN_ALLOW_THREADS;
4354 err = self->db_env->set_tmp_dir(self->db_env, dir);
4355 MYDB_END_ALLOW_THREADS;
4356 RETURN_IF_ERR();
4357 RETURN_NONE();
4358}
4359
4360
Jesus Ceaef9764f2008-05-13 18:45:46 +00004361#if (DBVER >= 40)
4362static PyObject*
4363DBEnv_txn_recover(DBEnvObject* self, PyObject* args)
4364{
4365 int flags = DB_FIRST;
4366 int err, i;
4367 PyObject *list, *tuple, *gid;
4368 DBTxnObject *txn;
4369#define PREPLIST_LEN 16
4370 DB_PREPLIST preplist[PREPLIST_LEN];
4371 long retp;
4372
4373 if (!PyArg_ParseTuple(args, ":txn_recover"))
4374 return NULL;
4375
4376 CHECK_ENV_NOT_CLOSED(self);
4377
4378 list=PyList_New(0);
4379 if (!list)
4380 return NULL;
4381 while (!0) {
4382 MYDB_BEGIN_ALLOW_THREADS
4383 err=self->db_env->txn_recover(self->db_env,
4384 preplist, PREPLIST_LEN, &retp, flags);
4385#undef PREPLIST_LEN
4386 MYDB_END_ALLOW_THREADS
4387 if (err) {
4388 Py_DECREF(list);
4389 RETURN_IF_ERR();
4390 }
4391 if (!retp) break;
4392 flags=DB_NEXT; /* Prepare for next loop pass */
4393 for (i=0; i<retp; i++) {
4394 gid=PyString_FromStringAndSize((char *)(preplist[i].gid),
4395 DB_XIDDATASIZE);
4396 if (!gid) {
4397 Py_DECREF(list);
4398 return NULL;
4399 }
4400 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4401 if (!txn) {
4402 Py_DECREF(list);
4403 Py_DECREF(gid);
4404 return NULL;
4405 }
4406 txn->flag_prepare=1; /* Recover state */
4407 tuple=PyTuple_New(2);
4408 if (!tuple) {
4409 Py_DECREF(list);
4410 Py_DECREF(gid);
4411 Py_DECREF(txn);
4412 return NULL;
4413 }
4414 if (PyTuple_SetItem(tuple, 0, gid)) {
4415 Py_DECREF(list);
4416 Py_DECREF(gid);
4417 Py_DECREF(txn);
4418 Py_DECREF(tuple);
4419 return NULL;
4420 }
4421 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4422 Py_DECREF(list);
4423 Py_DECREF(txn);
4424 Py_DECREF(tuple); /* This delete the "gid" also */
4425 return NULL;
4426 }
4427 if (PyList_Append(list, tuple)) {
4428 Py_DECREF(list);
4429 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4430 return NULL;
4431 }
4432 Py_DECREF(tuple);
4433 }
4434 }
4435 return list;
4436}
4437#endif
4438
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004439static PyObject*
4440DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4441{
4442 int flags = 0;
4443 PyObject* txnobj = NULL;
4444 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004445 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004446
4447 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4448 &txnobj, &flags))
4449 return NULL;
4450
4451 if (!checkTxnObj(txnobj, &txn))
4452 return NULL;
4453 CHECK_ENV_NOT_CLOSED(self);
4454
Jesus Ceaef9764f2008-05-13 18:45:46 +00004455 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004456}
4457
4458
4459static PyObject*
4460DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4461{
4462 int err, kbyte=0, min=0, flags=0;
4463
4464 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4465 return NULL;
4466 CHECK_ENV_NOT_CLOSED(self);
4467
4468 MYDB_BEGIN_ALLOW_THREADS;
4469#if (DBVER >= 40)
4470 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4471#else
4472 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4473#endif
4474 MYDB_END_ALLOW_THREADS;
4475 RETURN_IF_ERR();
4476 RETURN_NONE();
4477}
4478
4479
4480static PyObject*
4481DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4482{
4483 int err, max;
4484
4485 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4486 return NULL;
4487 CHECK_ENV_NOT_CLOSED(self);
4488
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004489 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004490 RETURN_IF_ERR();
4491 RETURN_NONE();
4492}
4493
4494
4495static PyObject*
4496DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4497{
4498 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004499 long stamp;
4500 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004501
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004502 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004503 return NULL;
4504 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004505 timestamp = (time_t)stamp;
4506 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004507 RETURN_IF_ERR();
4508 RETURN_NONE();
4509}
4510
4511
4512static PyObject*
4513DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4514{
4515 int err, atype, flags=0;
4516 int aborted = 0;
4517
4518 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4519 return NULL;
4520 CHECK_ENV_NOT_CLOSED(self);
4521
4522 MYDB_BEGIN_ALLOW_THREADS;
4523#if (DBVER >= 40)
4524 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4525#else
4526 err = lock_detect(self->db_env, flags, atype, &aborted);
4527#endif
4528 MYDB_END_ALLOW_THREADS;
4529 RETURN_IF_ERR();
4530 return PyInt_FromLong(aborted);
4531}
4532
4533
4534static PyObject*
4535DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4536{
4537 int flags=0;
4538 int locker, lock_mode;
4539 DBT obj;
4540 PyObject* objobj;
4541
4542 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4543 return NULL;
4544
4545
4546 if (!make_dbt(objobj, &obj))
4547 return NULL;
4548
4549 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4550}
4551
4552
4553static PyObject*
4554DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4555{
4556 int err;
4557 u_int32_t theID;
4558
4559 if (!PyArg_ParseTuple(args, ":lock_id"))
4560 return NULL;
4561
4562 CHECK_ENV_NOT_CLOSED(self);
4563 MYDB_BEGIN_ALLOW_THREADS;
4564#if (DBVER >= 40)
4565 err = self->db_env->lock_id(self->db_env, &theID);
4566#else
4567 err = lock_id(self->db_env, &theID);
4568#endif
4569 MYDB_END_ALLOW_THREADS;
4570 RETURN_IF_ERR();
4571
4572 return PyInt_FromLong((long)theID);
4573}
4574
Gregory P. Smithac11e022007-11-05 02:56:31 +00004575#if (DBVER >= 40)
4576static PyObject*
4577DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4578{
4579 int err;
4580 u_int32_t theID;
4581
4582 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4583 return NULL;
4584
4585 CHECK_ENV_NOT_CLOSED(self);
4586 MYDB_BEGIN_ALLOW_THREADS;
4587 err = self->db_env->lock_id_free(self->db_env, theID);
4588 MYDB_END_ALLOW_THREADS;
4589 RETURN_IF_ERR();
4590 RETURN_NONE();
4591}
4592#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004593
4594static PyObject*
4595DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4596{
4597 int err;
4598 DBLockObject* dblockobj;
4599
4600 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4601 return NULL;
4602
4603 CHECK_ENV_NOT_CLOSED(self);
4604 MYDB_BEGIN_ALLOW_THREADS;
4605#if (DBVER >= 40)
4606 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4607#else
4608 err = lock_put(self->db_env, &dblockobj->lock);
4609#endif
4610 MYDB_END_ALLOW_THREADS;
4611 RETURN_IF_ERR();
4612 RETURN_NONE();
4613}
4614
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004615#if (DBVER >= 44)
4616static PyObject*
4617DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4618{
4619 int err;
4620 char *file;
4621 u_int32_t flags = 0;
4622 static char* kwnames[] = { "file", "flags", NULL};
4623
4624 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4625 &file, &flags))
4626 return NULL;
4627 CHECK_ENV_NOT_CLOSED(self);
4628
4629 MYDB_BEGIN_ALLOW_THREADS;
4630 err = self->db_env->lsn_reset(self->db_env, file, flags);
4631 MYDB_END_ALLOW_THREADS;
4632 RETURN_IF_ERR();
4633 RETURN_NONE();
4634}
4635#endif /* DBVER >= 4.4 */
4636
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004637#if (DBVER >= 40)
4638static PyObject*
4639DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4640{
4641 int err;
4642 DB_LOG_STAT* statp = NULL;
4643 PyObject* d = NULL;
4644 u_int32_t flags = 0;
4645
4646 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4647 return NULL;
4648 CHECK_ENV_NOT_CLOSED(self);
4649
4650 MYDB_BEGIN_ALLOW_THREADS;
4651 err = self->db_env->log_stat(self->db_env, &statp, flags);
4652 MYDB_END_ALLOW_THREADS;
4653 RETURN_IF_ERR();
4654
4655 /* Turn the stat structure into a dictionary */
4656 d = PyDict_New();
4657 if (d == NULL) {
4658 if (statp)
4659 free(statp);
4660 return NULL;
4661 }
4662
4663#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4664
4665 MAKE_ENTRY(magic);
4666 MAKE_ENTRY(version);
4667 MAKE_ENTRY(mode);
4668 MAKE_ENTRY(lg_bsize);
4669#if (DBVER >= 44)
4670 MAKE_ENTRY(lg_size);
4671 MAKE_ENTRY(record);
4672#endif
4673#if (DBVER <= 40)
4674 MAKE_ENTRY(lg_max);
4675#endif
4676 MAKE_ENTRY(w_mbytes);
4677 MAKE_ENTRY(w_bytes);
4678 MAKE_ENTRY(wc_mbytes);
4679 MAKE_ENTRY(wc_bytes);
4680 MAKE_ENTRY(wcount);
4681 MAKE_ENTRY(wcount_fill);
4682#if (DBVER >= 44)
4683 MAKE_ENTRY(rcount);
4684#endif
4685 MAKE_ENTRY(scount);
4686 MAKE_ENTRY(cur_file);
4687 MAKE_ENTRY(cur_offset);
4688 MAKE_ENTRY(disk_file);
4689 MAKE_ENTRY(disk_offset);
4690 MAKE_ENTRY(maxcommitperflush);
4691 MAKE_ENTRY(mincommitperflush);
4692 MAKE_ENTRY(regsize);
4693 MAKE_ENTRY(region_wait);
4694 MAKE_ENTRY(region_nowait);
4695
4696#undef MAKE_ENTRY
4697 free(statp);
4698 return d;
4699} /* DBEnv_log_stat */
4700#endif /* DBVER >= 4.0 for log_stat method */
4701
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004702
4703static PyObject*
4704DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4705{
4706 int err;
4707 DB_LOCK_STAT* sp;
4708 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004709 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004710
4711 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4712 return NULL;
4713 CHECK_ENV_NOT_CLOSED(self);
4714
4715 MYDB_BEGIN_ALLOW_THREADS;
4716#if (DBVER >= 40)
4717 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4718#else
4719#if (DBVER >= 33)
4720 err = lock_stat(self->db_env, &sp);
4721#else
4722 err = lock_stat(self->db_env, &sp, NULL);
4723#endif
4724#endif
4725 MYDB_END_ALLOW_THREADS;
4726 RETURN_IF_ERR();
4727
4728 /* Turn the stat structure into a dictionary */
4729 d = PyDict_New();
4730 if (d == NULL) {
4731 free(sp);
4732 return NULL;
4733 }
4734
4735#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4736
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004737#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004738 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004739#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004740#if (DBVER >=41)
4741 MAKE_ENTRY(id);
4742 MAKE_ENTRY(cur_maxid);
4743#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004744 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004745 MAKE_ENTRY(maxlocks);
4746 MAKE_ENTRY(maxlockers);
4747 MAKE_ENTRY(maxobjects);
4748 MAKE_ENTRY(nlocks);
4749 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004750 MAKE_ENTRY(nlockers);
4751 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004752 MAKE_ENTRY(nobjects);
4753 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004754 MAKE_ENTRY(nrequests);
4755 MAKE_ENTRY(nreleases);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004756#if (DBVER >= 44)
4757 MAKE_ENTRY(nupgrade);
4758 MAKE_ENTRY(ndowngrade);
4759#endif
Gregory P. Smith29602d22006-01-24 09:46:48 +00004760#if (DBVER < 44)
4761 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004762 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004763#else
4764 MAKE_ENTRY(lock_nowait);
4765 MAKE_ENTRY(lock_wait);
4766#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004767 MAKE_ENTRY(ndeadlocks);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004768#if (DBVER >= 41)
4769 MAKE_ENTRY(locktimeout);
4770 MAKE_ENTRY(txntimeout);
4771#endif
4772#if (DBVER >= 40)
4773 MAKE_ENTRY(nlocktimeouts);
4774 MAKE_ENTRY(ntxntimeouts);
4775#endif
4776#if (DBVER >= 46)
4777 MAKE_ENTRY(objs_wait);
4778 MAKE_ENTRY(objs_nowait);
4779 MAKE_ENTRY(lockers_wait);
4780 MAKE_ENTRY(lockers_nowait);
4781 MAKE_ENTRY(locks_wait);
4782 MAKE_ENTRY(locks_nowait);
4783 MAKE_ENTRY(hash_len);
4784#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004785 MAKE_ENTRY(regsize);
4786 MAKE_ENTRY(region_wait);
4787 MAKE_ENTRY(region_nowait);
4788
4789#undef MAKE_ENTRY
4790 free(sp);
4791 return d;
4792}
4793
Jesus Ceaef9764f2008-05-13 18:45:46 +00004794#if (DBVER >= 40)
4795static PyObject*
4796DBEnv_log_flush(DBEnvObject* self, PyObject* args)
4797{
4798 int err;
4799
4800 if (!PyArg_ParseTuple(args, ":log_flush"))
4801 return NULL;
4802 CHECK_ENV_NOT_CLOSED(self);
4803
4804 MYDB_BEGIN_ALLOW_THREADS
4805 err = self->db_env->log_flush(self->db_env, NULL);
4806 MYDB_END_ALLOW_THREADS
4807
4808 RETURN_IF_ERR();
4809 RETURN_NONE();
4810}
4811#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004812
4813static PyObject*
4814DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4815{
4816 int flags=0;
4817 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004818 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004819 PyObject* list;
4820 PyObject* item = NULL;
4821
4822 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4823 return NULL;
4824
4825 CHECK_ENV_NOT_CLOSED(self);
4826 MYDB_BEGIN_ALLOW_THREADS;
4827#if (DBVER >= 40)
4828 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4829#elif (DBVER == 33)
4830 err = log_archive(self->db_env, &log_list, flags);
4831#else
4832 err = log_archive(self->db_env, &log_list, flags, NULL);
4833#endif
4834 MYDB_END_ALLOW_THREADS;
4835 RETURN_IF_ERR();
4836
Gregory P. Smithbad47452006-06-05 00:33:35 +00004837 list = PyList_New(0);
4838 if (list == NULL) {
4839 if (log_list)
4840 free(log_list);
4841 return NULL;
4842 }
4843
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004844 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004845 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004846 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4847 item = PyString_FromString (*log_list);
4848 if (item == NULL) {
4849 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004850 list = NULL;
4851 break;
4852 }
4853 PyList_Append(list, item);
4854 Py_DECREF(item);
4855 }
4856 free(log_list_start);
4857 }
4858 return list;
4859}
4860
4861
4862static PyObject*
4863DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4864{
4865 int err;
4866 DB_TXN_STAT* sp;
4867 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004868 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004869
4870 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4871 return NULL;
4872 CHECK_ENV_NOT_CLOSED(self);
4873
4874 MYDB_BEGIN_ALLOW_THREADS;
4875#if (DBVER >= 40)
4876 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4877#elif (DBVER == 33)
4878 err = txn_stat(self->db_env, &sp);
4879#else
4880 err = txn_stat(self->db_env, &sp, NULL);
4881#endif
4882 MYDB_END_ALLOW_THREADS;
4883 RETURN_IF_ERR();
4884
4885 /* Turn the stat structure into a dictionary */
4886 d = PyDict_New();
4887 if (d == NULL) {
4888 free(sp);
4889 return NULL;
4890 }
4891
Jesus Ceaef9764f2008-05-13 18:45:46 +00004892#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4893#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4894#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004895
Jesus Ceaef9764f2008-05-13 18:45:46 +00004896#if (DBVER >= 40)
4897 MAKE_DB_LSN_ENTRY(last_ckp);
4898#endif
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004899 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004900 MAKE_ENTRY(last_txnid);
4901 MAKE_ENTRY(maxtxns);
4902 MAKE_ENTRY(nactive);
4903 MAKE_ENTRY(maxnactive);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004904#if (DBVER >= 45)
4905 MAKE_ENTRY(nsnapshot);
4906 MAKE_ENTRY(maxnsnapshot);
4907#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004908 MAKE_ENTRY(nbegins);
4909 MAKE_ENTRY(naborts);
4910 MAKE_ENTRY(ncommits);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004911#if (DBVER >= 40)
4912 MAKE_ENTRY(nrestores);
4913#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004914 MAKE_ENTRY(regsize);
4915 MAKE_ENTRY(region_wait);
4916 MAKE_ENTRY(region_nowait);
4917
Jesus Ceaef9764f2008-05-13 18:45:46 +00004918#undef MAKE_DB_LSN_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004919#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004920#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004921 free(sp);
4922 return d;
4923}
4924
4925
4926static PyObject*
4927DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4928{
4929 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004930 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004931
4932 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4933 return NULL;
4934 CHECK_ENV_NOT_CLOSED(self);
4935
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004936 if (self->moduleFlags.getReturnsNone)
4937 ++oldValue;
4938 if (self->moduleFlags.cursorSetReturnsNone)
4939 ++oldValue;
4940 self->moduleFlags.getReturnsNone = (flags >= 1);
4941 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004942 return PyInt_FromLong(oldValue);
4943}
4944
Jesus Ceaef9764f2008-05-13 18:45:46 +00004945#if (DBVER >= 40)
4946static PyObject*
4947DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
4948{
4949 int err;
4950 int which, onoff;
4951
4952 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
4953 return NULL;
4954 }
4955 CHECK_ENV_NOT_CLOSED(self);
4956 MYDB_BEGIN_ALLOW_THREADS;
4957 err = self->db_env->set_verbose(self->db_env, which, onoff);
4958 MYDB_END_ALLOW_THREADS;
4959 RETURN_IF_ERR();
4960 RETURN_NONE();
4961}
4962
4963#if (DBVER >= 42)
4964static PyObject*
4965DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
4966{
4967 int err;
4968 int which;
4969 int verbose;
4970
4971 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
4972 return NULL;
4973 }
4974 CHECK_ENV_NOT_CLOSED(self);
4975 MYDB_BEGIN_ALLOW_THREADS;
4976 err = self->db_env->get_verbose(self->db_env, which, &verbose);
4977 MYDB_END_ALLOW_THREADS;
4978 RETURN_IF_ERR();
4979 return PyBool_FromLong(verbose);
4980}
4981#endif
4982#endif
4983
4984#if (DBVER >= 45)
4985static void
4986_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
4987{
4988 DBEnvObject *dbenv;
4989 PyObject* callback;
4990 PyObject* args;
4991 PyObject* result = NULL;
4992
4993 MYDB_BEGIN_BLOCK_THREADS;
4994 dbenv = (DBEnvObject *)db_env->app_private;
4995 callback = dbenv->event_notifyCallback;
4996 if (callback) {
4997 if (event == DB_EVENT_REP_NEWMASTER) {
4998 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
4999 } else {
5000 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5001 }
5002 if (args) {
5003 result = PyEval_CallObject(callback, args);
5004 }
5005 if ((!args) || (!result)) {
5006 PyErr_Print();
5007 }
5008 Py_XDECREF(args);
5009 Py_XDECREF(result);
5010 }
5011 MYDB_END_BLOCK_THREADS;
5012}
5013#endif
5014
5015#if (DBVER >= 45)
5016static PyObject*
5017DBEnv_set_event_notify(DBEnvObject* self, PyObject* args)
5018{
5019 int err;
5020 PyObject *notifyFunc;
5021
5022 if (!PyArg_ParseTuple(args, "O:set_event_notify", &notifyFunc)) {
5023 return NULL;
5024 }
5025
5026 CHECK_ENV_NOT_CLOSED(self);
5027
5028 if (!PyCallable_Check(notifyFunc)) {
5029 makeTypeError("Callable", notifyFunc);
5030 return NULL;
5031 }
5032
5033 Py_XDECREF(self->event_notifyCallback);
5034 Py_INCREF(notifyFunc);
5035 self->event_notifyCallback = notifyFunc;
5036
5037 MYDB_BEGIN_ALLOW_THREADS;
5038 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5039 MYDB_END_ALLOW_THREADS;
5040
5041 if (err) {
5042 Py_DECREF(notifyFunc);
5043 self->event_notifyCallback = NULL;
5044 }
5045
5046 RETURN_IF_ERR();
5047 RETURN_NONE();
5048}
5049#endif
5050
5051
5052/* --------------------------------------------------------------------- */
5053/* REPLICATION METHODS: Base Replication */
5054
5055#if (DBVER >= 45)
5056static PyObject*
5057DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5058{
5059 int err;
5060 int nsites;
5061
5062 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5063 return NULL;
5064 }
5065 CHECK_ENV_NOT_CLOSED(self);
5066 MYDB_BEGIN_ALLOW_THREADS;
5067 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5068 MYDB_END_ALLOW_THREADS;
5069 RETURN_IF_ERR();
5070 RETURN_NONE();
5071}
5072
5073static PyObject*
5074DBEnv_rep_get_nsites(DBEnvObject* self, PyObject* args)
5075{
5076 int err;
5077 int nsites;
5078
5079 if (!PyArg_ParseTuple(args, ":rep_get_nsites")) {
5080 return NULL;
5081 }
5082 CHECK_ENV_NOT_CLOSED(self);
5083 MYDB_BEGIN_ALLOW_THREADS;
5084 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5085 MYDB_END_ALLOW_THREADS;
5086 RETURN_IF_ERR();
5087 return PyInt_FromLong(nsites);
5088}
5089
5090static PyObject*
5091DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5092{
5093 int err;
5094 int priority;
5095
5096 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5097 return NULL;
5098 }
5099 CHECK_ENV_NOT_CLOSED(self);
5100 MYDB_BEGIN_ALLOW_THREADS;
5101 err = self->db_env->rep_set_priority(self->db_env, priority);
5102 MYDB_END_ALLOW_THREADS;
5103 RETURN_IF_ERR();
5104 RETURN_NONE();
5105}
5106
5107static PyObject*
5108DBEnv_rep_get_priority(DBEnvObject* self, PyObject* args)
5109{
5110 int err;
5111 int priority;
5112
5113 if (!PyArg_ParseTuple(args, ":rep_get_priority")) {
5114 return NULL;
5115 }
5116 CHECK_ENV_NOT_CLOSED(self);
5117 MYDB_BEGIN_ALLOW_THREADS;
5118 err = self->db_env->rep_get_priority(self->db_env, &priority);
5119 MYDB_END_ALLOW_THREADS;
5120 RETURN_IF_ERR();
5121 return PyInt_FromLong(priority);
5122}
5123
5124static PyObject*
5125DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5126{
5127 int err;
5128 int which, timeout;
5129
5130 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5131 return NULL;
5132 }
5133 CHECK_ENV_NOT_CLOSED(self);
5134 MYDB_BEGIN_ALLOW_THREADS;
5135 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5136 MYDB_END_ALLOW_THREADS;
5137 RETURN_IF_ERR();
5138 RETURN_NONE();
5139}
5140
5141static PyObject*
5142DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5143{
5144 int err;
5145 int which;
5146 u_int32_t timeout;
5147
5148 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5149 return NULL;
5150 }
5151 CHECK_ENV_NOT_CLOSED(self);
5152 MYDB_BEGIN_ALLOW_THREADS;
5153 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5154 MYDB_END_ALLOW_THREADS;
5155 RETURN_IF_ERR();
5156 return PyInt_FromLong(timeout);
5157}
5158#endif
5159
5160/* --------------------------------------------------------------------- */
5161/* REPLICATION METHODS: Replication Manager */
5162
5163#if (DBVER >= 45)
5164static PyObject*
5165DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5166 kwargs)
5167{
5168 int err;
5169 int nthreads, flags;
5170 static char* kwnames[] = {"nthreads","flags", NULL};
5171
5172 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5173 "ii:repmgr_start", kwnames, &nthreads, &flags))
5174 {
5175 return NULL;
5176 }
5177 CHECK_ENV_NOT_CLOSED(self);
5178 MYDB_BEGIN_ALLOW_THREADS;
5179 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5180 MYDB_END_ALLOW_THREADS;
5181 RETURN_IF_ERR();
5182 RETURN_NONE();
5183}
5184
5185static PyObject*
5186DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5187 kwargs)
5188{
5189 int err;
5190 char *host;
5191 int port;
5192 int flags = 0;
5193 static char* kwnames[] = {"host", "port", "flags", NULL};
5194
5195 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5196 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5197 {
5198 return NULL;
5199 }
5200 CHECK_ENV_NOT_CLOSED(self);
5201 MYDB_BEGIN_ALLOW_THREADS;
5202 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5203 MYDB_END_ALLOW_THREADS;
5204 RETURN_IF_ERR();
5205 RETURN_NONE();
5206}
5207
5208static PyObject*
5209DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5210 kwargs)
5211{
5212 int err;
5213 char *host;
5214 int port;
5215 int flags = 0;
5216 int eidp;
5217 static char* kwnames[] = {"host", "port", "flags", NULL};
5218
5219 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5220 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5221 {
5222 return NULL;
5223 }
5224 CHECK_ENV_NOT_CLOSED(self);
5225 MYDB_BEGIN_ALLOW_THREADS;
5226 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5227 MYDB_END_ALLOW_THREADS;
5228 RETURN_IF_ERR();
5229 return PyInt_FromLong(eidp);
5230}
5231
5232static PyObject*
5233DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5234{
5235 int err;
5236 int ack_policy;
5237
5238 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5239 {
5240 return NULL;
5241 }
5242 CHECK_ENV_NOT_CLOSED(self);
5243 MYDB_BEGIN_ALLOW_THREADS;
5244 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5245 MYDB_END_ALLOW_THREADS;
5246 RETURN_IF_ERR();
5247 RETURN_NONE();
5248}
5249
5250static PyObject*
5251DBEnv_repmgr_get_ack_policy(DBEnvObject* self, PyObject* args)
5252{
5253 int err;
5254 int ack_policy;
5255
5256 if (!PyArg_ParseTuple(args, ":repmgr_get_ack_policy"))
5257 {
5258 return NULL;
5259 }
5260 CHECK_ENV_NOT_CLOSED(self);
5261 MYDB_BEGIN_ALLOW_THREADS;
5262 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5263 MYDB_END_ALLOW_THREADS;
5264 RETURN_IF_ERR();
5265 return PyInt_FromLong(ack_policy);
5266}
5267
5268static PyObject*
5269DBEnv_repmgr_site_list(DBEnvObject* self, PyObject* args)
5270{
5271 int err;
5272 unsigned int countp;
5273 DB_REPMGR_SITE *listp;
5274 PyObject *stats, *key, *tuple;
5275
5276 if (!PyArg_ParseTuple(args, ":repmgr_site_list"))
5277 {
5278 return NULL;
5279 }
5280 CHECK_ENV_NOT_CLOSED(self);
5281 MYDB_BEGIN_ALLOW_THREADS;
5282 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5283 MYDB_END_ALLOW_THREADS;
5284 RETURN_IF_ERR();
5285
5286 stats=PyDict_New();
5287 if (stats == NULL) {
5288 free(listp);
5289 return NULL;
5290 }
5291
5292 for(;countp--;) {
5293 key=PyInt_FromLong(listp[countp].eid);
5294 if(!key) {
5295 Py_DECREF(stats);
5296 free(listp);
5297 return NULL;
5298 }
5299#if (PY_VERSION_HEX >= 0x02040000)
5300 tuple=Py_BuildValue("(sII)", listp[countp].host,
5301 listp[countp].port, listp[countp].status);
5302#else
5303 tuple=Py_BuildValue("(sii)", listp[countp].host,
5304 listp[countp].port, listp[countp].status);
5305#endif
5306 if(!tuple) {
5307 Py_DECREF(key);
5308 Py_DECREF(stats);
5309 free(listp);
5310 return NULL;
5311 }
5312 if(PyDict_SetItem(stats, key, tuple)) {
5313 Py_DECREF(key);
5314 Py_DECREF(tuple);
5315 Py_DECREF(stats);
5316 free(listp);
5317 return NULL;
5318 }
5319 }
5320 free(listp);
5321 return stats;
5322}
5323#endif
5324
5325#if (DBVER >= 46)
5326static PyObject*
5327DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5328{
5329 int err;
5330 int flags=0;
5331 static char* kwnames[] = { "flags", NULL };
5332
5333 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5334 kwnames, &flags))
5335 {
5336 return NULL;
5337 }
5338 CHECK_ENV_NOT_CLOSED(self);
5339 MYDB_BEGIN_ALLOW_THREADS;
5340 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5341 MYDB_END_ALLOW_THREADS;
5342 RETURN_IF_ERR();
5343 RETURN_NONE();
5344}
5345
5346static PyObject*
5347DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5348{
5349 int err;
5350 int flags=0;
5351 DB_REPMGR_STAT *statp;
5352 PyObject *stats;
5353 static char* kwnames[] = { "flags", NULL };
5354
5355 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5356 kwnames, &flags))
5357 {
5358 return NULL;
5359 }
5360 CHECK_ENV_NOT_CLOSED(self);
5361 MYDB_BEGIN_ALLOW_THREADS;
5362 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5363 MYDB_END_ALLOW_THREADS;
5364 RETURN_IF_ERR();
5365
5366 stats=PyDict_New();
5367 if (stats == NULL) {
5368 free(statp);
5369 return NULL;
5370 }
5371
5372#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5373
5374 MAKE_ENTRY(perm_failed);
5375 MAKE_ENTRY(msgs_queued);
5376 MAKE_ENTRY(msgs_dropped);
5377 MAKE_ENTRY(connection_drop);
5378 MAKE_ENTRY(connect_fail);
5379
5380#undef MAKE_ENTRY
5381
5382 free(statp);
5383 return stats;
5384}
5385#endif
5386
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005387
5388/* --------------------------------------------------------------------- */
5389/* DBTxn methods */
5390
5391
Jesus Ceaef9764f2008-05-13 18:45:46 +00005392static void _close_transaction_cursors(DBTxnObject* txn)
5393{
5394 PyObject *dummy;
5395
5396 while(txn->children_cursors) {
5397 PyErr_Warn(PyExc_RuntimeWarning,
5398 "Must close cursors before resolving a transaction.");
5399 dummy=DBC_close_internal(txn->children_cursors);
5400 Py_XDECREF(dummy);
5401 }
5402}
5403
5404static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5405{
5406 DBObject *db;
5407#if (DBVER >= 43)
5408 DBSequenceObject *dbs;
5409#endif
5410
5411 while (txn->children_dbs) {
5412 db=txn->children_dbs;
5413 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5414 if (txn->parent_txn) {
5415 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5416 db->txn=txn->parent_txn;
5417 } else {
5418 /* The db is already linked to its environment,
5419 ** so nothing to do.
5420 */
5421 db->txn=NULL;
5422 }
5423 }
5424
5425#if (DBVER >= 43)
5426 while (txn->children_sequences) {
5427 dbs=txn->children_sequences;
5428 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5429 if (txn->parent_txn) {
5430 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5431 dbs->txn=txn->parent_txn;
5432 } else {
5433 /* The sequence is already linked to its
5434 ** parent db. Nothing to do.
5435 */
5436 dbs->txn=NULL;
5437 }
5438 }
5439#endif
5440}
5441
5442
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005443static PyObject*
5444DBTxn_commit(DBTxnObject* self, PyObject* args)
5445{
5446 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005447 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005448
5449 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5450 return NULL;
5451
Jesus Ceaef9764f2008-05-13 18:45:46 +00005452 _close_transaction_cursors(self);
5453
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005454 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005455 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005456 "after txn_commit, txn_abort "
5457 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005458 PyErr_SetObject(DBError, t);
5459 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005460 return NULL;
5461 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005462 self->flag_prepare=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005463 txn = self->txn;
5464 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005465
5466 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5467
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005468 MYDB_BEGIN_ALLOW_THREADS;
5469#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005470 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005471#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005472 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005473#endif
5474 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005475
5476 _promote_transaction_dbs_and_sequences(self);
5477
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005478 RETURN_IF_ERR();
5479 RETURN_NONE();
5480}
5481
5482static PyObject*
5483DBTxn_prepare(DBTxnObject* self, PyObject* args)
5484{
5485#if (DBVER >= 33)
5486 int err;
5487 char* gid=NULL;
5488 int gid_size=0;
5489
5490 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
5491 return NULL;
5492
5493 if (gid_size != DB_XIDDATASIZE) {
5494 PyErr_SetString(PyExc_TypeError,
5495 "gid must be DB_XIDDATASIZE bytes long");
5496 return NULL;
5497 }
5498
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005499 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005500 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005501 "after txn_commit, txn_abort "
5502 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005503 PyErr_SetObject(DBError, t);
5504 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005505 return NULL;
5506 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005507 self->flag_prepare=1; /* Prepare state */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005508 MYDB_BEGIN_ALLOW_THREADS;
5509#if (DBVER >= 40)
5510 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
5511#else
5512 err = txn_prepare(self->txn, (u_int8_t*)gid);
5513#endif
5514 MYDB_END_ALLOW_THREADS;
5515 RETURN_IF_ERR();
5516 RETURN_NONE();
5517#else
5518 int err;
5519
5520 if (!PyArg_ParseTuple(args, ":prepare"))
5521 return NULL;
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 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005531 MYDB_BEGIN_ALLOW_THREADS;
5532 err = txn_prepare(self->txn);
5533 MYDB_END_ALLOW_THREADS;
5534 RETURN_IF_ERR();
5535 RETURN_NONE();
5536#endif
5537}
5538
5539
5540static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005541DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005542{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005543 PyObject *dummy;
5544 int err=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005545 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005546
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005547 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005548 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005549 "after txn_commit, txn_abort "
5550 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005551 PyErr_SetObject(DBError, t);
5552 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005553 return NULL;
5554 }
5555 txn = self->txn;
5556 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005557
5558 _close_transaction_cursors(self);
5559#if (DBVER >= 43)
5560 while (self->children_sequences) {
5561 dummy=DBSequence_close_internal(self->children_sequences,0,0);
5562 Py_XDECREF(dummy);
5563 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005564#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005565 while (self->children_dbs) {
5566 dummy=DB_close_internal(self->children_dbs,0);
5567 Py_XDECREF(dummy);
5568 }
5569
5570 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5571
5572 MYDB_BEGIN_ALLOW_THREADS;
5573 if (discard) {
5574 assert(!self->flag_prepare);
5575#if (DBVER >= 40)
5576 err = txn->discard(txn,0);
5577#else
5578 err = txn_discard(txn);
5579#endif
5580 } else {
5581 /*
5582 ** If the transaction is in the "prepare" or "recover" state,
5583 ** we better do not implicitly abort it.
5584 */
5585 if (!self->flag_prepare) {
5586#if (DBVER >= 40)
5587 err = txn->abort(txn);
5588#else
5589 err = txn_abort(txn);
5590#endif
5591 }
5592 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005593 MYDB_END_ALLOW_THREADS;
5594 RETURN_IF_ERR();
5595 RETURN_NONE();
5596}
5597
Jesus Ceaef9764f2008-05-13 18:45:46 +00005598static PyObject*
5599DBTxn_abort(DBTxnObject* self, PyObject* args)
5600{
5601 if (!PyArg_ParseTuple(args, ":abort"))
5602 return NULL;
5603
5604 self->flag_prepare=0;
5605 _close_transaction_cursors(self);
5606
5607 return DBTxn_abort_discard_internal(self,0);
5608}
5609
5610static PyObject*
5611DBTxn_discard(DBTxnObject* self, PyObject* args)
5612{
5613 if (!PyArg_ParseTuple(args, ":discard"))
5614 return NULL;
5615
5616 self->flag_prepare=0;
5617 _close_transaction_cursors(self);
5618
5619 return DBTxn_abort_discard_internal(self,1);
5620}
5621
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005622
5623static PyObject*
5624DBTxn_id(DBTxnObject* self, PyObject* args)
5625{
5626 int id;
5627
5628 if (!PyArg_ParseTuple(args, ":id"))
5629 return NULL;
5630
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005631 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005632 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005633 "after txn_commit, txn_abort "
5634 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005635 PyErr_SetObject(DBError, t);
5636 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005637 return NULL;
5638 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005639 MYDB_BEGIN_ALLOW_THREADS;
5640#if (DBVER >= 40)
5641 id = self->txn->id(self->txn);
5642#else
5643 id = txn_id(self->txn);
5644#endif
5645 MYDB_END_ALLOW_THREADS;
5646 return PyInt_FromLong(id);
5647}
5648
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005649#if (DBVER >= 43)
5650/* --------------------------------------------------------------------- */
5651/* DBSequence methods */
5652
5653
5654static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005655DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005656{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005657 int err=0;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005658
Jesus Ceaef9764f2008-05-13 18:45:46 +00005659 if (self->sequence!=NULL) {
5660 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5661 if (self->txn) {
5662 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
5663 self->txn=NULL;
5664 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005665
Jesus Ceaef9764f2008-05-13 18:45:46 +00005666 if (!do_not_close) {
5667 MYDB_BEGIN_ALLOW_THREADS
5668 err = self->sequence->close(self->sequence, flags);
5669 MYDB_END_ALLOW_THREADS
5670 }
5671 self->sequence = NULL;
5672
5673 RETURN_IF_ERR();
5674 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005675
5676 RETURN_NONE();
5677}
5678
5679static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005680DBSequence_close(DBSequenceObject* self, PyObject* args)
5681{
5682 int flags=0;
5683 if (!PyArg_ParseTuple(args,"|i:close", &flags))
5684 return NULL;
5685
5686 return DBSequence_close_internal(self,flags,0);
5687}
5688
5689static PyObject*
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005690DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5691{
5692 int err, flags = 0;
5693 int delta = 1;
5694 db_seq_t value;
5695 PyObject *txnobj = NULL;
5696 DB_TXN *txn = NULL;
5697 static char* kwnames[] = {"delta", "txn", "flags", NULL };
5698 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
5699 return NULL;
5700 CHECK_SEQUENCE_NOT_CLOSED(self)
5701
5702 if (!checkTxnObj(txnobj, &txn))
5703 return NULL;
5704
5705 MYDB_BEGIN_ALLOW_THREADS
5706 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
5707 MYDB_END_ALLOW_THREADS
5708
5709 RETURN_IF_ERR();
5710 return PyLong_FromLongLong(value);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005711}
5712
5713static PyObject*
5714DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
5715{
5716 if (!PyArg_ParseTuple(args,":get_dbp"))
5717 return NULL;
5718 CHECK_SEQUENCE_NOT_CLOSED(self)
5719 Py_INCREF(self->mydb);
5720 return (PyObject* )self->mydb;
5721}
5722
5723static PyObject*
5724DBSequence_get_key(DBSequenceObject* self, PyObject* args)
5725{
5726 int err;
5727 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00005728 PyObject *retval = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005729
5730 if (!PyArg_ParseTuple(args,":get_key"))
5731 return NULL;
5732
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005733 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005734 CHECK_SEQUENCE_NOT_CLOSED(self)
5735 MYDB_BEGIN_ALLOW_THREADS
5736 err = self->sequence->get_key(self->sequence, &key);
5737 MYDB_END_ALLOW_THREADS
5738
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005739 if (!err)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005740 retval = Build_PyString(key.data, key.size);
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005741
5742 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005743 RETURN_IF_ERR();
5744
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005745 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005746}
5747
5748static PyObject*
5749DBSequence_init_value(DBSequenceObject* self, PyObject* args)
5750{
5751 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005752 PY_LONG_LONG value;
5753 db_seq_t value2;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005754 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005755 return NULL;
5756 CHECK_SEQUENCE_NOT_CLOSED(self)
5757
Jesus Ceaef9764f2008-05-13 18:45:46 +00005758 value2=value; /* If truncation, compiler should show a warning */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005759 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005760 err = self->sequence->initial_value(self->sequence, value2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005761 MYDB_END_ALLOW_THREADS
5762
5763 RETURN_IF_ERR();
5764
5765 RETURN_NONE();
5766}
5767
5768static PyObject*
5769DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5770{
5771 int err, flags = 0;
5772 PyObject* keyobj;
5773 PyObject *txnobj = NULL;
5774 DB_TXN *txn = NULL;
5775 DBT key;
5776
5777 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005778 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005779 return NULL;
5780
5781 if (!checkTxnObj(txnobj, &txn))
5782 return NULL;
5783
5784 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
5785 return NULL;
5786
5787 MYDB_BEGIN_ALLOW_THREADS
5788 err = self->sequence->open(self->sequence, txn, &key, flags);
5789 MYDB_END_ALLOW_THREADS
5790
5791 CLEAR_DBT(key);
5792 RETURN_IF_ERR();
5793
Jesus Ceaef9764f2008-05-13 18:45:46 +00005794 if (txn) {
5795 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
5796 self->txn=(DBTxnObject *)txnobj;
5797 }
5798
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005799 RETURN_NONE();
5800}
5801
5802static PyObject*
5803DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5804{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005805 PyObject *dummy;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005806 int err, flags = 0;
5807 PyObject *txnobj = NULL;
5808 DB_TXN *txn = NULL;
5809
5810 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005811 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005812 return NULL;
5813
5814 if (!checkTxnObj(txnobj, &txn))
5815 return NULL;
5816
5817 CHECK_SEQUENCE_NOT_CLOSED(self)
5818
5819 MYDB_BEGIN_ALLOW_THREADS
5820 err = self->sequence->remove(self->sequence, txn, flags);
5821 MYDB_END_ALLOW_THREADS
5822
Jesus Ceaef9764f2008-05-13 18:45:46 +00005823 dummy=DBSequence_close_internal(self,flags,1);
5824 Py_XDECREF(dummy);
5825
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005826 RETURN_IF_ERR();
5827 RETURN_NONE();
5828}
5829
5830static PyObject*
5831DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
5832{
5833 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005834 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005835 return NULL;
5836 CHECK_SEQUENCE_NOT_CLOSED(self)
5837
5838 MYDB_BEGIN_ALLOW_THREADS
5839 err = self->sequence->set_cachesize(self->sequence, size);
5840 MYDB_END_ALLOW_THREADS
5841
5842 RETURN_IF_ERR();
5843 RETURN_NONE();
5844}
5845
5846static PyObject*
5847DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5848{
5849 int err, size;
5850 if (!PyArg_ParseTuple(args,":get_cachesize"))
5851 return NULL;
5852 CHECK_SEQUENCE_NOT_CLOSED(self)
5853
5854 MYDB_BEGIN_ALLOW_THREADS
5855 err = self->sequence->get_cachesize(self->sequence, &size);
5856 MYDB_END_ALLOW_THREADS
5857
5858 RETURN_IF_ERR();
5859 return PyInt_FromLong(size);
5860}
5861
5862static PyObject*
5863DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5864{
5865 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005866 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005867 return NULL;
5868 CHECK_SEQUENCE_NOT_CLOSED(self)
5869
5870 MYDB_BEGIN_ALLOW_THREADS
5871 err = self->sequence->set_flags(self->sequence, flags);
5872 MYDB_END_ALLOW_THREADS
5873
5874 RETURN_IF_ERR();
5875 RETURN_NONE();
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005876}
5877
5878static PyObject*
5879DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5880{
5881 unsigned int flags;
5882 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005883 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005884 return NULL;
5885 CHECK_SEQUENCE_NOT_CLOSED(self)
5886
5887 MYDB_BEGIN_ALLOW_THREADS
5888 err = self->sequence->get_flags(self->sequence, &flags);
5889 MYDB_END_ALLOW_THREADS
5890
5891 RETURN_IF_ERR();
5892 return PyInt_FromLong((int)flags);
5893}
5894
5895static PyObject*
5896DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5897{
5898 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005899 PY_LONG_LONG min, max;
5900 db_seq_t min2, max2;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005901 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005902 return NULL;
5903 CHECK_SEQUENCE_NOT_CLOSED(self)
5904
Jesus Ceaef9764f2008-05-13 18:45:46 +00005905 min2=min; /* If truncation, compiler should show a warning */
5906 max2=max;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005907 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005908 err = self->sequence->set_range(self->sequence, min2, max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005909 MYDB_END_ALLOW_THREADS
5910
5911 RETURN_IF_ERR();
5912 RETURN_NONE();
5913}
5914
5915static PyObject*
5916DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5917{
5918 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005919 PY_LONG_LONG min, max;
5920 db_seq_t min2, max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005921 if (!PyArg_ParseTuple(args,":get_range"))
5922 return NULL;
5923 CHECK_SEQUENCE_NOT_CLOSED(self)
5924
5925 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005926 err = self->sequence->get_range(self->sequence, &min2, &max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005927 MYDB_END_ALLOW_THREADS
5928
5929 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00005930 min=min2; /* If truncation, compiler should show a warning */
5931 max=max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005932 return Py_BuildValue("(LL)", min, max);
5933}
5934
5935static PyObject*
5936DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5937{
5938 int err, flags = 0;
5939 DB_SEQUENCE_STAT* sp = NULL;
5940 PyObject* dict_stat;
5941 static char* kwnames[] = {"flags", NULL };
5942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5943 return NULL;
5944 CHECK_SEQUENCE_NOT_CLOSED(self);
5945
5946 MYDB_BEGIN_ALLOW_THREADS;
5947 err = self->sequence->stat(self->sequence, &sp, flags);
5948 MYDB_END_ALLOW_THREADS;
5949 RETURN_IF_ERR();
5950
5951 if ((dict_stat = PyDict_New()) == NULL) {
5952 free(sp);
5953 return NULL;
5954 }
5955
5956
5957#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5958#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5959
5960 MAKE_INT_ENTRY(wait);
5961 MAKE_INT_ENTRY(nowait);
5962 MAKE_LONG_LONG_ENTRY(current);
5963 MAKE_LONG_LONG_ENTRY(value);
5964 MAKE_LONG_LONG_ENTRY(last_value);
5965 MAKE_LONG_LONG_ENTRY(min);
5966 MAKE_LONG_LONG_ENTRY(max);
5967 MAKE_INT_ENTRY(cache_size);
5968 MAKE_INT_ENTRY(flags);
5969
5970#undef MAKE_INT_ENTRY
5971#undef MAKE_LONG_LONG_ENTRY
5972
5973 free(sp);
5974 return dict_stat;
5975}
5976#endif
5977
5978
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005979/* --------------------------------------------------------------------- */
5980/* Method definition tables and type objects */
5981
5982static PyMethodDef DB_methods[] = {
5983 {"append", (PyCFunction)DB_append, METH_VARARGS},
5984#if (DBVER >= 33)
5985 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5986#endif
5987 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005988 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5989 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005990 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5991 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5992 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5993 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005994#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00005995 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00005996#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005997 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5998 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5999 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
6000 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
6001 {"join", (PyCFunction)DB_join, METH_VARARGS},
6002 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
6003 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
6004 {"items", (PyCFunction)DB_items, METH_VARARGS},
6005 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6006 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6007 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6008 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6009 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6010 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006011#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00006012 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006013#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006014 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006015#if (DBVER >= 41)
6016 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6017#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006018 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6019 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6020 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6021 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6022 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6023 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6024 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6025 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6026 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006027 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006028 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006029 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
6030#if (DBVER >= 33)
6031 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
6032#endif
6033 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
6034 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6035 {"values", (PyCFunction)DB_values, METH_VARARGS},
6036 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6037 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6038 {NULL, NULL} /* sentinel */
6039};
6040
6041
6042static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00006043 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006044 (binaryfunc)DB_subscript, /*mp_subscript*/
6045 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6046};
6047
6048
6049static PyMethodDef DBCursor_methods[] = {
6050 {"close", (PyCFunction)DBC_close, METH_VARARGS},
6051 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6052 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6053 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6054 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6055 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6056 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006057#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00006058 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006059#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006060 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
6061 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6062 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6063 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6064 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6065 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6066 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6067 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00006068 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00006069 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006070 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6071 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6072 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6073 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6074 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6075 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6076 {NULL, NULL} /* sentinel */
6077};
6078
6079
6080static PyMethodDef DBEnv_methods[] = {
6081 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6082 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6083 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006084#if (DBVER >= 41)
6085 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6086 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6087 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6088#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00006089#if (DBVER >= 40)
6090 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
6091#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00006092 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006093 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6094 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006095 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006096 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6097 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6098 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006099#if (DBVER >= 42)
6100 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_VARARGS},
6101#endif
Neal Norwitz84562352005-10-20 04:30:15 +00006102#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00006103 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006104#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006105 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006106#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006107 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006108#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006109 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6110 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6111 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006112 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6113 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6114 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6115 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6116 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6117 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00006118 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006119 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6120 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
6121 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Gregory P. Smithac11e022007-11-05 02:56:31 +00006122#if (DBVER >= 40)
6123 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
6124#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006125 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6126 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6127 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006128#if (DBVER >= 40)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006129 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_VARARGS},
6130#endif
6131#if (DBVER >= 40)
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006132 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
6133#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00006134#if (DBVER >= 44)
6135 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6136#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006137 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006138#if (DBVER >= 40)
6139 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_VARARGS},
6140#endif
6141#if (DBVER >= 40)
6142 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6143#if (DBVER >= 42)
6144 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6145#endif
6146#endif
6147#if (DBVER >= 45)
6148 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_VARARGS},
6149#endif
6150#if (DBVER >= 45)
6151 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
6152 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_VARARGS},
6153 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
6154 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_VARARGS},
6155 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6156 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6157#endif
6158#if (DBVER >= 45)
6159 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6160 METH_VARARGS|METH_KEYWORDS},
6161 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6162 METH_VARARGS|METH_KEYWORDS},
6163 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6164 METH_VARARGS|METH_KEYWORDS},
6165 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6166 METH_VARARGS},
6167 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
6168 METH_VARARGS},
6169 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
6170 METH_VARARGS},
6171#endif
6172#if (DBVER >= 46)
6173 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6174 METH_VARARGS|METH_KEYWORDS},
6175 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6176 METH_VARARGS|METH_KEYWORDS},
6177#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006178 {NULL, NULL} /* sentinel */
6179};
6180
6181
6182static PyMethodDef DBTxn_methods[] = {
6183 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6184 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006185 {"discard", (PyCFunction)DBTxn_discard, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006186 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
6187 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
6188 {NULL, NULL} /* sentinel */
6189};
6190
6191
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006192#if (DBVER >= 43)
6193static PyMethodDef DBSequence_methods[] = {
6194 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6195 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
6196 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
6197 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006198 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6199 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6200 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6201 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
6202 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
6203 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
6204 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
6205 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
6206 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
6207 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6208 {NULL, NULL} /* sentinel */
6209};
6210#endif
6211
6212
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006213static PyObject*
6214DB_getattr(DBObject* self, char *name)
6215{
6216 return Py_FindMethod(DB_methods, (PyObject* )self, name);
6217}
6218
6219
6220static PyObject*
6221DBEnv_getattr(DBEnvObject* self, char *name)
6222{
6223 if (!strcmp(name, "db_home")) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00006224 const char *home = NULL;
6225 CHECK_ENV_NOT_CLOSED(self);
6226#if (DBVER >= 42)
6227 self->db_env->get_home(self->db_env, &home);
6228#else
6229 home=self->db_env->db_home;
6230#endif
6231 if (home == NULL) {
6232 RETURN_NONE();
6233 }
6234 return PyString_FromString(home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006235 }
6236
6237 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
6238}
6239
6240
6241static PyObject*
6242DBCursor_getattr(DBCursorObject* self, char *name)
6243{
6244 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
6245}
6246
6247static PyObject*
6248DBTxn_getattr(DBTxnObject* self, char *name)
6249{
6250 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
6251}
6252
6253static PyObject*
6254DBLock_getattr(DBLockObject* self, char *name)
6255{
6256 return NULL;
6257}
6258
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006259#if (DBVER >= 43)
6260static PyObject*
6261DBSequence_getattr(DBSequenceObject* self, char *name)
6262{
6263 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
6264}
6265#endif
6266
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006267statichere PyTypeObject DB_Type = {
6268 PyObject_HEAD_INIT(NULL)
6269 0, /*ob_size*/
6270 "DB", /*tp_name*/
6271 sizeof(DBObject), /*tp_basicsize*/
6272 0, /*tp_itemsize*/
6273 /* methods */
6274 (destructor)DB_dealloc, /*tp_dealloc*/
6275 0, /*tp_print*/
6276 (getattrfunc)DB_getattr, /*tp_getattr*/
6277 0, /*tp_setattr*/
6278 0, /*tp_compare*/
6279 0, /*tp_repr*/
6280 0, /*tp_as_number*/
6281 0, /*tp_as_sequence*/
6282 &DB_mapping,/*tp_as_mapping*/
6283 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006284 0, /* tp_call */
6285 0, /* tp_str */
6286 0, /* tp_getattro */
6287 0, /* tp_setattro */
6288 0, /* tp_as_buffer */
6289 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6290 0, /* tp_doc */
6291 0, /* tp_traverse */
6292 0, /* tp_clear */
6293 0, /* tp_richcompare */
6294 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006295};
6296
6297
6298statichere PyTypeObject DBCursor_Type = {
6299 PyObject_HEAD_INIT(NULL)
6300 0, /*ob_size*/
6301 "DBCursor", /*tp_name*/
6302 sizeof(DBCursorObject), /*tp_basicsize*/
6303 0, /*tp_itemsize*/
6304 /* methods */
6305 (destructor)DBCursor_dealloc,/*tp_dealloc*/
6306 0, /*tp_print*/
6307 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
6308 0, /*tp_setattr*/
6309 0, /*tp_compare*/
6310 0, /*tp_repr*/
6311 0, /*tp_as_number*/
6312 0, /*tp_as_sequence*/
6313 0, /*tp_as_mapping*/
6314 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00006315 0, /* tp_call */
6316 0, /* tp_str */
6317 0, /* tp_getattro */
6318 0, /* tp_setattro */
6319 0, /* tp_as_buffer */
6320 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6321 0, /* tp_doc */
6322 0, /* tp_traverse */
6323 0, /* tp_clear */
6324 0, /* tp_richcompare */
6325 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006326};
6327
6328
6329statichere PyTypeObject DBEnv_Type = {
6330 PyObject_HEAD_INIT(NULL)
6331 0, /*ob_size*/
6332 "DBEnv", /*tp_name*/
6333 sizeof(DBEnvObject), /*tp_basicsize*/
6334 0, /*tp_itemsize*/
6335 /* methods */
6336 (destructor)DBEnv_dealloc, /*tp_dealloc*/
6337 0, /*tp_print*/
6338 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
6339 0, /*tp_setattr*/
6340 0, /*tp_compare*/
6341 0, /*tp_repr*/
6342 0, /*tp_as_number*/
6343 0, /*tp_as_sequence*/
6344 0, /*tp_as_mapping*/
6345 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006346 0, /* tp_call */
6347 0, /* tp_str */
6348 0, /* tp_getattro */
6349 0, /* tp_setattro */
6350 0, /* tp_as_buffer */
6351 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6352 0, /* tp_doc */
6353 0, /* tp_traverse */
6354 0, /* tp_clear */
6355 0, /* tp_richcompare */
6356 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006357};
6358
6359statichere PyTypeObject DBTxn_Type = {
6360 PyObject_HEAD_INIT(NULL)
6361 0, /*ob_size*/
6362 "DBTxn", /*tp_name*/
6363 sizeof(DBTxnObject), /*tp_basicsize*/
6364 0, /*tp_itemsize*/
6365 /* methods */
6366 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6367 0, /*tp_print*/
6368 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
6369 0, /*tp_setattr*/
6370 0, /*tp_compare*/
6371 0, /*tp_repr*/
6372 0, /*tp_as_number*/
6373 0, /*tp_as_sequence*/
6374 0, /*tp_as_mapping*/
6375 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006376 0, /* tp_call */
6377 0, /* tp_str */
6378 0, /* tp_getattro */
6379 0, /* tp_setattro */
6380 0, /* tp_as_buffer */
6381 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6382 0, /* tp_doc */
6383 0, /* tp_traverse */
6384 0, /* tp_clear */
6385 0, /* tp_richcompare */
6386 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006387};
6388
6389
6390statichere PyTypeObject DBLock_Type = {
6391 PyObject_HEAD_INIT(NULL)
6392 0, /*ob_size*/
6393 "DBLock", /*tp_name*/
6394 sizeof(DBLockObject), /*tp_basicsize*/
6395 0, /*tp_itemsize*/
6396 /* methods */
6397 (destructor)DBLock_dealloc, /*tp_dealloc*/
6398 0, /*tp_print*/
6399 (getattrfunc)DBLock_getattr, /*tp_getattr*/
6400 0, /*tp_setattr*/
6401 0, /*tp_compare*/
6402 0, /*tp_repr*/
6403 0, /*tp_as_number*/
6404 0, /*tp_as_sequence*/
6405 0, /*tp_as_mapping*/
6406 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006407 0, /* tp_call */
6408 0, /* tp_str */
6409 0, /* tp_getattro */
6410 0, /* tp_setattro */
6411 0, /* tp_as_buffer */
6412 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6413 0, /* tp_doc */
6414 0, /* tp_traverse */
6415 0, /* tp_clear */
6416 0, /* tp_richcompare */
6417 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006418};
6419
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006420#if (DBVER >= 43)
6421statichere PyTypeObject DBSequence_Type = {
6422 PyObject_HEAD_INIT(NULL)
6423 0, /*ob_size*/
6424 "DBSequence", /*tp_name*/
6425 sizeof(DBSequenceObject), /*tp_basicsize*/
6426 0, /*tp_itemsize*/
6427 /* methods */
6428 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6429 0, /*tp_print*/
6430 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
6431 0, /*tp_setattr*/
6432 0, /*tp_compare*/
6433 0, /*tp_repr*/
6434 0, /*tp_as_number*/
6435 0, /*tp_as_sequence*/
6436 0, /*tp_as_mapping*/
6437 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006438 0, /* tp_call */
6439 0, /* tp_str */
6440 0, /* tp_getattro */
6441 0, /* tp_setattro */
6442 0, /* tp_as_buffer */
6443 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6444 0, /* tp_doc */
6445 0, /* tp_traverse */
6446 0, /* tp_clear */
6447 0, /* tp_richcompare */
6448 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006449};
6450#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006451
6452/* --------------------------------------------------------------------- */
6453/* Module-level functions */
6454
6455static PyObject*
6456DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6457{
6458 PyObject* dbenvobj = NULL;
6459 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00006460 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006461
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006462 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6463 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006464 return NULL;
6465 if (dbenvobj == Py_None)
6466 dbenvobj = NULL;
6467 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6468 makeTypeError("DBEnv", dbenvobj);
6469 return NULL;
6470 }
6471
6472 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6473}
6474
6475
6476static PyObject*
6477DBEnv_construct(PyObject* self, PyObject* args)
6478{
6479 int flags = 0;
6480 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6481 return (PyObject* )newDBEnvObject(flags);
6482}
6483
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006484#if (DBVER >= 43)
6485static PyObject*
6486DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6487{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006488 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006489 int flags = 0;
6490 static char* kwnames[] = { "db", "flags", NULL};
6491
6492 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6493 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006494 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006495 makeTypeError("DB", dbobj);
6496 return NULL;
6497 }
6498 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6499}
6500#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006501
6502static char bsddb_version_doc[] =
6503"Returns a tuple of major, minor, and patch release numbers of the\n\
6504underlying DB library.";
6505
6506static PyObject*
6507bsddb_version(PyObject* self, PyObject* args)
6508{
6509 int major, minor, patch;
6510
6511 if (!PyArg_ParseTuple(args, ":version"))
6512 return NULL;
6513 db_version(&major, &minor, &patch);
6514 return Py_BuildValue("(iii)", major, minor, patch);
6515}
6516
6517
6518/* List of functions defined in the module */
6519
6520static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006521 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6522 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
6523#if (DBVER >= 43)
6524 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
6525#endif
6526 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006527 {NULL, NULL} /* sentinel */
6528};
6529
Gregory P. Smith39250532007-10-09 06:02:21 +00006530/* API structure */
6531static BSDDB_api bsddb_api;
6532
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006533
6534/* --------------------------------------------------------------------- */
6535/* Module initialization */
6536
6537
6538/* Convenience routine to export an integer value.
6539 * Errors are silently ignored, for better or for worse...
6540 */
6541#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
6542
Gregory P. Smith41631e82003-09-21 00:08:14 +00006543#define MODULE_NAME_MAX_LEN 11
6544static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006545
6546DL_EXPORT(void) init_bsddb(void)
6547{
6548 PyObject* m;
6549 PyObject* d;
6550 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
6551 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
6552 PyObject* cvsid_s = PyString_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00006553 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006554
6555 /* Initialize the type of the new type objects here; doing it here
6556 is required for portability to Windows without requiring C++. */
Christian Heimese93237d2007-12-19 02:37:44 +00006557 Py_TYPE(&DB_Type) = &PyType_Type;
6558 Py_TYPE(&DBCursor_Type) = &PyType_Type;
6559 Py_TYPE(&DBEnv_Type) = &PyType_Type;
6560 Py_TYPE(&DBTxn_Type) = &PyType_Type;
6561 Py_TYPE(&DBLock_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006562#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +00006563 Py_TYPE(&DBSequence_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006564#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006565
6566
Mark Hammonda69d4092003-04-22 23:13:27 +00006567#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006568 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00006569 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006570#endif
6571
6572 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00006573 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00006574 if (m == NULL)
6575 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006576
6577 /* Add some symbolic constants to the module */
6578 d = PyModule_GetDict(m);
6579 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
6580 PyDict_SetItemString(d, "cvsid", cvsid_s);
6581 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
6582 Py_DECREF(pybsddb_version_s);
6583 pybsddb_version_s = NULL;
6584 Py_DECREF(cvsid_s);
6585 cvsid_s = NULL;
6586 Py_DECREF(db_version_s);
6587 db_version_s = NULL;
6588
6589 ADD_INT(d, DB_VERSION_MAJOR);
6590 ADD_INT(d, DB_VERSION_MINOR);
6591 ADD_INT(d, DB_VERSION_PATCH);
6592
6593 ADD_INT(d, DB_MAX_PAGES);
6594 ADD_INT(d, DB_MAX_RECORDS);
6595
Gregory P. Smith41631e82003-09-21 00:08:14 +00006596#if (DBVER >= 42)
6597 ADD_INT(d, DB_RPCCLIENT);
6598#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006599 ADD_INT(d, DB_CLIENT);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006600 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
Gregory P. Smith41631e82003-09-21 00:08:14 +00006601 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
6602#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006603 ADD_INT(d, DB_XA_CREATE);
6604
6605 ADD_INT(d, DB_CREATE);
6606 ADD_INT(d, DB_NOMMAP);
6607 ADD_INT(d, DB_THREAD);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006608#if (DBVER >= 45)
6609 ADD_INT(d, DB_MULTIVERSION);
6610#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006611
6612 ADD_INT(d, DB_FORCE);
6613 ADD_INT(d, DB_INIT_CDB);
6614 ADD_INT(d, DB_INIT_LOCK);
6615 ADD_INT(d, DB_INIT_LOG);
6616 ADD_INT(d, DB_INIT_MPOOL);
6617 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006618 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006619
Jesus Ceaef9764f2008-05-13 18:45:46 +00006620#if (DBVER >= 40)
6621 ADD_INT(d, DB_XIDDATASIZE);
6622#endif
6623
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006624 ADD_INT(d, DB_RECOVER);
6625 ADD_INT(d, DB_RECOVER_FATAL);
6626 ADD_INT(d, DB_TXN_NOSYNC);
6627 ADD_INT(d, DB_USE_ENVIRON);
6628 ADD_INT(d, DB_USE_ENVIRON_ROOT);
6629
6630 ADD_INT(d, DB_LOCKDOWN);
6631 ADD_INT(d, DB_PRIVATE);
6632 ADD_INT(d, DB_SYSTEM_MEM);
6633
6634 ADD_INT(d, DB_TXN_SYNC);
6635 ADD_INT(d, DB_TXN_NOWAIT);
6636
6637 ADD_INT(d, DB_EXCL);
6638 ADD_INT(d, DB_FCNTL_LOCKING);
6639 ADD_INT(d, DB_ODDFILESIZE);
6640 ADD_INT(d, DB_RDWRMASTER);
6641 ADD_INT(d, DB_RDONLY);
6642 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006643 ADD_INT(d, DB_EXTENT);
6644 ADD_INT(d, DB_CDB_ALLDB);
6645 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006646 ADD_INT(d, DB_UPGRADE);
6647
6648 ADD_INT(d, DB_AGGRESSIVE);
6649 ADD_INT(d, DB_NOORDERCHK);
6650 ADD_INT(d, DB_ORDERCHKONLY);
6651 ADD_INT(d, DB_PR_PAGE);
6652#if ! (DBVER >= 33)
6653 ADD_INT(d, DB_VRFY_FLAGMASK);
6654 ADD_INT(d, DB_PR_HEADERS);
6655#endif
6656 ADD_INT(d, DB_PR_RECOVERYTEST);
6657 ADD_INT(d, DB_SALVAGE);
6658
6659 ADD_INT(d, DB_LOCK_NORUN);
6660 ADD_INT(d, DB_LOCK_DEFAULT);
6661 ADD_INT(d, DB_LOCK_OLDEST);
6662 ADD_INT(d, DB_LOCK_RANDOM);
6663 ADD_INT(d, DB_LOCK_YOUNGEST);
6664#if (DBVER >= 33)
6665 ADD_INT(d, DB_LOCK_MAXLOCKS);
6666 ADD_INT(d, DB_LOCK_MINLOCKS);
6667 ADD_INT(d, DB_LOCK_MINWRITE);
6668#endif
6669
Jesus Ceaef9764f2008-05-13 18:45:46 +00006670#if (DBVER >= 40)
6671 ADD_INT(d, DB_LOCK_EXPIRE);
6672#endif
6673#if (DBVER >= 43)
6674 ADD_INT(d, DB_LOCK_MAXWRITE);
6675#endif
6676
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006677
6678#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006679 /* docs say to use zero instead */
6680 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006681#else
6682 ADD_INT(d, DB_LOCK_CONFLICT);
6683#endif
6684
6685 ADD_INT(d, DB_LOCK_DUMP);
6686 ADD_INT(d, DB_LOCK_GET);
6687 ADD_INT(d, DB_LOCK_INHERIT);
6688 ADD_INT(d, DB_LOCK_PUT);
6689 ADD_INT(d, DB_LOCK_PUT_ALL);
6690 ADD_INT(d, DB_LOCK_PUT_OBJ);
6691
6692 ADD_INT(d, DB_LOCK_NG);
6693 ADD_INT(d, DB_LOCK_READ);
6694 ADD_INT(d, DB_LOCK_WRITE);
6695 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006696 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006697 ADD_INT(d, DB_LOCK_IWRITE);
6698 ADD_INT(d, DB_LOCK_IREAD);
6699 ADD_INT(d, DB_LOCK_IWR);
6700#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00006701#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006702 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00006703#else
6704 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
6705#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006706 ADD_INT(d, DB_LOCK_WWRITE);
6707#endif
6708
6709 ADD_INT(d, DB_LOCK_RECORD);
6710 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006711 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006712#if (DBVER >= 33)
6713 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
6714#endif
6715
6716 ADD_INT(d, DB_LOCK_NOWAIT);
6717 ADD_INT(d, DB_LOCK_RECORD);
6718 ADD_INT(d, DB_LOCK_UPGRADE);
6719
6720#if (DBVER >= 33)
6721 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006722#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006723 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006724#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006725 ADD_INT(d, DB_LSTAT_FREE);
6726 ADD_INT(d, DB_LSTAT_HELD);
6727#if (DBVER == 33)
6728 ADD_INT(d, DB_LSTAT_NOGRANT);
6729#endif
6730 ADD_INT(d, DB_LSTAT_PENDING);
6731 ADD_INT(d, DB_LSTAT_WAITING);
6732#endif
6733
6734 ADD_INT(d, DB_ARCH_ABS);
6735 ADD_INT(d, DB_ARCH_DATA);
6736 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00006737#if (DBVER >= 42)
6738 ADD_INT(d, DB_ARCH_REMOVE);
6739#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006740
6741 ADD_INT(d, DB_BTREE);
6742 ADD_INT(d, DB_HASH);
6743 ADD_INT(d, DB_RECNO);
6744 ADD_INT(d, DB_QUEUE);
6745 ADD_INT(d, DB_UNKNOWN);
6746
6747 ADD_INT(d, DB_DUP);
6748 ADD_INT(d, DB_DUPSORT);
6749 ADD_INT(d, DB_RECNUM);
6750 ADD_INT(d, DB_RENUMBER);
6751 ADD_INT(d, DB_REVSPLITOFF);
6752 ADD_INT(d, DB_SNAPSHOT);
6753
6754 ADD_INT(d, DB_JOIN_NOSORT);
6755
6756 ADD_INT(d, DB_AFTER);
6757 ADD_INT(d, DB_APPEND);
6758 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006759#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006760 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006761#endif
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006762#if (DBVER >= 41)
6763 _addIntToDict(d, "DB_CHECKPOINT", 0);
6764#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006765 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006766 ADD_INT(d, DB_CURLSN);
6767#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00006768#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006769 ADD_INT(d, DB_COMMIT);
6770#endif
6771 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006772 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006773 ADD_INT(d, DB_CURRENT);
6774#if (DBVER >= 33)
6775 ADD_INT(d, DB_FAST_STAT);
6776#endif
6777 ADD_INT(d, DB_FIRST);
6778 ADD_INT(d, DB_FLUSH);
6779 ADD_INT(d, DB_GET_BOTH);
6780 ADD_INT(d, DB_GET_RECNO);
6781 ADD_INT(d, DB_JOIN_ITEM);
6782 ADD_INT(d, DB_KEYFIRST);
6783 ADD_INT(d, DB_KEYLAST);
6784 ADD_INT(d, DB_LAST);
6785 ADD_INT(d, DB_NEXT);
6786 ADD_INT(d, DB_NEXT_DUP);
6787 ADD_INT(d, DB_NEXT_NODUP);
6788 ADD_INT(d, DB_NODUPDATA);
6789 ADD_INT(d, DB_NOOVERWRITE);
6790 ADD_INT(d, DB_NOSYNC);
6791 ADD_INT(d, DB_POSITION);
6792 ADD_INT(d, DB_PREV);
6793 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006794#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006795 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006796#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006797 ADD_INT(d, DB_SET);
6798 ADD_INT(d, DB_SET_RANGE);
6799 ADD_INT(d, DB_SET_RECNO);
6800 ADD_INT(d, DB_WRITECURSOR);
6801
6802 ADD_INT(d, DB_OPFLAGS_MASK);
6803 ADD_INT(d, DB_RMW);
6804#if (DBVER >= 33)
6805 ADD_INT(d, DB_DIRTY_READ);
6806 ADD_INT(d, DB_MULTIPLE);
6807 ADD_INT(d, DB_MULTIPLE_KEY);
6808#endif
6809
Gregory P. Smith29602d22006-01-24 09:46:48 +00006810#if (DBVER >= 44)
6811 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
6812 ADD_INT(d, DB_READ_COMMITTED);
6813#endif
6814
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006815#if (DBVER >= 33)
6816 ADD_INT(d, DB_DONOTINDEX);
6817#endif
6818
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006819#if (DBVER >= 41)
6820 _addIntToDict(d, "DB_INCOMPLETE", 0);
6821#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006822 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006823#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006824 ADD_INT(d, DB_KEYEMPTY);
6825 ADD_INT(d, DB_KEYEXIST);
6826 ADD_INT(d, DB_LOCK_DEADLOCK);
6827 ADD_INT(d, DB_LOCK_NOTGRANTED);
6828 ADD_INT(d, DB_NOSERVER);
6829 ADD_INT(d, DB_NOSERVER_HOME);
6830 ADD_INT(d, DB_NOSERVER_ID);
6831 ADD_INT(d, DB_NOTFOUND);
6832 ADD_INT(d, DB_OLD_VERSION);
6833 ADD_INT(d, DB_RUNRECOVERY);
6834 ADD_INT(d, DB_VERIFY_BAD);
6835#if (DBVER >= 33)
6836 ADD_INT(d, DB_PAGE_NOTFOUND);
6837 ADD_INT(d, DB_SECONDARY_BAD);
6838#endif
6839#if (DBVER >= 40)
6840 ADD_INT(d, DB_STAT_CLEAR);
6841 ADD_INT(d, DB_REGION_INIT);
6842 ADD_INT(d, DB_NOLOCKING);
6843 ADD_INT(d, DB_YIELDCPU);
6844 ADD_INT(d, DB_PANIC_ENVIRONMENT);
6845 ADD_INT(d, DB_NOPANIC);
6846#endif
6847
Jesus Ceaef9764f2008-05-13 18:45:46 +00006848#if (DBVER >= 41)
6849 ADD_INT(d, DB_OVERWRITE);
6850#endif
6851
Gregory P. Smithaae141a2007-11-01 21:08:14 +00006852#ifdef DB_REGISTER
6853 ADD_INT(d, DB_REGISTER);
6854#endif
6855
Gregory P. Smith41631e82003-09-21 00:08:14 +00006856#if (DBVER >= 42)
6857 ADD_INT(d, DB_TIME_NOTGRANTED);
6858 ADD_INT(d, DB_TXN_NOT_DURABLE);
6859 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
6860 ADD_INT(d, DB_LOG_AUTOREMOVE);
6861 ADD_INT(d, DB_DIRECT_LOG);
6862 ADD_INT(d, DB_DIRECT_DB);
6863 ADD_INT(d, DB_INIT_REP);
6864 ADD_INT(d, DB_ENCRYPT);
6865 ADD_INT(d, DB_CHKSUM);
6866#endif
6867
Jesus Ceaef9764f2008-05-13 18:45:46 +00006868#if (DBVER >= 44)
6869 ADD_INT(d, DB_DSYNC_DB);
6870#endif
6871
6872#if (DBVER >= 45)
6873 ADD_INT(d, DB_TXN_SNAPSHOT);
6874#endif
6875
6876#if (DBVER >= 40)
6877 ADD_INT(d, DB_VERB_DEADLOCK);
6878#if (DBVER >= 46)
6879 ADD_INT(d, DB_VERB_FILEOPS);
6880 ADD_INT(d, DB_VERB_FILEOPS_ALL);
6881#endif
6882 ADD_INT(d, DB_VERB_RECOVERY);
6883#if (DBVER >= 44)
6884 ADD_INT(d, DB_VERB_REGISTER);
6885#endif
6886 ADD_INT(d, DB_VERB_REPLICATION);
6887 ADD_INT(d, DB_VERB_WAITSFOR);
6888#endif
6889
6890#if (DBVER >= 45)
6891 ADD_INT(d, DB_EVENT_PANIC);
6892 ADD_INT(d, DB_EVENT_REP_CLIENT);
6893#if (DBVER >= 46)
6894 ADD_INT(d, DB_EVENT_REP_ELECTED);
6895#endif
6896 ADD_INT(d, DB_EVENT_REP_MASTER);
6897 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
6898#if (DBVER >= 46)
6899 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
6900#endif
6901 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
6902 ADD_INT(d, DB_EVENT_WRITE_FAILED);
6903#endif
6904
6905#if (DBVER >= 40)
6906 ADD_INT(d, DB_REP_MASTER);
6907 ADD_INT(d, DB_REP_CLIENT);
6908#if (DBVER >= 45)
6909 ADD_INT(d, DB_REP_ELECTION);
6910
6911 ADD_INT(d, DB_REP_ACK_TIMEOUT);
6912 ADD_INT(d, DB_REP_CONNECTION_RETRY);
6913 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
6914 ADD_INT(d, DB_REP_ELECTION_RETRY);
6915#endif
6916#if (DBVER >= 46)
6917 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
6918 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
6919#endif
6920#endif
6921
6922#if (DBVER >= 45)
6923 ADD_INT(d, DB_REPMGR_PEER);
6924 ADD_INT(d, DB_REPMGR_ACKS_ALL);
6925 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
6926 ADD_INT(d, DB_REPMGR_ACKS_NONE);
6927 ADD_INT(d, DB_REPMGR_ACKS_ONE);
6928 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
6929 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
6930 ADD_INT(d, DB_REPMGR_CONNECTED);
6931 ADD_INT(d, DB_REPMGR_DISCONNECTED);
6932 ADD_INT(d, DB_STAT_CLEAR);
6933 ADD_INT(d, DB_STAT_ALL);
6934#endif
6935
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006936#if (DBVER >= 43)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006937 ADD_INT(d, DB_DSYNC_LOG);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006938 ADD_INT(d, DB_LOG_INMEMORY);
6939 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006940 ADD_INT(d, DB_SEQ_DEC);
6941 ADD_INT(d, DB_SEQ_INC);
6942 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006943#endif
6944
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006945#if (DBVER >= 41)
6946 ADD_INT(d, DB_ENCRYPT_AES);
6947 ADD_INT(d, DB_AUTO_COMMIT);
6948#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00006949 /* allow Berkeley DB 4.1 aware apps to run on older versions */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006950 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
6951#endif
6952
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006953 ADD_INT(d, EINVAL);
6954 ADD_INT(d, EACCES);
6955 ADD_INT(d, ENOSPC);
6956 ADD_INT(d, ENOMEM);
6957 ADD_INT(d, EAGAIN);
6958 ADD_INT(d, EBUSY);
6959 ADD_INT(d, EEXIST);
6960 ADD_INT(d, ENOENT);
6961 ADD_INT(d, EPERM);
6962
Barry Warsaw1baa9822003-03-31 19:51:29 +00006963#if (DBVER >= 40)
6964 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
6965 ADD_INT(d, DB_SET_TXN_TIMEOUT);
6966#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006967
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00006968 /* The exception name must be correct for pickled exception *
6969 * objects to unpickle properly. */
6970#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
6971#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
6972#else
6973#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
6974#endif
6975
6976 /* All the rest of the exceptions derive only from DBError */
6977#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
6978 PyDict_SetItemString(d, #name, name)
6979
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006980 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00006981 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6982 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006983
Gregory P. Smithe9477062005-06-04 06:46:59 +00006984 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6985 * from both DBError and KeyError, since the API only supports
6986 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006987 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00006988 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6989 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006990 Py_file_input, d, d);
6991 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00006992 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006993 PyDict_DelItemString(d, "KeyError");
6994
6995
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006996#if !INCOMPLETE_IS_WARNING
6997 MAKE_EX(DBIncompleteError);
6998#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00006999 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007000 MAKE_EX(DBKeyEmptyError);
7001 MAKE_EX(DBKeyExistError);
7002 MAKE_EX(DBLockDeadlockError);
7003 MAKE_EX(DBLockNotGrantedError);
7004 MAKE_EX(DBOldVersionError);
7005 MAKE_EX(DBRunRecoveryError);
7006 MAKE_EX(DBVerifyBadError);
7007 MAKE_EX(DBNoServerError);
7008 MAKE_EX(DBNoServerHomeError);
7009 MAKE_EX(DBNoServerIDError);
7010#if (DBVER >= 33)
7011 MAKE_EX(DBPageNotFoundError);
7012 MAKE_EX(DBSecondaryBadError);
7013#endif
7014
7015 MAKE_EX(DBInvalidArgError);
7016 MAKE_EX(DBAccessError);
7017 MAKE_EX(DBNoSpaceError);
7018 MAKE_EX(DBNoMemoryError);
7019 MAKE_EX(DBAgainError);
7020 MAKE_EX(DBBusyError);
7021 MAKE_EX(DBFileExistsError);
7022 MAKE_EX(DBNoSuchFileError);
7023 MAKE_EX(DBPermissionsError);
7024
Jesus Ceaef9764f2008-05-13 18:45:46 +00007025#if (DBVER >= 42)
7026 MAKE_EX(DBRepHandleDeadError);
7027#endif
7028
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007029#undef MAKE_EX
7030
Gregory P. Smith39250532007-10-09 06:02:21 +00007031 /* Initiliase the C API structure and add it to the module */
7032 bsddb_api.db_type = &DB_Type;
7033 bsddb_api.dbcursor_type = &DBCursor_Type;
7034 bsddb_api.dbenv_type = &DBEnv_Type;
7035 bsddb_api.dbtxn_type = &DBTxn_Type;
7036 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007037#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00007038 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007039#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00007040 bsddb_api.makeDBError = makeDBError;
7041
7042 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7043 PyDict_SetItemString(d, "api", py_api);
7044 Py_DECREF(py_api);
7045
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007046 /* Check for errors */
7047 if (PyErr_Occurred()) {
7048 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007049 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007050 }
7051}
Gregory P. Smith41631e82003-09-21 00:08:14 +00007052
7053/* allow this module to be named _pybsddb so that it can be installed
7054 * and imported on top of python >= 2.3 that includes its own older
7055 * copy of the library named _bsddb without importing the old version. */
7056DL_EXPORT(void) init_pybsddb(void)
7057{
7058 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
7059 init_bsddb();
7060}