blob: 9e89273fc93541345444c66e8529e2a28bd750ad [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 Cea6ba33292008-08-31 14:12:11 +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. Smithc4119182007-09-09 20:17:22 +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 Cea6ba33292008-08-31 14:12:11 +000051 * Gregory P. Smith <greg@krypto.org> was once again the maintainer.
52 *
53 * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.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 *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +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)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +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>
Guido van Rossum8ce8a782007-11-01 19:42:39 +000093
94#define COMPILING_BSDDB_C
95#include "bsddb.h"
96#undef COMPILING_BSDDB_C
97
Jesus Cea6ba33292008-08-31 14:12:11 +000098static char *rcs_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000099
100/* --------------------------------------------------------------------- */
101/* Various macro definitions */
102
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000103#if (PY_VERSION_HEX < 0x02050000)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000104typedef int Py_ssize_t;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000105#endif
106
Jesus Cea6ba33292008-08-31 14:12:11 +0000107#if (PY_VERSION_HEX < 0x02060000) /* really: before python trunk r63675 */
108/* This code now uses PyBytes* API function names instead of PyString*.
109 * These #defines map to their equivalent on earlier python versions. */
110#define PyBytes_FromStringAndSize PyString_FromStringAndSize
111#define PyBytes_FromString PyString_FromString
112#define PyBytes_AsStringAndSize PyString_AsStringAndSize
113#define PyBytes_Check PyString_Check
114#define PyBytes_GET_SIZE PyString_GET_SIZE
115#define PyBytes_AS_STRING PyString_AS_STRING
116#endif
117
118#if (PY_VERSION_HEX >= 0x03000000)
119#define NUMBER_Check PyLong_Check
120#define NUMBER_AsLong PyLong_AsLong
121#define NUMBER_FromLong PyLong_FromLong
122#else
123#define NUMBER_Check PyInt_Check
124#define NUMBER_AsLong PyInt_AsLong
125#define NUMBER_FromLong PyInt_FromLong
126#endif
127
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128#ifdef WITH_THREAD
129
130/* These are for when calling Python --> C */
131#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
132#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
133
Mark Hammonda69d4092003-04-22 23:13:27 +0000134/* For 2.3, use the PyGILState_ calls */
135#if (PY_VERSION_HEX >= 0x02030000)
136#define MYDB_USE_GILSTATE
137#endif
138
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000139/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000140#if defined(MYDB_USE_GILSTATE)
141#define MYDB_BEGIN_BLOCK_THREADS \
142 PyGILState_STATE __savestate = PyGILState_Ensure();
143#define MYDB_END_BLOCK_THREADS \
144 PyGILState_Release(__savestate);
145#else /* MYDB_USE_GILSTATE */
146/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000147static PyInterpreterState* _db_interpreterState = NULL;
148#define MYDB_BEGIN_BLOCK_THREADS { \
149 PyThreadState* prevState; \
150 PyThreadState* newState; \
151 PyEval_AcquireLock(); \
152 newState = PyThreadState_New(_db_interpreterState); \
153 prevState = PyThreadState_Swap(newState);
154
155#define MYDB_END_BLOCK_THREADS \
156 newState = PyThreadState_Swap(prevState); \
157 PyThreadState_Clear(newState); \
158 PyEval_ReleaseLock(); \
159 PyThreadState_Delete(newState); \
160 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000161#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162
163#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000164/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000165#define MYDB_BEGIN_ALLOW_THREADS
166#define MYDB_END_ALLOW_THREADS
167#define MYDB_BEGIN_BLOCK_THREADS
168#define MYDB_END_BLOCK_THREADS
169
170#endif
171
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000172/* Should DB_INCOMPLETE be turned into a warning or an exception? */
173#define INCOMPLETE_IS_WARNING 1
174
175/* --------------------------------------------------------------------- */
176/* Exceptions */
177
178static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000179static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000180static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000181static PyObject* DBKeyExistError; /* DB_KEYEXIST */
182static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
183static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
184static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
185static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
186static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
187static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
188static PyObject* DBNoServerError; /* DB_NOSERVER */
189static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
190static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000191static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
192static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000193
194#if !INCOMPLETE_IS_WARNING
195static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
196#endif
197
198static PyObject* DBInvalidArgError; /* EINVAL */
199static PyObject* DBAccessError; /* EACCES */
200static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000201static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000202static PyObject* DBAgainError; /* EAGAIN */
203static PyObject* DBBusyError; /* EBUSY */
204static PyObject* DBFileExistsError; /* EEXIST */
205static PyObject* DBNoSuchFileError; /* ENOENT */
206static PyObject* DBPermissionsError; /* EPERM */
207
Jesus Cea6ba33292008-08-31 14:12:11 +0000208#if (DBVER >= 42)
209static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
210#endif
211
212static PyObject* DBRepUnavailError; /* DB_REP_UNAVAIL */
213
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000214#if (DBVER < 43)
215#define DB_BUFFER_SMALL ENOMEM
216#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000217
218
219/* --------------------------------------------------------------------- */
220/* Structure definitions */
221
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000222#if PYTHON_API_VERSION < 1010
223#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000224#endif
225
Gregory P. Smith31c50652004-06-28 01:20:40 +0000226
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000227/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000228#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000229#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000230
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000231
Jesus Cea6ba33292008-08-31 14:12:11 +0000232/* See comment in Python 2.6 "object.h" */
233#ifndef staticforward
234#define staticforward static
235#endif
236#ifndef statichere
237#define statichere static
238#endif
239
240staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
241 DBLock_Type;
242#if (DBVER >= 43)
243staticforward PyTypeObject DBSequence_Type;
244#endif
245
246#ifndef Py_TYPE
247/* for compatibility with Python 2.5 and earlier */
248#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
249#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000250
Christian Heimes90aa7642007-12-19 02:45:37 +0000251#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
252#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
253#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
254#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
255#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000256#if (DBVER >= 43)
Christian Heimes90aa7642007-12-19 02:45:37 +0000257#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000258#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000259
Jesus Cea6ba33292008-08-31 14:12:11 +0000260#if (DBVER < 46)
261 #define _DBC_close(dbc) dbc->c_close(dbc)
262 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
263 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
264 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
265 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
266 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
267 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
268#else
269 #define _DBC_close(dbc) dbc->close(dbc)
270 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
271 #define _DBC_del(dbc,a) dbc->del(dbc,a)
272 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
273 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
274 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
275 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
276#endif
277
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278
279/* --------------------------------------------------------------------- */
280/* Utility macros and functions */
281
Jesus Cea6ba33292008-08-31 14:12:11 +0000282#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
283 { \
284 object->sibling_next=backlink; \
285 object->sibling_prev_p=&(backlink); \
286 backlink=object; \
287 if (object->sibling_next) { \
288 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
289 } \
290 }
291
292#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
293 { \
294 if (object->sibling_next) { \
295 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
296 } \
297 *(object->sibling_prev_p)=object->sibling_next; \
298 }
299
300#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
301 { \
302 if (object->sibling_next) { \
303 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
304 } \
305 if (object->sibling_prev_p) { \
306 *(object->sibling_prev_p)=object->sibling_next; \
307 } \
308 }
309
310#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
311 { \
312 object->sibling_next_txn=backlink; \
313 object->sibling_prev_p_txn=&(backlink); \
314 backlink=object; \
315 if (object->sibling_next_txn) { \
316 object->sibling_next_txn->sibling_prev_p_txn= \
317 &(object->sibling_next_txn); \
318 } \
319 }
320
321#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
322 { \
323 if (object->sibling_next_txn) { \
324 object->sibling_next_txn->sibling_prev_p_txn= \
325 object->sibling_prev_p_txn; \
326 } \
327 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
328 }
329
330
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000331#define RETURN_IF_ERR() \
332 if (makeDBError(err)) { \
333 return NULL; \
334 }
335
336#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
337
Gregory P. Smithe2767172003-11-02 08:06:29 +0000338#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
339 if ((nonNull) == NULL) { \
340 PyObject *errTuple = NULL; \
341 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
Jesus Cea6ba33292008-08-31 14:12:11 +0000342 if (errTuple) { \
343 PyErr_SetObject((pyErrObj), errTuple); \
344 Py_DECREF(errTuple); \
345 } \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000346 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000347 }
348
Gregory P. Smithe2767172003-11-02 08:06:29 +0000349#define CHECK_DB_NOT_CLOSED(dbobj) \
350 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
351
352#define CHECK_ENV_NOT_CLOSED(env) \
353 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000354
355#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000356 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000357
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000358#if (DBVER >= 43)
359#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
360 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
361#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000362
363#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
364 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
365
366#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
367
Jesus Cea6ba33292008-08-31 14:12:11 +0000368#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
369 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
370
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000371
372static int makeDBError(int err);
373
374
375/* Return the access method type of the DBObject */
376static int _DB_get_type(DBObject* self)
377{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000378 DBTYPE type;
379 int err;
Jesus Cea6ba33292008-08-31 14:12:11 +0000380
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000381 err = self->db->get_type(self->db, &type);
382 if (makeDBError(err)) {
383 return -1;
384 }
385 return type;
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000386}
387
388
389/* Create a DBT structure (containing key and data values) from Python
Jesus Cea6ba33292008-08-31 14:12:11 +0000390 strings. Returns 1 on success, 0 on an error. */
391static int make_dbt(PyObject* obj, DBT* dbt)
Gregory P. Smith3d5cb222007-08-28 08:23:15 +0000392{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000393 CLEAR_DBT(*dbt);
394 if (obj == Py_None) {
395 /* no need to do anything, the structure has already been zeroed */
396 }
Jesus Cea6ba33292008-08-31 14:12:11 +0000397 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398 PyErr_SetString(PyExc_TypeError,
Jesus Cea6ba33292008-08-31 14:12:11 +0000399#if (PY_VERSION_HEX < 0x03000000)
400 "Data values must be of type string or None.");
401#else
402 "Data values must be of type bytes or None.");
403#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000404 return 0;
405 }
406 return 1;
407}
408
409
410/* Recno and Queue DBs can have integer keys. This function figures out
411 what's been given, verifies that it's allowed, and then makes the DBT.
412
Jesus Cea6ba33292008-08-31 14:12:11 +0000413 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000414static int
Jesus Cea6ba33292008-08-31 14:12:11 +0000415make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000416{
417 db_recno_t recno;
418 int type;
419
420 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000421 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000422 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000423 if (type == -1)
424 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000425 if (type == DB_RECNO || type == DB_QUEUE) {
426 PyErr_SetString(
427 PyExc_TypeError,
428 "None keys not allowed for Recno and Queue DB's");
429 return 0;
430 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000431 /* no need to do anything, the structure has already been zeroed */
432 }
433
Jesus Cea6ba33292008-08-31 14:12:11 +0000434 else if (PyBytes_Check(keyobj)) {
435 /* verify access method type */
436 type = _DB_get_type(self);
437 if (type == -1)
438 return 0;
439 if (type == DB_RECNO || type == DB_QUEUE) {
440 PyErr_SetString(
441 PyExc_TypeError,
442#if (PY_VERSION_HEX < 0x03000000)
443 "String keys not allowed for Recno and Queue DB's");
444#else
445 "Bytes keys not allowed for Recno and Queue DB's");
446#endif
447 return 0;
448 }
449
450 /*
451 * NOTE(gps): I don't like doing a data copy here, it seems
452 * wasteful. But without a clean way to tell FREE_DBT if it
453 * should free key->data or not we have to. Other places in
454 * the code check for DB_THREAD and forceably set DBT_MALLOC
455 * when we otherwise would leave flags 0 to indicate that.
456 */
457 key->data = malloc(PyBytes_GET_SIZE(keyobj));
458 if (key->data == NULL) {
459 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
460 return 0;
461 }
462 memcpy(key->data, PyBytes_AS_STRING(keyobj),
463 PyBytes_GET_SIZE(keyobj));
464 key->flags = DB_DBT_REALLOC;
465 key->size = PyBytes_GET_SIZE(keyobj);
466 }
467
468 else if (NUMBER_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000469 /* verify access method type */
470 type = _DB_get_type(self);
471 if (type == -1)
472 return 0;
473 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000474 /* if BTREE then an Integer key is allowed with the
475 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000476 *pflags |= DB_SET_RECNO;
477 }
478 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000479 PyErr_SetString(
480 PyExc_TypeError,
481 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000482 return 0;
483 }
484
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000485 /* Make a key out of the requested recno, use allocated space so DB
486 * will be able to realloc room for the real key if needed. */
Jesus Cea6ba33292008-08-31 14:12:11 +0000487 recno = NUMBER_AsLong(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000488 key->data = malloc(sizeof(db_recno_t));
489 if (key->data == NULL) {
490 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
491 return 0;
492 }
493 key->ulen = key->size = sizeof(db_recno_t);
494 memcpy(key->data, &recno, sizeof(db_recno_t));
495 key->flags = DB_DBT_REALLOC;
496 }
497 else {
498 PyErr_Format(PyExc_TypeError,
Jesus Cea6ba33292008-08-31 14:12:11 +0000499#if (PY_VERSION_HEX < 0x03000000)
500 "String or Integer object expected for key, %s found",
501#else
502 "Bytes or Integer object expected for key, %s found",
503#endif
Christian Heimes90aa7642007-12-19 02:45:37 +0000504 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000505 return 0;
506 }
507
508 return 1;
509}
510
511
512/* Add partial record access to an existing DBT data struct.
513 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
514 and the data storage/retrieval will be done using dlen and doff. */
515static int add_partial_dbt(DBT* d, int dlen, int doff) {
516 /* if neither were set we do nothing (-1 is the default value) */
517 if ((dlen == -1) && (doff == -1)) {
518 return 1;
519 }
520
521 if ((dlen < 0) || (doff < 0)) {
522 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
523 return 0;
524 }
525
526 d->flags = d->flags | DB_DBT_PARTIAL;
527 d->dlen = (unsigned int) dlen;
528 d->doff = (unsigned int) doff;
529 return 1;
530}
531
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000532/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
533/* TODO: make this use the native libc strlcpy() when available (BSD) */
534unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
535{
536 unsigned int srclen, copylen;
537
538 srclen = strlen(src);
539 if (n <= 0)
540 return srclen;
541 copylen = (srclen > n-1) ? n-1 : srclen;
542 /* populate dest[0] thru dest[copylen-1] */
543 memcpy(dest, src, copylen);
544 /* guarantee null termination */
545 dest[copylen] = 0;
546
547 return srclen;
548}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000550/* Callback used to save away more information about errors from the DB
551 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000552static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000553#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000554static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000555#else
556static void _db_errorCallback(const DB_ENV *db_env,
557 const char* prefix, const char* msg)
558#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000559{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000560 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000561}
562
563
Jesus Cea6ba33292008-08-31 14:12:11 +0000564/*
565** We need these functions because some results
566** are undefined if pointer is NULL. Some other
567** give None instead of "".
568**
569** This functions are static and will be
570** -I hope- inlined.
571*/
572static const char *DummyString = "This string is a simple placeholder";
573static PyObject *Build_PyString(const char *p,int s)
574{
575 if (!p) {
576 p=DummyString;
577 assert(s==0);
578 }
579 return PyBytes_FromStringAndSize(p,s);
580}
581
582static PyObject *BuildValue_S(const void *p,int s)
583{
584 if (!p) {
585 p=DummyString;
586 assert(s==0);
587 }
588 return PyBytes_FromStringAndSize(p, s);
589}
590
591static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
592{
593PyObject *a, *b, *r;
594
595 if (!p1) {
596 p1=DummyString;
597 assert(s1==0);
598 }
599 if (!p2) {
600 p2=DummyString;
601 assert(s2==0);
602 }
603
604 if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
605 return NULL;
606 }
607 if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
608 Py_DECREF(a);
609 return NULL;
610 }
611
612#if (PY_VERSION_HEX >= 0x02040000)
613 r = PyTuple_Pack(2, a, b) ;
614#else
615 r = Py_BuildValue("OO", a, b);
616#endif
617 Py_DECREF(a);
618 Py_DECREF(b);
619 return r;
620}
621
622static PyObject *BuildValue_IS(int i,const void *p,int s)
623{
624 PyObject *a, *r;
625
626 if (!p) {
627 p=DummyString;
628 assert(s==0);
629 }
630
631 if (!(a = PyBytes_FromStringAndSize(p, s))) {
632 return NULL;
633 }
634
635 r = Py_BuildValue("iO", i, a);
636 Py_DECREF(a);
637 return r;
638}
639
640static PyObject *BuildValue_LS(long l,const void *p,int s)
641{
642 PyObject *a, *r;
643
644 if (!p) {
645 p=DummyString;
646 assert(s==0);
647 }
648
649 if (!(a = PyBytes_FromStringAndSize(p, s))) {
650 return NULL;
651 }
652
653 r = Py_BuildValue("lO", l, a);
654 Py_DECREF(a);
655 return r;
656}
657
658
659
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000660/* make a nice exception object to raise for errors. */
661static int makeDBError(int err)
662{
663 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000664 PyObject *errObj = NULL;
665 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000666 int exceptionRaised = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000667 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000668
669 switch (err) {
670 case 0: /* successful, no error */ break;
671
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000672#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000673 case DB_INCOMPLETE:
674#if INCOMPLETE_IS_WARNING
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000675 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
676 /* Ensure that bytes_left never goes negative */
677 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
678 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
679 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000680 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000681 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000682 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000683 _db_errmsg[0] = 0;
Jesus Cea6ba33292008-08-31 14:12:11 +0000684 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000685
686#else /* do an exception instead */
687 errObj = DBIncompleteError;
688#endif
689 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000690#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000691
692 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
693 case DB_KEYEXIST: errObj = DBKeyExistError; break;
694 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
695 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
696 case DB_NOTFOUND: errObj = DBNotFoundError; break;
697 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
698 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
699 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
700 case DB_NOSERVER: errObj = DBNoServerError; break;
701 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
702 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000703 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
704 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000705 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000706
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000707#if (DBVER >= 43)
708 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
709 case ENOMEM: errObj = PyExc_MemoryError; break;
710#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000711 case EINVAL: errObj = DBInvalidArgError; break;
712 case EACCES: errObj = DBAccessError; break;
713 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000714 case EAGAIN: errObj = DBAgainError; break;
715 case EBUSY : errObj = DBBusyError; break;
716 case EEXIST: errObj = DBFileExistsError; break;
717 case ENOENT: errObj = DBNoSuchFileError; break;
718 case EPERM : errObj = DBPermissionsError; break;
719
Jesus Cea6ba33292008-08-31 14:12:11 +0000720#if (DBVER >= 42)
721 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
722#endif
723
724 case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
725
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000726 default: errObj = DBError; break;
727 }
728
729 if (errObj != NULL) {
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000730 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
731 /* Ensure that bytes_left never goes negative */
732 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
733 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
734 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000735 strcat(errTxt, " -- ");
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000736 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000737 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000738 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000739
Jesus Cea6ba33292008-08-31 14:12:11 +0000740 errTuple = Py_BuildValue("(is)", err, errTxt);
741 if (errTuple == NULL) {
742 Py_DECREF(errObj);
743 return !0;
744 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000745 PyErr_SetObject(errObj, errTuple);
Jesus Cea6ba33292008-08-31 14:12:11 +0000746 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000747 }
748
749 return ((errObj != NULL) || exceptionRaised);
750}
751
752
753
754/* set a type exception */
755static void makeTypeError(char* expected, PyObject* found)
756{
757 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimes90aa7642007-12-19 02:45:37 +0000758 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000759}
760
761
762/* verify that an obj is either None or a DBTxn, and set the txn pointer */
763static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
764{
765 if (txnobj == Py_None || txnobj == NULL) {
766 *txn = NULL;
767 return 1;
768 }
769 if (DBTxnObject_Check(txnobj)) {
770 *txn = ((DBTxnObject*)txnobj)->txn;
771 return 1;
772 }
773 else
774 makeTypeError("DBTxn", txnobj);
775 return 0;
776}
777
778
779/* Delete a key from a database
780 Returns 0 on success, -1 on an error. */
781static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
782{
783 int err;
784
785 MYDB_BEGIN_ALLOW_THREADS;
786 err = self->db->del(self->db, txn, key, 0);
787 MYDB_END_ALLOW_THREADS;
788 if (makeDBError(err)) {
789 return -1;
790 }
791 self->haveStat = 0;
792 return 0;
793}
794
795
796/* Store a key into a database
797 Returns 0 on success, -1 on an error. */
798static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
799{
800 int err;
801
802 MYDB_BEGIN_ALLOW_THREADS;
803 err = self->db->put(self->db, txn, key, data, flags);
804 MYDB_END_ALLOW_THREADS;
805 if (makeDBError(err)) {
806 return -1;
807 }
808 self->haveStat = 0;
809 return 0;
810}
811
812/* Get a key/data pair from a cursor */
813static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
814 PyObject *args, PyObject *kwargs, char *format)
815{
816 int err;
817 PyObject* retval = NULL;
818 DBT key, data;
819 int dlen = -1;
820 int doff = -1;
821 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000822 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000823
824 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
825 &flags, &dlen, &doff))
826 return NULL;
827
828 CHECK_CURSOR_NOT_CLOSED(self);
829
830 flags |= extra_flags;
831 CLEAR_DBT(key);
832 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000833 if (!add_partial_dbt(&data, dlen, doff))
834 return NULL;
835
836 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +0000837 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000838 MYDB_END_ALLOW_THREADS;
839
Gregory P. Smithe9477062005-06-04 06:46:59 +0000840 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
841 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000842 Py_INCREF(Py_None);
843 retval = Py_None;
844 }
845 else if (makeDBError(err)) {
846 retval = NULL;
847 }
848 else { /* otherwise, success! */
849
850 /* if Recno or Queue, return the key as an Int */
851 switch (_DB_get_type(self->mydb)) {
852 case -1:
853 retval = NULL;
854 break;
855
856 case DB_RECNO:
857 case DB_QUEUE:
Jesus Cea6ba33292008-08-31 14:12:11 +0000858 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000859 break;
860 case DB_HASH:
861 case DB_BTREE:
862 default:
Jesus Cea6ba33292008-08-31 14:12:11 +0000863 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000864 break;
865 }
866 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000867 return retval;
868}
869
870
871/* add an integer to a dictionary using the given name as a key */
872static void _addIntToDict(PyObject* dict, char *name, int value)
873{
Jesus Cea6ba33292008-08-31 14:12:11 +0000874 PyObject* v = NUMBER_FromLong((long) value);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000875 if (!v || PyDict_SetItemString(dict, name, v))
876 PyErr_Clear();
877
878 Py_XDECREF(v);
879}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000880
881/* The same, when the value is a time_t */
882static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
883{
884 PyObject* v;
885 /* if the value fits in regular int, use that. */
Jesus Cea6ba33292008-08-31 14:12:11 +0000886#ifdef PY_LONG_LONG
Guido van Rossumd8faa362007-04-27 19:54:29 +0000887 if (sizeof(time_t) > sizeof(long))
888 v = PyLong_FromLongLong((PY_LONG_LONG) value);
889 else
890#endif
Jesus Cea6ba33292008-08-31 14:12:11 +0000891 v = NUMBER_FromLong((long) value);
Guido van Rossumd8faa362007-04-27 19:54:29 +0000892 if (!v || PyDict_SetItemString(dict, name, v))
893 PyErr_Clear();
894
895 Py_XDECREF(v);
896}
897
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000898#if (DBVER >= 43)
899/* add an db_seq_t to a dictionary using the given name as a key */
900static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
901{
902 PyObject* v = PyLong_FromLongLong(value);
903 if (!v || PyDict_SetItemString(dict, name, v))
904 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000905
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000906 Py_XDECREF(v);
907}
908#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000909
Jesus Cea6ba33292008-08-31 14:12:11 +0000910static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
911{
912 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
913 if (!v || PyDict_SetItemString(dict, name, v))
914 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000915
Jesus Cea6ba33292008-08-31 14:12:11 +0000916 Py_XDECREF(v);
917}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000918
919/* --------------------------------------------------------------------- */
920/* Allocators and deallocators */
921
922static DBObject*
923newDBObject(DBEnvObject* arg, int flags)
924{
925 DBObject* self;
926 DB_ENV* db_env = NULL;
927 int err;
928
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000929 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930 if (self == NULL)
931 return NULL;
932
933 self->haveStat = 0;
934 self->flags = 0;
935 self->setflags = 0;
936 self->myenvobj = NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +0000937 self->db = NULL;
938 self->children_cursors = NULL;
939#if (DBVER >=43)
940 self->children_sequences = NULL;
941#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000943 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000944 self->primaryDBType = 0;
Jesus Cea6ba33292008-08-31 14:12:11 +0000945 Py_INCREF(Py_None);
946 self->private_obj = Py_None;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000947 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000948
949 /* keep a reference to our python DBEnv object */
950 if (arg) {
951 Py_INCREF(arg);
952 self->myenvobj = arg;
953 db_env = arg->db_env;
Jesus Cea6ba33292008-08-31 14:12:11 +0000954 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
955 } else {
956 self->sibling_prev_p=NULL;
957 self->sibling_next=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000958 }
Jesus Cea6ba33292008-08-31 14:12:11 +0000959 self->txn=NULL;
960 self->sibling_prev_p_txn=NULL;
961 self->sibling_next_txn=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000962
963 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000964 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000966 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
967 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000968
969 MYDB_BEGIN_ALLOW_THREADS;
970 err = db_create(&self->db, db_env, flags);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000971 if (self->db != NULL) {
972 self->db->set_errcall(self->db, _db_errorCallback);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000973 self->db->app_private = (void*)self;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000974 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000975 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000976 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
977 * list so that a DBEnv can refuse to close without aborting any open
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000978 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000979 if (makeDBError(err)) {
980 if (self->myenvobj) {
981 Py_DECREF(self->myenvobj);
982 self->myenvobj = NULL;
983 }
Jesus Cea6ba33292008-08-31 14:12:11 +0000984 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000985 self = NULL;
986 }
987 return self;
988}
989
990
Jesus Cea6ba33292008-08-31 14:12:11 +0000991/* Forward declaration */
992static PyObject *DB_close_internal(DBObject* self, int flags);
993
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000994static void
995DB_dealloc(DBObject* self)
996{
Jesus Cea6ba33292008-08-31 14:12:11 +0000997 PyObject *dummy;
998
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000999 if (self->db != NULL) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001000 dummy=DB_close_internal(self,0);
1001 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001002 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001003 if (self->in_weakreflist != NULL) {
1004 PyObject_ClearWeakRefs((PyObject *) self);
1005 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001006 if (self->myenvobj) {
1007 Py_DECREF(self->myenvobj);
1008 self->myenvobj = NULL;
1009 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001010 if (self->associateCallback != NULL) {
1011 Py_DECREF(self->associateCallback);
1012 self->associateCallback = NULL;
1013 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001014 if (self->btCompareCallback != NULL) {
1015 Py_DECREF(self->btCompareCallback);
1016 self->btCompareCallback = NULL;
1017 }
Jesus Cea6ba33292008-08-31 14:12:11 +00001018 Py_DECREF(self->private_obj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001019 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001020}
1021
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001022static DBCursorObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00001023newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001024{
Neal Norwitzb4a55812004-07-09 23:30:57 +00001025 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001026 if (self == NULL)
1027 return NULL;
1028
1029 self->dbc = dbc;
1030 self->mydb = db;
Jesus Cea6ba33292008-08-31 14:12:11 +00001031
1032 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
1033 if (txn && ((PyObject *)txn!=Py_None)) {
1034 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
1035 self->txn=txn;
1036 } else {
1037 self->txn=NULL;
1038 }
1039
Gregory P. Smitha703a212003-11-03 01:04:41 +00001040 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001041 Py_INCREF(self->mydb);
1042 return self;
1043}
1044
1045
Jesus Cea6ba33292008-08-31 14:12:11 +00001046/* Forward declaration */
1047static PyObject *DBC_close_internal(DBCursorObject* self);
1048
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001049static void
1050DBCursor_dealloc(DBCursorObject* self)
1051{
Jesus Cea6ba33292008-08-31 14:12:11 +00001052 PyObject *dummy;
Gregory P. Smitha703a212003-11-03 01:04:41 +00001053
Jesus Cea6ba33292008-08-31 14:12:11 +00001054 if (self->dbc != NULL) {
1055 dummy=DBC_close_internal(self);
1056 Py_XDECREF(dummy);
1057 }
Gregory P. Smitha703a212003-11-03 01:04:41 +00001058 if (self->in_weakreflist != NULL) {
1059 PyObject_ClearWeakRefs((PyObject *) self);
1060 }
Jesus Cea6ba33292008-08-31 14:12:11 +00001061 Py_DECREF(self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001062 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001063}
1064
1065
1066static DBEnvObject*
1067newDBEnvObject(int flags)
1068{
1069 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001070 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001071 if (self == NULL)
1072 return NULL;
1073
1074 self->closed = 1;
1075 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001076 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1077 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Jesus Cea6ba33292008-08-31 14:12:11 +00001078 self->children_dbs = NULL;
1079 self->children_txns = NULL;
1080 Py_INCREF(Py_None);
1081 self->private_obj = Py_None;
1082 Py_INCREF(Py_None);
1083 self->rep_transport = Py_None;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001084 self->in_weakreflist = NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00001085 self->event_notifyCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001086
1087 MYDB_BEGIN_ALLOW_THREADS;
1088 err = db_env_create(&self->db_env, flags);
1089 MYDB_END_ALLOW_THREADS;
1090 if (makeDBError(err)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001091 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001092 self = NULL;
1093 }
1094 else {
1095 self->db_env->set_errcall(self->db_env, _db_errorCallback);
Jesus Cea6ba33292008-08-31 14:12:11 +00001096 self->db_env->app_private = self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001097 }
1098 return self;
1099}
1100
Jesus Cea6ba33292008-08-31 14:12:11 +00001101/* Forward declaration */
1102static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001103
1104static void
1105DBEnv_dealloc(DBEnvObject* self)
1106{
Jesus Cea6ba33292008-08-31 14:12:11 +00001107 PyObject *dummy;
1108
1109 if (self->db_env && !self->closed) {
1110 dummy=DBEnv_close_internal(self,0);
1111 Py_XDECREF(dummy);
1112 }
1113
1114 Py_XDECREF(self->event_notifyCallback);
1115 self->event_notifyCallback = NULL;
1116
Gregory P. Smith31c50652004-06-28 01:20:40 +00001117 if (self->in_weakreflist != NULL) {
1118 PyObject_ClearWeakRefs((PyObject *) self);
1119 }
Jesus Cea6ba33292008-08-31 14:12:11 +00001120 Py_DECREF(self->private_obj);
1121 Py_DECREF(self->rep_transport);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001122 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001123}
1124
1125
1126static DBTxnObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00001127newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001128{
1129 int err;
Jesus Cea6ba33292008-08-31 14:12:11 +00001130 DB_TXN *parent_txn = NULL;
1131
Neal Norwitzb4a55812004-07-09 23:30:57 +00001132 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001133 if (self == NULL)
1134 return NULL;
1135
Jesus Cea6ba33292008-08-31 14:12:11 +00001136 self->in_weakreflist = NULL;
1137 self->children_txns = NULL;
1138 self->children_dbs = NULL;
1139 self->children_cursors = NULL;
1140 self->children_sequences = NULL;
1141 self->flag_prepare = 0;
1142 self->parent_txn = NULL;
1143 self->env = NULL;
1144
1145 if (parent && ((PyObject *)parent!=Py_None)) {
1146 parent_txn = parent->txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001147 }
Jesus Cea6ba33292008-08-31 14:12:11 +00001148
1149 if (txn) {
1150 self->txn = txn;
1151 } else {
1152 MYDB_BEGIN_ALLOW_THREADS;
1153 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
1154 MYDB_END_ALLOW_THREADS;
1155
1156 if (makeDBError(err)) {
1157 Py_DECREF(self);
1158 return NULL;
1159 }
1160 }
1161
1162 /* Can't use 'parent' because could be 'parent==Py_None' */
1163 if (parent_txn) {
1164 self->parent_txn = parent;
1165 Py_INCREF(parent);
1166 self->env = NULL;
1167 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
1168 } else {
1169 self->parent_txn = NULL;
1170 Py_INCREF(myenv);
1171 self->env = myenv;
1172 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
1173 }
1174
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001175 return self;
1176}
1177
Jesus Cea6ba33292008-08-31 14:12:11 +00001178/* Forward declaration */
1179static PyObject *
1180DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001181
1182static void
1183DBTxn_dealloc(DBTxnObject* self)
1184{
Jesus Cea6ba33292008-08-31 14:12:11 +00001185 PyObject *dummy;
1186
1187 if (self->txn) {
1188 int flag_prepare = self->flag_prepare;
1189 dummy=DBTxn_abort_discard_internal(self,0);
1190 Py_XDECREF(dummy);
1191 if (!flag_prepare) {
1192 PyErr_Warn(PyExc_RuntimeWarning,
1193 "DBTxn aborted in destructor. No prior commit() or abort().");
1194 }
1195 }
1196
Gregory P. Smith31c50652004-06-28 01:20:40 +00001197 if (self->in_weakreflist != NULL) {
1198 PyObject_ClearWeakRefs((PyObject *) self);
1199 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001200
Jesus Cea6ba33292008-08-31 14:12:11 +00001201 if (self->env) {
1202 Py_DECREF(self->env);
1203 } else {
1204 Py_DECREF(self->parent_txn);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001205 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001206 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001207}
1208
1209
1210static DBLockObject*
1211newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1212 db_lockmode_t lock_mode, int flags)
1213{
1214 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001215 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001216 if (self == NULL)
1217 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001218 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001219
1220 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001221 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1222 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001223 MYDB_END_ALLOW_THREADS;
1224 if (makeDBError(err)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001225 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001226 self = NULL;
1227 }
1228
1229 return self;
1230}
1231
1232
1233static void
1234DBLock_dealloc(DBLockObject* self)
1235{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001236 if (self->in_weakreflist != NULL) {
1237 PyObject_ClearWeakRefs((PyObject *) self);
1238 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001239 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001240
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001241 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242}
1243
1244
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001245#if (DBVER >= 43)
1246static DBSequenceObject*
1247newDBSequenceObject(DBObject* mydb, int flags)
1248{
1249 int err;
1250 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1251 if (self == NULL)
1252 return NULL;
1253 Py_INCREF(mydb);
1254 self->mydb = mydb;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001255
Jesus Cea6ba33292008-08-31 14:12:11 +00001256 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
1257 self->txn = NULL;
1258
1259 self->in_weakreflist = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001260
1261 MYDB_BEGIN_ALLOW_THREADS;
1262 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1263 MYDB_END_ALLOW_THREADS;
1264 if (makeDBError(err)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001265 Py_DECREF(self);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001266 self = NULL;
1267 }
1268
1269 return self;
1270}
1271
Jesus Cea6ba33292008-08-31 14:12:11 +00001272/* Forward declaration */
1273static PyObject
1274*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001275
1276static void
1277DBSequence_dealloc(DBSequenceObject* self)
1278{
Jesus Cea6ba33292008-08-31 14:12:11 +00001279 PyObject *dummy;
1280
1281 if (self->sequence != NULL) {
1282 dummy=DBSequence_close_internal(self,0,0);
1283 Py_XDECREF(dummy);
1284 }
1285
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001286 if (self->in_weakreflist != NULL) {
1287 PyObject_ClearWeakRefs((PyObject *) self);
1288 }
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001289
1290 Py_DECREF(self->mydb);
1291 PyObject_Del(self);
1292}
1293#endif
1294
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001295/* --------------------------------------------------------------------- */
1296/* DB methods */
1297
1298static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00001299DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001300{
1301 PyObject* txnobj = NULL;
1302 PyObject* dataobj;
1303 db_recno_t recno;
1304 DBT key, data;
1305 DB_TXN *txn = NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00001306 static char* kwnames[] = { "data", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001307
Jesus Cea6ba33292008-08-31 14:12:11 +00001308 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
1309 &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001310 return NULL;
1311
1312 CHECK_DB_NOT_CLOSED(self);
1313
1314 /* make a dummy key out of a recno */
1315 recno = 0;
1316 CLEAR_DBT(key);
1317 key.data = &recno;
1318 key.size = sizeof(recno);
1319 key.ulen = key.size;
1320 key.flags = DB_DBT_USERMEM;
1321
Jesus Cea6ba33292008-08-31 14:12:11 +00001322 if (!make_dbt(dataobj, &data)) return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001323 if (!checkTxnObj(txnobj, &txn)) return NULL;
1324
Jesus Cea6ba33292008-08-31 14:12:11 +00001325 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001326 return NULL;
1327
Jesus Cea6ba33292008-08-31 14:12:11 +00001328 return NUMBER_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001329}
1330
1331
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001332static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001333_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1334 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001335{
1336 int retval = DB_DONOTINDEX;
1337 DBObject* secondaryDB = (DBObject*)db->app_private;
1338 PyObject* callback = secondaryDB->associateCallback;
1339 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001340 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001341 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001342
1343
1344 if (callback != NULL) {
1345 MYDB_BEGIN_BLOCK_THREADS;
1346
Thomas Woutersb3153832006-03-08 01:47:19 +00001347 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Cea6ba33292008-08-31 14:12:11 +00001348 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
Thomas Woutersb3153832006-03-08 01:47:19 +00001349 else
Jesus Cea6ba33292008-08-31 14:12:11 +00001350 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001351 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001352 result = PyEval_CallObject(callback, args);
1353 }
1354 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001355 PyErr_Print();
1356 }
1357 else if (result == Py_None) {
1358 retval = DB_DONOTINDEX;
1359 }
Jesus Cea6ba33292008-08-31 14:12:11 +00001360 else if (NUMBER_Check(result)) {
1361 retval = NUMBER_AsLong(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001362 }
Jesus Cea6ba33292008-08-31 14:12:11 +00001363 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001364 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001365 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001366
1367 CLEAR_DBT(*secKey);
Jesus Cea6ba33292008-08-31 14:12:11 +00001368 PyBytes_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001369 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1370 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001371 if (secKey->data) {
1372 memcpy(secKey->data, data, size);
1373 secKey->size = size;
1374 retval = 0;
1375 }
1376 else {
1377 PyErr_SetString(PyExc_MemoryError,
1378 "malloc failed in _db_associateCallback");
1379 PyErr_Print();
1380 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001381 }
1382 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001383 PyErr_SetString(
1384 PyExc_TypeError,
Jesus Cea6ba33292008-08-31 14:12:11 +00001385 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001386 PyErr_Print();
1387 }
1388
Thomas Woutersb3153832006-03-08 01:47:19 +00001389 Py_XDECREF(args);
1390 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001391
1392 MYDB_END_BLOCK_THREADS;
1393 }
1394 return retval;
1395}
1396
1397
1398static PyObject*
1399DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1400{
1401 int err, flags=0;
1402 DBObject* secondaryDB;
1403 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001404#if (DBVER >= 41)
1405 PyObject *txnobj = NULL;
1406 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001407 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001408 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001409#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001410 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001411#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001412
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001413#if (DBVER >= 41)
1414 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1415 &secondaryDB, &callback, &flags,
1416 &txnobj)) {
1417#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001418 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001419 &secondaryDB, &callback, &flags)) {
1420#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001421 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001422 }
1423
1424#if (DBVER >= 41)
1425 if (!checkTxnObj(txnobj, &txn)) return NULL;
1426#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427
1428 CHECK_DB_NOT_CLOSED(self);
1429 if (!DBObject_Check(secondaryDB)) {
1430 makeTypeError("DB", (PyObject*)secondaryDB);
1431 return NULL;
1432 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001433 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001434 if (callback == Py_None) {
1435 callback = NULL;
1436 }
1437 else if (!PyCallable_Check(callback)) {
1438 makeTypeError("Callable", callback);
1439 return NULL;
1440 }
1441
1442 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001443 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001444 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001445 secondaryDB->associateCallback = callback;
1446 secondaryDB->primaryDBType = _DB_get_type(self);
1447
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001448 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1449 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1450 * The global interepreter lock is not initialized until the first
1451 * thread is created using thread.start_new_thread() or fork() is
1452 * called. that would cause the ALLOW_THREADS here to segfault due
1453 * to a null pointer reference if no threads or child processes
1454 * have been created. This works around that and is a no-op if
1455 * threads have already been initialized.
1456 * (see pybsddb-users mailing list post on 2002-08-07)
1457 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001458#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001459 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001460#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001461 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001462#if (DBVER >= 41)
1463 err = self->db->associate(self->db,
1464 txn,
1465 secondaryDB->db,
1466 _db_associateCallback,
1467 flags);
1468#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001469 err = self->db->associate(self->db,
1470 secondaryDB->db,
1471 _db_associateCallback,
1472 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001473#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001474 MYDB_END_ALLOW_THREADS;
1475
1476 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001477 Py_XDECREF(secondaryDB->associateCallback);
1478 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001479 secondaryDB->primaryDBType = 0;
1480 }
1481
1482 RETURN_IF_ERR();
1483 RETURN_NONE();
1484}
1485
1486
Jesus Cea6ba33292008-08-31 14:12:11 +00001487static PyObject*
1488DB_close_internal(DBObject* self, int flags)
1489{
1490 PyObject *dummy;
1491 int err;
1492
1493 if (self->db != NULL) {
1494 /* Can be NULL if db is not in an environment */
1495 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
1496
1497 if (self->txn) {
1498 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1499 self->txn=NULL;
1500 }
1501
1502 while(self->children_cursors) {
1503 dummy=DBC_close_internal(self->children_cursors);
1504 Py_XDECREF(dummy);
1505 }
1506
1507#if (DBVER >= 43)
1508 while(self->children_sequences) {
1509 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1510 Py_XDECREF(dummy);
1511 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001512#endif
1513
Jesus Cea6ba33292008-08-31 14:12:11 +00001514 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001515 err = self->db->close(self->db, flags);
Jesus Cea6ba33292008-08-31 14:12:11 +00001516 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001517 self->db = NULL;
1518 RETURN_IF_ERR();
1519 }
1520 RETURN_NONE();
1521}
1522
Jesus Cea6ba33292008-08-31 14:12:11 +00001523static PyObject*
1524DB_close(DBObject* self, PyObject* args)
1525{
1526 int flags=0;
1527 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1528 return NULL;
1529 return DB_close_internal(self,flags);
1530}
1531
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001532
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001533static PyObject*
1534_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1535{
1536 int err, flags=0, type;
1537 PyObject* txnobj = NULL;
1538 PyObject* retval = NULL;
1539 DBT key, data;
1540 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001541 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001542
1543 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1544 &txnobj, &flags))
1545 return NULL;
1546
1547 CHECK_DB_NOT_CLOSED(self);
1548 type = _DB_get_type(self);
1549 if (type == -1)
1550 return NULL;
1551 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001552 PyErr_SetString(PyExc_TypeError,
1553 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001554 return NULL;
1555 }
1556 if (!checkTxnObj(txnobj, &txn))
1557 return NULL;
1558
1559 CLEAR_DBT(key);
1560 CLEAR_DBT(data);
1561 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001562 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001563 data.flags = DB_DBT_MALLOC;
1564 key.flags = DB_DBT_MALLOC;
1565 }
1566
1567 MYDB_BEGIN_ALLOW_THREADS;
1568 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1569 MYDB_END_ALLOW_THREADS;
1570
Gregory P. Smithe9477062005-06-04 06:46:59 +00001571 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1572 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001573 err = 0;
1574 Py_INCREF(Py_None);
1575 retval = Py_None;
1576 }
1577 else if (!err) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001578 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
1579 FREE_DBT(key);
1580 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001581 }
1582
1583 RETURN_IF_ERR();
1584 return retval;
1585}
1586
1587static PyObject*
1588DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1589{
1590 return _DB_consume(self, args, kwargs, DB_CONSUME);
1591}
1592
1593static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001594DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1595 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001596{
1597 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1598}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001599
1600
1601static PyObject*
1602DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1603{
1604 int err, flags=0;
1605 DBC* dbc;
1606 PyObject* txnobj = NULL;
1607 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001608 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001609
1610 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1611 &txnobj, &flags))
1612 return NULL;
1613 CHECK_DB_NOT_CLOSED(self);
1614 if (!checkTxnObj(txnobj, &txn))
1615 return NULL;
1616
1617 MYDB_BEGIN_ALLOW_THREADS;
1618 err = self->db->cursor(self->db, txn, &dbc, flags);
1619 MYDB_END_ALLOW_THREADS;
1620 RETURN_IF_ERR();
Jesus Cea6ba33292008-08-31 14:12:11 +00001621 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001622}
1623
1624
1625static PyObject*
1626DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1627{
1628 PyObject* txnobj = NULL;
1629 int flags = 0;
1630 PyObject* keyobj;
1631 DBT key;
1632 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001633 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001634
1635 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1636 &keyobj, &txnobj, &flags))
1637 return NULL;
1638 CHECK_DB_NOT_CLOSED(self);
Jesus Cea6ba33292008-08-31 14:12:11 +00001639 if (!make_key_dbt(self, keyobj, &key, NULL))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001640 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001641 if (!checkTxnObj(txnobj, &txn)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001642 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001643 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001644 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001645
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001646 if (-1 == _DB_delete(self, txn, &key, 0)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001647 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001648 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001649 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001650
Jesus Cea6ba33292008-08-31 14:12:11 +00001651 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001652 RETURN_NONE();
1653}
1654
1655
1656static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00001657DB_fd(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001658{
1659 int err, the_fd;
1660
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001661 CHECK_DB_NOT_CLOSED(self);
1662
1663 MYDB_BEGIN_ALLOW_THREADS;
1664 err = self->db->fd(self->db, &the_fd);
1665 MYDB_END_ALLOW_THREADS;
1666 RETURN_IF_ERR();
Jesus Cea6ba33292008-08-31 14:12:11 +00001667 return NUMBER_FromLong(the_fd);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001668}
1669
1670
1671static PyObject*
1672DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1673{
1674 int err, flags=0;
1675 PyObject* txnobj = NULL;
1676 PyObject* keyobj;
1677 PyObject* dfltobj = NULL;
1678 PyObject* retval = NULL;
1679 int dlen = -1;
1680 int doff = -1;
1681 DBT key, data;
1682 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001683 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001684 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001685
1686 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001687 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1688 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001689 return NULL;
1690
1691 CHECK_DB_NOT_CLOSED(self);
Jesus Cea6ba33292008-08-31 14:12:11 +00001692 if (!make_key_dbt(self, keyobj, &key, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001693 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001694 if (!checkTxnObj(txnobj, &txn)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001695 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001696 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001697 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001698
1699 CLEAR_DBT(data);
1700 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001701 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001702 data.flags = DB_DBT_MALLOC;
1703 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001704 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001705 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001706 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001707 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001708
1709 MYDB_BEGIN_ALLOW_THREADS;
1710 err = self->db->get(self->db, txn, &key, &data, flags);
1711 MYDB_END_ALLOW_THREADS;
1712
Gregory P. Smithe9477062005-06-04 06:46:59 +00001713 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714 err = 0;
1715 Py_INCREF(dfltobj);
1716 retval = dfltobj;
1717 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001718 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1719 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001720 err = 0;
1721 Py_INCREF(Py_None);
1722 retval = Py_None;
1723 }
1724 else if (!err) {
1725 if (flags & DB_SET_RECNO) /* return both key and data */
Jesus Cea6ba33292008-08-31 14:12:11 +00001726 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001727 else /* return just the data */
Jesus Cea6ba33292008-08-31 14:12:11 +00001728 retval = Build_PyString(data.data, data.size);
1729 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001730 }
Jesus Cea6ba33292008-08-31 14:12:11 +00001731 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001732
1733 RETURN_IF_ERR();
1734 return retval;
1735}
1736
Gregory P. Smith19699a92004-06-28 04:06:49 +00001737static PyObject*
1738DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1739{
1740 int err, flags=0;
1741 PyObject* txnobj = NULL;
1742 PyObject* keyobj;
1743 PyObject* dfltobj = NULL;
1744 PyObject* retval = NULL;
1745 int dlen = -1;
1746 int doff = -1;
1747 DBT key, pkey, data;
1748 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001749 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001750 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001751
1752 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1753 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1754 &doff))
1755 return NULL;
1756
1757 CHECK_DB_NOT_CLOSED(self);
Jesus Cea6ba33292008-08-31 14:12:11 +00001758 if (!make_key_dbt(self, keyobj, &key, &flags))
Gregory P. Smith19699a92004-06-28 04:06:49 +00001759 return NULL;
1760 if (!checkTxnObj(txnobj, &txn)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001761 FREE_DBT(key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001762 return NULL;
1763 }
1764
1765 CLEAR_DBT(data);
1766 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001767 /* Tell Berkeley DB to malloc the return value (thread safe) */
Gregory P. Smith19699a92004-06-28 04:06:49 +00001768 data.flags = DB_DBT_MALLOC;
1769 }
1770 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001771 FREE_DBT(key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001772 return NULL;
1773 }
1774
1775 CLEAR_DBT(pkey);
1776 pkey.flags = DB_DBT_MALLOC;
Jesus Cea6ba33292008-08-31 14:12:11 +00001777
Gregory P. Smith19699a92004-06-28 04:06:49 +00001778 MYDB_BEGIN_ALLOW_THREADS;
1779 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1780 MYDB_END_ALLOW_THREADS;
1781
Gregory P. Smithe9477062005-06-04 06:46:59 +00001782 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001783 err = 0;
1784 Py_INCREF(dfltobj);
1785 retval = dfltobj;
1786 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001787 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1788 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001789 err = 0;
1790 Py_INCREF(Py_None);
1791 retval = Py_None;
1792 }
1793 else if (!err) {
1794 PyObject *pkeyObj;
1795 PyObject *dataObj;
Jesus Cea6ba33292008-08-31 14:12:11 +00001796 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001797
1798 if (self->primaryDBType == DB_RECNO ||
1799 self->primaryDBType == DB_QUEUE)
Jesus Cea6ba33292008-08-31 14:12:11 +00001800 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001801 else
Jesus Cea6ba33292008-08-31 14:12:11 +00001802 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001803
1804 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1805 {
1806 PyObject *keyObj;
1807 int type = _DB_get_type(self);
1808 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Cea6ba33292008-08-31 14:12:11 +00001809 keyObj = NUMBER_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001810 else
Jesus Cea6ba33292008-08-31 14:12:11 +00001811 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001812#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001813 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001814#else
1815 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1816#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001817 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001818 }
1819 else /* return just the pkey and data */
1820 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001821#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001822 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001823#else
1824 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1825#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001826 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001827 Py_DECREF(dataObj);
1828 Py_DECREF(pkeyObj);
Jesus Cea6ba33292008-08-31 14:12:11 +00001829 FREE_DBT(pkey);
1830 FREE_DBT(data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001831 }
Jesus Cea6ba33292008-08-31 14:12:11 +00001832 FREE_DBT(key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001833
1834 RETURN_IF_ERR();
1835 return retval;
1836}
1837
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001838
1839/* Return size of entry */
1840static PyObject*
1841DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1842{
1843 int err, flags=0;
1844 PyObject* txnobj = NULL;
1845 PyObject* keyobj;
1846 PyObject* retval = NULL;
1847 DBT key, data;
1848 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001849 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001850
1851 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1852 &keyobj, &txnobj))
1853 return NULL;
1854 CHECK_DB_NOT_CLOSED(self);
Jesus Cea6ba33292008-08-31 14:12:11 +00001855 if (!make_key_dbt(self, keyobj, &key, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001856 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001857 if (!checkTxnObj(txnobj, &txn)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001858 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001859 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001860 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001861 CLEAR_DBT(data);
1862
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001863 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1864 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001865 data.flags = DB_DBT_USERMEM;
1866 data.ulen = 0;
1867 MYDB_BEGIN_ALLOW_THREADS;
1868 err = self->db->get(self->db, txn, &key, &data, flags);
1869 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001870 if (err == DB_BUFFER_SMALL) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001871 retval = NUMBER_FromLong((long)data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001872 err = 0;
1873 }
1874
Jesus Cea6ba33292008-08-31 14:12:11 +00001875 FREE_DBT(key);
1876 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001877 RETURN_IF_ERR();
1878 return retval;
1879}
1880
1881
1882static PyObject*
1883DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1884{
1885 int err, flags=0;
1886 PyObject* txnobj = NULL;
1887 PyObject* keyobj;
1888 PyObject* dataobj;
1889 PyObject* retval = NULL;
1890 DBT key, data;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001891 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001892 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001893 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001894
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001895 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1896 &keyobj, &dataobj, &txnobj, &flags))
1897 return NULL;
1898
1899 CHECK_DB_NOT_CLOSED(self);
Jesus Cea6ba33292008-08-31 14:12:11 +00001900 if (!make_key_dbt(self, keyobj, &key, NULL))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001901 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00001902 if ( !make_dbt(dataobj, &data) ||
1903 !checkTxnObj(txnobj, &txn) )
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001904 {
Jesus Cea6ba33292008-08-31 14:12:11 +00001905 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001906 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001907 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001908
1909 flags |= DB_GET_BOTH;
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001910 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001911
1912 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00001913 /* Tell Berkeley DB to malloc the return value (thread safe) */
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001914 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001915 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001916 }
1917
1918 MYDB_BEGIN_ALLOW_THREADS;
1919 err = self->db->get(self->db, txn, &key, &data, flags);
1920 MYDB_END_ALLOW_THREADS;
1921
Gregory P. Smithe9477062005-06-04 06:46:59 +00001922 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1923 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001924 err = 0;
1925 Py_INCREF(Py_None);
1926 retval = Py_None;
1927 }
1928 else if (!err) {
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001929 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Jesus Cea6ba33292008-08-31 14:12:11 +00001930 retval = Build_PyString(data.data, data.size);
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001931
1932 /* Even though the flags require DB_DBT_MALLOC, data is not always
1933 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1934 if (data.data != orig_data)
Jesus Cea6ba33292008-08-31 14:12:11 +00001935 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001936 }
1937
Jesus Cea6ba33292008-08-31 14:12:11 +00001938 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001939 RETURN_IF_ERR();
1940 return retval;
1941}
1942
1943
1944static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00001945DB_get_byteswapped(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001946{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001947 int err = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001948 int retval = -1;
1949
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001950 CHECK_DB_NOT_CLOSED(self);
1951
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001952 MYDB_BEGIN_ALLOW_THREADS;
1953 err = self->db->get_byteswapped(self->db, &retval);
1954 MYDB_END_ALLOW_THREADS;
1955 RETURN_IF_ERR();
Jesus Cea6ba33292008-08-31 14:12:11 +00001956 return NUMBER_FromLong(retval);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001957}
1958
1959
1960static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00001961DB_get_type(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001962{
1963 int type;
1964
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001965 CHECK_DB_NOT_CLOSED(self);
1966
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001967 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001968 if (type == -1)
1969 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00001970 return NUMBER_FromLong(type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001971}
1972
1973
1974static PyObject*
1975DB_join(DBObject* self, PyObject* args)
1976{
1977 int err, flags=0;
1978 int length, x;
1979 PyObject* cursorsObj;
1980 DBC** cursors;
1981 DBC* dbc;
1982
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001983 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1984 return NULL;
1985
1986 CHECK_DB_NOT_CLOSED(self);
1987
1988 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001989 PyErr_SetString(PyExc_TypeError,
1990 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001991 return NULL;
1992 }
1993
1994 length = PyObject_Length(cursorsObj);
1995 cursors = malloc((length+1) * sizeof(DBC*));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00001996 if (!cursors) {
1997 PyErr_NoMemory();
1998 return NULL;
1999 }
2000
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002001 cursors[length] = NULL;
2002 for (x=0; x<length; x++) {
2003 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00002004 if (item == NULL) {
2005 free(cursors);
2006 return NULL;
2007 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002008 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002009 PyErr_SetString(PyExc_TypeError,
2010 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002011 free(cursors);
2012 return NULL;
2013 }
2014 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002015 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002016 }
2017
2018 MYDB_BEGIN_ALLOW_THREADS;
2019 err = self->db->join(self->db, cursors, &dbc, flags);
2020 MYDB_END_ALLOW_THREADS;
2021 free(cursors);
2022 RETURN_IF_ERR();
2023
Gregory P. Smith7441e652003-11-03 21:35:31 +00002024 /* FIXME: this is a buggy interface. The returned cursor
2025 contains internal references to the passed in cursors
2026 but does not hold python references to them or prevent
2027 them from being closed prematurely. This can cause
2028 python to crash when things are done in the wrong order. */
Jesus Cea6ba33292008-08-31 14:12:11 +00002029 return (PyObject*) newDBCursorObject(dbc, NULL, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002030}
2031
2032
2033static PyObject*
2034DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
2035{
2036 int err, flags=0;
2037 PyObject* txnobj = NULL;
2038 PyObject* keyobj;
2039 DBT key;
2040 DB_TXN *txn = NULL;
2041 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002042 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002043
2044 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
2045 &keyobj, &txnobj, &flags))
2046 return NULL;
2047 CHECK_DB_NOT_CLOSED(self);
Jesus Cea6ba33292008-08-31 14:12:11 +00002048 if (!make_dbt(keyobj, &key))
Gregory P. Smith3d5cb222007-08-28 08:23:15 +00002049 /* BTree only, don't need to allow for an int key */
2050 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00002051 if (!checkTxnObj(txnobj, &txn))
2052 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002053
2054 MYDB_BEGIN_ALLOW_THREADS;
2055 err = self->db->key_range(self->db, txn, &key, &range, flags);
2056 MYDB_END_ALLOW_THREADS;
2057
2058 RETURN_IF_ERR();
2059 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2060}
2061
2062
2063static PyObject*
2064DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2065{
2066 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2067 char* filename = NULL;
2068 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002069#if (DBVER >= 41)
2070 PyObject *txnobj = NULL;
2071 DB_TXN *txn = NULL;
2072 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002073 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002074 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2075 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00002076 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002077 "filename", "dbtype", "flags", "mode", "txn", NULL};
2078#else
2079 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002080 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002081 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2082 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002083 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002084 "filename", "dbtype", "flags", "mode", NULL};
2085#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002086
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002087#if (DBVER >= 41)
2088 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2089 &filename, &dbname, &type, &flags, &mode,
2090 &txnobj))
2091#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002092 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002093 &filename, &dbname, &type, &flags,
2094 &mode))
2095#endif
2096 {
2097 PyErr_Clear();
2098 type = DB_UNKNOWN; flags = 0; mode = 0660;
2099 filename = NULL; dbname = NULL;
2100#if (DBVER >= 41)
2101 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2102 kwnames_basic,
2103 &filename, &type, &flags, &mode,
2104 &txnobj))
2105 return NULL;
2106#else
2107 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2108 kwnames_basic,
2109 &filename, &type, &flags, &mode))
2110 return NULL;
2111#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002112 }
2113
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002114#if (DBVER >= 41)
2115 if (!checkTxnObj(txnobj, &txn)) return NULL;
2116#endif
2117
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002118 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002119 PyObject *t = Py_BuildValue("(is)", 0,
2120 "Cannot call open() twice for DB object");
Jesus Cea6ba33292008-08-31 14:12:11 +00002121 if (t) {
2122 PyErr_SetObject(DBError, t);
2123 Py_DECREF(t);
2124 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002125 return NULL;
2126 }
2127
Jesus Cea6ba33292008-08-31 14:12:11 +00002128#if (DBVER >= 41)
2129 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2130 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2131 self->txn=(DBTxnObject *)txnobj;
2132 } else {
2133 self->txn=NULL;
2134 }
2135#else
2136 self->txn=NULL;
2137#endif
2138
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002139 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002140#if (DBVER >= 41)
2141 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2142#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002143 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002144#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002145 MYDB_END_ALLOW_THREADS;
2146 if (makeDBError(err)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00002147 PyObject *dummy;
2148
2149 dummy=DB_close_internal(self,0);
2150 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002151 return NULL;
2152 }
2153
Guido van Rossum77677112007-11-05 19:43:04 +00002154#if (DBVER >= 42)
2155 self->db->get_flags(self->db, &self->setflags);
2156#endif
2157
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002158 self->flags = flags;
Jesus Cea6ba33292008-08-31 14:12:11 +00002159
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002160 RETURN_NONE();
2161}
2162
2163
2164static PyObject*
2165DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2166{
2167 int flags=0;
2168 PyObject* txnobj = NULL;
2169 int dlen = -1;
2170 int doff = -1;
Jesus Cea6ba33292008-08-31 14:12:11 +00002171 PyObject* keyobj, *dataobj, *retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002172 DBT key, data;
2173 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002174 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002175 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002176
2177 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2178 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2179 return NULL;
2180
2181 CHECK_DB_NOT_CLOSED(self);
Jesus Cea6ba33292008-08-31 14:12:11 +00002182 if (!make_key_dbt(self, keyobj, &key, NULL))
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002183 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00002184 if ( !make_dbt(dataobj, &data) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002185 !add_partial_dbt(&data, dlen, doff) ||
2186 !checkTxnObj(txnobj, &txn) )
2187 {
Jesus Cea6ba33292008-08-31 14:12:11 +00002188 FREE_DBT(key);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002189 return NULL;
2190 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002191
2192 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00002193 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002194 return NULL;
2195 }
2196
2197 if (flags & DB_APPEND)
Jesus Cea6ba33292008-08-31 14:12:11 +00002198 retval = NUMBER_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002199 else {
2200 retval = Py_None;
2201 Py_INCREF(retval);
2202 }
Jesus Cea6ba33292008-08-31 14:12:11 +00002203 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002204 return retval;
2205}
2206
2207
2208
2209static PyObject*
2210DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2211{
2212 char* filename;
2213 char* database = NULL;
2214 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002215 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002216
2217 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2218 &filename, &database, &flags))
2219 return NULL;
2220 CHECK_DB_NOT_CLOSED(self);
2221
Jesus Cea6ba33292008-08-31 14:12:11 +00002222 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
2223
2224 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002225 err = self->db->remove(self->db, filename, database, flags);
Jesus Cea6ba33292008-08-31 14:12:11 +00002226 MYDB_END_ALLOW_THREADS;
2227
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002228 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002229 RETURN_IF_ERR();
2230 RETURN_NONE();
2231}
2232
2233
2234
2235static PyObject*
2236DB_rename(DBObject* self, PyObject* args)
2237{
2238 char* filename;
2239 char* database;
2240 char* newname;
2241 int err, flags=0;
2242
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002243 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2244 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002245 return NULL;
2246 CHECK_DB_NOT_CLOSED(self);
2247
2248 MYDB_BEGIN_ALLOW_THREADS;
2249 err = self->db->rename(self->db, filename, database, newname, flags);
2250 MYDB_END_ALLOW_THREADS;
2251 RETURN_IF_ERR();
2252 RETURN_NONE();
2253}
2254
2255
2256static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00002257DB_get_private(DBObject* self)
2258{
2259 /* We can give out the private field even if db is closed */
2260 Py_INCREF(self->private_obj);
2261 return self->private_obj;
2262}
2263
2264static PyObject*
2265DB_set_private(DBObject* self, PyObject* private_obj)
2266{
2267 /* We can set the private field even if db is closed */
2268 Py_DECREF(self->private_obj);
2269 Py_INCREF(private_obj);
2270 self->private_obj = private_obj;
2271 RETURN_NONE();
2272}
2273
2274
2275static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002276DB_set_bt_minkey(DBObject* self, PyObject* args)
2277{
2278 int err, minkey;
2279
2280 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2281 return NULL;
2282 CHECK_DB_NOT_CLOSED(self);
2283
2284 MYDB_BEGIN_ALLOW_THREADS;
2285 err = self->db->set_bt_minkey(self->db, minkey);
2286 MYDB_END_ALLOW_THREADS;
2287 RETURN_IF_ERR();
2288 RETURN_NONE();
2289}
2290
Jesus Cea6ba33292008-08-31 14:12:11 +00002291static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002292_default_cmp(const DBT *leftKey,
2293 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002294{
2295 int res;
2296 int lsize = leftKey->size, rsize = rightKey->size;
2297
Jesus Cea6ba33292008-08-31 14:12:11 +00002298 res = memcmp(leftKey->data, rightKey->data,
Georg Brandlef1701f2006-03-07 14:57:48 +00002299 lsize < rsize ? lsize : rsize);
Jesus Cea6ba33292008-08-31 14:12:11 +00002300
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002301 if (res == 0) {
2302 if (lsize < rsize) {
2303 res = -1;
2304 }
2305 else if (lsize > rsize) {
2306 res = 1;
2307 }
2308 }
2309 return res;
2310}
2311
2312static int
Jesus Cea6ba33292008-08-31 14:12:11 +00002313_db_compareCallback(DB* db,
Georg Brandlef1701f2006-03-07 14:57:48 +00002314 const DBT *leftKey,
2315 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002316{
2317 int res = 0;
2318 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002319 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002320 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002321
2322 if (self == NULL || self->btCompareCallback == NULL) {
2323 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002324 PyErr_SetString(PyExc_TypeError,
2325 (self == 0
2326 ? "DB_bt_compare db is NULL."
2327 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002328 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002329 PyErr_Print();
2330 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002331 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002332 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002333 MYDB_BEGIN_BLOCK_THREADS;
2334
Jesus Cea6ba33292008-08-31 14:12:11 +00002335 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002336 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002337 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002338 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002339 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002340 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002341 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002342 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002343 PyErr_Print();
2344 res = _default_cmp(leftKey, rightKey);
Jesus Cea6ba33292008-08-31 14:12:11 +00002345 } else if (NUMBER_Check(result)) {
2346 res = NUMBER_AsLong(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002347 } else {
2348 PyErr_SetString(PyExc_TypeError,
2349 "DB_bt_compare callback MUST return an int.");
2350 /* we're in a callback within the DB code, we can't raise */
2351 PyErr_Print();
2352 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002353 }
Jesus Cea6ba33292008-08-31 14:12:11 +00002354
Thomas Woutersb3153832006-03-08 01:47:19 +00002355 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002356 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002357
2358 MYDB_END_BLOCK_THREADS;
2359 }
2360 return res;
2361}
2362
2363static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00002364DB_set_bt_compare(DBObject* self, PyObject* comparator)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002365{
2366 int err;
Thomas Woutersb3153832006-03-08 01:47:19 +00002367 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002368
Georg Brandlef1701f2006-03-07 14:57:48 +00002369 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002370
Georg Brandlef1701f2006-03-07 14:57:48 +00002371 if (!PyCallable_Check(comparator)) {
2372 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002373 return NULL;
2374 }
2375
Jesus Cea6ba33292008-08-31 14:12:11 +00002376 /*
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002377 * Perform a test call of the comparator function with two empty
2378 * string objects here. verify that it returns an int (0).
2379 * err if not.
2380 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002381 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002382 result = PyEval_CallObject(comparator, tuple);
2383 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002384 if (result == NULL)
2385 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00002386 if (!NUMBER_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002387 PyErr_SetString(PyExc_TypeError,
2388 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002389 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00002390 } else if (NUMBER_AsLong(result) != 0) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002391 PyErr_SetString(PyExc_TypeError,
2392 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002393 return NULL;
2394 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002395 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002396
2397 /* We don't accept multiple set_bt_compare operations, in order to
2398 * simplify the code. This would have no real use, as one cannot
2399 * change the function once the db is opened anyway */
2400 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002401 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002402 return NULL;
2403 }
2404
Georg Brandlef1701f2006-03-07 14:57:48 +00002405 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002406 self->btCompareCallback = comparator;
2407
2408 /* This is to workaround a problem with un-initialized threads (see
2409 comment in DB_associate) */
2410#ifdef WITH_THREAD
2411 PyEval_InitThreads();
2412#endif
2413
Thomas Woutersb3153832006-03-08 01:47:19 +00002414 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002415
2416 if (err) {
2417 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002418 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002419 self->btCompareCallback = NULL;
2420 }
2421
Georg Brandlef1701f2006-03-07 14:57:48 +00002422 RETURN_IF_ERR();
2423 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002424}
2425
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002426
2427static PyObject*
2428DB_set_cachesize(DBObject* self, PyObject* args)
2429{
2430 int err;
2431 int gbytes = 0, bytes = 0, ncache = 0;
2432
2433 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2434 &gbytes,&bytes,&ncache))
2435 return NULL;
2436 CHECK_DB_NOT_CLOSED(self);
2437
2438 MYDB_BEGIN_ALLOW_THREADS;
2439 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2440 MYDB_END_ALLOW_THREADS;
2441 RETURN_IF_ERR();
2442 RETURN_NONE();
2443}
2444
2445
2446static PyObject*
2447DB_set_flags(DBObject* self, PyObject* args)
2448{
2449 int err, flags;
2450
2451 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2452 return NULL;
2453 CHECK_DB_NOT_CLOSED(self);
2454
2455 MYDB_BEGIN_ALLOW_THREADS;
2456 err = self->db->set_flags(self->db, flags);
2457 MYDB_END_ALLOW_THREADS;
2458 RETURN_IF_ERR();
2459
2460 self->setflags |= flags;
2461 RETURN_NONE();
2462}
2463
2464
2465static PyObject*
2466DB_set_h_ffactor(DBObject* self, PyObject* args)
2467{
2468 int err, ffactor;
2469
2470 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2471 return NULL;
2472 CHECK_DB_NOT_CLOSED(self);
2473
2474 MYDB_BEGIN_ALLOW_THREADS;
2475 err = self->db->set_h_ffactor(self->db, ffactor);
2476 MYDB_END_ALLOW_THREADS;
2477 RETURN_IF_ERR();
2478 RETURN_NONE();
2479}
2480
2481
2482static PyObject*
2483DB_set_h_nelem(DBObject* self, PyObject* args)
2484{
2485 int err, nelem;
2486
2487 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2488 return NULL;
2489 CHECK_DB_NOT_CLOSED(self);
2490
2491 MYDB_BEGIN_ALLOW_THREADS;
2492 err = self->db->set_h_nelem(self->db, nelem);
2493 MYDB_END_ALLOW_THREADS;
2494 RETURN_IF_ERR();
2495 RETURN_NONE();
2496}
2497
2498
2499static PyObject*
2500DB_set_lorder(DBObject* self, PyObject* args)
2501{
2502 int err, lorder;
2503
2504 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2505 return NULL;
2506 CHECK_DB_NOT_CLOSED(self);
2507
2508 MYDB_BEGIN_ALLOW_THREADS;
2509 err = self->db->set_lorder(self->db, lorder);
2510 MYDB_END_ALLOW_THREADS;
2511 RETURN_IF_ERR();
2512 RETURN_NONE();
2513}
2514
2515
2516static PyObject*
2517DB_set_pagesize(DBObject* self, PyObject* args)
2518{
2519 int err, pagesize;
2520
2521 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2522 return NULL;
2523 CHECK_DB_NOT_CLOSED(self);
2524
2525 MYDB_BEGIN_ALLOW_THREADS;
2526 err = self->db->set_pagesize(self->db, pagesize);
2527 MYDB_END_ALLOW_THREADS;
2528 RETURN_IF_ERR();
2529 RETURN_NONE();
2530}
2531
2532
2533static PyObject*
2534DB_set_re_delim(DBObject* self, PyObject* args)
2535{
2536 int err;
2537 char delim;
2538
2539 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2540 PyErr_Clear();
2541 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2542 return NULL;
2543 }
2544
2545 CHECK_DB_NOT_CLOSED(self);
2546
2547 MYDB_BEGIN_ALLOW_THREADS;
2548 err = self->db->set_re_delim(self->db, delim);
2549 MYDB_END_ALLOW_THREADS;
2550 RETURN_IF_ERR();
2551 RETURN_NONE();
2552}
2553
2554static PyObject*
2555DB_set_re_len(DBObject* self, PyObject* args)
2556{
2557 int err, len;
2558
2559 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2560 return NULL;
2561 CHECK_DB_NOT_CLOSED(self);
2562
2563 MYDB_BEGIN_ALLOW_THREADS;
2564 err = self->db->set_re_len(self->db, len);
2565 MYDB_END_ALLOW_THREADS;
2566 RETURN_IF_ERR();
2567 RETURN_NONE();
2568}
2569
2570
2571static PyObject*
2572DB_set_re_pad(DBObject* self, PyObject* args)
2573{
2574 int err;
2575 char pad;
2576
2577 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2578 PyErr_Clear();
2579 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2580 return NULL;
2581 }
2582 CHECK_DB_NOT_CLOSED(self);
2583
2584 MYDB_BEGIN_ALLOW_THREADS;
2585 err = self->db->set_re_pad(self->db, pad);
2586 MYDB_END_ALLOW_THREADS;
2587 RETURN_IF_ERR();
2588 RETURN_NONE();
2589}
2590
2591
2592static PyObject*
2593DB_set_re_source(DBObject* self, PyObject* args)
2594{
2595 int err;
2596 char *re_source;
2597
2598 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2599 return NULL;
2600 CHECK_DB_NOT_CLOSED(self);
2601
2602 MYDB_BEGIN_ALLOW_THREADS;
2603 err = self->db->set_re_source(self->db, re_source);
2604 MYDB_END_ALLOW_THREADS;
2605 RETURN_IF_ERR();
2606 RETURN_NONE();
2607}
2608
2609
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002610static PyObject*
2611DB_set_q_extentsize(DBObject* self, PyObject* args)
2612{
2613 int err;
2614 int extentsize;
2615
2616 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2617 return NULL;
2618 CHECK_DB_NOT_CLOSED(self);
2619
2620 MYDB_BEGIN_ALLOW_THREADS;
2621 err = self->db->set_q_extentsize(self->db, extentsize);
2622 MYDB_END_ALLOW_THREADS;
2623 RETURN_IF_ERR();
2624 RETURN_NONE();
2625}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002626
2627static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002628DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002629{
2630 int err, flags = 0, type;
2631 void* sp;
2632 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002633#if (DBVER >= 43)
2634 PyObject* txnobj = NULL;
2635 DB_TXN *txn = NULL;
Thomas Wouters89f507f2006-12-13 04:49:30 +00002636 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002637#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002638 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002639#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002640
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002641#if (DBVER >= 43)
2642 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2643 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002644 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002645 if (!checkTxnObj(txnobj, &txn))
2646 return NULL;
2647#else
2648 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2649 return NULL;
2650#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002651 CHECK_DB_NOT_CLOSED(self);
2652
2653 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002654#if (DBVER >= 43)
2655 err = self->db->stat(self->db, txn, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002656#else
Jesus Cea6ba33292008-08-31 14:12:11 +00002657 err = self->db->stat(self->db, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002658#endif
2659 MYDB_END_ALLOW_THREADS;
2660 RETURN_IF_ERR();
2661
2662 self->haveStat = 1;
2663
2664 /* Turn the stat structure into a dictionary */
2665 type = _DB_get_type(self);
2666 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2667 free(sp);
2668 return NULL;
2669 }
2670
2671#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2672#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2673#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2674
2675 switch (type) {
2676 case DB_HASH:
2677 MAKE_HASH_ENTRY(magic);
2678 MAKE_HASH_ENTRY(version);
2679 MAKE_HASH_ENTRY(nkeys);
2680 MAKE_HASH_ENTRY(ndata);
Jesus Cea6ba33292008-08-31 14:12:11 +00002681#if (DBVER >= 46)
2682 MAKE_HASH_ENTRY(pagecnt);
2683#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002684 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002685#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002686 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002687#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002688 MAKE_HASH_ENTRY(ffactor);
2689 MAKE_HASH_ENTRY(buckets);
2690 MAKE_HASH_ENTRY(free);
2691 MAKE_HASH_ENTRY(bfree);
2692 MAKE_HASH_ENTRY(bigpages);
2693 MAKE_HASH_ENTRY(big_bfree);
2694 MAKE_HASH_ENTRY(overflows);
2695 MAKE_HASH_ENTRY(ovfl_free);
2696 MAKE_HASH_ENTRY(dup);
2697 MAKE_HASH_ENTRY(dup_free);
2698 break;
2699
2700 case DB_BTREE:
2701 case DB_RECNO:
2702 MAKE_BT_ENTRY(magic);
2703 MAKE_BT_ENTRY(version);
2704 MAKE_BT_ENTRY(nkeys);
2705 MAKE_BT_ENTRY(ndata);
Jesus Cea6ba33292008-08-31 14:12:11 +00002706#if (DBVER >= 46)
2707 MAKE_BT_ENTRY(pagecnt);
2708#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002709 MAKE_BT_ENTRY(pagesize);
2710 MAKE_BT_ENTRY(minkey);
2711 MAKE_BT_ENTRY(re_len);
2712 MAKE_BT_ENTRY(re_pad);
2713 MAKE_BT_ENTRY(levels);
2714 MAKE_BT_ENTRY(int_pg);
2715 MAKE_BT_ENTRY(leaf_pg);
2716 MAKE_BT_ENTRY(dup_pg);
2717 MAKE_BT_ENTRY(over_pg);
Jesus Cea6ba33292008-08-31 14:12:11 +00002718#if (DBVER >= 43)
2719 MAKE_BT_ENTRY(empty_pg);
2720#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002721 MAKE_BT_ENTRY(free);
2722 MAKE_BT_ENTRY(int_pgfree);
2723 MAKE_BT_ENTRY(leaf_pgfree);
2724 MAKE_BT_ENTRY(dup_pgfree);
2725 MAKE_BT_ENTRY(over_pgfree);
2726 break;
2727
2728 case DB_QUEUE:
2729 MAKE_QUEUE_ENTRY(magic);
2730 MAKE_QUEUE_ENTRY(version);
2731 MAKE_QUEUE_ENTRY(nkeys);
2732 MAKE_QUEUE_ENTRY(ndata);
2733 MAKE_QUEUE_ENTRY(pagesize);
Jesus Cea6ba33292008-08-31 14:12:11 +00002734#if (DBVER >= 41)
2735 MAKE_QUEUE_ENTRY(extentsize);
2736#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002737 MAKE_QUEUE_ENTRY(pages);
2738 MAKE_QUEUE_ENTRY(re_len);
2739 MAKE_QUEUE_ENTRY(re_pad);
2740 MAKE_QUEUE_ENTRY(pgfree);
2741#if (DBVER == 31)
2742 MAKE_QUEUE_ENTRY(start);
2743#endif
2744 MAKE_QUEUE_ENTRY(first_recno);
2745 MAKE_QUEUE_ENTRY(cur_recno);
2746 break;
2747
2748 default:
2749 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2750 Py_DECREF(d);
2751 d = NULL;
2752 }
2753
2754#undef MAKE_HASH_ENTRY
2755#undef MAKE_BT_ENTRY
2756#undef MAKE_QUEUE_ENTRY
2757
2758 free(sp);
2759 return d;
2760}
2761
2762static PyObject*
2763DB_sync(DBObject* self, PyObject* args)
2764{
2765 int err;
2766 int flags = 0;
2767
2768 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2769 return NULL;
2770 CHECK_DB_NOT_CLOSED(self);
2771
2772 MYDB_BEGIN_ALLOW_THREADS;
2773 err = self->db->sync(self->db, flags);
2774 MYDB_END_ALLOW_THREADS;
2775 RETURN_IF_ERR();
2776 RETURN_NONE();
2777}
2778
2779
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002780static PyObject*
2781DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2782{
2783 int err, flags=0;
2784 u_int32_t count=0;
2785 PyObject* txnobj = NULL;
2786 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002787 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002788
2789 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2790 &txnobj, &flags))
2791 return NULL;
2792 CHECK_DB_NOT_CLOSED(self);
2793 if (!checkTxnObj(txnobj, &txn))
2794 return NULL;
2795
2796 MYDB_BEGIN_ALLOW_THREADS;
2797 err = self->db->truncate(self->db, txn, &count, flags);
2798 MYDB_END_ALLOW_THREADS;
2799 RETURN_IF_ERR();
Jesus Cea6ba33292008-08-31 14:12:11 +00002800 return NUMBER_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002801}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002802
2803
2804static PyObject*
2805DB_upgrade(DBObject* self, PyObject* args)
2806{
2807 int err, flags=0;
2808 char *filename;
2809
2810 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2811 return NULL;
2812 CHECK_DB_NOT_CLOSED(self);
2813
2814 MYDB_BEGIN_ALLOW_THREADS;
2815 err = self->db->upgrade(self->db, filename, flags);
2816 MYDB_END_ALLOW_THREADS;
2817 RETURN_IF_ERR();
2818 RETURN_NONE();
2819}
2820
2821
2822static PyObject*
2823DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2824{
2825 int err, flags=0;
2826 char* fileName;
2827 char* dbName=NULL;
2828 char* outFileName=NULL;
2829 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002830 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002831 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002832
2833 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2834 &fileName, &dbName, &outFileName, &flags))
2835 return NULL;
2836
2837 CHECK_DB_NOT_CLOSED(self);
2838 if (outFileName)
2839 outFile = fopen(outFileName, "w");
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002840 /* XXX(nnorwitz): it should probably be an exception if outFile
2841 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002842
2843 MYDB_BEGIN_ALLOW_THREADS;
2844 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2845 MYDB_END_ALLOW_THREADS;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002846 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002847 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002848
Jesus Cea6ba33292008-08-31 14:12:11 +00002849 { /* DB.verify acts as a DB handle destructor (like close) */
2850 PyObject *error;
2851
2852 error=DB_close_internal(self,0);
2853 if (error ) {
2854 return error;
2855 }
2856 }
Gregory P. Smith41631e82003-09-21 00:08:14 +00002857
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858 RETURN_IF_ERR();
2859 RETURN_NONE();
2860}
2861
2862
2863static PyObject*
2864DB_set_get_returns_none(DBObject* self, PyObject* args)
2865{
2866 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002867 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002868
2869 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2870 return NULL;
2871 CHECK_DB_NOT_CLOSED(self);
2872
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002873 if (self->moduleFlags.getReturnsNone)
2874 ++oldValue;
2875 if (self->moduleFlags.cursorSetReturnsNone)
2876 ++oldValue;
2877 self->moduleFlags.getReturnsNone = (flags >= 1);
2878 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Jesus Cea6ba33292008-08-31 14:12:11 +00002879 return NUMBER_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002880}
2881
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002882#if (DBVER >= 41)
2883static PyObject*
2884DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2885{
2886 int err;
2887 u_int32_t flags=0;
2888 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002889 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002890
2891 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2892 &passwd, &flags)) {
2893 return NULL;
2894 }
2895
2896 MYDB_BEGIN_ALLOW_THREADS;
2897 err = self->db->set_encrypt(self->db, passwd, flags);
2898 MYDB_END_ALLOW_THREADS;
2899
2900 RETURN_IF_ERR();
2901 RETURN_NONE();
2902}
2903#endif /* DBVER >= 41 */
2904
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002905
2906/*-------------------------------------------------------------- */
2907/* Mapping and Dictionary-like access routines */
2908
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002909Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002910{
2911 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002912 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002913 int flags = 0;
2914 void* sp;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002915 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002916
2917 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002918 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
Jesus Cea6ba33292008-08-31 14:12:11 +00002919 if (t) {
2920 PyErr_SetObject(DBError, t);
2921 Py_DECREF(t);
2922 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002923 return -1;
2924 }
2925
2926 if (self->haveStat) { /* Has the stat function been called recently? If
2927 so, we can use the cached value. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002928 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002929 }
2930
2931 MYDB_BEGIN_ALLOW_THREADS;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002932redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002933#if (DBVER >= 43)
2934 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002935#else
Jesus Cea6ba33292008-08-31 14:12:11 +00002936 err = self->db->stat(self->db, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002937#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002938
2939 /* All the stat structures have matching fields upto the ndata field,
2940 so we can use any of them for the type cast */
2941 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2942
Jesus Cea6ba33292008-08-31 14:12:11 +00002943 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002944 * redo a full stat to make sure.
2945 * Fixes SF python bug 1493322, pybsddb bug 1184012
2946 */
2947 if (size == 0 && (flags & DB_FAST_STAT)) {
2948 flags = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002949 if (!err)
2950 free(sp);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002951 goto redo_stat_for_length;
2952 }
2953
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002954 MYDB_END_ALLOW_THREADS;
2955
2956 if (err)
2957 return -1;
2958
2959 self->haveStat = 1;
2960
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002961 free(sp);
2962 return size;
2963}
2964
2965
2966PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2967{
2968 int err;
2969 PyObject* retval;
2970 DBT key;
2971 DBT data;
2972
2973 CHECK_DB_NOT_CLOSED(self);
Jesus Cea6ba33292008-08-31 14:12:11 +00002974 if (!make_key_dbt(self, keyobj, &key, NULL))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002975 return NULL;
2976
2977 CLEAR_DBT(data);
2978 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00002979 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002980 data.flags = DB_DBT_MALLOC;
2981 }
2982 MYDB_BEGIN_ALLOW_THREADS;
2983 err = self->db->get(self->db, NULL, &key, &data, 0);
2984 MYDB_END_ALLOW_THREADS;
2985 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2986 PyErr_SetObject(PyExc_KeyError, keyobj);
2987 retval = NULL;
2988 }
2989 else if (makeDBError(err)) {
2990 retval = NULL;
2991 }
2992 else {
Jesus Cea6ba33292008-08-31 14:12:11 +00002993 retval = Build_PyString(data.data, data.size);
2994 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002995 }
2996
Jesus Cea6ba33292008-08-31 14:12:11 +00002997 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002998 return retval;
2999}
3000
3001
3002static int
3003DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
3004{
3005 DBT key, data;
3006 int retval;
3007 int flags = 0;
3008
3009 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00003010 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
Jesus Cea6ba33292008-08-31 14:12:11 +00003011 if (t) {
3012 PyErr_SetObject(DBError, t);
3013 Py_DECREF(t);
3014 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003015 return -1;
3016 }
3017
Jesus Cea6ba33292008-08-31 14:12:11 +00003018 if (!make_key_dbt(self, keyobj, &key, NULL))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003019 return -1;
3020
3021 if (dataobj != NULL) {
Jesus Cea6ba33292008-08-31 14:12:11 +00003022 if (!make_dbt(dataobj, &data))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003023 retval = -1;
3024 else {
3025 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003026 /* dictionaries shouldn't have duplicate keys */
3027 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003028 retval = _DB_put(self, NULL, &key, &data, flags);
3029
3030 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003031 /* try deleting any old record that matches and then PUT it
3032 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003033 _DB_delete(self, NULL, &key, 0);
3034 PyErr_Clear();
3035 retval = _DB_put(self, NULL, &key, &data, flags);
3036 }
3037 }
3038 }
3039 else {
3040 /* dataobj == NULL, so delete the key */
3041 retval = _DB_delete(self, NULL, &key, 0);
3042 }
Jesus Cea6ba33292008-08-31 14:12:11 +00003043 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003044 return retval;
3045}
3046
3047
3048static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00003049DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003050{
3051 int err;
3052 PyObject* keyobj;
3053 DBT key, data;
3054 PyObject* txnobj = NULL;
3055 DB_TXN *txn = NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00003056 static char* kwnames[] = {"key","txn", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003057
Jesus Cea6ba33292008-08-31 14:12:11 +00003058 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
3059 &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003060 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00003061
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003062 CHECK_DB_NOT_CLOSED(self);
Jesus Cea6ba33292008-08-31 14:12:11 +00003063 if (!make_key_dbt(self, keyobj, &key, NULL))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003064 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003065 if (!checkTxnObj(txnobj, &txn)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00003066 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003067 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003068 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003069
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003070 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003071 it has a record but can't allocate a buffer for the data. This saves
3072 having to deal with data we won't be using.
3073 */
3074 CLEAR_DBT(data);
3075 data.flags = DB_DBT_USERMEM;
3076
3077 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00003078 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003079 MYDB_END_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003080 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003081
3082 if (err == DB_BUFFER_SMALL || err == 0) {
Jesus Cea6ba33292008-08-31 14:12:11 +00003083 return NUMBER_FromLong(1);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003084 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
Jesus Cea6ba33292008-08-31 14:12:11 +00003085 return NUMBER_FromLong(0);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003086 }
3087
3088 makeDBError(err);
3089 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003090}
3091
3092
3093#define _KEYS_LIST 1
3094#define _VALUES_LIST 2
3095#define _ITEMS_LIST 3
3096
3097static PyObject*
3098_DB_make_list(DBObject* self, DB_TXN* txn, int type)
3099{
3100 int err, dbtype;
3101 DBT key;
3102 DBT data;
3103 DBC *cursor;
3104 PyObject* list;
3105 PyObject* item = NULL;
3106
3107 CHECK_DB_NOT_CLOSED(self);
3108 CLEAR_DBT(key);
3109 CLEAR_DBT(data);
3110
3111 dbtype = _DB_get_type(self);
3112 if (dbtype == -1)
3113 return NULL;
3114
3115 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00003116 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003117 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003118
3119 /* get a cursor */
3120 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00003121 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003122 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00003123 if (makeDBError(err)) {
3124 Py_DECREF(list);
3125 return NULL;
3126 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003127
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003128 while (1) { /* use the cursor to traverse the DB, collecting items */
3129 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003130 err = _DBC_get(cursor, &key, &data, DB_NEXT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003131 MYDB_END_ALLOW_THREADS;
3132
3133 if (err) {
3134 /* for any error, break out of the loop */
3135 break;
3136 }
3137
3138 switch (type) {
3139 case _KEYS_LIST:
3140 switch(dbtype) {
3141 case DB_BTREE:
3142 case DB_HASH:
3143 default:
Jesus Cea6ba33292008-08-31 14:12:11 +00003144 item = Build_PyString(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003145 break;
3146 case DB_RECNO:
3147 case DB_QUEUE:
Jesus Cea6ba33292008-08-31 14:12:11 +00003148 item = NUMBER_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003149 break;
3150 }
3151 break;
3152
3153 case _VALUES_LIST:
Jesus Cea6ba33292008-08-31 14:12:11 +00003154 item = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003155 break;
3156
3157 case _ITEMS_LIST:
3158 switch(dbtype) {
3159 case DB_BTREE:
3160 case DB_HASH:
3161 default:
Jesus Cea6ba33292008-08-31 14:12:11 +00003162 item = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003163 break;
3164 case DB_RECNO:
3165 case DB_QUEUE:
Jesus Cea6ba33292008-08-31 14:12:11 +00003166 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003167 break;
3168 }
3169 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00003170 default:
3171 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3172 item = NULL;
3173 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003174 }
3175 if (item == NULL) {
3176 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003177 list = NULL;
3178 goto done;
3179 }
Jesus Cea6ba33292008-08-31 14:12:11 +00003180 if (PyList_Append(list, item)) {
3181 Py_DECREF(list);
3182 Py_DECREF(item);
3183 list = NULL;
3184 goto done;
3185 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003186 Py_DECREF(item);
3187 }
3188
Gregory P. Smithe9477062005-06-04 06:46:59 +00003189 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3190 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003191 Py_DECREF(list);
3192 list = NULL;
3193 }
3194
3195 done:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003196 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003197 _DBC_close(cursor);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003198 MYDB_END_ALLOW_THREADS;
3199 return list;
3200}
3201
3202
3203static PyObject*
3204DB_keys(DBObject* self, PyObject* args)
3205{
3206 PyObject* txnobj = NULL;
3207 DB_TXN *txn = NULL;
3208
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003209 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003210 return NULL;
3211 if (!checkTxnObj(txnobj, &txn))
3212 return NULL;
3213 return _DB_make_list(self, txn, _KEYS_LIST);
3214}
3215
3216
3217static PyObject*
3218DB_items(DBObject* self, PyObject* args)
3219{
3220 PyObject* txnobj = NULL;
3221 DB_TXN *txn = NULL;
3222
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003223 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003224 return NULL;
3225 if (!checkTxnObj(txnobj, &txn))
3226 return NULL;
3227 return _DB_make_list(self, txn, _ITEMS_LIST);
3228}
3229
3230
3231static PyObject*
3232DB_values(DBObject* self, PyObject* args)
3233{
3234 PyObject* txnobj = NULL;
3235 DB_TXN *txn = NULL;
3236
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00003237 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003238 return NULL;
3239 if (!checkTxnObj(txnobj, &txn))
3240 return NULL;
3241 return _DB_make_list(self, txn, _VALUES_LIST);
3242}
3243
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003244/* --------------------------------------------------------------------- */
3245/* DBCursor methods */
3246
3247
3248static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00003249DBC_close_internal(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003250{
3251 int err = 0;
3252
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003253 if (self->dbc != NULL) {
Jesus Cea6ba33292008-08-31 14:12:11 +00003254 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3255 if (self->txn) {
3256 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3257 self->txn=NULL;
3258 }
3259
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003260 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003261 err = _DBC_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003262 MYDB_END_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003263 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003264 }
3265 RETURN_IF_ERR();
3266 RETURN_NONE();
3267}
3268
Jesus Cea6ba33292008-08-31 14:12:11 +00003269static PyObject*
3270DBC_close(DBCursorObject* self)
3271{
3272 return DBC_close_internal(self);
3273}
3274
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003275
3276static PyObject*
3277DBC_count(DBCursorObject* self, PyObject* args)
3278{
3279 int err = 0;
3280 db_recno_t count;
3281 int flags = 0;
3282
3283 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3284 return NULL;
3285
3286 CHECK_CURSOR_NOT_CLOSED(self);
3287
3288 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003289 err = _DBC_count(self->dbc, &count, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003290 MYDB_END_ALLOW_THREADS;
3291 RETURN_IF_ERR();
3292
Jesus Cea6ba33292008-08-31 14:12:11 +00003293 return NUMBER_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003294}
3295
3296
3297static PyObject*
3298DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3299{
3300 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3301}
3302
3303
3304static PyObject*
3305DBC_delete(DBCursorObject* self, PyObject* args)
3306{
3307 int err, flags=0;
3308
3309 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3310 return NULL;
3311
3312 CHECK_CURSOR_NOT_CLOSED(self);
3313
3314 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003315 err = _DBC_del(self->dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003316 MYDB_END_ALLOW_THREADS;
3317 RETURN_IF_ERR();
3318
3319 self->mydb->haveStat = 0;
3320 RETURN_NONE();
3321}
3322
3323
3324static PyObject*
3325DBC_dup(DBCursorObject* self, PyObject* args)
3326{
3327 int err, flags =0;
3328 DBC* dbc = NULL;
3329
3330 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3331 return NULL;
3332
3333 CHECK_CURSOR_NOT_CLOSED(self);
3334
3335 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003336 err = _DBC_dup(self->dbc, &dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003337 MYDB_END_ALLOW_THREADS;
3338 RETURN_IF_ERR();
3339
Jesus Cea6ba33292008-08-31 14:12:11 +00003340 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003341}
3342
3343static PyObject*
3344DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3345{
3346 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3347}
3348
3349
3350static PyObject*
3351DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3352{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003353 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003354 PyObject* keyobj = NULL;
3355 PyObject* dataobj = NULL;
3356 PyObject* retval = NULL;
3357 int dlen = -1;
3358 int doff = -1;
3359 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003360 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003361 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003362
3363 CLEAR_DBT(key);
3364 CLEAR_DBT(data);
3365 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003366 &flags, &dlen, &doff))
3367 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003368 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003369 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
Jesus Cea6ba33292008-08-31 14:12:11 +00003370 &kwnames[1],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003371 &keyobj, &flags, &dlen, &doff))
3372 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003373 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003374 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3375 kwnames, &keyobj, &dataobj,
3376 &flags, &dlen, &doff))
3377 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003378 return NULL;
3379 }
3380 }
3381 }
3382
3383 CHECK_CURSOR_NOT_CLOSED(self);
3384
Jesus Cea6ba33292008-08-31 14:12:11 +00003385 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003386 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00003387 if ( (dataobj && !make_dbt(dataobj, &data)) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003388 (!add_partial_dbt(&data, dlen, doff)) )
3389 {
Jesus Cea6ba33292008-08-31 14:12:11 +00003390 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003391 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003392 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003393
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003394 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003395 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003396 MYDB_END_ALLOW_THREADS;
3397
Gregory P. Smithe9477062005-06-04 06:46:59 +00003398 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3399 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003400 Py_INCREF(Py_None);
3401 retval = Py_None;
3402 }
3403 else if (makeDBError(err)) {
3404 retval = NULL;
3405 }
3406 else {
3407 switch (_DB_get_type(self->mydb)) {
3408 case -1:
3409 retval = NULL;
3410 break;
3411 case DB_BTREE:
3412 case DB_HASH:
3413 default:
Jesus Cea6ba33292008-08-31 14:12:11 +00003414 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003415 break;
3416 case DB_RECNO:
3417 case DB_QUEUE:
Jesus Cea6ba33292008-08-31 14:12:11 +00003418 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003419 break;
3420 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003421 }
Jesus Cea6ba33292008-08-31 14:12:11 +00003422 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003423 return retval;
3424}
3425
Gregory P. Smith19699a92004-06-28 04:06:49 +00003426static PyObject*
3427DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3428{
3429 int err, flags=0;
3430 PyObject* keyobj = NULL;
3431 PyObject* dataobj = NULL;
3432 PyObject* retval = NULL;
3433 int dlen = -1;
3434 int doff = -1;
3435 DBT key, pkey, data;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003436 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3437 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003438
3439 CLEAR_DBT(key);
3440 CLEAR_DBT(data);
3441 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3442 &flags, &dlen, &doff))
3443 {
3444 PyErr_Clear();
3445 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00003446 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003447 &keyobj, &flags, &dlen, &doff))
3448 {
3449 PyErr_Clear();
3450 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3451 kwnames, &keyobj, &dataobj,
3452 &flags, &dlen, &doff))
3453 {
3454 return NULL;
3455 }
3456 }
3457 }
3458
3459 CHECK_CURSOR_NOT_CLOSED(self);
3460
Jesus Cea6ba33292008-08-31 14:12:11 +00003461 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
Gregory P. Smith19699a92004-06-28 04:06:49 +00003462 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00003463 if ( (dataobj && !make_dbt(dataobj, &data)) ||
Gregory P. Smith19699a92004-06-28 04:06:49 +00003464 (!add_partial_dbt(&data, dlen, doff)) ) {
Jesus Cea6ba33292008-08-31 14:12:11 +00003465 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003466 return NULL;
3467 }
3468
Gregory P. Smith19699a92004-06-28 04:06:49 +00003469 CLEAR_DBT(pkey);
3470 pkey.flags = DB_DBT_MALLOC;
3471
3472 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003473 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003474 MYDB_END_ALLOW_THREADS;
3475
Gregory P. Smithe9477062005-06-04 06:46:59 +00003476 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3477 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003478 Py_INCREF(Py_None);
3479 retval = Py_None;
3480 }
3481 else if (makeDBError(err)) {
3482 retval = NULL;
3483 }
3484 else {
3485 PyObject *pkeyObj;
3486 PyObject *dataObj;
Jesus Cea6ba33292008-08-31 14:12:11 +00003487 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003488
3489 if (self->mydb->primaryDBType == DB_RECNO ||
3490 self->mydb->primaryDBType == DB_QUEUE)
Jesus Cea6ba33292008-08-31 14:12:11 +00003491 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003492 else
Jesus Cea6ba33292008-08-31 14:12:11 +00003493 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003494
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003495 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003496 {
3497 PyObject *keyObj;
3498 int type = _DB_get_type(self->mydb);
3499 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Cea6ba33292008-08-31 14:12:11 +00003500 keyObj = NUMBER_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003501 else
Jesus Cea6ba33292008-08-31 14:12:11 +00003502 keyObj = Build_PyString(key.data, key.size);
3503#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003504 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Jesus Cea6ba33292008-08-31 14:12:11 +00003505#else
3506 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3507#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003508 Py_DECREF(keyObj);
Jesus Cea6ba33292008-08-31 14:12:11 +00003509 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003510 }
3511 else /* return just the pkey and data */
3512 {
Jesus Cea6ba33292008-08-31 14:12:11 +00003513#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003514 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Jesus Cea6ba33292008-08-31 14:12:11 +00003515#else
3516 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3517#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003518 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003519 Py_DECREF(dataObj);
3520 Py_DECREF(pkeyObj);
Jesus Cea6ba33292008-08-31 14:12:11 +00003521 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003522 }
3523 /* the only time REALLOC should be set is if we used an integer
3524 * key that make_key_dbt malloc'd for us. always free these. */
Jesus Cea6ba33292008-08-31 14:12:11 +00003525 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
3526 FREE_DBT(key);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003527 }
3528 return retval;
3529}
3530
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003531
3532static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00003533DBC_get_recno(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003534{
3535 int err;
3536 db_recno_t recno;
3537 DBT key;
3538 DBT data;
3539
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003540 CHECK_CURSOR_NOT_CLOSED(self);
3541
3542 CLEAR_DBT(key);
3543 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003544
3545 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003546 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003547 MYDB_END_ALLOW_THREADS;
3548 RETURN_IF_ERR();
3549
3550 recno = *((db_recno_t*)data.data);
Jesus Cea6ba33292008-08-31 14:12:11 +00003551 return NUMBER_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003552}
3553
3554
3555static PyObject*
3556DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3557{
3558 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3559}
3560
3561
3562static PyObject*
3563DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3564{
3565 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3566}
3567
3568
3569static PyObject*
3570DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3571{
3572 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3573}
3574
3575
3576static PyObject*
3577DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3578{
3579 int err, flags = 0;
Jesus Cea6ba33292008-08-31 14:12:11 +00003580 PyObject* keyobj, *dataobj;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003581 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003582 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003583 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003584 int dlen = -1;
3585 int doff = -1;
3586
3587 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3588 &keyobj, &dataobj, &flags, &dlen, &doff))
3589 return NULL;
3590
3591 CHECK_CURSOR_NOT_CLOSED(self);
3592
Jesus Cea6ba33292008-08-31 14:12:11 +00003593 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003594 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00003595 if (!make_dbt(dataobj, &data) ||
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003596 !add_partial_dbt(&data, dlen, doff) )
3597 {
Jesus Cea6ba33292008-08-31 14:12:11 +00003598 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003599 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003600 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003601
3602 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003603 err = _DBC_put(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003604 MYDB_END_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003605 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003606 RETURN_IF_ERR();
3607 self->mydb->haveStat = 0;
3608 RETURN_NONE();
3609}
3610
3611
3612static PyObject*
3613DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3614{
3615 int err, flags = 0;
3616 DBT key, data;
Jesus Cea6ba33292008-08-31 14:12:11 +00003617 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003618 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003619 int dlen = -1;
3620 int doff = -1;
3621
3622 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3623 &keyobj, &flags, &dlen, &doff))
3624 return NULL;
3625
3626 CHECK_CURSOR_NOT_CLOSED(self);
3627
Jesus Cea6ba33292008-08-31 14:12:11 +00003628 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003629 return NULL;
3630
3631 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003632 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00003633 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003634 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003635 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003636
3637 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003638 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003639 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003640 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3641 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003642 Py_INCREF(Py_None);
3643 retval = Py_None;
3644 }
3645 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003646 retval = NULL;
3647 }
3648 else {
3649 switch (_DB_get_type(self->mydb)) {
3650 case -1:
3651 retval = NULL;
3652 break;
3653 case DB_BTREE:
3654 case DB_HASH:
3655 default:
Jesus Cea6ba33292008-08-31 14:12:11 +00003656 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003657 break;
3658 case DB_RECNO:
3659 case DB_QUEUE:
Jesus Cea6ba33292008-08-31 14:12:11 +00003660 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003661 break;
3662 }
Jesus Cea6ba33292008-08-31 14:12:11 +00003663 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003664 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003665 /* the only time REALLOC should be set is if we used an integer
3666 * key that make_key_dbt malloc'd for us. always free these. */
3667 if (key.flags & DB_DBT_REALLOC) {
Jesus Cea6ba33292008-08-31 14:12:11 +00003668 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003669 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003670
3671 return retval;
3672}
3673
3674
3675static PyObject*
3676DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3677{
3678 int err, flags = 0;
3679 DBT key, data;
Jesus Cea6ba33292008-08-31 14:12:11 +00003680 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003681 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003682 int dlen = -1;
3683 int doff = -1;
3684
3685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3686 &keyobj, &flags, &dlen, &doff))
3687 return NULL;
3688
3689 CHECK_CURSOR_NOT_CLOSED(self);
3690
Jesus Cea6ba33292008-08-31 14:12:11 +00003691 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003692 return NULL;
3693
3694 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003695 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00003696 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003697 return NULL;
3698 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003699 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003700 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003701 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003702 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3703 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003704 Py_INCREF(Py_None);
3705 retval = Py_None;
3706 }
3707 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003708 retval = NULL;
3709 }
3710 else {
3711 switch (_DB_get_type(self->mydb)) {
3712 case -1:
3713 retval = NULL;
3714 break;
3715 case DB_BTREE:
3716 case DB_HASH:
3717 default:
Jesus Cea6ba33292008-08-31 14:12:11 +00003718 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003719 break;
3720 case DB_RECNO:
3721 case DB_QUEUE:
Jesus Cea6ba33292008-08-31 14:12:11 +00003722 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003723 break;
3724 }
Jesus Cea6ba33292008-08-31 14:12:11 +00003725 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003726 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003727 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003728 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003729 if (key.flags & DB_DBT_REALLOC) {
Jesus Cea6ba33292008-08-31 14:12:11 +00003730 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003731 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003732
3733 return retval;
3734}
3735
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003736static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003737_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3738 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003739{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003740 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003741 DBT key, data;
Jesus Cea6ba33292008-08-31 14:12:11 +00003742 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003743
Gregory P. Smith7441e652003-11-03 21:35:31 +00003744 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Jesus Cea6ba33292008-08-31 14:12:11 +00003745 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003746 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00003747 if (!make_dbt(dataobj, &data)) {
3748 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003749 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003750 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003751
3752 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003753 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003754 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003755 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003756 Py_INCREF(Py_None);
3757 retval = Py_None;
3758 }
3759 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003760 retval = NULL;
3761 }
3762 else {
3763 switch (_DB_get_type(self->mydb)) {
3764 case -1:
3765 retval = NULL;
3766 break;
3767 case DB_BTREE:
3768 case DB_HASH:
3769 default:
Jesus Cea6ba33292008-08-31 14:12:11 +00003770 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003771 break;
3772 case DB_RECNO:
3773 case DB_QUEUE:
Jesus Cea6ba33292008-08-31 14:12:11 +00003774 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003775 break;
3776 }
3777 }
3778
Jesus Cea6ba33292008-08-31 14:12:11 +00003779 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003780 return retval;
3781}
3782
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003783static PyObject*
3784DBC_get_both(DBCursorObject* self, PyObject* args)
3785{
3786 int flags=0;
3787 PyObject *keyobj, *dataobj;
3788
3789 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3790 return NULL;
3791
Gregory P. Smith7441e652003-11-03 21:35:31 +00003792 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003793 CHECK_CURSOR_NOT_CLOSED(self);
3794
3795 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3796 self->mydb->moduleFlags.getReturnsNone);
3797}
3798
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003799/* Return size of entry */
3800static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00003801DBC_get_current_size(DBCursorObject* self)
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003802{
3803 int err, flags=DB_CURRENT;
3804 PyObject* retval = NULL;
3805 DBT key, data;
3806
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003807 CHECK_CURSOR_NOT_CLOSED(self);
3808 CLEAR_DBT(key);
3809 CLEAR_DBT(data);
3810
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003811 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003812 getting the record size. */
3813 data.flags = DB_DBT_USERMEM;
3814 data.ulen = 0;
3815 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003816 err = _DBC_get(self->dbc, &key, &data, flags);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003817 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003818 if (err == DB_BUFFER_SMALL || !err) {
3819 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Jesus Cea6ba33292008-08-31 14:12:11 +00003820 retval = NUMBER_FromLong((long)data.size);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003821 err = 0;
3822 }
3823
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003824 RETURN_IF_ERR();
3825 return retval;
3826}
3827
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003828static PyObject*
3829DBC_set_both(DBCursorObject* self, PyObject* args)
3830{
3831 int flags=0;
3832 PyObject *keyobj, *dataobj;
3833
3834 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3835 return NULL;
3836
Gregory P. Smith7441e652003-11-03 21:35:31 +00003837 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003838 CHECK_CURSOR_NOT_CLOSED(self);
3839
3840 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3841 self->mydb->moduleFlags.cursorSetReturnsNone);
3842}
3843
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003844
3845static PyObject*
3846DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3847{
3848 int err, irecno, flags=0;
3849 db_recno_t recno;
3850 DBT key, data;
3851 PyObject* retval;
3852 int dlen = -1;
3853 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003854 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003855
3856 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3857 &irecno, &flags, &dlen, &doff))
3858 return NULL;
3859
3860 CHECK_CURSOR_NOT_CLOSED(self);
3861
3862 CLEAR_DBT(key);
3863 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003864 /* use allocated space so DB will be able to realloc room for the real
3865 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003866 key.data = malloc(sizeof(db_recno_t));
3867 if (key.data == NULL) {
3868 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3869 return NULL;
3870 }
3871 key.size = sizeof(db_recno_t);
3872 key.ulen = key.size;
3873 memcpy(key.data, &recno, sizeof(db_recno_t));
3874 key.flags = DB_DBT_REALLOC;
3875
3876 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003877 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Cea6ba33292008-08-31 14:12:11 +00003878 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003879 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003880 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003881
3882 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003883 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003884 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003885 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3886 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003887 Py_INCREF(Py_None);
3888 retval = Py_None;
3889 }
3890 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003891 retval = NULL;
3892 }
3893 else { /* Can only be used for BTrees, so no need to return int key */
Jesus Cea6ba33292008-08-31 14:12:11 +00003894 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003895 }
Jesus Cea6ba33292008-08-31 14:12:11 +00003896 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003897
3898 return retval;
3899}
3900
3901
3902static PyObject*
3903DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3904{
3905 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3906}
3907
3908
3909static PyObject*
3910DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3911{
3912 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3913}
3914
3915
3916static PyObject*
3917DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3918{
3919 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3920}
3921
3922
3923static PyObject*
3924DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3925{
3926 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3927}
3928
3929
3930static PyObject*
3931DBC_join_item(DBCursorObject* self, PyObject* args)
3932{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003933 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003934 DBT key, data;
3935 PyObject* retval;
3936
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003937 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003938 return NULL;
3939
3940 CHECK_CURSOR_NOT_CLOSED(self);
3941
3942 CLEAR_DBT(key);
3943 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003944
3945 MYDB_BEGIN_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00003946 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003947 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003948 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3949 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003950 Py_INCREF(Py_None);
3951 retval = Py_None;
3952 }
3953 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003954 retval = NULL;
3955 }
3956 else {
Jesus Cea6ba33292008-08-31 14:12:11 +00003957 retval = BuildValue_S(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003958 }
3959
3960 return retval;
3961}
3962
3963
3964
3965/* --------------------------------------------------------------------- */
3966/* DBEnv methods */
3967
3968
3969static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00003970DBEnv_close_internal(DBEnvObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003971{
Jesus Cea6ba33292008-08-31 14:12:11 +00003972 PyObject *dummy;
3973 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003974
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003975 if (!self->closed) { /* Don't close more than once */
Jesus Cea6ba33292008-08-31 14:12:11 +00003976 while(self->children_txns) {
3977 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
3978 Py_XDECREF(dummy);
3979 }
3980 while(self->children_dbs) {
3981 dummy=DB_close_internal(self->children_dbs,0);
3982 Py_XDECREF(dummy);
3983 }
3984
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003985 MYDB_BEGIN_ALLOW_THREADS;
3986 err = self->db_env->close(self->db_env, flags);
3987 MYDB_END_ALLOW_THREADS;
3988 /* after calling DBEnv->close, regardless of error, this DBEnv
Jesus Cea6ba33292008-08-31 14:12:11 +00003989 * may not be accessed again (Berkeley DB docs). */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003990 self->closed = 1;
3991 self->db_env = NULL;
3992 RETURN_IF_ERR();
3993 }
3994 RETURN_NONE();
3995}
3996
Jesus Cea6ba33292008-08-31 14:12:11 +00003997static PyObject*
3998DBEnv_close(DBEnvObject* self, PyObject* args)
3999{
4000 int flags = 0;
4001
4002 if (!PyArg_ParseTuple(args, "|i:close", &flags))
4003 return NULL;
4004 return DBEnv_close_internal(self,flags);
4005}
4006
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004007
4008static PyObject*
4009DBEnv_open(DBEnvObject* self, PyObject* args)
4010{
4011 int err, flags=0, mode=0660;
4012 char *db_home;
4013
4014 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
4015 return NULL;
4016
4017 CHECK_ENV_NOT_CLOSED(self);
4018
4019 MYDB_BEGIN_ALLOW_THREADS;
4020 err = self->db_env->open(self->db_env, db_home, flags, mode);
4021 MYDB_END_ALLOW_THREADS;
4022 RETURN_IF_ERR();
4023 self->closed = 0;
4024 self->flags = flags;
4025 RETURN_NONE();
4026}
4027
4028
4029static PyObject*
4030DBEnv_remove(DBEnvObject* self, PyObject* args)
4031{
4032 int err, flags=0;
4033 char *db_home;
4034
4035 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
4036 return NULL;
4037 CHECK_ENV_NOT_CLOSED(self);
4038 MYDB_BEGIN_ALLOW_THREADS;
4039 err = self->db_env->remove(self->db_env, db_home, flags);
4040 MYDB_END_ALLOW_THREADS;
4041 RETURN_IF_ERR();
4042 RETURN_NONE();
4043}
4044
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004045#if (DBVER >= 41)
4046static PyObject*
4047DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4048{
4049 int err;
4050 u_int32_t flags=0;
4051 char *file = NULL;
4052 char *database = NULL;
4053 PyObject *txnobj = NULL;
4054 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004055 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004056 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004057
Thomas Wouters0e3f5912006-08-11 14:57:12 +00004058 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004059 &file, &database, &txnobj, &flags)) {
4060 return NULL;
4061 }
4062 if (!checkTxnObj(txnobj, &txn)) {
4063 return NULL;
4064 }
4065 CHECK_ENV_NOT_CLOSED(self);
4066 MYDB_BEGIN_ALLOW_THREADS;
4067 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4068 MYDB_END_ALLOW_THREADS;
4069 RETURN_IF_ERR();
4070 RETURN_NONE();
4071}
4072
4073static PyObject*
4074DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4075{
4076 int err;
4077 u_int32_t flags=0;
4078 char *file = NULL;
4079 char *database = NULL;
4080 char *newname = NULL;
4081 PyObject *txnobj = NULL;
4082 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004083 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004084 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004085
Thomas Wouters0e3f5912006-08-11 14:57:12 +00004086 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004087 &file, &database, &newname, &txnobj, &flags)) {
4088 return NULL;
4089 }
4090 if (!checkTxnObj(txnobj, &txn)) {
4091 return NULL;
4092 }
4093 CHECK_ENV_NOT_CLOSED(self);
4094 MYDB_BEGIN_ALLOW_THREADS;
4095 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4096 flags);
4097 MYDB_END_ALLOW_THREADS;
4098 RETURN_IF_ERR();
4099 RETURN_NONE();
4100}
4101
4102static PyObject*
4103DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4104{
4105 int err;
4106 u_int32_t flags=0;
4107 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004108 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004109
4110 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4111 &passwd, &flags)) {
4112 return NULL;
4113 }
4114
4115 MYDB_BEGIN_ALLOW_THREADS;
4116 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4117 MYDB_END_ALLOW_THREADS;
4118
4119 RETURN_IF_ERR();
4120 RETURN_NONE();
4121}
4122#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004123
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004124static PyObject*
4125DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4126{
4127 int err;
4128 u_int32_t flags=0;
4129 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004130 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004131
4132 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4133 &timeout, &flags)) {
4134 return NULL;
4135 }
4136
4137 MYDB_BEGIN_ALLOW_THREADS;
4138 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4139 MYDB_END_ALLOW_THREADS;
4140
4141 RETURN_IF_ERR();
4142 RETURN_NONE();
4143}
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004144
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004145static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004146DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4147{
4148 int err;
4149 long shm_key = 0;
4150
4151 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4152 return NULL;
4153 CHECK_ENV_NOT_CLOSED(self);
4154
4155 err = self->db_env->set_shm_key(self->db_env, shm_key);
4156 RETURN_IF_ERR();
4157 RETURN_NONE();
4158}
4159
4160static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004161DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4162{
4163 int err, gbytes=0, bytes=0, ncache=0;
4164
4165 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4166 &gbytes, &bytes, &ncache))
4167 return NULL;
4168 CHECK_ENV_NOT_CLOSED(self);
4169
4170 MYDB_BEGIN_ALLOW_THREADS;
4171 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4172 MYDB_END_ALLOW_THREADS;
4173 RETURN_IF_ERR();
4174 RETURN_NONE();
4175}
4176
4177
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004178static PyObject*
4179DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4180{
4181 int err, flags=0, onoff=0;
4182
4183 if (!PyArg_ParseTuple(args, "ii:set_flags",
4184 &flags, &onoff))
4185 return NULL;
4186 CHECK_ENV_NOT_CLOSED(self);
4187
4188 MYDB_BEGIN_ALLOW_THREADS;
4189 err = self->db_env->set_flags(self->db_env, flags, onoff);
4190 MYDB_END_ALLOW_THREADS;
4191 RETURN_IF_ERR();
4192 RETURN_NONE();
4193}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004194
4195
Jesus Cea6ba33292008-08-31 14:12:11 +00004196#if (DBVER >= 47)
4197static PyObject*
4198DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
4199{
4200 int err, flags, onoff;
4201
4202 if (!PyArg_ParseTuple(args, "ii:log_set_config",
4203 &flags, &onoff))
4204 return NULL;
4205 CHECK_ENV_NOT_CLOSED(self);
4206
4207 MYDB_BEGIN_ALLOW_THREADS;
4208 err = self->db_env->log_set_config(self->db_env, flags, onoff);
4209 MYDB_END_ALLOW_THREADS;
4210 RETURN_IF_ERR();
4211 RETURN_NONE();
4212}
4213#endif /* DBVER >= 47 */
4214
4215
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004216static PyObject*
4217DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4218{
4219 int err;
4220 char *dir;
4221
4222 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4223 return NULL;
4224 CHECK_ENV_NOT_CLOSED(self);
4225
4226 MYDB_BEGIN_ALLOW_THREADS;
4227 err = self->db_env->set_data_dir(self->db_env, dir);
4228 MYDB_END_ALLOW_THREADS;
4229 RETURN_IF_ERR();
4230 RETURN_NONE();
4231}
4232
4233
4234static PyObject*
4235DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4236{
4237 int err, lg_bsize;
4238
4239 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4240 return NULL;
4241 CHECK_ENV_NOT_CLOSED(self);
4242
4243 MYDB_BEGIN_ALLOW_THREADS;
4244 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4245 MYDB_END_ALLOW_THREADS;
4246 RETURN_IF_ERR();
4247 RETURN_NONE();
4248}
4249
4250
4251static PyObject*
4252DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4253{
4254 int err;
4255 char *dir;
4256
4257 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4258 return NULL;
4259 CHECK_ENV_NOT_CLOSED(self);
4260
4261 MYDB_BEGIN_ALLOW_THREADS;
4262 err = self->db_env->set_lg_dir(self->db_env, dir);
4263 MYDB_END_ALLOW_THREADS;
4264 RETURN_IF_ERR();
4265 RETURN_NONE();
4266}
4267
4268static PyObject*
4269DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4270{
4271 int err, lg_max;
4272
4273 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4274 return NULL;
4275 CHECK_ENV_NOT_CLOSED(self);
4276
4277 MYDB_BEGIN_ALLOW_THREADS;
4278 err = self->db_env->set_lg_max(self->db_env, lg_max);
4279 MYDB_END_ALLOW_THREADS;
4280 RETURN_IF_ERR();
4281 RETURN_NONE();
4282}
4283
Jesus Cea6ba33292008-08-31 14:12:11 +00004284#if (DBVER >= 42)
4285static PyObject*
4286DBEnv_get_lg_max(DBEnvObject* self)
4287{
4288 int err;
4289 u_int32_t lg_max;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004290
Jesus Cea6ba33292008-08-31 14:12:11 +00004291 CHECK_ENV_NOT_CLOSED(self);
4292
4293 MYDB_BEGIN_ALLOW_THREADS;
4294 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4295 MYDB_END_ALLOW_THREADS;
4296 RETURN_IF_ERR();
4297 return NUMBER_FromLong(lg_max);
4298}
4299#endif
4300
4301
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004302static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004303DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4304{
4305 int err, lg_max;
4306
4307 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4308 return NULL;
4309 CHECK_ENV_NOT_CLOSED(self);
4310
4311 MYDB_BEGIN_ALLOW_THREADS;
4312 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4313 MYDB_END_ALLOW_THREADS;
4314 RETURN_IF_ERR();
4315 RETURN_NONE();
4316}
4317
4318
4319static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004320DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4321{
4322 int err, lk_detect;
4323
4324 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4325 return NULL;
4326 CHECK_ENV_NOT_CLOSED(self);
4327
4328 MYDB_BEGIN_ALLOW_THREADS;
4329 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4330 MYDB_END_ALLOW_THREADS;
4331 RETURN_IF_ERR();
4332 RETURN_NONE();
4333}
4334
4335
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004336#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004337static PyObject*
4338DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4339{
4340 int err, max;
4341
4342 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4343 return NULL;
4344 CHECK_ENV_NOT_CLOSED(self);
4345
4346 MYDB_BEGIN_ALLOW_THREADS;
4347 err = self->db_env->set_lk_max(self->db_env, max);
4348 MYDB_END_ALLOW_THREADS;
4349 RETURN_IF_ERR();
4350 RETURN_NONE();
4351}
Thomas Wouters902d6eb2007-01-09 23:18:33 +00004352#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004353
4354
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004355
4356static PyObject*
4357DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4358{
4359 int err, max;
4360
4361 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4362 return NULL;
4363 CHECK_ENV_NOT_CLOSED(self);
4364
4365 MYDB_BEGIN_ALLOW_THREADS;
4366 err = self->db_env->set_lk_max_locks(self->db_env, max);
4367 MYDB_END_ALLOW_THREADS;
4368 RETURN_IF_ERR();
4369 RETURN_NONE();
4370}
4371
4372
4373static PyObject*
4374DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4375{
4376 int err, max;
4377
4378 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4379 return NULL;
4380 CHECK_ENV_NOT_CLOSED(self);
4381
4382 MYDB_BEGIN_ALLOW_THREADS;
4383 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4384 MYDB_END_ALLOW_THREADS;
4385 RETURN_IF_ERR();
4386 RETURN_NONE();
4387}
4388
4389
4390static PyObject*
4391DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4392{
4393 int err, max;
4394
4395 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4396 return NULL;
4397 CHECK_ENV_NOT_CLOSED(self);
4398
4399 MYDB_BEGIN_ALLOW_THREADS;
4400 err = self->db_env->set_lk_max_objects(self->db_env, max);
4401 MYDB_END_ALLOW_THREADS;
4402 RETURN_IF_ERR();
4403 RETURN_NONE();
4404}
4405
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004406
4407static PyObject*
4408DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4409{
4410 int err, mp_mmapsize;
4411
4412 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4413 return NULL;
4414 CHECK_ENV_NOT_CLOSED(self);
4415
4416 MYDB_BEGIN_ALLOW_THREADS;
4417 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4418 MYDB_END_ALLOW_THREADS;
4419 RETURN_IF_ERR();
4420 RETURN_NONE();
4421}
4422
4423
4424static PyObject*
4425DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4426{
4427 int err;
4428 char *dir;
4429
4430 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4431 return NULL;
4432 CHECK_ENV_NOT_CLOSED(self);
4433
4434 MYDB_BEGIN_ALLOW_THREADS;
4435 err = self->db_env->set_tmp_dir(self->db_env, dir);
4436 MYDB_END_ALLOW_THREADS;
4437 RETURN_IF_ERR();
4438 RETURN_NONE();
4439}
4440
4441
4442static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00004443DBEnv_txn_recover(DBEnvObject* self)
4444{
4445 int flags = DB_FIRST;
4446 int err, i;
4447 PyObject *list, *tuple, *gid;
4448 DBTxnObject *txn;
4449#define PREPLIST_LEN 16
4450 DB_PREPLIST preplist[PREPLIST_LEN];
4451 long retp;
4452
4453 CHECK_ENV_NOT_CLOSED(self);
4454
4455 list=PyList_New(0);
4456 if (!list)
4457 return NULL;
4458 while (!0) {
4459 MYDB_BEGIN_ALLOW_THREADS
4460 err=self->db_env->txn_recover(self->db_env,
4461 preplist, PREPLIST_LEN, &retp, flags);
4462#undef PREPLIST_LEN
4463 MYDB_END_ALLOW_THREADS
4464 if (err) {
4465 Py_DECREF(list);
4466 RETURN_IF_ERR();
4467 }
4468 if (!retp) break;
4469 flags=DB_NEXT; /* Prepare for next loop pass */
4470 for (i=0; i<retp; i++) {
4471 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
4472 DB_XIDDATASIZE);
4473 if (!gid) {
4474 Py_DECREF(list);
4475 return NULL;
4476 }
4477 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4478 if (!txn) {
4479 Py_DECREF(list);
4480 Py_DECREF(gid);
4481 return NULL;
4482 }
4483 txn->flag_prepare=1; /* Recover state */
4484 tuple=PyTuple_New(2);
4485 if (!tuple) {
4486 Py_DECREF(list);
4487 Py_DECREF(gid);
4488 Py_DECREF(txn);
4489 return NULL;
4490 }
4491 if (PyTuple_SetItem(tuple, 0, gid)) {
4492 Py_DECREF(list);
4493 Py_DECREF(gid);
4494 Py_DECREF(txn);
4495 Py_DECREF(tuple);
4496 return NULL;
4497 }
4498 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4499 Py_DECREF(list);
4500 Py_DECREF(txn);
4501 Py_DECREF(tuple); /* This delete the "gid" also */
4502 return NULL;
4503 }
4504 if (PyList_Append(list, tuple)) {
4505 Py_DECREF(list);
4506 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4507 return NULL;
4508 }
4509 Py_DECREF(tuple);
4510 }
4511 }
4512 return list;
4513}
4514
4515static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004516DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4517{
4518 int flags = 0;
4519 PyObject* txnobj = NULL;
4520 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004521 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004522
4523 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4524 &txnobj, &flags))
4525 return NULL;
4526
4527 if (!checkTxnObj(txnobj, &txn))
4528 return NULL;
4529 CHECK_ENV_NOT_CLOSED(self);
4530
Jesus Cea6ba33292008-08-31 14:12:11 +00004531 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004532}
4533
4534
4535static PyObject*
4536DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4537{
4538 int err, kbyte=0, min=0, flags=0;
4539
4540 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4541 return NULL;
4542 CHECK_ENV_NOT_CLOSED(self);
4543
4544 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004545 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004546 MYDB_END_ALLOW_THREADS;
4547 RETURN_IF_ERR();
4548 RETURN_NONE();
4549}
4550
4551
4552static PyObject*
4553DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4554{
4555 int err, max;
4556
4557 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4558 return NULL;
4559 CHECK_ENV_NOT_CLOSED(self);
4560
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004561 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004562 RETURN_IF_ERR();
4563 RETURN_NONE();
4564}
4565
4566
4567static PyObject*
4568DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4569{
4570 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004571 long stamp;
4572 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004573
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004574 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004575 return NULL;
4576 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004577 timestamp = (time_t)stamp;
4578 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004579 RETURN_IF_ERR();
4580 RETURN_NONE();
4581}
4582
4583
4584static PyObject*
4585DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4586{
4587 int err, atype, flags=0;
4588 int aborted = 0;
4589
4590 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4591 return NULL;
4592 CHECK_ENV_NOT_CLOSED(self);
4593
4594 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004595 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004596 MYDB_END_ALLOW_THREADS;
4597 RETURN_IF_ERR();
Jesus Cea6ba33292008-08-31 14:12:11 +00004598 return NUMBER_FromLong(aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004599}
4600
4601
4602static PyObject*
4603DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4604{
4605 int flags=0;
4606 int locker, lock_mode;
4607 DBT obj;
Jesus Cea6ba33292008-08-31 14:12:11 +00004608 PyObject* objobj;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004609
4610 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4611 return NULL;
4612
Jesus Cea6ba33292008-08-31 14:12:11 +00004613
4614 if (!make_dbt(objobj, &obj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004615 return NULL;
4616
Jesus Cea6ba33292008-08-31 14:12:11 +00004617 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004618}
4619
4620
4621static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00004622DBEnv_lock_id(DBEnvObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004623{
4624 int err;
4625 u_int32_t theID;
4626
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004627 CHECK_ENV_NOT_CLOSED(self);
4628 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004629 err = self->db_env->lock_id(self->db_env, &theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004630 MYDB_END_ALLOW_THREADS;
4631 RETURN_IF_ERR();
4632
Jesus Cea6ba33292008-08-31 14:12:11 +00004633 return NUMBER_FromLong((long)theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004634}
4635
Guido van Rossum77677112007-11-05 19:43:04 +00004636static PyObject*
4637DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4638{
4639 int err;
4640 u_int32_t theID;
4641
4642 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4643 return NULL;
4644
4645 CHECK_ENV_NOT_CLOSED(self);
4646 MYDB_BEGIN_ALLOW_THREADS;
4647 err = self->db_env->lock_id_free(self->db_env, theID);
4648 MYDB_END_ALLOW_THREADS;
4649 RETURN_IF_ERR();
4650 RETURN_NONE();
4651}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004652
4653static PyObject*
4654DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4655{
4656 int err;
4657 DBLockObject* dblockobj;
4658
4659 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4660 return NULL;
4661
4662 CHECK_ENV_NOT_CLOSED(self);
4663 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004664 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004665 MYDB_END_ALLOW_THREADS;
4666 RETURN_IF_ERR();
4667 RETURN_NONE();
4668}
4669
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004670#if (DBVER >= 44)
4671static PyObject*
4672DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4673{
4674 int err;
4675 char *file;
4676 u_int32_t flags = 0;
4677 static char* kwnames[] = { "file", "flags", NULL};
4678
4679 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4680 &file, &flags))
4681 return NULL;
4682 CHECK_ENV_NOT_CLOSED(self);
4683
4684 MYDB_BEGIN_ALLOW_THREADS;
4685 err = self->db_env->lsn_reset(self->db_env, file, flags);
4686 MYDB_END_ALLOW_THREADS;
4687 RETURN_IF_ERR();
4688 RETURN_NONE();
4689}
4690#endif /* DBVER >= 4.4 */
4691
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004692static PyObject*
4693DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4694{
4695 int err;
4696 DB_LOG_STAT* statp = NULL;
4697 PyObject* d = NULL;
4698 u_int32_t flags = 0;
4699
4700 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4701 return NULL;
4702 CHECK_ENV_NOT_CLOSED(self);
4703
4704 MYDB_BEGIN_ALLOW_THREADS;
4705 err = self->db_env->log_stat(self->db_env, &statp, flags);
4706 MYDB_END_ALLOW_THREADS;
4707 RETURN_IF_ERR();
4708
4709 /* Turn the stat structure into a dictionary */
4710 d = PyDict_New();
4711 if (d == NULL) {
4712 if (statp)
4713 free(statp);
4714 return NULL;
4715 }
4716
4717#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4718
4719 MAKE_ENTRY(magic);
4720 MAKE_ENTRY(version);
4721 MAKE_ENTRY(mode);
4722 MAKE_ENTRY(lg_bsize);
4723#if (DBVER >= 44)
4724 MAKE_ENTRY(lg_size);
4725 MAKE_ENTRY(record);
4726#endif
Jesus Cea6ba33292008-08-31 14:12:11 +00004727#if (DBVER < 41)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004728 MAKE_ENTRY(lg_max);
4729#endif
4730 MAKE_ENTRY(w_mbytes);
4731 MAKE_ENTRY(w_bytes);
4732 MAKE_ENTRY(wc_mbytes);
4733 MAKE_ENTRY(wc_bytes);
4734 MAKE_ENTRY(wcount);
4735 MAKE_ENTRY(wcount_fill);
4736#if (DBVER >= 44)
4737 MAKE_ENTRY(rcount);
4738#endif
4739 MAKE_ENTRY(scount);
4740 MAKE_ENTRY(cur_file);
4741 MAKE_ENTRY(cur_offset);
4742 MAKE_ENTRY(disk_file);
4743 MAKE_ENTRY(disk_offset);
4744 MAKE_ENTRY(maxcommitperflush);
4745 MAKE_ENTRY(mincommitperflush);
4746 MAKE_ENTRY(regsize);
4747 MAKE_ENTRY(region_wait);
4748 MAKE_ENTRY(region_nowait);
4749
4750#undef MAKE_ENTRY
4751 free(statp);
4752 return d;
4753} /* DBEnv_log_stat */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004754
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004755
4756static PyObject*
4757DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4758{
4759 int err;
4760 DB_LOCK_STAT* sp;
4761 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004762 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004763
4764 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4765 return NULL;
4766 CHECK_ENV_NOT_CLOSED(self);
4767
4768 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004769 err = self->db_env->lock_stat(self->db_env, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004770 MYDB_END_ALLOW_THREADS;
4771 RETURN_IF_ERR();
4772
4773 /* Turn the stat structure into a dictionary */
4774 d = PyDict_New();
4775 if (d == NULL) {
4776 free(sp);
4777 return NULL;
4778 }
4779
4780#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4781
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004782#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004783 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004784#endif
Jesus Cea6ba33292008-08-31 14:12:11 +00004785#if (DBVER >=41)
4786 MAKE_ENTRY(id);
4787 MAKE_ENTRY(cur_maxid);
4788#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004789 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004790 MAKE_ENTRY(maxlocks);
4791 MAKE_ENTRY(maxlockers);
4792 MAKE_ENTRY(maxobjects);
4793 MAKE_ENTRY(nlocks);
4794 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004795 MAKE_ENTRY(nlockers);
4796 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004797 MAKE_ENTRY(nobjects);
4798 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004799 MAKE_ENTRY(nrequests);
4800 MAKE_ENTRY(nreleases);
Jesus Cea6ba33292008-08-31 14:12:11 +00004801#if (DBVER >= 44)
4802 MAKE_ENTRY(nupgrade);
4803 MAKE_ENTRY(ndowngrade);
4804#endif
Gregory P. Smith29602d22006-01-24 09:46:48 +00004805#if (DBVER < 44)
4806 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004807 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004808#else
4809 MAKE_ENTRY(lock_nowait);
4810 MAKE_ENTRY(lock_wait);
4811#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004812 MAKE_ENTRY(ndeadlocks);
Jesus Cea6ba33292008-08-31 14:12:11 +00004813#if (DBVER >= 41)
4814 MAKE_ENTRY(locktimeout);
4815 MAKE_ENTRY(txntimeout);
4816#endif
4817 MAKE_ENTRY(nlocktimeouts);
4818 MAKE_ENTRY(ntxntimeouts);
4819#if (DBVER >= 46)
4820 MAKE_ENTRY(objs_wait);
4821 MAKE_ENTRY(objs_nowait);
4822 MAKE_ENTRY(lockers_wait);
4823 MAKE_ENTRY(lockers_nowait);
4824#if (DBVER >= 47)
4825 MAKE_ENTRY(lock_wait);
4826 MAKE_ENTRY(lock_nowait);
4827#else
4828 MAKE_ENTRY(locks_wait);
4829 MAKE_ENTRY(locks_nowait);
4830#endif
4831 MAKE_ENTRY(hash_len);
4832#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004833 MAKE_ENTRY(regsize);
4834 MAKE_ENTRY(region_wait);
4835 MAKE_ENTRY(region_nowait);
4836
4837#undef MAKE_ENTRY
4838 free(sp);
4839 return d;
4840}
4841
Jesus Cea6ba33292008-08-31 14:12:11 +00004842static PyObject*
4843DBEnv_log_flush(DBEnvObject* self)
4844{
4845 int err;
4846
4847 CHECK_ENV_NOT_CLOSED(self);
4848
4849 MYDB_BEGIN_ALLOW_THREADS
4850 err = self->db_env->log_flush(self->db_env, NULL);
4851 MYDB_END_ALLOW_THREADS
4852
4853 RETURN_IF_ERR();
4854 RETURN_NONE();
4855}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004856
4857static PyObject*
4858DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4859{
4860 int flags=0;
4861 int err;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004862 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004863 PyObject* list;
4864 PyObject* item = NULL;
4865
4866 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4867 return NULL;
4868
4869 CHECK_ENV_NOT_CLOSED(self);
4870 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004871 err = self->db_env->log_archive(self->db_env, &log_list, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004872 MYDB_END_ALLOW_THREADS;
4873 RETURN_IF_ERR();
4874
4875 list = PyList_New(0);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004876 if (list == NULL) {
4877 if (log_list)
4878 free(log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004879 return NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004880 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004881
4882 if (log_list) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00004883 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004884 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Jesus Cea6ba33292008-08-31 14:12:11 +00004885 item = PyBytes_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004886 if (item == NULL) {
4887 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004888 list = NULL;
4889 break;
4890 }
Jesus Cea6ba33292008-08-31 14:12:11 +00004891 if (PyList_Append(list, item)) {
4892 Py_DECREF(list);
4893 list = NULL;
4894 Py_DECREF(item);
4895 break;
4896 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004897 Py_DECREF(item);
4898 }
4899 free(log_list_start);
4900 }
4901 return list;
4902}
4903
4904
4905static PyObject*
4906DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4907{
4908 int err;
4909 DB_TXN_STAT* sp;
4910 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004911 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004912
4913 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4914 return NULL;
4915 CHECK_ENV_NOT_CLOSED(self);
4916
4917 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004918 err = self->db_env->txn_stat(self->db_env, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004919 MYDB_END_ALLOW_THREADS;
4920 RETURN_IF_ERR();
4921
4922 /* Turn the stat structure into a dictionary */
4923 d = PyDict_New();
4924 if (d == NULL) {
4925 free(sp);
4926 return NULL;
4927 }
4928
Jesus Cea6ba33292008-08-31 14:12:11 +00004929#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4930#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4931#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004932
Jesus Cea6ba33292008-08-31 14:12:11 +00004933 MAKE_DB_LSN_ENTRY(last_ckp);
Guido van Rossumd8faa362007-04-27 19:54:29 +00004934 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004935 MAKE_ENTRY(last_txnid);
4936 MAKE_ENTRY(maxtxns);
4937 MAKE_ENTRY(nactive);
4938 MAKE_ENTRY(maxnactive);
Jesus Cea6ba33292008-08-31 14:12:11 +00004939#if (DBVER >= 45)
4940 MAKE_ENTRY(nsnapshot);
4941 MAKE_ENTRY(maxnsnapshot);
4942#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004943 MAKE_ENTRY(nbegins);
4944 MAKE_ENTRY(naborts);
4945 MAKE_ENTRY(ncommits);
Jesus Cea6ba33292008-08-31 14:12:11 +00004946 MAKE_ENTRY(nrestores);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004947 MAKE_ENTRY(regsize);
4948 MAKE_ENTRY(region_wait);
4949 MAKE_ENTRY(region_nowait);
4950
Jesus Cea6ba33292008-08-31 14:12:11 +00004951#undef MAKE_DB_LSN_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004952#undef MAKE_ENTRY
Guido van Rossumd8faa362007-04-27 19:54:29 +00004953#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004954 free(sp);
4955 return d;
4956}
4957
4958
4959static PyObject*
4960DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4961{
4962 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004963 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004964
4965 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4966 return NULL;
4967 CHECK_ENV_NOT_CLOSED(self);
4968
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004969 if (self->moduleFlags.getReturnsNone)
4970 ++oldValue;
4971 if (self->moduleFlags.cursorSetReturnsNone)
4972 ++oldValue;
4973 self->moduleFlags.getReturnsNone = (flags >= 1);
4974 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Jesus Cea6ba33292008-08-31 14:12:11 +00004975 return NUMBER_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004976}
4977
Jesus Cea6ba33292008-08-31 14:12:11 +00004978static PyObject*
4979DBEnv_get_private(DBEnvObject* self)
4980{
4981 /* We can give out the private field even if dbenv is closed */
4982 Py_INCREF(self->private_obj);
4983 return self->private_obj;
4984}
4985
4986static PyObject*
4987DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
4988{
4989 /* We can set the private field even if dbenv is closed */
4990 Py_DECREF(self->private_obj);
4991 Py_INCREF(private_obj);
4992 self->private_obj = private_obj;
4993 RETURN_NONE();
4994}
4995
4996
4997static PyObject*
4998DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4999{
5000 int err;
5001 char *host;
5002 long cl_timeout=0, sv_timeout=0;
5003
5004 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
5005
5006 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
5007 &host, &cl_timeout, &sv_timeout))
5008 return NULL;
5009 CHECK_ENV_NOT_CLOSED(self);
5010
5011 MYDB_BEGIN_ALLOW_THREADS;
5012 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
5013 sv_timeout, 0);
5014 MYDB_END_ALLOW_THREADS;
5015 RETURN_IF_ERR();
5016 RETURN_NONE();
5017}
5018
5019static PyObject*
5020DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
5021{
5022 int err;
5023 int which, onoff;
5024
5025 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
5026 return NULL;
5027 }
5028 CHECK_ENV_NOT_CLOSED(self);
5029 MYDB_BEGIN_ALLOW_THREADS;
5030 err = self->db_env->set_verbose(self->db_env, which, onoff);
5031 MYDB_END_ALLOW_THREADS;
5032 RETURN_IF_ERR();
5033 RETURN_NONE();
5034}
5035
5036#if (DBVER >= 42)
5037static PyObject*
5038DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
5039{
5040 int err;
5041 int which;
5042 int verbose;
5043
5044 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
5045 return NULL;
5046 }
5047 CHECK_ENV_NOT_CLOSED(self);
5048 MYDB_BEGIN_ALLOW_THREADS;
5049 err = self->db_env->get_verbose(self->db_env, which, &verbose);
5050 MYDB_END_ALLOW_THREADS;
5051 RETURN_IF_ERR();
5052 return PyBool_FromLong(verbose);
5053}
5054#endif
5055
5056#if (DBVER >= 45)
5057static void
5058_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
5059{
5060 DBEnvObject *dbenv;
5061 PyObject* callback;
5062 PyObject* args;
5063 PyObject* result = NULL;
5064
5065 MYDB_BEGIN_BLOCK_THREADS;
5066 dbenv = (DBEnvObject *)db_env->app_private;
5067 callback = dbenv->event_notifyCallback;
5068 if (callback) {
5069 if (event == DB_EVENT_REP_NEWMASTER) {
5070 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
5071 } else {
5072 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5073 }
5074 if (args) {
5075 result = PyEval_CallObject(callback, args);
5076 }
5077 if ((!args) || (!result)) {
5078 PyErr_Print();
5079 }
5080 Py_XDECREF(args);
5081 Py_XDECREF(result);
5082 }
5083 MYDB_END_BLOCK_THREADS;
5084}
5085#endif
5086
5087#if (DBVER >= 45)
5088static PyObject*
5089DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
5090{
5091 int err;
5092
5093 CHECK_ENV_NOT_CLOSED(self);
5094
5095 if (!PyCallable_Check(notifyFunc)) {
5096 makeTypeError("Callable", notifyFunc);
5097 return NULL;
5098 }
5099
5100 Py_XDECREF(self->event_notifyCallback);
5101 Py_INCREF(notifyFunc);
5102 self->event_notifyCallback = notifyFunc;
5103
5104 /* This is to workaround a problem with un-initialized threads (see
5105 comment in DB_associate) */
5106#ifdef WITH_THREAD
5107 PyEval_InitThreads();
5108#endif
5109
5110 MYDB_BEGIN_ALLOW_THREADS;
5111 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5112 MYDB_END_ALLOW_THREADS;
5113
5114 if (err) {
5115 Py_DECREF(notifyFunc);
5116 self->event_notifyCallback = NULL;
5117 }
5118
5119 RETURN_IF_ERR();
5120 RETURN_NONE();
5121}
5122#endif
5123
5124
5125/* --------------------------------------------------------------------- */
5126/* REPLICATION METHODS: Base Replication */
5127
5128
5129static PyObject*
5130DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
5131{
5132 int err;
5133 PyObject *control_py, *rec_py;
5134 DBT control, rec;
5135 int envid;
5136#if (DBVER >= 42)
5137 DB_LSN lsn;
5138#endif
5139
5140 if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
5141 &rec_py, &envid))
5142 return NULL;
5143 CHECK_ENV_NOT_CLOSED(self);
5144
5145 if (!make_dbt(control_py, &control))
5146 return NULL;
5147 if (!make_dbt(rec_py, &rec))
5148 return NULL;
5149
5150 MYDB_BEGIN_ALLOW_THREADS;
5151#if (DBVER >= 46)
5152 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5153 envid, &lsn);
5154#else
5155#if (DBVER >= 42)
5156 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5157 &envid, &lsn);
5158#else
5159 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5160 &envid);
5161#endif
5162#endif
5163 MYDB_END_ALLOW_THREADS;
5164 switch (err) {
5165 case DB_REP_NEWMASTER :
5166 return Py_BuildValue("(iO)", envid, Py_None);
5167 break;
5168
5169 case DB_REP_DUPMASTER :
5170 case DB_REP_HOLDELECTION :
5171#if (DBVER >= 44)
5172 case DB_REP_IGNORE :
5173 case DB_REP_JOIN_FAILURE :
5174#endif
5175 return Py_BuildValue("(iO)", err, Py_None);
5176 break;
5177 case DB_REP_NEWSITE :
5178 {
5179 PyObject *tmp, *r;
5180
5181 if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
5182 return NULL;
5183 }
5184
5185 r = Py_BuildValue("(iO)", err, tmp);
5186 Py_DECREF(tmp);
5187 return r;
5188 break;
5189 }
5190#if (DBVER >= 42)
5191 case DB_REP_NOTPERM :
5192 case DB_REP_ISPERM :
5193 return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
5194 break;
5195#endif
5196 }
5197 RETURN_IF_ERR();
5198 return Py_BuildValue("(OO)", Py_None, Py_None);
5199}
5200
5201static int
5202_DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
5203 const DB_LSN *lsn, int envid, u_int32_t flags)
5204{
5205 DBEnvObject *dbenv;
5206 PyObject* rep_transport;
5207 PyObject* args;
5208 PyObject *a, *b;
5209 PyObject* result = NULL;
5210 int ret=0;
5211
5212 MYDB_BEGIN_BLOCK_THREADS;
5213 dbenv = (DBEnvObject *)db_env->app_private;
5214 rep_transport = dbenv->rep_transport;
5215
5216 /*
5217 ** The errors in 'a' or 'b' are detected in "Py_BuildValue".
5218 */
5219 a = PyBytes_FromStringAndSize(control->data, control->size);
5220 b = PyBytes_FromStringAndSize(rec->data, rec->size);
5221
5222 args = Py_BuildValue(
5223#if (PY_VERSION_HEX >= 0x02040000)
5224 "(OOO(ll)iI)",
5225#else
5226 "(OOO(ll)ii)",
5227#endif
5228 dbenv,
5229 a, b,
5230 lsn->file, lsn->offset, envid, flags);
5231 if (args) {
5232 result = PyEval_CallObject(rep_transport, args);
5233 }
5234
5235 if ((!args) || (!result)) {
5236 PyErr_Print();
5237 ret = -1;
5238 }
5239 Py_XDECREF(a);
5240 Py_XDECREF(b);
5241 Py_XDECREF(args);
5242 Py_XDECREF(result);
5243 MYDB_END_BLOCK_THREADS;
5244 return ret;
5245}
5246
5247#if (DBVER <= 41)
5248static int
5249_DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec,
5250 int envid, u_int32_t flags)
5251{
5252 DB_LSN lsn;
5253
5254 lsn.file = -1; /* Dummy values */
5255 lsn.offset = -1;
5256 return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid,
5257 flags);
5258}
5259#endif
5260
5261static PyObject*
5262DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
5263{
5264 int err;
5265 int envid;
5266 PyObject *rep_transport;
5267
5268 if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
5269 return NULL;
5270 CHECK_ENV_NOT_CLOSED(self);
5271 if (!PyCallable_Check(rep_transport)) {
5272 makeTypeError("Callable", rep_transport);
5273 return NULL;
5274 }
5275
5276 MYDB_BEGIN_ALLOW_THREADS;
5277#if (DBVER >=45)
5278 err = self->db_env->rep_set_transport(self->db_env, envid,
5279 &_DBEnv_rep_transportCallback);
5280#else
5281#if (DBVER >= 42)
5282 err = self->db_env->set_rep_transport(self->db_env, envid,
5283 &_DBEnv_rep_transportCallback);
5284#else
5285 err = self->db_env->set_rep_transport(self->db_env, envid,
5286 &_DBEnv_rep_transportCallbackOLD);
5287#endif
5288#endif
5289 MYDB_END_ALLOW_THREADS;
5290 RETURN_IF_ERR();
5291
5292 Py_DECREF(self->rep_transport);
5293 Py_INCREF(rep_transport);
5294 self->rep_transport = rep_transport;
5295 RETURN_NONE();
5296}
5297
5298#if (DBVER >= 47)
5299static PyObject*
5300DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
5301{
5302 int err;
5303 unsigned int minimum, maximum;
5304
5305 if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
5306 return NULL;
5307 CHECK_ENV_NOT_CLOSED(self);
5308
5309 MYDB_BEGIN_ALLOW_THREADS;
5310 err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
5311 MYDB_END_ALLOW_THREADS;
5312 RETURN_IF_ERR();
5313 RETURN_NONE();
5314}
5315
5316static PyObject*
5317DBEnv_rep_get_request(DBEnvObject* self)
5318{
5319 int err;
5320 u_int32_t minimum, maximum;
5321
5322 CHECK_ENV_NOT_CLOSED(self);
5323 MYDB_BEGIN_ALLOW_THREADS;
5324 err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
5325 MYDB_END_ALLOW_THREADS;
5326 RETURN_IF_ERR();
5327#if (PY_VERSION_HEX >= 0x02040000)
5328 return Py_BuildValue("II", minimum, maximum);
5329#else
5330 return Py_BuildValue("ii", minimum, maximum);
5331#endif
5332}
5333#endif
5334
5335#if (DBVER >= 45)
5336static PyObject*
5337DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
5338{
5339 int err;
5340 int limit;
5341
5342 if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
5343 return NULL;
5344 CHECK_ENV_NOT_CLOSED(self);
5345
5346 MYDB_BEGIN_ALLOW_THREADS;
5347 err = self->db_env->rep_set_limit(self->db_env, 0, limit);
5348 MYDB_END_ALLOW_THREADS;
5349 RETURN_IF_ERR();
5350 RETURN_NONE();
5351}
5352
5353static PyObject*
5354DBEnv_rep_get_limit(DBEnvObject* self)
5355{
5356 int err;
5357 u_int32_t gbytes, bytes;
5358
5359 CHECK_ENV_NOT_CLOSED(self);
5360 MYDB_BEGIN_ALLOW_THREADS;
5361 err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
5362 MYDB_END_ALLOW_THREADS;
5363 RETURN_IF_ERR();
5364 return NUMBER_FromLong(bytes);
5365}
5366#endif
5367
5368#if (DBVER >= 44)
5369static PyObject*
5370DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
5371{
5372 int err;
5373 int which;
5374 int onoff;
5375
5376 if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
5377 return NULL;
5378 CHECK_ENV_NOT_CLOSED(self);
5379
5380 MYDB_BEGIN_ALLOW_THREADS;
5381 err = self->db_env->rep_set_config(self->db_env, which, onoff);
5382 MYDB_END_ALLOW_THREADS;
5383 RETURN_IF_ERR();
5384 RETURN_NONE();
5385}
5386
5387static PyObject*
5388DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
5389{
5390 int err;
5391 int which;
5392 int onoff;
5393
5394 if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
5395 return NULL;
5396 }
5397 CHECK_ENV_NOT_CLOSED(self);
5398 MYDB_BEGIN_ALLOW_THREADS;
5399 err = self->db_env->rep_get_config(self->db_env, which, &onoff);
5400 MYDB_END_ALLOW_THREADS;
5401 RETURN_IF_ERR();
5402 return PyBool_FromLong(onoff);
5403}
5404#endif
5405
5406#if (DBVER >= 46)
5407static PyObject*
5408DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
5409{
5410 int err;
5411 u_int32_t nsites, nvotes;
5412
5413 if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
5414 return NULL;
5415 }
5416 CHECK_ENV_NOT_CLOSED(self);
5417 MYDB_BEGIN_ALLOW_THREADS;
5418 err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0);
5419 MYDB_END_ALLOW_THREADS;
5420 RETURN_IF_ERR();
5421 RETURN_NONE();
5422}
5423#endif
5424
5425static PyObject*
5426DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5427{
5428 int err;
5429 PyObject *cdata_py = Py_None;
5430 DBT cdata;
5431 int flags;
5432 static char* kwnames[] = {"flags","cdata", NULL};
5433
5434 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5435 "i|O:rep_start", kwnames, &flags, &cdata_py))
5436 {
5437 return NULL;
5438 }
5439 CHECK_ENV_NOT_CLOSED(self);
5440
5441 if (!make_dbt(cdata_py, &cdata))
5442 return NULL;
5443
5444 MYDB_BEGIN_ALLOW_THREADS;
5445 err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
5446 flags);
5447 MYDB_END_ALLOW_THREADS;
5448 RETURN_IF_ERR();
5449 RETURN_NONE();
5450}
5451
5452#if (DBVER >= 44)
5453static PyObject*
5454DBEnv_rep_sync(DBEnvObject* self)
5455{
5456 int err;
5457
5458 CHECK_ENV_NOT_CLOSED(self);
5459 MYDB_BEGIN_ALLOW_THREADS;
5460 err = self->db_env->rep_sync(self->db_env, 0);
5461 MYDB_END_ALLOW_THREADS;
5462 RETURN_IF_ERR();
5463 RETURN_NONE();
5464}
5465#endif
5466
5467
5468#if (DBVER >= 45)
5469static PyObject*
5470DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5471{
5472 int err;
5473 int nsites;
5474
5475 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5476 return NULL;
5477 }
5478 CHECK_ENV_NOT_CLOSED(self);
5479 MYDB_BEGIN_ALLOW_THREADS;
5480 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5481 MYDB_END_ALLOW_THREADS;
5482 RETURN_IF_ERR();
5483 RETURN_NONE();
5484}
5485
5486static PyObject*
5487DBEnv_rep_get_nsites(DBEnvObject* self)
5488{
5489 int err;
5490#if (DBVER >= 47)
5491 u_int32_t nsites;
5492#else
5493 int nsites;
5494#endif
5495
5496 CHECK_ENV_NOT_CLOSED(self);
5497 MYDB_BEGIN_ALLOW_THREADS;
5498 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5499 MYDB_END_ALLOW_THREADS;
5500 RETURN_IF_ERR();
5501 return NUMBER_FromLong(nsites);
5502}
5503
5504static PyObject*
5505DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5506{
5507 int err;
5508 int priority;
5509
5510 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5511 return NULL;
5512 }
5513 CHECK_ENV_NOT_CLOSED(self);
5514 MYDB_BEGIN_ALLOW_THREADS;
5515 err = self->db_env->rep_set_priority(self->db_env, priority);
5516 MYDB_END_ALLOW_THREADS;
5517 RETURN_IF_ERR();
5518 RETURN_NONE();
5519}
5520
5521static PyObject*
5522DBEnv_rep_get_priority(DBEnvObject* self)
5523{
5524 int err;
5525#if (DBVER >= 47)
5526 u_int32_t priority;
5527#else
5528 int priority;
5529#endif
5530
5531 CHECK_ENV_NOT_CLOSED(self);
5532 MYDB_BEGIN_ALLOW_THREADS;
5533 err = self->db_env->rep_get_priority(self->db_env, &priority);
5534 MYDB_END_ALLOW_THREADS;
5535 RETURN_IF_ERR();
5536 return NUMBER_FromLong(priority);
5537}
5538
5539static PyObject*
5540DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5541{
5542 int err;
5543 int which, timeout;
5544
5545 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5546 return NULL;
5547 }
5548 CHECK_ENV_NOT_CLOSED(self);
5549 MYDB_BEGIN_ALLOW_THREADS;
5550 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5551 MYDB_END_ALLOW_THREADS;
5552 RETURN_IF_ERR();
5553 RETURN_NONE();
5554}
5555
5556static PyObject*
5557DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5558{
5559 int err;
5560 int which;
5561 u_int32_t timeout;
5562
5563 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5564 return NULL;
5565 }
5566 CHECK_ENV_NOT_CLOSED(self);
5567 MYDB_BEGIN_ALLOW_THREADS;
5568 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5569 MYDB_END_ALLOW_THREADS;
5570 RETURN_IF_ERR();
5571 return NUMBER_FromLong(timeout);
5572}
5573#endif
5574
5575/* --------------------------------------------------------------------- */
5576/* REPLICATION METHODS: Replication Manager */
5577
5578#if (DBVER >= 45)
5579static PyObject*
5580DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5581 kwargs)
5582{
5583 int err;
5584 int nthreads, flags;
5585 static char* kwnames[] = {"nthreads","flags", NULL};
5586
5587 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5588 "ii:repmgr_start", kwnames, &nthreads, &flags))
5589 {
5590 return NULL;
5591 }
5592 CHECK_ENV_NOT_CLOSED(self);
5593 MYDB_BEGIN_ALLOW_THREADS;
5594 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5595 MYDB_END_ALLOW_THREADS;
5596 RETURN_IF_ERR();
5597 RETURN_NONE();
5598}
5599
5600static PyObject*
5601DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5602 kwargs)
5603{
5604 int err;
5605 char *host;
5606 int port;
5607 int flags = 0;
5608 static char* kwnames[] = {"host", "port", "flags", NULL};
5609
5610 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5611 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5612 {
5613 return NULL;
5614 }
5615 CHECK_ENV_NOT_CLOSED(self);
5616 MYDB_BEGIN_ALLOW_THREADS;
5617 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5618 MYDB_END_ALLOW_THREADS;
5619 RETURN_IF_ERR();
5620 RETURN_NONE();
5621}
5622
5623static PyObject*
5624DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5625 kwargs)
5626{
5627 int err;
5628 char *host;
5629 int port;
5630 int flags = 0;
5631 int eidp;
5632 static char* kwnames[] = {"host", "port", "flags", NULL};
5633
5634 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5635 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5636 {
5637 return NULL;
5638 }
5639 CHECK_ENV_NOT_CLOSED(self);
5640 MYDB_BEGIN_ALLOW_THREADS;
5641 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5642 MYDB_END_ALLOW_THREADS;
5643 RETURN_IF_ERR();
5644 return NUMBER_FromLong(eidp);
5645}
5646
5647static PyObject*
5648DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5649{
5650 int err;
5651 int ack_policy;
5652
5653 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5654 {
5655 return NULL;
5656 }
5657 CHECK_ENV_NOT_CLOSED(self);
5658 MYDB_BEGIN_ALLOW_THREADS;
5659 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5660 MYDB_END_ALLOW_THREADS;
5661 RETURN_IF_ERR();
5662 RETURN_NONE();
5663}
5664
5665static PyObject*
5666DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
5667{
5668 int err;
5669 int ack_policy;
5670
5671 CHECK_ENV_NOT_CLOSED(self);
5672 MYDB_BEGIN_ALLOW_THREADS;
5673 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5674 MYDB_END_ALLOW_THREADS;
5675 RETURN_IF_ERR();
5676 return NUMBER_FromLong(ack_policy);
5677}
5678
5679static PyObject*
5680DBEnv_repmgr_site_list(DBEnvObject* self)
5681{
5682 int err;
5683 unsigned int countp;
5684 DB_REPMGR_SITE *listp;
5685 PyObject *stats, *key, *tuple;
5686
5687 CHECK_ENV_NOT_CLOSED(self);
5688 MYDB_BEGIN_ALLOW_THREADS;
5689 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5690 MYDB_END_ALLOW_THREADS;
5691 RETURN_IF_ERR();
5692
5693 stats=PyDict_New();
5694 if (stats == NULL) {
5695 free(listp);
5696 return NULL;
5697 }
5698
5699 for(;countp--;) {
5700 key=NUMBER_FromLong(listp[countp].eid);
5701 if(!key) {
5702 Py_DECREF(stats);
5703 free(listp);
5704 return NULL;
5705 }
5706#if (PY_VERSION_HEX >= 0x02040000)
5707 tuple=Py_BuildValue("(sII)", listp[countp].host,
5708 listp[countp].port, listp[countp].status);
5709#else
5710 tuple=Py_BuildValue("(sii)", listp[countp].host,
5711 listp[countp].port, listp[countp].status);
5712#endif
5713 if(!tuple) {
5714 Py_DECREF(key);
5715 Py_DECREF(stats);
5716 free(listp);
5717 return NULL;
5718 }
5719 if(PyDict_SetItem(stats, key, tuple)) {
5720 Py_DECREF(key);
5721 Py_DECREF(tuple);
5722 Py_DECREF(stats);
5723 free(listp);
5724 return NULL;
5725 }
5726 }
5727 free(listp);
5728 return stats;
5729}
5730#endif
5731
5732#if (DBVER >= 46)
5733static PyObject*
5734DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5735{
5736 int err;
5737 int flags=0;
5738 static char* kwnames[] = { "flags", NULL };
5739
5740 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5741 kwnames, &flags))
5742 {
5743 return NULL;
5744 }
5745 CHECK_ENV_NOT_CLOSED(self);
5746 MYDB_BEGIN_ALLOW_THREADS;
5747 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5748 MYDB_END_ALLOW_THREADS;
5749 RETURN_IF_ERR();
5750 RETURN_NONE();
5751}
5752
5753static PyObject*
5754DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5755{
5756 int err;
5757 int flags=0;
5758 DB_REPMGR_STAT *statp;
5759 PyObject *stats;
5760 static char* kwnames[] = { "flags", NULL };
5761
5762 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5763 kwnames, &flags))
5764 {
5765 return NULL;
5766 }
5767 CHECK_ENV_NOT_CLOSED(self);
5768 MYDB_BEGIN_ALLOW_THREADS;
5769 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5770 MYDB_END_ALLOW_THREADS;
5771 RETURN_IF_ERR();
5772
5773 stats=PyDict_New();
5774 if (stats == NULL) {
5775 free(statp);
5776 return NULL;
5777 }
5778
5779#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5780
5781 MAKE_ENTRY(perm_failed);
5782 MAKE_ENTRY(msgs_queued);
5783 MAKE_ENTRY(msgs_dropped);
5784 MAKE_ENTRY(connection_drop);
5785 MAKE_ENTRY(connect_fail);
5786
5787#undef MAKE_ENTRY
5788
5789 free(statp);
5790 return stats;
5791}
5792#endif
5793
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005794
5795/* --------------------------------------------------------------------- */
5796/* DBTxn methods */
5797
5798
Jesus Cea6ba33292008-08-31 14:12:11 +00005799static void _close_transaction_cursors(DBTxnObject* txn)
5800{
5801 PyObject *dummy;
5802
5803 while(txn->children_cursors) {
5804 PyErr_Warn(PyExc_RuntimeWarning,
5805 "Must close cursors before resolving a transaction.");
5806 dummy=DBC_close_internal(txn->children_cursors);
5807 Py_XDECREF(dummy);
5808 }
5809}
5810
5811static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5812{
5813 DBObject *db;
5814#if (DBVER >= 43)
5815 DBSequenceObject *dbs;
5816#endif
5817
5818 while (txn->children_dbs) {
5819 db=txn->children_dbs;
5820 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5821 if (txn->parent_txn) {
5822 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5823 db->txn=txn->parent_txn;
5824 } else {
5825 /* The db is already linked to its environment,
5826 ** so nothing to do.
5827 */
5828 db->txn=NULL;
5829 }
5830 }
5831
5832#if (DBVER >= 43)
5833 while (txn->children_sequences) {
5834 dbs=txn->children_sequences;
5835 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5836 if (txn->parent_txn) {
5837 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5838 dbs->txn=txn->parent_txn;
5839 } else {
5840 /* The sequence is already linked to its
5841 ** parent db. Nothing to do.
5842 */
5843 dbs->txn=NULL;
5844 }
5845 }
5846#endif
5847}
5848
5849
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005850static PyObject*
5851DBTxn_commit(DBTxnObject* self, PyObject* args)
5852{
5853 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005854 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005855
5856 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5857 return NULL;
5858
Jesus Cea6ba33292008-08-31 14:12:11 +00005859 _close_transaction_cursors(self);
5860
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005861 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005862 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Cea6ba33292008-08-31 14:12:11 +00005863 "after txn_commit, txn_abort "
5864 "or txn_discard");
5865 if (t) {
5866 PyErr_SetObject(DBError, t);
5867 Py_DECREF(t);
5868 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005869 return NULL;
5870 }
Jesus Cea6ba33292008-08-31 14:12:11 +00005871 self->flag_prepare=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005872 txn = self->txn;
5873 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Cea6ba33292008-08-31 14:12:11 +00005874
5875 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5876
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005877 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005878 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005879 MYDB_END_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00005880
5881 _promote_transaction_dbs_and_sequences(self);
5882
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005883 RETURN_IF_ERR();
5884 RETURN_NONE();
5885}
5886
5887static PyObject*
5888DBTxn_prepare(DBTxnObject* self, PyObject* args)
5889{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005890 int err;
5891 char* gid=NULL;
5892 int gid_size=0;
5893
Jesus Cea6ba33292008-08-31 14:12:11 +00005894 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005895 return NULL;
5896
5897 if (gid_size != DB_XIDDATASIZE) {
5898 PyErr_SetString(PyExc_TypeError,
5899 "gid must be DB_XIDDATASIZE bytes long");
5900 return NULL;
5901 }
5902
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005903 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005904 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
Jesus Cea6ba33292008-08-31 14:12:11 +00005905 "after txn_commit, txn_abort "
5906 "or txn_discard");
5907 if (t) {
5908 PyErr_SetObject(DBError, t);
5909 Py_DECREF(t);
5910 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005911 return NULL;
5912 }
Jesus Cea6ba33292008-08-31 14:12:11 +00005913 self->flag_prepare=1; /* Prepare state */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005914 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005915 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005916 MYDB_END_ALLOW_THREADS;
5917 RETURN_IF_ERR();
5918 RETURN_NONE();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005919}
5920
5921
5922static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00005923DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005924{
Jesus Cea6ba33292008-08-31 14:12:11 +00005925 PyObject *dummy;
5926 int err=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005927 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005928
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005929 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005930 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Cea6ba33292008-08-31 14:12:11 +00005931 "after txn_commit, txn_abort "
5932 "or txn_discard");
5933 if (t) {
5934 PyErr_SetObject(DBError, t);
5935 Py_DECREF(t);
5936 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005937 return NULL;
5938 }
5939 txn = self->txn;
5940 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Cea6ba33292008-08-31 14:12:11 +00005941
5942 _close_transaction_cursors(self);
5943#if (DBVER >= 43)
5944 while (self->children_sequences) {
5945 dummy=DBSequence_close_internal(self->children_sequences,0,0);
5946 Py_XDECREF(dummy);
5947 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005948#endif
Jesus Cea6ba33292008-08-31 14:12:11 +00005949 while (self->children_dbs) {
5950 dummy=DB_close_internal(self->children_dbs,0);
5951 Py_XDECREF(dummy);
5952 }
5953
5954 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5955
5956 MYDB_BEGIN_ALLOW_THREADS;
5957 if (discard) {
5958 assert(!self->flag_prepare);
5959 err = txn->discard(txn,0);
5960 } else {
5961 /*
5962 ** If the transaction is in the "prepare" or "recover" state,
5963 ** we better do not implicitly abort it.
5964 */
5965 if (!self->flag_prepare) {
5966 err = txn->abort(txn);
5967 }
5968 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005969 MYDB_END_ALLOW_THREADS;
5970 RETURN_IF_ERR();
5971 RETURN_NONE();
5972}
5973
Jesus Cea6ba33292008-08-31 14:12:11 +00005974static PyObject*
5975DBTxn_abort(DBTxnObject* self)
5976{
5977 self->flag_prepare=0;
5978 _close_transaction_cursors(self);
5979
5980 return DBTxn_abort_discard_internal(self,0);
5981}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005982
5983static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00005984DBTxn_discard(DBTxnObject* self)
5985{
5986 self->flag_prepare=0;
5987 _close_transaction_cursors(self);
5988
5989 return DBTxn_abort_discard_internal(self,1);
5990}
5991
5992
5993static PyObject*
5994DBTxn_id(DBTxnObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005995{
5996 int id;
5997
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005998 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005999 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Cea6ba33292008-08-31 14:12:11 +00006000 "after txn_commit, txn_abort "
6001 "or txn_discard");
6002 if (t) {
6003 PyErr_SetObject(DBError, t);
6004 Py_DECREF(t);
6005 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00006006 return NULL;
6007 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006008 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006009 id = self->txn->id(self->txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006010 MYDB_END_ALLOW_THREADS;
Jesus Cea6ba33292008-08-31 14:12:11 +00006011 return NUMBER_FromLong(id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006012}
6013
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006014#if (DBVER >= 43)
6015/* --------------------------------------------------------------------- */
6016/* DBSequence methods */
6017
6018
6019static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00006020DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006021{
Jesus Cea6ba33292008-08-31 14:12:11 +00006022 int err=0;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006023
Jesus Cea6ba33292008-08-31 14:12:11 +00006024 if (self->sequence!=NULL) {
6025 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
6026 if (self->txn) {
6027 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
6028 self->txn=NULL;
6029 }
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006030
Jesus Cea6ba33292008-08-31 14:12:11 +00006031 if (!do_not_close) {
6032 MYDB_BEGIN_ALLOW_THREADS
6033 err = self->sequence->close(self->sequence, flags);
6034 MYDB_END_ALLOW_THREADS
6035 }
6036 self->sequence = NULL;
6037
6038 RETURN_IF_ERR();
6039 }
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006040
6041 RETURN_NONE();
6042}
6043
6044static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00006045DBSequence_close(DBSequenceObject* self, PyObject* args)
6046{
6047 int flags=0;
6048 if (!PyArg_ParseTuple(args,"|i:close", &flags))
6049 return NULL;
6050
6051 return DBSequence_close_internal(self,flags,0);
6052}
6053
6054static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006055DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6056{
6057 int err, flags = 0;
6058 int delta = 1;
6059 db_seq_t value;
6060 PyObject *txnobj = NULL;
6061 DB_TXN *txn = NULL;
6062 static char* kwnames[] = {"delta", "txn", "flags", NULL };
6063 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
6064 return NULL;
6065 CHECK_SEQUENCE_NOT_CLOSED(self)
6066
6067 if (!checkTxnObj(txnobj, &txn))
6068 return NULL;
6069
6070 MYDB_BEGIN_ALLOW_THREADS
6071 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
6072 MYDB_END_ALLOW_THREADS
6073
6074 RETURN_IF_ERR();
6075 return PyLong_FromLongLong(value);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006076}
6077
6078static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00006079DBSequence_get_dbp(DBSequenceObject* self)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006080{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006081 CHECK_SEQUENCE_NOT_CLOSED(self)
6082 Py_INCREF(self->mydb);
6083 return (PyObject* )self->mydb;
6084}
6085
6086static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00006087DBSequence_get_key(DBSequenceObject* self)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006088{
6089 int err;
6090 DBT key;
Guido van Rossum8ce8a782007-11-01 19:42:39 +00006091 PyObject *retval = NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00006092
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00006093 key.flags = DB_DBT_MALLOC;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006094 CHECK_SEQUENCE_NOT_CLOSED(self)
6095 MYDB_BEGIN_ALLOW_THREADS
6096 err = self->sequence->get_key(self->sequence, &key);
6097 MYDB_END_ALLOW_THREADS
6098
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00006099 if (!err)
Jesus Cea6ba33292008-08-31 14:12:11 +00006100 retval = Build_PyString(key.data, key.size);
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00006101
Jesus Cea6ba33292008-08-31 14:12:11 +00006102 FREE_DBT(key);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006103 RETURN_IF_ERR();
6104
Gregory P. Smith9e780cc2007-10-06 08:22:26 +00006105 return retval;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006106}
6107
6108static PyObject*
6109DBSequence_init_value(DBSequenceObject* self, PyObject* args)
6110{
6111 int err;
Jesus Cea6ba33292008-08-31 14:12:11 +00006112 PY_LONG_LONG value;
6113 db_seq_t value2;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006114 if (!PyArg_ParseTuple(args,"L:init_value", &value))
6115 return NULL;
6116 CHECK_SEQUENCE_NOT_CLOSED(self)
6117
Jesus Cea6ba33292008-08-31 14:12:11 +00006118 value2=value; /* If truncation, compiler should show a warning */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006119 MYDB_BEGIN_ALLOW_THREADS
Jesus Cea6ba33292008-08-31 14:12:11 +00006120 err = self->sequence->initial_value(self->sequence, value2);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006121 MYDB_END_ALLOW_THREADS
6122
6123 RETURN_IF_ERR();
6124
6125 RETURN_NONE();
6126}
6127
6128static PyObject*
6129DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6130{
6131 int err, flags = 0;
Jesus Cea6ba33292008-08-31 14:12:11 +00006132 PyObject* keyobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006133 PyObject *txnobj = NULL;
6134 DB_TXN *txn = NULL;
6135 DBT key;
6136
6137 static char* kwnames[] = {"key", "txn", "flags", NULL };
6138 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
6139 return NULL;
6140
6141 if (!checkTxnObj(txnobj, &txn))
6142 return NULL;
6143
Jesus Cea6ba33292008-08-31 14:12:11 +00006144 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006145 return NULL;
6146
6147 MYDB_BEGIN_ALLOW_THREADS
6148 err = self->sequence->open(self->sequence, txn, &key, flags);
6149 MYDB_END_ALLOW_THREADS
6150
Jesus Cea6ba33292008-08-31 14:12:11 +00006151 CLEAR_DBT(key);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006152 RETURN_IF_ERR();
6153
Jesus Cea6ba33292008-08-31 14:12:11 +00006154 if (txn) {
6155 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
6156 self->txn=(DBTxnObject *)txnobj;
6157 }
6158
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006159 RETURN_NONE();
6160}
6161
6162static PyObject*
6163DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6164{
Jesus Cea6ba33292008-08-31 14:12:11 +00006165 PyObject *dummy;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006166 int err, flags = 0;
6167 PyObject *txnobj = NULL;
6168 DB_TXN *txn = NULL;
6169
6170 static char* kwnames[] = {"txn", "flags", NULL };
6171 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
6172 return NULL;
6173
6174 if (!checkTxnObj(txnobj, &txn))
6175 return NULL;
6176
6177 CHECK_SEQUENCE_NOT_CLOSED(self)
6178
6179 MYDB_BEGIN_ALLOW_THREADS
6180 err = self->sequence->remove(self->sequence, txn, flags);
6181 MYDB_END_ALLOW_THREADS
6182
Jesus Cea6ba33292008-08-31 14:12:11 +00006183 dummy=DBSequence_close_internal(self,flags,1);
6184 Py_XDECREF(dummy);
6185
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006186 RETURN_IF_ERR();
6187 RETURN_NONE();
6188}
6189
6190static PyObject*
6191DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
6192{
6193 int err, size;
6194 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
6195 return NULL;
6196 CHECK_SEQUENCE_NOT_CLOSED(self)
6197
6198 MYDB_BEGIN_ALLOW_THREADS
6199 err = self->sequence->set_cachesize(self->sequence, size);
6200 MYDB_END_ALLOW_THREADS
6201
6202 RETURN_IF_ERR();
6203 RETURN_NONE();
6204}
6205
6206static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00006207DBSequence_get_cachesize(DBSequenceObject* self)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006208{
6209 int err, size;
Jesus Cea6ba33292008-08-31 14:12:11 +00006210
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006211 CHECK_SEQUENCE_NOT_CLOSED(self)
6212
6213 MYDB_BEGIN_ALLOW_THREADS
6214 err = self->sequence->get_cachesize(self->sequence, &size);
6215 MYDB_END_ALLOW_THREADS
6216
6217 RETURN_IF_ERR();
Jesus Cea6ba33292008-08-31 14:12:11 +00006218 return NUMBER_FromLong(size);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006219}
6220
6221static PyObject*
6222DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
6223{
6224 int err, flags = 0;
6225 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
6226 return NULL;
6227 CHECK_SEQUENCE_NOT_CLOSED(self)
6228
6229 MYDB_BEGIN_ALLOW_THREADS
6230 err = self->sequence->set_flags(self->sequence, flags);
6231 MYDB_END_ALLOW_THREADS
6232
6233 RETURN_IF_ERR();
6234 RETURN_NONE();
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006235}
6236
6237static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00006238DBSequence_get_flags(DBSequenceObject* self)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006239{
6240 unsigned int flags;
6241 int err;
Jesus Cea6ba33292008-08-31 14:12:11 +00006242
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006243 CHECK_SEQUENCE_NOT_CLOSED(self)
6244
6245 MYDB_BEGIN_ALLOW_THREADS
6246 err = self->sequence->get_flags(self->sequence, &flags);
6247 MYDB_END_ALLOW_THREADS
6248
6249 RETURN_IF_ERR();
Jesus Cea6ba33292008-08-31 14:12:11 +00006250 return NUMBER_FromLong((int)flags);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006251}
6252
6253static PyObject*
6254DBSequence_set_range(DBSequenceObject* self, PyObject* args)
6255{
6256 int err;
Jesus Cea6ba33292008-08-31 14:12:11 +00006257 PY_LONG_LONG min, max;
6258 db_seq_t min2, max2;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006259 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
6260 return NULL;
6261 CHECK_SEQUENCE_NOT_CLOSED(self)
6262
Jesus Cea6ba33292008-08-31 14:12:11 +00006263 min2=min; /* If truncation, compiler should show a warning */
6264 max2=max;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006265 MYDB_BEGIN_ALLOW_THREADS
Jesus Cea6ba33292008-08-31 14:12:11 +00006266 err = self->sequence->set_range(self->sequence, min2, max2);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006267 MYDB_END_ALLOW_THREADS
6268
6269 RETURN_IF_ERR();
6270 RETURN_NONE();
6271}
6272
6273static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00006274DBSequence_get_range(DBSequenceObject* self)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006275{
6276 int err;
Jesus Cea6ba33292008-08-31 14:12:11 +00006277 PY_LONG_LONG min, max;
6278 db_seq_t min2, max2;
6279
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006280 CHECK_SEQUENCE_NOT_CLOSED(self)
6281
6282 MYDB_BEGIN_ALLOW_THREADS
Jesus Cea6ba33292008-08-31 14:12:11 +00006283 err = self->sequence->get_range(self->sequence, &min2, &max2);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006284 MYDB_END_ALLOW_THREADS
6285
6286 RETURN_IF_ERR();
Jesus Cea6ba33292008-08-31 14:12:11 +00006287 min=min2; /* If truncation, compiler should show a warning */
6288 max=max2;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006289 return Py_BuildValue("(LL)", min, max);
6290}
6291
6292static PyObject*
6293DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6294{
6295 int err, flags = 0;
6296 DB_SEQUENCE_STAT* sp = NULL;
6297 PyObject* dict_stat;
6298 static char* kwnames[] = {"flags", NULL };
6299 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
6300 return NULL;
6301 CHECK_SEQUENCE_NOT_CLOSED(self);
6302
6303 MYDB_BEGIN_ALLOW_THREADS;
6304 err = self->sequence->stat(self->sequence, &sp, flags);
6305 MYDB_END_ALLOW_THREADS;
6306 RETURN_IF_ERR();
6307
6308 if ((dict_stat = PyDict_New()) == NULL) {
6309 free(sp);
6310 return NULL;
6311 }
6312
6313
6314#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
6315#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
6316
6317 MAKE_INT_ENTRY(wait);
6318 MAKE_INT_ENTRY(nowait);
6319 MAKE_LONG_LONG_ENTRY(current);
6320 MAKE_LONG_LONG_ENTRY(value);
6321 MAKE_LONG_LONG_ENTRY(last_value);
6322 MAKE_LONG_LONG_ENTRY(min);
6323 MAKE_LONG_LONG_ENTRY(max);
6324 MAKE_INT_ENTRY(cache_size);
6325 MAKE_INT_ENTRY(flags);
6326
6327#undef MAKE_INT_ENTRY
6328#undef MAKE_LONG_LONG_ENTRY
6329
6330 free(sp);
6331 return dict_stat;
6332}
6333#endif
6334
6335
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006336/* --------------------------------------------------------------------- */
6337/* Method definition tables and type objects */
6338
6339static PyMethodDef DB_methods[] = {
Jesus Cea6ba33292008-08-31 14:12:11 +00006340 {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006341 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006342 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006343 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
6344 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006345 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
6346 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006347 {"fd", (PyCFunction)DB_fd, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006348 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00006349 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006350 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006351 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006352 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006353 {"get_type", (PyCFunction)DB_get_type, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006354 {"join", (PyCFunction)DB_join, METH_VARARGS},
6355 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006356 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006357 {"items", (PyCFunction)DB_items, METH_VARARGS},
6358 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6359 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6360 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6361 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6362 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6363 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006364 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006365 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006366#if (DBVER >= 41)
6367 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6368#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006369 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6370 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6371 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6372 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6373 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6374 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6375 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6376 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6377 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006378 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
6379 {"set_private", (PyCFunction)DB_set_private, METH_O},
6380 {"get_private", (PyCFunction)DB_get_private, METH_NOARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006381 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006382 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006383 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006384 {"type", (PyCFunction)DB_get_type, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006385 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6386 {"values", (PyCFunction)DB_values, METH_VARARGS},
6387 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6388 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6389 {NULL, NULL} /* sentinel */
6390};
6391
6392
6393static PyMappingMethods DB_mapping = {
Thomas Wouters0e3f5912006-08-11 14:57:12 +00006394 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006395 (binaryfunc)DB_subscript, /*mp_subscript*/
6396 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6397};
6398
6399
6400static PyMethodDef DBCursor_methods[] = {
Jesus Cea6ba33292008-08-31 14:12:11 +00006401 {"close", (PyCFunction)DBC_close, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006402 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6403 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6404 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6405 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6406 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6407 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00006408 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006409 {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006410 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6411 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6412 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6413 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6414 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6415 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6416 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006417 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00006418 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006419 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6420 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6421 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6422 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6423 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6424 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6425 {NULL, NULL} /* sentinel */
6426};
6427
6428
6429static PyMethodDef DBEnv_methods[] = {
6430 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6431 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6432 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006433#if (DBVER >= 41)
6434 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6435 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6436 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6437#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00006438 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00006439 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006440 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6441 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006442 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006443#if (DBVER >= 47)
6444 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
6445#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006446 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6447 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6448 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006449#if (DBVER >= 42)
6450 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006451#endif
Jesus Cea6ba33292008-08-31 14:12:11 +00006452 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006453 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00006454#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006455 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Thomas Wouters902d6eb2007-01-09 23:18:33 +00006456#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006457 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6458 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6459 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006460 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6461 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6462 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6463 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6464 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6465 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00006466 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006467 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6468 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006469 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS},
Guido van Rossum77677112007-11-05 19:43:04 +00006470 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006471 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6472 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6473 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006474 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006475 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006476#if (DBVER >= 44)
6477 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6478#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006479 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006480 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS},
6481 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
6482 METH_VARARGS||METH_KEYWORDS},
6483 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6484#if (DBVER >= 42)
6485 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6486#endif
6487 {"set_private", (PyCFunction)DBEnv_set_private, METH_O},
6488 {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS},
6489 {"rep_start", (PyCFunction)DBEnv_rep_start,
6490 METH_VARARGS|METH_KEYWORDS},
6491 {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
6492 {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
6493 METH_VARARGS},
6494#if (DBVER >= 46)
6495 {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS},
6496#endif
6497#if (DBVER >= 44)
6498 {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS},
6499 {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS},
6500 {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS},
6501#endif
6502#if (DBVER >= 45)
6503 {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS},
6504 {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS},
6505#endif
6506#if (DBVER >= 47)
6507 {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS},
6508 {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS},
6509#endif
6510#if (DBVER >= 45)
6511 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
6512#endif
6513#if (DBVER >= 45)
6514 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
6515 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
6516 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
6517 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
6518 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6519 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6520#endif
6521#if (DBVER >= 45)
6522 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6523 METH_VARARGS|METH_KEYWORDS},
6524 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6525 METH_VARARGS|METH_KEYWORDS},
6526 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6527 METH_VARARGS|METH_KEYWORDS},
6528 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6529 METH_VARARGS},
6530 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
6531 METH_NOARGS},
6532 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
6533 METH_NOARGS},
6534#endif
6535#if (DBVER >= 46)
6536 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6537 METH_VARARGS|METH_KEYWORDS},
6538 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6539 METH_VARARGS|METH_KEYWORDS},
6540#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006541 {NULL, NULL} /* sentinel */
6542};
6543
6544
6545static PyMethodDef DBTxn_methods[] = {
6546 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6547 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006548 {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS},
6549 {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS},
6550 {"id", (PyCFunction)DBTxn_id, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006551 {NULL, NULL} /* sentinel */
6552};
6553
6554
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006555#if (DBVER >= 43)
6556static PyMethodDef DBSequence_methods[] = {
6557 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6558 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006559 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS},
6560 {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006561 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6562 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6563 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6564 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006565 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006566 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006567 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006568 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006569 {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS},
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006570 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6571 {NULL, NULL} /* sentinel */
6572};
6573#endif
6574
Jesus Cea6ba33292008-08-31 14:12:11 +00006575
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006576static PyObject*
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006577DBEnv_db_home_get(DBEnvObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006578{
Jesus Cea6ba33292008-08-31 14:12:11 +00006579 const char *home = NULL;
6580
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006581 CHECK_ENV_NOT_CLOSED(self);
Jesus Cea6ba33292008-08-31 14:12:11 +00006582
6583#if (DBVER >= 42)
6584 self->db_env->get_home(self->db_env, &home);
6585#else
6586 home=self->db_env->db_home;
6587#endif
6588
6589 if (home == NULL) {
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006590 RETURN_NONE();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006591 }
Jesus Cea6ba33292008-08-31 14:12:11 +00006592 return PyBytes_FromString(home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006593}
6594
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006595static PyGetSetDef DBEnv_getsets[] = {
6596 {"db_home", (getter)DBEnv_db_home_get, NULL,},
6597 {NULL}
6598};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006599
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006600
Jesus Cea6ba33292008-08-31 14:12:11 +00006601statichere PyTypeObject DB_Type = {
6602#if (PY_VERSION_HEX < 0x03000000)
6603 PyObject_HEAD_INIT(NULL)
6604 0, /*ob_size*/
6605#else
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00006606 PyVarObject_HEAD_INIT(NULL, 0)
Jesus Cea6ba33292008-08-31 14:12:11 +00006607#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006608 "DB", /*tp_name*/
6609 sizeof(DBObject), /*tp_basicsize*/
6610 0, /*tp_itemsize*/
6611 /* methods */
6612 (destructor)DB_dealloc, /*tp_dealloc*/
Jesus Cea6ba33292008-08-31 14:12:11 +00006613 0, /*tp_print*/
6614 0, /*tp_getattr*/
6615 0, /*tp_setattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006616 0, /*tp_compare*/
6617 0, /*tp_repr*/
6618 0, /*tp_as_number*/
6619 0, /*tp_as_sequence*/
6620 &DB_mapping,/*tp_as_mapping*/
6621 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006622 0, /* tp_call */
6623 0, /* tp_str */
6624 0, /* tp_getattro */
Jesus Cea6ba33292008-08-31 14:12:11 +00006625 0, /* tp_setattro */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006626 0, /* tp_as_buffer */
Jesus Cea6ba33292008-08-31 14:12:11 +00006627#if (PY_VERSION_HEX < 0x03000000)
6628 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6629#else
6630 Py_TPFLAGS_DEFAULT, /* tp_flags */
6631#endif
6632 0, /* tp_doc */
6633 0, /* tp_traverse */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006634 0, /* tp_clear */
6635 0, /* tp_richcompare */
6636 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Cea6ba33292008-08-31 14:12:11 +00006637 0, /*tp_iter*/
6638 0, /*tp_iternext*/
6639 DB_methods, /*tp_methods*/
6640 0, /*tp_members*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006641};
6642
6643
Jesus Cea6ba33292008-08-31 14:12:11 +00006644statichere PyTypeObject DBCursor_Type = {
6645#if (PY_VERSION_HEX < 0x03000000)
6646 PyObject_HEAD_INIT(NULL)
6647 0, /*ob_size*/
6648#else
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00006649 PyVarObject_HEAD_INIT(NULL, 0)
Jesus Cea6ba33292008-08-31 14:12:11 +00006650#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006651 "DBCursor", /*tp_name*/
6652 sizeof(DBCursorObject), /*tp_basicsize*/
Jesus Cea6ba33292008-08-31 14:12:11 +00006653 0, /*tp_itemsize*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006654 /* methods */
6655 (destructor)DBCursor_dealloc,/*tp_dealloc*/
Jesus Cea6ba33292008-08-31 14:12:11 +00006656 0, /*tp_print*/
6657 0, /*tp_getattr*/
6658 0, /*tp_setattr*/
6659 0, /*tp_compare*/
6660 0, /*tp_repr*/
6661 0, /*tp_as_number*/
6662 0, /*tp_as_sequence*/
6663 0, /*tp_as_mapping*/
6664 0, /*tp_hash*/
6665 0, /*tp_call*/
6666 0, /*tp_str*/
6667 0, /*tp_getattro*/
6668 0, /*tp_setattro*/
6669 0, /*tp_as_buffer*/
6670#if (PY_VERSION_HEX < 0x03000000)
6671 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6672#else
6673 Py_TPFLAGS_DEFAULT, /* tp_flags */
6674#endif
6675 0, /* tp_doc */
6676 0, /* tp_traverse */
6677 0, /* tp_clear */
6678 0, /* tp_richcompare */
Gregory P. Smitha703a212003-11-03 01:04:41 +00006679 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Cea6ba33292008-08-31 14:12:11 +00006680 0, /*tp_iter*/
6681 0, /*tp_iternext*/
6682 DBCursor_methods, /*tp_methods*/
6683 0, /*tp_members*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006684};
6685
6686
Jesus Cea6ba33292008-08-31 14:12:11 +00006687statichere PyTypeObject DBEnv_Type = {
6688#if (PY_VERSION_HEX < 0x03000000)
6689 PyObject_HEAD_INIT(NULL)
6690 0, /*ob_size*/
6691#else
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00006692 PyVarObject_HEAD_INIT(NULL, 0)
Jesus Cea6ba33292008-08-31 14:12:11 +00006693#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006694 "DBEnv", /*tp_name*/
6695 sizeof(DBEnvObject), /*tp_basicsize*/
6696 0, /*tp_itemsize*/
6697 /* methods */
6698 (destructor)DBEnv_dealloc, /*tp_dealloc*/
6699 0, /*tp_print*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006700 0, /*tp_getattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006701 0, /*tp_setattr*/
6702 0, /*tp_compare*/
6703 0, /*tp_repr*/
6704 0, /*tp_as_number*/
6705 0, /*tp_as_sequence*/
6706 0, /*tp_as_mapping*/
6707 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006708 0, /* tp_call */
6709 0, /* tp_str */
6710 0, /* tp_getattro */
Jesus Cea6ba33292008-08-31 14:12:11 +00006711 0, /* tp_setattro */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006712 0, /* tp_as_buffer */
Jesus Cea6ba33292008-08-31 14:12:11 +00006713#if (PY_VERSION_HEX < 0x03000000)
6714 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6715#else
6716 Py_TPFLAGS_DEFAULT, /* tp_flags */
6717#endif
6718 0, /* tp_doc */
6719 0, /* tp_traverse */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006720 0, /* tp_clear */
6721 0, /* tp_richcompare */
6722 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Cea6ba33292008-08-31 14:12:11 +00006723 0, /* tp_iter */
6724 0, /* tp_iternext */
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006725 DBEnv_methods, /* tp_methods */
Jesus Cea6ba33292008-08-31 14:12:11 +00006726 0, /* tp_members */
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006727 DBEnv_getsets, /* tp_getsets */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006728};
6729
Jesus Cea6ba33292008-08-31 14:12:11 +00006730statichere PyTypeObject DBTxn_Type = {
6731#if (PY_VERSION_HEX < 0x03000000)
6732 PyObject_HEAD_INIT(NULL)
6733 0, /*ob_size*/
6734#else
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00006735 PyVarObject_HEAD_INIT(NULL, 0)
Jesus Cea6ba33292008-08-31 14:12:11 +00006736#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006737 "DBTxn", /*tp_name*/
6738 sizeof(DBTxnObject), /*tp_basicsize*/
6739 0, /*tp_itemsize*/
6740 /* methods */
6741 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6742 0, /*tp_print*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006743 0, /*tp_getattr*/
6744 0, /*tp_setattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006745 0, /*tp_compare*/
6746 0, /*tp_repr*/
6747 0, /*tp_as_number*/
6748 0, /*tp_as_sequence*/
6749 0, /*tp_as_mapping*/
6750 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006751 0, /* tp_call */
6752 0, /* tp_str */
6753 0, /* tp_getattro */
Jesus Cea6ba33292008-08-31 14:12:11 +00006754 0, /* tp_setattro */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006755 0, /* tp_as_buffer */
Jesus Cea6ba33292008-08-31 14:12:11 +00006756#if (PY_VERSION_HEX < 0x03000000)
6757 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6758#else
6759 Py_TPFLAGS_DEFAULT, /* tp_flags */
6760#endif
6761 0, /* tp_doc */
6762 0, /* tp_traverse */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006763 0, /* tp_clear */
6764 0, /* tp_richcompare */
6765 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Cea6ba33292008-08-31 14:12:11 +00006766 0, /*tp_iter*/
6767 0, /*tp_iternext*/
6768 DBTxn_methods, /*tp_methods*/
6769 0, /*tp_members*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006770};
6771
6772
Jesus Cea6ba33292008-08-31 14:12:11 +00006773statichere PyTypeObject DBLock_Type = {
6774#if (PY_VERSION_HEX < 0x03000000)
6775 PyObject_HEAD_INIT(NULL)
6776 0, /*ob_size*/
6777#else
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00006778 PyVarObject_HEAD_INIT(NULL, 0)
Jesus Cea6ba33292008-08-31 14:12:11 +00006779#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006780 "DBLock", /*tp_name*/
6781 sizeof(DBLockObject), /*tp_basicsize*/
6782 0, /*tp_itemsize*/
6783 /* methods */
6784 (destructor)DBLock_dealloc, /*tp_dealloc*/
6785 0, /*tp_print*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006786 0, /*tp_getattr*/
6787 0, /*tp_setattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006788 0, /*tp_compare*/
6789 0, /*tp_repr*/
6790 0, /*tp_as_number*/
6791 0, /*tp_as_sequence*/
6792 0, /*tp_as_mapping*/
6793 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006794 0, /* tp_call */
6795 0, /* tp_str */
6796 0, /* tp_getattro */
Jesus Cea6ba33292008-08-31 14:12:11 +00006797 0, /* tp_setattro */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006798 0, /* tp_as_buffer */
Jesus Cea6ba33292008-08-31 14:12:11 +00006799#if (PY_VERSION_HEX < 0x03000000)
6800 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6801#else
6802 Py_TPFLAGS_DEFAULT, /* tp_flags */
6803#endif
6804 0, /* tp_doc */
6805 0, /* tp_traverse */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006806 0, /* tp_clear */
6807 0, /* tp_richcompare */
6808 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006809};
6810
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006811#if (DBVER >= 43)
Jesus Cea6ba33292008-08-31 14:12:11 +00006812statichere PyTypeObject DBSequence_Type = {
6813#if (PY_VERSION_HEX < 0x03000000)
6814 PyObject_HEAD_INIT(NULL)
6815 0, /*ob_size*/
6816#else
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00006817 PyVarObject_HEAD_INIT(NULL, 0)
Jesus Cea6ba33292008-08-31 14:12:11 +00006818#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006819 "DBSequence", /*tp_name*/
6820 sizeof(DBSequenceObject), /*tp_basicsize*/
6821 0, /*tp_itemsize*/
6822 /* methods */
6823 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6824 0, /*tp_print*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006825 0, /*tp_getattr*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006826 0, /*tp_setattr*/
6827 0, /*tp_compare*/
6828 0, /*tp_repr*/
6829 0, /*tp_as_number*/
6830 0, /*tp_as_sequence*/
6831 0, /*tp_as_mapping*/
6832 0, /*tp_hash*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006833 0, /* tp_call */
6834 0, /* tp_str */
6835 0, /* tp_getattro */
6836 0, /* tp_setattro */
6837 0, /* tp_as_buffer */
Jesus Cea6ba33292008-08-31 14:12:11 +00006838#if (PY_VERSION_HEX < 0x03000000)
6839 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6840#else
6841 Py_TPFLAGS_DEFAULT, /* tp_flags */
6842#endif
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006843 0, /* tp_doc */
6844 0, /* tp_traverse */
6845 0, /* tp_clear */
6846 0, /* tp_richcompare */
6847 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Cea6ba33292008-08-31 14:12:11 +00006848 0, /*tp_iter*/
6849 0, /*tp_iternext*/
6850 DBSequence_methods, /*tp_methods*/
6851 0, /*tp_members*/
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006852};
6853#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006854
6855/* --------------------------------------------------------------------- */
6856/* Module-level functions */
6857
6858static PyObject*
6859DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6860{
6861 PyObject* dbenvobj = NULL;
6862 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00006863 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006864
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006865 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6866 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006867 return NULL;
6868 if (dbenvobj == Py_None)
6869 dbenvobj = NULL;
6870 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6871 makeTypeError("DBEnv", dbenvobj);
6872 return NULL;
6873 }
6874
6875 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6876}
6877
6878
6879static PyObject*
6880DBEnv_construct(PyObject* self, PyObject* args)
6881{
6882 int flags = 0;
6883 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6884 return (PyObject* )newDBEnvObject(flags);
6885}
6886
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006887#if (DBVER >= 43)
6888static PyObject*
6889DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6890{
Thomas Wouters0e3f5912006-08-11 14:57:12 +00006891 PyObject* dbobj;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006892 int flags = 0;
6893 static char* kwnames[] = { "db", "flags", NULL};
6894
6895 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6896 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00006897 if (!DBObject_Check(dbobj)) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006898 makeTypeError("DB", dbobj);
6899 return NULL;
6900 }
6901 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6902}
6903#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006904
6905static char bsddb_version_doc[] =
6906"Returns a tuple of major, minor, and patch release numbers of the\n\
6907underlying DB library.";
6908
6909static PyObject*
Jesus Cea6ba33292008-08-31 14:12:11 +00006910bsddb_version(PyObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006911{
6912 int major, minor, patch;
6913
Jesus Cea6ba33292008-08-31 14:12:11 +00006914 db_version(&major, &minor, &patch);
6915 return Py_BuildValue("(iii)", major, minor, patch);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006916}
6917
6918
6919/* List of functions defined in the module */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006920static PyMethodDef bsddb_methods[] = {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006921 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6922 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
Jesus Cea6ba33292008-08-31 14:12:11 +00006923#if (DBVER >= 43)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00006924 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
Jesus Cea6ba33292008-08-31 14:12:11 +00006925#endif
6926 {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006927 {NULL, NULL} /* sentinel */
6928};
6929
Jesus Cea6ba33292008-08-31 14:12:11 +00006930
Guido van Rossum8ce8a782007-11-01 19:42:39 +00006931/* API structure */
6932static BSDDB_api bsddb_api;
6933
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006934
6935/* --------------------------------------------------------------------- */
6936/* Module initialization */
6937
6938
6939/* Convenience routine to export an integer value.
6940 * Errors are silently ignored, for better or for worse...
6941 */
6942#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
6943
Gregory P. Smith41631e82003-09-21 00:08:14 +00006944#define MODULE_NAME_MAX_LEN 11
6945static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006946
Jesus Cea6ba33292008-08-31 14:12:11 +00006947#if (PY_VERSION_HEX >= 0x03000000)
6948static struct PyModuleDef bsddbmodule = {
6949 PyModuleDef_HEAD_INIT,
6950 _bsddbModuleName, /* Name of module */
6951 NULL, /* module documentation, may be NULL */
6952 -1, /* size of per-interpreter state of the module,
6953 or -1 if the module keeps state in global variables. */
6954 bsddb_methods,
6955 NULL, /* Reload */
6956 NULL, /* Traverse */
6957 NULL, /* Clear */
6958 NULL /* Free */
Martin v. Löwis1a214512008-06-11 05:26:20 +00006959};
Jesus Cea6ba33292008-08-31 14:12:11 +00006960#endif
Martin v. Löwis1a214512008-06-11 05:26:20 +00006961
Jesus Cea6ba33292008-08-31 14:12:11 +00006962
6963#if (PY_VERSION_HEX < 0x03000000)
6964DL_EXPORT(void) init_bsddb(void)
6965#else
6966PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */
6967#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006968{
6969 PyObject* m;
6970 PyObject* d;
Jesus Cea6ba33292008-08-31 14:12:11 +00006971 PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
6972 PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
6973 PyObject* cvsid_s = PyBytes_FromString( rcs_id );
Guido van Rossum8ce8a782007-11-01 19:42:39 +00006974 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006975
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006976 /* Initialize object types */
Jesus Cea6ba33292008-08-31 14:12:11 +00006977 if ((PyType_Ready(&DB_Type) < 0)
6978 || (PyType_Ready(&DBCursor_Type) < 0)
6979 || (PyType_Ready(&DBEnv_Type) < 0)
6980 || (PyType_Ready(&DBTxn_Type) < 0)
6981 || (PyType_Ready(&DBLock_Type) < 0)
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006982#if (DBVER >= 43)
Jesus Cea6ba33292008-08-31 14:12:11 +00006983 || (PyType_Ready(&DBSequence_Type) < 0)
6984#endif
6985 ) {
6986#if (PY_VERSION_HEX < 0x03000000)
6987 return;
6988#else
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +00006989 return NULL;
6990#endif
Jesus Cea6ba33292008-08-31 14:12:11 +00006991 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006992
Mark Hammonda69d4092003-04-22 23:13:27 +00006993#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006994 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00006995 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006996#endif
6997
6998 /* Create the module and add the functions */
Jesus Cea6ba33292008-08-31 14:12:11 +00006999#if (PY_VERSION_HEX < 0x03000000)
7000 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
7001#else
7002 m=PyModule_Create(&bsddbmodule);
7003#endif
7004 if (m == NULL) {
7005#if (PY_VERSION_HEX < 0x03000000)
7006 return;
7007#else
Martin v. Löwis1a214512008-06-11 05:26:20 +00007008 return NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00007009#endif
7010 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007011
7012 /* Add some symbolic constants to the module */
7013 d = PyModule_GetDict(m);
7014 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
Jesus Cea6ba33292008-08-31 14:12:11 +00007015 PyDict_SetItemString(d, "cvsid", cvsid_s);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007016 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
7017 Py_DECREF(pybsddb_version_s);
7018 pybsddb_version_s = NULL;
Jesus Cea6ba33292008-08-31 14:12:11 +00007019 Py_DECREF(cvsid_s);
7020 cvsid_s = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007021 Py_DECREF(db_version_s);
7022 db_version_s = NULL;
7023
7024 ADD_INT(d, DB_VERSION_MAJOR);
7025 ADD_INT(d, DB_VERSION_MINOR);
7026 ADD_INT(d, DB_VERSION_PATCH);
7027
7028 ADD_INT(d, DB_MAX_PAGES);
7029 ADD_INT(d, DB_MAX_RECORDS);
7030
Gregory P. Smith41631e82003-09-21 00:08:14 +00007031#if (DBVER >= 42)
7032 ADD_INT(d, DB_RPCCLIENT);
7033#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007034 ADD_INT(d, DB_CLIENT);
Jesus Cea6ba33292008-08-31 14:12:11 +00007035 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
Gregory P. Smith41631e82003-09-21 00:08:14 +00007036 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
7037#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007038 ADD_INT(d, DB_XA_CREATE);
7039
7040 ADD_INT(d, DB_CREATE);
7041 ADD_INT(d, DB_NOMMAP);
7042 ADD_INT(d, DB_THREAD);
Jesus Cea6ba33292008-08-31 14:12:11 +00007043#if (DBVER >= 45)
7044 ADD_INT(d, DB_MULTIVERSION);
7045#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007046
7047 ADD_INT(d, DB_FORCE);
7048 ADD_INT(d, DB_INIT_CDB);
7049 ADD_INT(d, DB_INIT_LOCK);
7050 ADD_INT(d, DB_INIT_LOG);
7051 ADD_INT(d, DB_INIT_MPOOL);
7052 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007053 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007054
Jesus Cea6ba33292008-08-31 14:12:11 +00007055 ADD_INT(d, DB_XIDDATASIZE);
7056
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007057 ADD_INT(d, DB_RECOVER);
7058 ADD_INT(d, DB_RECOVER_FATAL);
7059 ADD_INT(d, DB_TXN_NOSYNC);
7060 ADD_INT(d, DB_USE_ENVIRON);
7061 ADD_INT(d, DB_USE_ENVIRON_ROOT);
7062
7063 ADD_INT(d, DB_LOCKDOWN);
7064 ADD_INT(d, DB_PRIVATE);
7065 ADD_INT(d, DB_SYSTEM_MEM);
7066
7067 ADD_INT(d, DB_TXN_SYNC);
7068 ADD_INT(d, DB_TXN_NOWAIT);
7069
7070 ADD_INT(d, DB_EXCL);
7071 ADD_INT(d, DB_FCNTL_LOCKING);
7072 ADD_INT(d, DB_ODDFILESIZE);
7073 ADD_INT(d, DB_RDWRMASTER);
7074 ADD_INT(d, DB_RDONLY);
7075 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007076 ADD_INT(d, DB_EXTENT);
7077 ADD_INT(d, DB_CDB_ALLDB);
7078 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007079 ADD_INT(d, DB_UPGRADE);
7080
7081 ADD_INT(d, DB_AGGRESSIVE);
7082 ADD_INT(d, DB_NOORDERCHK);
7083 ADD_INT(d, DB_ORDERCHKONLY);
7084 ADD_INT(d, DB_PR_PAGE);
Jesus Cea6ba33292008-08-31 14:12:11 +00007085
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007086 ADD_INT(d, DB_PR_RECOVERYTEST);
7087 ADD_INT(d, DB_SALVAGE);
7088
7089 ADD_INT(d, DB_LOCK_NORUN);
7090 ADD_INT(d, DB_LOCK_DEFAULT);
7091 ADD_INT(d, DB_LOCK_OLDEST);
7092 ADD_INT(d, DB_LOCK_RANDOM);
7093 ADD_INT(d, DB_LOCK_YOUNGEST);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007094 ADD_INT(d, DB_LOCK_MAXLOCKS);
7095 ADD_INT(d, DB_LOCK_MINLOCKS);
7096 ADD_INT(d, DB_LOCK_MINWRITE);
Jesus Cea6ba33292008-08-31 14:12:11 +00007097
7098 ADD_INT(d, DB_LOCK_EXPIRE);
7099#if (DBVER >= 43)
7100 ADD_INT(d, DB_LOCK_MAXWRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007101#endif
7102
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007103 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007104
7105 ADD_INT(d, DB_LOCK_DUMP);
7106 ADD_INT(d, DB_LOCK_GET);
7107 ADD_INT(d, DB_LOCK_INHERIT);
7108 ADD_INT(d, DB_LOCK_PUT);
7109 ADD_INT(d, DB_LOCK_PUT_ALL);
7110 ADD_INT(d, DB_LOCK_PUT_OBJ);
7111
7112 ADD_INT(d, DB_LOCK_NG);
7113 ADD_INT(d, DB_LOCK_READ);
7114 ADD_INT(d, DB_LOCK_WRITE);
7115 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007116 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007117 ADD_INT(d, DB_LOCK_IWRITE);
7118 ADD_INT(d, DB_LOCK_IREAD);
7119 ADD_INT(d, DB_LOCK_IWR);
Gregory P. Smith29602d22006-01-24 09:46:48 +00007120#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007121 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00007122#else
7123 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
7124#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007125 ADD_INT(d, DB_LOCK_WWRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007126
7127 ADD_INT(d, DB_LOCK_RECORD);
7128 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007129 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007130 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007131
7132 ADD_INT(d, DB_LOCK_NOWAIT);
7133 ADD_INT(d, DB_LOCK_RECORD);
7134 ADD_INT(d, DB_LOCK_UPGRADE);
7135
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007136 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007137#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007138 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007139#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007140 ADD_INT(d, DB_LSTAT_FREE);
7141 ADD_INT(d, DB_LSTAT_HELD);
Jesus Cea6ba33292008-08-31 14:12:11 +00007142
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007143 ADD_INT(d, DB_LSTAT_PENDING);
7144 ADD_INT(d, DB_LSTAT_WAITING);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007145
7146 ADD_INT(d, DB_ARCH_ABS);
7147 ADD_INT(d, DB_ARCH_DATA);
7148 ADD_INT(d, DB_ARCH_LOG);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00007149#if (DBVER >= 42)
7150 ADD_INT(d, DB_ARCH_REMOVE);
7151#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007152
7153 ADD_INT(d, DB_BTREE);
7154 ADD_INT(d, DB_HASH);
7155 ADD_INT(d, DB_RECNO);
7156 ADD_INT(d, DB_QUEUE);
7157 ADD_INT(d, DB_UNKNOWN);
7158
7159 ADD_INT(d, DB_DUP);
7160 ADD_INT(d, DB_DUPSORT);
7161 ADD_INT(d, DB_RECNUM);
7162 ADD_INT(d, DB_RENUMBER);
7163 ADD_INT(d, DB_REVSPLITOFF);
7164 ADD_INT(d, DB_SNAPSHOT);
7165
7166 ADD_INT(d, DB_JOIN_NOSORT);
7167
7168 ADD_INT(d, DB_AFTER);
7169 ADD_INT(d, DB_APPEND);
7170 ADD_INT(d, DB_BEFORE);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00007171#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007172 ADD_INT(d, DB_CACHED_COUNTS);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00007173#endif
Jesus Cea6ba33292008-08-31 14:12:11 +00007174
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007175#if (DBVER >= 41)
7176 _addIntToDict(d, "DB_CHECKPOINT", 0);
7177#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007178 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007179 ADD_INT(d, DB_CURLSN);
7180#endif
Jesus Cea6ba33292008-08-31 14:12:11 +00007181#if (DBVER <= 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007182 ADD_INT(d, DB_COMMIT);
7183#endif
7184 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007185 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007186 ADD_INT(d, DB_CURRENT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007187 ADD_INT(d, DB_FAST_STAT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007188 ADD_INT(d, DB_FIRST);
7189 ADD_INT(d, DB_FLUSH);
7190 ADD_INT(d, DB_GET_BOTH);
7191 ADD_INT(d, DB_GET_RECNO);
7192 ADD_INT(d, DB_JOIN_ITEM);
7193 ADD_INT(d, DB_KEYFIRST);
7194 ADD_INT(d, DB_KEYLAST);
7195 ADD_INT(d, DB_LAST);
7196 ADD_INT(d, DB_NEXT);
7197 ADD_INT(d, DB_NEXT_DUP);
7198 ADD_INT(d, DB_NEXT_NODUP);
7199 ADD_INT(d, DB_NODUPDATA);
7200 ADD_INT(d, DB_NOOVERWRITE);
7201 ADD_INT(d, DB_NOSYNC);
7202 ADD_INT(d, DB_POSITION);
7203 ADD_INT(d, DB_PREV);
7204 ADD_INT(d, DB_PREV_NODUP);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00007205#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007206 ADD_INT(d, DB_RECORDCOUNT);
Thomas Wouters902d6eb2007-01-09 23:18:33 +00007207#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007208 ADD_INT(d, DB_SET);
7209 ADD_INT(d, DB_SET_RANGE);
7210 ADD_INT(d, DB_SET_RECNO);
7211 ADD_INT(d, DB_WRITECURSOR);
7212
7213 ADD_INT(d, DB_OPFLAGS_MASK);
7214 ADD_INT(d, DB_RMW);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007215 ADD_INT(d, DB_DIRTY_READ);
7216 ADD_INT(d, DB_MULTIPLE);
7217 ADD_INT(d, DB_MULTIPLE_KEY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007218
Gregory P. Smith29602d22006-01-24 09:46:48 +00007219#if (DBVER >= 44)
7220 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
7221 ADD_INT(d, DB_READ_COMMITTED);
7222#endif
7223
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007224 ADD_INT(d, DB_DONOTINDEX);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007225
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007226#if (DBVER >= 41)
7227 _addIntToDict(d, "DB_INCOMPLETE", 0);
7228#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007229 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007230#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007231 ADD_INT(d, DB_KEYEMPTY);
7232 ADD_INT(d, DB_KEYEXIST);
7233 ADD_INT(d, DB_LOCK_DEADLOCK);
7234 ADD_INT(d, DB_LOCK_NOTGRANTED);
7235 ADD_INT(d, DB_NOSERVER);
7236 ADD_INT(d, DB_NOSERVER_HOME);
7237 ADD_INT(d, DB_NOSERVER_ID);
7238 ADD_INT(d, DB_NOTFOUND);
7239 ADD_INT(d, DB_OLD_VERSION);
7240 ADD_INT(d, DB_RUNRECOVERY);
7241 ADD_INT(d, DB_VERIFY_BAD);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007242 ADD_INT(d, DB_PAGE_NOTFOUND);
7243 ADD_INT(d, DB_SECONDARY_BAD);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007244 ADD_INT(d, DB_STAT_CLEAR);
7245 ADD_INT(d, DB_REGION_INIT);
7246 ADD_INT(d, DB_NOLOCKING);
7247 ADD_INT(d, DB_YIELDCPU);
7248 ADD_INT(d, DB_PANIC_ENVIRONMENT);
7249 ADD_INT(d, DB_NOPANIC);
Jesus Cea6ba33292008-08-31 14:12:11 +00007250
7251#if (DBVER >= 41)
7252 ADD_INT(d, DB_OVERWRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007253#endif
7254
Guido van Rossum2cc30da2007-11-02 23:46:40 +00007255#ifdef DB_REGISTER
7256 ADD_INT(d, DB_REGISTER);
7257#endif
7258
Gregory P. Smith41631e82003-09-21 00:08:14 +00007259#if (DBVER >= 42)
7260 ADD_INT(d, DB_TIME_NOTGRANTED);
7261 ADD_INT(d, DB_TXN_NOT_DURABLE);
7262 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
Gregory P. Smith41631e82003-09-21 00:08:14 +00007263 ADD_INT(d, DB_DIRECT_DB);
7264 ADD_INT(d, DB_INIT_REP);
7265 ADD_INT(d, DB_ENCRYPT);
7266 ADD_INT(d, DB_CHKSUM);
7267#endif
7268
Jesus Cea6ba33292008-08-31 14:12:11 +00007269#if (DBVER >= 42) && (DBVER < 47)
7270 ADD_INT(d, DB_LOG_AUTOREMOVE);
7271 ADD_INT(d, DB_DIRECT_LOG);
7272#endif
7273
7274#if (DBVER >= 47)
7275 ADD_INT(d, DB_LOG_DIRECT);
7276 ADD_INT(d, DB_LOG_DSYNC);
7277 ADD_INT(d, DB_LOG_IN_MEMORY);
7278 ADD_INT(d, DB_LOG_AUTO_REMOVE);
7279 ADD_INT(d, DB_LOG_ZERO);
7280#endif
7281
7282#if (DBVER >= 44)
7283 ADD_INT(d, DB_DSYNC_DB);
7284#endif
7285
7286#if (DBVER >= 45)
7287 ADD_INT(d, DB_TXN_SNAPSHOT);
7288#endif
7289
7290 ADD_INT(d, DB_VERB_DEADLOCK);
7291#if (DBVER >= 46)
7292 ADD_INT(d, DB_VERB_FILEOPS);
7293 ADD_INT(d, DB_VERB_FILEOPS_ALL);
7294#endif
7295 ADD_INT(d, DB_VERB_RECOVERY);
7296#if (DBVER >= 44)
7297 ADD_INT(d, DB_VERB_REGISTER);
7298#endif
7299 ADD_INT(d, DB_VERB_REPLICATION);
7300 ADD_INT(d, DB_VERB_WAITSFOR);
7301
7302#if (DBVER >= 45)
7303 ADD_INT(d, DB_EVENT_PANIC);
7304 ADD_INT(d, DB_EVENT_REP_CLIENT);
7305#if (DBVER >= 46)
7306 ADD_INT(d, DB_EVENT_REP_ELECTED);
7307#endif
7308 ADD_INT(d, DB_EVENT_REP_MASTER);
7309 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
7310#if (DBVER >= 46)
7311 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
7312#endif
7313 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
7314 ADD_INT(d, DB_EVENT_WRITE_FAILED);
7315#endif
7316
7317 ADD_INT(d, DB_REP_DUPMASTER);
7318 ADD_INT(d, DB_REP_HOLDELECTION);
7319#if (DBVER >= 44)
7320 ADD_INT(d, DB_REP_IGNORE);
7321 ADD_INT(d, DB_REP_JOIN_FAILURE);
7322#endif
7323#if (DBVER >= 42)
7324 ADD_INT(d, DB_REP_ISPERM);
7325 ADD_INT(d, DB_REP_NOTPERM);
7326#endif
7327 ADD_INT(d, DB_REP_NEWSITE);
7328
7329 ADD_INT(d, DB_REP_MASTER);
7330 ADD_INT(d, DB_REP_CLIENT);
7331#if (DBVER >= 45)
7332 ADD_INT(d, DB_REP_ELECTION);
7333
7334 ADD_INT(d, DB_REP_ACK_TIMEOUT);
7335 ADD_INT(d, DB_REP_CONNECTION_RETRY);
7336 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
7337 ADD_INT(d, DB_REP_ELECTION_RETRY);
7338#endif
7339#if (DBVER >= 46)
7340 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
7341 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
7342#endif
7343
7344#if (DBVER >= 45)
7345 ADD_INT(d, DB_REPMGR_PEER);
7346 ADD_INT(d, DB_REPMGR_ACKS_ALL);
7347 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
7348 ADD_INT(d, DB_REPMGR_ACKS_NONE);
7349 ADD_INT(d, DB_REPMGR_ACKS_ONE);
7350 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
7351 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
7352 ADD_INT(d, DB_REPMGR_CONNECTED);
7353 ADD_INT(d, DB_REPMGR_DISCONNECTED);
7354 ADD_INT(d, DB_STAT_CLEAR);
7355 ADD_INT(d, DB_STAT_ALL);
7356#endif
7357
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007358#if (DBVER >= 43)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007359 ADD_INT(d, DB_BUFFER_SMALL);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00007360 ADD_INT(d, DB_SEQ_DEC);
7361 ADD_INT(d, DB_SEQ_INC);
7362 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007363#endif
7364
Jesus Cea6ba33292008-08-31 14:12:11 +00007365#if (DBVER >= 43) && (DBVER < 47)
7366 ADD_INT(d, DB_LOG_INMEMORY);
7367 ADD_INT(d, DB_DSYNC_LOG);
7368#endif
7369
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007370#if (DBVER >= 41)
7371 ADD_INT(d, DB_ENCRYPT_AES);
7372 ADD_INT(d, DB_AUTO_COMMIT);
7373#else
Jesus Cea6ba33292008-08-31 14:12:11 +00007374 /* allow Berkeley DB 4.1 aware apps to run on older versions */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007375 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
7376#endif
7377
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007378 ADD_INT(d, EINVAL);
7379 ADD_INT(d, EACCES);
7380 ADD_INT(d, ENOSPC);
7381 ADD_INT(d, ENOMEM);
7382 ADD_INT(d, EAGAIN);
7383 ADD_INT(d, EBUSY);
7384 ADD_INT(d, EEXIST);
7385 ADD_INT(d, ENOENT);
7386 ADD_INT(d, EPERM);
7387
Barry Warsaw1baa9822003-03-31 19:51:29 +00007388 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
7389 ADD_INT(d, DB_SET_TXN_TIMEOUT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007390
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00007391 /* The exception name must be correct for pickled exception *
7392 * objects to unpickle properly. */
7393#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
7394#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
7395#else
7396#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
7397#endif
7398
7399 /* All the rest of the exceptions derive only from DBError */
7400#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
7401 PyDict_SetItemString(d, #name, name)
7402
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007403 /* The base exception class is DBError */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00007404 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
7405 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007406
Jesus Cea6ba33292008-08-31 14:12:11 +00007407#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithe9477062005-06-04 06:46:59 +00007408 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
7409 * from both DBError and KeyError, since the API only supports
7410 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007411 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00007412 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
7413 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007414 Py_file_input, d, d);
7415 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00007416 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007417 PyDict_DelItemString(d, "KeyError");
Jesus Cea6ba33292008-08-31 14:12:11 +00007418#else
7419 /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
7420 ** derive from several classes. We use this new API only for Python 3.0,
7421 ** though.
7422 */
7423 {
7424 PyObject* bases;
7425
7426 bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
7427
7428#define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
7429 PyDict_SetItemString(d, #name, name)
7430 MAKE_EX2(DBNotFoundError);
7431 MAKE_EX2(DBKeyEmptyError);
7432
7433#undef MAKE_EX2
7434
7435 Py_XDECREF(bases);
7436 }
7437#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007438
7439
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007440#if !INCOMPLETE_IS_WARNING
7441 MAKE_EX(DBIncompleteError);
7442#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00007443 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007444 MAKE_EX(DBKeyEmptyError);
7445 MAKE_EX(DBKeyExistError);
7446 MAKE_EX(DBLockDeadlockError);
7447 MAKE_EX(DBLockNotGrantedError);
7448 MAKE_EX(DBOldVersionError);
7449 MAKE_EX(DBRunRecoveryError);
7450 MAKE_EX(DBVerifyBadError);
7451 MAKE_EX(DBNoServerError);
7452 MAKE_EX(DBNoServerHomeError);
7453 MAKE_EX(DBNoServerIDError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007454 MAKE_EX(DBPageNotFoundError);
7455 MAKE_EX(DBSecondaryBadError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007456
7457 MAKE_EX(DBInvalidArgError);
7458 MAKE_EX(DBAccessError);
7459 MAKE_EX(DBNoSpaceError);
7460 MAKE_EX(DBNoMemoryError);
7461 MAKE_EX(DBAgainError);
7462 MAKE_EX(DBBusyError);
7463 MAKE_EX(DBFileExistsError);
7464 MAKE_EX(DBNoSuchFileError);
7465 MAKE_EX(DBPermissionsError);
7466
Jesus Cea6ba33292008-08-31 14:12:11 +00007467#if (DBVER >= 42)
7468 MAKE_EX(DBRepHandleDeadError);
7469#endif
7470
7471 MAKE_EX(DBRepUnavailError);
7472
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007473#undef MAKE_EX
7474
Guido van Rossum8ce8a782007-11-01 19:42:39 +00007475 /* Initiliase the C API structure and add it to the module */
7476 bsddb_api.db_type = &DB_Type;
7477 bsddb_api.dbcursor_type = &DBCursor_Type;
7478 bsddb_api.dbenv_type = &DBEnv_Type;
7479 bsddb_api.dbtxn_type = &DBTxn_Type;
7480 bsddb_api.dblock_type = &DBLock_Type;
7481#if (DBVER >= 43)
7482 bsddb_api.dbsequence_type = &DBSequence_Type;
7483#endif
7484 bsddb_api.makeDBError = makeDBError;
7485
7486 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7487 PyDict_SetItemString(d, "api", py_api);
7488 Py_DECREF(py_api);
7489
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007490 /* Check for errors */
7491 if (PyErr_Occurred()) {
7492 PyErr_Print();
Jesus Cea6ba33292008-08-31 14:12:11 +00007493 Py_FatalError("can't initialize module _bsddb/_pybsddb");
7494 Py_DECREF(m);
7495 m = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007496 }
Jesus Cea6ba33292008-08-31 14:12:11 +00007497#if (PY_VERSION_HEX < 0x03000000)
7498 return;
7499#else
Martin v. Löwis1a214512008-06-11 05:26:20 +00007500 return m;
Jesus Cea6ba33292008-08-31 14:12:11 +00007501#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007502}
Gregory P. Smith41631e82003-09-21 00:08:14 +00007503
7504/* allow this module to be named _pybsddb so that it can be installed
7505 * and imported on top of python >= 2.3 that includes its own older
7506 * copy of the library named _bsddb without importing the old version. */
Jesus Cea6ba33292008-08-31 14:12:11 +00007507#if (PY_VERSION_HEX < 0x03000000)
7508DL_EXPORT(void) init_pybsddb(void)
7509#else
7510PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */
7511#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00007512{
7513 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
Jesus Cea6ba33292008-08-31 14:12:11 +00007514#if (PY_VERSION_HEX < 0x03000000)
7515 init_bsddb();
7516#else
7517 return PyInit__bsddb(); /* Note the two underscores */
7518#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00007519}
Jesus Cea6ba33292008-08-31 14:12:11 +00007520