blob: 104962fa892e99e138f444be672273391741cec1 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Jesus Ceaef9764f2008-05-13 18:45:46 +000039 * to compile with Berkeley DB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
Gregory P. Smithf8057852007-09-09 20:25:00 +000042 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * Berkeley DB 2.7.x.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000045 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
Jesus Ceaef9764f2008-05-13 18:45:46 +000051 * Gregory P. Smith <greg@krypto.org> was once again the maintainer.
52 *
Jesus Ceaca3939c2008-05-22 15:27:38 +000053 * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>.
Jesus Ceaef9764f2008-05-13 18:45:46 +000054 * Jesus Cea licenses this code to PSF under a Contributor Agreement.
Barry Warsaw9a0d7792002-12-30 20:53:52 +000055 *
56 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000057 * Things can change faster than the header of this file is updated. This
58 * file is shared with the PyBSDDB project at SourceForge:
59 *
60 * http://pybsddb.sf.net
61 *
62 * This file should remain backward compatible with Python 2.1, but see PEP
63 * 291 for the most current backward compatibility requirements:
64 *
65 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000066 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000067 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000068 *
69 * DB (Database)
70 * DBCursor (Database Cursor)
71 * DBEnv (database environment)
72 * DBTxn (An explicit database transaction)
73 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000074 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000075 *
76 */
77
78/* --------------------------------------------------------------------- */
79
80/*
81 * Portions of this module, associated unit tests and build scripts are the
82 * result of a contract with The Written Word (http://thewrittenword.com/)
83 * Many thanks go out to them for causing me to raise the bar on quality and
84 * functionality, resulting in a better bsddb3 package for all of us to use.
85 *
86 * --Robin
87 */
88
89/* --------------------------------------------------------------------- */
90
Gregory P. Smitha703a212003-11-03 01:04:41 +000091#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000092#include <Python.h>
Gregory P. Smith39250532007-10-09 06:02:21 +000093
94#define COMPILING_BSDDB_C
95#include "bsddb.h"
96#undef COMPILING_BSDDB_C
97
98static char *rcs_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000099
100/* --------------------------------------------------------------------- */
101/* Various macro definitions */
102
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000103#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000104typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#endif
106
Gregory P. Smith572226c2008-05-26 19:03:35 +0000107#if (PY_VERSION_HEX < 0x02060000) /* really: before python trunk r63675 */
108/* This code now uses PyBytes* API function names instead of PyString*.
109 * These #defines map to their equivalent on earlier python versions. */
110#define PyBytes_FromStringAndSize PyString_FromStringAndSize
111#define PyBytes_FromString PyString_FromString
112#define PyBytes_AsStringAndSize PyString_AsStringAndSize
113#define PyBytes_Check PyString_Check
114#define PyBytes_GET_SIZE PyString_GET_SIZE
115#define PyBytes_AS_STRING PyString_AS_STRING
116#endif
117
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000118#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 Ceaef9764f2008-05-13 18:45:46 +0000208#if (DBVER >= 42)
209static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
210#endif
211
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000212static 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
Gregory P. Smith39250532007-10-09 06:02:21 +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
Gregory P. Smith39250532007-10-09 06:02:21 +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 Ceac5a11fa2008-07-23 11:38:42 +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;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000242#if (DBVER >= 43)
243staticforward PyTypeObject DBSequence_Type;
244#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000245
Martin v. Löwis83c92012008-04-24 13:17:24 +0000246#ifndef Py_TYPE
Gregory P. Smithfc006692007-11-05 09:06:28 +0000247/* for compatibility with Python 2.5 and earlier */
Christian Heimese93237d2007-12-19 02:37:44 +0000248#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
Gregory P. Smithfc006692007-11-05 09:06:28 +0000249#endif
250
Christian Heimese93237d2007-12-19 02:37:44 +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)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000256#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +0000257#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000258#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000259
Jesus Ceaef9764f2008-05-13 18:45:46 +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 Ceaef9764f2008-05-13 18:45:46 +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 Ceac5a11fa2008-07-23 11:38:42 +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
Gregory P. Smithf0547d02006-06-05 17:38:04 +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
368#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000369 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000370
371
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 Ceac5a11fa2008-07-23 11:38:42 +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;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386}
387
388
389/* Create a DBT structure (containing key and data values) from Python
390 strings. Returns 1 on success, 0 on an error. */
391static int make_dbt(PyObject* obj, DBT* dbt)
392{
393 CLEAR_DBT(*dbt);
394 if (obj == Py_None) {
395 /* no need to do anything, the structure has already been zeroed */
396 }
397 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
398 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000399 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000400 return 0;
401 }
402 return 1;
403}
404
405
406/* Recno and Queue DBs can have integer keys. This function figures out
407 what's been given, verifies that it's allowed, and then makes the DBT.
408
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000409 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000410static int
411make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000412{
413 db_recno_t recno;
414 int type;
415
416 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000417 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000418 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000419 if (type == -1)
420 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000421 if (type == DB_RECNO || type == DB_QUEUE) {
422 PyErr_SetString(
423 PyExc_TypeError,
424 "None keys not allowed for Recno and Queue DB's");
425 return 0;
426 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000427 /* no need to do anything, the structure has already been zeroed */
428 }
429
Christian Heimes593daf52008-05-26 12:51:38 +0000430 else if (PyBytes_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000431 /* verify access method type */
432 type = _DB_get_type(self);
433 if (type == -1)
434 return 0;
435 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000436 PyErr_SetString(
437 PyExc_TypeError,
438 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000439 return 0;
440 }
441
Gregory P. Smith10bed542007-10-09 06:50:43 +0000442 /*
443 * NOTE(gps): I don't like doing a data copy here, it seems
444 * wasteful. But without a clean way to tell FREE_DBT if it
445 * should free key->data or not we have to. Other places in
446 * the code check for DB_THREAD and forceably set DBT_MALLOC
447 * when we otherwise would leave flags 0 to indicate that.
448 */
Christian Heimes593daf52008-05-26 12:51:38 +0000449 key->data = malloc(PyBytes_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000450 if (key->data == NULL) {
451 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
452 return 0;
453 }
Christian Heimes593daf52008-05-26 12:51:38 +0000454 memcpy(key->data, PyBytes_AS_STRING(keyobj),
455 PyBytes_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000456 key->flags = DB_DBT_REALLOC;
Christian Heimes593daf52008-05-26 12:51:38 +0000457 key->size = PyBytes_GET_SIZE(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000458 }
459
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000460 else if (NUMBER_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000461 /* verify access method type */
462 type = _DB_get_type(self);
463 if (type == -1)
464 return 0;
465 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000466 /* if BTREE then an Integer key is allowed with the
467 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000468 *pflags |= DB_SET_RECNO;
469 }
470 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000471 PyErr_SetString(
472 PyExc_TypeError,
473 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000474 return 0;
475 }
476
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000477 /* Make a key out of the requested recno, use allocated space so DB
478 * will be able to realloc room for the real key if needed. */
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000479 recno = NUMBER_AsLong(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000480 key->data = malloc(sizeof(db_recno_t));
481 if (key->data == NULL) {
482 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
483 return 0;
484 }
485 key->ulen = key->size = sizeof(db_recno_t);
486 memcpy(key->data, &recno, sizeof(db_recno_t));
487 key->flags = DB_DBT_REALLOC;
488 }
489 else {
490 PyErr_Format(PyExc_TypeError,
491 "String or Integer object expected for key, %s found",
Christian Heimese93237d2007-12-19 02:37:44 +0000492 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000493 return 0;
494 }
495
496 return 1;
497}
498
499
500/* Add partial record access to an existing DBT data struct.
501 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
502 and the data storage/retrieval will be done using dlen and doff. */
503static int add_partial_dbt(DBT* d, int dlen, int doff) {
504 /* if neither were set we do nothing (-1 is the default value) */
505 if ((dlen == -1) && (doff == -1)) {
506 return 1;
507 }
508
509 if ((dlen < 0) || (doff < 0)) {
510 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
511 return 0;
512 }
513
514 d->flags = d->flags | DB_DBT_PARTIAL;
515 d->dlen = (unsigned int) dlen;
516 d->doff = (unsigned int) doff;
517 return 1;
518}
519
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000520/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
521/* TODO: make this use the native libc strlcpy() when available (BSD) */
522unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
523{
524 unsigned int srclen, copylen;
525
526 srclen = strlen(src);
527 if (n <= 0)
528 return srclen;
529 copylen = (srclen > n-1) ? n-1 : srclen;
530 /* populate dest[0] thru dest[copylen-1] */
531 memcpy(dest, src, copylen);
532 /* guarantee null termination */
533 dest[copylen] = 0;
534
535 return srclen;
536}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000537
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000538/* Callback used to save away more information about errors from the DB
539 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000540static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000541#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000542static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000543#else
544static void _db_errorCallback(const DB_ENV *db_env,
545 const char* prefix, const char* msg)
546#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000547{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000548 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549}
550
551
Jesus Ceaef9764f2008-05-13 18:45:46 +0000552/*
553** We need these functions because some results
554** are undefined if pointer is NULL. Some other
555** give None instead of "".
556**
557** This functions are static and will be
558** -I hope- inlined.
559*/
560static const char *DummyString = "This string is a simple placeholder";
561static PyObject *Build_PyString(const char *p,int s)
562{
563 if (!p) {
564 p=DummyString;
565 assert(s==0);
566 }
Christian Heimes593daf52008-05-26 12:51:38 +0000567 return PyBytes_FromStringAndSize(p,s);
Jesus Ceaef9764f2008-05-13 18:45:46 +0000568}
569
570static PyObject *BuildValue_S(const void *p,int s)
571{
572 if (!p) {
573 p=DummyString;
574 assert(s==0);
575 }
576 return Py_BuildValue("s#",p,s);
577}
578
579static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
580{
581 if (!p1) {
582 p1=DummyString;
583 assert(s1==0);
584 }
585 if (!p2) {
586 p2=DummyString;
587 assert(s2==0);
588 }
589 return Py_BuildValue("s#s#",p1,s1,p2,s2);
590}
591
592static PyObject *BuildValue_IS(int i,const void *p,int s)
593{
594 if (!p) {
595 p=DummyString;
596 assert(s==0);
597 }
598 return Py_BuildValue("is#",i,p,s);
599}
600
601static PyObject *BuildValue_LS(long i,const void *p,int s)
602{
603 if (!p) {
604 p=DummyString;
605 assert(s==0);
606 }
607 return Py_BuildValue("ls#",i,p,s);
608}
609
610
611
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000612/* make a nice exception object to raise for errors. */
613static int makeDBError(int err)
614{
615 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000616 PyObject *errObj = NULL;
617 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000618 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000619 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000620
621 switch (err) {
622 case 0: /* successful, no error */ break;
623
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000624#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000625 case DB_INCOMPLETE:
626#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000627 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
628 /* Ensure that bytes_left never goes negative */
629 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
630 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
631 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000632 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000633 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000634 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000635 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000636 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000637
638#else /* do an exception instead */
639 errObj = DBIncompleteError;
640#endif
641 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000642#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000643
644 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
645 case DB_KEYEXIST: errObj = DBKeyExistError; break;
646 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
647 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
648 case DB_NOTFOUND: errObj = DBNotFoundError; break;
649 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
650 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
651 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
652 case DB_NOSERVER: errObj = DBNoServerError; break;
653 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
654 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000655 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
656 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000657 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000658
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000659#if (DBVER >= 43)
660 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
661 case ENOMEM: errObj = PyExc_MemoryError; break;
662#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000663 case EINVAL: errObj = DBInvalidArgError; break;
664 case EACCES: errObj = DBAccessError; break;
665 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000666 case EAGAIN: errObj = DBAgainError; break;
667 case EBUSY : errObj = DBBusyError; break;
668 case EEXIST: errObj = DBFileExistsError; break;
669 case ENOENT: errObj = DBNoSuchFileError; break;
670 case EPERM : errObj = DBPermissionsError; break;
671
Jesus Ceaef9764f2008-05-13 18:45:46 +0000672#if (DBVER >= 42)
673 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
674#endif
675
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000676 case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
677
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000678 default: errObj = DBError; break;
679 }
680
681 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000682 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
683 /* Ensure that bytes_left never goes negative */
684 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
685 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
686 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000687 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000688 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000689 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000690 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000691
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000692 errTuple = Py_BuildValue("(is)", err, errTxt);
693 if (errTuple == NULL) {
694 Py_DECREF(errObj);
695 return !0;
696 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000697 PyErr_SetObject(errObj, errTuple);
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000698 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000699 }
700
701 return ((errObj != NULL) || exceptionRaised);
702}
703
704
705
706/* set a type exception */
707static void makeTypeError(char* expected, PyObject* found)
708{
709 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimese93237d2007-12-19 02:37:44 +0000710 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000711}
712
713
714/* verify that an obj is either None or a DBTxn, and set the txn pointer */
715static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
716{
717 if (txnobj == Py_None || txnobj == NULL) {
718 *txn = NULL;
719 return 1;
720 }
721 if (DBTxnObject_Check(txnobj)) {
722 *txn = ((DBTxnObject*)txnobj)->txn;
723 return 1;
724 }
725 else
726 makeTypeError("DBTxn", txnobj);
727 return 0;
728}
729
730
731/* Delete a key from a database
732 Returns 0 on success, -1 on an error. */
733static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
734{
735 int err;
736
737 MYDB_BEGIN_ALLOW_THREADS;
738 err = self->db->del(self->db, txn, key, 0);
739 MYDB_END_ALLOW_THREADS;
740 if (makeDBError(err)) {
741 return -1;
742 }
743 self->haveStat = 0;
744 return 0;
745}
746
747
748/* Store a key into a database
749 Returns 0 on success, -1 on an error. */
750static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
751{
752 int err;
753
754 MYDB_BEGIN_ALLOW_THREADS;
755 err = self->db->put(self->db, txn, key, data, flags);
756 MYDB_END_ALLOW_THREADS;
757 if (makeDBError(err)) {
758 return -1;
759 }
760 self->haveStat = 0;
761 return 0;
762}
763
764/* Get a key/data pair from a cursor */
765static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
766 PyObject *args, PyObject *kwargs, char *format)
767{
768 int err;
769 PyObject* retval = NULL;
770 DBT key, data;
771 int dlen = -1;
772 int doff = -1;
773 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000774 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000775
776 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
777 &flags, &dlen, &doff))
778 return NULL;
779
780 CHECK_CURSOR_NOT_CLOSED(self);
781
782 flags |= extra_flags;
783 CLEAR_DBT(key);
784 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000785 if (!add_partial_dbt(&data, dlen, doff))
786 return NULL;
787
788 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000789 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000790 MYDB_END_ALLOW_THREADS;
791
Gregory P. Smithe9477062005-06-04 06:46:59 +0000792 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
793 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000794 Py_INCREF(Py_None);
795 retval = Py_None;
796 }
797 else if (makeDBError(err)) {
798 retval = NULL;
799 }
800 else { /* otherwise, success! */
801
802 /* if Recno or Queue, return the key as an Int */
803 switch (_DB_get_type(self->mydb)) {
804 case -1:
805 retval = NULL;
806 break;
807
808 case DB_RECNO:
809 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000810 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000811 break;
812 case DB_HASH:
813 case DB_BTREE:
814 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000815 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000816 break;
817 }
818 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000819 return retval;
820}
821
822
823/* add an integer to a dictionary using the given name as a key */
824static void _addIntToDict(PyObject* dict, char *name, int value)
825{
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000826 PyObject* v = NUMBER_FromLong((long) value);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000827 if (!v || PyDict_SetItemString(dict, name, v))
828 PyErr_Clear();
829
830 Py_XDECREF(v);
831}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000832
833/* The same, when the value is a time_t */
834static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
835{
836 PyObject* v;
837 /* if the value fits in regular int, use that. */
Jesus Ceaef9764f2008-05-13 18:45:46 +0000838#ifdef PY_LONG_LONG
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000839 if (sizeof(time_t) > sizeof(long))
840 v = PyLong_FromLongLong((PY_LONG_LONG) value);
841 else
842#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000843 v = NUMBER_FromLong((long) value);
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000844 if (!v || PyDict_SetItemString(dict, name, v))
845 PyErr_Clear();
846
847 Py_XDECREF(v);
848}
849
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000850#if (DBVER >= 43)
851/* add an db_seq_t to a dictionary using the given name as a key */
852static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
853{
854 PyObject* v = PyLong_FromLongLong(value);
855 if (!v || PyDict_SetItemString(dict, name, v))
856 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000857
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000858 Py_XDECREF(v);
859}
860#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000861
Jesus Ceaef9764f2008-05-13 18:45:46 +0000862static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
863{
864 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
865 if (!v || PyDict_SetItemString(dict, name, v))
866 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000867
Jesus Ceaef9764f2008-05-13 18:45:46 +0000868 Py_XDECREF(v);
869}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000870
871/* --------------------------------------------------------------------- */
872/* Allocators and deallocators */
873
874static DBObject*
875newDBObject(DBEnvObject* arg, int flags)
876{
877 DBObject* self;
878 DB_ENV* db_env = NULL;
879 int err;
880
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000881 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000882 if (self == NULL)
883 return NULL;
884
885 self->haveStat = 0;
886 self->flags = 0;
887 self->setflags = 0;
888 self->myenvobj = NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000889 self->db = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000890 self->children_cursors = NULL;
891#if (DBVER >=43)
892 self->children_sequences = NULL;
893#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000894 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000895 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000896 self->primaryDBType = 0;
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000897 Py_INCREF(Py_None);
898 self->private = Py_None;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000899 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000900
901 /* keep a reference to our python DBEnv object */
902 if (arg) {
903 Py_INCREF(arg);
904 self->myenvobj = arg;
905 db_env = arg->db_env;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000906 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
907 } else {
908 self->sibling_prev_p=NULL;
909 self->sibling_next=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000910 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000911 self->txn=NULL;
912 self->sibling_prev_p_txn=NULL;
913 self->sibling_next_txn=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000914
915 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000916 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000917 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000918 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
919 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000920
921 MYDB_BEGIN_ALLOW_THREADS;
922 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000923 if (self->db != NULL) {
924 self->db->set_errcall(self->db, _db_errorCallback);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000925 self->db->app_private = (void*)self;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000926 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000927 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000928 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
929 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000930 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000931 if (makeDBError(err)) {
932 if (self->myenvobj) {
933 Py_DECREF(self->myenvobj);
934 self->myenvobj = NULL;
935 }
Gregory P. Smith664782e2008-05-17 06:12:02 +0000936 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000937 self = NULL;
938 }
939 return self;
940}
941
942
Jesus Ceaef9764f2008-05-13 18:45:46 +0000943/* Forward declaration */
944static PyObject *DB_close_internal(DBObject* self, int flags);
945
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000946static void
947DB_dealloc(DBObject* self)
948{
Jesus Ceaef9764f2008-05-13 18:45:46 +0000949 PyObject *dummy;
950
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000951 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +0000952 dummy=DB_close_internal(self,0);
953 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000954 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000955 if (self->in_weakreflist != NULL) {
956 PyObject_ClearWeakRefs((PyObject *) self);
957 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000958 if (self->myenvobj) {
959 Py_DECREF(self->myenvobj);
960 self->myenvobj = NULL;
961 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000962 if (self->associateCallback != NULL) {
963 Py_DECREF(self->associateCallback);
964 self->associateCallback = NULL;
965 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000966 if (self->btCompareCallback != NULL) {
967 Py_DECREF(self->btCompareCallback);
968 self->btCompareCallback = NULL;
969 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000970 Py_DECREF(self->private);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000971 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000972}
973
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000974static DBCursorObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +0000975newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000976{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000977 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000978 if (self == NULL)
979 return NULL;
980
981 self->dbc = dbc;
982 self->mydb = db;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000983
984 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
985 if (txn && ((PyObject *)txn!=Py_None)) {
986 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
987 self->txn=txn;
988 } else {
989 self->txn=NULL;
990 }
991
Gregory P. Smitha703a212003-11-03 01:04:41 +0000992 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000993 Py_INCREF(self->mydb);
994 return self;
995}
996
997
Jesus Ceaef9764f2008-05-13 18:45:46 +0000998/* Forward declaration */
999static PyObject *DBC_close_internal(DBCursorObject* self);
1000
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001001static void
1002DBCursor_dealloc(DBCursorObject* self)
1003{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001004 PyObject *dummy;
Gregory P. Smitha703a212003-11-03 01:04:41 +00001005
Jesus Ceaef9764f2008-05-13 18:45:46 +00001006 if (self->dbc != NULL) {
1007 dummy=DBC_close_internal(self);
1008 Py_XDECREF(dummy);
1009 }
Gregory P. Smitha703a212003-11-03 01:04:41 +00001010 if (self->in_weakreflist != NULL) {
1011 PyObject_ClearWeakRefs((PyObject *) self);
1012 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001013 Py_DECREF(self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001014 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001015}
1016
1017
1018static DBEnvObject*
1019newDBEnvObject(int flags)
1020{
1021 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001022 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001023 if (self == NULL)
1024 return NULL;
1025
1026 self->closed = 1;
1027 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001028 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1029 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001030 self->children_dbs = NULL;
1031 self->children_txns = NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001032 Py_INCREF(Py_None);
1033 self->private = Py_None;
1034 Py_INCREF(Py_None);
1035 self->rep_transport = Py_None;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001036 self->in_weakreflist = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001037 self->event_notifyCallback = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001038
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001039 MYDB_BEGIN_ALLOW_THREADS;
1040 err = db_env_create(&self->db_env, flags);
1041 MYDB_END_ALLOW_THREADS;
1042 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001043 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001044 self = NULL;
1045 }
1046 else {
1047 self->db_env->set_errcall(self->db_env, _db_errorCallback);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001048 self->db_env->app_private=self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001049 }
1050 return self;
1051}
1052
Jesus Ceaef9764f2008-05-13 18:45:46 +00001053/* Forward declaration */
1054static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001055
1056static void
1057DBEnv_dealloc(DBEnvObject* self)
1058{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001059 PyObject *dummy;
1060
1061 if (self->db_env && !self->closed) {
1062 dummy=DBEnv_close_internal(self,0);
1063 Py_XDECREF(dummy);
1064 }
1065
Jesus Ceaef9764f2008-05-13 18:45:46 +00001066 Py_XDECREF(self->event_notifyCallback);
1067 self->event_notifyCallback = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001068
Gregory P. Smith31c50652004-06-28 01:20:40 +00001069 if (self->in_weakreflist != NULL) {
1070 PyObject_ClearWeakRefs((PyObject *) self);
1071 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001072 Py_DECREF(self->private);
1073 Py_DECREF(self->rep_transport);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001074 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001075}
1076
1077
1078static DBTxnObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001079newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001080{
1081 int err;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001082 DB_TXN *parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001083
Neal Norwitzb4a55812004-07-09 23:30:57 +00001084 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001085 if (self == NULL)
1086 return NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001087
Gregory P. Smith31c50652004-06-28 01:20:40 +00001088 self->in_weakreflist = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001089 self->children_txns = NULL;
1090 self->children_dbs = NULL;
1091 self->children_cursors = NULL;
1092 self->children_sequences = NULL;
1093 self->flag_prepare = 0;
1094 self->parent_txn = NULL;
1095 self->env = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001096
Jesus Ceaef9764f2008-05-13 18:45:46 +00001097 if (parent && ((PyObject *)parent!=Py_None)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001098 parent_txn = parent->txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001099 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001100
1101 if (txn) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001102 self->txn = txn;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001103 } else {
1104 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001105 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001106 MYDB_END_ALLOW_THREADS;
1107
1108 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001109 Py_DECREF(self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001110 return NULL;
1111 }
1112 }
1113
Gregory P. Smith664782e2008-05-17 06:12:02 +00001114 /* Can't use 'parent' because could be 'parent==Py_None' */
1115 if (parent_txn) {
1116 self->parent_txn = parent;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001117 Py_INCREF(parent);
1118 self->env = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001119 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001120 } else {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001121 self->parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001122 Py_INCREF(myenv);
1123 self->env = myenv;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001124 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001125 }
1126
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001127 return self;
1128}
1129
Jesus Ceaef9764f2008-05-13 18:45:46 +00001130/* Forward declaration */
1131static PyObject *
1132DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001133
1134static void
1135DBTxn_dealloc(DBTxnObject* self)
1136{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001137 PyObject *dummy;
1138
1139 if (self->txn) {
1140 int flag_prepare = self->flag_prepare;
1141 dummy=DBTxn_abort_discard_internal(self,0);
1142 Py_XDECREF(dummy);
1143 if (!flag_prepare) {
1144 PyErr_Warn(PyExc_RuntimeWarning,
1145 "DBTxn aborted in destructor. No prior commit() or abort().");
1146 }
1147 }
1148
Gregory P. Smith31c50652004-06-28 01:20:40 +00001149 if (self->in_weakreflist != NULL) {
1150 PyObject_ClearWeakRefs((PyObject *) self);
1151 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001152
Jesus Ceaef9764f2008-05-13 18:45:46 +00001153 if (self->env) {
1154 Py_DECREF(self->env);
1155 } else {
1156 Py_DECREF(self->parent_txn);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001157 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001158 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001159}
1160
1161
1162static DBLockObject*
1163newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1164 db_lockmode_t lock_mode, int flags)
1165{
1166 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001167 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001168 if (self == NULL)
1169 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001170 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001171
1172 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001173 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1174 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001175 MYDB_END_ALLOW_THREADS;
1176 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001177 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001178 self = NULL;
1179 }
1180
1181 return self;
1182}
1183
1184
1185static void
1186DBLock_dealloc(DBLockObject* self)
1187{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001188 if (self->in_weakreflist != NULL) {
1189 PyObject_ClearWeakRefs((PyObject *) self);
1190 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001191 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001192
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001193 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001194}
1195
1196
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001197#if (DBVER >= 43)
1198static DBSequenceObject*
1199newDBSequenceObject(DBObject* mydb, int flags)
1200{
1201 int err;
1202 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1203 if (self == NULL)
1204 return NULL;
1205 Py_INCREF(mydb);
1206 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001207
Jesus Ceaef9764f2008-05-13 18:45:46 +00001208 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
Gregory P. Smith664782e2008-05-17 06:12:02 +00001209 self->txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001210
1211 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001212
1213 MYDB_BEGIN_ALLOW_THREADS;
1214 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1215 MYDB_END_ALLOW_THREADS;
1216 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001217 Py_DECREF(self);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001218 self = NULL;
1219 }
1220
1221 return self;
1222}
1223
Jesus Ceaef9764f2008-05-13 18:45:46 +00001224/* Forward declaration */
1225static PyObject
1226*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001227
1228static void
1229DBSequence_dealloc(DBSequenceObject* self)
1230{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001231 PyObject *dummy;
1232
1233 if (self->sequence != NULL) {
1234 dummy=DBSequence_close_internal(self,0,0);
1235 Py_XDECREF(dummy);
1236 }
1237
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001238 if (self->in_weakreflist != NULL) {
1239 PyObject_ClearWeakRefs((PyObject *) self);
1240 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001241
1242 Py_DECREF(self->mydb);
1243 PyObject_Del(self);
1244}
1245#endif
1246
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001247/* --------------------------------------------------------------------- */
1248/* DB methods */
1249
1250static PyObject*
1251DB_append(DBObject* self, PyObject* args)
1252{
1253 PyObject* txnobj = NULL;
1254 PyObject* dataobj;
1255 db_recno_t recno;
1256 DBT key, data;
1257 DB_TXN *txn = NULL;
1258
Georg Brandl96a8c392006-05-29 21:04:52 +00001259 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001260 return NULL;
1261
1262 CHECK_DB_NOT_CLOSED(self);
1263
1264 /* make a dummy key out of a recno */
1265 recno = 0;
1266 CLEAR_DBT(key);
1267 key.data = &recno;
1268 key.size = sizeof(recno);
1269 key.ulen = key.size;
1270 key.flags = DB_DBT_USERMEM;
1271
1272 if (!make_dbt(dataobj, &data)) return NULL;
1273 if (!checkTxnObj(txnobj, &txn)) return NULL;
1274
1275 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1276 return NULL;
1277
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001278 return NUMBER_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001279}
1280
1281
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001282static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001283_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1284 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001285{
1286 int retval = DB_DONOTINDEX;
1287 DBObject* secondaryDB = (DBObject*)db->app_private;
1288 PyObject* callback = secondaryDB->associateCallback;
1289 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001290 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001291 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001292
1293
1294 if (callback != NULL) {
1295 MYDB_BEGIN_BLOCK_THREADS;
1296
Thomas Woutersb3153832006-03-08 01:47:19 +00001297 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceaef9764f2008-05-13 18:45:46 +00001298 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
Thomas Woutersb3153832006-03-08 01:47:19 +00001299 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001300 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001301 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001302 result = PyEval_CallObject(callback, args);
1303 }
1304 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001305 PyErr_Print();
1306 }
1307 else if (result == Py_None) {
1308 retval = DB_DONOTINDEX;
1309 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001310 else if (NUMBER_Check(result)) {
1311 retval = NUMBER_AsLong(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001312 }
Christian Heimes593daf52008-05-26 12:51:38 +00001313 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001314 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001315 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001316
1317 CLEAR_DBT(*secKey);
Christian Heimes593daf52008-05-26 12:51:38 +00001318 PyBytes_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001319 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1320 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001321 if (secKey->data) {
1322 memcpy(secKey->data, data, size);
1323 secKey->size = size;
1324 retval = 0;
1325 }
1326 else {
1327 PyErr_SetString(PyExc_MemoryError,
1328 "malloc failed in _db_associateCallback");
1329 PyErr_Print();
1330 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001331 }
1332 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001333 PyErr_SetString(
1334 PyExc_TypeError,
1335 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001336 PyErr_Print();
1337 }
1338
Thomas Woutersb3153832006-03-08 01:47:19 +00001339 Py_XDECREF(args);
1340 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001341
1342 MYDB_END_BLOCK_THREADS;
1343 }
1344 return retval;
1345}
1346
1347
1348static PyObject*
1349DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1350{
1351 int err, flags=0;
1352 DBObject* secondaryDB;
1353 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001354#if (DBVER >= 41)
1355 PyObject *txnobj = NULL;
1356 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001357 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001358 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001359#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001360 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001361#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001362
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001363#if (DBVER >= 41)
1364 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1365 &secondaryDB, &callback, &flags,
1366 &txnobj)) {
1367#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001368 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001369 &secondaryDB, &callback, &flags)) {
1370#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001371 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001372 }
1373
1374#if (DBVER >= 41)
1375 if (!checkTxnObj(txnobj, &txn)) return NULL;
1376#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001377
1378 CHECK_DB_NOT_CLOSED(self);
1379 if (!DBObject_Check(secondaryDB)) {
1380 makeTypeError("DB", (PyObject*)secondaryDB);
1381 return NULL;
1382 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001383 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001384 if (callback == Py_None) {
1385 callback = NULL;
1386 }
1387 else if (!PyCallable_Check(callback)) {
1388 makeTypeError("Callable", callback);
1389 return NULL;
1390 }
1391
1392 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001393 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001394 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001395 secondaryDB->associateCallback = callback;
1396 secondaryDB->primaryDBType = _DB_get_type(self);
1397
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001398 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1399 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1400 * The global interepreter lock is not initialized until the first
1401 * thread is created using thread.start_new_thread() or fork() is
1402 * called. that would cause the ALLOW_THREADS here to segfault due
1403 * to a null pointer reference if no threads or child processes
1404 * have been created. This works around that and is a no-op if
1405 * threads have already been initialized.
1406 * (see pybsddb-users mailing list post on 2002-08-07)
1407 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001408#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001409 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001410#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001411 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001412#if (DBVER >= 41)
1413 err = self->db->associate(self->db,
1414 txn,
1415 secondaryDB->db,
1416 _db_associateCallback,
1417 flags);
1418#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001419 err = self->db->associate(self->db,
1420 secondaryDB->db,
1421 _db_associateCallback,
1422 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001423#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001424 MYDB_END_ALLOW_THREADS;
1425
1426 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001427 Py_XDECREF(secondaryDB->associateCallback);
1428 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001429 secondaryDB->primaryDBType = 0;
1430 }
1431
1432 RETURN_IF_ERR();
1433 RETURN_NONE();
1434}
1435
1436
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001437static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001438DB_close_internal(DBObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001439{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001440 PyObject *dummy;
1441 int err;
1442
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001443 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001444 /* Can be NULL if db is not in an environment */
1445 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
1446 if (self->txn) {
1447 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1448 self->txn=NULL;
1449 }
1450
1451 while(self->children_cursors) {
1452 dummy=DBC_close_internal(self->children_cursors);
1453 Py_XDECREF(dummy);
1454 }
1455
1456#if (DBVER >= 43)
1457 while(self->children_sequences) {
1458 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1459 Py_XDECREF(dummy);
1460 }
1461#endif
1462
1463 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001464 err = self->db->close(self->db, flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001465 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001466 self->db = NULL;
1467 RETURN_IF_ERR();
1468 }
1469 RETURN_NONE();
1470}
1471
Jesus Ceaef9764f2008-05-13 18:45:46 +00001472static PyObject*
1473DB_close(DBObject* self, PyObject* args)
1474{
1475 int flags=0;
1476 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1477 return NULL;
1478 return DB_close_internal(self,flags);
1479}
1480
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001481
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001482static PyObject*
1483_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1484{
1485 int err, flags=0, type;
1486 PyObject* txnobj = NULL;
1487 PyObject* retval = NULL;
1488 DBT key, data;
1489 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001490 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001491
1492 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1493 &txnobj, &flags))
1494 return NULL;
1495
1496 CHECK_DB_NOT_CLOSED(self);
1497 type = _DB_get_type(self);
1498 if (type == -1)
1499 return NULL;
1500 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001501 PyErr_SetString(PyExc_TypeError,
1502 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001503 return NULL;
1504 }
1505 if (!checkTxnObj(txnobj, &txn))
1506 return NULL;
1507
1508 CLEAR_DBT(key);
1509 CLEAR_DBT(data);
1510 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001511 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001512 data.flags = DB_DBT_MALLOC;
1513 key.flags = DB_DBT_MALLOC;
1514 }
1515
1516 MYDB_BEGIN_ALLOW_THREADS;
1517 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1518 MYDB_END_ALLOW_THREADS;
1519
Gregory P. Smithe9477062005-06-04 06:46:59 +00001520 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1521 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001522 err = 0;
1523 Py_INCREF(Py_None);
1524 retval = Py_None;
1525 }
1526 else if (!err) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001527 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001528 FREE_DBT(key);
1529 FREE_DBT(data);
1530 }
1531
1532 RETURN_IF_ERR();
1533 return retval;
1534}
1535
1536static PyObject*
1537DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1538{
1539 return _DB_consume(self, args, kwargs, DB_CONSUME);
1540}
1541
1542static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001543DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1544 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001545{
1546 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1547}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001548
1549
1550static PyObject*
1551DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1552{
1553 int err, flags=0;
1554 DBC* dbc;
1555 PyObject* txnobj = NULL;
1556 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001557 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001558
1559 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1560 &txnobj, &flags))
1561 return NULL;
1562 CHECK_DB_NOT_CLOSED(self);
1563 if (!checkTxnObj(txnobj, &txn))
1564 return NULL;
1565
1566 MYDB_BEGIN_ALLOW_THREADS;
1567 err = self->db->cursor(self->db, txn, &dbc, flags);
1568 MYDB_END_ALLOW_THREADS;
1569 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001570 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001571}
1572
1573
1574static PyObject*
1575DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1576{
1577 PyObject* txnobj = NULL;
1578 int flags = 0;
1579 PyObject* keyobj;
1580 DBT key;
1581 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001582 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001583
1584 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1585 &keyobj, &txnobj, &flags))
1586 return NULL;
1587 CHECK_DB_NOT_CLOSED(self);
1588 if (!make_key_dbt(self, keyobj, &key, NULL))
1589 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001590 if (!checkTxnObj(txnobj, &txn)) {
1591 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001592 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001593 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001594
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001595 if (-1 == _DB_delete(self, txn, &key, 0)) {
1596 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001597 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001598 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001599
1600 FREE_DBT(key);
1601 RETURN_NONE();
1602}
1603
1604
1605static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001606DB_fd(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001607{
1608 int err, the_fd;
1609
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001610 CHECK_DB_NOT_CLOSED(self);
1611
1612 MYDB_BEGIN_ALLOW_THREADS;
1613 err = self->db->fd(self->db, &the_fd);
1614 MYDB_END_ALLOW_THREADS;
1615 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001616 return NUMBER_FromLong(the_fd);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001617}
1618
1619
1620static PyObject*
1621DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1622{
1623 int err, flags=0;
1624 PyObject* txnobj = NULL;
1625 PyObject* keyobj;
1626 PyObject* dfltobj = NULL;
1627 PyObject* retval = NULL;
1628 int dlen = -1;
1629 int doff = -1;
1630 DBT key, data;
1631 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001632 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001633 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001634
1635 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001636 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1637 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001638 return NULL;
1639
1640 CHECK_DB_NOT_CLOSED(self);
1641 if (!make_key_dbt(self, keyobj, &key, &flags))
1642 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001643 if (!checkTxnObj(txnobj, &txn)) {
1644 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001645 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001646 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001647
1648 CLEAR_DBT(data);
1649 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001650 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001651 data.flags = DB_DBT_MALLOC;
1652 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001653 if (!add_partial_dbt(&data, dlen, doff)) {
1654 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001655 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001656 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657
1658 MYDB_BEGIN_ALLOW_THREADS;
1659 err = self->db->get(self->db, txn, &key, &data, flags);
1660 MYDB_END_ALLOW_THREADS;
1661
Gregory P. Smithe9477062005-06-04 06:46:59 +00001662 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001663 err = 0;
1664 Py_INCREF(dfltobj);
1665 retval = dfltobj;
1666 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001667 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1668 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001669 err = 0;
1670 Py_INCREF(Py_None);
1671 retval = Py_None;
1672 }
1673 else if (!err) {
1674 if (flags & DB_SET_RECNO) /* return both key and data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001675 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001676 else /* return just the data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001677 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001678 FREE_DBT(data);
1679 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001680 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001681
1682 RETURN_IF_ERR();
1683 return retval;
1684}
1685
Gregory P. Smith19699a92004-06-28 04:06:49 +00001686static PyObject*
1687DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1688{
1689 int err, flags=0;
1690 PyObject* txnobj = NULL;
1691 PyObject* keyobj;
1692 PyObject* dfltobj = NULL;
1693 PyObject* retval = NULL;
1694 int dlen = -1;
1695 int doff = -1;
1696 DBT key, pkey, data;
1697 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001698 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001699 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001700
1701 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1702 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1703 &doff))
1704 return NULL;
1705
1706 CHECK_DB_NOT_CLOSED(self);
1707 if (!make_key_dbt(self, keyobj, &key, &flags))
1708 return NULL;
1709 if (!checkTxnObj(txnobj, &txn)) {
1710 FREE_DBT(key);
1711 return NULL;
1712 }
1713
1714 CLEAR_DBT(data);
1715 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001716 /* Tell Berkeley DB to malloc the return value (thread safe) */
Gregory P. Smith19699a92004-06-28 04:06:49 +00001717 data.flags = DB_DBT_MALLOC;
1718 }
1719 if (!add_partial_dbt(&data, dlen, doff)) {
1720 FREE_DBT(key);
1721 return NULL;
1722 }
1723
1724 CLEAR_DBT(pkey);
1725 pkey.flags = DB_DBT_MALLOC;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001726
Gregory P. Smith19699a92004-06-28 04:06:49 +00001727 MYDB_BEGIN_ALLOW_THREADS;
1728 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1729 MYDB_END_ALLOW_THREADS;
1730
Gregory P. Smithe9477062005-06-04 06:46:59 +00001731 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001732 err = 0;
1733 Py_INCREF(dfltobj);
1734 retval = dfltobj;
1735 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001736 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1737 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001738 err = 0;
1739 Py_INCREF(Py_None);
1740 retval = Py_None;
1741 }
1742 else if (!err) {
1743 PyObject *pkeyObj;
1744 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001745 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001746
1747 if (self->primaryDBType == DB_RECNO ||
1748 self->primaryDBType == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001749 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001750 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001751 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001752
1753 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1754 {
1755 PyObject *keyObj;
1756 int type = _DB_get_type(self);
1757 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001758 keyObj = NUMBER_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001759 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001760 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001761#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001762 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001763#else
1764 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1765#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001766 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001767 }
1768 else /* return just the pkey and data */
1769 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001770#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001771 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001772#else
1773 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1774#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001775 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001776 Py_DECREF(dataObj);
1777 Py_DECREF(pkeyObj);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001778 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001779 FREE_DBT(data);
1780 }
1781 FREE_DBT(key);
1782
1783 RETURN_IF_ERR();
1784 return retval;
1785}
1786
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001787
1788/* Return size of entry */
1789static PyObject*
1790DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1791{
1792 int err, flags=0;
1793 PyObject* txnobj = NULL;
1794 PyObject* keyobj;
1795 PyObject* retval = NULL;
1796 DBT key, data;
1797 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001798 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001799
1800 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1801 &keyobj, &txnobj))
1802 return NULL;
1803 CHECK_DB_NOT_CLOSED(self);
1804 if (!make_key_dbt(self, keyobj, &key, &flags))
1805 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001806 if (!checkTxnObj(txnobj, &txn)) {
1807 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001808 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001809 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001810 CLEAR_DBT(data);
1811
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001812 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1813 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001814 data.flags = DB_DBT_USERMEM;
1815 data.ulen = 0;
1816 MYDB_BEGIN_ALLOW_THREADS;
1817 err = self->db->get(self->db, txn, &key, &data, flags);
1818 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001819 if (err == DB_BUFFER_SMALL) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001820 retval = NUMBER_FromLong((long)data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001821 err = 0;
1822 }
1823
1824 FREE_DBT(key);
1825 FREE_DBT(data);
1826 RETURN_IF_ERR();
1827 return retval;
1828}
1829
1830
1831static PyObject*
1832DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1833{
1834 int err, flags=0;
1835 PyObject* txnobj = NULL;
1836 PyObject* keyobj;
1837 PyObject* dataobj;
1838 PyObject* retval = NULL;
1839 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001840 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001841 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001842 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001843
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001844 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1845 &keyobj, &dataobj, &txnobj, &flags))
1846 return NULL;
1847
1848 CHECK_DB_NOT_CLOSED(self);
1849 if (!make_key_dbt(self, keyobj, &key, NULL))
1850 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001851 if ( !make_dbt(dataobj, &data) ||
1852 !checkTxnObj(txnobj, &txn) )
1853 {
1854 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001855 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001856 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001857
1858 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001859 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001860
1861 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001862 /* Tell Berkeley DB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001863 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001864 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001865 }
1866
1867 MYDB_BEGIN_ALLOW_THREADS;
1868 err = self->db->get(self->db, txn, &key, &data, flags);
1869 MYDB_END_ALLOW_THREADS;
1870
Gregory P. Smithe9477062005-06-04 06:46:59 +00001871 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1872 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001873 err = 0;
1874 Py_INCREF(Py_None);
1875 retval = Py_None;
1876 }
1877 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001878 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001879 retval = Build_PyString(data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001880
1881 /* Even though the flags require DB_DBT_MALLOC, data is not always
1882 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1883 if (data.data != orig_data)
1884 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001885 }
1886
1887 FREE_DBT(key);
1888 RETURN_IF_ERR();
1889 return retval;
1890}
1891
1892
1893static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001894DB_get_byteswapped(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001895{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001896 int err = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001897 int retval = -1;
1898
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001899 CHECK_DB_NOT_CLOSED(self);
1900
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001901 MYDB_BEGIN_ALLOW_THREADS;
1902 err = self->db->get_byteswapped(self->db, &retval);
1903 MYDB_END_ALLOW_THREADS;
1904 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001905 return NUMBER_FromLong(retval);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001906}
1907
1908
1909static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001910DB_get_type(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001911{
1912 int type;
1913
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001914 CHECK_DB_NOT_CLOSED(self);
1915
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001916 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001917 if (type == -1)
1918 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001919 return NUMBER_FromLong(type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001920}
1921
1922
1923static PyObject*
1924DB_join(DBObject* self, PyObject* args)
1925{
1926 int err, flags=0;
1927 int length, x;
1928 PyObject* cursorsObj;
1929 DBC** cursors;
1930 DBC* dbc;
1931
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001932 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1933 return NULL;
1934
1935 CHECK_DB_NOT_CLOSED(self);
1936
1937 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001938 PyErr_SetString(PyExc_TypeError,
1939 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001940 return NULL;
1941 }
1942
1943 length = PyObject_Length(cursorsObj);
1944 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001945 if (!cursors) {
1946 PyErr_NoMemory();
1947 return NULL;
1948 }
1949
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001950 cursors[length] = NULL;
1951 for (x=0; x<length; x++) {
1952 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001953 if (item == NULL) {
1954 free(cursors);
1955 return NULL;
1956 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001957 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001958 PyErr_SetString(PyExc_TypeError,
1959 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001960 free(cursors);
1961 return NULL;
1962 }
1963 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001964 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001965 }
1966
1967 MYDB_BEGIN_ALLOW_THREADS;
1968 err = self->db->join(self->db, cursors, &dbc, flags);
1969 MYDB_END_ALLOW_THREADS;
1970 free(cursors);
1971 RETURN_IF_ERR();
1972
Gregory P. Smith7441e652003-11-03 21:35:31 +00001973 /* FIXME: this is a buggy interface. The returned cursor
1974 contains internal references to the passed in cursors
1975 but does not hold python references to them or prevent
1976 them from being closed prematurely. This can cause
1977 python to crash when things are done in the wrong order. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001978 return (PyObject*) newDBCursorObject(dbc, NULL, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001979}
1980
1981
1982static PyObject*
1983DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1984{
1985 int err, flags=0;
1986 PyObject* txnobj = NULL;
1987 PyObject* keyobj;
1988 DBT key;
1989 DB_TXN *txn = NULL;
1990 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001991 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001992
1993 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1994 &keyobj, &txnobj, &flags))
1995 return NULL;
1996 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001997 if (!make_dbt(keyobj, &key))
1998 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001999 return NULL;
2000 if (!checkTxnObj(txnobj, &txn))
2001 return NULL;
2002
2003 MYDB_BEGIN_ALLOW_THREADS;
2004 err = self->db->key_range(self->db, txn, &key, &range, flags);
2005 MYDB_END_ALLOW_THREADS;
2006
2007 RETURN_IF_ERR();
2008 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2009}
2010
2011
2012static PyObject*
2013DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2014{
2015 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2016 char* filename = NULL;
2017 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002018#if (DBVER >= 41)
2019 PyObject *txnobj = NULL;
2020 DB_TXN *txn = NULL;
2021 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002022 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002023 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2024 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00002025 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002026 "filename", "dbtype", "flags", "mode", "txn", NULL};
2027#else
2028 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002029 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002030 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2031 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002032 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002033 "filename", "dbtype", "flags", "mode", NULL};
2034#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002035
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002036#if (DBVER >= 41)
2037 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2038 &filename, &dbname, &type, &flags, &mode,
2039 &txnobj))
2040#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002041 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002042 &filename, &dbname, &type, &flags,
2043 &mode))
2044#endif
2045 {
2046 PyErr_Clear();
2047 type = DB_UNKNOWN; flags = 0; mode = 0660;
2048 filename = NULL; dbname = NULL;
2049#if (DBVER >= 41)
2050 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2051 kwnames_basic,
2052 &filename, &type, &flags, &mode,
2053 &txnobj))
2054 return NULL;
2055#else
2056 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2057 kwnames_basic,
2058 &filename, &type, &flags, &mode))
2059 return NULL;
2060#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002061 }
2062
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002063#if (DBVER >= 41)
2064 if (!checkTxnObj(txnobj, &txn)) return NULL;
2065#endif
2066
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002067 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002068 PyObject *t = Py_BuildValue("(is)", 0,
2069 "Cannot call open() twice for DB object");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002070 if (t) {
2071 PyErr_SetObject(DBError, t);
2072 Py_DECREF(t);
2073 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002074 return NULL;
2075 }
2076
Jesus Ceaef9764f2008-05-13 18:45:46 +00002077#if (DBVER >= 41)
2078 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2079 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2080 self->txn=(DBTxnObject *)txnobj;
2081 } else {
2082 self->txn=NULL;
2083 }
2084#else
2085 self->txn=NULL;
2086#endif
2087
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002088 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002089#if (DBVER >= 41)
2090 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2091#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002092 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002093#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002094 MYDB_END_ALLOW_THREADS;
2095 if (makeDBError(err)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002096 PyObject *dummy;
2097
2098 dummy=DB_close_internal(self,0);
2099 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002100 return NULL;
2101 }
2102
Gregory P. Smithfc006692007-11-05 09:06:28 +00002103#if (DBVER >= 42)
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002104 self->db->get_flags(self->db, &self->setflags);
Gregory P. Smithfc006692007-11-05 09:06:28 +00002105#endif
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002106
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002107 self->flags = flags;
Jesus Ceaef9764f2008-05-13 18:45:46 +00002108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002109 RETURN_NONE();
2110}
2111
2112
2113static PyObject*
2114DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2115{
2116 int flags=0;
2117 PyObject* txnobj = NULL;
2118 int dlen = -1;
2119 int doff = -1;
2120 PyObject* keyobj, *dataobj, *retval;
2121 DBT key, data;
2122 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002123 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002124 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002125
2126 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2127 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2128 return NULL;
2129
2130 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002131 if (!make_key_dbt(self, keyobj, &key, NULL))
2132 return NULL;
2133 if ( !make_dbt(dataobj, &data) ||
2134 !add_partial_dbt(&data, dlen, doff) ||
2135 !checkTxnObj(txnobj, &txn) )
2136 {
2137 FREE_DBT(key);
2138 return NULL;
2139 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002140
2141 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2142 FREE_DBT(key);
2143 return NULL;
2144 }
2145
2146 if (flags & DB_APPEND)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002147 retval = NUMBER_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002148 else {
2149 retval = Py_None;
2150 Py_INCREF(retval);
2151 }
2152 FREE_DBT(key);
2153 return retval;
2154}
2155
2156
2157
2158static PyObject*
2159DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2160{
2161 char* filename;
2162 char* database = NULL;
2163 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002164 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002165
2166 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2167 &filename, &database, &flags))
2168 return NULL;
2169 CHECK_DB_NOT_CLOSED(self);
2170
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002171 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002172 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002173 RETURN_IF_ERR();
2174 RETURN_NONE();
2175}
2176
2177
2178
2179static PyObject*
2180DB_rename(DBObject* self, PyObject* args)
2181{
2182 char* filename;
2183 char* database;
2184 char* newname;
2185 int err, flags=0;
2186
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002187 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2188 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002189 return NULL;
2190 CHECK_DB_NOT_CLOSED(self);
2191
2192 MYDB_BEGIN_ALLOW_THREADS;
2193 err = self->db->rename(self->db, filename, database, newname, flags);
2194 MYDB_END_ALLOW_THREADS;
2195 RETURN_IF_ERR();
2196 RETURN_NONE();
2197}
2198
2199
2200static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002201DB_get_private(DBObject* self)
2202{
2203 /* We can give out the private field even if db is closed */
2204 Py_INCREF(self->private);
2205 return self->private;
2206}
2207
2208static PyObject*
2209DB_set_private(DBObject* self, PyObject* private)
2210{
2211 /* We can set the private field even if db is closed */
2212 Py_DECREF(self->private);
2213 Py_INCREF(private);
2214 self->private = private;
2215 RETURN_NONE();
2216}
2217
2218
2219static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002220DB_set_bt_minkey(DBObject* self, PyObject* args)
2221{
2222 int err, minkey;
2223
2224 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2225 return NULL;
2226 CHECK_DB_NOT_CLOSED(self);
2227
2228 MYDB_BEGIN_ALLOW_THREADS;
2229 err = self->db->set_bt_minkey(self->db, minkey);
2230 MYDB_END_ALLOW_THREADS;
2231 RETURN_IF_ERR();
2232 RETURN_NONE();
2233}
2234
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002235static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002236_default_cmp(const DBT *leftKey,
2237 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002238{
2239 int res;
2240 int lsize = leftKey->size, rsize = rightKey->size;
2241
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002242 res = memcmp(leftKey->data, rightKey->data,
Georg Brandlef1701f2006-03-07 14:57:48 +00002243 lsize < rsize ? lsize : rsize);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002244
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002245 if (res == 0) {
2246 if (lsize < rsize) {
2247 res = -1;
2248 }
2249 else if (lsize > rsize) {
2250 res = 1;
2251 }
2252 }
2253 return res;
2254}
2255
2256static int
Jesus Ceaef9764f2008-05-13 18:45:46 +00002257_db_compareCallback(DB* db,
Georg Brandlef1701f2006-03-07 14:57:48 +00002258 const DBT *leftKey,
2259 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002260{
2261 int res = 0;
2262 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002263 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002264 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002265
2266 if (self == NULL || self->btCompareCallback == NULL) {
2267 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002268 PyErr_SetString(PyExc_TypeError,
2269 (self == 0
2270 ? "DB_bt_compare db is NULL."
2271 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002272 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002273 PyErr_Print();
2274 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002275 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002276 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002277 MYDB_BEGIN_BLOCK_THREADS;
2278
Jesus Ceaef9764f2008-05-13 18:45:46 +00002279 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002280 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002281 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002282 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002283 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002284 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002285 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002286 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002287 PyErr_Print();
2288 res = _default_cmp(leftKey, rightKey);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002289 } else if (NUMBER_Check(result)) {
2290 res = NUMBER_AsLong(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002291 } else {
2292 PyErr_SetString(PyExc_TypeError,
2293 "DB_bt_compare callback MUST return an int.");
2294 /* we're in a callback within the DB code, we can't raise */
2295 PyErr_Print();
2296 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002297 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002298
Thomas Woutersb3153832006-03-08 01:47:19 +00002299 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002300 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002301
2302 MYDB_END_BLOCK_THREADS;
2303 }
2304 return res;
2305}
2306
2307static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002308DB_set_bt_compare(DBObject* self, PyObject* comparator)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002309{
2310 int err;
Thomas Woutersb3153832006-03-08 01:47:19 +00002311 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002312
Georg Brandlef1701f2006-03-07 14:57:48 +00002313 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002314
Georg Brandlef1701f2006-03-07 14:57:48 +00002315 if (!PyCallable_Check(comparator)) {
2316 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002317 return NULL;
2318 }
2319
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002320 /*
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002321 * Perform a test call of the comparator function with two empty
2322 * string objects here. verify that it returns an int (0).
2323 * err if not.
2324 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002325 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002326 result = PyEval_CallObject(comparator, tuple);
2327 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002328 if (result == NULL)
2329 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002330 if (!NUMBER_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002331 PyErr_SetString(PyExc_TypeError,
2332 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002333 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002334 } else if (NUMBER_AsLong(result) != 0) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002335 PyErr_SetString(PyExc_TypeError,
2336 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002337 return NULL;
2338 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002339 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002340
2341 /* We don't accept multiple set_bt_compare operations, in order to
2342 * simplify the code. This would have no real use, as one cannot
2343 * change the function once the db is opened anyway */
2344 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002345 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002346 return NULL;
2347 }
2348
Georg Brandlef1701f2006-03-07 14:57:48 +00002349 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002350 self->btCompareCallback = comparator;
2351
2352 /* This is to workaround a problem with un-initialized threads (see
2353 comment in DB_associate) */
2354#ifdef WITH_THREAD
2355 PyEval_InitThreads();
2356#endif
2357
Thomas Woutersb3153832006-03-08 01:47:19 +00002358 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002359
2360 if (err) {
2361 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002362 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002363 self->btCompareCallback = NULL;
2364 }
2365
Georg Brandlef1701f2006-03-07 14:57:48 +00002366 RETURN_IF_ERR();
2367 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002368}
2369
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002370
2371static PyObject*
2372DB_set_cachesize(DBObject* self, PyObject* args)
2373{
2374 int err;
2375 int gbytes = 0, bytes = 0, ncache = 0;
2376
2377 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2378 &gbytes,&bytes,&ncache))
2379 return NULL;
2380 CHECK_DB_NOT_CLOSED(self);
2381
2382 MYDB_BEGIN_ALLOW_THREADS;
2383 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2384 MYDB_END_ALLOW_THREADS;
2385 RETURN_IF_ERR();
2386 RETURN_NONE();
2387}
2388
2389
2390static PyObject*
2391DB_set_flags(DBObject* self, PyObject* args)
2392{
2393 int err, flags;
2394
2395 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2396 return NULL;
2397 CHECK_DB_NOT_CLOSED(self);
2398
2399 MYDB_BEGIN_ALLOW_THREADS;
2400 err = self->db->set_flags(self->db, flags);
2401 MYDB_END_ALLOW_THREADS;
2402 RETURN_IF_ERR();
2403
2404 self->setflags |= flags;
2405 RETURN_NONE();
2406}
2407
2408
2409static PyObject*
2410DB_set_h_ffactor(DBObject* self, PyObject* args)
2411{
2412 int err, ffactor;
2413
2414 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2415 return NULL;
2416 CHECK_DB_NOT_CLOSED(self);
2417
2418 MYDB_BEGIN_ALLOW_THREADS;
2419 err = self->db->set_h_ffactor(self->db, ffactor);
2420 MYDB_END_ALLOW_THREADS;
2421 RETURN_IF_ERR();
2422 RETURN_NONE();
2423}
2424
2425
2426static PyObject*
2427DB_set_h_nelem(DBObject* self, PyObject* args)
2428{
2429 int err, nelem;
2430
2431 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2432 return NULL;
2433 CHECK_DB_NOT_CLOSED(self);
2434
2435 MYDB_BEGIN_ALLOW_THREADS;
2436 err = self->db->set_h_nelem(self->db, nelem);
2437 MYDB_END_ALLOW_THREADS;
2438 RETURN_IF_ERR();
2439 RETURN_NONE();
2440}
2441
2442
2443static PyObject*
2444DB_set_lorder(DBObject* self, PyObject* args)
2445{
2446 int err, lorder;
2447
2448 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2449 return NULL;
2450 CHECK_DB_NOT_CLOSED(self);
2451
2452 MYDB_BEGIN_ALLOW_THREADS;
2453 err = self->db->set_lorder(self->db, lorder);
2454 MYDB_END_ALLOW_THREADS;
2455 RETURN_IF_ERR();
2456 RETURN_NONE();
2457}
2458
2459
2460static PyObject*
2461DB_set_pagesize(DBObject* self, PyObject* args)
2462{
2463 int err, pagesize;
2464
2465 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2466 return NULL;
2467 CHECK_DB_NOT_CLOSED(self);
2468
2469 MYDB_BEGIN_ALLOW_THREADS;
2470 err = self->db->set_pagesize(self->db, pagesize);
2471 MYDB_END_ALLOW_THREADS;
2472 RETURN_IF_ERR();
2473 RETURN_NONE();
2474}
2475
2476
2477static PyObject*
2478DB_set_re_delim(DBObject* self, PyObject* args)
2479{
2480 int err;
2481 char delim;
2482
2483 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2484 PyErr_Clear();
2485 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2486 return NULL;
2487 }
2488
2489 CHECK_DB_NOT_CLOSED(self);
2490
2491 MYDB_BEGIN_ALLOW_THREADS;
2492 err = self->db->set_re_delim(self->db, delim);
2493 MYDB_END_ALLOW_THREADS;
2494 RETURN_IF_ERR();
2495 RETURN_NONE();
2496}
2497
2498static PyObject*
2499DB_set_re_len(DBObject* self, PyObject* args)
2500{
2501 int err, len;
2502
2503 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2504 return NULL;
2505 CHECK_DB_NOT_CLOSED(self);
2506
2507 MYDB_BEGIN_ALLOW_THREADS;
2508 err = self->db->set_re_len(self->db, len);
2509 MYDB_END_ALLOW_THREADS;
2510 RETURN_IF_ERR();
2511 RETURN_NONE();
2512}
2513
2514
2515static PyObject*
2516DB_set_re_pad(DBObject* self, PyObject* args)
2517{
2518 int err;
2519 char pad;
2520
2521 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2522 PyErr_Clear();
2523 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2524 return NULL;
2525 }
2526 CHECK_DB_NOT_CLOSED(self);
2527
2528 MYDB_BEGIN_ALLOW_THREADS;
2529 err = self->db->set_re_pad(self->db, pad);
2530 MYDB_END_ALLOW_THREADS;
2531 RETURN_IF_ERR();
2532 RETURN_NONE();
2533}
2534
2535
2536static PyObject*
2537DB_set_re_source(DBObject* self, PyObject* args)
2538{
2539 int err;
2540 char *re_source;
2541
2542 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2543 return NULL;
2544 CHECK_DB_NOT_CLOSED(self);
2545
2546 MYDB_BEGIN_ALLOW_THREADS;
2547 err = self->db->set_re_source(self->db, re_source);
2548 MYDB_END_ALLOW_THREADS;
2549 RETURN_IF_ERR();
2550 RETURN_NONE();
2551}
2552
2553
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002554static PyObject*
2555DB_set_q_extentsize(DBObject* self, PyObject* args)
2556{
2557 int err;
2558 int extentsize;
2559
2560 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2561 return NULL;
2562 CHECK_DB_NOT_CLOSED(self);
2563
2564 MYDB_BEGIN_ALLOW_THREADS;
2565 err = self->db->set_q_extentsize(self->db, extentsize);
2566 MYDB_END_ALLOW_THREADS;
2567 RETURN_IF_ERR();
2568 RETURN_NONE();
2569}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002570
2571static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002572DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002573{
2574 int err, flags = 0, type;
2575 void* sp;
2576 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002577#if (DBVER >= 43)
2578 PyObject* txnobj = NULL;
2579 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002580 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002581#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002582 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002583#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002584
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002585#if (DBVER >= 43)
2586 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2587 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002588 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002589 if (!checkTxnObj(txnobj, &txn))
2590 return NULL;
2591#else
2592 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2593 return NULL;
2594#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002595 CHECK_DB_NOT_CLOSED(self);
2596
2597 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002598#if (DBVER >= 43)
2599 err = self->db->stat(self->db, txn, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002600#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002601 err = self->db->stat(self->db, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002602#endif
2603 MYDB_END_ALLOW_THREADS;
2604 RETURN_IF_ERR();
2605
2606 self->haveStat = 1;
2607
2608 /* Turn the stat structure into a dictionary */
2609 type = _DB_get_type(self);
2610 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2611 free(sp);
2612 return NULL;
2613 }
2614
2615#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2616#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2617#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2618
2619 switch (type) {
2620 case DB_HASH:
2621 MAKE_HASH_ENTRY(magic);
2622 MAKE_HASH_ENTRY(version);
2623 MAKE_HASH_ENTRY(nkeys);
2624 MAKE_HASH_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002625#if (DBVER >= 46)
2626 MAKE_HASH_ENTRY(pagecnt);
2627#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002628 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002629#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002630 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002631#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002632 MAKE_HASH_ENTRY(ffactor);
2633 MAKE_HASH_ENTRY(buckets);
2634 MAKE_HASH_ENTRY(free);
2635 MAKE_HASH_ENTRY(bfree);
2636 MAKE_HASH_ENTRY(bigpages);
2637 MAKE_HASH_ENTRY(big_bfree);
2638 MAKE_HASH_ENTRY(overflows);
2639 MAKE_HASH_ENTRY(ovfl_free);
2640 MAKE_HASH_ENTRY(dup);
2641 MAKE_HASH_ENTRY(dup_free);
2642 break;
2643
2644 case DB_BTREE:
2645 case DB_RECNO:
2646 MAKE_BT_ENTRY(magic);
2647 MAKE_BT_ENTRY(version);
2648 MAKE_BT_ENTRY(nkeys);
2649 MAKE_BT_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002650#if (DBVER >= 46)
2651 MAKE_BT_ENTRY(pagecnt);
2652#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002653 MAKE_BT_ENTRY(pagesize);
2654 MAKE_BT_ENTRY(minkey);
2655 MAKE_BT_ENTRY(re_len);
2656 MAKE_BT_ENTRY(re_pad);
2657 MAKE_BT_ENTRY(levels);
2658 MAKE_BT_ENTRY(int_pg);
2659 MAKE_BT_ENTRY(leaf_pg);
2660 MAKE_BT_ENTRY(dup_pg);
2661 MAKE_BT_ENTRY(over_pg);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002662#if (DBVER >= 43)
2663 MAKE_BT_ENTRY(empty_pg);
2664#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002665 MAKE_BT_ENTRY(free);
2666 MAKE_BT_ENTRY(int_pgfree);
2667 MAKE_BT_ENTRY(leaf_pgfree);
2668 MAKE_BT_ENTRY(dup_pgfree);
2669 MAKE_BT_ENTRY(over_pgfree);
2670 break;
2671
2672 case DB_QUEUE:
2673 MAKE_QUEUE_ENTRY(magic);
2674 MAKE_QUEUE_ENTRY(version);
2675 MAKE_QUEUE_ENTRY(nkeys);
2676 MAKE_QUEUE_ENTRY(ndata);
2677 MAKE_QUEUE_ENTRY(pagesize);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002678#if (DBVER >= 41)
Jesus Ceaef9764f2008-05-13 18:45:46 +00002679 MAKE_QUEUE_ENTRY(extentsize);
2680#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002681 MAKE_QUEUE_ENTRY(pages);
2682 MAKE_QUEUE_ENTRY(re_len);
2683 MAKE_QUEUE_ENTRY(re_pad);
2684 MAKE_QUEUE_ENTRY(pgfree);
2685#if (DBVER == 31)
2686 MAKE_QUEUE_ENTRY(start);
2687#endif
2688 MAKE_QUEUE_ENTRY(first_recno);
2689 MAKE_QUEUE_ENTRY(cur_recno);
2690 break;
2691
2692 default:
2693 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2694 Py_DECREF(d);
2695 d = NULL;
2696 }
2697
2698#undef MAKE_HASH_ENTRY
2699#undef MAKE_BT_ENTRY
2700#undef MAKE_QUEUE_ENTRY
2701
2702 free(sp);
2703 return d;
2704}
2705
2706static PyObject*
2707DB_sync(DBObject* self, PyObject* args)
2708{
2709 int err;
2710 int flags = 0;
2711
2712 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2713 return NULL;
2714 CHECK_DB_NOT_CLOSED(self);
2715
2716 MYDB_BEGIN_ALLOW_THREADS;
2717 err = self->db->sync(self->db, flags);
2718 MYDB_END_ALLOW_THREADS;
2719 RETURN_IF_ERR();
2720 RETURN_NONE();
2721}
2722
2723
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002724static PyObject*
2725DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2726{
2727 int err, flags=0;
2728 u_int32_t count=0;
2729 PyObject* txnobj = NULL;
2730 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002731 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002732
2733 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2734 &txnobj, &flags))
2735 return NULL;
2736 CHECK_DB_NOT_CLOSED(self);
2737 if (!checkTxnObj(txnobj, &txn))
2738 return NULL;
2739
2740 MYDB_BEGIN_ALLOW_THREADS;
2741 err = self->db->truncate(self->db, txn, &count, flags);
2742 MYDB_END_ALLOW_THREADS;
2743 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002744 return NUMBER_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002745}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002746
2747
2748static PyObject*
2749DB_upgrade(DBObject* self, PyObject* args)
2750{
2751 int err, flags=0;
2752 char *filename;
2753
2754 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2755 return NULL;
2756 CHECK_DB_NOT_CLOSED(self);
2757
2758 MYDB_BEGIN_ALLOW_THREADS;
2759 err = self->db->upgrade(self->db, filename, flags);
2760 MYDB_END_ALLOW_THREADS;
2761 RETURN_IF_ERR();
2762 RETURN_NONE();
2763}
2764
2765
2766static PyObject*
2767DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2768{
2769 int err, flags=0;
2770 char* fileName;
2771 char* dbName=NULL;
2772 char* outFileName=NULL;
2773 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002774 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002775 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002776
2777 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2778 &fileName, &dbName, &outFileName, &flags))
2779 return NULL;
2780
2781 CHECK_DB_NOT_CLOSED(self);
2782 if (outFileName)
2783 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002784 /* XXX(nnorwitz): it should probably be an exception if outFile
2785 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002786
2787 MYDB_BEGIN_ALLOW_THREADS;
2788 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2789 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002790 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002791 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002792
Jesus Ceaef9764f2008-05-13 18:45:46 +00002793 { /* DB.verify acts as a DB handle destructor (like close) */
2794 PyObject *error;
2795
2796 error=DB_close_internal(self,0);
2797 if (error ) {
2798 return error;
2799 }
2800 }
Gregory P. Smith41631e82003-09-21 00:08:14 +00002801
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002802 RETURN_IF_ERR();
2803 RETURN_NONE();
2804}
2805
2806
2807static PyObject*
2808DB_set_get_returns_none(DBObject* self, PyObject* args)
2809{
2810 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002811 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002812
2813 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2814 return NULL;
2815 CHECK_DB_NOT_CLOSED(self);
2816
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002817 if (self->moduleFlags.getReturnsNone)
2818 ++oldValue;
2819 if (self->moduleFlags.cursorSetReturnsNone)
2820 ++oldValue;
2821 self->moduleFlags.getReturnsNone = (flags >= 1);
2822 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002823 return NUMBER_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002824}
2825
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002826#if (DBVER >= 41)
2827static PyObject*
2828DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2829{
2830 int err;
2831 u_int32_t flags=0;
2832 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002833 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002834
2835 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2836 &passwd, &flags)) {
2837 return NULL;
2838 }
2839
2840 MYDB_BEGIN_ALLOW_THREADS;
2841 err = self->db->set_encrypt(self->db, passwd, flags);
2842 MYDB_END_ALLOW_THREADS;
2843
2844 RETURN_IF_ERR();
2845 RETURN_NONE();
2846}
2847#endif /* DBVER >= 41 */
2848
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002849
2850/*-------------------------------------------------------------- */
2851/* Mapping and Dictionary-like access routines */
2852
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002853Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002854{
2855 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002856 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002857 int flags = 0;
2858 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002859 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002860
2861 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002862 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002863 if (t) {
2864 PyErr_SetObject(DBError, t);
2865 Py_DECREF(t);
2866 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002867 return -1;
2868 }
2869
2870 if (self->haveStat) { /* Has the stat function been called recently? If
2871 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002872 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002873 }
2874
2875 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002876redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002877#if (DBVER >= 43)
2878 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002879#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002880 err = self->db->stat(self->db, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002881#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002882
2883 /* All the stat structures have matching fields upto the ndata field,
2884 so we can use any of them for the type cast */
2885 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2886
Jesus Ceaef9764f2008-05-13 18:45:46 +00002887 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002888 * redo a full stat to make sure.
2889 * Fixes SF python bug 1493322, pybsddb bug 1184012
2890 */
2891 if (size == 0 && (flags & DB_FAST_STAT)) {
2892 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002893 if (!err)
2894 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002895 goto redo_stat_for_length;
2896 }
2897
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002898 MYDB_END_ALLOW_THREADS;
2899
2900 if (err)
2901 return -1;
2902
2903 self->haveStat = 1;
2904
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002905 free(sp);
2906 return size;
2907}
2908
2909
2910PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2911{
2912 int err;
2913 PyObject* retval;
2914 DBT key;
2915 DBT data;
2916
2917 CHECK_DB_NOT_CLOSED(self);
2918 if (!make_key_dbt(self, keyobj, &key, NULL))
2919 return NULL;
2920
2921 CLEAR_DBT(data);
2922 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002923 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002924 data.flags = DB_DBT_MALLOC;
2925 }
2926 MYDB_BEGIN_ALLOW_THREADS;
2927 err = self->db->get(self->db, NULL, &key, &data, 0);
2928 MYDB_END_ALLOW_THREADS;
2929 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2930 PyErr_SetObject(PyExc_KeyError, keyobj);
2931 retval = NULL;
2932 }
2933 else if (makeDBError(err)) {
2934 retval = NULL;
2935 }
2936 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002937 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002938 FREE_DBT(data);
2939 }
2940
2941 FREE_DBT(key);
2942 return retval;
2943}
2944
2945
2946static int
2947DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2948{
2949 DBT key, data;
2950 int retval;
2951 int flags = 0;
2952
2953 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002954 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002955 if (t) {
2956 PyErr_SetObject(DBError, t);
2957 Py_DECREF(t);
2958 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002959 return -1;
2960 }
2961
2962 if (!make_key_dbt(self, keyobj, &key, NULL))
2963 return -1;
2964
2965 if (dataobj != NULL) {
2966 if (!make_dbt(dataobj, &data))
2967 retval = -1;
2968 else {
2969 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002970 /* dictionaries shouldn't have duplicate keys */
2971 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002972 retval = _DB_put(self, NULL, &key, &data, flags);
2973
2974 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002975 /* try deleting any old record that matches and then PUT it
2976 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002977 _DB_delete(self, NULL, &key, 0);
2978 PyErr_Clear();
2979 retval = _DB_put(self, NULL, &key, &data, flags);
2980 }
2981 }
2982 }
2983 else {
2984 /* dataobj == NULL, so delete the key */
2985 retval = _DB_delete(self, NULL, &key, 0);
2986 }
2987 FREE_DBT(key);
2988 return retval;
2989}
2990
2991
2992static PyObject*
2993DB_has_key(DBObject* self, PyObject* args)
2994{
2995 int err;
2996 PyObject* keyobj;
2997 DBT key, data;
2998 PyObject* txnobj = NULL;
2999 DB_TXN *txn = NULL;
3000
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003001 if (!PyArg_UnpackTuple(args,"has_key", 1, 2, &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003002 return NULL;
3003 CHECK_DB_NOT_CLOSED(self);
3004 if (!make_key_dbt(self, keyobj, &key, NULL))
3005 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003006 if (!checkTxnObj(txnobj, &txn)) {
3007 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003008 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003009 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003010
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003011 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003012 it has a record but can't allocate a buffer for the data. This saves
3013 having to deal with data we won't be using.
3014 */
3015 CLEAR_DBT(data);
3016 data.flags = DB_DBT_USERMEM;
3017
3018 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00003019 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003020 MYDB_END_ALLOW_THREADS;
3021 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003022
3023 if (err == DB_BUFFER_SMALL || err == 0) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003024 return NUMBER_FromLong(1);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003025 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003026 return NUMBER_FromLong(0);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003027 }
3028
3029 makeDBError(err);
3030 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003031}
3032
3033
3034#define _KEYS_LIST 1
3035#define _VALUES_LIST 2
3036#define _ITEMS_LIST 3
3037
3038static PyObject*
3039_DB_make_list(DBObject* self, DB_TXN* txn, int type)
3040{
3041 int err, dbtype;
3042 DBT key;
3043 DBT data;
3044 DBC *cursor;
3045 PyObject* list;
3046 PyObject* item = NULL;
3047
3048 CHECK_DB_NOT_CLOSED(self);
3049 CLEAR_DBT(key);
3050 CLEAR_DBT(data);
3051
3052 dbtype = _DB_get_type(self);
3053 if (dbtype == -1)
3054 return NULL;
3055
3056 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00003057 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003058 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003059
3060 /* get a cursor */
3061 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00003062 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003063 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00003064 if (makeDBError(err)) {
3065 Py_DECREF(list);
3066 return NULL;
3067 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003068
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003069 while (1) { /* use the cursor to traverse the DB, collecting items */
3070 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003071 err = _DBC_get(cursor, &key, &data, DB_NEXT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003072 MYDB_END_ALLOW_THREADS;
3073
3074 if (err) {
3075 /* for any error, break out of the loop */
3076 break;
3077 }
3078
3079 switch (type) {
3080 case _KEYS_LIST:
3081 switch(dbtype) {
3082 case DB_BTREE:
3083 case DB_HASH:
3084 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003085 item = Build_PyString(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003086 break;
3087 case DB_RECNO:
3088 case DB_QUEUE:
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003089 item = NUMBER_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003090 break;
3091 }
3092 break;
3093
3094 case _VALUES_LIST:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003095 item = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003096 break;
3097
3098 case _ITEMS_LIST:
3099 switch(dbtype) {
3100 case DB_BTREE:
3101 case DB_HASH:
3102 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003103 item = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003104 break;
3105 case DB_RECNO:
3106 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003107 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003108 break;
3109 }
3110 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00003111 default:
3112 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3113 item = NULL;
3114 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003115 }
3116 if (item == NULL) {
3117 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003118 list = NULL;
3119 goto done;
3120 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003121 if (PyList_Append(list, item)) {
3122 Py_DECREF(list);
3123 Py_DECREF(item);
3124 list = NULL;
3125 goto done;
3126 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003127 Py_DECREF(item);
3128 }
3129
Gregory P. Smithe9477062005-06-04 06:46:59 +00003130 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3131 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003132 Py_DECREF(list);
3133 list = NULL;
3134 }
3135
3136 done:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003137 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003138 _DBC_close(cursor);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003139 MYDB_END_ALLOW_THREADS;
3140 return list;
3141}
3142
3143
3144static PyObject*
3145DB_keys(DBObject* self, PyObject* args)
3146{
3147 PyObject* txnobj = NULL;
3148 DB_TXN *txn = NULL;
3149
Georg Brandl96a8c392006-05-29 21:04:52 +00003150 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003151 return NULL;
3152 if (!checkTxnObj(txnobj, &txn))
3153 return NULL;
3154 return _DB_make_list(self, txn, _KEYS_LIST);
3155}
3156
3157
3158static PyObject*
3159DB_items(DBObject* self, PyObject* args)
3160{
3161 PyObject* txnobj = NULL;
3162 DB_TXN *txn = NULL;
3163
Georg Brandl96a8c392006-05-29 21:04:52 +00003164 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003165 return NULL;
3166 if (!checkTxnObj(txnobj, &txn))
3167 return NULL;
3168 return _DB_make_list(self, txn, _ITEMS_LIST);
3169}
3170
3171
3172static PyObject*
3173DB_values(DBObject* self, PyObject* args)
3174{
3175 PyObject* txnobj = NULL;
3176 DB_TXN *txn = NULL;
3177
Georg Brandl96a8c392006-05-29 21:04:52 +00003178 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003179 return NULL;
3180 if (!checkTxnObj(txnobj, &txn))
3181 return NULL;
3182 return _DB_make_list(self, txn, _VALUES_LIST);
3183}
3184
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003185/* --------------------------------------------------------------------- */
3186/* DBCursor methods */
3187
3188
3189static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003190DBC_close_internal(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003191{
3192 int err = 0;
3193
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003194 if (self->dbc != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003195 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3196 if (self->txn) {
3197 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3198 self->txn=NULL;
3199 }
3200
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003201 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003202 err = _DBC_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003203 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003204 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003205 }
3206 RETURN_IF_ERR();
3207 RETURN_NONE();
3208}
3209
Jesus Ceaef9764f2008-05-13 18:45:46 +00003210static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003211DBC_close(DBCursorObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00003212{
Jesus Ceaef9764f2008-05-13 18:45:46 +00003213 return DBC_close_internal(self);
3214}
3215
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003216
3217static PyObject*
3218DBC_count(DBCursorObject* self, PyObject* args)
3219{
3220 int err = 0;
3221 db_recno_t count;
3222 int flags = 0;
3223
3224 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3225 return NULL;
3226
3227 CHECK_CURSOR_NOT_CLOSED(self);
3228
3229 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003230 err = _DBC_count(self->dbc, &count, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003231 MYDB_END_ALLOW_THREADS;
3232 RETURN_IF_ERR();
3233
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003234 return NUMBER_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003235}
3236
3237
3238static PyObject*
3239DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3240{
3241 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3242}
3243
3244
3245static PyObject*
3246DBC_delete(DBCursorObject* self, PyObject* args)
3247{
3248 int err, flags=0;
3249
3250 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3251 return NULL;
3252
3253 CHECK_CURSOR_NOT_CLOSED(self);
3254
3255 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003256 err = _DBC_del(self->dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003257 MYDB_END_ALLOW_THREADS;
3258 RETURN_IF_ERR();
3259
3260 self->mydb->haveStat = 0;
3261 RETURN_NONE();
3262}
3263
3264
3265static PyObject*
3266DBC_dup(DBCursorObject* self, PyObject* args)
3267{
3268 int err, flags =0;
3269 DBC* dbc = NULL;
3270
3271 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3272 return NULL;
3273
3274 CHECK_CURSOR_NOT_CLOSED(self);
3275
3276 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003277 err = _DBC_dup(self->dbc, &dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003278 MYDB_END_ALLOW_THREADS;
3279 RETURN_IF_ERR();
3280
Jesus Ceaef9764f2008-05-13 18:45:46 +00003281 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003282}
3283
3284static PyObject*
3285DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3286{
3287 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3288}
3289
3290
3291static PyObject*
3292DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3293{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003294 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003295 PyObject* keyobj = NULL;
3296 PyObject* dataobj = NULL;
3297 PyObject* retval = NULL;
3298 int dlen = -1;
3299 int doff = -1;
3300 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003301 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003302 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003303
3304 CLEAR_DBT(key);
3305 CLEAR_DBT(data);
3306 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003307 &flags, &dlen, &doff))
3308 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003309 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003310 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3311 &kwnames[1],
3312 &keyobj, &flags, &dlen, &doff))
3313 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003314 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003315 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3316 kwnames, &keyobj, &dataobj,
3317 &flags, &dlen, &doff))
3318 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003319 return NULL;
3320 }
3321 }
3322 }
3323
3324 CHECK_CURSOR_NOT_CLOSED(self);
3325
3326 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3327 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003328 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3329 (!add_partial_dbt(&data, dlen, doff)) )
3330 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003331 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003332 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003333 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003334
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003335 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003336 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003337 MYDB_END_ALLOW_THREADS;
3338
Gregory P. Smithe9477062005-06-04 06:46:59 +00003339 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3340 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003341 Py_INCREF(Py_None);
3342 retval = Py_None;
3343 }
3344 else if (makeDBError(err)) {
3345 retval = NULL;
3346 }
3347 else {
3348 switch (_DB_get_type(self->mydb)) {
3349 case -1:
3350 retval = NULL;
3351 break;
3352 case DB_BTREE:
3353 case DB_HASH:
3354 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003355 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003356 break;
3357 case DB_RECNO:
3358 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003359 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003360 break;
3361 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003362 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003363 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003364 return retval;
3365}
3366
Gregory P. Smith19699a92004-06-28 04:06:49 +00003367static PyObject*
3368DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3369{
3370 int err, flags=0;
3371 PyObject* keyobj = NULL;
3372 PyObject* dataobj = NULL;
3373 PyObject* retval = NULL;
3374 int dlen = -1;
3375 int doff = -1;
3376 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003377 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3378 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003379
3380 CLEAR_DBT(key);
3381 CLEAR_DBT(data);
3382 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3383 &flags, &dlen, &doff))
3384 {
3385 PyErr_Clear();
3386 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003387 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003388 &keyobj, &flags, &dlen, &doff))
3389 {
3390 PyErr_Clear();
3391 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3392 kwnames, &keyobj, &dataobj,
3393 &flags, &dlen, &doff))
3394 {
3395 return NULL;
3396 }
3397 }
3398 }
3399
3400 CHECK_CURSOR_NOT_CLOSED(self);
3401
3402 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3403 return NULL;
3404 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3405 (!add_partial_dbt(&data, dlen, doff)) ) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003406 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003407 return NULL;
3408 }
3409
Gregory P. Smith19699a92004-06-28 04:06:49 +00003410 CLEAR_DBT(pkey);
3411 pkey.flags = DB_DBT_MALLOC;
3412
3413 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003414 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003415 MYDB_END_ALLOW_THREADS;
3416
Gregory P. Smithe9477062005-06-04 06:46:59 +00003417 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3418 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003419 Py_INCREF(Py_None);
3420 retval = Py_None;
3421 }
3422 else if (makeDBError(err)) {
3423 retval = NULL;
3424 }
3425 else {
3426 PyObject *pkeyObj;
3427 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003428 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003429
3430 if (self->mydb->primaryDBType == DB_RECNO ||
3431 self->mydb->primaryDBType == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003432 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003433 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003434 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003435
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003436 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003437 {
3438 PyObject *keyObj;
3439 int type = _DB_get_type(self->mydb);
3440 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003441 keyObj = NUMBER_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003442 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003443 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003444#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003445 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003446#else
3447 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3448#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003449 Py_DECREF(keyObj);
Jesus Ceaef9764f2008-05-13 18:45:46 +00003450 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003451 }
3452 else /* return just the pkey and data */
3453 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003454#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003455 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003456#else
3457 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3458#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003459 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003460 Py_DECREF(dataObj);
3461 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003462 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003463 }
3464 /* the only time REALLOC should be set is if we used an integer
3465 * key that make_key_dbt malloc'd for us. always free these. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003466 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003467 FREE_DBT(key);
3468 }
3469 return retval;
3470}
3471
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003472
3473static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003474DBC_get_recno(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003475{
3476 int err;
3477 db_recno_t recno;
3478 DBT key;
3479 DBT data;
3480
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003481 CHECK_CURSOR_NOT_CLOSED(self);
3482
3483 CLEAR_DBT(key);
3484 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003485
3486 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003487 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003488 MYDB_END_ALLOW_THREADS;
3489 RETURN_IF_ERR();
3490
3491 recno = *((db_recno_t*)data.data);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003492 return NUMBER_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003493}
3494
3495
3496static PyObject*
3497DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3498{
3499 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3500}
3501
3502
3503static PyObject*
3504DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3505{
3506 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3507}
3508
3509
3510static PyObject*
3511DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3512{
3513 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3514}
3515
3516
3517static PyObject*
3518DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3519{
3520 int err, flags = 0;
3521 PyObject* keyobj, *dataobj;
3522 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003523 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003524 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003525 int dlen = -1;
3526 int doff = -1;
3527
3528 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3529 &keyobj, &dataobj, &flags, &dlen, &doff))
3530 return NULL;
3531
3532 CHECK_CURSOR_NOT_CLOSED(self);
3533
3534 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3535 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003536 if (!make_dbt(dataobj, &data) ||
3537 !add_partial_dbt(&data, dlen, doff) )
3538 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003539 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003540 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003541 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003542
3543 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003544 err = _DBC_put(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003545 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003546 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003547 RETURN_IF_ERR();
3548 self->mydb->haveStat = 0;
3549 RETURN_NONE();
3550}
3551
3552
3553static PyObject*
3554DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3555{
3556 int err, flags = 0;
3557 DBT key, data;
3558 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003559 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003560 int dlen = -1;
3561 int doff = -1;
3562
3563 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3564 &keyobj, &flags, &dlen, &doff))
3565 return NULL;
3566
3567 CHECK_CURSOR_NOT_CLOSED(self);
3568
3569 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3570 return NULL;
3571
3572 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003573 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003574 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003575 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003576 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003577
3578 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003579 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003580 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003581 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3582 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003583 Py_INCREF(Py_None);
3584 retval = Py_None;
3585 }
3586 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003587 retval = NULL;
3588 }
3589 else {
3590 switch (_DB_get_type(self->mydb)) {
3591 case -1:
3592 retval = NULL;
3593 break;
3594 case DB_BTREE:
3595 case DB_HASH:
3596 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003597 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003598 break;
3599 case DB_RECNO:
3600 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003601 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003602 break;
3603 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003604 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003605 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003606 /* the only time REALLOC should be set is if we used an integer
3607 * key that make_key_dbt malloc'd for us. always free these. */
3608 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003609 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003610 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003611
3612 return retval;
3613}
3614
3615
3616static PyObject*
3617DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3618{
3619 int err, flags = 0;
3620 DBT key, data;
3621 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003622 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003623 int dlen = -1;
3624 int doff = -1;
3625
3626 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3627 &keyobj, &flags, &dlen, &doff))
3628 return NULL;
3629
3630 CHECK_CURSOR_NOT_CLOSED(self);
3631
3632 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3633 return NULL;
3634
3635 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003636 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003637 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003638 return NULL;
3639 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003640 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003641 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003642 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003643 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3644 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003645 Py_INCREF(Py_None);
3646 retval = Py_None;
3647 }
3648 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003649 retval = NULL;
3650 }
3651 else {
3652 switch (_DB_get_type(self->mydb)) {
3653 case -1:
3654 retval = NULL;
3655 break;
3656 case DB_BTREE:
3657 case DB_HASH:
3658 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003659 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003660 break;
3661 case DB_RECNO:
3662 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003663 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003664 break;
3665 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003666 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003667 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003668 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003669 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003670 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003671 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003672 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003673
3674 return retval;
3675}
3676
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003677static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003678_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3679 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003680{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003681 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003682 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003683 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003684
Gregory P. Smith7441e652003-11-03 21:35:31 +00003685 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003686 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3687 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003688 if (!make_dbt(dataobj, &data)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003689 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003690 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003691 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003692
3693 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003694 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003695 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003696 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003697 Py_INCREF(Py_None);
3698 retval = Py_None;
3699 }
3700 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003701 retval = NULL;
3702 }
3703 else {
3704 switch (_DB_get_type(self->mydb)) {
3705 case -1:
3706 retval = NULL;
3707 break;
3708 case DB_BTREE:
3709 case DB_HASH:
3710 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003711 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003712 break;
3713 case DB_RECNO:
3714 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003715 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003716 break;
3717 }
3718 }
3719
Jesus Ceaef9764f2008-05-13 18:45:46 +00003720 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003721 return retval;
3722}
3723
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003724static PyObject*
3725DBC_get_both(DBCursorObject* self, PyObject* args)
3726{
3727 int flags=0;
3728 PyObject *keyobj, *dataobj;
3729
3730 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3731 return NULL;
3732
Gregory P. Smith7441e652003-11-03 21:35:31 +00003733 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003734 CHECK_CURSOR_NOT_CLOSED(self);
3735
3736 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3737 self->mydb->moduleFlags.getReturnsNone);
3738}
3739
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003740/* Return size of entry */
3741static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003742DBC_get_current_size(DBCursorObject* self)
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003743{
3744 int err, flags=DB_CURRENT;
3745 PyObject* retval = NULL;
3746 DBT key, data;
3747
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003748 CHECK_CURSOR_NOT_CLOSED(self);
3749 CLEAR_DBT(key);
3750 CLEAR_DBT(data);
3751
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003752 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003753 getting the record size. */
3754 data.flags = DB_DBT_USERMEM;
3755 data.ulen = 0;
3756 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003757 err = _DBC_get(self->dbc, &key, &data, flags);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003758 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003759 if (err == DB_BUFFER_SMALL || !err) {
3760 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003761 retval = NUMBER_FromLong((long)data.size);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003762 err = 0;
3763 }
3764
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003765 RETURN_IF_ERR();
3766 return retval;
3767}
3768
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003769static PyObject*
3770DBC_set_both(DBCursorObject* self, PyObject* args)
3771{
3772 int flags=0;
3773 PyObject *keyobj, *dataobj;
3774
3775 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3776 return NULL;
3777
Gregory P. Smith7441e652003-11-03 21:35:31 +00003778 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003779 CHECK_CURSOR_NOT_CLOSED(self);
3780
3781 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3782 self->mydb->moduleFlags.cursorSetReturnsNone);
3783}
3784
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003785
3786static PyObject*
3787DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3788{
3789 int err, irecno, flags=0;
3790 db_recno_t recno;
3791 DBT key, data;
3792 PyObject* retval;
3793 int dlen = -1;
3794 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003795 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003796
3797 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3798 &irecno, &flags, &dlen, &doff))
3799 return NULL;
3800
3801 CHECK_CURSOR_NOT_CLOSED(self);
3802
3803 CLEAR_DBT(key);
3804 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003805 /* use allocated space so DB will be able to realloc room for the real
3806 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003807 key.data = malloc(sizeof(db_recno_t));
3808 if (key.data == NULL) {
3809 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3810 return NULL;
3811 }
3812 key.size = sizeof(db_recno_t);
3813 key.ulen = key.size;
3814 memcpy(key.data, &recno, sizeof(db_recno_t));
3815 key.flags = DB_DBT_REALLOC;
3816
3817 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003818 if (!add_partial_dbt(&data, dlen, doff)) {
3819 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003820 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003821 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003822
3823 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003824 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003825 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003826 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3827 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003828 Py_INCREF(Py_None);
3829 retval = Py_None;
3830 }
3831 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003832 retval = NULL;
3833 }
3834 else { /* Can only be used for BTrees, so no need to return int key */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003835 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003836 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003837 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003838
3839 return retval;
3840}
3841
3842
3843static PyObject*
3844DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3845{
3846 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3847}
3848
3849
3850static PyObject*
3851DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3852{
3853 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3854}
3855
3856
3857static PyObject*
3858DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3859{
3860 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3861}
3862
3863
3864static PyObject*
3865DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3866{
3867 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3868}
3869
3870
3871static PyObject*
3872DBC_join_item(DBCursorObject* self, PyObject* args)
3873{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003874 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003875 DBT key, data;
3876 PyObject* retval;
3877
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003878 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003879 return NULL;
3880
3881 CHECK_CURSOR_NOT_CLOSED(self);
3882
3883 CLEAR_DBT(key);
3884 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003885
3886 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003887 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003888 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003889 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3890 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003891 Py_INCREF(Py_None);
3892 retval = Py_None;
3893 }
3894 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003895 retval = NULL;
3896 }
3897 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003898 retval = BuildValue_S(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003899 }
3900
3901 return retval;
3902}
3903
3904
3905
3906/* --------------------------------------------------------------------- */
3907/* DBEnv methods */
3908
3909
3910static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003911DBEnv_close_internal(DBEnvObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003912{
Jesus Ceaef9764f2008-05-13 18:45:46 +00003913 PyObject *dummy;
3914 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003915
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003916 if (!self->closed) { /* Don't close more than once */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003917 while(self->children_txns) {
3918 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
3919 Py_XDECREF(dummy);
3920 }
3921 while(self->children_dbs) {
3922 dummy=DB_close_internal(self->children_dbs,0);
3923 Py_XDECREF(dummy);
3924 }
3925
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003926 MYDB_BEGIN_ALLOW_THREADS;
3927 err = self->db_env->close(self->db_env, flags);
3928 MYDB_END_ALLOW_THREADS;
3929 /* after calling DBEnv->close, regardless of error, this DBEnv
Jesus Ceaef9764f2008-05-13 18:45:46 +00003930 * may not be accessed again (Berkeley DB docs). */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003931 self->closed = 1;
3932 self->db_env = NULL;
3933 RETURN_IF_ERR();
3934 }
3935 RETURN_NONE();
3936}
3937
Jesus Ceaef9764f2008-05-13 18:45:46 +00003938static PyObject*
3939DBEnv_close(DBEnvObject* self, PyObject* args)
3940{
3941 int flags = 0;
3942
3943 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3944 return NULL;
3945 return DBEnv_close_internal(self,flags);
3946}
3947
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003948
3949static PyObject*
3950DBEnv_open(DBEnvObject* self, PyObject* args)
3951{
3952 int err, flags=0, mode=0660;
3953 char *db_home;
3954
3955 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3956 return NULL;
3957
3958 CHECK_ENV_NOT_CLOSED(self);
3959
3960 MYDB_BEGIN_ALLOW_THREADS;
3961 err = self->db_env->open(self->db_env, db_home, flags, mode);
3962 MYDB_END_ALLOW_THREADS;
3963 RETURN_IF_ERR();
3964 self->closed = 0;
3965 self->flags = flags;
3966 RETURN_NONE();
3967}
3968
3969
3970static PyObject*
3971DBEnv_remove(DBEnvObject* self, PyObject* args)
3972{
3973 int err, flags=0;
3974 char *db_home;
3975
3976 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3977 return NULL;
3978 CHECK_ENV_NOT_CLOSED(self);
3979 MYDB_BEGIN_ALLOW_THREADS;
3980 err = self->db_env->remove(self->db_env, db_home, flags);
3981 MYDB_END_ALLOW_THREADS;
3982 RETURN_IF_ERR();
3983 RETURN_NONE();
3984}
3985
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003986#if (DBVER >= 41)
3987static PyObject*
3988DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3989{
3990 int err;
3991 u_int32_t flags=0;
3992 char *file = NULL;
3993 char *database = NULL;
3994 PyObject *txnobj = NULL;
3995 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003996 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003997 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003998
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003999 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004000 &file, &database, &txnobj, &flags)) {
4001 return NULL;
4002 }
4003 if (!checkTxnObj(txnobj, &txn)) {
4004 return NULL;
4005 }
4006 CHECK_ENV_NOT_CLOSED(self);
4007 MYDB_BEGIN_ALLOW_THREADS;
4008 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4009 MYDB_END_ALLOW_THREADS;
4010 RETURN_IF_ERR();
4011 RETURN_NONE();
4012}
4013
4014static PyObject*
4015DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4016{
4017 int err;
4018 u_int32_t flags=0;
4019 char *file = NULL;
4020 char *database = NULL;
4021 char *newname = NULL;
4022 PyObject *txnobj = NULL;
4023 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004024 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004025 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004026
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004027 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004028 &file, &database, &newname, &txnobj, &flags)) {
4029 return NULL;
4030 }
4031 if (!checkTxnObj(txnobj, &txn)) {
4032 return NULL;
4033 }
4034 CHECK_ENV_NOT_CLOSED(self);
4035 MYDB_BEGIN_ALLOW_THREADS;
4036 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4037 flags);
4038 MYDB_END_ALLOW_THREADS;
4039 RETURN_IF_ERR();
4040 RETURN_NONE();
4041}
4042
4043static PyObject*
4044DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4045{
4046 int err;
4047 u_int32_t flags=0;
4048 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004049 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004050
4051 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4052 &passwd, &flags)) {
4053 return NULL;
4054 }
4055
4056 MYDB_BEGIN_ALLOW_THREADS;
4057 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4058 MYDB_END_ALLOW_THREADS;
4059
4060 RETURN_IF_ERR();
4061 RETURN_NONE();
4062}
4063#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004064
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004065static PyObject*
4066DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4067{
4068 int err;
4069 u_int32_t flags=0;
4070 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004071 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004072
4073 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4074 &timeout, &flags)) {
4075 return NULL;
4076 }
4077
4078 MYDB_BEGIN_ALLOW_THREADS;
4079 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4080 MYDB_END_ALLOW_THREADS;
4081
4082 RETURN_IF_ERR();
4083 RETURN_NONE();
4084}
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004085
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004086static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004087DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4088{
4089 int err;
4090 long shm_key = 0;
4091
4092 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4093 return NULL;
4094 CHECK_ENV_NOT_CLOSED(self);
4095
4096 err = self->db_env->set_shm_key(self->db_env, shm_key);
4097 RETURN_IF_ERR();
4098 RETURN_NONE();
4099}
4100
4101static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004102DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4103{
4104 int err, gbytes=0, bytes=0, ncache=0;
4105
4106 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4107 &gbytes, &bytes, &ncache))
4108 return NULL;
4109 CHECK_ENV_NOT_CLOSED(self);
4110
4111 MYDB_BEGIN_ALLOW_THREADS;
4112 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4113 MYDB_END_ALLOW_THREADS;
4114 RETURN_IF_ERR();
4115 RETURN_NONE();
4116}
4117
4118
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004119static PyObject*
4120DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4121{
4122 int err, flags=0, onoff=0;
4123
4124 if (!PyArg_ParseTuple(args, "ii:set_flags",
4125 &flags, &onoff))
4126 return NULL;
4127 CHECK_ENV_NOT_CLOSED(self);
4128
4129 MYDB_BEGIN_ALLOW_THREADS;
4130 err = self->db_env->set_flags(self->db_env, flags, onoff);
4131 MYDB_END_ALLOW_THREADS;
4132 RETURN_IF_ERR();
4133 RETURN_NONE();
4134}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004135
4136
Jesus Ceaca3939c2008-05-22 15:27:38 +00004137#if (DBVER >= 47)
4138static PyObject*
4139DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
4140{
4141 int err, flags, onoff;
4142
4143 if (!PyArg_ParseTuple(args, "ii:log_set_config",
4144 &flags, &onoff))
4145 return NULL;
4146 CHECK_ENV_NOT_CLOSED(self);
4147
4148 MYDB_BEGIN_ALLOW_THREADS;
4149 err = self->db_env->log_set_config(self->db_env, flags, onoff);
4150 MYDB_END_ALLOW_THREADS;
4151 RETURN_IF_ERR();
4152 RETURN_NONE();
4153}
4154#endif /* DBVER >= 47 */
4155
4156
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004157static PyObject*
4158DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4159{
4160 int err;
4161 char *dir;
4162
4163 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4164 return NULL;
4165 CHECK_ENV_NOT_CLOSED(self);
4166
4167 MYDB_BEGIN_ALLOW_THREADS;
4168 err = self->db_env->set_data_dir(self->db_env, dir);
4169 MYDB_END_ALLOW_THREADS;
4170 RETURN_IF_ERR();
4171 RETURN_NONE();
4172}
4173
4174
4175static PyObject*
4176DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4177{
4178 int err, lg_bsize;
4179
4180 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4181 return NULL;
4182 CHECK_ENV_NOT_CLOSED(self);
4183
4184 MYDB_BEGIN_ALLOW_THREADS;
4185 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4186 MYDB_END_ALLOW_THREADS;
4187 RETURN_IF_ERR();
4188 RETURN_NONE();
4189}
4190
4191
4192static PyObject*
4193DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4194{
4195 int err;
4196 char *dir;
4197
4198 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4199 return NULL;
4200 CHECK_ENV_NOT_CLOSED(self);
4201
4202 MYDB_BEGIN_ALLOW_THREADS;
4203 err = self->db_env->set_lg_dir(self->db_env, dir);
4204 MYDB_END_ALLOW_THREADS;
4205 RETURN_IF_ERR();
4206 RETURN_NONE();
4207}
4208
4209static PyObject*
4210DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4211{
4212 int err, lg_max;
4213
4214 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4215 return NULL;
4216 CHECK_ENV_NOT_CLOSED(self);
4217
4218 MYDB_BEGIN_ALLOW_THREADS;
4219 err = self->db_env->set_lg_max(self->db_env, lg_max);
4220 MYDB_END_ALLOW_THREADS;
4221 RETURN_IF_ERR();
4222 RETURN_NONE();
4223}
4224
Jesus Ceaef9764f2008-05-13 18:45:46 +00004225#if (DBVER >= 42)
4226static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004227DBEnv_get_lg_max(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004228{
4229 int err;
4230 u_int32_t lg_max;
4231
Jesus Ceaef9764f2008-05-13 18:45:46 +00004232 CHECK_ENV_NOT_CLOSED(self);
4233
4234 MYDB_BEGIN_ALLOW_THREADS;
4235 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4236 MYDB_END_ALLOW_THREADS;
4237 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004238 return NUMBER_FromLong(lg_max);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004239}
4240#endif
4241
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004242
4243static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004244DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4245{
4246 int err, lg_max;
4247
4248 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4249 return NULL;
4250 CHECK_ENV_NOT_CLOSED(self);
4251
4252 MYDB_BEGIN_ALLOW_THREADS;
4253 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4254 MYDB_END_ALLOW_THREADS;
4255 RETURN_IF_ERR();
4256 RETURN_NONE();
4257}
4258
4259
4260static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004261DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4262{
4263 int err, lk_detect;
4264
4265 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4266 return NULL;
4267 CHECK_ENV_NOT_CLOSED(self);
4268
4269 MYDB_BEGIN_ALLOW_THREADS;
4270 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4271 MYDB_END_ALLOW_THREADS;
4272 RETURN_IF_ERR();
4273 RETURN_NONE();
4274}
4275
4276
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004277#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004278static PyObject*
4279DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4280{
4281 int err, max;
4282
4283 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4284 return NULL;
4285 CHECK_ENV_NOT_CLOSED(self);
4286
4287 MYDB_BEGIN_ALLOW_THREADS;
4288 err = self->db_env->set_lk_max(self->db_env, max);
4289 MYDB_END_ALLOW_THREADS;
4290 RETURN_IF_ERR();
4291 RETURN_NONE();
4292}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004293#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004294
4295
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004296
4297static PyObject*
4298DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4299{
4300 int err, max;
4301
4302 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4303 return NULL;
4304 CHECK_ENV_NOT_CLOSED(self);
4305
4306 MYDB_BEGIN_ALLOW_THREADS;
4307 err = self->db_env->set_lk_max_locks(self->db_env, max);
4308 MYDB_END_ALLOW_THREADS;
4309 RETURN_IF_ERR();
4310 RETURN_NONE();
4311}
4312
4313
4314static PyObject*
4315DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4316{
4317 int err, max;
4318
4319 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4320 return NULL;
4321 CHECK_ENV_NOT_CLOSED(self);
4322
4323 MYDB_BEGIN_ALLOW_THREADS;
4324 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4325 MYDB_END_ALLOW_THREADS;
4326 RETURN_IF_ERR();
4327 RETURN_NONE();
4328}
4329
4330
4331static PyObject*
4332DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4333{
4334 int err, max;
4335
4336 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4337 return NULL;
4338 CHECK_ENV_NOT_CLOSED(self);
4339
4340 MYDB_BEGIN_ALLOW_THREADS;
4341 err = self->db_env->set_lk_max_objects(self->db_env, max);
4342 MYDB_END_ALLOW_THREADS;
4343 RETURN_IF_ERR();
4344 RETURN_NONE();
4345}
4346
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004347
4348static PyObject*
4349DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4350{
4351 int err, mp_mmapsize;
4352
4353 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4354 return NULL;
4355 CHECK_ENV_NOT_CLOSED(self);
4356
4357 MYDB_BEGIN_ALLOW_THREADS;
4358 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4359 MYDB_END_ALLOW_THREADS;
4360 RETURN_IF_ERR();
4361 RETURN_NONE();
4362}
4363
4364
4365static PyObject*
4366DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4367{
4368 int err;
4369 char *dir;
4370
4371 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4372 return NULL;
4373 CHECK_ENV_NOT_CLOSED(self);
4374
4375 MYDB_BEGIN_ALLOW_THREADS;
4376 err = self->db_env->set_tmp_dir(self->db_env, dir);
4377 MYDB_END_ALLOW_THREADS;
4378 RETURN_IF_ERR();
4379 RETURN_NONE();
4380}
4381
4382
Jesus Ceaef9764f2008-05-13 18:45:46 +00004383static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004384DBEnv_txn_recover(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004385{
4386 int flags = DB_FIRST;
4387 int err, i;
4388 PyObject *list, *tuple, *gid;
4389 DBTxnObject *txn;
4390#define PREPLIST_LEN 16
4391 DB_PREPLIST preplist[PREPLIST_LEN];
4392 long retp;
4393
Jesus Ceaef9764f2008-05-13 18:45:46 +00004394 CHECK_ENV_NOT_CLOSED(self);
4395
4396 list=PyList_New(0);
4397 if (!list)
4398 return NULL;
4399 while (!0) {
4400 MYDB_BEGIN_ALLOW_THREADS
4401 err=self->db_env->txn_recover(self->db_env,
4402 preplist, PREPLIST_LEN, &retp, flags);
4403#undef PREPLIST_LEN
4404 MYDB_END_ALLOW_THREADS
4405 if (err) {
4406 Py_DECREF(list);
4407 RETURN_IF_ERR();
4408 }
4409 if (!retp) break;
4410 flags=DB_NEXT; /* Prepare for next loop pass */
4411 for (i=0; i<retp; i++) {
Christian Heimes593daf52008-05-26 12:51:38 +00004412 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
Jesus Ceaef9764f2008-05-13 18:45:46 +00004413 DB_XIDDATASIZE);
4414 if (!gid) {
4415 Py_DECREF(list);
4416 return NULL;
4417 }
4418 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4419 if (!txn) {
4420 Py_DECREF(list);
4421 Py_DECREF(gid);
4422 return NULL;
4423 }
4424 txn->flag_prepare=1; /* Recover state */
4425 tuple=PyTuple_New(2);
4426 if (!tuple) {
4427 Py_DECREF(list);
4428 Py_DECREF(gid);
4429 Py_DECREF(txn);
4430 return NULL;
4431 }
4432 if (PyTuple_SetItem(tuple, 0, gid)) {
4433 Py_DECREF(list);
4434 Py_DECREF(gid);
4435 Py_DECREF(txn);
4436 Py_DECREF(tuple);
4437 return NULL;
4438 }
4439 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4440 Py_DECREF(list);
4441 Py_DECREF(txn);
4442 Py_DECREF(tuple); /* This delete the "gid" also */
4443 return NULL;
4444 }
4445 if (PyList_Append(list, tuple)) {
4446 Py_DECREF(list);
4447 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4448 return NULL;
4449 }
4450 Py_DECREF(tuple);
4451 }
4452 }
4453 return list;
4454}
Jesus Ceaef9764f2008-05-13 18:45:46 +00004455
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004456static PyObject*
4457DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4458{
4459 int flags = 0;
4460 PyObject* txnobj = NULL;
4461 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004462 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004463
4464 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4465 &txnobj, &flags))
4466 return NULL;
4467
4468 if (!checkTxnObj(txnobj, &txn))
4469 return NULL;
4470 CHECK_ENV_NOT_CLOSED(self);
4471
Jesus Ceaef9764f2008-05-13 18:45:46 +00004472 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004473}
4474
4475
4476static PyObject*
4477DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4478{
4479 int err, kbyte=0, min=0, flags=0;
4480
4481 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4482 return NULL;
4483 CHECK_ENV_NOT_CLOSED(self);
4484
4485 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004486 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004487 MYDB_END_ALLOW_THREADS;
4488 RETURN_IF_ERR();
4489 RETURN_NONE();
4490}
4491
4492
4493static PyObject*
4494DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4495{
4496 int err, max;
4497
4498 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4499 return NULL;
4500 CHECK_ENV_NOT_CLOSED(self);
4501
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004502 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004503 RETURN_IF_ERR();
4504 RETURN_NONE();
4505}
4506
4507
4508static PyObject*
4509DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4510{
4511 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004512 long stamp;
4513 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004514
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004515 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004516 return NULL;
4517 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004518 timestamp = (time_t)stamp;
4519 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004520 RETURN_IF_ERR();
4521 RETURN_NONE();
4522}
4523
4524
4525static PyObject*
4526DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4527{
4528 int err, atype, flags=0;
4529 int aborted = 0;
4530
4531 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4532 return NULL;
4533 CHECK_ENV_NOT_CLOSED(self);
4534
4535 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004536 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004537 MYDB_END_ALLOW_THREADS;
4538 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004539 return NUMBER_FromLong(aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004540}
4541
4542
4543static PyObject*
4544DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4545{
4546 int flags=0;
4547 int locker, lock_mode;
4548 DBT obj;
4549 PyObject* objobj;
4550
4551 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4552 return NULL;
4553
4554
4555 if (!make_dbt(objobj, &obj))
4556 return NULL;
4557
4558 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4559}
4560
4561
4562static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004563DBEnv_lock_id(DBEnvObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004564{
4565 int err;
4566 u_int32_t theID;
4567
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004568 CHECK_ENV_NOT_CLOSED(self);
4569 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004570 err = self->db_env->lock_id(self->db_env, &theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004571 MYDB_END_ALLOW_THREADS;
4572 RETURN_IF_ERR();
4573
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004574 return NUMBER_FromLong((long)theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004575}
4576
Gregory P. Smithac11e022007-11-05 02:56:31 +00004577static PyObject*
4578DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4579{
4580 int err;
4581 u_int32_t theID;
4582
4583 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4584 return NULL;
4585
4586 CHECK_ENV_NOT_CLOSED(self);
4587 MYDB_BEGIN_ALLOW_THREADS;
4588 err = self->db_env->lock_id_free(self->db_env, theID);
4589 MYDB_END_ALLOW_THREADS;
4590 RETURN_IF_ERR();
4591 RETURN_NONE();
4592}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004593
4594static PyObject*
4595DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4596{
4597 int err;
4598 DBLockObject* dblockobj;
4599
4600 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4601 return NULL;
4602
4603 CHECK_ENV_NOT_CLOSED(self);
4604 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004605 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004606 MYDB_END_ALLOW_THREADS;
4607 RETURN_IF_ERR();
4608 RETURN_NONE();
4609}
4610
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004611#if (DBVER >= 44)
4612static PyObject*
4613DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4614{
4615 int err;
4616 char *file;
4617 u_int32_t flags = 0;
4618 static char* kwnames[] = { "file", "flags", NULL};
4619
4620 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4621 &file, &flags))
4622 return NULL;
4623 CHECK_ENV_NOT_CLOSED(self);
4624
4625 MYDB_BEGIN_ALLOW_THREADS;
4626 err = self->db_env->lsn_reset(self->db_env, file, flags);
4627 MYDB_END_ALLOW_THREADS;
4628 RETURN_IF_ERR();
4629 RETURN_NONE();
4630}
4631#endif /* DBVER >= 4.4 */
4632
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004633static PyObject*
4634DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4635{
4636 int err;
4637 DB_LOG_STAT* statp = NULL;
4638 PyObject* d = NULL;
4639 u_int32_t flags = 0;
4640
4641 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4642 return NULL;
4643 CHECK_ENV_NOT_CLOSED(self);
4644
4645 MYDB_BEGIN_ALLOW_THREADS;
4646 err = self->db_env->log_stat(self->db_env, &statp, flags);
4647 MYDB_END_ALLOW_THREADS;
4648 RETURN_IF_ERR();
4649
4650 /* Turn the stat structure into a dictionary */
4651 d = PyDict_New();
4652 if (d == NULL) {
4653 if (statp)
4654 free(statp);
4655 return NULL;
4656 }
4657
4658#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4659
4660 MAKE_ENTRY(magic);
4661 MAKE_ENTRY(version);
4662 MAKE_ENTRY(mode);
4663 MAKE_ENTRY(lg_bsize);
4664#if (DBVER >= 44)
4665 MAKE_ENTRY(lg_size);
4666 MAKE_ENTRY(record);
4667#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004668#if (DBVER < 41)
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004669 MAKE_ENTRY(lg_max);
4670#endif
4671 MAKE_ENTRY(w_mbytes);
4672 MAKE_ENTRY(w_bytes);
4673 MAKE_ENTRY(wc_mbytes);
4674 MAKE_ENTRY(wc_bytes);
4675 MAKE_ENTRY(wcount);
4676 MAKE_ENTRY(wcount_fill);
4677#if (DBVER >= 44)
4678 MAKE_ENTRY(rcount);
4679#endif
4680 MAKE_ENTRY(scount);
4681 MAKE_ENTRY(cur_file);
4682 MAKE_ENTRY(cur_offset);
4683 MAKE_ENTRY(disk_file);
4684 MAKE_ENTRY(disk_offset);
4685 MAKE_ENTRY(maxcommitperflush);
4686 MAKE_ENTRY(mincommitperflush);
4687 MAKE_ENTRY(regsize);
4688 MAKE_ENTRY(region_wait);
4689 MAKE_ENTRY(region_nowait);
4690
4691#undef MAKE_ENTRY
4692 free(statp);
4693 return d;
4694} /* DBEnv_log_stat */
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004695
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004696
4697static PyObject*
4698DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4699{
4700 int err;
4701 DB_LOCK_STAT* sp;
4702 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004703 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004704
4705 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4706 return NULL;
4707 CHECK_ENV_NOT_CLOSED(self);
4708
4709 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004710 err = self->db_env->lock_stat(self->db_env, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004711 MYDB_END_ALLOW_THREADS;
4712 RETURN_IF_ERR();
4713
4714 /* Turn the stat structure into a dictionary */
4715 d = PyDict_New();
4716 if (d == NULL) {
4717 free(sp);
4718 return NULL;
4719 }
4720
4721#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4722
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004723#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004724 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004725#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004726#if (DBVER >=41)
4727 MAKE_ENTRY(id);
4728 MAKE_ENTRY(cur_maxid);
4729#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004730 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004731 MAKE_ENTRY(maxlocks);
4732 MAKE_ENTRY(maxlockers);
4733 MAKE_ENTRY(maxobjects);
4734 MAKE_ENTRY(nlocks);
4735 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004736 MAKE_ENTRY(nlockers);
4737 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004738 MAKE_ENTRY(nobjects);
4739 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004740 MAKE_ENTRY(nrequests);
4741 MAKE_ENTRY(nreleases);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004742#if (DBVER >= 44)
4743 MAKE_ENTRY(nupgrade);
4744 MAKE_ENTRY(ndowngrade);
4745#endif
Gregory P. Smith29602d22006-01-24 09:46:48 +00004746#if (DBVER < 44)
4747 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004748 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004749#else
4750 MAKE_ENTRY(lock_nowait);
4751 MAKE_ENTRY(lock_wait);
4752#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004753 MAKE_ENTRY(ndeadlocks);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004754#if (DBVER >= 41)
4755 MAKE_ENTRY(locktimeout);
4756 MAKE_ENTRY(txntimeout);
4757#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004758 MAKE_ENTRY(nlocktimeouts);
4759 MAKE_ENTRY(ntxntimeouts);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004760#if (DBVER >= 46)
4761 MAKE_ENTRY(objs_wait);
4762 MAKE_ENTRY(objs_nowait);
4763 MAKE_ENTRY(lockers_wait);
4764 MAKE_ENTRY(lockers_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004765#if (DBVER >= 47)
4766 MAKE_ENTRY(lock_wait);
4767 MAKE_ENTRY(lock_nowait);
4768#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00004769 MAKE_ENTRY(locks_wait);
4770 MAKE_ENTRY(locks_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004771#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004772 MAKE_ENTRY(hash_len);
4773#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004774 MAKE_ENTRY(regsize);
4775 MAKE_ENTRY(region_wait);
4776 MAKE_ENTRY(region_nowait);
4777
4778#undef MAKE_ENTRY
4779 free(sp);
4780 return d;
4781}
4782
Jesus Ceaef9764f2008-05-13 18:45:46 +00004783static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004784DBEnv_log_flush(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004785{
4786 int err;
4787
Jesus Ceaef9764f2008-05-13 18:45:46 +00004788 CHECK_ENV_NOT_CLOSED(self);
4789
4790 MYDB_BEGIN_ALLOW_THREADS
4791 err = self->db_env->log_flush(self->db_env, NULL);
4792 MYDB_END_ALLOW_THREADS
4793
4794 RETURN_IF_ERR();
4795 RETURN_NONE();
4796}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004797
4798static PyObject*
4799DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4800{
4801 int flags=0;
4802 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004803 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004804 PyObject* list;
4805 PyObject* item = NULL;
4806
4807 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4808 return NULL;
4809
4810 CHECK_ENV_NOT_CLOSED(self);
4811 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004812 err = self->db_env->log_archive(self->db_env, &log_list, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004813 MYDB_END_ALLOW_THREADS;
4814 RETURN_IF_ERR();
4815
Gregory P. Smithbad47452006-06-05 00:33:35 +00004816 list = PyList_New(0);
4817 if (list == NULL) {
4818 if (log_list)
4819 free(log_list);
4820 return NULL;
4821 }
4822
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004823 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004824 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004825 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Christian Heimes593daf52008-05-26 12:51:38 +00004826 item = PyBytes_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004827 if (item == NULL) {
4828 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004829 list = NULL;
4830 break;
4831 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004832 if (PyList_Append(list, item)) {
4833 Py_DECREF(list);
4834 list = NULL;
4835 Py_DECREF(item);
4836 break;
4837 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004838 Py_DECREF(item);
4839 }
4840 free(log_list_start);
4841 }
4842 return list;
4843}
4844
4845
4846static PyObject*
4847DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4848{
4849 int err;
4850 DB_TXN_STAT* sp;
4851 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004852 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004853
4854 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4855 return NULL;
4856 CHECK_ENV_NOT_CLOSED(self);
4857
4858 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004859 err = self->db_env->txn_stat(self->db_env, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004860 MYDB_END_ALLOW_THREADS;
4861 RETURN_IF_ERR();
4862
4863 /* Turn the stat structure into a dictionary */
4864 d = PyDict_New();
4865 if (d == NULL) {
4866 free(sp);
4867 return NULL;
4868 }
4869
Jesus Ceaef9764f2008-05-13 18:45:46 +00004870#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4871#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4872#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004873
Jesus Ceaef9764f2008-05-13 18:45:46 +00004874 MAKE_DB_LSN_ENTRY(last_ckp);
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004875 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004876 MAKE_ENTRY(last_txnid);
4877 MAKE_ENTRY(maxtxns);
4878 MAKE_ENTRY(nactive);
4879 MAKE_ENTRY(maxnactive);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004880#if (DBVER >= 45)
4881 MAKE_ENTRY(nsnapshot);
4882 MAKE_ENTRY(maxnsnapshot);
4883#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004884 MAKE_ENTRY(nbegins);
4885 MAKE_ENTRY(naborts);
4886 MAKE_ENTRY(ncommits);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004887 MAKE_ENTRY(nrestores);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004888 MAKE_ENTRY(regsize);
4889 MAKE_ENTRY(region_wait);
4890 MAKE_ENTRY(region_nowait);
4891
Jesus Ceaef9764f2008-05-13 18:45:46 +00004892#undef MAKE_DB_LSN_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004893#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004894#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004895 free(sp);
4896 return d;
4897}
4898
4899
4900static PyObject*
4901DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4902{
4903 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004904 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004905
4906 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4907 return NULL;
4908 CHECK_ENV_NOT_CLOSED(self);
4909
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004910 if (self->moduleFlags.getReturnsNone)
4911 ++oldValue;
4912 if (self->moduleFlags.cursorSetReturnsNone)
4913 ++oldValue;
4914 self->moduleFlags.getReturnsNone = (flags >= 1);
4915 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004916 return NUMBER_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004917}
4918
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004919static PyObject*
4920DBEnv_get_private(DBEnvObject* self)
4921{
4922 /* We can give out the private field even if dbenv is closed */
4923 Py_INCREF(self->private);
4924 return self->private;
4925}
4926
4927static PyObject*
4928DBEnv_set_private(DBEnvObject* self, PyObject* private)
4929{
4930 /* We can set the private field even if dbenv is closed */
4931 Py_DECREF(self->private);
4932 Py_INCREF(private);
4933 self->private = private;
4934 RETURN_NONE();
4935}
4936
4937
Jesus Ceaef9764f2008-05-13 18:45:46 +00004938static PyObject*
Jesus Ceaca3939c2008-05-22 15:27:38 +00004939DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4940{
4941 int err;
4942 char *host;
4943 long cl_timeout=0, sv_timeout=0;
4944
4945 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
4946
4947 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
4948 &host, &cl_timeout, &sv_timeout))
4949 return NULL;
4950 CHECK_ENV_NOT_CLOSED(self);
4951
4952 MYDB_BEGIN_ALLOW_THREADS;
4953 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
4954 sv_timeout, 0);
4955 MYDB_END_ALLOW_THREADS;
4956 RETURN_IF_ERR();
4957 RETURN_NONE();
4958}
Jesus Ceaca3939c2008-05-22 15:27:38 +00004959
Jesus Ceaca3939c2008-05-22 15:27:38 +00004960static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00004961DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
4962{
4963 int err;
4964 int which, onoff;
4965
4966 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
4967 return NULL;
4968 }
4969 CHECK_ENV_NOT_CLOSED(self);
4970 MYDB_BEGIN_ALLOW_THREADS;
4971 err = self->db_env->set_verbose(self->db_env, which, onoff);
4972 MYDB_END_ALLOW_THREADS;
4973 RETURN_IF_ERR();
4974 RETURN_NONE();
4975}
4976
4977#if (DBVER >= 42)
4978static PyObject*
4979DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
4980{
4981 int err;
4982 int which;
4983 int verbose;
4984
4985 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
4986 return NULL;
4987 }
4988 CHECK_ENV_NOT_CLOSED(self);
4989 MYDB_BEGIN_ALLOW_THREADS;
4990 err = self->db_env->get_verbose(self->db_env, which, &verbose);
4991 MYDB_END_ALLOW_THREADS;
4992 RETURN_IF_ERR();
4993 return PyBool_FromLong(verbose);
4994}
4995#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004996
4997#if (DBVER >= 45)
4998static void
4999_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
5000{
5001 DBEnvObject *dbenv;
5002 PyObject* callback;
5003 PyObject* args;
5004 PyObject* result = NULL;
5005
5006 MYDB_BEGIN_BLOCK_THREADS;
5007 dbenv = (DBEnvObject *)db_env->app_private;
5008 callback = dbenv->event_notifyCallback;
5009 if (callback) {
5010 if (event == DB_EVENT_REP_NEWMASTER) {
5011 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
5012 } else {
5013 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5014 }
5015 if (args) {
5016 result = PyEval_CallObject(callback, args);
5017 }
5018 if ((!args) || (!result)) {
5019 PyErr_Print();
5020 }
5021 Py_XDECREF(args);
5022 Py_XDECREF(result);
5023 }
5024 MYDB_END_BLOCK_THREADS;
5025}
5026#endif
5027
5028#if (DBVER >= 45)
5029static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005030DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005031{
5032 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005033
5034 CHECK_ENV_NOT_CLOSED(self);
5035
5036 if (!PyCallable_Check(notifyFunc)) {
5037 makeTypeError("Callable", notifyFunc);
5038 return NULL;
5039 }
5040
5041 Py_XDECREF(self->event_notifyCallback);
5042 Py_INCREF(notifyFunc);
5043 self->event_notifyCallback = notifyFunc;
5044
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005045 /* This is to workaround a problem with un-initialized threads (see
5046 comment in DB_associate) */
5047#ifdef WITH_THREAD
5048 PyEval_InitThreads();
5049#endif
5050
Jesus Ceaef9764f2008-05-13 18:45:46 +00005051 MYDB_BEGIN_ALLOW_THREADS;
5052 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5053 MYDB_END_ALLOW_THREADS;
5054
5055 if (err) {
5056 Py_DECREF(notifyFunc);
5057 self->event_notifyCallback = NULL;
5058 }
5059
5060 RETURN_IF_ERR();
5061 RETURN_NONE();
5062}
5063#endif
5064
5065
5066/* --------------------------------------------------------------------- */
5067/* REPLICATION METHODS: Base Replication */
5068
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005069
5070static PyObject*
5071DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
5072{
5073 int err;
5074 PyObject *control_py, *rec_py;
5075 DBT control, rec;
5076 int envid;
5077#if (DBVER >= 42)
5078 DB_LSN lsn;
5079#endif
5080
5081 if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
5082 &rec_py, &envid))
5083 return NULL;
5084 CHECK_ENV_NOT_CLOSED(self);
5085
5086 if (!make_dbt(control_py, &control))
5087 return NULL;
5088 if (!make_dbt(rec_py, &rec))
5089 return NULL;
5090
5091 MYDB_BEGIN_ALLOW_THREADS;
5092#if (DBVER >= 46)
5093 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5094 envid, &lsn);
5095#else
5096#if (DBVER >= 42)
5097 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5098 &envid, &lsn);
5099#else
5100 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5101 &envid);
5102#endif
5103#endif
5104 MYDB_END_ALLOW_THREADS;
5105 switch (err) {
5106 case DB_REP_NEWMASTER :
5107 return Py_BuildValue("(iO)", envid, Py_None);
5108 break;
5109
5110 case DB_REP_DUPMASTER :
5111 case DB_REP_HOLDELECTION :
5112#if (DBVER >= 44)
5113 case DB_REP_IGNORE :
5114 case DB_REP_JOIN_FAILURE :
5115#endif
5116 return Py_BuildValue("(iO)", err, Py_None);
5117 break;
5118 case DB_REP_NEWSITE :
5119 return Py_BuildValue("(is#)", err, rec.data, rec.size);
5120 break;
5121#if (DBVER >= 42)
5122 case DB_REP_NOTPERM :
5123 case DB_REP_ISPERM :
5124 return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
5125 break;
5126#endif
5127 }
5128 RETURN_IF_ERR();
5129 return Py_BuildValue("(OO)", Py_None, Py_None);
5130}
5131
5132static int
5133_DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
5134 const DB_LSN *lsn, int envid, u_int32_t flags)
5135{
5136 DBEnvObject *dbenv;
5137 PyObject* rep_transport;
5138 PyObject* args;
5139 PyObject* result = NULL;
5140 int ret=0;
5141
5142 MYDB_BEGIN_BLOCK_THREADS;
5143 dbenv = (DBEnvObject *)db_env->app_private;
5144 rep_transport = dbenv->rep_transport;
5145
5146 args = Py_BuildValue(
5147#if (PY_VERSION_HEX >= 0x02040000)
5148 "(Os#s#(ll)iI)",
5149#else
5150 "(Os#s#(ll)ii)",
5151#endif
5152 dbenv,
5153 control->data, control->size,
5154 rec->data, rec->size, lsn->file, lsn->offset, envid, flags);
5155 if (args) {
5156 result = PyEval_CallObject(rep_transport, args);
5157 }
5158
5159 if ((!args) || (!result)) {
5160 PyErr_Print();
5161 ret = -1;
5162 }
5163 Py_XDECREF(args);
5164 Py_XDECREF(result);
5165 MYDB_END_BLOCK_THREADS;
5166 return ret;
5167}
5168
5169#if (DBVER <= 41)
5170static int
5171_DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec,
5172 int envid, u_int32_t flags)
5173{
5174 DB_LSN lsn;
5175
5176 lsn.file = -1; /* Dummy values */
5177 lsn.offset = -1;
5178 return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid,
5179 flags);
5180}
5181#endif
5182
5183static PyObject*
5184DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
5185{
5186 int err;
5187 int envid;
5188 PyObject *rep_transport;
5189
5190 if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
5191 return NULL;
5192 CHECK_ENV_NOT_CLOSED(self);
5193 if (!PyCallable_Check(rep_transport)) {
5194 makeTypeError("Callable", rep_transport);
5195 return NULL;
5196 }
5197
5198 MYDB_BEGIN_ALLOW_THREADS;
5199#if (DBVER >=45)
5200 err = self->db_env->rep_set_transport(self->db_env, envid,
5201 &_DBEnv_rep_transportCallback);
5202#else
5203#if (DBVER >= 42)
5204 err = self->db_env->set_rep_transport(self->db_env, envid,
5205 &_DBEnv_rep_transportCallback);
5206#else
5207 err = self->db_env->set_rep_transport(self->db_env, envid,
5208 &_DBEnv_rep_transportCallbackOLD);
5209#endif
5210#endif
5211 MYDB_END_ALLOW_THREADS;
5212 RETURN_IF_ERR();
5213
5214 Py_DECREF(self->rep_transport);
5215 Py_INCREF(rep_transport);
5216 self->rep_transport = rep_transport;
5217 RETURN_NONE();
5218}
5219
5220#if (DBVER >= 47)
5221static PyObject*
5222DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
5223{
5224 int err;
5225 unsigned int minimum, maximum;
5226
5227 if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
5228 return NULL;
5229 CHECK_ENV_NOT_CLOSED(self);
5230
5231 MYDB_BEGIN_ALLOW_THREADS;
5232 err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
5233 MYDB_END_ALLOW_THREADS;
5234 RETURN_IF_ERR();
5235 RETURN_NONE();
5236}
5237
5238static PyObject*
5239DBEnv_rep_get_request(DBEnvObject* self)
5240{
5241 int err;
5242 u_int32_t minimum, maximum;
5243
5244 CHECK_ENV_NOT_CLOSED(self);
5245 MYDB_BEGIN_ALLOW_THREADS;
5246 err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
5247 MYDB_END_ALLOW_THREADS;
5248 RETURN_IF_ERR();
5249#if (PY_VERSION_HEX >= 0x02040000)
5250 return Py_BuildValue("II", minimum, maximum);
5251#else
5252 return Py_BuildValue("ii", minimum, maximum);
5253#endif
5254}
5255#endif
5256
5257#if (DBVER >= 45)
5258static PyObject*
5259DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
5260{
5261 int err;
5262 int limit;
5263
5264 if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
5265 return NULL;
5266 CHECK_ENV_NOT_CLOSED(self);
5267
5268 MYDB_BEGIN_ALLOW_THREADS;
5269 err = self->db_env->rep_set_limit(self->db_env, 0, limit);
5270 MYDB_END_ALLOW_THREADS;
5271 RETURN_IF_ERR();
5272 RETURN_NONE();
5273}
5274
5275static PyObject*
5276DBEnv_rep_get_limit(DBEnvObject* self)
5277{
5278 int err;
5279 u_int32_t gbytes, bytes;
5280
5281 CHECK_ENV_NOT_CLOSED(self);
5282 MYDB_BEGIN_ALLOW_THREADS;
5283 err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
5284 MYDB_END_ALLOW_THREADS;
5285 RETURN_IF_ERR();
5286 return NUMBER_FromLong(bytes);
5287}
5288#endif
5289
5290#if (DBVER >= 44)
5291static PyObject*
5292DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
5293{
5294 int err;
5295 int which;
5296 int onoff;
5297
5298 if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
5299 return NULL;
5300 CHECK_ENV_NOT_CLOSED(self);
5301
5302 MYDB_BEGIN_ALLOW_THREADS;
5303 err = self->db_env->rep_set_config(self->db_env, which, onoff);
5304 MYDB_END_ALLOW_THREADS;
5305 RETURN_IF_ERR();
5306 RETURN_NONE();
5307}
5308
5309static PyObject*
5310DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
5311{
5312 int err;
5313 int which;
5314 int onoff;
5315
5316 if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
5317 return NULL;
5318 }
5319 CHECK_ENV_NOT_CLOSED(self);
5320 MYDB_BEGIN_ALLOW_THREADS;
5321 err = self->db_env->rep_get_config(self->db_env, which, &onoff);
5322 MYDB_END_ALLOW_THREADS;
5323 RETURN_IF_ERR();
5324 return PyBool_FromLong(onoff);
5325}
5326#endif
5327
5328#if (DBVER >= 46)
5329static PyObject*
5330DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
5331{
5332 int err;
5333 u_int32_t nsites, nvotes;
5334
5335 if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
5336 return NULL;
5337 }
5338 CHECK_ENV_NOT_CLOSED(self);
5339 MYDB_BEGIN_ALLOW_THREADS;
5340 err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0);
5341 MYDB_END_ALLOW_THREADS;
5342 RETURN_IF_ERR();
5343 RETURN_NONE();
5344}
5345#endif
5346
5347static PyObject*
5348DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5349{
5350 int err;
5351 PyObject *cdata_py = Py_None;
5352 DBT cdata;
5353 int flags;
5354 static char* kwnames[] = {"flags","cdata", NULL};
5355
5356 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5357 "i|O:rep_start", kwnames, &flags, &cdata_py))
5358 {
5359 return NULL;
5360 }
5361 CHECK_ENV_NOT_CLOSED(self);
5362
5363 if (!make_dbt(cdata_py, &cdata))
5364 return NULL;
5365
5366 MYDB_BEGIN_ALLOW_THREADS;
5367 err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
5368 flags);
5369 MYDB_END_ALLOW_THREADS;
5370 RETURN_IF_ERR();
5371 RETURN_NONE();
5372}
5373
5374#if (DBVER >= 44)
5375static PyObject*
5376DBEnv_rep_sync(DBEnvObject* self)
5377{
5378 int err;
5379
5380 CHECK_ENV_NOT_CLOSED(self);
5381 MYDB_BEGIN_ALLOW_THREADS;
5382 err = self->db_env->rep_sync(self->db_env, 0);
5383 MYDB_END_ALLOW_THREADS;
5384 RETURN_IF_ERR();
5385 RETURN_NONE();
5386}
5387#endif
5388
5389
Jesus Ceaef9764f2008-05-13 18:45:46 +00005390#if (DBVER >= 45)
5391static PyObject*
5392DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5393{
5394 int err;
5395 int nsites;
5396
5397 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5398 return NULL;
5399 }
5400 CHECK_ENV_NOT_CLOSED(self);
5401 MYDB_BEGIN_ALLOW_THREADS;
5402 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5403 MYDB_END_ALLOW_THREADS;
5404 RETURN_IF_ERR();
5405 RETURN_NONE();
5406}
5407
5408static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005409DBEnv_rep_get_nsites(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005410{
5411 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005412#if (DBVER >= 47)
5413 u_int32_t nsites;
5414#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005415 int nsites;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005416#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005417
Jesus Ceaef9764f2008-05-13 18:45:46 +00005418 CHECK_ENV_NOT_CLOSED(self);
5419 MYDB_BEGIN_ALLOW_THREADS;
5420 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5421 MYDB_END_ALLOW_THREADS;
5422 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005423 return NUMBER_FromLong(nsites);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005424}
5425
5426static PyObject*
5427DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5428{
5429 int err;
5430 int priority;
5431
5432 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5433 return NULL;
5434 }
5435 CHECK_ENV_NOT_CLOSED(self);
5436 MYDB_BEGIN_ALLOW_THREADS;
5437 err = self->db_env->rep_set_priority(self->db_env, priority);
5438 MYDB_END_ALLOW_THREADS;
5439 RETURN_IF_ERR();
5440 RETURN_NONE();
5441}
5442
5443static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005444DBEnv_rep_get_priority(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005445{
5446 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005447#if (DBVER >= 47)
5448 u_int32_t priority;
5449#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005450 int priority;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005451#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005452
Jesus Ceaef9764f2008-05-13 18:45:46 +00005453 CHECK_ENV_NOT_CLOSED(self);
5454 MYDB_BEGIN_ALLOW_THREADS;
5455 err = self->db_env->rep_get_priority(self->db_env, &priority);
5456 MYDB_END_ALLOW_THREADS;
5457 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005458 return NUMBER_FromLong(priority);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005459}
5460
5461static PyObject*
5462DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5463{
5464 int err;
5465 int which, timeout;
5466
5467 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5468 return NULL;
5469 }
5470 CHECK_ENV_NOT_CLOSED(self);
5471 MYDB_BEGIN_ALLOW_THREADS;
5472 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5473 MYDB_END_ALLOW_THREADS;
5474 RETURN_IF_ERR();
5475 RETURN_NONE();
5476}
5477
5478static PyObject*
5479DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5480{
5481 int err;
5482 int which;
5483 u_int32_t timeout;
5484
5485 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5486 return NULL;
5487 }
5488 CHECK_ENV_NOT_CLOSED(self);
5489 MYDB_BEGIN_ALLOW_THREADS;
5490 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5491 MYDB_END_ALLOW_THREADS;
5492 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005493 return NUMBER_FromLong(timeout);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005494}
5495#endif
5496
5497/* --------------------------------------------------------------------- */
5498/* REPLICATION METHODS: Replication Manager */
5499
5500#if (DBVER >= 45)
5501static PyObject*
5502DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5503 kwargs)
5504{
5505 int err;
5506 int nthreads, flags;
5507 static char* kwnames[] = {"nthreads","flags", NULL};
5508
5509 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5510 "ii:repmgr_start", kwnames, &nthreads, &flags))
5511 {
5512 return NULL;
5513 }
5514 CHECK_ENV_NOT_CLOSED(self);
5515 MYDB_BEGIN_ALLOW_THREADS;
5516 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5517 MYDB_END_ALLOW_THREADS;
5518 RETURN_IF_ERR();
5519 RETURN_NONE();
5520}
5521
5522static PyObject*
5523DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5524 kwargs)
5525{
5526 int err;
5527 char *host;
5528 int port;
5529 int flags = 0;
5530 static char* kwnames[] = {"host", "port", "flags", NULL};
5531
5532 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5533 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5534 {
5535 return NULL;
5536 }
5537 CHECK_ENV_NOT_CLOSED(self);
5538 MYDB_BEGIN_ALLOW_THREADS;
5539 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5540 MYDB_END_ALLOW_THREADS;
5541 RETURN_IF_ERR();
5542 RETURN_NONE();
5543}
5544
5545static PyObject*
5546DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5547 kwargs)
5548{
5549 int err;
5550 char *host;
5551 int port;
5552 int flags = 0;
5553 int eidp;
5554 static char* kwnames[] = {"host", "port", "flags", NULL};
5555
5556 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5557 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5558 {
5559 return NULL;
5560 }
5561 CHECK_ENV_NOT_CLOSED(self);
5562 MYDB_BEGIN_ALLOW_THREADS;
5563 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5564 MYDB_END_ALLOW_THREADS;
5565 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005566 return NUMBER_FromLong(eidp);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005567}
5568
5569static PyObject*
5570DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5571{
5572 int err;
5573 int ack_policy;
5574
5575 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5576 {
5577 return NULL;
5578 }
5579 CHECK_ENV_NOT_CLOSED(self);
5580 MYDB_BEGIN_ALLOW_THREADS;
5581 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5582 MYDB_END_ALLOW_THREADS;
5583 RETURN_IF_ERR();
5584 RETURN_NONE();
5585}
5586
5587static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005588DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005589{
5590 int err;
5591 int ack_policy;
5592
Jesus Ceaef9764f2008-05-13 18:45:46 +00005593 CHECK_ENV_NOT_CLOSED(self);
5594 MYDB_BEGIN_ALLOW_THREADS;
5595 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5596 MYDB_END_ALLOW_THREADS;
5597 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005598 return NUMBER_FromLong(ack_policy);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005599}
5600
5601static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005602DBEnv_repmgr_site_list(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005603{
5604 int err;
5605 unsigned int countp;
5606 DB_REPMGR_SITE *listp;
5607 PyObject *stats, *key, *tuple;
5608
Jesus Ceaef9764f2008-05-13 18:45:46 +00005609 CHECK_ENV_NOT_CLOSED(self);
5610 MYDB_BEGIN_ALLOW_THREADS;
5611 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5612 MYDB_END_ALLOW_THREADS;
5613 RETURN_IF_ERR();
5614
5615 stats=PyDict_New();
5616 if (stats == NULL) {
5617 free(listp);
5618 return NULL;
5619 }
5620
5621 for(;countp--;) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005622 key=NUMBER_FromLong(listp[countp].eid);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005623 if(!key) {
5624 Py_DECREF(stats);
5625 free(listp);
5626 return NULL;
5627 }
5628#if (PY_VERSION_HEX >= 0x02040000)
5629 tuple=Py_BuildValue("(sII)", listp[countp].host,
5630 listp[countp].port, listp[countp].status);
5631#else
5632 tuple=Py_BuildValue("(sii)", listp[countp].host,
5633 listp[countp].port, listp[countp].status);
5634#endif
5635 if(!tuple) {
5636 Py_DECREF(key);
5637 Py_DECREF(stats);
5638 free(listp);
5639 return NULL;
5640 }
5641 if(PyDict_SetItem(stats, key, tuple)) {
5642 Py_DECREF(key);
5643 Py_DECREF(tuple);
5644 Py_DECREF(stats);
5645 free(listp);
5646 return NULL;
5647 }
5648 }
5649 free(listp);
5650 return stats;
5651}
5652#endif
5653
5654#if (DBVER >= 46)
5655static PyObject*
5656DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5657{
5658 int err;
5659 int flags=0;
5660 static char* kwnames[] = { "flags", NULL };
5661
5662 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5663 kwnames, &flags))
5664 {
5665 return NULL;
5666 }
5667 CHECK_ENV_NOT_CLOSED(self);
5668 MYDB_BEGIN_ALLOW_THREADS;
5669 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5670 MYDB_END_ALLOW_THREADS;
5671 RETURN_IF_ERR();
5672 RETURN_NONE();
5673}
5674
5675static PyObject*
5676DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5677{
5678 int err;
5679 int flags=0;
5680 DB_REPMGR_STAT *statp;
5681 PyObject *stats;
5682 static char* kwnames[] = { "flags", NULL };
5683
5684 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5685 kwnames, &flags))
5686 {
5687 return NULL;
5688 }
5689 CHECK_ENV_NOT_CLOSED(self);
5690 MYDB_BEGIN_ALLOW_THREADS;
5691 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5692 MYDB_END_ALLOW_THREADS;
5693 RETURN_IF_ERR();
5694
5695 stats=PyDict_New();
5696 if (stats == NULL) {
5697 free(statp);
5698 return NULL;
5699 }
5700
5701#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5702
5703 MAKE_ENTRY(perm_failed);
5704 MAKE_ENTRY(msgs_queued);
5705 MAKE_ENTRY(msgs_dropped);
5706 MAKE_ENTRY(connection_drop);
5707 MAKE_ENTRY(connect_fail);
5708
5709#undef MAKE_ENTRY
5710
5711 free(statp);
5712 return stats;
5713}
5714#endif
5715
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005716
5717/* --------------------------------------------------------------------- */
5718/* DBTxn methods */
5719
5720
Jesus Ceaef9764f2008-05-13 18:45:46 +00005721static void _close_transaction_cursors(DBTxnObject* txn)
5722{
5723 PyObject *dummy;
5724
5725 while(txn->children_cursors) {
5726 PyErr_Warn(PyExc_RuntimeWarning,
5727 "Must close cursors before resolving a transaction.");
5728 dummy=DBC_close_internal(txn->children_cursors);
5729 Py_XDECREF(dummy);
5730 }
5731}
5732
5733static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5734{
5735 DBObject *db;
5736#if (DBVER >= 43)
5737 DBSequenceObject *dbs;
5738#endif
5739
5740 while (txn->children_dbs) {
5741 db=txn->children_dbs;
5742 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5743 if (txn->parent_txn) {
5744 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5745 db->txn=txn->parent_txn;
5746 } else {
5747 /* The db is already linked to its environment,
5748 ** so nothing to do.
5749 */
5750 db->txn=NULL;
5751 }
5752 }
5753
5754#if (DBVER >= 43)
5755 while (txn->children_sequences) {
5756 dbs=txn->children_sequences;
5757 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5758 if (txn->parent_txn) {
5759 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5760 dbs->txn=txn->parent_txn;
5761 } else {
5762 /* The sequence is already linked to its
5763 ** parent db. Nothing to do.
5764 */
5765 dbs->txn=NULL;
5766 }
5767 }
5768#endif
5769}
5770
5771
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005772static PyObject*
5773DBTxn_commit(DBTxnObject* self, PyObject* args)
5774{
5775 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005776 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005777
5778 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5779 return NULL;
5780
Jesus Ceaef9764f2008-05-13 18:45:46 +00005781 _close_transaction_cursors(self);
5782
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005783 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005784 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005785 "after txn_commit, txn_abort "
5786 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005787 if (t) {
5788 PyErr_SetObject(DBError, t);
5789 Py_DECREF(t);
5790 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005791 return NULL;
5792 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005793 self->flag_prepare=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005794 txn = self->txn;
5795 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005796
5797 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5798
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005799 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005800 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005801 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005802
5803 _promote_transaction_dbs_and_sequences(self);
5804
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005805 RETURN_IF_ERR();
5806 RETURN_NONE();
5807}
5808
5809static PyObject*
5810DBTxn_prepare(DBTxnObject* self, PyObject* args)
5811{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005812 int err;
5813 char* gid=NULL;
5814 int gid_size=0;
5815
5816 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
5817 return NULL;
5818
5819 if (gid_size != DB_XIDDATASIZE) {
5820 PyErr_SetString(PyExc_TypeError,
5821 "gid must be DB_XIDDATASIZE bytes long");
5822 return NULL;
5823 }
5824
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005825 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005826 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005827 "after txn_commit, txn_abort "
5828 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005829 if (t) {
5830 PyErr_SetObject(DBError, t);
5831 Py_DECREF(t);
5832 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005833 return NULL;
5834 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005835 self->flag_prepare=1; /* Prepare state */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005836 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005837 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005838 MYDB_END_ALLOW_THREADS;
5839 RETURN_IF_ERR();
5840 RETURN_NONE();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005841}
5842
5843
5844static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005845DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005846{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005847 PyObject *dummy;
5848 int err=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005849 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005850
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005851 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005852 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005853 "after txn_commit, txn_abort "
5854 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005855 if (t) {
5856 PyErr_SetObject(DBError, t);
5857 Py_DECREF(t);
5858 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005859 return NULL;
5860 }
5861 txn = self->txn;
5862 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005863
5864 _close_transaction_cursors(self);
5865#if (DBVER >= 43)
5866 while (self->children_sequences) {
5867 dummy=DBSequence_close_internal(self->children_sequences,0,0);
5868 Py_XDECREF(dummy);
5869 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005870#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005871 while (self->children_dbs) {
5872 dummy=DB_close_internal(self->children_dbs,0);
5873 Py_XDECREF(dummy);
5874 }
5875
5876 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5877
5878 MYDB_BEGIN_ALLOW_THREADS;
5879 if (discard) {
5880 assert(!self->flag_prepare);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005881 err = txn->discard(txn,0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005882 } else {
5883 /*
5884 ** If the transaction is in the "prepare" or "recover" state,
5885 ** we better do not implicitly abort it.
5886 */
5887 if (!self->flag_prepare) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00005888 err = txn->abort(txn);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005889 }
5890 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005891 MYDB_END_ALLOW_THREADS;
5892 RETURN_IF_ERR();
5893 RETURN_NONE();
5894}
5895
Jesus Ceaef9764f2008-05-13 18:45:46 +00005896static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005897DBTxn_abort(DBTxnObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005898{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005899 self->flag_prepare=0;
5900 _close_transaction_cursors(self);
5901
5902 return DBTxn_abort_discard_internal(self,0);
5903}
5904
5905static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005906DBTxn_discard(DBTxnObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005907{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005908 self->flag_prepare=0;
5909 _close_transaction_cursors(self);
5910
5911 return DBTxn_abort_discard_internal(self,1);
5912}
5913
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005914
5915static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005916DBTxn_id(DBTxnObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005917{
5918 int id;
5919
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005920 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005921 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005922 "after txn_commit, txn_abort "
5923 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005924 if (t) {
5925 PyErr_SetObject(DBError, t);
5926 Py_DECREF(t);
5927 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005928 return NULL;
5929 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005930 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005931 id = self->txn->id(self->txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005932 MYDB_END_ALLOW_THREADS;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005933 return NUMBER_FromLong(id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005934}
5935
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005936#if (DBVER >= 43)
5937/* --------------------------------------------------------------------- */
5938/* DBSequence methods */
5939
5940
5941static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005942DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005943{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005944 int err=0;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005945
Jesus Ceaef9764f2008-05-13 18:45:46 +00005946 if (self->sequence!=NULL) {
5947 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5948 if (self->txn) {
5949 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
5950 self->txn=NULL;
5951 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005952
Jesus Ceaef9764f2008-05-13 18:45:46 +00005953 if (!do_not_close) {
5954 MYDB_BEGIN_ALLOW_THREADS
5955 err = self->sequence->close(self->sequence, flags);
5956 MYDB_END_ALLOW_THREADS
5957 }
5958 self->sequence = NULL;
5959
5960 RETURN_IF_ERR();
5961 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005962
5963 RETURN_NONE();
5964}
5965
5966static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005967DBSequence_close(DBSequenceObject* self, PyObject* args)
5968{
5969 int flags=0;
5970 if (!PyArg_ParseTuple(args,"|i:close", &flags))
5971 return NULL;
5972
5973 return DBSequence_close_internal(self,flags,0);
5974}
5975
5976static PyObject*
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005977DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5978{
5979 int err, flags = 0;
5980 int delta = 1;
5981 db_seq_t value;
5982 PyObject *txnobj = NULL;
5983 DB_TXN *txn = NULL;
5984 static char* kwnames[] = {"delta", "txn", "flags", NULL };
5985 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
5986 return NULL;
5987 CHECK_SEQUENCE_NOT_CLOSED(self)
5988
5989 if (!checkTxnObj(txnobj, &txn))
5990 return NULL;
5991
5992 MYDB_BEGIN_ALLOW_THREADS
5993 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
5994 MYDB_END_ALLOW_THREADS
5995
5996 RETURN_IF_ERR();
5997 return PyLong_FromLongLong(value);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005998}
5999
6000static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006001DBSequence_get_dbp(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006002{
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006003 CHECK_SEQUENCE_NOT_CLOSED(self)
6004 Py_INCREF(self->mydb);
6005 return (PyObject* )self->mydb;
6006}
6007
6008static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006009DBSequence_get_key(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006010{
6011 int err;
6012 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00006013 PyObject *retval = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006014
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006015 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006016 CHECK_SEQUENCE_NOT_CLOSED(self)
6017 MYDB_BEGIN_ALLOW_THREADS
6018 err = self->sequence->get_key(self->sequence, &key);
6019 MYDB_END_ALLOW_THREADS
6020
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006021 if (!err)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006022 retval = Build_PyString(key.data, key.size);
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006023
6024 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006025 RETURN_IF_ERR();
6026
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006027 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006028}
6029
6030static PyObject*
6031DBSequence_init_value(DBSequenceObject* self, PyObject* args)
6032{
6033 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006034 PY_LONG_LONG value;
6035 db_seq_t value2;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006036 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006037 return NULL;
6038 CHECK_SEQUENCE_NOT_CLOSED(self)
6039
Jesus Ceaef9764f2008-05-13 18:45:46 +00006040 value2=value; /* If truncation, compiler should show a warning */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006041 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006042 err = self->sequence->initial_value(self->sequence, value2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006043 MYDB_END_ALLOW_THREADS
6044
6045 RETURN_IF_ERR();
6046
6047 RETURN_NONE();
6048}
6049
6050static PyObject*
6051DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6052{
6053 int err, flags = 0;
6054 PyObject* keyobj;
6055 PyObject *txnobj = NULL;
6056 DB_TXN *txn = NULL;
6057 DBT key;
6058
6059 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006060 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006061 return NULL;
6062
6063 if (!checkTxnObj(txnobj, &txn))
6064 return NULL;
6065
6066 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
6067 return NULL;
6068
6069 MYDB_BEGIN_ALLOW_THREADS
6070 err = self->sequence->open(self->sequence, txn, &key, flags);
6071 MYDB_END_ALLOW_THREADS
6072
6073 CLEAR_DBT(key);
6074 RETURN_IF_ERR();
6075
Jesus Ceaef9764f2008-05-13 18:45:46 +00006076 if (txn) {
6077 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
6078 self->txn=(DBTxnObject *)txnobj;
6079 }
6080
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006081 RETURN_NONE();
6082}
6083
6084static PyObject*
6085DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6086{
Jesus Ceaef9764f2008-05-13 18:45:46 +00006087 PyObject *dummy;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006088 int err, flags = 0;
6089 PyObject *txnobj = NULL;
6090 DB_TXN *txn = NULL;
6091
6092 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006093 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006094 return NULL;
6095
6096 if (!checkTxnObj(txnobj, &txn))
6097 return NULL;
6098
6099 CHECK_SEQUENCE_NOT_CLOSED(self)
6100
6101 MYDB_BEGIN_ALLOW_THREADS
6102 err = self->sequence->remove(self->sequence, txn, flags);
6103 MYDB_END_ALLOW_THREADS
6104
Jesus Ceaef9764f2008-05-13 18:45:46 +00006105 dummy=DBSequence_close_internal(self,flags,1);
6106 Py_XDECREF(dummy);
6107
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006108 RETURN_IF_ERR();
6109 RETURN_NONE();
6110}
6111
6112static PyObject*
6113DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
6114{
6115 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006116 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006117 return NULL;
6118 CHECK_SEQUENCE_NOT_CLOSED(self)
6119
6120 MYDB_BEGIN_ALLOW_THREADS
6121 err = self->sequence->set_cachesize(self->sequence, size);
6122 MYDB_END_ALLOW_THREADS
6123
6124 RETURN_IF_ERR();
6125 RETURN_NONE();
6126}
6127
6128static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006129DBSequence_get_cachesize(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006130{
6131 int err, size;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006132
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006133 CHECK_SEQUENCE_NOT_CLOSED(self)
6134
6135 MYDB_BEGIN_ALLOW_THREADS
6136 err = self->sequence->get_cachesize(self->sequence, &size);
6137 MYDB_END_ALLOW_THREADS
6138
6139 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006140 return NUMBER_FromLong(size);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006141}
6142
6143static PyObject*
6144DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
6145{
6146 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006147 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006148 return NULL;
6149 CHECK_SEQUENCE_NOT_CLOSED(self)
6150
6151 MYDB_BEGIN_ALLOW_THREADS
6152 err = self->sequence->set_flags(self->sequence, flags);
6153 MYDB_END_ALLOW_THREADS
6154
6155 RETURN_IF_ERR();
6156 RETURN_NONE();
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006157}
6158
6159static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006160DBSequence_get_flags(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006161{
6162 unsigned int flags;
6163 int err;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006164
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006165 CHECK_SEQUENCE_NOT_CLOSED(self)
6166
6167 MYDB_BEGIN_ALLOW_THREADS
6168 err = self->sequence->get_flags(self->sequence, &flags);
6169 MYDB_END_ALLOW_THREADS
6170
6171 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006172 return NUMBER_FromLong((int)flags);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006173}
6174
6175static PyObject*
6176DBSequence_set_range(DBSequenceObject* self, PyObject* args)
6177{
6178 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006179 PY_LONG_LONG min, max;
6180 db_seq_t min2, max2;
Tim Petersbb21b2c2006-06-06 15:50:17 +00006181 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006182 return NULL;
6183 CHECK_SEQUENCE_NOT_CLOSED(self)
6184
Jesus Ceaef9764f2008-05-13 18:45:46 +00006185 min2=min; /* If truncation, compiler should show a warning */
6186 max2=max;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006187 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006188 err = self->sequence->set_range(self->sequence, min2, max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006189 MYDB_END_ALLOW_THREADS
6190
6191 RETURN_IF_ERR();
6192 RETURN_NONE();
6193}
6194
6195static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006196DBSequence_get_range(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006197{
6198 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006199 PY_LONG_LONG min, max;
6200 db_seq_t min2, max2;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006201
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006202 CHECK_SEQUENCE_NOT_CLOSED(self)
6203
6204 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006205 err = self->sequence->get_range(self->sequence, &min2, &max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006206 MYDB_END_ALLOW_THREADS
6207
6208 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00006209 min=min2; /* If truncation, compiler should show a warning */
6210 max=max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006211 return Py_BuildValue("(LL)", min, max);
6212}
6213
6214static PyObject*
6215DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6216{
6217 int err, flags = 0;
6218 DB_SEQUENCE_STAT* sp = NULL;
6219 PyObject* dict_stat;
6220 static char* kwnames[] = {"flags", NULL };
6221 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
6222 return NULL;
6223 CHECK_SEQUENCE_NOT_CLOSED(self);
6224
6225 MYDB_BEGIN_ALLOW_THREADS;
6226 err = self->sequence->stat(self->sequence, &sp, flags);
6227 MYDB_END_ALLOW_THREADS;
6228 RETURN_IF_ERR();
6229
6230 if ((dict_stat = PyDict_New()) == NULL) {
6231 free(sp);
6232 return NULL;
6233 }
6234
6235
6236#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
6237#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
6238
6239 MAKE_INT_ENTRY(wait);
6240 MAKE_INT_ENTRY(nowait);
6241 MAKE_LONG_LONG_ENTRY(current);
6242 MAKE_LONG_LONG_ENTRY(value);
6243 MAKE_LONG_LONG_ENTRY(last_value);
6244 MAKE_LONG_LONG_ENTRY(min);
6245 MAKE_LONG_LONG_ENTRY(max);
6246 MAKE_INT_ENTRY(cache_size);
6247 MAKE_INT_ENTRY(flags);
6248
6249#undef MAKE_INT_ENTRY
6250#undef MAKE_LONG_LONG_ENTRY
6251
6252 free(sp);
6253 return dict_stat;
6254}
6255#endif
6256
6257
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006258/* --------------------------------------------------------------------- */
6259/* Method definition tables and type objects */
6260
6261static PyMethodDef DB_methods[] = {
6262 {"append", (PyCFunction)DB_append, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006263 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006264 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006265 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
6266 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006267 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
6268 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006269 {"fd", (PyCFunction)DB_fd, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006270 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00006271 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006272 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006273 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006274 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006275 {"get_type", (PyCFunction)DB_get_type, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006276 {"join", (PyCFunction)DB_join, METH_VARARGS},
6277 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
6278 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
6279 {"items", (PyCFunction)DB_items, METH_VARARGS},
6280 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6281 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6282 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6283 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6284 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6285 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006286 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006287 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006288#if (DBVER >= 41)
6289 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6290#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006291 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6292 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6293 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6294 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6295 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6296 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6297 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6298 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6299 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006300 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
6301 {"set_private", (PyCFunction)DB_set_private, METH_O},
6302 {"get_private", (PyCFunction)DB_get_private, METH_NOARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006303 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006304 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006305 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006306 {"type", (PyCFunction)DB_get_type, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006307 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6308 {"values", (PyCFunction)DB_values, METH_VARARGS},
6309 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6310 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6311 {NULL, NULL} /* sentinel */
6312};
6313
6314
6315static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00006316 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006317 (binaryfunc)DB_subscript, /*mp_subscript*/
6318 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6319};
6320
6321
6322static PyMethodDef DBCursor_methods[] = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006323 {"close", (PyCFunction)DBC_close, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006324 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6325 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6326 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6327 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6328 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6329 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00006330 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006331 {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006332 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6333 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6334 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6335 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6336 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6337 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6338 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006339 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00006340 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006341 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6342 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6343 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6344 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6345 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6346 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6347 {NULL, NULL} /* sentinel */
6348};
6349
6350
6351static PyMethodDef DBEnv_methods[] = {
6352 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6353 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6354 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006355#if (DBVER >= 41)
6356 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6357 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6358 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6359#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00006360 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00006361 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006362 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6363 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006364 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Jesus Ceaca3939c2008-05-22 15:27:38 +00006365#if (DBVER >= 47)
6366 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
6367#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006368 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6369 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6370 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006371#if (DBVER >= 42)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006372 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006373#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00006374 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006375 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006376#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006377 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006378#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006379 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6380 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6381 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006382 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6383 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6384 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6385 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6386 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6387 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00006388 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006389 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6390 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006391 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS},
Gregory P. Smithac11e022007-11-05 02:56:31 +00006392 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006393 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6394 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6395 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006396 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006397 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00006398#if (DBVER >= 44)
6399 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6400#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006401 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006402 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS},
Jesus Ceaca3939c2008-05-22 15:27:38 +00006403 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
6404 METH_VARARGS||METH_KEYWORDS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006405 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6406#if (DBVER >= 42)
6407 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6408#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006409 {"set_private", (PyCFunction)DBEnv_set_private, METH_O},
6410 {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS},
6411 {"rep_start", (PyCFunction)DBEnv_rep_start,
6412 METH_VARARGS|METH_KEYWORDS},
6413 {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
6414 {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
6415 METH_VARARGS},
6416#if (DBVER >= 46)
6417 {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS},
6418#endif
6419#if (DBVER >= 44)
6420 {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS},
6421 {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS},
6422 {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006423#endif
6424#if (DBVER >= 45)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006425 {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS},
6426 {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS},
6427#endif
6428#if (DBVER >= 47)
6429 {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS},
6430 {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS},
6431#endif
6432#if (DBVER >= 45)
6433 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006434#endif
6435#if (DBVER >= 45)
6436 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006437 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006438 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006439 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006440 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6441 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6442#endif
6443#if (DBVER >= 45)
6444 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6445 METH_VARARGS|METH_KEYWORDS},
6446 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6447 METH_VARARGS|METH_KEYWORDS},
6448 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6449 METH_VARARGS|METH_KEYWORDS},
6450 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6451 METH_VARARGS},
6452 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006453 METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006454 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006455 METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006456#endif
6457#if (DBVER >= 46)
6458 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6459 METH_VARARGS|METH_KEYWORDS},
6460 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6461 METH_VARARGS|METH_KEYWORDS},
6462#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006463 {NULL, NULL} /* sentinel */
6464};
6465
6466
6467static PyMethodDef DBTxn_methods[] = {
6468 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6469 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006470 {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS},
6471 {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS},
6472 {"id", (PyCFunction)DBTxn_id, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006473 {NULL, NULL} /* sentinel */
6474};
6475
6476
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006477#if (DBVER >= 43)
6478static PyMethodDef DBSequence_methods[] = {
6479 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6480 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006481 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS},
6482 {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006483 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6484 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6485 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6486 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006487 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006488 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006489 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006490 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006491 {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006492 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6493 {NULL, NULL} /* sentinel */
6494};
6495#endif
6496
6497
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006498static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006499DBEnv_db_home_get(DBEnvObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006500{
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006501 const char *home = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006502
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006503 CHECK_ENV_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006504
Jesus Ceaef9764f2008-05-13 18:45:46 +00006505#if (DBVER >= 42)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006506 self->db_env->get_home(self->db_env, &home);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006507#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006508 home=self->db_env->db_home;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006509#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006510
6511 if (home == NULL) {
6512 RETURN_NONE();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006513 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006514 return PyBytes_FromString(home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006515}
6516
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006517static PyGetSetDef DBEnv_getsets[] = {
6518 {"db_home", (getter)DBEnv_db_home_get, NULL,},
6519 {NULL}
6520};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006521
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006522
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006523statichere PyTypeObject DB_Type = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006524#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006525 PyObject_HEAD_INIT(NULL)
6526 0, /*ob_size*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006527#else
6528 PyVarObject_HEAD_INIT(NULL, 0)
6529#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006530 "DB", /*tp_name*/
6531 sizeof(DBObject), /*tp_basicsize*/
6532 0, /*tp_itemsize*/
6533 /* methods */
6534 (destructor)DB_dealloc, /*tp_dealloc*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006535 0, /*tp_print*/
6536 0, /*tp_getattr*/
6537 0, /*tp_setattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006538 0, /*tp_compare*/
6539 0, /*tp_repr*/
6540 0, /*tp_as_number*/
6541 0, /*tp_as_sequence*/
6542 &DB_mapping,/*tp_as_mapping*/
6543 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006544 0, /* tp_call */
6545 0, /* tp_str */
6546 0, /* tp_getattro */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006547 0, /* tp_setattro */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006548 0, /* tp_as_buffer */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006549#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith31c50652004-06-28 01:20:40 +00006550 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006551#else
6552 Py_TPFLAGS_DEFAULT, /* tp_flags */
6553#endif
6554 0, /* tp_doc */
6555 0, /* tp_traverse */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006556 0, /* tp_clear */
6557 0, /* tp_richcompare */
6558 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006559 0, /*tp_iter*/
6560 0, /*tp_iternext*/
6561 DB_methods, /*tp_methods*/
6562 0, /*tp_members*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006563};
6564
6565
6566statichere PyTypeObject DBCursor_Type = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006567#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006568 PyObject_HEAD_INIT(NULL)
6569 0, /*ob_size*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006570#else
6571 PyVarObject_HEAD_INIT(NULL, 0)
6572#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006573 "DBCursor", /*tp_name*/
6574 sizeof(DBCursorObject), /*tp_basicsize*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006575 0, /*tp_itemsize*/
6576 /* methods */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006577 (destructor)DBCursor_dealloc,/*tp_dealloc*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006578 0, /*tp_print*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006579 0, /*tp_getattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006580 0, /*tp_setattr*/
6581 0, /*tp_compare*/
6582 0, /*tp_repr*/
6583 0, /*tp_as_number*/
6584 0, /*tp_as_sequence*/
6585 0, /*tp_as_mapping*/
6586 0, /*tp_hash*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006587 0, /*tp_call*/
6588 0, /*tp_str*/
6589 0, /*tp_getattro*/
6590 0, /*tp_setattro*/
6591 0, /*tp_as_buffer*/
6592#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith31c50652004-06-28 01:20:40 +00006593 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006594#else
6595 Py_TPFLAGS_DEFAULT, /* tp_flags */
6596#endif
6597 0, /* tp_doc */
6598 0, /* tp_traverse */
6599 0, /* tp_clear */
6600 0, /* tp_richcompare */
6601 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
6602 0, /*tp_iter*/
6603 0, /*tp_iternext*/
6604 DBCursor_methods, /*tp_methods*/
6605 0, /*tp_members*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006606};
6607
6608
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006609statichere PyTypeObject DBEnv_Type = {
6610#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006611 PyObject_HEAD_INIT(NULL)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006612 0, /*ob_size*/
6613#else
6614 PyVarObject_HEAD_INIT(NULL, 0)
6615#endif
6616 "DBEnv", /*tp_name*/
6617 sizeof(DBEnvObject), /*tp_basicsize*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006618 0, /*tp_itemsize*/
6619 /* methods */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006620 (destructor)DBEnv_dealloc, /*tp_dealloc*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006621 0, /*tp_print*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006622 0, /*tp_getattr*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006623 0, /*tp_setattr*/
6624 0, /*tp_compare*/
6625 0, /*tp_repr*/
6626 0, /*tp_as_number*/
6627 0, /*tp_as_sequence*/
6628 0, /*tp_as_mapping*/
6629 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006630 0, /* tp_call */
6631 0, /* tp_str */
6632 0, /* tp_getattro */
6633 0, /* tp_setattro */
6634 0, /* tp_as_buffer */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006635#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006636 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006637#else
6638 Py_TPFLAGS_DEFAULT, /* tp_flags */
6639#endif
6640 0, /* tp_doc */
6641 0, /* tp_traverse */
6642 0, /* tp_clear */
6643 0, /* tp_richcompare */
6644 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
6645 0, /* tp_iter */
6646 0, /* tp_iternext */
6647 DBEnv_methods, /* tp_methods */
6648 0, /* tp_members */
6649 DBEnv_getsets, /* tp_getsets */
6650};
6651
6652statichere PyTypeObject DBTxn_Type = {
6653#if (PY_VERSION_HEX < 0x03000000)
6654 PyObject_HEAD_INIT(NULL)
6655 0, /*ob_size*/
6656#else
6657 PyVarObject_HEAD_INIT(NULL, 0)
6658#endif
6659 "DBTxn", /*tp_name*/
6660 sizeof(DBTxnObject), /*tp_basicsize*/
6661 0, /*tp_itemsize*/
6662 /* methods */
6663 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6664 0, /*tp_print*/
6665 0, /*tp_getattr*/
6666 0, /*tp_setattr*/
6667 0, /*tp_compare*/
6668 0, /*tp_repr*/
6669 0, /*tp_as_number*/
6670 0, /*tp_as_sequence*/
6671 0, /*tp_as_mapping*/
6672 0, /*tp_hash*/
6673 0, /* tp_call */
6674 0, /* tp_str */
6675 0, /* tp_getattro */
6676 0, /* tp_setattro */
6677 0, /* tp_as_buffer */
6678#if (PY_VERSION_HEX < 0x03000000)
6679 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6680#else
6681 Py_TPFLAGS_DEFAULT, /* tp_flags */
6682#endif
6683 0, /* tp_doc */
6684 0, /* tp_traverse */
6685 0, /* tp_clear */
6686 0, /* tp_richcompare */
6687 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
6688 0, /*tp_iter*/
6689 0, /*tp_iternext*/
6690 DBTxn_methods, /*tp_methods*/
6691 0, /*tp_members*/
6692};
6693
6694
6695statichere PyTypeObject DBLock_Type = {
6696#if (PY_VERSION_HEX < 0x03000000)
6697 PyObject_HEAD_INIT(NULL)
6698 0, /*ob_size*/
6699#else
6700 PyVarObject_HEAD_INIT(NULL, 0)
6701#endif
6702 "DBLock", /*tp_name*/
6703 sizeof(DBLockObject), /*tp_basicsize*/
6704 0, /*tp_itemsize*/
6705 /* methods */
6706 (destructor)DBLock_dealloc, /*tp_dealloc*/
6707 0, /*tp_print*/
6708 0, /*tp_getattr*/
6709 0, /*tp_setattr*/
6710 0, /*tp_compare*/
6711 0, /*tp_repr*/
6712 0, /*tp_as_number*/
6713 0, /*tp_as_sequence*/
6714 0, /*tp_as_mapping*/
6715 0, /*tp_hash*/
6716 0, /* tp_call */
6717 0, /* tp_str */
6718 0, /* tp_getattro */
6719 0, /* tp_setattro */
6720 0, /* tp_as_buffer */
6721#if (PY_VERSION_HEX < 0x03000000)
6722 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6723#else
6724 Py_TPFLAGS_DEFAULT, /* tp_flags */
6725#endif
6726 0, /* tp_doc */
6727 0, /* tp_traverse */
6728 0, /* tp_clear */
6729 0, /* tp_richcompare */
6730 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
6731};
6732
6733#if (DBVER >= 43)
6734statichere PyTypeObject DBSequence_Type = {
6735#if (PY_VERSION_HEX < 0x03000000)
6736 PyObject_HEAD_INIT(NULL)
6737 0, /*ob_size*/
6738#else
6739 PyVarObject_HEAD_INIT(NULL, 0)
6740#endif
6741 "DBSequence", /*tp_name*/
6742 sizeof(DBSequenceObject), /*tp_basicsize*/
6743 0, /*tp_itemsize*/
6744 /* methods */
6745 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6746 0, /*tp_print*/
6747 0, /*tp_getattr*/
6748 0, /*tp_setattr*/
6749 0, /*tp_compare*/
6750 0, /*tp_repr*/
6751 0, /*tp_as_number*/
6752 0, /*tp_as_sequence*/
6753 0, /*tp_as_mapping*/
6754 0, /*tp_hash*/
6755 0, /* tp_call */
6756 0, /* tp_str */
6757 0, /* tp_getattro */
6758 0, /* tp_setattro */
6759 0, /* tp_as_buffer */
6760#if (PY_VERSION_HEX < 0x03000000)
6761 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6762#else
6763 Py_TPFLAGS_DEFAULT, /* tp_flags */
6764#endif
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006765 0, /* tp_doc */
6766 0, /* tp_traverse */
6767 0, /* tp_clear */
6768 0, /* tp_richcompare */
6769 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006770 0, /*tp_iter*/
6771 0, /*tp_iternext*/
6772 DBSequence_methods, /*tp_methods*/
6773 0, /*tp_members*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006774};
6775#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006776
6777/* --------------------------------------------------------------------- */
6778/* Module-level functions */
6779
6780static PyObject*
6781DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6782{
6783 PyObject* dbenvobj = NULL;
6784 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00006785 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006786
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006787 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6788 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006789 return NULL;
6790 if (dbenvobj == Py_None)
6791 dbenvobj = NULL;
6792 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6793 makeTypeError("DBEnv", dbenvobj);
6794 return NULL;
6795 }
6796
6797 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6798}
6799
6800
6801static PyObject*
6802DBEnv_construct(PyObject* self, PyObject* args)
6803{
6804 int flags = 0;
6805 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6806 return (PyObject* )newDBEnvObject(flags);
6807}
6808
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006809#if (DBVER >= 43)
6810static PyObject*
6811DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6812{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006813 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006814 int flags = 0;
6815 static char* kwnames[] = { "db", "flags", NULL};
6816
6817 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6818 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006819 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006820 makeTypeError("DB", dbobj);
6821 return NULL;
6822 }
6823 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6824}
6825#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006826
6827static char bsddb_version_doc[] =
6828"Returns a tuple of major, minor, and patch release numbers of the\n\
6829underlying DB library.";
6830
6831static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006832bsddb_version(PyObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006833{
6834 int major, minor, patch;
6835
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006836 db_version(&major, &minor, &patch);
6837 return Py_BuildValue("(iii)", major, minor, patch);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006838}
6839
6840
6841/* List of functions defined in the module */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006842static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006843 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6844 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006845#if (DBVER >= 43)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006846 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006847#endif
6848 {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006849 {NULL, NULL} /* sentinel */
6850};
6851
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006852
Gregory P. Smith39250532007-10-09 06:02:21 +00006853/* API structure */
6854static BSDDB_api bsddb_api;
6855
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006856
6857/* --------------------------------------------------------------------- */
6858/* Module initialization */
6859
6860
6861/* Convenience routine to export an integer value.
6862 * Errors are silently ignored, for better or for worse...
6863 */
6864#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
6865
Gregory P. Smith41631e82003-09-21 00:08:14 +00006866#define MODULE_NAME_MAX_LEN 11
6867static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006868
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006869#if (PY_VERSION_HEX >= 0x03000000)
6870static struct PyModuleDef bsddbmodule = {
6871 PyModuleDef_HEAD_INIT,
6872 _bsddbModuleName, /* Name of module */
6873 NULL, /* module documentation, may be NULL */
6874 -1, /* size of per-interpreter state of the module,
6875 or -1 if the module keeps state in global variables. */
6876 bsddb_methods,
6877 NULL, /* Reload */
6878 NULL, /* Traverse */
6879 NULL, /* Clear */
6880 NULL /* Free */
6881};
6882#endif
6883
6884
6885#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006886DL_EXPORT(void) init_bsddb(void)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006887#else
6888PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */
6889#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006890{
6891 PyObject* m;
6892 PyObject* d;
Christian Heimes593daf52008-05-26 12:51:38 +00006893 PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
6894 PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
6895 PyObject* cvsid_s = PyBytes_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00006896 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006897
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006898 /* Initialize object types */
6899 if ((PyType_Ready(&DB_Type) < 0)
6900 || (PyType_Ready(&DBCursor_Type) < 0)
6901 || (PyType_Ready(&DBEnv_Type) < 0)
6902 || (PyType_Ready(&DBTxn_Type) < 0)
6903 || (PyType_Ready(&DBLock_Type) < 0)
6904#if (DBVER >= 43)
6905 || (PyType_Ready(&DBSequence_Type) < 0)
6906#endif
6907 ) {
6908#if (PY_VERSION_HEX < 0x03000000)
6909 return;
6910#else
6911 return NULL;
6912#endif
6913 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006914
Mark Hammonda69d4092003-04-22 23:13:27 +00006915#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006916 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00006917 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006918#endif
6919
6920 /* Create the module and add the functions */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006921#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00006922 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006923#else
6924 m=PyModule_Create(&bsddbmodule);
6925#endif
6926 if (m == NULL) {
6927#if (PY_VERSION_HEX < 0x03000000)
6928 return;
6929#else
6930 return NULL;
6931#endif
6932 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006933
6934 /* Add some symbolic constants to the module */
6935 d = PyModule_GetDict(m);
6936 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
6937 PyDict_SetItemString(d, "cvsid", cvsid_s);
6938 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
6939 Py_DECREF(pybsddb_version_s);
6940 pybsddb_version_s = NULL;
6941 Py_DECREF(cvsid_s);
6942 cvsid_s = NULL;
6943 Py_DECREF(db_version_s);
6944 db_version_s = NULL;
6945
6946 ADD_INT(d, DB_VERSION_MAJOR);
6947 ADD_INT(d, DB_VERSION_MINOR);
6948 ADD_INT(d, DB_VERSION_PATCH);
6949
6950 ADD_INT(d, DB_MAX_PAGES);
6951 ADD_INT(d, DB_MAX_RECORDS);
6952
Gregory P. Smith41631e82003-09-21 00:08:14 +00006953#if (DBVER >= 42)
6954 ADD_INT(d, DB_RPCCLIENT);
6955#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006956 ADD_INT(d, DB_CLIENT);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006957 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
Gregory P. Smith41631e82003-09-21 00:08:14 +00006958 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
6959#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006960 ADD_INT(d, DB_XA_CREATE);
6961
6962 ADD_INT(d, DB_CREATE);
6963 ADD_INT(d, DB_NOMMAP);
6964 ADD_INT(d, DB_THREAD);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006965#if (DBVER >= 45)
6966 ADD_INT(d, DB_MULTIVERSION);
6967#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006968
6969 ADD_INT(d, DB_FORCE);
6970 ADD_INT(d, DB_INIT_CDB);
6971 ADD_INT(d, DB_INIT_LOCK);
6972 ADD_INT(d, DB_INIT_LOG);
6973 ADD_INT(d, DB_INIT_MPOOL);
6974 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006975 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006976
Jesus Ceaef9764f2008-05-13 18:45:46 +00006977 ADD_INT(d, DB_XIDDATASIZE);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006978
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006979 ADD_INT(d, DB_RECOVER);
6980 ADD_INT(d, DB_RECOVER_FATAL);
6981 ADD_INT(d, DB_TXN_NOSYNC);
6982 ADD_INT(d, DB_USE_ENVIRON);
6983 ADD_INT(d, DB_USE_ENVIRON_ROOT);
6984
6985 ADD_INT(d, DB_LOCKDOWN);
6986 ADD_INT(d, DB_PRIVATE);
6987 ADD_INT(d, DB_SYSTEM_MEM);
6988
6989 ADD_INT(d, DB_TXN_SYNC);
6990 ADD_INT(d, DB_TXN_NOWAIT);
6991
6992 ADD_INT(d, DB_EXCL);
6993 ADD_INT(d, DB_FCNTL_LOCKING);
6994 ADD_INT(d, DB_ODDFILESIZE);
6995 ADD_INT(d, DB_RDWRMASTER);
6996 ADD_INT(d, DB_RDONLY);
6997 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006998 ADD_INT(d, DB_EXTENT);
6999 ADD_INT(d, DB_CDB_ALLDB);
7000 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007001 ADD_INT(d, DB_UPGRADE);
7002
7003 ADD_INT(d, DB_AGGRESSIVE);
7004 ADD_INT(d, DB_NOORDERCHK);
7005 ADD_INT(d, DB_ORDERCHKONLY);
7006 ADD_INT(d, DB_PR_PAGE);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007007
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007008 ADD_INT(d, DB_PR_RECOVERYTEST);
7009 ADD_INT(d, DB_SALVAGE);
7010
7011 ADD_INT(d, DB_LOCK_NORUN);
7012 ADD_INT(d, DB_LOCK_DEFAULT);
7013 ADD_INT(d, DB_LOCK_OLDEST);
7014 ADD_INT(d, DB_LOCK_RANDOM);
7015 ADD_INT(d, DB_LOCK_YOUNGEST);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007016 ADD_INT(d, DB_LOCK_MAXLOCKS);
7017 ADD_INT(d, DB_LOCK_MINLOCKS);
7018 ADD_INT(d, DB_LOCK_MINWRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007019
Jesus Ceaef9764f2008-05-13 18:45:46 +00007020 ADD_INT(d, DB_LOCK_EXPIRE);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007021#if (DBVER >= 43)
7022 ADD_INT(d, DB_LOCK_MAXWRITE);
7023#endif
7024
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007025 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007026
7027 ADD_INT(d, DB_LOCK_DUMP);
7028 ADD_INT(d, DB_LOCK_GET);
7029 ADD_INT(d, DB_LOCK_INHERIT);
7030 ADD_INT(d, DB_LOCK_PUT);
7031 ADD_INT(d, DB_LOCK_PUT_ALL);
7032 ADD_INT(d, DB_LOCK_PUT_OBJ);
7033
7034 ADD_INT(d, DB_LOCK_NG);
7035 ADD_INT(d, DB_LOCK_READ);
7036 ADD_INT(d, DB_LOCK_WRITE);
7037 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007038 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007039 ADD_INT(d, DB_LOCK_IWRITE);
7040 ADD_INT(d, DB_LOCK_IREAD);
7041 ADD_INT(d, DB_LOCK_IWR);
Gregory P. Smith29602d22006-01-24 09:46:48 +00007042#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007043 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00007044#else
7045 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
7046#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007047 ADD_INT(d, DB_LOCK_WWRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007048
7049 ADD_INT(d, DB_LOCK_RECORD);
7050 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007051 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007052 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007053
7054 ADD_INT(d, DB_LOCK_NOWAIT);
7055 ADD_INT(d, DB_LOCK_RECORD);
7056 ADD_INT(d, DB_LOCK_UPGRADE);
7057
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007058 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007059#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007060 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007061#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007062 ADD_INT(d, DB_LSTAT_FREE);
7063 ADD_INT(d, DB_LSTAT_HELD);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007064
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007065 ADD_INT(d, DB_LSTAT_PENDING);
7066 ADD_INT(d, DB_LSTAT_WAITING);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007067
7068 ADD_INT(d, DB_ARCH_ABS);
7069 ADD_INT(d, DB_ARCH_DATA);
7070 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00007071#if (DBVER >= 42)
7072 ADD_INT(d, DB_ARCH_REMOVE);
7073#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007074
7075 ADD_INT(d, DB_BTREE);
7076 ADD_INT(d, DB_HASH);
7077 ADD_INT(d, DB_RECNO);
7078 ADD_INT(d, DB_QUEUE);
7079 ADD_INT(d, DB_UNKNOWN);
7080
7081 ADD_INT(d, DB_DUP);
7082 ADD_INT(d, DB_DUPSORT);
7083 ADD_INT(d, DB_RECNUM);
7084 ADD_INT(d, DB_RENUMBER);
7085 ADD_INT(d, DB_REVSPLITOFF);
7086 ADD_INT(d, DB_SNAPSHOT);
7087
7088 ADD_INT(d, DB_JOIN_NOSORT);
7089
7090 ADD_INT(d, DB_AFTER);
7091 ADD_INT(d, DB_APPEND);
7092 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007093#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007094 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007095#endif
Jesus Ceaca3939c2008-05-22 15:27:38 +00007096
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007097#if (DBVER >= 41)
7098 _addIntToDict(d, "DB_CHECKPOINT", 0);
7099#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007100 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007101 ADD_INT(d, DB_CURLSN);
7102#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007103#if (DBVER <= 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007104 ADD_INT(d, DB_COMMIT);
7105#endif
7106 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007107 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007108 ADD_INT(d, DB_CURRENT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007109 ADD_INT(d, DB_FAST_STAT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007110 ADD_INT(d, DB_FIRST);
7111 ADD_INT(d, DB_FLUSH);
7112 ADD_INT(d, DB_GET_BOTH);
7113 ADD_INT(d, DB_GET_RECNO);
7114 ADD_INT(d, DB_JOIN_ITEM);
7115 ADD_INT(d, DB_KEYFIRST);
7116 ADD_INT(d, DB_KEYLAST);
7117 ADD_INT(d, DB_LAST);
7118 ADD_INT(d, DB_NEXT);
7119 ADD_INT(d, DB_NEXT_DUP);
7120 ADD_INT(d, DB_NEXT_NODUP);
7121 ADD_INT(d, DB_NODUPDATA);
7122 ADD_INT(d, DB_NOOVERWRITE);
7123 ADD_INT(d, DB_NOSYNC);
7124 ADD_INT(d, DB_POSITION);
7125 ADD_INT(d, DB_PREV);
7126 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007127#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007128 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007129#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007130 ADD_INT(d, DB_SET);
7131 ADD_INT(d, DB_SET_RANGE);
7132 ADD_INT(d, DB_SET_RECNO);
7133 ADD_INT(d, DB_WRITECURSOR);
7134
7135 ADD_INT(d, DB_OPFLAGS_MASK);
7136 ADD_INT(d, DB_RMW);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007137 ADD_INT(d, DB_DIRTY_READ);
7138 ADD_INT(d, DB_MULTIPLE);
7139 ADD_INT(d, DB_MULTIPLE_KEY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007140
Gregory P. Smith29602d22006-01-24 09:46:48 +00007141#if (DBVER >= 44)
7142 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
7143 ADD_INT(d, DB_READ_COMMITTED);
7144#endif
7145
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007146 ADD_INT(d, DB_DONOTINDEX);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007147
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007148#if (DBVER >= 41)
7149 _addIntToDict(d, "DB_INCOMPLETE", 0);
7150#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007151 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007152#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007153 ADD_INT(d, DB_KEYEMPTY);
7154 ADD_INT(d, DB_KEYEXIST);
7155 ADD_INT(d, DB_LOCK_DEADLOCK);
7156 ADD_INT(d, DB_LOCK_NOTGRANTED);
7157 ADD_INT(d, DB_NOSERVER);
7158 ADD_INT(d, DB_NOSERVER_HOME);
7159 ADD_INT(d, DB_NOSERVER_ID);
7160 ADD_INT(d, DB_NOTFOUND);
7161 ADD_INT(d, DB_OLD_VERSION);
7162 ADD_INT(d, DB_RUNRECOVERY);
7163 ADD_INT(d, DB_VERIFY_BAD);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007164 ADD_INT(d, DB_PAGE_NOTFOUND);
7165 ADD_INT(d, DB_SECONDARY_BAD);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007166 ADD_INT(d, DB_STAT_CLEAR);
7167 ADD_INT(d, DB_REGION_INIT);
7168 ADD_INT(d, DB_NOLOCKING);
7169 ADD_INT(d, DB_YIELDCPU);
7170 ADD_INT(d, DB_PANIC_ENVIRONMENT);
7171 ADD_INT(d, DB_NOPANIC);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007172
Jesus Ceaef9764f2008-05-13 18:45:46 +00007173#if (DBVER >= 41)
7174 ADD_INT(d, DB_OVERWRITE);
7175#endif
7176
Gregory P. Smithaae141a2007-11-01 21:08:14 +00007177#ifdef DB_REGISTER
7178 ADD_INT(d, DB_REGISTER);
7179#endif
7180
Gregory P. Smith41631e82003-09-21 00:08:14 +00007181#if (DBVER >= 42)
7182 ADD_INT(d, DB_TIME_NOTGRANTED);
7183 ADD_INT(d, DB_TXN_NOT_DURABLE);
7184 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
Gregory P. Smith41631e82003-09-21 00:08:14 +00007185 ADD_INT(d, DB_DIRECT_DB);
7186 ADD_INT(d, DB_INIT_REP);
7187 ADD_INT(d, DB_ENCRYPT);
7188 ADD_INT(d, DB_CHKSUM);
7189#endif
7190
Jesus Ceaca3939c2008-05-22 15:27:38 +00007191#if (DBVER >= 42) && (DBVER < 47)
7192 ADD_INT(d, DB_LOG_AUTOREMOVE);
7193 ADD_INT(d, DB_DIRECT_LOG);
7194#endif
7195
7196#if (DBVER >= 47)
7197 ADD_INT(d, DB_LOG_DIRECT);
7198 ADD_INT(d, DB_LOG_DSYNC);
7199 ADD_INT(d, DB_LOG_IN_MEMORY);
7200 ADD_INT(d, DB_LOG_AUTO_REMOVE);
7201 ADD_INT(d, DB_LOG_ZERO);
7202#endif
7203
Jesus Ceaef9764f2008-05-13 18:45:46 +00007204#if (DBVER >= 44)
7205 ADD_INT(d, DB_DSYNC_DB);
7206#endif
7207
7208#if (DBVER >= 45)
7209 ADD_INT(d, DB_TXN_SNAPSHOT);
7210#endif
7211
Jesus Ceaef9764f2008-05-13 18:45:46 +00007212 ADD_INT(d, DB_VERB_DEADLOCK);
7213#if (DBVER >= 46)
7214 ADD_INT(d, DB_VERB_FILEOPS);
7215 ADD_INT(d, DB_VERB_FILEOPS_ALL);
7216#endif
7217 ADD_INT(d, DB_VERB_RECOVERY);
7218#if (DBVER >= 44)
7219 ADD_INT(d, DB_VERB_REGISTER);
7220#endif
7221 ADD_INT(d, DB_VERB_REPLICATION);
7222 ADD_INT(d, DB_VERB_WAITSFOR);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007223
7224#if (DBVER >= 45)
7225 ADD_INT(d, DB_EVENT_PANIC);
7226 ADD_INT(d, DB_EVENT_REP_CLIENT);
7227#if (DBVER >= 46)
7228 ADD_INT(d, DB_EVENT_REP_ELECTED);
7229#endif
7230 ADD_INT(d, DB_EVENT_REP_MASTER);
7231 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
7232#if (DBVER >= 46)
7233 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
7234#endif
7235 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
7236 ADD_INT(d, DB_EVENT_WRITE_FAILED);
7237#endif
7238
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007239 ADD_INT(d, DB_REP_DUPMASTER);
7240 ADD_INT(d, DB_REP_HOLDELECTION);
7241#if (DBVER >= 44)
7242 ADD_INT(d, DB_REP_IGNORE);
7243 ADD_INT(d, DB_REP_JOIN_FAILURE);
7244#endif
7245#if (DBVER >= 42)
7246 ADD_INT(d, DB_REP_ISPERM);
7247 ADD_INT(d, DB_REP_NOTPERM);
7248#endif
7249 ADD_INT(d, DB_REP_NEWSITE);
7250
Jesus Ceaef9764f2008-05-13 18:45:46 +00007251 ADD_INT(d, DB_REP_MASTER);
7252 ADD_INT(d, DB_REP_CLIENT);
7253#if (DBVER >= 45)
7254 ADD_INT(d, DB_REP_ELECTION);
7255
7256 ADD_INT(d, DB_REP_ACK_TIMEOUT);
7257 ADD_INT(d, DB_REP_CONNECTION_RETRY);
7258 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
7259 ADD_INT(d, DB_REP_ELECTION_RETRY);
7260#endif
7261#if (DBVER >= 46)
7262 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
7263 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
7264#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00007265
7266#if (DBVER >= 45)
7267 ADD_INT(d, DB_REPMGR_PEER);
7268 ADD_INT(d, DB_REPMGR_ACKS_ALL);
7269 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
7270 ADD_INT(d, DB_REPMGR_ACKS_NONE);
7271 ADD_INT(d, DB_REPMGR_ACKS_ONE);
7272 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
7273 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
7274 ADD_INT(d, DB_REPMGR_CONNECTED);
7275 ADD_INT(d, DB_REPMGR_DISCONNECTED);
7276 ADD_INT(d, DB_STAT_CLEAR);
7277 ADD_INT(d, DB_STAT_ALL);
7278#endif
7279
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007280#if (DBVER >= 43)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007281 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00007282 ADD_INT(d, DB_SEQ_DEC);
7283 ADD_INT(d, DB_SEQ_INC);
7284 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007285#endif
7286
Jesus Ceaca3939c2008-05-22 15:27:38 +00007287#if (DBVER >= 43) && (DBVER < 47)
7288 ADD_INT(d, DB_LOG_INMEMORY);
7289 ADD_INT(d, DB_DSYNC_LOG);
7290#endif
7291
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007292#if (DBVER >= 41)
7293 ADD_INT(d, DB_ENCRYPT_AES);
7294 ADD_INT(d, DB_AUTO_COMMIT);
7295#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00007296 /* allow Berkeley DB 4.1 aware apps to run on older versions */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007297 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
7298#endif
7299
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007300 ADD_INT(d, EINVAL);
7301 ADD_INT(d, EACCES);
7302 ADD_INT(d, ENOSPC);
7303 ADD_INT(d, ENOMEM);
7304 ADD_INT(d, EAGAIN);
7305 ADD_INT(d, EBUSY);
7306 ADD_INT(d, EEXIST);
7307 ADD_INT(d, ENOENT);
7308 ADD_INT(d, EPERM);
7309
Barry Warsaw1baa9822003-03-31 19:51:29 +00007310 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
7311 ADD_INT(d, DB_SET_TXN_TIMEOUT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007312
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007313 /* The exception name must be correct for pickled exception *
7314 * objects to unpickle properly. */
7315#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
7316#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
7317#else
7318#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
7319#endif
7320
7321 /* All the rest of the exceptions derive only from DBError */
7322#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
7323 PyDict_SetItemString(d, #name, name)
7324
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007325 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007326 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
7327 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007328
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007329#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithe9477062005-06-04 06:46:59 +00007330 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
7331 * from both DBError and KeyError, since the API only supports
7332 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007333 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00007334 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
7335 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007336 Py_file_input, d, d);
7337 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00007338 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007339 PyDict_DelItemString(d, "KeyError");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007340#else
7341 /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
7342 ** derive from several classes. We use this new API only for Python 3.0,
7343 ** though.
7344 */
7345 {
7346 PyObject* bases;
7347
7348 bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
7349
7350#define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
7351 PyDict_SetItemString(d, #name, name)
7352 MAKE_EX2(DBNotFoundError);
7353 MAKE_EX2(DBKeyEmptyError);
7354
7355#undef MAKE_EX2
7356
7357 Py_XDECREF(bases);
7358 }
7359#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007360
7361
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007362#if !INCOMPLETE_IS_WARNING
7363 MAKE_EX(DBIncompleteError);
7364#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00007365 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007366 MAKE_EX(DBKeyEmptyError);
7367 MAKE_EX(DBKeyExistError);
7368 MAKE_EX(DBLockDeadlockError);
7369 MAKE_EX(DBLockNotGrantedError);
7370 MAKE_EX(DBOldVersionError);
7371 MAKE_EX(DBRunRecoveryError);
7372 MAKE_EX(DBVerifyBadError);
7373 MAKE_EX(DBNoServerError);
7374 MAKE_EX(DBNoServerHomeError);
7375 MAKE_EX(DBNoServerIDError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007376 MAKE_EX(DBPageNotFoundError);
7377 MAKE_EX(DBSecondaryBadError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007378
7379 MAKE_EX(DBInvalidArgError);
7380 MAKE_EX(DBAccessError);
7381 MAKE_EX(DBNoSpaceError);
7382 MAKE_EX(DBNoMemoryError);
7383 MAKE_EX(DBAgainError);
7384 MAKE_EX(DBBusyError);
7385 MAKE_EX(DBFileExistsError);
7386 MAKE_EX(DBNoSuchFileError);
7387 MAKE_EX(DBPermissionsError);
7388
Jesus Ceaef9764f2008-05-13 18:45:46 +00007389#if (DBVER >= 42)
7390 MAKE_EX(DBRepHandleDeadError);
7391#endif
7392
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007393 MAKE_EX(DBRepUnavailError);
7394
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007395#undef MAKE_EX
7396
Gregory P. Smith39250532007-10-09 06:02:21 +00007397 /* Initiliase the C API structure and add it to the module */
7398 bsddb_api.db_type = &DB_Type;
7399 bsddb_api.dbcursor_type = &DBCursor_Type;
7400 bsddb_api.dbenv_type = &DBEnv_Type;
7401 bsddb_api.dbtxn_type = &DBTxn_Type;
7402 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007403#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00007404 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007405#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00007406 bsddb_api.makeDBError = makeDBError;
7407
7408 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7409 PyDict_SetItemString(d, "api", py_api);
7410 Py_DECREF(py_api);
7411
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007412 /* Check for errors */
7413 if (PyErr_Occurred()) {
7414 PyErr_Print();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007415 Py_FatalError("can't initialize module _bsddb/_pybsddb");
7416 Py_DECREF(m);
7417 m = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007418 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007419#if (PY_VERSION_HEX < 0x03000000)
7420 return;
7421#else
7422 return m;
7423#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007424}
Gregory P. Smith41631e82003-09-21 00:08:14 +00007425
7426/* allow this module to be named _pybsddb so that it can be installed
7427 * and imported on top of python >= 2.3 that includes its own older
7428 * copy of the library named _bsddb without importing the old version. */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007429#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007430DL_EXPORT(void) init_pybsddb(void)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007431#else
7432PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */
7433#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00007434{
7435 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007436#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007437 init_bsddb();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007438#else
7439 return PyInit__bsddb(); /* Note the two underscores */
7440#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00007441}
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007442