blob: 149e43dc06e1e16a4fe4367e7870606f94357dc5 [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,
Jesus Cea4907d272008-08-31 14:00:51 +0000399#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000400 "Data values must be of type string or None.");
Jesus Cea4907d272008-08-31 14:00:51 +0000401#else
402 "Data values must be of type bytes or None.");
403#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000404 return 0;
405 }
406 return 1;
407}
408
409
410/* Recno and Queue DBs can have integer keys. This function figures out
411 what's been given, verifies that it's allowed, and then makes the DBT.
412
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000413 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000414static int
415make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000416{
417 db_recno_t recno;
418 int type;
419
420 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000421 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000422 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000423 if (type == -1)
424 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000425 if (type == DB_RECNO || type == DB_QUEUE) {
426 PyErr_SetString(
427 PyExc_TypeError,
428 "None keys not allowed for Recno and Queue DB's");
429 return 0;
430 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000431 /* no need to do anything, the structure has already been zeroed */
432 }
433
Christian Heimes593daf52008-05-26 12:51:38 +0000434 else if (PyBytes_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000435 /* verify access method type */
436 type = _DB_get_type(self);
437 if (type == -1)
438 return 0;
439 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000440 PyErr_SetString(
441 PyExc_TypeError,
Jesus Cea4907d272008-08-31 14:00:51 +0000442#if (PY_VERSION_HEX < 0x03000000)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000443 "String keys not allowed for Recno and Queue DB's");
Jesus Cea4907d272008-08-31 14:00:51 +0000444#else
445 "Bytes keys not allowed for Recno and Queue DB's");
446#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000447 return 0;
448 }
449
Gregory P. Smith10bed542007-10-09 06:50:43 +0000450 /*
451 * NOTE(gps): I don't like doing a data copy here, it seems
452 * wasteful. But without a clean way to tell FREE_DBT if it
453 * should free key->data or not we have to. Other places in
454 * the code check for DB_THREAD and forceably set DBT_MALLOC
455 * when we otherwise would leave flags 0 to indicate that.
456 */
Christian Heimes593daf52008-05-26 12:51:38 +0000457 key->data = malloc(PyBytes_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000458 if (key->data == NULL) {
459 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
460 return 0;
461 }
Christian Heimes593daf52008-05-26 12:51:38 +0000462 memcpy(key->data, PyBytes_AS_STRING(keyobj),
463 PyBytes_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000464 key->flags = DB_DBT_REALLOC;
Christian Heimes593daf52008-05-26 12:51:38 +0000465 key->size = PyBytes_GET_SIZE(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000466 }
467
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000468 else if (NUMBER_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000469 /* verify access method type */
470 type = _DB_get_type(self);
471 if (type == -1)
472 return 0;
473 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000474 /* if BTREE then an Integer key is allowed with the
475 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000476 *pflags |= DB_SET_RECNO;
477 }
478 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000479 PyErr_SetString(
480 PyExc_TypeError,
481 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000482 return 0;
483 }
484
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000485 /* Make a key out of the requested recno, use allocated space so DB
486 * will be able to realloc room for the real key if needed. */
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000487 recno = NUMBER_AsLong(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000488 key->data = malloc(sizeof(db_recno_t));
489 if (key->data == NULL) {
490 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
491 return 0;
492 }
493 key->ulen = key->size = sizeof(db_recno_t);
494 memcpy(key->data, &recno, sizeof(db_recno_t));
495 key->flags = DB_DBT_REALLOC;
496 }
497 else {
498 PyErr_Format(PyExc_TypeError,
Jesus Cea4907d272008-08-31 14:00:51 +0000499#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000500 "String or Integer object expected for key, %s found",
Jesus Cea4907d272008-08-31 14:00:51 +0000501#else
502 "Bytes or Integer object expected for key, %s found",
503#endif
Christian Heimese93237d2007-12-19 02:37:44 +0000504 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000505 return 0;
506 }
507
508 return 1;
509}
510
511
512/* Add partial record access to an existing DBT data struct.
513 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
514 and the data storage/retrieval will be done using dlen and doff. */
515static int add_partial_dbt(DBT* d, int dlen, int doff) {
516 /* if neither were set we do nothing (-1 is the default value) */
517 if ((dlen == -1) && (doff == -1)) {
518 return 1;
519 }
520
521 if ((dlen < 0) || (doff < 0)) {
522 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
523 return 0;
524 }
525
526 d->flags = d->flags | DB_DBT_PARTIAL;
527 d->dlen = (unsigned int) dlen;
528 d->doff = (unsigned int) doff;
529 return 1;
530}
531
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000532/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
533/* TODO: make this use the native libc strlcpy() when available (BSD) */
534unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
535{
536 unsigned int srclen, copylen;
537
538 srclen = strlen(src);
539 if (n <= 0)
540 return srclen;
541 copylen = (srclen > n-1) ? n-1 : srclen;
542 /* populate dest[0] thru dest[copylen-1] */
543 memcpy(dest, src, copylen);
544 /* guarantee null termination */
545 dest[copylen] = 0;
546
547 return srclen;
548}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000550/* Callback used to save away more information about errors from the DB
551 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000552static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000553#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000554static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000555#else
556static void _db_errorCallback(const DB_ENV *db_env,
557 const char* prefix, const char* msg)
558#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000559{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000560 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000561}
562
563
Jesus Ceaef9764f2008-05-13 18:45:46 +0000564/*
565** We need these functions because some results
566** are undefined if pointer is NULL. Some other
567** give None instead of "".
568**
569** This functions are static and will be
570** -I hope- inlined.
571*/
572static const char *DummyString = "This string is a simple placeholder";
573static PyObject *Build_PyString(const char *p,int s)
574{
575 if (!p) {
576 p=DummyString;
577 assert(s==0);
578 }
Christian Heimes593daf52008-05-26 12:51:38 +0000579 return PyBytes_FromStringAndSize(p,s);
Jesus Ceaef9764f2008-05-13 18:45:46 +0000580}
581
582static PyObject *BuildValue_S(const void *p,int s)
583{
584 if (!p) {
585 p=DummyString;
586 assert(s==0);
587 }
Jesus Cea4907d272008-08-31 14:00:51 +0000588 return PyBytes_FromStringAndSize(p, s);
Jesus Ceaef9764f2008-05-13 18:45:46 +0000589}
590
591static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
592{
Jesus Cea4907d272008-08-31 14:00:51 +0000593PyObject *a, *b, *r;
594
Jesus Ceaef9764f2008-05-13 18:45:46 +0000595 if (!p1) {
596 p1=DummyString;
597 assert(s1==0);
598 }
599 if (!p2) {
600 p2=DummyString;
601 assert(s2==0);
602 }
Jesus Cea4907d272008-08-31 14:00:51 +0000603
604 if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
605 return NULL;
606 }
607 if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
608 Py_DECREF(a);
609 return NULL;
610 }
611
612#if (PY_VERSION_HEX >= 0x02040000)
613 r = PyTuple_Pack(2, a, b) ;
614#else
615 r = Py_BuildValue("OO", a, b);
616#endif
617 Py_DECREF(a);
618 Py_DECREF(b);
619 return r;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000620}
621
622static PyObject *BuildValue_IS(int i,const void *p,int s)
623{
Jesus Cea4907d272008-08-31 14:00:51 +0000624 PyObject *a, *r;
625
Jesus Ceaef9764f2008-05-13 18:45:46 +0000626 if (!p) {
627 p=DummyString;
628 assert(s==0);
629 }
Jesus Cea4907d272008-08-31 14:00:51 +0000630
631 if (!(a = PyBytes_FromStringAndSize(p, s))) {
632 return NULL;
633 }
634
635 r = Py_BuildValue("iO", i, a);
636 Py_DECREF(a);
637 return r;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000638}
639
Jesus Cea4907d272008-08-31 14:00:51 +0000640static PyObject *BuildValue_LS(long l,const void *p,int s)
Jesus Ceaef9764f2008-05-13 18:45:46 +0000641{
Jesus Cea4907d272008-08-31 14:00:51 +0000642 PyObject *a, *r;
643
Jesus Ceaef9764f2008-05-13 18:45:46 +0000644 if (!p) {
645 p=DummyString;
646 assert(s==0);
647 }
Jesus Cea4907d272008-08-31 14:00:51 +0000648
649 if (!(a = PyBytes_FromStringAndSize(p, s))) {
650 return NULL;
651 }
652
653 r = Py_BuildValue("lO", l, a);
654 Py_DECREF(a);
655 return r;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000656}
657
658
659
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000660/* make a nice exception object to raise for errors. */
661static int makeDBError(int err)
662{
663 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000664 PyObject *errObj = NULL;
665 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000666 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000667 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000668
669 switch (err) {
670 case 0: /* successful, no error */ break;
671
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000672#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000673 case DB_INCOMPLETE:
674#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000675 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
676 /* Ensure that bytes_left never goes negative */
677 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
678 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
679 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000680 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000681 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000682 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000683 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000684 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000685
686#else /* do an exception instead */
687 errObj = DBIncompleteError;
688#endif
689 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000690#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000691
692 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
693 case DB_KEYEXIST: errObj = DBKeyExistError; break;
694 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
695 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
696 case DB_NOTFOUND: errObj = DBNotFoundError; break;
697 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
698 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
699 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
700 case DB_NOSERVER: errObj = DBNoServerError; break;
701 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
702 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000703 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
704 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000705 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000706
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000707#if (DBVER >= 43)
708 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
709 case ENOMEM: errObj = PyExc_MemoryError; break;
710#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000711 case EINVAL: errObj = DBInvalidArgError; break;
712 case EACCES: errObj = DBAccessError; break;
713 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000714 case EAGAIN: errObj = DBAgainError; break;
715 case EBUSY : errObj = DBBusyError; break;
716 case EEXIST: errObj = DBFileExistsError; break;
717 case ENOENT: errObj = DBNoSuchFileError; break;
718 case EPERM : errObj = DBPermissionsError; break;
719
Jesus Ceaef9764f2008-05-13 18:45:46 +0000720#if (DBVER >= 42)
721 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
722#endif
723
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000724 case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
725
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000726 default: errObj = DBError; break;
727 }
728
729 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000730 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
731 /* Ensure that bytes_left never goes negative */
732 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
733 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
734 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000735 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000736 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000737 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000738 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000739
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000740 errTuple = Py_BuildValue("(is)", err, errTxt);
741 if (errTuple == NULL) {
742 Py_DECREF(errObj);
743 return !0;
744 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000745 PyErr_SetObject(errObj, errTuple);
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000746 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000747 }
748
749 return ((errObj != NULL) || exceptionRaised);
750}
751
752
753
754/* set a type exception */
755static void makeTypeError(char* expected, PyObject* found)
756{
757 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimese93237d2007-12-19 02:37:44 +0000758 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000759}
760
761
762/* verify that an obj is either None or a DBTxn, and set the txn pointer */
763static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
764{
765 if (txnobj == Py_None || txnobj == NULL) {
766 *txn = NULL;
767 return 1;
768 }
769 if (DBTxnObject_Check(txnobj)) {
770 *txn = ((DBTxnObject*)txnobj)->txn;
771 return 1;
772 }
773 else
774 makeTypeError("DBTxn", txnobj);
775 return 0;
776}
777
778
779/* Delete a key from a database
780 Returns 0 on success, -1 on an error. */
781static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
782{
783 int err;
784
785 MYDB_BEGIN_ALLOW_THREADS;
786 err = self->db->del(self->db, txn, key, 0);
787 MYDB_END_ALLOW_THREADS;
788 if (makeDBError(err)) {
789 return -1;
790 }
791 self->haveStat = 0;
792 return 0;
793}
794
795
796/* Store a key into a database
797 Returns 0 on success, -1 on an error. */
798static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
799{
800 int err;
801
802 MYDB_BEGIN_ALLOW_THREADS;
803 err = self->db->put(self->db, txn, key, data, flags);
804 MYDB_END_ALLOW_THREADS;
805 if (makeDBError(err)) {
806 return -1;
807 }
808 self->haveStat = 0;
809 return 0;
810}
811
812/* Get a key/data pair from a cursor */
813static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
814 PyObject *args, PyObject *kwargs, char *format)
815{
816 int err;
817 PyObject* retval = NULL;
818 DBT key, data;
819 int dlen = -1;
820 int doff = -1;
821 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000822 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000823
824 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
825 &flags, &dlen, &doff))
826 return NULL;
827
828 CHECK_CURSOR_NOT_CLOSED(self);
829
830 flags |= extra_flags;
831 CLEAR_DBT(key);
832 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000833 if (!add_partial_dbt(&data, dlen, doff))
834 return NULL;
835
836 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000837 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000838 MYDB_END_ALLOW_THREADS;
839
Gregory P. Smithe9477062005-06-04 06:46:59 +0000840 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
841 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000842 Py_INCREF(Py_None);
843 retval = Py_None;
844 }
845 else if (makeDBError(err)) {
846 retval = NULL;
847 }
848 else { /* otherwise, success! */
849
850 /* if Recno or Queue, return the key as an Int */
851 switch (_DB_get_type(self->mydb)) {
852 case -1:
853 retval = NULL;
854 break;
855
856 case DB_RECNO:
857 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000858 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000859 break;
860 case DB_HASH:
861 case DB_BTREE:
862 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000863 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000864 break;
865 }
866 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000867 return retval;
868}
869
870
871/* add an integer to a dictionary using the given name as a key */
872static void _addIntToDict(PyObject* dict, char *name, int value)
873{
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000874 PyObject* v = NUMBER_FromLong((long) value);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000875 if (!v || PyDict_SetItemString(dict, name, v))
876 PyErr_Clear();
877
878 Py_XDECREF(v);
879}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000880
881/* The same, when the value is a time_t */
882static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
883{
884 PyObject* v;
885 /* if the value fits in regular int, use that. */
Jesus Ceaef9764f2008-05-13 18:45:46 +0000886#ifdef PY_LONG_LONG
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000887 if (sizeof(time_t) > sizeof(long))
888 v = PyLong_FromLongLong((PY_LONG_LONG) value);
889 else
890#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000891 v = NUMBER_FromLong((long) value);
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000892 if (!v || PyDict_SetItemString(dict, name, v))
893 PyErr_Clear();
894
895 Py_XDECREF(v);
896}
897
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000898#if (DBVER >= 43)
899/* add an db_seq_t to a dictionary using the given name as a key */
900static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
901{
902 PyObject* v = PyLong_FromLongLong(value);
903 if (!v || PyDict_SetItemString(dict, name, v))
904 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000905
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000906 Py_XDECREF(v);
907}
908#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000909
Jesus Ceaef9764f2008-05-13 18:45:46 +0000910static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
911{
912 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
913 if (!v || PyDict_SetItemString(dict, name, v))
914 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000915
Jesus Ceaef9764f2008-05-13 18:45:46 +0000916 Py_XDECREF(v);
917}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000918
919/* --------------------------------------------------------------------- */
920/* Allocators and deallocators */
921
922static DBObject*
923newDBObject(DBEnvObject* arg, int flags)
924{
925 DBObject* self;
926 DB_ENV* db_env = NULL;
927 int err;
928
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000929 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930 if (self == NULL)
931 return NULL;
932
933 self->haveStat = 0;
934 self->flags = 0;
935 self->setflags = 0;
936 self->myenvobj = NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000937 self->db = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000938 self->children_cursors = NULL;
939#if (DBVER >=43)
940 self->children_sequences = NULL;
941#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000943 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000944 self->primaryDBType = 0;
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000945 Py_INCREF(Py_None);
Jesus Cea4907d272008-08-31 14:00:51 +0000946 self->private_obj = Py_None;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000947 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000948
949 /* keep a reference to our python DBEnv object */
950 if (arg) {
951 Py_INCREF(arg);
952 self->myenvobj = arg;
953 db_env = arg->db_env;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000954 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
955 } else {
956 self->sibling_prev_p=NULL;
957 self->sibling_next=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000958 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000959 self->txn=NULL;
960 self->sibling_prev_p_txn=NULL;
961 self->sibling_next_txn=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000962
963 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000964 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000966 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
967 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000968
969 MYDB_BEGIN_ALLOW_THREADS;
970 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000971 if (self->db != NULL) {
972 self->db->set_errcall(self->db, _db_errorCallback);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000973 self->db->app_private = (void*)self;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000974 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000975 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000976 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
977 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000978 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000979 if (makeDBError(err)) {
980 if (self->myenvobj) {
981 Py_DECREF(self->myenvobj);
982 self->myenvobj = NULL;
983 }
Gregory P. Smith664782e2008-05-17 06:12:02 +0000984 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000985 self = NULL;
986 }
987 return self;
988}
989
990
Jesus Ceaef9764f2008-05-13 18:45:46 +0000991/* Forward declaration */
Jesus Cea5cd5f122008-09-23 18:54:08 +0000992static PyObject *DB_close_internal(DBObject* self, int flags, int do_not_close);
Jesus Ceaef9764f2008-05-13 18:45:46 +0000993
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000994static void
995DB_dealloc(DBObject* self)
996{
Jesus Ceaef9764f2008-05-13 18:45:46 +0000997 PyObject *dummy;
998
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000999 if (self->db != NULL) {
Jesus Cea5cd5f122008-09-23 18:54:08 +00001000 dummy=DB_close_internal(self, 0, 0);
1001 /*
1002 ** Raising exceptions while doing
1003 ** garbage collection is a fatal error.
1004 */
1005 if (dummy)
1006 Py_DECREF(dummy);
1007 else
1008 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001009 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001010 if (self->in_weakreflist != NULL) {
1011 PyObject_ClearWeakRefs((PyObject *) self);
1012 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001013 if (self->myenvobj) {
1014 Py_DECREF(self->myenvobj);
1015 self->myenvobj = NULL;
1016 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001017 if (self->associateCallback != NULL) {
1018 Py_DECREF(self->associateCallback);
1019 self->associateCallback = NULL;
1020 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001021 if (self->btCompareCallback != NULL) {
1022 Py_DECREF(self->btCompareCallback);
1023 self->btCompareCallback = NULL;
1024 }
Jesus Cea4907d272008-08-31 14:00:51 +00001025 Py_DECREF(self->private_obj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001026 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001027}
1028
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001029static DBCursorObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001030newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001031{
Neal Norwitzb4a55812004-07-09 23:30:57 +00001032 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001033 if (self == NULL)
1034 return NULL;
1035
1036 self->dbc = dbc;
1037 self->mydb = db;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001038
1039 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
1040 if (txn && ((PyObject *)txn!=Py_None)) {
1041 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
1042 self->txn=txn;
1043 } else {
1044 self->txn=NULL;
1045 }
1046
Gregory P. Smitha703a212003-11-03 01:04:41 +00001047 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001048 Py_INCREF(self->mydb);
1049 return self;
1050}
1051
1052
Jesus Ceaef9764f2008-05-13 18:45:46 +00001053/* Forward declaration */
1054static PyObject *DBC_close_internal(DBCursorObject* self);
1055
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056static void
1057DBCursor_dealloc(DBCursorObject* self)
1058{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001059 PyObject *dummy;
Gregory P. Smitha703a212003-11-03 01:04:41 +00001060
Jesus Ceaef9764f2008-05-13 18:45:46 +00001061 if (self->dbc != NULL) {
Jesus Cea5cd5f122008-09-23 18:54:08 +00001062 dummy=DBC_close_internal(self);
1063 /*
1064 ** Raising exceptions while doing
1065 ** garbage collection is a fatal error.
1066 */
1067 if (dummy)
1068 Py_DECREF(dummy);
1069 else
1070 PyErr_Clear();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001071 }
Gregory P. Smitha703a212003-11-03 01:04:41 +00001072 if (self->in_weakreflist != NULL) {
1073 PyObject_ClearWeakRefs((PyObject *) self);
1074 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001075 Py_DECREF(self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001076 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001077}
1078
1079
1080static DBEnvObject*
1081newDBEnvObject(int flags)
1082{
1083 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001084 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001085 if (self == NULL)
1086 return NULL;
1087
Jesus Cea5cd5f122008-09-23 18:54:08 +00001088 self->db_env = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001089 self->closed = 1;
1090 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001091 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1092 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001093 self->children_dbs = NULL;
1094 self->children_txns = NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001095 Py_INCREF(Py_None);
Jesus Cea4907d272008-08-31 14:00:51 +00001096 self->private_obj = Py_None;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001097 Py_INCREF(Py_None);
1098 self->rep_transport = Py_None;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001099 self->in_weakreflist = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001100 self->event_notifyCallback = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001101
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001102 MYDB_BEGIN_ALLOW_THREADS;
1103 err = db_env_create(&self->db_env, flags);
1104 MYDB_END_ALLOW_THREADS;
1105 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001106 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001107 self = NULL;
1108 }
1109 else {
1110 self->db_env->set_errcall(self->db_env, _db_errorCallback);
Jesus Cea4907d272008-08-31 14:00:51 +00001111 self->db_env->app_private = self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001112 }
1113 return self;
1114}
1115
Jesus Ceaef9764f2008-05-13 18:45:46 +00001116/* Forward declaration */
1117static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001118
1119static void
1120DBEnv_dealloc(DBEnvObject* self)
1121{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001122 PyObject *dummy;
1123
Jesus Ceaac25fab2008-09-03 17:50:32 +00001124 if (self->db_env) {
Jesus Cea5cd5f122008-09-23 18:54:08 +00001125 dummy=DBEnv_close_internal(self, 0);
1126 /*
1127 ** Raising exceptions while doing
1128 ** garbage collection is a fatal error.
1129 */
1130 if (dummy)
1131 Py_DECREF(dummy);
1132 else
1133 PyErr_Clear();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001134 }
1135
Jesus Ceaef9764f2008-05-13 18:45:46 +00001136 Py_XDECREF(self->event_notifyCallback);
1137 self->event_notifyCallback = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001138
Gregory P. Smith31c50652004-06-28 01:20:40 +00001139 if (self->in_weakreflist != NULL) {
1140 PyObject_ClearWeakRefs((PyObject *) self);
1141 }
Jesus Cea4907d272008-08-31 14:00:51 +00001142 Py_DECREF(self->private_obj);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001143 Py_DECREF(self->rep_transport);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001144 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001145}
1146
1147
1148static DBTxnObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001149newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001150{
1151 int err;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001152 DB_TXN *parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001153
Neal Norwitzb4a55812004-07-09 23:30:57 +00001154 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001155 if (self == NULL)
1156 return NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001157
Gregory P. Smith31c50652004-06-28 01:20:40 +00001158 self->in_weakreflist = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001159 self->children_txns = NULL;
1160 self->children_dbs = NULL;
1161 self->children_cursors = NULL;
1162 self->children_sequences = NULL;
1163 self->flag_prepare = 0;
1164 self->parent_txn = NULL;
1165 self->env = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001166
Jesus Ceaef9764f2008-05-13 18:45:46 +00001167 if (parent && ((PyObject *)parent!=Py_None)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001168 parent_txn = parent->txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001169 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001170
1171 if (txn) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001172 self->txn = txn;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001173 } else {
1174 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001175 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001176 MYDB_END_ALLOW_THREADS;
1177
1178 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001179 Py_DECREF(self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001180 return NULL;
1181 }
1182 }
1183
Gregory P. Smith664782e2008-05-17 06:12:02 +00001184 /* Can't use 'parent' because could be 'parent==Py_None' */
1185 if (parent_txn) {
1186 self->parent_txn = parent;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001187 Py_INCREF(parent);
1188 self->env = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001189 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001190 } else {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001191 self->parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001192 Py_INCREF(myenv);
1193 self->env = myenv;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001194 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001195 }
1196
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001197 return self;
1198}
1199
Jesus Ceaef9764f2008-05-13 18:45:46 +00001200/* Forward declaration */
1201static PyObject *
1202DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001203
1204static void
1205DBTxn_dealloc(DBTxnObject* self)
1206{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001207 PyObject *dummy;
1208
1209 if (self->txn) {
1210 int flag_prepare = self->flag_prepare;
Jesus Cea5cd5f122008-09-23 18:54:08 +00001211
Jesus Ceaef9764f2008-05-13 18:45:46 +00001212 dummy=DBTxn_abort_discard_internal(self,0);
Jesus Cea5cd5f122008-09-23 18:54:08 +00001213 /*
1214 ** Raising exceptions while doing
1215 ** garbage collection is a fatal error.
1216 */
1217 if (dummy)
1218 Py_DECREF(dummy);
1219 else
1220 PyErr_Clear();
1221
Jesus Ceaef9764f2008-05-13 18:45:46 +00001222 if (!flag_prepare) {
1223 PyErr_Warn(PyExc_RuntimeWarning,
1224 "DBTxn aborted in destructor. No prior commit() or abort().");
1225 }
1226 }
1227
Gregory P. Smith31c50652004-06-28 01:20:40 +00001228 if (self->in_weakreflist != NULL) {
1229 PyObject_ClearWeakRefs((PyObject *) self);
1230 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001231
Jesus Ceaef9764f2008-05-13 18:45:46 +00001232 if (self->env) {
1233 Py_DECREF(self->env);
1234 } else {
1235 Py_DECREF(self->parent_txn);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001236 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001237 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001238}
1239
1240
1241static DBLockObject*
1242newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1243 db_lockmode_t lock_mode, int flags)
1244{
1245 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001246 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001247 if (self == NULL)
1248 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001249 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001250
1251 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001252 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1253 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001254 MYDB_END_ALLOW_THREADS;
1255 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001256 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001257 self = NULL;
1258 }
1259
1260 return self;
1261}
1262
1263
1264static void
1265DBLock_dealloc(DBLockObject* self)
1266{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001267 if (self->in_weakreflist != NULL) {
1268 PyObject_ClearWeakRefs((PyObject *) self);
1269 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001270 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001271
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001272 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001273}
1274
1275
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001276#if (DBVER >= 43)
1277static DBSequenceObject*
1278newDBSequenceObject(DBObject* mydb, int flags)
1279{
1280 int err;
1281 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1282 if (self == NULL)
1283 return NULL;
1284 Py_INCREF(mydb);
1285 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001286
Jesus Ceaef9764f2008-05-13 18:45:46 +00001287 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
Gregory P. Smith664782e2008-05-17 06:12:02 +00001288 self->txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001289
1290 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001291
1292 MYDB_BEGIN_ALLOW_THREADS;
1293 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1294 MYDB_END_ALLOW_THREADS;
1295 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001296 Py_DECREF(self);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001297 self = NULL;
1298 }
1299
1300 return self;
1301}
1302
Jesus Ceaef9764f2008-05-13 18:45:46 +00001303/* Forward declaration */
1304static PyObject
1305*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001306
1307static void
1308DBSequence_dealloc(DBSequenceObject* self)
1309{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001310 PyObject *dummy;
1311
1312 if (self->sequence != NULL) {
1313 dummy=DBSequence_close_internal(self,0,0);
Jesus Cea5cd5f122008-09-23 18:54:08 +00001314 /*
1315 ** Raising exceptions while doing
1316 ** garbage collection is a fatal error.
1317 */
1318 if (dummy)
1319 Py_DECREF(dummy);
1320 else
1321 PyErr_Clear();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001322 }
1323
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001324 if (self->in_weakreflist != NULL) {
1325 PyObject_ClearWeakRefs((PyObject *) self);
1326 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001327
1328 Py_DECREF(self->mydb);
1329 PyObject_Del(self);
1330}
1331#endif
1332
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001333/* --------------------------------------------------------------------- */
1334/* DB methods */
1335
1336static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00001337DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001338{
1339 PyObject* txnobj = NULL;
1340 PyObject* dataobj;
1341 db_recno_t recno;
1342 DBT key, data;
1343 DB_TXN *txn = NULL;
Jesus Cea4907d272008-08-31 14:00:51 +00001344 static char* kwnames[] = { "data", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001345
Jesus Cea4907d272008-08-31 14:00:51 +00001346 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
1347 &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001348 return NULL;
1349
1350 CHECK_DB_NOT_CLOSED(self);
1351
1352 /* make a dummy key out of a recno */
1353 recno = 0;
1354 CLEAR_DBT(key);
1355 key.data = &recno;
1356 key.size = sizeof(recno);
1357 key.ulen = key.size;
1358 key.flags = DB_DBT_USERMEM;
1359
1360 if (!make_dbt(dataobj, &data)) return NULL;
1361 if (!checkTxnObj(txnobj, &txn)) return NULL;
1362
1363 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1364 return NULL;
1365
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001366 return NUMBER_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001367}
1368
1369
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001370static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001371_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1372 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001373{
1374 int retval = DB_DONOTINDEX;
1375 DBObject* secondaryDB = (DBObject*)db->app_private;
1376 PyObject* callback = secondaryDB->associateCallback;
1377 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001378 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001379 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001380
1381
1382 if (callback != NULL) {
1383 MYDB_BEGIN_BLOCK_THREADS;
1384
Thomas Woutersb3153832006-03-08 01:47:19 +00001385 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceaef9764f2008-05-13 18:45:46 +00001386 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
Thomas Woutersb3153832006-03-08 01:47:19 +00001387 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001388 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001389 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001390 result = PyEval_CallObject(callback, args);
1391 }
1392 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001393 PyErr_Print();
1394 }
1395 else if (result == Py_None) {
1396 retval = DB_DONOTINDEX;
1397 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001398 else if (NUMBER_Check(result)) {
1399 retval = NUMBER_AsLong(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001400 }
Christian Heimes593daf52008-05-26 12:51:38 +00001401 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001402 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001403 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001404
1405 CLEAR_DBT(*secKey);
Christian Heimes593daf52008-05-26 12:51:38 +00001406 PyBytes_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001407 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1408 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001409 if (secKey->data) {
1410 memcpy(secKey->data, data, size);
1411 secKey->size = size;
1412 retval = 0;
1413 }
1414 else {
1415 PyErr_SetString(PyExc_MemoryError,
1416 "malloc failed in _db_associateCallback");
1417 PyErr_Print();
1418 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001419 }
1420 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001421 PyErr_SetString(
1422 PyExc_TypeError,
1423 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001424 PyErr_Print();
1425 }
1426
Thomas Woutersb3153832006-03-08 01:47:19 +00001427 Py_XDECREF(args);
1428 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001429
1430 MYDB_END_BLOCK_THREADS;
1431 }
1432 return retval;
1433}
1434
1435
1436static PyObject*
1437DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1438{
1439 int err, flags=0;
1440 DBObject* secondaryDB;
1441 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001442#if (DBVER >= 41)
1443 PyObject *txnobj = NULL;
1444 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001445 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001446 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001447#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001448 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001449#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001450
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001451#if (DBVER >= 41)
1452 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1453 &secondaryDB, &callback, &flags,
1454 &txnobj)) {
1455#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001457 &secondaryDB, &callback, &flags)) {
1458#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001459 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001460 }
1461
1462#if (DBVER >= 41)
1463 if (!checkTxnObj(txnobj, &txn)) return NULL;
1464#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001465
1466 CHECK_DB_NOT_CLOSED(self);
1467 if (!DBObject_Check(secondaryDB)) {
1468 makeTypeError("DB", (PyObject*)secondaryDB);
1469 return NULL;
1470 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001471 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001472 if (callback == Py_None) {
1473 callback = NULL;
1474 }
1475 else if (!PyCallable_Check(callback)) {
1476 makeTypeError("Callable", callback);
1477 return NULL;
1478 }
1479
1480 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001481 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001482 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001483 secondaryDB->associateCallback = callback;
1484 secondaryDB->primaryDBType = _DB_get_type(self);
1485
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001486 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1487 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1488 * The global interepreter lock is not initialized until the first
1489 * thread is created using thread.start_new_thread() or fork() is
1490 * called. that would cause the ALLOW_THREADS here to segfault due
1491 * to a null pointer reference if no threads or child processes
1492 * have been created. This works around that and is a no-op if
1493 * threads have already been initialized.
1494 * (see pybsddb-users mailing list post on 2002-08-07)
1495 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001496#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001497 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001498#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001499 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001500#if (DBVER >= 41)
1501 err = self->db->associate(self->db,
1502 txn,
1503 secondaryDB->db,
1504 _db_associateCallback,
1505 flags);
1506#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001507 err = self->db->associate(self->db,
1508 secondaryDB->db,
1509 _db_associateCallback,
1510 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001511#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001512 MYDB_END_ALLOW_THREADS;
1513
1514 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001515 Py_XDECREF(secondaryDB->associateCallback);
1516 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001517 secondaryDB->primaryDBType = 0;
1518 }
1519
1520 RETURN_IF_ERR();
1521 RETURN_NONE();
1522}
1523
1524
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001525static PyObject*
Jesus Cea5cd5f122008-09-23 18:54:08 +00001526DB_close_internal(DBObject* self, int flags, int do_not_close)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001527{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001528 PyObject *dummy;
Jesus Cea5cd5f122008-09-23 18:54:08 +00001529 int err = 0;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001530
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001531 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001532 /* Can be NULL if db is not in an environment */
1533 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
Jesus Cea4907d272008-08-31 14:00:51 +00001534
Jesus Ceaef9764f2008-05-13 18:45:46 +00001535 if (self->txn) {
1536 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1537 self->txn=NULL;
1538 }
1539
1540 while(self->children_cursors) {
1541 dummy=DBC_close_internal(self->children_cursors);
1542 Py_XDECREF(dummy);
1543 }
1544
1545#if (DBVER >= 43)
1546 while(self->children_sequences) {
1547 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1548 Py_XDECREF(dummy);
1549 }
1550#endif
1551
Jesus Cea5cd5f122008-09-23 18:54:08 +00001552 /*
1553 ** "do_not_close" is used to dispose all related objects in the
1554 ** tree, without actually releasing the "root" object.
1555 ** This is done, for example, because function calls like
1556 ** "DB.verify()" implicitly close the underlying handle. So
1557 ** the handle doesn't need to be closed, but related objects
1558 ** must be cleaned up.
1559 */
1560 if (!do_not_close) {
1561 MYDB_BEGIN_ALLOW_THREADS;
1562 err = self->db->close(self->db, flags);
1563 MYDB_END_ALLOW_THREADS;
1564 self->db = NULL;
1565 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001566 RETURN_IF_ERR();
1567 }
1568 RETURN_NONE();
1569}
1570
Jesus Ceaef9764f2008-05-13 18:45:46 +00001571static PyObject*
1572DB_close(DBObject* self, PyObject* args)
1573{
1574 int flags=0;
1575 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1576 return NULL;
Jesus Cea5cd5f122008-09-23 18:54:08 +00001577 return DB_close_internal(self, flags, 0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001578}
1579
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001580
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001581static PyObject*
1582_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1583{
1584 int err, flags=0, type;
1585 PyObject* txnobj = NULL;
1586 PyObject* retval = NULL;
1587 DBT key, data;
1588 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001589 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001590
1591 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1592 &txnobj, &flags))
1593 return NULL;
1594
1595 CHECK_DB_NOT_CLOSED(self);
1596 type = _DB_get_type(self);
1597 if (type == -1)
1598 return NULL;
1599 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001600 PyErr_SetString(PyExc_TypeError,
1601 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001602 return NULL;
1603 }
1604 if (!checkTxnObj(txnobj, &txn))
1605 return NULL;
1606
1607 CLEAR_DBT(key);
1608 CLEAR_DBT(data);
1609 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001610 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001611 data.flags = DB_DBT_MALLOC;
1612 key.flags = DB_DBT_MALLOC;
1613 }
1614
1615 MYDB_BEGIN_ALLOW_THREADS;
1616 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1617 MYDB_END_ALLOW_THREADS;
1618
Gregory P. Smithe9477062005-06-04 06:46:59 +00001619 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1620 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001621 err = 0;
1622 Py_INCREF(Py_None);
1623 retval = Py_None;
1624 }
1625 else if (!err) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001626 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001627 FREE_DBT(key);
1628 FREE_DBT(data);
1629 }
1630
1631 RETURN_IF_ERR();
1632 return retval;
1633}
1634
1635static PyObject*
1636DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1637{
1638 return _DB_consume(self, args, kwargs, DB_CONSUME);
1639}
1640
1641static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001642DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1643 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001644{
1645 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1646}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001647
1648
1649static PyObject*
1650DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1651{
1652 int err, flags=0;
1653 DBC* dbc;
1654 PyObject* txnobj = NULL;
1655 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001656 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657
1658 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1659 &txnobj, &flags))
1660 return NULL;
1661 CHECK_DB_NOT_CLOSED(self);
1662 if (!checkTxnObj(txnobj, &txn))
1663 return NULL;
1664
1665 MYDB_BEGIN_ALLOW_THREADS;
1666 err = self->db->cursor(self->db, txn, &dbc, flags);
1667 MYDB_END_ALLOW_THREADS;
1668 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001669 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001670}
1671
1672
1673static PyObject*
1674DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1675{
1676 PyObject* txnobj = NULL;
1677 int flags = 0;
1678 PyObject* keyobj;
1679 DBT key;
1680 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001681 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001682
1683 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1684 &keyobj, &txnobj, &flags))
1685 return NULL;
1686 CHECK_DB_NOT_CLOSED(self);
1687 if (!make_key_dbt(self, keyobj, &key, NULL))
1688 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001689 if (!checkTxnObj(txnobj, &txn)) {
1690 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001691 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001692 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001693
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001694 if (-1 == _DB_delete(self, txn, &key, 0)) {
1695 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001696 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001697 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001698
1699 FREE_DBT(key);
1700 RETURN_NONE();
1701}
1702
1703
1704static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001705DB_fd(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001706{
1707 int err, the_fd;
1708
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001709 CHECK_DB_NOT_CLOSED(self);
1710
1711 MYDB_BEGIN_ALLOW_THREADS;
1712 err = self->db->fd(self->db, &the_fd);
1713 MYDB_END_ALLOW_THREADS;
1714 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001715 return NUMBER_FromLong(the_fd);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001716}
1717
1718
1719static PyObject*
1720DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1721{
1722 int err, flags=0;
1723 PyObject* txnobj = NULL;
1724 PyObject* keyobj;
1725 PyObject* dfltobj = NULL;
1726 PyObject* retval = NULL;
1727 int dlen = -1;
1728 int doff = -1;
1729 DBT key, data;
1730 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001731 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001732 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001733
1734 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001735 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1736 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001737 return NULL;
1738
1739 CHECK_DB_NOT_CLOSED(self);
1740 if (!make_key_dbt(self, keyobj, &key, &flags))
1741 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001742 if (!checkTxnObj(txnobj, &txn)) {
1743 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001744 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001745 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001746
1747 CLEAR_DBT(data);
1748 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001749 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001750 data.flags = DB_DBT_MALLOC;
1751 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001752 if (!add_partial_dbt(&data, dlen, doff)) {
1753 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001754 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001755 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001756
1757 MYDB_BEGIN_ALLOW_THREADS;
1758 err = self->db->get(self->db, txn, &key, &data, flags);
1759 MYDB_END_ALLOW_THREADS;
1760
Gregory P. Smithe9477062005-06-04 06:46:59 +00001761 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001762 err = 0;
1763 Py_INCREF(dfltobj);
1764 retval = dfltobj;
1765 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001766 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1767 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001768 err = 0;
1769 Py_INCREF(Py_None);
1770 retval = Py_None;
1771 }
1772 else if (!err) {
1773 if (flags & DB_SET_RECNO) /* return both key and data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001774 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001775 else /* return just the data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001776 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001777 FREE_DBT(data);
1778 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001779 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001780
1781 RETURN_IF_ERR();
1782 return retval;
1783}
1784
Gregory P. Smith19699a92004-06-28 04:06:49 +00001785static PyObject*
1786DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1787{
1788 int err, flags=0;
1789 PyObject* txnobj = NULL;
1790 PyObject* keyobj;
1791 PyObject* dfltobj = NULL;
1792 PyObject* retval = NULL;
1793 int dlen = -1;
1794 int doff = -1;
1795 DBT key, pkey, data;
1796 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001797 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001798 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001799
1800 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1801 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1802 &doff))
1803 return NULL;
1804
1805 CHECK_DB_NOT_CLOSED(self);
1806 if (!make_key_dbt(self, keyobj, &key, &flags))
1807 return NULL;
1808 if (!checkTxnObj(txnobj, &txn)) {
1809 FREE_DBT(key);
1810 return NULL;
1811 }
1812
1813 CLEAR_DBT(data);
1814 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001815 /* Tell Berkeley DB to malloc the return value (thread safe) */
Gregory P. Smith19699a92004-06-28 04:06:49 +00001816 data.flags = DB_DBT_MALLOC;
1817 }
1818 if (!add_partial_dbt(&data, dlen, doff)) {
1819 FREE_DBT(key);
1820 return NULL;
1821 }
1822
1823 CLEAR_DBT(pkey);
1824 pkey.flags = DB_DBT_MALLOC;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001825
Gregory P. Smith19699a92004-06-28 04:06:49 +00001826 MYDB_BEGIN_ALLOW_THREADS;
1827 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1828 MYDB_END_ALLOW_THREADS;
1829
Gregory P. Smithe9477062005-06-04 06:46:59 +00001830 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001831 err = 0;
1832 Py_INCREF(dfltobj);
1833 retval = dfltobj;
1834 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001835 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1836 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001837 err = 0;
1838 Py_INCREF(Py_None);
1839 retval = Py_None;
1840 }
1841 else if (!err) {
1842 PyObject *pkeyObj;
1843 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001844 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001845
1846 if (self->primaryDBType == DB_RECNO ||
1847 self->primaryDBType == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001848 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001849 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001850 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001851
1852 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1853 {
1854 PyObject *keyObj;
1855 int type = _DB_get_type(self);
1856 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001857 keyObj = NUMBER_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001858 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001859 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001860#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001861 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001862#else
1863 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1864#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001865 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001866 }
1867 else /* return just the pkey and data */
1868 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001869#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001870 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001871#else
1872 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1873#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001874 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001875 Py_DECREF(dataObj);
1876 Py_DECREF(pkeyObj);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001877 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001878 FREE_DBT(data);
1879 }
1880 FREE_DBT(key);
1881
1882 RETURN_IF_ERR();
1883 return retval;
1884}
1885
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001886
1887/* Return size of entry */
1888static PyObject*
1889DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1890{
1891 int err, flags=0;
1892 PyObject* txnobj = NULL;
1893 PyObject* keyobj;
1894 PyObject* retval = NULL;
1895 DBT key, data;
1896 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001897 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001898
1899 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1900 &keyobj, &txnobj))
1901 return NULL;
1902 CHECK_DB_NOT_CLOSED(self);
1903 if (!make_key_dbt(self, keyobj, &key, &flags))
1904 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001905 if (!checkTxnObj(txnobj, &txn)) {
1906 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001907 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001908 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001909 CLEAR_DBT(data);
1910
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001911 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1912 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001913 data.flags = DB_DBT_USERMEM;
1914 data.ulen = 0;
1915 MYDB_BEGIN_ALLOW_THREADS;
1916 err = self->db->get(self->db, txn, &key, &data, flags);
1917 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001918 if (err == DB_BUFFER_SMALL) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001919 retval = NUMBER_FromLong((long)data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001920 err = 0;
1921 }
1922
1923 FREE_DBT(key);
1924 FREE_DBT(data);
1925 RETURN_IF_ERR();
1926 return retval;
1927}
1928
1929
1930static PyObject*
1931DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1932{
1933 int err, flags=0;
1934 PyObject* txnobj = NULL;
1935 PyObject* keyobj;
1936 PyObject* dataobj;
1937 PyObject* retval = NULL;
1938 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001939 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001940 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001941 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001942
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001943 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1944 &keyobj, &dataobj, &txnobj, &flags))
1945 return NULL;
1946
1947 CHECK_DB_NOT_CLOSED(self);
1948 if (!make_key_dbt(self, keyobj, &key, NULL))
1949 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001950 if ( !make_dbt(dataobj, &data) ||
1951 !checkTxnObj(txnobj, &txn) )
1952 {
1953 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001954 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001955 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001956
1957 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001958 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001959
1960 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001961 /* Tell Berkeley DB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001962 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001963 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001964 }
1965
1966 MYDB_BEGIN_ALLOW_THREADS;
1967 err = self->db->get(self->db, txn, &key, &data, flags);
1968 MYDB_END_ALLOW_THREADS;
1969
Gregory P. Smithe9477062005-06-04 06:46:59 +00001970 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1971 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001972 err = 0;
1973 Py_INCREF(Py_None);
1974 retval = Py_None;
1975 }
1976 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001977 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001978 retval = Build_PyString(data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001979
1980 /* Even though the flags require DB_DBT_MALLOC, data is not always
1981 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1982 if (data.data != orig_data)
1983 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001984 }
1985
1986 FREE_DBT(key);
1987 RETURN_IF_ERR();
1988 return retval;
1989}
1990
1991
1992static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001993DB_get_byteswapped(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001994{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001995 int err = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001996 int retval = -1;
1997
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001998 CHECK_DB_NOT_CLOSED(self);
1999
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002000 MYDB_BEGIN_ALLOW_THREADS;
2001 err = self->db->get_byteswapped(self->db, &retval);
2002 MYDB_END_ALLOW_THREADS;
2003 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002004 return NUMBER_FromLong(retval);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002005}
2006
2007
2008static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002009DB_get_type(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002010{
2011 int type;
2012
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002013 CHECK_DB_NOT_CLOSED(self);
2014
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002015 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002016 if (type == -1)
2017 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002018 return NUMBER_FromLong(type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002019}
2020
2021
2022static PyObject*
2023DB_join(DBObject* self, PyObject* args)
2024{
2025 int err, flags=0;
2026 int length, x;
2027 PyObject* cursorsObj;
2028 DBC** cursors;
2029 DBC* dbc;
2030
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002031 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
2032 return NULL;
2033
2034 CHECK_DB_NOT_CLOSED(self);
2035
2036 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002037 PyErr_SetString(PyExc_TypeError,
2038 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002039 return NULL;
2040 }
2041
2042 length = PyObject_Length(cursorsObj);
2043 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00002044 if (!cursors) {
2045 PyErr_NoMemory();
2046 return NULL;
2047 }
2048
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002049 cursors[length] = NULL;
2050 for (x=0; x<length; x++) {
2051 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00002052 if (item == NULL) {
2053 free(cursors);
2054 return NULL;
2055 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002056 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002057 PyErr_SetString(PyExc_TypeError,
2058 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002059 free(cursors);
2060 return NULL;
2061 }
2062 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002063 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002064 }
2065
2066 MYDB_BEGIN_ALLOW_THREADS;
2067 err = self->db->join(self->db, cursors, &dbc, flags);
2068 MYDB_END_ALLOW_THREADS;
2069 free(cursors);
2070 RETURN_IF_ERR();
2071
Gregory P. Smith7441e652003-11-03 21:35:31 +00002072 /* FIXME: this is a buggy interface. The returned cursor
2073 contains internal references to the passed in cursors
2074 but does not hold python references to them or prevent
2075 them from being closed prematurely. This can cause
2076 python to crash when things are done in the wrong order. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00002077 return (PyObject*) newDBCursorObject(dbc, NULL, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002078}
2079
2080
2081static PyObject*
2082DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
2083{
2084 int err, flags=0;
2085 PyObject* txnobj = NULL;
2086 PyObject* keyobj;
2087 DBT key;
2088 DB_TXN *txn = NULL;
2089 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002090 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002091
2092 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
2093 &keyobj, &txnobj, &flags))
2094 return NULL;
2095 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002096 if (!make_dbt(keyobj, &key))
2097 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002098 return NULL;
2099 if (!checkTxnObj(txnobj, &txn))
2100 return NULL;
2101
2102 MYDB_BEGIN_ALLOW_THREADS;
2103 err = self->db->key_range(self->db, txn, &key, &range, flags);
2104 MYDB_END_ALLOW_THREADS;
2105
2106 RETURN_IF_ERR();
2107 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2108}
2109
2110
2111static PyObject*
2112DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2113{
2114 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2115 char* filename = NULL;
2116 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002117#if (DBVER >= 41)
2118 PyObject *txnobj = NULL;
2119 DB_TXN *txn = NULL;
2120 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002121 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002122 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2123 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00002124 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002125 "filename", "dbtype", "flags", "mode", "txn", NULL};
2126#else
2127 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002128 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002129 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2130 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002131 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002132 "filename", "dbtype", "flags", "mode", NULL};
2133#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002134
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002135#if (DBVER >= 41)
2136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2137 &filename, &dbname, &type, &flags, &mode,
2138 &txnobj))
2139#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002140 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002141 &filename, &dbname, &type, &flags,
2142 &mode))
2143#endif
2144 {
2145 PyErr_Clear();
2146 type = DB_UNKNOWN; flags = 0; mode = 0660;
2147 filename = NULL; dbname = NULL;
2148#if (DBVER >= 41)
2149 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2150 kwnames_basic,
2151 &filename, &type, &flags, &mode,
2152 &txnobj))
2153 return NULL;
2154#else
2155 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2156 kwnames_basic,
2157 &filename, &type, &flags, &mode))
2158 return NULL;
2159#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002160 }
2161
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002162#if (DBVER >= 41)
2163 if (!checkTxnObj(txnobj, &txn)) return NULL;
2164#endif
2165
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002166 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002167 PyObject *t = Py_BuildValue("(is)", 0,
2168 "Cannot call open() twice for DB object");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002169 if (t) {
2170 PyErr_SetObject(DBError, t);
2171 Py_DECREF(t);
2172 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002173 return NULL;
2174 }
2175
Jesus Ceaef9764f2008-05-13 18:45:46 +00002176#if (DBVER >= 41)
2177 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2178 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2179 self->txn=(DBTxnObject *)txnobj;
2180 } else {
2181 self->txn=NULL;
2182 }
2183#else
2184 self->txn=NULL;
2185#endif
2186
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002187 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002188#if (DBVER >= 41)
2189 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2190#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002191 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002192#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002193 MYDB_END_ALLOW_THREADS;
2194 if (makeDBError(err)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002195 PyObject *dummy;
2196
Jesus Cea5cd5f122008-09-23 18:54:08 +00002197 dummy=DB_close_internal(self, 0, 0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002198 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002199 return NULL;
2200 }
2201
Gregory P. Smithfc006692007-11-05 09:06:28 +00002202#if (DBVER >= 42)
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002203 self->db->get_flags(self->db, &self->setflags);
Gregory P. Smithfc006692007-11-05 09:06:28 +00002204#endif
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002205
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002206 self->flags = flags;
Jesus Ceaef9764f2008-05-13 18:45:46 +00002207
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002208 RETURN_NONE();
2209}
2210
2211
2212static PyObject*
2213DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2214{
2215 int flags=0;
2216 PyObject* txnobj = NULL;
2217 int dlen = -1;
2218 int doff = -1;
2219 PyObject* keyobj, *dataobj, *retval;
2220 DBT key, data;
2221 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002222 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002223 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002224
2225 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2226 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2227 return NULL;
2228
2229 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002230 if (!make_key_dbt(self, keyobj, &key, NULL))
2231 return NULL;
2232 if ( !make_dbt(dataobj, &data) ||
2233 !add_partial_dbt(&data, dlen, doff) ||
2234 !checkTxnObj(txnobj, &txn) )
2235 {
2236 FREE_DBT(key);
2237 return NULL;
2238 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002239
2240 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2241 FREE_DBT(key);
2242 return NULL;
2243 }
2244
2245 if (flags & DB_APPEND)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002246 retval = NUMBER_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002247 else {
2248 retval = Py_None;
2249 Py_INCREF(retval);
2250 }
2251 FREE_DBT(key);
2252 return retval;
2253}
2254
2255
2256
2257static PyObject*
2258DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2259{
2260 char* filename;
2261 char* database = NULL;
2262 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002263 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002264
2265 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2266 &filename, &database, &flags))
2267 return NULL;
2268 CHECK_DB_NOT_CLOSED(self);
2269
Jesus Cea4907d272008-08-31 14:00:51 +00002270 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
2271
2272 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002273 err = self->db->remove(self->db, filename, database, flags);
Jesus Cea4907d272008-08-31 14:00:51 +00002274 MYDB_END_ALLOW_THREADS;
2275
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002276 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002277 RETURN_IF_ERR();
2278 RETURN_NONE();
2279}
2280
2281
2282
2283static PyObject*
2284DB_rename(DBObject* self, PyObject* args)
2285{
2286 char* filename;
2287 char* database;
2288 char* newname;
2289 int err, flags=0;
2290
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002291 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2292 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002293 return NULL;
2294 CHECK_DB_NOT_CLOSED(self);
2295
2296 MYDB_BEGIN_ALLOW_THREADS;
2297 err = self->db->rename(self->db, filename, database, newname, flags);
2298 MYDB_END_ALLOW_THREADS;
2299 RETURN_IF_ERR();
2300 RETURN_NONE();
2301}
2302
2303
2304static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002305DB_get_private(DBObject* self)
2306{
2307 /* We can give out the private field even if db is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00002308 Py_INCREF(self->private_obj);
2309 return self->private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002310}
2311
2312static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00002313DB_set_private(DBObject* self, PyObject* private_obj)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002314{
2315 /* We can set the private field even if db is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00002316 Py_DECREF(self->private_obj);
2317 Py_INCREF(private_obj);
2318 self->private_obj = private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002319 RETURN_NONE();
2320}
2321
2322
2323static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002324DB_set_bt_minkey(DBObject* self, PyObject* args)
2325{
2326 int err, minkey;
2327
2328 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2329 return NULL;
2330 CHECK_DB_NOT_CLOSED(self);
2331
2332 MYDB_BEGIN_ALLOW_THREADS;
2333 err = self->db->set_bt_minkey(self->db, minkey);
2334 MYDB_END_ALLOW_THREADS;
2335 RETURN_IF_ERR();
2336 RETURN_NONE();
2337}
2338
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002339static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002340_default_cmp(const DBT *leftKey,
2341 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002342{
2343 int res;
2344 int lsize = leftKey->size, rsize = rightKey->size;
2345
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002346 res = memcmp(leftKey->data, rightKey->data,
Georg Brandlef1701f2006-03-07 14:57:48 +00002347 lsize < rsize ? lsize : rsize);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002348
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002349 if (res == 0) {
2350 if (lsize < rsize) {
2351 res = -1;
2352 }
2353 else if (lsize > rsize) {
2354 res = 1;
2355 }
2356 }
2357 return res;
2358}
2359
2360static int
Jesus Ceaef9764f2008-05-13 18:45:46 +00002361_db_compareCallback(DB* db,
Georg Brandlef1701f2006-03-07 14:57:48 +00002362 const DBT *leftKey,
2363 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002364{
2365 int res = 0;
2366 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002367 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002368 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002369
2370 if (self == NULL || self->btCompareCallback == NULL) {
2371 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002372 PyErr_SetString(PyExc_TypeError,
2373 (self == 0
2374 ? "DB_bt_compare db is NULL."
2375 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002376 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002377 PyErr_Print();
2378 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002379 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002380 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002381 MYDB_BEGIN_BLOCK_THREADS;
2382
Jesus Ceaef9764f2008-05-13 18:45:46 +00002383 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002384 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002385 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002386 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002387 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002388 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002389 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002390 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002391 PyErr_Print();
2392 res = _default_cmp(leftKey, rightKey);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002393 } else if (NUMBER_Check(result)) {
2394 res = NUMBER_AsLong(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002395 } else {
2396 PyErr_SetString(PyExc_TypeError,
2397 "DB_bt_compare callback MUST return an int.");
2398 /* we're in a callback within the DB code, we can't raise */
2399 PyErr_Print();
2400 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002401 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002402
Thomas Woutersb3153832006-03-08 01:47:19 +00002403 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002404 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002405
2406 MYDB_END_BLOCK_THREADS;
2407 }
2408 return res;
2409}
2410
2411static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002412DB_set_bt_compare(DBObject* self, PyObject* comparator)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002413{
2414 int err;
Thomas Woutersb3153832006-03-08 01:47:19 +00002415 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002416
Georg Brandlef1701f2006-03-07 14:57:48 +00002417 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002418
Georg Brandlef1701f2006-03-07 14:57:48 +00002419 if (!PyCallable_Check(comparator)) {
2420 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002421 return NULL;
2422 }
2423
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002424 /*
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002425 * Perform a test call of the comparator function with two empty
2426 * string objects here. verify that it returns an int (0).
2427 * err if not.
2428 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002429 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002430 result = PyEval_CallObject(comparator, tuple);
2431 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002432 if (result == NULL)
2433 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002434 if (!NUMBER_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002435 PyErr_SetString(PyExc_TypeError,
2436 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002437 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002438 } else if (NUMBER_AsLong(result) != 0) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002439 PyErr_SetString(PyExc_TypeError,
2440 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002441 return NULL;
2442 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002443 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002444
2445 /* We don't accept multiple set_bt_compare operations, in order to
2446 * simplify the code. This would have no real use, as one cannot
2447 * change the function once the db is opened anyway */
2448 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002449 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002450 return NULL;
2451 }
2452
Georg Brandlef1701f2006-03-07 14:57:48 +00002453 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002454 self->btCompareCallback = comparator;
2455
2456 /* This is to workaround a problem with un-initialized threads (see
2457 comment in DB_associate) */
2458#ifdef WITH_THREAD
2459 PyEval_InitThreads();
2460#endif
2461
Thomas Woutersb3153832006-03-08 01:47:19 +00002462 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002463
2464 if (err) {
2465 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002466 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002467 self->btCompareCallback = NULL;
2468 }
2469
Georg Brandlef1701f2006-03-07 14:57:48 +00002470 RETURN_IF_ERR();
2471 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002472}
2473
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002474
2475static PyObject*
2476DB_set_cachesize(DBObject* self, PyObject* args)
2477{
2478 int err;
2479 int gbytes = 0, bytes = 0, ncache = 0;
2480
2481 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2482 &gbytes,&bytes,&ncache))
2483 return NULL;
2484 CHECK_DB_NOT_CLOSED(self);
2485
2486 MYDB_BEGIN_ALLOW_THREADS;
2487 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2488 MYDB_END_ALLOW_THREADS;
2489 RETURN_IF_ERR();
2490 RETURN_NONE();
2491}
2492
2493
2494static PyObject*
2495DB_set_flags(DBObject* self, PyObject* args)
2496{
2497 int err, flags;
2498
2499 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2500 return NULL;
2501 CHECK_DB_NOT_CLOSED(self);
2502
2503 MYDB_BEGIN_ALLOW_THREADS;
2504 err = self->db->set_flags(self->db, flags);
2505 MYDB_END_ALLOW_THREADS;
2506 RETURN_IF_ERR();
2507
2508 self->setflags |= flags;
2509 RETURN_NONE();
2510}
2511
2512
2513static PyObject*
2514DB_set_h_ffactor(DBObject* self, PyObject* args)
2515{
2516 int err, ffactor;
2517
2518 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2519 return NULL;
2520 CHECK_DB_NOT_CLOSED(self);
2521
2522 MYDB_BEGIN_ALLOW_THREADS;
2523 err = self->db->set_h_ffactor(self->db, ffactor);
2524 MYDB_END_ALLOW_THREADS;
2525 RETURN_IF_ERR();
2526 RETURN_NONE();
2527}
2528
2529
2530static PyObject*
2531DB_set_h_nelem(DBObject* self, PyObject* args)
2532{
2533 int err, nelem;
2534
2535 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2536 return NULL;
2537 CHECK_DB_NOT_CLOSED(self);
2538
2539 MYDB_BEGIN_ALLOW_THREADS;
2540 err = self->db->set_h_nelem(self->db, nelem);
2541 MYDB_END_ALLOW_THREADS;
2542 RETURN_IF_ERR();
2543 RETURN_NONE();
2544}
2545
2546
2547static PyObject*
2548DB_set_lorder(DBObject* self, PyObject* args)
2549{
2550 int err, lorder;
2551
2552 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2553 return NULL;
2554 CHECK_DB_NOT_CLOSED(self);
2555
2556 MYDB_BEGIN_ALLOW_THREADS;
2557 err = self->db->set_lorder(self->db, lorder);
2558 MYDB_END_ALLOW_THREADS;
2559 RETURN_IF_ERR();
2560 RETURN_NONE();
2561}
2562
2563
2564static PyObject*
2565DB_set_pagesize(DBObject* self, PyObject* args)
2566{
2567 int err, pagesize;
2568
2569 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2570 return NULL;
2571 CHECK_DB_NOT_CLOSED(self);
2572
2573 MYDB_BEGIN_ALLOW_THREADS;
2574 err = self->db->set_pagesize(self->db, pagesize);
2575 MYDB_END_ALLOW_THREADS;
2576 RETURN_IF_ERR();
2577 RETURN_NONE();
2578}
2579
2580
2581static PyObject*
2582DB_set_re_delim(DBObject* self, PyObject* args)
2583{
2584 int err;
2585 char delim;
2586
2587 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2588 PyErr_Clear();
2589 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2590 return NULL;
2591 }
2592
2593 CHECK_DB_NOT_CLOSED(self);
2594
2595 MYDB_BEGIN_ALLOW_THREADS;
2596 err = self->db->set_re_delim(self->db, delim);
2597 MYDB_END_ALLOW_THREADS;
2598 RETURN_IF_ERR();
2599 RETURN_NONE();
2600}
2601
2602static PyObject*
2603DB_set_re_len(DBObject* self, PyObject* args)
2604{
2605 int err, len;
2606
2607 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2608 return NULL;
2609 CHECK_DB_NOT_CLOSED(self);
2610
2611 MYDB_BEGIN_ALLOW_THREADS;
2612 err = self->db->set_re_len(self->db, len);
2613 MYDB_END_ALLOW_THREADS;
2614 RETURN_IF_ERR();
2615 RETURN_NONE();
2616}
2617
2618
2619static PyObject*
2620DB_set_re_pad(DBObject* self, PyObject* args)
2621{
2622 int err;
2623 char pad;
2624
2625 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2626 PyErr_Clear();
2627 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2628 return NULL;
2629 }
2630 CHECK_DB_NOT_CLOSED(self);
2631
2632 MYDB_BEGIN_ALLOW_THREADS;
2633 err = self->db->set_re_pad(self->db, pad);
2634 MYDB_END_ALLOW_THREADS;
2635 RETURN_IF_ERR();
2636 RETURN_NONE();
2637}
2638
2639
2640static PyObject*
2641DB_set_re_source(DBObject* self, PyObject* args)
2642{
2643 int err;
2644 char *re_source;
2645
2646 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2647 return NULL;
2648 CHECK_DB_NOT_CLOSED(self);
2649
2650 MYDB_BEGIN_ALLOW_THREADS;
2651 err = self->db->set_re_source(self->db, re_source);
2652 MYDB_END_ALLOW_THREADS;
2653 RETURN_IF_ERR();
2654 RETURN_NONE();
2655}
2656
2657
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002658static PyObject*
2659DB_set_q_extentsize(DBObject* self, PyObject* args)
2660{
2661 int err;
2662 int extentsize;
2663
2664 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2665 return NULL;
2666 CHECK_DB_NOT_CLOSED(self);
2667
2668 MYDB_BEGIN_ALLOW_THREADS;
2669 err = self->db->set_q_extentsize(self->db, extentsize);
2670 MYDB_END_ALLOW_THREADS;
2671 RETURN_IF_ERR();
2672 RETURN_NONE();
2673}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002674
2675static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002676DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002677{
2678 int err, flags = 0, type;
2679 void* sp;
2680 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002681#if (DBVER >= 43)
2682 PyObject* txnobj = NULL;
2683 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002684 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002685#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002686 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002687#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002688
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002689#if (DBVER >= 43)
2690 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2691 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002692 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002693 if (!checkTxnObj(txnobj, &txn))
2694 return NULL;
2695#else
2696 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2697 return NULL;
2698#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002699 CHECK_DB_NOT_CLOSED(self);
2700
2701 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002702#if (DBVER >= 43)
2703 err = self->db->stat(self->db, txn, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002704#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002705 err = self->db->stat(self->db, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002706#endif
2707 MYDB_END_ALLOW_THREADS;
2708 RETURN_IF_ERR();
2709
2710 self->haveStat = 1;
2711
2712 /* Turn the stat structure into a dictionary */
2713 type = _DB_get_type(self);
2714 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2715 free(sp);
2716 return NULL;
2717 }
2718
2719#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2720#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2721#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2722
2723 switch (type) {
2724 case DB_HASH:
2725 MAKE_HASH_ENTRY(magic);
2726 MAKE_HASH_ENTRY(version);
2727 MAKE_HASH_ENTRY(nkeys);
2728 MAKE_HASH_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002729#if (DBVER >= 46)
2730 MAKE_HASH_ENTRY(pagecnt);
2731#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002732 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002733#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002734 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002735#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002736 MAKE_HASH_ENTRY(ffactor);
2737 MAKE_HASH_ENTRY(buckets);
2738 MAKE_HASH_ENTRY(free);
2739 MAKE_HASH_ENTRY(bfree);
2740 MAKE_HASH_ENTRY(bigpages);
2741 MAKE_HASH_ENTRY(big_bfree);
2742 MAKE_HASH_ENTRY(overflows);
2743 MAKE_HASH_ENTRY(ovfl_free);
2744 MAKE_HASH_ENTRY(dup);
2745 MAKE_HASH_ENTRY(dup_free);
2746 break;
2747
2748 case DB_BTREE:
2749 case DB_RECNO:
2750 MAKE_BT_ENTRY(magic);
2751 MAKE_BT_ENTRY(version);
2752 MAKE_BT_ENTRY(nkeys);
2753 MAKE_BT_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002754#if (DBVER >= 46)
2755 MAKE_BT_ENTRY(pagecnt);
2756#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002757 MAKE_BT_ENTRY(pagesize);
2758 MAKE_BT_ENTRY(minkey);
2759 MAKE_BT_ENTRY(re_len);
2760 MAKE_BT_ENTRY(re_pad);
2761 MAKE_BT_ENTRY(levels);
2762 MAKE_BT_ENTRY(int_pg);
2763 MAKE_BT_ENTRY(leaf_pg);
2764 MAKE_BT_ENTRY(dup_pg);
2765 MAKE_BT_ENTRY(over_pg);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002766#if (DBVER >= 43)
2767 MAKE_BT_ENTRY(empty_pg);
2768#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002769 MAKE_BT_ENTRY(free);
2770 MAKE_BT_ENTRY(int_pgfree);
2771 MAKE_BT_ENTRY(leaf_pgfree);
2772 MAKE_BT_ENTRY(dup_pgfree);
2773 MAKE_BT_ENTRY(over_pgfree);
2774 break;
2775
2776 case DB_QUEUE:
2777 MAKE_QUEUE_ENTRY(magic);
2778 MAKE_QUEUE_ENTRY(version);
2779 MAKE_QUEUE_ENTRY(nkeys);
2780 MAKE_QUEUE_ENTRY(ndata);
2781 MAKE_QUEUE_ENTRY(pagesize);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002782#if (DBVER >= 41)
Jesus Ceaef9764f2008-05-13 18:45:46 +00002783 MAKE_QUEUE_ENTRY(extentsize);
2784#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002785 MAKE_QUEUE_ENTRY(pages);
2786 MAKE_QUEUE_ENTRY(re_len);
2787 MAKE_QUEUE_ENTRY(re_pad);
2788 MAKE_QUEUE_ENTRY(pgfree);
2789#if (DBVER == 31)
2790 MAKE_QUEUE_ENTRY(start);
2791#endif
2792 MAKE_QUEUE_ENTRY(first_recno);
2793 MAKE_QUEUE_ENTRY(cur_recno);
2794 break;
2795
2796 default:
2797 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2798 Py_DECREF(d);
2799 d = NULL;
2800 }
2801
2802#undef MAKE_HASH_ENTRY
2803#undef MAKE_BT_ENTRY
2804#undef MAKE_QUEUE_ENTRY
2805
2806 free(sp);
2807 return d;
2808}
2809
2810static PyObject*
2811DB_sync(DBObject* self, PyObject* args)
2812{
2813 int err;
2814 int flags = 0;
2815
2816 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2817 return NULL;
2818 CHECK_DB_NOT_CLOSED(self);
2819
2820 MYDB_BEGIN_ALLOW_THREADS;
2821 err = self->db->sync(self->db, flags);
2822 MYDB_END_ALLOW_THREADS;
2823 RETURN_IF_ERR();
2824 RETURN_NONE();
2825}
2826
2827
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002828static PyObject*
2829DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2830{
2831 int err, flags=0;
2832 u_int32_t count=0;
2833 PyObject* txnobj = NULL;
2834 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002835 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002836
2837 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2838 &txnobj, &flags))
2839 return NULL;
2840 CHECK_DB_NOT_CLOSED(self);
2841 if (!checkTxnObj(txnobj, &txn))
2842 return NULL;
2843
2844 MYDB_BEGIN_ALLOW_THREADS;
2845 err = self->db->truncate(self->db, txn, &count, flags);
2846 MYDB_END_ALLOW_THREADS;
2847 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002848 return NUMBER_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002849}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850
2851
2852static PyObject*
2853DB_upgrade(DBObject* self, PyObject* args)
2854{
2855 int err, flags=0;
2856 char *filename;
2857
2858 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2859 return NULL;
2860 CHECK_DB_NOT_CLOSED(self);
2861
2862 MYDB_BEGIN_ALLOW_THREADS;
2863 err = self->db->upgrade(self->db, filename, flags);
2864 MYDB_END_ALLOW_THREADS;
2865 RETURN_IF_ERR();
2866 RETURN_NONE();
2867}
2868
2869
2870static PyObject*
2871DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2872{
2873 int err, flags=0;
2874 char* fileName;
2875 char* dbName=NULL;
2876 char* outFileName=NULL;
2877 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002878 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002879 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002880
2881 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2882 &fileName, &dbName, &outFileName, &flags))
2883 return NULL;
2884
2885 CHECK_DB_NOT_CLOSED(self);
2886 if (outFileName)
2887 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002888 /* XXX(nnorwitz): it should probably be an exception if outFile
2889 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002890
Jesus Ceaef9764f2008-05-13 18:45:46 +00002891 { /* DB.verify acts as a DB handle destructor (like close) */
2892 PyObject *error;
2893
Jesus Cea5cd5f122008-09-23 18:54:08 +00002894 error=DB_close_internal(self, 0, 1);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002895 if (error ) {
2896 return error;
2897 }
2898 }
Gregory P. Smith41631e82003-09-21 00:08:14 +00002899
Jesus Cea5cd5f122008-09-23 18:54:08 +00002900 MYDB_BEGIN_ALLOW_THREADS;
2901 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2902 MYDB_END_ALLOW_THREADS;
2903
2904 self->db = NULL; /* Implicit close; related objects already released */
2905
2906 if (outFile)
2907 fclose(outFile);
2908
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002909 RETURN_IF_ERR();
2910 RETURN_NONE();
2911}
2912
2913
2914static PyObject*
2915DB_set_get_returns_none(DBObject* self, PyObject* args)
2916{
2917 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002918 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002919
2920 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2921 return NULL;
2922 CHECK_DB_NOT_CLOSED(self);
2923
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002924 if (self->moduleFlags.getReturnsNone)
2925 ++oldValue;
2926 if (self->moduleFlags.cursorSetReturnsNone)
2927 ++oldValue;
2928 self->moduleFlags.getReturnsNone = (flags >= 1);
2929 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002930 return NUMBER_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002931}
2932
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002933#if (DBVER >= 41)
2934static PyObject*
2935DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2936{
2937 int err;
2938 u_int32_t flags=0;
2939 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002940 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002941
2942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2943 &passwd, &flags)) {
2944 return NULL;
2945 }
2946
2947 MYDB_BEGIN_ALLOW_THREADS;
2948 err = self->db->set_encrypt(self->db, passwd, flags);
2949 MYDB_END_ALLOW_THREADS;
2950
2951 RETURN_IF_ERR();
2952 RETURN_NONE();
2953}
2954#endif /* DBVER >= 41 */
2955
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002956
2957/*-------------------------------------------------------------- */
2958/* Mapping and Dictionary-like access routines */
2959
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002960Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002961{
2962 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002963 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002964 int flags = 0;
2965 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002966 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002967
2968 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002969 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002970 if (t) {
2971 PyErr_SetObject(DBError, t);
2972 Py_DECREF(t);
2973 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002974 return -1;
2975 }
2976
2977 if (self->haveStat) { /* Has the stat function been called recently? If
2978 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002979 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002980 }
2981
2982 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002983redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002984#if (DBVER >= 43)
2985 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002986#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002987 err = self->db->stat(self->db, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002988#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002989
2990 /* All the stat structures have matching fields upto the ndata field,
2991 so we can use any of them for the type cast */
2992 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2993
Jesus Ceaef9764f2008-05-13 18:45:46 +00002994 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002995 * redo a full stat to make sure.
2996 * Fixes SF python bug 1493322, pybsddb bug 1184012
2997 */
2998 if (size == 0 && (flags & DB_FAST_STAT)) {
2999 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00003000 if (!err)
3001 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00003002 goto redo_stat_for_length;
3003 }
3004
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003005 MYDB_END_ALLOW_THREADS;
3006
3007 if (err)
3008 return -1;
3009
3010 self->haveStat = 1;
3011
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003012 free(sp);
3013 return size;
3014}
3015
3016
3017PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
3018{
3019 int err;
3020 PyObject* retval;
3021 DBT key;
3022 DBT data;
3023
3024 CHECK_DB_NOT_CLOSED(self);
3025 if (!make_key_dbt(self, keyobj, &key, NULL))
3026 return NULL;
3027
3028 CLEAR_DBT(data);
3029 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003030 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003031 data.flags = DB_DBT_MALLOC;
3032 }
3033 MYDB_BEGIN_ALLOW_THREADS;
3034 err = self->db->get(self->db, NULL, &key, &data, 0);
3035 MYDB_END_ALLOW_THREADS;
3036 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3037 PyErr_SetObject(PyExc_KeyError, keyobj);
3038 retval = NULL;
3039 }
3040 else if (makeDBError(err)) {
3041 retval = NULL;
3042 }
3043 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003044 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003045 FREE_DBT(data);
3046 }
3047
3048 FREE_DBT(key);
3049 return retval;
3050}
3051
3052
3053static int
3054DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
3055{
3056 DBT key, data;
3057 int retval;
3058 int flags = 0;
3059
3060 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00003061 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003062 if (t) {
3063 PyErr_SetObject(DBError, t);
3064 Py_DECREF(t);
3065 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003066 return -1;
3067 }
3068
3069 if (!make_key_dbt(self, keyobj, &key, NULL))
3070 return -1;
3071
3072 if (dataobj != NULL) {
3073 if (!make_dbt(dataobj, &data))
3074 retval = -1;
3075 else {
3076 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003077 /* dictionaries shouldn't have duplicate keys */
3078 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003079 retval = _DB_put(self, NULL, &key, &data, flags);
3080
3081 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003082 /* try deleting any old record that matches and then PUT it
3083 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003084 _DB_delete(self, NULL, &key, 0);
3085 PyErr_Clear();
3086 retval = _DB_put(self, NULL, &key, &data, flags);
3087 }
3088 }
3089 }
3090 else {
3091 /* dataobj == NULL, so delete the key */
3092 retval = _DB_delete(self, NULL, &key, 0);
3093 }
3094 FREE_DBT(key);
3095 return retval;
3096}
3097
3098
3099static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00003100DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003101{
3102 int err;
3103 PyObject* keyobj;
3104 DBT key, data;
3105 PyObject* txnobj = NULL;
3106 DB_TXN *txn = NULL;
Jesus Cea4907d272008-08-31 14:00:51 +00003107 static char* kwnames[] = {"key","txn", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003108
Jesus Cea4907d272008-08-31 14:00:51 +00003109 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
3110 &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003111 return NULL;
Jesus Cea4907d272008-08-31 14:00:51 +00003112
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003113 CHECK_DB_NOT_CLOSED(self);
3114 if (!make_key_dbt(self, keyobj, &key, NULL))
3115 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003116 if (!checkTxnObj(txnobj, &txn)) {
3117 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003118 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003119 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003120
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003121 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003122 it has a record but can't allocate a buffer for the data. This saves
3123 having to deal with data we won't be using.
3124 */
3125 CLEAR_DBT(data);
3126 data.flags = DB_DBT_USERMEM;
3127
3128 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00003129 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003130 MYDB_END_ALLOW_THREADS;
3131 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003132
3133 if (err == DB_BUFFER_SMALL || err == 0) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003134 return NUMBER_FromLong(1);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003135 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003136 return NUMBER_FromLong(0);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003137 }
3138
3139 makeDBError(err);
3140 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003141}
3142
3143
3144#define _KEYS_LIST 1
3145#define _VALUES_LIST 2
3146#define _ITEMS_LIST 3
3147
3148static PyObject*
3149_DB_make_list(DBObject* self, DB_TXN* txn, int type)
3150{
3151 int err, dbtype;
3152 DBT key;
3153 DBT data;
3154 DBC *cursor;
3155 PyObject* list;
3156 PyObject* item = NULL;
3157
3158 CHECK_DB_NOT_CLOSED(self);
3159 CLEAR_DBT(key);
3160 CLEAR_DBT(data);
3161
3162 dbtype = _DB_get_type(self);
3163 if (dbtype == -1)
3164 return NULL;
3165
3166 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00003167 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003168 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003169
3170 /* get a cursor */
3171 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00003172 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00003174 if (makeDBError(err)) {
3175 Py_DECREF(list);
3176 return NULL;
3177 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003178
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003179 while (1) { /* use the cursor to traverse the DB, collecting items */
3180 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003181 err = _DBC_get(cursor, &key, &data, DB_NEXT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003182 MYDB_END_ALLOW_THREADS;
3183
3184 if (err) {
3185 /* for any error, break out of the loop */
3186 break;
3187 }
3188
3189 switch (type) {
3190 case _KEYS_LIST:
3191 switch(dbtype) {
3192 case DB_BTREE:
3193 case DB_HASH:
3194 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003195 item = Build_PyString(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003196 break;
3197 case DB_RECNO:
3198 case DB_QUEUE:
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003199 item = NUMBER_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003200 break;
3201 }
3202 break;
3203
3204 case _VALUES_LIST:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003205 item = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003206 break;
3207
3208 case _ITEMS_LIST:
3209 switch(dbtype) {
3210 case DB_BTREE:
3211 case DB_HASH:
3212 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003213 item = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003214 break;
3215 case DB_RECNO:
3216 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003217 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003218 break;
3219 }
3220 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00003221 default:
3222 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3223 item = NULL;
3224 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003225 }
3226 if (item == NULL) {
3227 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003228 list = NULL;
3229 goto done;
3230 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003231 if (PyList_Append(list, item)) {
3232 Py_DECREF(list);
3233 Py_DECREF(item);
3234 list = NULL;
3235 goto done;
3236 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003237 Py_DECREF(item);
3238 }
3239
Gregory P. Smithe9477062005-06-04 06:46:59 +00003240 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3241 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003242 Py_DECREF(list);
3243 list = NULL;
3244 }
3245
3246 done:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003247 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003248 _DBC_close(cursor);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003249 MYDB_END_ALLOW_THREADS;
3250 return list;
3251}
3252
3253
3254static PyObject*
3255DB_keys(DBObject* self, PyObject* args)
3256{
3257 PyObject* txnobj = NULL;
3258 DB_TXN *txn = NULL;
3259
Georg Brandl96a8c392006-05-29 21:04:52 +00003260 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003261 return NULL;
3262 if (!checkTxnObj(txnobj, &txn))
3263 return NULL;
3264 return _DB_make_list(self, txn, _KEYS_LIST);
3265}
3266
3267
3268static PyObject*
3269DB_items(DBObject* self, PyObject* args)
3270{
3271 PyObject* txnobj = NULL;
3272 DB_TXN *txn = NULL;
3273
Georg Brandl96a8c392006-05-29 21:04:52 +00003274 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003275 return NULL;
3276 if (!checkTxnObj(txnobj, &txn))
3277 return NULL;
3278 return _DB_make_list(self, txn, _ITEMS_LIST);
3279}
3280
3281
3282static PyObject*
3283DB_values(DBObject* self, PyObject* args)
3284{
3285 PyObject* txnobj = NULL;
3286 DB_TXN *txn = NULL;
3287
Georg Brandl96a8c392006-05-29 21:04:52 +00003288 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003289 return NULL;
3290 if (!checkTxnObj(txnobj, &txn))
3291 return NULL;
3292 return _DB_make_list(self, txn, _VALUES_LIST);
3293}
3294
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003295/* --------------------------------------------------------------------- */
3296/* DBCursor methods */
3297
3298
3299static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003300DBC_close_internal(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003301{
3302 int err = 0;
3303
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003304 if (self->dbc != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003305 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3306 if (self->txn) {
3307 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3308 self->txn=NULL;
3309 }
3310
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003311 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003312 err = _DBC_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003313 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003314 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003315 }
3316 RETURN_IF_ERR();
3317 RETURN_NONE();
3318}
3319
Jesus Ceaef9764f2008-05-13 18:45:46 +00003320static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003321DBC_close(DBCursorObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00003322{
Jesus Ceaef9764f2008-05-13 18:45:46 +00003323 return DBC_close_internal(self);
3324}
3325
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003326
3327static PyObject*
3328DBC_count(DBCursorObject* self, PyObject* args)
3329{
3330 int err = 0;
3331 db_recno_t count;
3332 int flags = 0;
3333
3334 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3335 return NULL;
3336
3337 CHECK_CURSOR_NOT_CLOSED(self);
3338
3339 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003340 err = _DBC_count(self->dbc, &count, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003341 MYDB_END_ALLOW_THREADS;
3342 RETURN_IF_ERR();
3343
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003344 return NUMBER_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003345}
3346
3347
3348static PyObject*
3349DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3350{
3351 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3352}
3353
3354
3355static PyObject*
3356DBC_delete(DBCursorObject* self, PyObject* args)
3357{
3358 int err, flags=0;
3359
3360 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3361 return NULL;
3362
3363 CHECK_CURSOR_NOT_CLOSED(self);
3364
3365 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003366 err = _DBC_del(self->dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003367 MYDB_END_ALLOW_THREADS;
3368 RETURN_IF_ERR();
3369
3370 self->mydb->haveStat = 0;
3371 RETURN_NONE();
3372}
3373
3374
3375static PyObject*
3376DBC_dup(DBCursorObject* self, PyObject* args)
3377{
3378 int err, flags =0;
3379 DBC* dbc = NULL;
3380
3381 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3382 return NULL;
3383
3384 CHECK_CURSOR_NOT_CLOSED(self);
3385
3386 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003387 err = _DBC_dup(self->dbc, &dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003388 MYDB_END_ALLOW_THREADS;
3389 RETURN_IF_ERR();
3390
Jesus Ceaef9764f2008-05-13 18:45:46 +00003391 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003392}
3393
3394static PyObject*
3395DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3396{
3397 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3398}
3399
3400
3401static PyObject*
3402DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3403{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003404 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003405 PyObject* keyobj = NULL;
3406 PyObject* dataobj = NULL;
3407 PyObject* retval = NULL;
3408 int dlen = -1;
3409 int doff = -1;
3410 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003411 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003412 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003413
3414 CLEAR_DBT(key);
3415 CLEAR_DBT(data);
3416 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003417 &flags, &dlen, &doff))
3418 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003419 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003420 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
Jesus Cea4907d272008-08-31 14:00:51 +00003421 &kwnames[1],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003422 &keyobj, &flags, &dlen, &doff))
3423 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003424 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003425 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3426 kwnames, &keyobj, &dataobj,
3427 &flags, &dlen, &doff))
3428 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003429 return NULL;
3430 }
3431 }
3432 }
3433
3434 CHECK_CURSOR_NOT_CLOSED(self);
3435
3436 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3437 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003438 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3439 (!add_partial_dbt(&data, dlen, doff)) )
3440 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003441 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003442 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003443 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003444
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003445 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003446 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003447 MYDB_END_ALLOW_THREADS;
3448
Gregory P. Smithe9477062005-06-04 06:46:59 +00003449 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3450 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003451 Py_INCREF(Py_None);
3452 retval = Py_None;
3453 }
3454 else if (makeDBError(err)) {
3455 retval = NULL;
3456 }
3457 else {
3458 switch (_DB_get_type(self->mydb)) {
3459 case -1:
3460 retval = NULL;
3461 break;
3462 case DB_BTREE:
3463 case DB_HASH:
3464 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003465 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003466 break;
3467 case DB_RECNO:
3468 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003469 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003470 break;
3471 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003472 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003473 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003474 return retval;
3475}
3476
Gregory P. Smith19699a92004-06-28 04:06:49 +00003477static PyObject*
3478DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3479{
3480 int err, flags=0;
3481 PyObject* keyobj = NULL;
3482 PyObject* dataobj = NULL;
3483 PyObject* retval = NULL;
3484 int dlen = -1;
3485 int doff = -1;
3486 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003487 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3488 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003489
3490 CLEAR_DBT(key);
3491 CLEAR_DBT(data);
3492 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3493 &flags, &dlen, &doff))
3494 {
3495 PyErr_Clear();
3496 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003497 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003498 &keyobj, &flags, &dlen, &doff))
3499 {
3500 PyErr_Clear();
3501 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3502 kwnames, &keyobj, &dataobj,
3503 &flags, &dlen, &doff))
3504 {
3505 return NULL;
3506 }
3507 }
3508 }
3509
3510 CHECK_CURSOR_NOT_CLOSED(self);
3511
3512 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3513 return NULL;
3514 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3515 (!add_partial_dbt(&data, dlen, doff)) ) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003516 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003517 return NULL;
3518 }
3519
Gregory P. Smith19699a92004-06-28 04:06:49 +00003520 CLEAR_DBT(pkey);
3521 pkey.flags = DB_DBT_MALLOC;
3522
3523 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003524 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003525 MYDB_END_ALLOW_THREADS;
3526
Gregory P. Smithe9477062005-06-04 06:46:59 +00003527 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3528 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003529 Py_INCREF(Py_None);
3530 retval = Py_None;
3531 }
3532 else if (makeDBError(err)) {
3533 retval = NULL;
3534 }
3535 else {
3536 PyObject *pkeyObj;
3537 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003538 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003539
3540 if (self->mydb->primaryDBType == DB_RECNO ||
3541 self->mydb->primaryDBType == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003542 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003543 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003544 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003545
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003546 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003547 {
3548 PyObject *keyObj;
3549 int type = _DB_get_type(self->mydb);
3550 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003551 keyObj = NUMBER_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003552 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003553 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003554#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003555 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003556#else
3557 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3558#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003559 Py_DECREF(keyObj);
Jesus Ceaef9764f2008-05-13 18:45:46 +00003560 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003561 }
3562 else /* return just the pkey and data */
3563 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003564#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003565 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003566#else
3567 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3568#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003569 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003570 Py_DECREF(dataObj);
3571 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003572 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003573 }
3574 /* the only time REALLOC should be set is if we used an integer
3575 * key that make_key_dbt malloc'd for us. always free these. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003576 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003577 FREE_DBT(key);
3578 }
3579 return retval;
3580}
3581
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003582
3583static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003584DBC_get_recno(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003585{
3586 int err;
3587 db_recno_t recno;
3588 DBT key;
3589 DBT data;
3590
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003591 CHECK_CURSOR_NOT_CLOSED(self);
3592
3593 CLEAR_DBT(key);
3594 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003595
3596 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003597 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003598 MYDB_END_ALLOW_THREADS;
3599 RETURN_IF_ERR();
3600
3601 recno = *((db_recno_t*)data.data);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003602 return NUMBER_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003603}
3604
3605
3606static PyObject*
3607DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3608{
3609 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3610}
3611
3612
3613static PyObject*
3614DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3615{
3616 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3617}
3618
3619
3620static PyObject*
3621DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3622{
3623 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3624}
3625
3626
3627static PyObject*
3628DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3629{
3630 int err, flags = 0;
3631 PyObject* keyobj, *dataobj;
3632 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003633 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003634 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003635 int dlen = -1;
3636 int doff = -1;
3637
3638 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3639 &keyobj, &dataobj, &flags, &dlen, &doff))
3640 return NULL;
3641
3642 CHECK_CURSOR_NOT_CLOSED(self);
3643
3644 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3645 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003646 if (!make_dbt(dataobj, &data) ||
3647 !add_partial_dbt(&data, dlen, doff) )
3648 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003649 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003650 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003651 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003652
3653 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003654 err = _DBC_put(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003655 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003656 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003657 RETURN_IF_ERR();
3658 self->mydb->haveStat = 0;
3659 RETURN_NONE();
3660}
3661
3662
3663static PyObject*
3664DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3665{
3666 int err, flags = 0;
3667 DBT key, data;
3668 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003669 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003670 int dlen = -1;
3671 int doff = -1;
3672
3673 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3674 &keyobj, &flags, &dlen, &doff))
3675 return NULL;
3676
3677 CHECK_CURSOR_NOT_CLOSED(self);
3678
3679 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3680 return NULL;
3681
3682 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003683 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003684 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003685 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003686 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003687
3688 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003689 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003690 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003691 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3692 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003693 Py_INCREF(Py_None);
3694 retval = Py_None;
3695 }
3696 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003697 retval = NULL;
3698 }
3699 else {
3700 switch (_DB_get_type(self->mydb)) {
3701 case -1:
3702 retval = NULL;
3703 break;
3704 case DB_BTREE:
3705 case DB_HASH:
3706 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003707 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003708 break;
3709 case DB_RECNO:
3710 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003711 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003712 break;
3713 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003714 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003715 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003716 /* the only time REALLOC should be set is if we used an integer
3717 * key that make_key_dbt malloc'd for us. always free these. */
3718 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003719 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003720 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003721
3722 return retval;
3723}
3724
3725
3726static PyObject*
3727DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3728{
3729 int err, flags = 0;
3730 DBT key, data;
3731 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003732 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003733 int dlen = -1;
3734 int doff = -1;
3735
3736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3737 &keyobj, &flags, &dlen, &doff))
3738 return NULL;
3739
3740 CHECK_CURSOR_NOT_CLOSED(self);
3741
3742 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3743 return NULL;
3744
3745 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003746 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003747 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003748 return NULL;
3749 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003750 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003751 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003752 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003753 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3754 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003755 Py_INCREF(Py_None);
3756 retval = Py_None;
3757 }
3758 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003759 retval = NULL;
3760 }
3761 else {
3762 switch (_DB_get_type(self->mydb)) {
3763 case -1:
3764 retval = NULL;
3765 break;
3766 case DB_BTREE:
3767 case DB_HASH:
3768 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003769 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003770 break;
3771 case DB_RECNO:
3772 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003773 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003774 break;
3775 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003776 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003777 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003778 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003779 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003780 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003781 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003782 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003783
3784 return retval;
3785}
3786
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003787static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003788_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3789 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003790{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003791 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003792 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003793 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003794
Gregory P. Smith7441e652003-11-03 21:35:31 +00003795 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003796 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3797 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003798 if (!make_dbt(dataobj, &data)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003799 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003800 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003801 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003802
3803 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003804 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003805 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003806 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003807 Py_INCREF(Py_None);
3808 retval = Py_None;
3809 }
3810 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003811 retval = NULL;
3812 }
3813 else {
3814 switch (_DB_get_type(self->mydb)) {
3815 case -1:
3816 retval = NULL;
3817 break;
3818 case DB_BTREE:
3819 case DB_HASH:
3820 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003821 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003822 break;
3823 case DB_RECNO:
3824 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003825 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003826 break;
3827 }
3828 }
3829
Jesus Ceaef9764f2008-05-13 18:45:46 +00003830 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003831 return retval;
3832}
3833
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003834static PyObject*
3835DBC_get_both(DBCursorObject* self, PyObject* args)
3836{
3837 int flags=0;
3838 PyObject *keyobj, *dataobj;
3839
3840 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3841 return NULL;
3842
Gregory P. Smith7441e652003-11-03 21:35:31 +00003843 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003844 CHECK_CURSOR_NOT_CLOSED(self);
3845
3846 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3847 self->mydb->moduleFlags.getReturnsNone);
3848}
3849
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003850/* Return size of entry */
3851static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003852DBC_get_current_size(DBCursorObject* self)
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003853{
3854 int err, flags=DB_CURRENT;
3855 PyObject* retval = NULL;
3856 DBT key, data;
3857
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003858 CHECK_CURSOR_NOT_CLOSED(self);
3859 CLEAR_DBT(key);
3860 CLEAR_DBT(data);
3861
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003862 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003863 getting the record size. */
3864 data.flags = DB_DBT_USERMEM;
3865 data.ulen = 0;
3866 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003867 err = _DBC_get(self->dbc, &key, &data, flags);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003868 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003869 if (err == DB_BUFFER_SMALL || !err) {
3870 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003871 retval = NUMBER_FromLong((long)data.size);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003872 err = 0;
3873 }
3874
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003875 RETURN_IF_ERR();
3876 return retval;
3877}
3878
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003879static PyObject*
3880DBC_set_both(DBCursorObject* self, PyObject* args)
3881{
3882 int flags=0;
3883 PyObject *keyobj, *dataobj;
3884
3885 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3886 return NULL;
3887
Gregory P. Smith7441e652003-11-03 21:35:31 +00003888 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003889 CHECK_CURSOR_NOT_CLOSED(self);
3890
3891 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3892 self->mydb->moduleFlags.cursorSetReturnsNone);
3893}
3894
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003895
3896static PyObject*
3897DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3898{
3899 int err, irecno, flags=0;
3900 db_recno_t recno;
3901 DBT key, data;
3902 PyObject* retval;
3903 int dlen = -1;
3904 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003905 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003906
3907 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3908 &irecno, &flags, &dlen, &doff))
3909 return NULL;
3910
3911 CHECK_CURSOR_NOT_CLOSED(self);
3912
3913 CLEAR_DBT(key);
3914 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003915 /* use allocated space so DB will be able to realloc room for the real
3916 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003917 key.data = malloc(sizeof(db_recno_t));
3918 if (key.data == NULL) {
3919 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3920 return NULL;
3921 }
3922 key.size = sizeof(db_recno_t);
3923 key.ulen = key.size;
3924 memcpy(key.data, &recno, sizeof(db_recno_t));
3925 key.flags = DB_DBT_REALLOC;
3926
3927 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003928 if (!add_partial_dbt(&data, dlen, doff)) {
3929 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003930 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003931 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003932
3933 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003934 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003935 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003936 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3937 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003938 Py_INCREF(Py_None);
3939 retval = Py_None;
3940 }
3941 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003942 retval = NULL;
3943 }
3944 else { /* Can only be used for BTrees, so no need to return int key */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003945 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003946 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003947 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003948
3949 return retval;
3950}
3951
3952
3953static PyObject*
3954DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3955{
3956 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3957}
3958
3959
3960static PyObject*
3961DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3962{
3963 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3964}
3965
3966
3967static PyObject*
3968DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3969{
3970 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3971}
3972
3973
3974static PyObject*
3975DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3976{
3977 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3978}
3979
3980
3981static PyObject*
3982DBC_join_item(DBCursorObject* self, PyObject* args)
3983{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003984 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003985 DBT key, data;
3986 PyObject* retval;
3987
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003988 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003989 return NULL;
3990
3991 CHECK_CURSOR_NOT_CLOSED(self);
3992
3993 CLEAR_DBT(key);
3994 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003995
3996 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003997 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003998 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003999 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
4000 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004001 Py_INCREF(Py_None);
4002 retval = Py_None;
4003 }
4004 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004005 retval = NULL;
4006 }
4007 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00004008 retval = BuildValue_S(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004009 }
4010
4011 return retval;
4012}
4013
4014
4015
4016/* --------------------------------------------------------------------- */
4017/* DBEnv methods */
4018
4019
4020static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00004021DBEnv_close_internal(DBEnvObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004022{
Jesus Ceaef9764f2008-05-13 18:45:46 +00004023 PyObject *dummy;
4024 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004025
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004026 if (!self->closed) { /* Don't close more than once */
Jesus Ceaef9764f2008-05-13 18:45:46 +00004027 while(self->children_txns) {
4028 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
4029 Py_XDECREF(dummy);
4030 }
4031 while(self->children_dbs) {
Jesus Cea5cd5f122008-09-23 18:54:08 +00004032 dummy=DB_close_internal(self->children_dbs, 0, 0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004033 Py_XDECREF(dummy);
4034 }
Jesus Ceaac25fab2008-09-03 17:50:32 +00004035 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00004036
Jesus Ceaac25fab2008-09-03 17:50:32 +00004037 self->closed = 1;
4038 if (self->db_env) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004039 MYDB_BEGIN_ALLOW_THREADS;
4040 err = self->db_env->close(self->db_env, flags);
4041 MYDB_END_ALLOW_THREADS;
4042 /* after calling DBEnv->close, regardless of error, this DBEnv
Jesus Ceaef9764f2008-05-13 18:45:46 +00004043 * may not be accessed again (Berkeley DB docs). */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004044 self->db_env = NULL;
4045 RETURN_IF_ERR();
4046 }
4047 RETURN_NONE();
4048}
4049
Jesus Ceaef9764f2008-05-13 18:45:46 +00004050static PyObject*
4051DBEnv_close(DBEnvObject* self, PyObject* args)
4052{
4053 int flags = 0;
4054
4055 if (!PyArg_ParseTuple(args, "|i:close", &flags))
4056 return NULL;
Jesus Cea5cd5f122008-09-23 18:54:08 +00004057 return DBEnv_close_internal(self, flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004058}
4059
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004060
4061static PyObject*
4062DBEnv_open(DBEnvObject* self, PyObject* args)
4063{
4064 int err, flags=0, mode=0660;
4065 char *db_home;
4066
4067 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
4068 return NULL;
4069
4070 CHECK_ENV_NOT_CLOSED(self);
4071
4072 MYDB_BEGIN_ALLOW_THREADS;
4073 err = self->db_env->open(self->db_env, db_home, flags, mode);
4074 MYDB_END_ALLOW_THREADS;
4075 RETURN_IF_ERR();
4076 self->closed = 0;
4077 self->flags = flags;
4078 RETURN_NONE();
4079}
4080
4081
4082static PyObject*
4083DBEnv_remove(DBEnvObject* self, PyObject* args)
4084{
4085 int err, flags=0;
4086 char *db_home;
4087
4088 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
4089 return NULL;
4090 CHECK_ENV_NOT_CLOSED(self);
4091 MYDB_BEGIN_ALLOW_THREADS;
4092 err = self->db_env->remove(self->db_env, db_home, flags);
4093 MYDB_END_ALLOW_THREADS;
4094 RETURN_IF_ERR();
4095 RETURN_NONE();
4096}
4097
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004098#if (DBVER >= 41)
4099static PyObject*
4100DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4101{
4102 int err;
4103 u_int32_t flags=0;
4104 char *file = NULL;
4105 char *database = NULL;
4106 PyObject *txnobj = NULL;
4107 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004108 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004109 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004110
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004111 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004112 &file, &database, &txnobj, &flags)) {
4113 return NULL;
4114 }
4115 if (!checkTxnObj(txnobj, &txn)) {
4116 return NULL;
4117 }
4118 CHECK_ENV_NOT_CLOSED(self);
4119 MYDB_BEGIN_ALLOW_THREADS;
4120 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4121 MYDB_END_ALLOW_THREADS;
4122 RETURN_IF_ERR();
4123 RETURN_NONE();
4124}
4125
4126static PyObject*
4127DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4128{
4129 int err;
4130 u_int32_t flags=0;
4131 char *file = NULL;
4132 char *database = NULL;
4133 char *newname = NULL;
4134 PyObject *txnobj = NULL;
4135 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004136 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004137 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004138
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004139 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004140 &file, &database, &newname, &txnobj, &flags)) {
4141 return NULL;
4142 }
4143 if (!checkTxnObj(txnobj, &txn)) {
4144 return NULL;
4145 }
4146 CHECK_ENV_NOT_CLOSED(self);
4147 MYDB_BEGIN_ALLOW_THREADS;
4148 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4149 flags);
4150 MYDB_END_ALLOW_THREADS;
4151 RETURN_IF_ERR();
4152 RETURN_NONE();
4153}
4154
4155static PyObject*
4156DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4157{
4158 int err;
4159 u_int32_t flags=0;
4160 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004161 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004162
4163 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4164 &passwd, &flags)) {
4165 return NULL;
4166 }
4167
4168 MYDB_BEGIN_ALLOW_THREADS;
4169 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4170 MYDB_END_ALLOW_THREADS;
4171
4172 RETURN_IF_ERR();
4173 RETURN_NONE();
4174}
4175#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004176
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004177static PyObject*
4178DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4179{
4180 int err;
4181 u_int32_t flags=0;
4182 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004183 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004184
4185 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4186 &timeout, &flags)) {
4187 return NULL;
4188 }
4189
4190 MYDB_BEGIN_ALLOW_THREADS;
4191 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4192 MYDB_END_ALLOW_THREADS;
4193
4194 RETURN_IF_ERR();
4195 RETURN_NONE();
4196}
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004197
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004198static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004199DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4200{
4201 int err;
4202 long shm_key = 0;
4203
4204 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4205 return NULL;
4206 CHECK_ENV_NOT_CLOSED(self);
4207
4208 err = self->db_env->set_shm_key(self->db_env, shm_key);
4209 RETURN_IF_ERR();
4210 RETURN_NONE();
4211}
4212
4213static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004214DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4215{
4216 int err, gbytes=0, bytes=0, ncache=0;
4217
4218 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4219 &gbytes, &bytes, &ncache))
4220 return NULL;
4221 CHECK_ENV_NOT_CLOSED(self);
4222
4223 MYDB_BEGIN_ALLOW_THREADS;
4224 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4225 MYDB_END_ALLOW_THREADS;
4226 RETURN_IF_ERR();
4227 RETURN_NONE();
4228}
4229
4230
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004231static PyObject*
4232DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4233{
4234 int err, flags=0, onoff=0;
4235
4236 if (!PyArg_ParseTuple(args, "ii:set_flags",
4237 &flags, &onoff))
4238 return NULL;
4239 CHECK_ENV_NOT_CLOSED(self);
4240
4241 MYDB_BEGIN_ALLOW_THREADS;
4242 err = self->db_env->set_flags(self->db_env, flags, onoff);
4243 MYDB_END_ALLOW_THREADS;
4244 RETURN_IF_ERR();
4245 RETURN_NONE();
4246}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004247
4248
Jesus Ceaca3939c2008-05-22 15:27:38 +00004249#if (DBVER >= 47)
4250static PyObject*
4251DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
4252{
4253 int err, flags, onoff;
4254
4255 if (!PyArg_ParseTuple(args, "ii:log_set_config",
4256 &flags, &onoff))
4257 return NULL;
4258 CHECK_ENV_NOT_CLOSED(self);
4259
4260 MYDB_BEGIN_ALLOW_THREADS;
4261 err = self->db_env->log_set_config(self->db_env, flags, onoff);
4262 MYDB_END_ALLOW_THREADS;
4263 RETURN_IF_ERR();
4264 RETURN_NONE();
4265}
4266#endif /* DBVER >= 47 */
4267
4268
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004269static PyObject*
4270DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4271{
4272 int err;
4273 char *dir;
4274
4275 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4276 return NULL;
4277 CHECK_ENV_NOT_CLOSED(self);
4278
4279 MYDB_BEGIN_ALLOW_THREADS;
4280 err = self->db_env->set_data_dir(self->db_env, dir);
4281 MYDB_END_ALLOW_THREADS;
4282 RETURN_IF_ERR();
4283 RETURN_NONE();
4284}
4285
4286
4287static PyObject*
4288DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4289{
4290 int err, lg_bsize;
4291
4292 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4293 return NULL;
4294 CHECK_ENV_NOT_CLOSED(self);
4295
4296 MYDB_BEGIN_ALLOW_THREADS;
4297 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4298 MYDB_END_ALLOW_THREADS;
4299 RETURN_IF_ERR();
4300 RETURN_NONE();
4301}
4302
4303
4304static PyObject*
4305DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4306{
4307 int err;
4308 char *dir;
4309
4310 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4311 return NULL;
4312 CHECK_ENV_NOT_CLOSED(self);
4313
4314 MYDB_BEGIN_ALLOW_THREADS;
4315 err = self->db_env->set_lg_dir(self->db_env, dir);
4316 MYDB_END_ALLOW_THREADS;
4317 RETURN_IF_ERR();
4318 RETURN_NONE();
4319}
4320
4321static PyObject*
4322DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4323{
4324 int err, lg_max;
4325
4326 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4327 return NULL;
4328 CHECK_ENV_NOT_CLOSED(self);
4329
4330 MYDB_BEGIN_ALLOW_THREADS;
4331 err = self->db_env->set_lg_max(self->db_env, lg_max);
4332 MYDB_END_ALLOW_THREADS;
4333 RETURN_IF_ERR();
4334 RETURN_NONE();
4335}
4336
Jesus Ceaef9764f2008-05-13 18:45:46 +00004337#if (DBVER >= 42)
4338static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004339DBEnv_get_lg_max(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004340{
4341 int err;
4342 u_int32_t lg_max;
4343
Jesus Ceaef9764f2008-05-13 18:45:46 +00004344 CHECK_ENV_NOT_CLOSED(self);
4345
4346 MYDB_BEGIN_ALLOW_THREADS;
4347 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4348 MYDB_END_ALLOW_THREADS;
4349 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004350 return NUMBER_FromLong(lg_max);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004351}
4352#endif
4353
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004354
4355static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004356DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4357{
4358 int err, lg_max;
4359
4360 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4361 return NULL;
4362 CHECK_ENV_NOT_CLOSED(self);
4363
4364 MYDB_BEGIN_ALLOW_THREADS;
4365 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4366 MYDB_END_ALLOW_THREADS;
4367 RETURN_IF_ERR();
4368 RETURN_NONE();
4369}
4370
4371
4372static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004373DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4374{
4375 int err, lk_detect;
4376
4377 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4378 return NULL;
4379 CHECK_ENV_NOT_CLOSED(self);
4380
4381 MYDB_BEGIN_ALLOW_THREADS;
4382 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4383 MYDB_END_ALLOW_THREADS;
4384 RETURN_IF_ERR();
4385 RETURN_NONE();
4386}
4387
4388
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004389#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004390static PyObject*
4391DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4392{
4393 int err, max;
4394
4395 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4396 return NULL;
4397 CHECK_ENV_NOT_CLOSED(self);
4398
4399 MYDB_BEGIN_ALLOW_THREADS;
4400 err = self->db_env->set_lk_max(self->db_env, max);
4401 MYDB_END_ALLOW_THREADS;
4402 RETURN_IF_ERR();
4403 RETURN_NONE();
4404}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004405#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004406
4407
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004408
4409static PyObject*
4410DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4411{
4412 int err, max;
4413
4414 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4415 return NULL;
4416 CHECK_ENV_NOT_CLOSED(self);
4417
4418 MYDB_BEGIN_ALLOW_THREADS;
4419 err = self->db_env->set_lk_max_locks(self->db_env, max);
4420 MYDB_END_ALLOW_THREADS;
4421 RETURN_IF_ERR();
4422 RETURN_NONE();
4423}
4424
4425
4426static PyObject*
4427DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4428{
4429 int err, max;
4430
4431 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4432 return NULL;
4433 CHECK_ENV_NOT_CLOSED(self);
4434
4435 MYDB_BEGIN_ALLOW_THREADS;
4436 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4437 MYDB_END_ALLOW_THREADS;
4438 RETURN_IF_ERR();
4439 RETURN_NONE();
4440}
4441
4442
4443static PyObject*
4444DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4445{
4446 int err, max;
4447
4448 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4449 return NULL;
4450 CHECK_ENV_NOT_CLOSED(self);
4451
4452 MYDB_BEGIN_ALLOW_THREADS;
4453 err = self->db_env->set_lk_max_objects(self->db_env, max);
4454 MYDB_END_ALLOW_THREADS;
4455 RETURN_IF_ERR();
4456 RETURN_NONE();
4457}
4458
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004459
4460static PyObject*
4461DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4462{
4463 int err, mp_mmapsize;
4464
4465 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4466 return NULL;
4467 CHECK_ENV_NOT_CLOSED(self);
4468
4469 MYDB_BEGIN_ALLOW_THREADS;
4470 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4471 MYDB_END_ALLOW_THREADS;
4472 RETURN_IF_ERR();
4473 RETURN_NONE();
4474}
4475
4476
4477static PyObject*
4478DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4479{
4480 int err;
4481 char *dir;
4482
4483 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4484 return NULL;
4485 CHECK_ENV_NOT_CLOSED(self);
4486
4487 MYDB_BEGIN_ALLOW_THREADS;
4488 err = self->db_env->set_tmp_dir(self->db_env, dir);
4489 MYDB_END_ALLOW_THREADS;
4490 RETURN_IF_ERR();
4491 RETURN_NONE();
4492}
4493
4494
Jesus Ceaef9764f2008-05-13 18:45:46 +00004495static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004496DBEnv_txn_recover(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004497{
4498 int flags = DB_FIRST;
4499 int err, i;
4500 PyObject *list, *tuple, *gid;
4501 DBTxnObject *txn;
4502#define PREPLIST_LEN 16
4503 DB_PREPLIST preplist[PREPLIST_LEN];
4504 long retp;
4505
Jesus Ceaef9764f2008-05-13 18:45:46 +00004506 CHECK_ENV_NOT_CLOSED(self);
4507
4508 list=PyList_New(0);
4509 if (!list)
4510 return NULL;
4511 while (!0) {
4512 MYDB_BEGIN_ALLOW_THREADS
4513 err=self->db_env->txn_recover(self->db_env,
4514 preplist, PREPLIST_LEN, &retp, flags);
4515#undef PREPLIST_LEN
4516 MYDB_END_ALLOW_THREADS
4517 if (err) {
4518 Py_DECREF(list);
4519 RETURN_IF_ERR();
4520 }
4521 if (!retp) break;
4522 flags=DB_NEXT; /* Prepare for next loop pass */
4523 for (i=0; i<retp; i++) {
Christian Heimes593daf52008-05-26 12:51:38 +00004524 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
Jesus Ceaef9764f2008-05-13 18:45:46 +00004525 DB_XIDDATASIZE);
4526 if (!gid) {
4527 Py_DECREF(list);
4528 return NULL;
4529 }
4530 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4531 if (!txn) {
4532 Py_DECREF(list);
4533 Py_DECREF(gid);
4534 return NULL;
4535 }
4536 txn->flag_prepare=1; /* Recover state */
4537 tuple=PyTuple_New(2);
4538 if (!tuple) {
4539 Py_DECREF(list);
4540 Py_DECREF(gid);
4541 Py_DECREF(txn);
4542 return NULL;
4543 }
4544 if (PyTuple_SetItem(tuple, 0, gid)) {
4545 Py_DECREF(list);
4546 Py_DECREF(gid);
4547 Py_DECREF(txn);
4548 Py_DECREF(tuple);
4549 return NULL;
4550 }
4551 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4552 Py_DECREF(list);
4553 Py_DECREF(txn);
4554 Py_DECREF(tuple); /* This delete the "gid" also */
4555 return NULL;
4556 }
4557 if (PyList_Append(list, tuple)) {
4558 Py_DECREF(list);
4559 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4560 return NULL;
4561 }
4562 Py_DECREF(tuple);
4563 }
4564 }
4565 return list;
4566}
Jesus Ceaef9764f2008-05-13 18:45:46 +00004567
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004568static PyObject*
4569DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4570{
4571 int flags = 0;
4572 PyObject* txnobj = NULL;
4573 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004574 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004575
4576 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4577 &txnobj, &flags))
4578 return NULL;
4579
4580 if (!checkTxnObj(txnobj, &txn))
4581 return NULL;
4582 CHECK_ENV_NOT_CLOSED(self);
4583
Jesus Ceaef9764f2008-05-13 18:45:46 +00004584 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004585}
4586
4587
4588static PyObject*
4589DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4590{
4591 int err, kbyte=0, min=0, flags=0;
4592
4593 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4594 return NULL;
4595 CHECK_ENV_NOT_CLOSED(self);
4596
4597 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004598 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004599 MYDB_END_ALLOW_THREADS;
4600 RETURN_IF_ERR();
4601 RETURN_NONE();
4602}
4603
4604
4605static PyObject*
4606DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4607{
4608 int err, max;
4609
4610 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4611 return NULL;
4612 CHECK_ENV_NOT_CLOSED(self);
4613
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004614 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004615 RETURN_IF_ERR();
4616 RETURN_NONE();
4617}
4618
4619
4620static PyObject*
4621DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4622{
4623 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004624 long stamp;
4625 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004626
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004627 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004628 return NULL;
4629 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004630 timestamp = (time_t)stamp;
4631 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004632 RETURN_IF_ERR();
4633 RETURN_NONE();
4634}
4635
4636
4637static PyObject*
4638DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4639{
4640 int err, atype, flags=0;
4641 int aborted = 0;
4642
4643 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4644 return NULL;
4645 CHECK_ENV_NOT_CLOSED(self);
4646
4647 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004648 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004649 MYDB_END_ALLOW_THREADS;
4650 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004651 return NUMBER_FromLong(aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004652}
4653
4654
4655static PyObject*
4656DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4657{
4658 int flags=0;
4659 int locker, lock_mode;
4660 DBT obj;
4661 PyObject* objobj;
4662
4663 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4664 return NULL;
4665
4666
4667 if (!make_dbt(objobj, &obj))
4668 return NULL;
4669
4670 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4671}
4672
4673
4674static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004675DBEnv_lock_id(DBEnvObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004676{
4677 int err;
4678 u_int32_t theID;
4679
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004680 CHECK_ENV_NOT_CLOSED(self);
4681 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004682 err = self->db_env->lock_id(self->db_env, &theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004683 MYDB_END_ALLOW_THREADS;
4684 RETURN_IF_ERR();
4685
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004686 return NUMBER_FromLong((long)theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004687}
4688
Gregory P. Smithac11e022007-11-05 02:56:31 +00004689static PyObject*
4690DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4691{
4692 int err;
4693 u_int32_t theID;
4694
4695 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4696 return NULL;
4697
4698 CHECK_ENV_NOT_CLOSED(self);
4699 MYDB_BEGIN_ALLOW_THREADS;
4700 err = self->db_env->lock_id_free(self->db_env, theID);
4701 MYDB_END_ALLOW_THREADS;
4702 RETURN_IF_ERR();
4703 RETURN_NONE();
4704}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004705
4706static PyObject*
4707DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4708{
4709 int err;
4710 DBLockObject* dblockobj;
4711
4712 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4713 return NULL;
4714
4715 CHECK_ENV_NOT_CLOSED(self);
4716 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004717 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004718 MYDB_END_ALLOW_THREADS;
4719 RETURN_IF_ERR();
4720 RETURN_NONE();
4721}
4722
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004723#if (DBVER >= 44)
4724static PyObject*
4725DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4726{
4727 int err;
4728 char *file;
4729 u_int32_t flags = 0;
4730 static char* kwnames[] = { "file", "flags", NULL};
4731
4732 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4733 &file, &flags))
4734 return NULL;
4735 CHECK_ENV_NOT_CLOSED(self);
4736
4737 MYDB_BEGIN_ALLOW_THREADS;
4738 err = self->db_env->lsn_reset(self->db_env, file, flags);
4739 MYDB_END_ALLOW_THREADS;
4740 RETURN_IF_ERR();
4741 RETURN_NONE();
4742}
4743#endif /* DBVER >= 4.4 */
4744
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004745static PyObject*
4746DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4747{
4748 int err;
4749 DB_LOG_STAT* statp = NULL;
4750 PyObject* d = NULL;
4751 u_int32_t flags = 0;
4752
4753 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4754 return NULL;
4755 CHECK_ENV_NOT_CLOSED(self);
4756
4757 MYDB_BEGIN_ALLOW_THREADS;
4758 err = self->db_env->log_stat(self->db_env, &statp, flags);
4759 MYDB_END_ALLOW_THREADS;
4760 RETURN_IF_ERR();
4761
4762 /* Turn the stat structure into a dictionary */
4763 d = PyDict_New();
4764 if (d == NULL) {
4765 if (statp)
4766 free(statp);
4767 return NULL;
4768 }
4769
4770#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4771
4772 MAKE_ENTRY(magic);
4773 MAKE_ENTRY(version);
4774 MAKE_ENTRY(mode);
4775 MAKE_ENTRY(lg_bsize);
4776#if (DBVER >= 44)
4777 MAKE_ENTRY(lg_size);
4778 MAKE_ENTRY(record);
4779#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004780#if (DBVER < 41)
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004781 MAKE_ENTRY(lg_max);
4782#endif
4783 MAKE_ENTRY(w_mbytes);
4784 MAKE_ENTRY(w_bytes);
4785 MAKE_ENTRY(wc_mbytes);
4786 MAKE_ENTRY(wc_bytes);
4787 MAKE_ENTRY(wcount);
4788 MAKE_ENTRY(wcount_fill);
4789#if (DBVER >= 44)
4790 MAKE_ENTRY(rcount);
4791#endif
4792 MAKE_ENTRY(scount);
4793 MAKE_ENTRY(cur_file);
4794 MAKE_ENTRY(cur_offset);
4795 MAKE_ENTRY(disk_file);
4796 MAKE_ENTRY(disk_offset);
4797 MAKE_ENTRY(maxcommitperflush);
4798 MAKE_ENTRY(mincommitperflush);
4799 MAKE_ENTRY(regsize);
4800 MAKE_ENTRY(region_wait);
4801 MAKE_ENTRY(region_nowait);
4802
4803#undef MAKE_ENTRY
4804 free(statp);
4805 return d;
4806} /* DBEnv_log_stat */
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004807
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004808
4809static PyObject*
4810DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4811{
4812 int err;
4813 DB_LOCK_STAT* sp;
4814 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004815 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004816
4817 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4818 return NULL;
4819 CHECK_ENV_NOT_CLOSED(self);
4820
4821 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004822 err = self->db_env->lock_stat(self->db_env, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004823 MYDB_END_ALLOW_THREADS;
4824 RETURN_IF_ERR();
4825
4826 /* Turn the stat structure into a dictionary */
4827 d = PyDict_New();
4828 if (d == NULL) {
4829 free(sp);
4830 return NULL;
4831 }
4832
4833#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4834
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004835#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004836 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004837#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004838#if (DBVER >=41)
4839 MAKE_ENTRY(id);
4840 MAKE_ENTRY(cur_maxid);
4841#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004842 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004843 MAKE_ENTRY(maxlocks);
4844 MAKE_ENTRY(maxlockers);
4845 MAKE_ENTRY(maxobjects);
4846 MAKE_ENTRY(nlocks);
4847 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004848 MAKE_ENTRY(nlockers);
4849 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004850 MAKE_ENTRY(nobjects);
4851 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004852 MAKE_ENTRY(nrequests);
4853 MAKE_ENTRY(nreleases);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004854#if (DBVER >= 44)
4855 MAKE_ENTRY(nupgrade);
4856 MAKE_ENTRY(ndowngrade);
4857#endif
Gregory P. Smith29602d22006-01-24 09:46:48 +00004858#if (DBVER < 44)
4859 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004860 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004861#else
4862 MAKE_ENTRY(lock_nowait);
4863 MAKE_ENTRY(lock_wait);
4864#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004865 MAKE_ENTRY(ndeadlocks);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004866#if (DBVER >= 41)
4867 MAKE_ENTRY(locktimeout);
4868 MAKE_ENTRY(txntimeout);
4869#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004870 MAKE_ENTRY(nlocktimeouts);
4871 MAKE_ENTRY(ntxntimeouts);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004872#if (DBVER >= 46)
4873 MAKE_ENTRY(objs_wait);
4874 MAKE_ENTRY(objs_nowait);
4875 MAKE_ENTRY(lockers_wait);
4876 MAKE_ENTRY(lockers_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004877#if (DBVER >= 47)
4878 MAKE_ENTRY(lock_wait);
4879 MAKE_ENTRY(lock_nowait);
4880#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00004881 MAKE_ENTRY(locks_wait);
4882 MAKE_ENTRY(locks_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004883#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004884 MAKE_ENTRY(hash_len);
4885#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004886 MAKE_ENTRY(regsize);
4887 MAKE_ENTRY(region_wait);
4888 MAKE_ENTRY(region_nowait);
4889
4890#undef MAKE_ENTRY
4891 free(sp);
4892 return d;
4893}
4894
Jesus Ceaef9764f2008-05-13 18:45:46 +00004895static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004896DBEnv_log_flush(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004897{
4898 int err;
4899
Jesus Ceaef9764f2008-05-13 18:45:46 +00004900 CHECK_ENV_NOT_CLOSED(self);
4901
4902 MYDB_BEGIN_ALLOW_THREADS
4903 err = self->db_env->log_flush(self->db_env, NULL);
4904 MYDB_END_ALLOW_THREADS
4905
4906 RETURN_IF_ERR();
4907 RETURN_NONE();
4908}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004909
4910static PyObject*
4911DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4912{
4913 int flags=0;
4914 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004915 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004916 PyObject* list;
4917 PyObject* item = NULL;
4918
4919 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4920 return NULL;
4921
4922 CHECK_ENV_NOT_CLOSED(self);
4923 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004924 err = self->db_env->log_archive(self->db_env, &log_list, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004925 MYDB_END_ALLOW_THREADS;
4926 RETURN_IF_ERR();
4927
Gregory P. Smithbad47452006-06-05 00:33:35 +00004928 list = PyList_New(0);
4929 if (list == NULL) {
4930 if (log_list)
4931 free(log_list);
4932 return NULL;
4933 }
4934
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004935 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004936 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004937 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Christian Heimes593daf52008-05-26 12:51:38 +00004938 item = PyBytes_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004939 if (item == NULL) {
4940 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004941 list = NULL;
4942 break;
4943 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004944 if (PyList_Append(list, item)) {
4945 Py_DECREF(list);
4946 list = NULL;
4947 Py_DECREF(item);
4948 break;
4949 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004950 Py_DECREF(item);
4951 }
4952 free(log_list_start);
4953 }
4954 return list;
4955}
4956
4957
4958static PyObject*
4959DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4960{
4961 int err;
4962 DB_TXN_STAT* sp;
4963 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004964 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004965
4966 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4967 return NULL;
4968 CHECK_ENV_NOT_CLOSED(self);
4969
4970 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004971 err = self->db_env->txn_stat(self->db_env, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004972 MYDB_END_ALLOW_THREADS;
4973 RETURN_IF_ERR();
4974
4975 /* Turn the stat structure into a dictionary */
4976 d = PyDict_New();
4977 if (d == NULL) {
4978 free(sp);
4979 return NULL;
4980 }
4981
Jesus Ceaef9764f2008-05-13 18:45:46 +00004982#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4983#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4984#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004985
Jesus Ceaef9764f2008-05-13 18:45:46 +00004986 MAKE_DB_LSN_ENTRY(last_ckp);
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004987 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004988 MAKE_ENTRY(last_txnid);
4989 MAKE_ENTRY(maxtxns);
4990 MAKE_ENTRY(nactive);
4991 MAKE_ENTRY(maxnactive);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004992#if (DBVER >= 45)
4993 MAKE_ENTRY(nsnapshot);
4994 MAKE_ENTRY(maxnsnapshot);
4995#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004996 MAKE_ENTRY(nbegins);
4997 MAKE_ENTRY(naborts);
4998 MAKE_ENTRY(ncommits);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004999 MAKE_ENTRY(nrestores);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005000 MAKE_ENTRY(regsize);
5001 MAKE_ENTRY(region_wait);
5002 MAKE_ENTRY(region_nowait);
5003
Jesus Ceaef9764f2008-05-13 18:45:46 +00005004#undef MAKE_DB_LSN_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005005#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00005006#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005007 free(sp);
5008 return d;
5009}
5010
5011
5012static PyObject*
5013DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
5014{
5015 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005016 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005017
5018 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
5019 return NULL;
5020 CHECK_ENV_NOT_CLOSED(self);
5021
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005022 if (self->moduleFlags.getReturnsNone)
5023 ++oldValue;
5024 if (self->moduleFlags.cursorSetReturnsNone)
5025 ++oldValue;
5026 self->moduleFlags.getReturnsNone = (flags >= 1);
5027 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005028 return NUMBER_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005029}
5030
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005031static PyObject*
5032DBEnv_get_private(DBEnvObject* self)
5033{
5034 /* We can give out the private field even if dbenv is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00005035 Py_INCREF(self->private_obj);
5036 return self->private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005037}
5038
5039static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00005040DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005041{
5042 /* We can set the private field even if dbenv is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00005043 Py_DECREF(self->private_obj);
5044 Py_INCREF(private_obj);
5045 self->private_obj = private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005046 RETURN_NONE();
5047}
5048
5049
Jesus Ceaef9764f2008-05-13 18:45:46 +00005050static PyObject*
Jesus Ceaca3939c2008-05-22 15:27:38 +00005051DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5052{
5053 int err;
5054 char *host;
5055 long cl_timeout=0, sv_timeout=0;
5056
5057 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
5058
5059 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
5060 &host, &cl_timeout, &sv_timeout))
5061 return NULL;
5062 CHECK_ENV_NOT_CLOSED(self);
5063
5064 MYDB_BEGIN_ALLOW_THREADS;
5065 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
5066 sv_timeout, 0);
5067 MYDB_END_ALLOW_THREADS;
5068 RETURN_IF_ERR();
5069 RETURN_NONE();
5070}
Jesus Ceaca3939c2008-05-22 15:27:38 +00005071
Jesus Ceaca3939c2008-05-22 15:27:38 +00005072static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005073DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
5074{
5075 int err;
5076 int which, onoff;
5077
5078 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
5079 return NULL;
5080 }
5081 CHECK_ENV_NOT_CLOSED(self);
5082 MYDB_BEGIN_ALLOW_THREADS;
5083 err = self->db_env->set_verbose(self->db_env, which, onoff);
5084 MYDB_END_ALLOW_THREADS;
5085 RETURN_IF_ERR();
5086 RETURN_NONE();
5087}
5088
5089#if (DBVER >= 42)
5090static PyObject*
5091DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
5092{
5093 int err;
5094 int which;
5095 int verbose;
5096
5097 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
5098 return NULL;
5099 }
5100 CHECK_ENV_NOT_CLOSED(self);
5101 MYDB_BEGIN_ALLOW_THREADS;
5102 err = self->db_env->get_verbose(self->db_env, which, &verbose);
5103 MYDB_END_ALLOW_THREADS;
5104 RETURN_IF_ERR();
5105 return PyBool_FromLong(verbose);
5106}
5107#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005108
5109#if (DBVER >= 45)
5110static void
5111_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
5112{
5113 DBEnvObject *dbenv;
5114 PyObject* callback;
5115 PyObject* args;
5116 PyObject* result = NULL;
5117
5118 MYDB_BEGIN_BLOCK_THREADS;
5119 dbenv = (DBEnvObject *)db_env->app_private;
5120 callback = dbenv->event_notifyCallback;
5121 if (callback) {
5122 if (event == DB_EVENT_REP_NEWMASTER) {
5123 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
5124 } else {
5125 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5126 }
5127 if (args) {
5128 result = PyEval_CallObject(callback, args);
5129 }
5130 if ((!args) || (!result)) {
5131 PyErr_Print();
5132 }
5133 Py_XDECREF(args);
5134 Py_XDECREF(result);
5135 }
5136 MYDB_END_BLOCK_THREADS;
5137}
5138#endif
5139
5140#if (DBVER >= 45)
5141static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005142DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005143{
5144 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005145
5146 CHECK_ENV_NOT_CLOSED(self);
5147
5148 if (!PyCallable_Check(notifyFunc)) {
5149 makeTypeError("Callable", notifyFunc);
5150 return NULL;
5151 }
5152
5153 Py_XDECREF(self->event_notifyCallback);
5154 Py_INCREF(notifyFunc);
5155 self->event_notifyCallback = notifyFunc;
5156
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005157 /* This is to workaround a problem with un-initialized threads (see
5158 comment in DB_associate) */
5159#ifdef WITH_THREAD
5160 PyEval_InitThreads();
5161#endif
5162
Jesus Ceaef9764f2008-05-13 18:45:46 +00005163 MYDB_BEGIN_ALLOW_THREADS;
5164 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5165 MYDB_END_ALLOW_THREADS;
5166
5167 if (err) {
5168 Py_DECREF(notifyFunc);
5169 self->event_notifyCallback = NULL;
5170 }
5171
5172 RETURN_IF_ERR();
5173 RETURN_NONE();
5174}
5175#endif
5176
5177
5178/* --------------------------------------------------------------------- */
5179/* REPLICATION METHODS: Base Replication */
5180
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005181
5182static PyObject*
5183DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
5184{
5185 int err;
5186 PyObject *control_py, *rec_py;
5187 DBT control, rec;
5188 int envid;
5189#if (DBVER >= 42)
5190 DB_LSN lsn;
5191#endif
5192
5193 if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
5194 &rec_py, &envid))
5195 return NULL;
5196 CHECK_ENV_NOT_CLOSED(self);
5197
5198 if (!make_dbt(control_py, &control))
5199 return NULL;
5200 if (!make_dbt(rec_py, &rec))
5201 return NULL;
5202
5203 MYDB_BEGIN_ALLOW_THREADS;
5204#if (DBVER >= 46)
5205 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5206 envid, &lsn);
5207#else
5208#if (DBVER >= 42)
5209 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5210 &envid, &lsn);
5211#else
5212 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5213 &envid);
5214#endif
5215#endif
5216 MYDB_END_ALLOW_THREADS;
5217 switch (err) {
5218 case DB_REP_NEWMASTER :
5219 return Py_BuildValue("(iO)", envid, Py_None);
5220 break;
5221
5222 case DB_REP_DUPMASTER :
5223 case DB_REP_HOLDELECTION :
5224#if (DBVER >= 44)
5225 case DB_REP_IGNORE :
5226 case DB_REP_JOIN_FAILURE :
5227#endif
5228 return Py_BuildValue("(iO)", err, Py_None);
5229 break;
5230 case DB_REP_NEWSITE :
Jesus Cea4907d272008-08-31 14:00:51 +00005231 {
5232 PyObject *tmp, *r;
5233
5234 if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
5235 return NULL;
5236 }
5237
5238 r = Py_BuildValue("(iO)", err, tmp);
5239 Py_DECREF(tmp);
5240 return r;
5241 break;
5242 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005243#if (DBVER >= 42)
5244 case DB_REP_NOTPERM :
5245 case DB_REP_ISPERM :
5246 return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
5247 break;
5248#endif
5249 }
5250 RETURN_IF_ERR();
5251 return Py_BuildValue("(OO)", Py_None, Py_None);
5252}
5253
5254static int
5255_DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
5256 const DB_LSN *lsn, int envid, u_int32_t flags)
5257{
5258 DBEnvObject *dbenv;
5259 PyObject* rep_transport;
5260 PyObject* args;
Jesus Cea4907d272008-08-31 14:00:51 +00005261 PyObject *a, *b;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005262 PyObject* result = NULL;
5263 int ret=0;
5264
5265 MYDB_BEGIN_BLOCK_THREADS;
5266 dbenv = (DBEnvObject *)db_env->app_private;
5267 rep_transport = dbenv->rep_transport;
5268
Jesus Cea4907d272008-08-31 14:00:51 +00005269 /*
5270 ** The errors in 'a' or 'b' are detected in "Py_BuildValue".
5271 */
5272 a = PyBytes_FromStringAndSize(control->data, control->size);
5273 b = PyBytes_FromStringAndSize(rec->data, rec->size);
5274
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005275 args = Py_BuildValue(
5276#if (PY_VERSION_HEX >= 0x02040000)
Jesus Cea4907d272008-08-31 14:00:51 +00005277 "(OOO(ll)iI)",
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005278#else
Jesus Cea4907d272008-08-31 14:00:51 +00005279 "(OOO(ll)ii)",
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005280#endif
5281 dbenv,
Jesus Cea4907d272008-08-31 14:00:51 +00005282 a, b,
5283 lsn->file, lsn->offset, envid, flags);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005284 if (args) {
5285 result = PyEval_CallObject(rep_transport, args);
5286 }
5287
5288 if ((!args) || (!result)) {
5289 PyErr_Print();
5290 ret = -1;
5291 }
Jesus Cea4907d272008-08-31 14:00:51 +00005292 Py_XDECREF(a);
5293 Py_XDECREF(b);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005294 Py_XDECREF(args);
5295 Py_XDECREF(result);
5296 MYDB_END_BLOCK_THREADS;
5297 return ret;
5298}
5299
5300#if (DBVER <= 41)
5301static int
5302_DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec,
5303 int envid, u_int32_t flags)
5304{
5305 DB_LSN lsn;
5306
5307 lsn.file = -1; /* Dummy values */
5308 lsn.offset = -1;
5309 return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid,
5310 flags);
5311}
5312#endif
5313
5314static PyObject*
5315DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
5316{
5317 int err;
5318 int envid;
5319 PyObject *rep_transport;
5320
5321 if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
5322 return NULL;
5323 CHECK_ENV_NOT_CLOSED(self);
5324 if (!PyCallable_Check(rep_transport)) {
5325 makeTypeError("Callable", rep_transport);
5326 return NULL;
5327 }
5328
5329 MYDB_BEGIN_ALLOW_THREADS;
5330#if (DBVER >=45)
5331 err = self->db_env->rep_set_transport(self->db_env, envid,
5332 &_DBEnv_rep_transportCallback);
5333#else
5334#if (DBVER >= 42)
5335 err = self->db_env->set_rep_transport(self->db_env, envid,
5336 &_DBEnv_rep_transportCallback);
5337#else
5338 err = self->db_env->set_rep_transport(self->db_env, envid,
5339 &_DBEnv_rep_transportCallbackOLD);
5340#endif
5341#endif
5342 MYDB_END_ALLOW_THREADS;
5343 RETURN_IF_ERR();
5344
5345 Py_DECREF(self->rep_transport);
5346 Py_INCREF(rep_transport);
5347 self->rep_transport = rep_transport;
5348 RETURN_NONE();
5349}
5350
5351#if (DBVER >= 47)
5352static PyObject*
5353DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
5354{
5355 int err;
5356 unsigned int minimum, maximum;
5357
5358 if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
5359 return NULL;
5360 CHECK_ENV_NOT_CLOSED(self);
5361
5362 MYDB_BEGIN_ALLOW_THREADS;
5363 err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
5364 MYDB_END_ALLOW_THREADS;
5365 RETURN_IF_ERR();
5366 RETURN_NONE();
5367}
5368
5369static PyObject*
5370DBEnv_rep_get_request(DBEnvObject* self)
5371{
5372 int err;
5373 u_int32_t minimum, maximum;
5374
5375 CHECK_ENV_NOT_CLOSED(self);
5376 MYDB_BEGIN_ALLOW_THREADS;
5377 err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
5378 MYDB_END_ALLOW_THREADS;
5379 RETURN_IF_ERR();
5380#if (PY_VERSION_HEX >= 0x02040000)
5381 return Py_BuildValue("II", minimum, maximum);
5382#else
5383 return Py_BuildValue("ii", minimum, maximum);
5384#endif
5385}
5386#endif
5387
5388#if (DBVER >= 45)
5389static PyObject*
5390DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
5391{
5392 int err;
5393 int limit;
5394
5395 if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
5396 return NULL;
5397 CHECK_ENV_NOT_CLOSED(self);
5398
5399 MYDB_BEGIN_ALLOW_THREADS;
5400 err = self->db_env->rep_set_limit(self->db_env, 0, limit);
5401 MYDB_END_ALLOW_THREADS;
5402 RETURN_IF_ERR();
5403 RETURN_NONE();
5404}
5405
5406static PyObject*
5407DBEnv_rep_get_limit(DBEnvObject* self)
5408{
5409 int err;
5410 u_int32_t gbytes, bytes;
5411
5412 CHECK_ENV_NOT_CLOSED(self);
5413 MYDB_BEGIN_ALLOW_THREADS;
5414 err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
5415 MYDB_END_ALLOW_THREADS;
5416 RETURN_IF_ERR();
5417 return NUMBER_FromLong(bytes);
5418}
5419#endif
5420
5421#if (DBVER >= 44)
5422static PyObject*
5423DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
5424{
5425 int err;
5426 int which;
5427 int onoff;
5428
5429 if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
5430 return NULL;
5431 CHECK_ENV_NOT_CLOSED(self);
5432
5433 MYDB_BEGIN_ALLOW_THREADS;
5434 err = self->db_env->rep_set_config(self->db_env, which, onoff);
5435 MYDB_END_ALLOW_THREADS;
5436 RETURN_IF_ERR();
5437 RETURN_NONE();
5438}
5439
5440static PyObject*
5441DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
5442{
5443 int err;
5444 int which;
5445 int onoff;
5446
5447 if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
5448 return NULL;
5449 }
5450 CHECK_ENV_NOT_CLOSED(self);
5451 MYDB_BEGIN_ALLOW_THREADS;
5452 err = self->db_env->rep_get_config(self->db_env, which, &onoff);
5453 MYDB_END_ALLOW_THREADS;
5454 RETURN_IF_ERR();
5455 return PyBool_FromLong(onoff);
5456}
5457#endif
5458
5459#if (DBVER >= 46)
5460static PyObject*
5461DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
5462{
5463 int err;
5464 u_int32_t nsites, nvotes;
5465
5466 if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
5467 return NULL;
5468 }
5469 CHECK_ENV_NOT_CLOSED(self);
5470 MYDB_BEGIN_ALLOW_THREADS;
5471 err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0);
5472 MYDB_END_ALLOW_THREADS;
5473 RETURN_IF_ERR();
5474 RETURN_NONE();
5475}
5476#endif
5477
5478static PyObject*
5479DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5480{
5481 int err;
5482 PyObject *cdata_py = Py_None;
5483 DBT cdata;
5484 int flags;
5485 static char* kwnames[] = {"flags","cdata", NULL};
5486
5487 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5488 "i|O:rep_start", kwnames, &flags, &cdata_py))
5489 {
5490 return NULL;
5491 }
5492 CHECK_ENV_NOT_CLOSED(self);
5493
5494 if (!make_dbt(cdata_py, &cdata))
5495 return NULL;
5496
5497 MYDB_BEGIN_ALLOW_THREADS;
5498 err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
5499 flags);
5500 MYDB_END_ALLOW_THREADS;
5501 RETURN_IF_ERR();
5502 RETURN_NONE();
5503}
5504
5505#if (DBVER >= 44)
5506static PyObject*
5507DBEnv_rep_sync(DBEnvObject* self)
5508{
5509 int err;
5510
5511 CHECK_ENV_NOT_CLOSED(self);
5512 MYDB_BEGIN_ALLOW_THREADS;
5513 err = self->db_env->rep_sync(self->db_env, 0);
5514 MYDB_END_ALLOW_THREADS;
5515 RETURN_IF_ERR();
5516 RETURN_NONE();
5517}
5518#endif
5519
5520
Jesus Ceaef9764f2008-05-13 18:45:46 +00005521#if (DBVER >= 45)
5522static PyObject*
5523DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5524{
5525 int err;
5526 int nsites;
5527
5528 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5529 return NULL;
5530 }
5531 CHECK_ENV_NOT_CLOSED(self);
5532 MYDB_BEGIN_ALLOW_THREADS;
5533 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5534 MYDB_END_ALLOW_THREADS;
5535 RETURN_IF_ERR();
5536 RETURN_NONE();
5537}
5538
5539static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005540DBEnv_rep_get_nsites(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005541{
5542 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005543#if (DBVER >= 47)
5544 u_int32_t nsites;
5545#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005546 int nsites;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005547#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005548
Jesus Ceaef9764f2008-05-13 18:45:46 +00005549 CHECK_ENV_NOT_CLOSED(self);
5550 MYDB_BEGIN_ALLOW_THREADS;
5551 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5552 MYDB_END_ALLOW_THREADS;
5553 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005554 return NUMBER_FromLong(nsites);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005555}
5556
5557static PyObject*
5558DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5559{
5560 int err;
5561 int priority;
5562
5563 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5564 return NULL;
5565 }
5566 CHECK_ENV_NOT_CLOSED(self);
5567 MYDB_BEGIN_ALLOW_THREADS;
5568 err = self->db_env->rep_set_priority(self->db_env, priority);
5569 MYDB_END_ALLOW_THREADS;
5570 RETURN_IF_ERR();
5571 RETURN_NONE();
5572}
5573
5574static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005575DBEnv_rep_get_priority(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005576{
5577 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005578#if (DBVER >= 47)
5579 u_int32_t priority;
5580#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005581 int priority;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005582#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005583
Jesus Ceaef9764f2008-05-13 18:45:46 +00005584 CHECK_ENV_NOT_CLOSED(self);
5585 MYDB_BEGIN_ALLOW_THREADS;
5586 err = self->db_env->rep_get_priority(self->db_env, &priority);
5587 MYDB_END_ALLOW_THREADS;
5588 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005589 return NUMBER_FromLong(priority);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005590}
5591
5592static PyObject*
5593DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5594{
5595 int err;
5596 int which, timeout;
5597
5598 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5599 return NULL;
5600 }
5601 CHECK_ENV_NOT_CLOSED(self);
5602 MYDB_BEGIN_ALLOW_THREADS;
5603 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5604 MYDB_END_ALLOW_THREADS;
5605 RETURN_IF_ERR();
5606 RETURN_NONE();
5607}
5608
5609static PyObject*
5610DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5611{
5612 int err;
5613 int which;
5614 u_int32_t timeout;
5615
5616 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5617 return NULL;
5618 }
5619 CHECK_ENV_NOT_CLOSED(self);
5620 MYDB_BEGIN_ALLOW_THREADS;
5621 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5622 MYDB_END_ALLOW_THREADS;
5623 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005624 return NUMBER_FromLong(timeout);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005625}
5626#endif
5627
5628/* --------------------------------------------------------------------- */
5629/* REPLICATION METHODS: Replication Manager */
5630
5631#if (DBVER >= 45)
5632static PyObject*
5633DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5634 kwargs)
5635{
5636 int err;
5637 int nthreads, flags;
5638 static char* kwnames[] = {"nthreads","flags", NULL};
5639
5640 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5641 "ii:repmgr_start", kwnames, &nthreads, &flags))
5642 {
5643 return NULL;
5644 }
5645 CHECK_ENV_NOT_CLOSED(self);
5646 MYDB_BEGIN_ALLOW_THREADS;
5647 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5648 MYDB_END_ALLOW_THREADS;
5649 RETURN_IF_ERR();
5650 RETURN_NONE();
5651}
5652
5653static PyObject*
5654DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5655 kwargs)
5656{
5657 int err;
5658 char *host;
5659 int port;
5660 int flags = 0;
5661 static char* kwnames[] = {"host", "port", "flags", NULL};
5662
5663 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5664 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5665 {
5666 return NULL;
5667 }
5668 CHECK_ENV_NOT_CLOSED(self);
5669 MYDB_BEGIN_ALLOW_THREADS;
5670 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5671 MYDB_END_ALLOW_THREADS;
5672 RETURN_IF_ERR();
5673 RETURN_NONE();
5674}
5675
5676static PyObject*
5677DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5678 kwargs)
5679{
5680 int err;
5681 char *host;
5682 int port;
5683 int flags = 0;
5684 int eidp;
5685 static char* kwnames[] = {"host", "port", "flags", NULL};
5686
5687 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5688 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5689 {
5690 return NULL;
5691 }
5692 CHECK_ENV_NOT_CLOSED(self);
5693 MYDB_BEGIN_ALLOW_THREADS;
5694 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5695 MYDB_END_ALLOW_THREADS;
5696 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005697 return NUMBER_FromLong(eidp);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005698}
5699
5700static PyObject*
5701DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5702{
5703 int err;
5704 int ack_policy;
5705
5706 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5707 {
5708 return NULL;
5709 }
5710 CHECK_ENV_NOT_CLOSED(self);
5711 MYDB_BEGIN_ALLOW_THREADS;
5712 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5713 MYDB_END_ALLOW_THREADS;
5714 RETURN_IF_ERR();
5715 RETURN_NONE();
5716}
5717
5718static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005719DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005720{
5721 int err;
5722 int ack_policy;
5723
Jesus Ceaef9764f2008-05-13 18:45:46 +00005724 CHECK_ENV_NOT_CLOSED(self);
5725 MYDB_BEGIN_ALLOW_THREADS;
5726 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5727 MYDB_END_ALLOW_THREADS;
5728 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005729 return NUMBER_FromLong(ack_policy);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005730}
5731
5732static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005733DBEnv_repmgr_site_list(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005734{
5735 int err;
5736 unsigned int countp;
5737 DB_REPMGR_SITE *listp;
5738 PyObject *stats, *key, *tuple;
5739
Jesus Ceaef9764f2008-05-13 18:45:46 +00005740 CHECK_ENV_NOT_CLOSED(self);
5741 MYDB_BEGIN_ALLOW_THREADS;
5742 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5743 MYDB_END_ALLOW_THREADS;
5744 RETURN_IF_ERR();
5745
5746 stats=PyDict_New();
5747 if (stats == NULL) {
5748 free(listp);
5749 return NULL;
5750 }
5751
5752 for(;countp--;) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005753 key=NUMBER_FromLong(listp[countp].eid);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005754 if(!key) {
5755 Py_DECREF(stats);
5756 free(listp);
5757 return NULL;
5758 }
5759#if (PY_VERSION_HEX >= 0x02040000)
5760 tuple=Py_BuildValue("(sII)", listp[countp].host,
5761 listp[countp].port, listp[countp].status);
5762#else
5763 tuple=Py_BuildValue("(sii)", listp[countp].host,
5764 listp[countp].port, listp[countp].status);
5765#endif
5766 if(!tuple) {
5767 Py_DECREF(key);
5768 Py_DECREF(stats);
5769 free(listp);
5770 return NULL;
5771 }
5772 if(PyDict_SetItem(stats, key, tuple)) {
5773 Py_DECREF(key);
5774 Py_DECREF(tuple);
5775 Py_DECREF(stats);
5776 free(listp);
5777 return NULL;
5778 }
5779 }
5780 free(listp);
5781 return stats;
5782}
5783#endif
5784
5785#if (DBVER >= 46)
5786static PyObject*
5787DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5788{
5789 int err;
5790 int flags=0;
5791 static char* kwnames[] = { "flags", NULL };
5792
5793 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5794 kwnames, &flags))
5795 {
5796 return NULL;
5797 }
5798 CHECK_ENV_NOT_CLOSED(self);
5799 MYDB_BEGIN_ALLOW_THREADS;
5800 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5801 MYDB_END_ALLOW_THREADS;
5802 RETURN_IF_ERR();
5803 RETURN_NONE();
5804}
5805
5806static PyObject*
5807DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5808{
5809 int err;
5810 int flags=0;
5811 DB_REPMGR_STAT *statp;
5812 PyObject *stats;
5813 static char* kwnames[] = { "flags", NULL };
5814
5815 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5816 kwnames, &flags))
5817 {
5818 return NULL;
5819 }
5820 CHECK_ENV_NOT_CLOSED(self);
5821 MYDB_BEGIN_ALLOW_THREADS;
5822 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5823 MYDB_END_ALLOW_THREADS;
5824 RETURN_IF_ERR();
5825
5826 stats=PyDict_New();
5827 if (stats == NULL) {
5828 free(statp);
5829 return NULL;
5830 }
5831
5832#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5833
5834 MAKE_ENTRY(perm_failed);
5835 MAKE_ENTRY(msgs_queued);
5836 MAKE_ENTRY(msgs_dropped);
5837 MAKE_ENTRY(connection_drop);
5838 MAKE_ENTRY(connect_fail);
5839
5840#undef MAKE_ENTRY
5841
5842 free(statp);
5843 return stats;
5844}
5845#endif
5846
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005847
5848/* --------------------------------------------------------------------- */
5849/* DBTxn methods */
5850
5851
Jesus Ceaef9764f2008-05-13 18:45:46 +00005852static void _close_transaction_cursors(DBTxnObject* txn)
5853{
5854 PyObject *dummy;
5855
5856 while(txn->children_cursors) {
5857 PyErr_Warn(PyExc_RuntimeWarning,
5858 "Must close cursors before resolving a transaction.");
5859 dummy=DBC_close_internal(txn->children_cursors);
5860 Py_XDECREF(dummy);
5861 }
5862}
5863
5864static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5865{
5866 DBObject *db;
5867#if (DBVER >= 43)
5868 DBSequenceObject *dbs;
5869#endif
5870
5871 while (txn->children_dbs) {
5872 db=txn->children_dbs;
5873 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5874 if (txn->parent_txn) {
5875 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5876 db->txn=txn->parent_txn;
5877 } else {
5878 /* The db is already linked to its environment,
5879 ** so nothing to do.
5880 */
5881 db->txn=NULL;
5882 }
5883 }
5884
5885#if (DBVER >= 43)
5886 while (txn->children_sequences) {
5887 dbs=txn->children_sequences;
5888 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5889 if (txn->parent_txn) {
5890 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5891 dbs->txn=txn->parent_txn;
5892 } else {
5893 /* The sequence is already linked to its
5894 ** parent db. Nothing to do.
5895 */
5896 dbs->txn=NULL;
5897 }
5898 }
5899#endif
5900}
5901
5902
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005903static PyObject*
5904DBTxn_commit(DBTxnObject* self, PyObject* args)
5905{
5906 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005907 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005908
5909 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5910 return NULL;
5911
Jesus Ceaef9764f2008-05-13 18:45:46 +00005912 _close_transaction_cursors(self);
5913
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005914 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005915 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005916 "after txn_commit, txn_abort "
5917 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005918 if (t) {
5919 PyErr_SetObject(DBError, t);
5920 Py_DECREF(t);
5921 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005922 return NULL;
5923 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005924 self->flag_prepare=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005925 txn = self->txn;
5926 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005927
5928 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5929
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005930 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005931 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005932 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005933
5934 _promote_transaction_dbs_and_sequences(self);
5935
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005936 RETURN_IF_ERR();
5937 RETURN_NONE();
5938}
5939
5940static PyObject*
5941DBTxn_prepare(DBTxnObject* self, PyObject* args)
5942{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005943 int err;
5944 char* gid=NULL;
5945 int gid_size=0;
5946
5947 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
5948 return NULL;
5949
5950 if (gid_size != DB_XIDDATASIZE) {
5951 PyErr_SetString(PyExc_TypeError,
5952 "gid must be DB_XIDDATASIZE bytes long");
5953 return NULL;
5954 }
5955
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005956 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005957 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005958 "after txn_commit, txn_abort "
5959 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005960 if (t) {
5961 PyErr_SetObject(DBError, t);
5962 Py_DECREF(t);
5963 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005964 return NULL;
5965 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005966 self->flag_prepare=1; /* Prepare state */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005967 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005968 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005969 MYDB_END_ALLOW_THREADS;
5970 RETURN_IF_ERR();
5971 RETURN_NONE();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005972}
5973
5974
5975static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005976DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005977{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005978 PyObject *dummy;
5979 int err=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005980 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005981
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005982 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005983 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005984 "after txn_commit, txn_abort "
5985 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005986 if (t) {
5987 PyErr_SetObject(DBError, t);
5988 Py_DECREF(t);
5989 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005990 return NULL;
5991 }
5992 txn = self->txn;
5993 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005994
5995 _close_transaction_cursors(self);
5996#if (DBVER >= 43)
5997 while (self->children_sequences) {
5998 dummy=DBSequence_close_internal(self->children_sequences,0,0);
5999 Py_XDECREF(dummy);
6000 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006001#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00006002 while (self->children_dbs) {
Jesus Cea5cd5f122008-09-23 18:54:08 +00006003 dummy=DB_close_internal(self->children_dbs, 0, 0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006004 Py_XDECREF(dummy);
6005 }
6006
6007 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
6008
6009 MYDB_BEGIN_ALLOW_THREADS;
6010 if (discard) {
6011 assert(!self->flag_prepare);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006012 err = txn->discard(txn,0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006013 } else {
6014 /*
6015 ** If the transaction is in the "prepare" or "recover" state,
6016 ** we better do not implicitly abort it.
6017 */
6018 if (!self->flag_prepare) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00006019 err = txn->abort(txn);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006020 }
6021 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006022 MYDB_END_ALLOW_THREADS;
6023 RETURN_IF_ERR();
6024 RETURN_NONE();
6025}
6026
Jesus Ceaef9764f2008-05-13 18:45:46 +00006027static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006028DBTxn_abort(DBTxnObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006029{
Jesus Ceaef9764f2008-05-13 18:45:46 +00006030 self->flag_prepare=0;
6031 _close_transaction_cursors(self);
6032
6033 return DBTxn_abort_discard_internal(self,0);
6034}
6035
6036static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006037DBTxn_discard(DBTxnObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006038{
Jesus Ceaef9764f2008-05-13 18:45:46 +00006039 self->flag_prepare=0;
6040 _close_transaction_cursors(self);
6041
6042 return DBTxn_abort_discard_internal(self,1);
6043}
6044
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006045
6046static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006047DBTxn_id(DBTxnObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006048{
6049 int id;
6050
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00006051 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00006052 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00006053 "after txn_commit, txn_abort "
6054 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006055 if (t) {
6056 PyErr_SetObject(DBError, t);
6057 Py_DECREF(t);
6058 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00006059 return NULL;
6060 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006061 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006062 id = self->txn->id(self->txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006063 MYDB_END_ALLOW_THREADS;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006064 return NUMBER_FromLong(id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006065}
6066
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006067#if (DBVER >= 43)
6068/* --------------------------------------------------------------------- */
6069/* DBSequence methods */
6070
6071
6072static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00006073DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006074{
Jesus Ceaef9764f2008-05-13 18:45:46 +00006075 int err=0;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006076
Jesus Ceaef9764f2008-05-13 18:45:46 +00006077 if (self->sequence!=NULL) {
6078 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
6079 if (self->txn) {
6080 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
6081 self->txn=NULL;
6082 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006083
Jesus Cea5cd5f122008-09-23 18:54:08 +00006084 /*
6085 ** "do_not_close" is used to dispose all related objects in the
6086 ** tree, without actually releasing the "root" object.
6087 ** This is done, for example, because function calls like
6088 ** "DBSequence.remove()" implicitly close the underlying handle. So
6089 ** the handle doesn't need to be closed, but related objects
6090 ** must be cleaned up.
6091 */
Jesus Ceaef9764f2008-05-13 18:45:46 +00006092 if (!do_not_close) {
6093 MYDB_BEGIN_ALLOW_THREADS
6094 err = self->sequence->close(self->sequence, flags);
6095 MYDB_END_ALLOW_THREADS
6096 }
6097 self->sequence = NULL;
6098
6099 RETURN_IF_ERR();
6100 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006101
6102 RETURN_NONE();
6103}
6104
6105static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00006106DBSequence_close(DBSequenceObject* self, PyObject* args)
6107{
6108 int flags=0;
6109 if (!PyArg_ParseTuple(args,"|i:close", &flags))
6110 return NULL;
6111
6112 return DBSequence_close_internal(self,flags,0);
6113}
6114
6115static PyObject*
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006116DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6117{
6118 int err, flags = 0;
6119 int delta = 1;
6120 db_seq_t value;
6121 PyObject *txnobj = NULL;
6122 DB_TXN *txn = NULL;
6123 static char* kwnames[] = {"delta", "txn", "flags", NULL };
6124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
6125 return NULL;
6126 CHECK_SEQUENCE_NOT_CLOSED(self)
6127
6128 if (!checkTxnObj(txnobj, &txn))
6129 return NULL;
6130
6131 MYDB_BEGIN_ALLOW_THREADS
6132 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
6133 MYDB_END_ALLOW_THREADS
6134
6135 RETURN_IF_ERR();
6136 return PyLong_FromLongLong(value);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006137}
6138
6139static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006140DBSequence_get_dbp(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006141{
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006142 CHECK_SEQUENCE_NOT_CLOSED(self)
6143 Py_INCREF(self->mydb);
6144 return (PyObject* )self->mydb;
6145}
6146
6147static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006148DBSequence_get_key(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006149{
6150 int err;
6151 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00006152 PyObject *retval = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006153
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006154 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006155 CHECK_SEQUENCE_NOT_CLOSED(self)
6156 MYDB_BEGIN_ALLOW_THREADS
6157 err = self->sequence->get_key(self->sequence, &key);
6158 MYDB_END_ALLOW_THREADS
6159
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006160 if (!err)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006161 retval = Build_PyString(key.data, key.size);
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006162
6163 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006164 RETURN_IF_ERR();
6165
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006166 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006167}
6168
6169static PyObject*
6170DBSequence_init_value(DBSequenceObject* self, PyObject* args)
6171{
6172 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006173 PY_LONG_LONG value;
6174 db_seq_t value2;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006175 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006176 return NULL;
6177 CHECK_SEQUENCE_NOT_CLOSED(self)
6178
Jesus Ceaef9764f2008-05-13 18:45:46 +00006179 value2=value; /* If truncation, compiler should show a warning */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006180 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006181 err = self->sequence->initial_value(self->sequence, value2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006182 MYDB_END_ALLOW_THREADS
6183
6184 RETURN_IF_ERR();
6185
6186 RETURN_NONE();
6187}
6188
6189static PyObject*
6190DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6191{
6192 int err, flags = 0;
6193 PyObject* keyobj;
6194 PyObject *txnobj = NULL;
6195 DB_TXN *txn = NULL;
6196 DBT key;
6197
6198 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006199 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006200 return NULL;
6201
6202 if (!checkTxnObj(txnobj, &txn))
6203 return NULL;
6204
6205 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
6206 return NULL;
6207
6208 MYDB_BEGIN_ALLOW_THREADS
6209 err = self->sequence->open(self->sequence, txn, &key, flags);
6210 MYDB_END_ALLOW_THREADS
6211
Jesus Ceaac25fab2008-09-03 17:50:32 +00006212 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006213 RETURN_IF_ERR();
6214
Jesus Ceaef9764f2008-05-13 18:45:46 +00006215 if (txn) {
6216 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
6217 self->txn=(DBTxnObject *)txnobj;
6218 }
6219
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006220 RETURN_NONE();
6221}
6222
6223static PyObject*
6224DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6225{
Jesus Ceaef9764f2008-05-13 18:45:46 +00006226 PyObject *dummy;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006227 int err, flags = 0;
6228 PyObject *txnobj = NULL;
6229 DB_TXN *txn = NULL;
6230
6231 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006232 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006233 return NULL;
6234
6235 if (!checkTxnObj(txnobj, &txn))
6236 return NULL;
6237
6238 CHECK_SEQUENCE_NOT_CLOSED(self)
6239
6240 MYDB_BEGIN_ALLOW_THREADS
6241 err = self->sequence->remove(self->sequence, txn, flags);
6242 MYDB_END_ALLOW_THREADS
6243
Jesus Ceaef9764f2008-05-13 18:45:46 +00006244 dummy=DBSequence_close_internal(self,flags,1);
6245 Py_XDECREF(dummy);
6246
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006247 RETURN_IF_ERR();
6248 RETURN_NONE();
6249}
6250
6251static PyObject*
6252DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
6253{
6254 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006255 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006256 return NULL;
6257 CHECK_SEQUENCE_NOT_CLOSED(self)
6258
6259 MYDB_BEGIN_ALLOW_THREADS
6260 err = self->sequence->set_cachesize(self->sequence, size);
6261 MYDB_END_ALLOW_THREADS
6262
6263 RETURN_IF_ERR();
6264 RETURN_NONE();
6265}
6266
6267static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006268DBSequence_get_cachesize(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006269{
6270 int err, size;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006271
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006272 CHECK_SEQUENCE_NOT_CLOSED(self)
6273
6274 MYDB_BEGIN_ALLOW_THREADS
6275 err = self->sequence->get_cachesize(self->sequence, &size);
6276 MYDB_END_ALLOW_THREADS
6277
6278 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006279 return NUMBER_FromLong(size);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006280}
6281
6282static PyObject*
6283DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
6284{
6285 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006286 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006287 return NULL;
6288 CHECK_SEQUENCE_NOT_CLOSED(self)
6289
6290 MYDB_BEGIN_ALLOW_THREADS
6291 err = self->sequence->set_flags(self->sequence, flags);
6292 MYDB_END_ALLOW_THREADS
6293
6294 RETURN_IF_ERR();
6295 RETURN_NONE();
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006296}
6297
6298static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006299DBSequence_get_flags(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006300{
6301 unsigned int flags;
6302 int err;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006303
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006304 CHECK_SEQUENCE_NOT_CLOSED(self)
6305
6306 MYDB_BEGIN_ALLOW_THREADS
6307 err = self->sequence->get_flags(self->sequence, &flags);
6308 MYDB_END_ALLOW_THREADS
6309
6310 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006311 return NUMBER_FromLong((int)flags);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006312}
6313
6314static PyObject*
6315DBSequence_set_range(DBSequenceObject* self, PyObject* args)
6316{
6317 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006318 PY_LONG_LONG min, max;
6319 db_seq_t min2, max2;
Tim Petersbb21b2c2006-06-06 15:50:17 +00006320 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006321 return NULL;
6322 CHECK_SEQUENCE_NOT_CLOSED(self)
6323
Jesus Ceaef9764f2008-05-13 18:45:46 +00006324 min2=min; /* If truncation, compiler should show a warning */
6325 max2=max;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006326 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006327 err = self->sequence->set_range(self->sequence, min2, max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006328 MYDB_END_ALLOW_THREADS
6329
6330 RETURN_IF_ERR();
6331 RETURN_NONE();
6332}
6333
6334static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006335DBSequence_get_range(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006336{
6337 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006338 PY_LONG_LONG min, max;
6339 db_seq_t min2, max2;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006340
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006341 CHECK_SEQUENCE_NOT_CLOSED(self)
6342
6343 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006344 err = self->sequence->get_range(self->sequence, &min2, &max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006345 MYDB_END_ALLOW_THREADS
6346
6347 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00006348 min=min2; /* If truncation, compiler should show a warning */
6349 max=max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006350 return Py_BuildValue("(LL)", min, max);
6351}
6352
6353static PyObject*
6354DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6355{
6356 int err, flags = 0;
6357 DB_SEQUENCE_STAT* sp = NULL;
6358 PyObject* dict_stat;
6359 static char* kwnames[] = {"flags", NULL };
6360 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
6361 return NULL;
6362 CHECK_SEQUENCE_NOT_CLOSED(self);
6363
6364 MYDB_BEGIN_ALLOW_THREADS;
6365 err = self->sequence->stat(self->sequence, &sp, flags);
6366 MYDB_END_ALLOW_THREADS;
6367 RETURN_IF_ERR();
6368
6369 if ((dict_stat = PyDict_New()) == NULL) {
6370 free(sp);
6371 return NULL;
6372 }
6373
6374
6375#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
6376#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
6377
6378 MAKE_INT_ENTRY(wait);
6379 MAKE_INT_ENTRY(nowait);
6380 MAKE_LONG_LONG_ENTRY(current);
6381 MAKE_LONG_LONG_ENTRY(value);
6382 MAKE_LONG_LONG_ENTRY(last_value);
6383 MAKE_LONG_LONG_ENTRY(min);
6384 MAKE_LONG_LONG_ENTRY(max);
6385 MAKE_INT_ENTRY(cache_size);
6386 MAKE_INT_ENTRY(flags);
6387
6388#undef MAKE_INT_ENTRY
6389#undef MAKE_LONG_LONG_ENTRY
6390
6391 free(sp);
6392 return dict_stat;
6393}
6394#endif
6395
6396
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006397/* --------------------------------------------------------------------- */
6398/* Method definition tables and type objects */
6399
6400static PyMethodDef DB_methods[] = {
Jesus Cea4907d272008-08-31 14:00:51 +00006401 {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006402 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006403 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006404 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
6405 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006406 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
6407 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006408 {"fd", (PyCFunction)DB_fd, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006409 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00006410 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006411 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006412 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006413 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006414 {"get_type", (PyCFunction)DB_get_type, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006415 {"join", (PyCFunction)DB_join, METH_VARARGS},
6416 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
Jesus Cea4907d272008-08-31 14:00:51 +00006417 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006418 {"items", (PyCFunction)DB_items, METH_VARARGS},
6419 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6420 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6421 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6422 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6423 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6424 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006425 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006426 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006427#if (DBVER >= 41)
6428 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6429#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006430 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6431 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6432 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6433 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6434 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6435 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6436 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6437 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6438 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006439 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
6440 {"set_private", (PyCFunction)DB_set_private, METH_O},
6441 {"get_private", (PyCFunction)DB_get_private, METH_NOARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006442 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006443 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006444 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006445 {"type", (PyCFunction)DB_get_type, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006446 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6447 {"values", (PyCFunction)DB_values, METH_VARARGS},
6448 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6449 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6450 {NULL, NULL} /* sentinel */
6451};
6452
6453
6454static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00006455 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006456 (binaryfunc)DB_subscript, /*mp_subscript*/
6457 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6458};
6459
6460
6461static PyMethodDef DBCursor_methods[] = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006462 {"close", (PyCFunction)DBC_close, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006463 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6464 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6465 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6466 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6467 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6468 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00006469 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006470 {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006471 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6472 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6473 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6474 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6475 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6476 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6477 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006478 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00006479 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006480 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6481 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6482 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6483 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6484 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6485 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6486 {NULL, NULL} /* sentinel */
6487};
6488
6489
6490static PyMethodDef DBEnv_methods[] = {
6491 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6492 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6493 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006494#if (DBVER >= 41)
6495 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6496 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6497 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6498#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00006499 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00006500 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006501 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6502 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006503 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Jesus Ceaca3939c2008-05-22 15:27:38 +00006504#if (DBVER >= 47)
6505 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
6506#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006507 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6508 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6509 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006510#if (DBVER >= 42)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006511 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006512#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00006513 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006514 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006515#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006516 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006517#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006518 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6519 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6520 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006521 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6522 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6523 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6524 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6525 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6526 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00006527 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006528 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6529 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006530 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS},
Gregory P. Smithac11e022007-11-05 02:56:31 +00006531 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006532 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6533 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6534 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006535 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006536 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00006537#if (DBVER >= 44)
6538 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6539#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006540 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006541 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS},
Jesus Ceaca3939c2008-05-22 15:27:38 +00006542 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
6543 METH_VARARGS||METH_KEYWORDS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006544 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6545#if (DBVER >= 42)
6546 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6547#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006548 {"set_private", (PyCFunction)DBEnv_set_private, METH_O},
6549 {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS},
6550 {"rep_start", (PyCFunction)DBEnv_rep_start,
6551 METH_VARARGS|METH_KEYWORDS},
6552 {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
6553 {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
6554 METH_VARARGS},
6555#if (DBVER >= 46)
6556 {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS},
6557#endif
6558#if (DBVER >= 44)
6559 {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS},
6560 {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS},
6561 {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006562#endif
6563#if (DBVER >= 45)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006564 {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS},
6565 {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS},
6566#endif
6567#if (DBVER >= 47)
6568 {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS},
6569 {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS},
6570#endif
6571#if (DBVER >= 45)
6572 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006573#endif
6574#if (DBVER >= 45)
6575 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006576 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006577 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006578 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006579 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6580 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6581#endif
6582#if (DBVER >= 45)
6583 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6584 METH_VARARGS|METH_KEYWORDS},
6585 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6586 METH_VARARGS|METH_KEYWORDS},
6587 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6588 METH_VARARGS|METH_KEYWORDS},
6589 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6590 METH_VARARGS},
6591 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006592 METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006593 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006594 METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006595#endif
6596#if (DBVER >= 46)
6597 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6598 METH_VARARGS|METH_KEYWORDS},
6599 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6600 METH_VARARGS|METH_KEYWORDS},
6601#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006602 {NULL, NULL} /* sentinel */
6603};
6604
6605
6606static PyMethodDef DBTxn_methods[] = {
6607 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6608 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006609 {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS},
6610 {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS},
6611 {"id", (PyCFunction)DBTxn_id, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006612 {NULL, NULL} /* sentinel */
6613};
6614
6615
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006616#if (DBVER >= 43)
6617static PyMethodDef DBSequence_methods[] = {
6618 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6619 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006620 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS},
6621 {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006622 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6623 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6624 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6625 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006626 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006627 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006628 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006629 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006630 {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006631 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6632 {NULL, NULL} /* sentinel */
6633};
6634#endif
6635
6636
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006637static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006638DBEnv_db_home_get(DBEnvObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006639{
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006640 const char *home = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006641
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006642 CHECK_ENV_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006643
Jesus Ceaef9764f2008-05-13 18:45:46 +00006644#if (DBVER >= 42)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006645 self->db_env->get_home(self->db_env, &home);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006646#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006647 home=self->db_env->db_home;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006648#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006649
6650 if (home == NULL) {
6651 RETURN_NONE();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006652 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006653 return PyBytes_FromString(home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006654}
6655
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006656static PyGetSetDef DBEnv_getsets[] = {
6657 {"db_home", (getter)DBEnv_db_home_get, NULL,},
6658 {NULL}
6659};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006660
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006661
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006662statichere PyTypeObject DB_Type = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006663#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006664 PyObject_HEAD_INIT(NULL)
6665 0, /*ob_size*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006666#else
6667 PyVarObject_HEAD_INIT(NULL, 0)
6668#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006669 "DB", /*tp_name*/
6670 sizeof(DBObject), /*tp_basicsize*/
6671 0, /*tp_itemsize*/
6672 /* methods */
6673 (destructor)DB_dealloc, /*tp_dealloc*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006674 0, /*tp_print*/
6675 0, /*tp_getattr*/
6676 0, /*tp_setattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006677 0, /*tp_compare*/
6678 0, /*tp_repr*/
6679 0, /*tp_as_number*/
6680 0, /*tp_as_sequence*/
6681 &DB_mapping,/*tp_as_mapping*/
6682 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006683 0, /* tp_call */
6684 0, /* tp_str */
6685 0, /* tp_getattro */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006686 0, /* tp_setattro */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006687 0, /* tp_as_buffer */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006688#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith31c50652004-06-28 01:20:40 +00006689 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006690#else
6691 Py_TPFLAGS_DEFAULT, /* tp_flags */
6692#endif
6693 0, /* tp_doc */
6694 0, /* tp_traverse */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006695 0, /* tp_clear */
6696 0, /* tp_richcompare */
6697 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006698 0, /*tp_iter*/
6699 0, /*tp_iternext*/
6700 DB_methods, /*tp_methods*/
6701 0, /*tp_members*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006702};
6703
6704
6705statichere PyTypeObject DBCursor_Type = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006706#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006707 PyObject_HEAD_INIT(NULL)
6708 0, /*ob_size*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006709#else
6710 PyVarObject_HEAD_INIT(NULL, 0)
6711#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006712 "DBCursor", /*tp_name*/
6713 sizeof(DBCursorObject), /*tp_basicsize*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006714 0, /*tp_itemsize*/
6715 /* methods */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006716 (destructor)DBCursor_dealloc,/*tp_dealloc*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006717 0, /*tp_print*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006718 0, /*tp_getattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006719 0, /*tp_setattr*/
6720 0, /*tp_compare*/
6721 0, /*tp_repr*/
6722 0, /*tp_as_number*/
6723 0, /*tp_as_sequence*/
6724 0, /*tp_as_mapping*/
6725 0, /*tp_hash*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006726 0, /*tp_call*/
6727 0, /*tp_str*/
6728 0, /*tp_getattro*/
6729 0, /*tp_setattro*/
6730 0, /*tp_as_buffer*/
6731#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith31c50652004-06-28 01:20:40 +00006732 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006733#else
6734 Py_TPFLAGS_DEFAULT, /* tp_flags */
6735#endif
6736 0, /* tp_doc */
6737 0, /* tp_traverse */
6738 0, /* tp_clear */
6739 0, /* tp_richcompare */
6740 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
6741 0, /*tp_iter*/
6742 0, /*tp_iternext*/
6743 DBCursor_methods, /*tp_methods*/
6744 0, /*tp_members*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006745};
6746
6747
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006748statichere PyTypeObject DBEnv_Type = {
6749#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006750 PyObject_HEAD_INIT(NULL)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006751 0, /*ob_size*/
6752#else
6753 PyVarObject_HEAD_INIT(NULL, 0)
6754#endif
6755 "DBEnv", /*tp_name*/
6756 sizeof(DBEnvObject), /*tp_basicsize*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006757 0, /*tp_itemsize*/
6758 /* methods */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006759 (destructor)DBEnv_dealloc, /*tp_dealloc*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006760 0, /*tp_print*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006761 0, /*tp_getattr*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006762 0, /*tp_setattr*/
6763 0, /*tp_compare*/
6764 0, /*tp_repr*/
6765 0, /*tp_as_number*/
6766 0, /*tp_as_sequence*/
6767 0, /*tp_as_mapping*/
6768 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006769 0, /* tp_call */
6770 0, /* tp_str */
6771 0, /* tp_getattro */
6772 0, /* tp_setattro */
6773 0, /* tp_as_buffer */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006774#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006775 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006776#else
6777 Py_TPFLAGS_DEFAULT, /* tp_flags */
6778#endif
6779 0, /* tp_doc */
6780 0, /* tp_traverse */
6781 0, /* tp_clear */
6782 0, /* tp_richcompare */
6783 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
6784 0, /* tp_iter */
6785 0, /* tp_iternext */
6786 DBEnv_methods, /* tp_methods */
6787 0, /* tp_members */
6788 DBEnv_getsets, /* tp_getsets */
6789};
6790
6791statichere PyTypeObject DBTxn_Type = {
6792#if (PY_VERSION_HEX < 0x03000000)
6793 PyObject_HEAD_INIT(NULL)
6794 0, /*ob_size*/
6795#else
6796 PyVarObject_HEAD_INIT(NULL, 0)
6797#endif
6798 "DBTxn", /*tp_name*/
6799 sizeof(DBTxnObject), /*tp_basicsize*/
6800 0, /*tp_itemsize*/
6801 /* methods */
6802 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6803 0, /*tp_print*/
6804 0, /*tp_getattr*/
6805 0, /*tp_setattr*/
6806 0, /*tp_compare*/
6807 0, /*tp_repr*/
6808 0, /*tp_as_number*/
6809 0, /*tp_as_sequence*/
6810 0, /*tp_as_mapping*/
6811 0, /*tp_hash*/
6812 0, /* tp_call */
6813 0, /* tp_str */
6814 0, /* tp_getattro */
6815 0, /* tp_setattro */
6816 0, /* tp_as_buffer */
6817#if (PY_VERSION_HEX < 0x03000000)
6818 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6819#else
6820 Py_TPFLAGS_DEFAULT, /* tp_flags */
6821#endif
6822 0, /* tp_doc */
6823 0, /* tp_traverse */
6824 0, /* tp_clear */
6825 0, /* tp_richcompare */
6826 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
6827 0, /*tp_iter*/
6828 0, /*tp_iternext*/
6829 DBTxn_methods, /*tp_methods*/
6830 0, /*tp_members*/
6831};
6832
6833
6834statichere PyTypeObject DBLock_Type = {
6835#if (PY_VERSION_HEX < 0x03000000)
6836 PyObject_HEAD_INIT(NULL)
6837 0, /*ob_size*/
6838#else
6839 PyVarObject_HEAD_INIT(NULL, 0)
6840#endif
6841 "DBLock", /*tp_name*/
6842 sizeof(DBLockObject), /*tp_basicsize*/
6843 0, /*tp_itemsize*/
6844 /* methods */
6845 (destructor)DBLock_dealloc, /*tp_dealloc*/
6846 0, /*tp_print*/
6847 0, /*tp_getattr*/
6848 0, /*tp_setattr*/
6849 0, /*tp_compare*/
6850 0, /*tp_repr*/
6851 0, /*tp_as_number*/
6852 0, /*tp_as_sequence*/
6853 0, /*tp_as_mapping*/
6854 0, /*tp_hash*/
6855 0, /* tp_call */
6856 0, /* tp_str */
6857 0, /* tp_getattro */
6858 0, /* tp_setattro */
6859 0, /* tp_as_buffer */
6860#if (PY_VERSION_HEX < 0x03000000)
6861 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6862#else
6863 Py_TPFLAGS_DEFAULT, /* tp_flags */
6864#endif
6865 0, /* tp_doc */
6866 0, /* tp_traverse */
6867 0, /* tp_clear */
6868 0, /* tp_richcompare */
6869 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
6870};
6871
6872#if (DBVER >= 43)
6873statichere PyTypeObject DBSequence_Type = {
6874#if (PY_VERSION_HEX < 0x03000000)
6875 PyObject_HEAD_INIT(NULL)
6876 0, /*ob_size*/
6877#else
6878 PyVarObject_HEAD_INIT(NULL, 0)
6879#endif
6880 "DBSequence", /*tp_name*/
6881 sizeof(DBSequenceObject), /*tp_basicsize*/
6882 0, /*tp_itemsize*/
6883 /* methods */
6884 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6885 0, /*tp_print*/
6886 0, /*tp_getattr*/
6887 0, /*tp_setattr*/
6888 0, /*tp_compare*/
6889 0, /*tp_repr*/
6890 0, /*tp_as_number*/
6891 0, /*tp_as_sequence*/
6892 0, /*tp_as_mapping*/
6893 0, /*tp_hash*/
6894 0, /* tp_call */
6895 0, /* tp_str */
6896 0, /* tp_getattro */
6897 0, /* tp_setattro */
6898 0, /* tp_as_buffer */
6899#if (PY_VERSION_HEX < 0x03000000)
6900 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6901#else
6902 Py_TPFLAGS_DEFAULT, /* tp_flags */
6903#endif
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006904 0, /* tp_doc */
6905 0, /* tp_traverse */
6906 0, /* tp_clear */
6907 0, /* tp_richcompare */
6908 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006909 0, /*tp_iter*/
6910 0, /*tp_iternext*/
6911 DBSequence_methods, /*tp_methods*/
6912 0, /*tp_members*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006913};
6914#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006915
6916/* --------------------------------------------------------------------- */
6917/* Module-level functions */
6918
6919static PyObject*
6920DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6921{
6922 PyObject* dbenvobj = NULL;
6923 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00006924 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006925
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006926 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6927 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006928 return NULL;
6929 if (dbenvobj == Py_None)
6930 dbenvobj = NULL;
6931 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6932 makeTypeError("DBEnv", dbenvobj);
6933 return NULL;
6934 }
6935
6936 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6937}
6938
6939
6940static PyObject*
6941DBEnv_construct(PyObject* self, PyObject* args)
6942{
6943 int flags = 0;
6944 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6945 return (PyObject* )newDBEnvObject(flags);
6946}
6947
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006948#if (DBVER >= 43)
6949static PyObject*
6950DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6951{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006952 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006953 int flags = 0;
6954 static char* kwnames[] = { "db", "flags", NULL};
6955
6956 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6957 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006958 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006959 makeTypeError("DB", dbobj);
6960 return NULL;
6961 }
6962 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6963}
6964#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006965
6966static char bsddb_version_doc[] =
6967"Returns a tuple of major, minor, and patch release numbers of the\n\
6968underlying DB library.";
6969
6970static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006971bsddb_version(PyObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006972{
6973 int major, minor, patch;
6974
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006975 db_version(&major, &minor, &patch);
6976 return Py_BuildValue("(iii)", major, minor, patch);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006977}
6978
6979
6980/* List of functions defined in the module */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006981static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006982 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6983 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006984#if (DBVER >= 43)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006985 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006986#endif
6987 {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006988 {NULL, NULL} /* sentinel */
6989};
6990
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006991
Gregory P. Smith39250532007-10-09 06:02:21 +00006992/* API structure */
6993static BSDDB_api bsddb_api;
6994
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006995
6996/* --------------------------------------------------------------------- */
6997/* Module initialization */
6998
6999
7000/* Convenience routine to export an integer value.
7001 * Errors are silently ignored, for better or for worse...
7002 */
7003#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
7004
Gregory P. Smith41631e82003-09-21 00:08:14 +00007005#define MODULE_NAME_MAX_LEN 11
7006static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007007
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007008#if (PY_VERSION_HEX >= 0x03000000)
7009static struct PyModuleDef bsddbmodule = {
7010 PyModuleDef_HEAD_INIT,
7011 _bsddbModuleName, /* Name of module */
7012 NULL, /* module documentation, may be NULL */
7013 -1, /* size of per-interpreter state of the module,
7014 or -1 if the module keeps state in global variables. */
7015 bsddb_methods,
7016 NULL, /* Reload */
7017 NULL, /* Traverse */
7018 NULL, /* Clear */
7019 NULL /* Free */
7020};
7021#endif
7022
7023
7024#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007025DL_EXPORT(void) init_bsddb(void)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007026#else
7027PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */
7028#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007029{
7030 PyObject* m;
7031 PyObject* d;
Christian Heimes593daf52008-05-26 12:51:38 +00007032 PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
7033 PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
7034 PyObject* cvsid_s = PyBytes_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00007035 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007036
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007037 /* Initialize object types */
7038 if ((PyType_Ready(&DB_Type) < 0)
7039 || (PyType_Ready(&DBCursor_Type) < 0)
7040 || (PyType_Ready(&DBEnv_Type) < 0)
7041 || (PyType_Ready(&DBTxn_Type) < 0)
7042 || (PyType_Ready(&DBLock_Type) < 0)
7043#if (DBVER >= 43)
7044 || (PyType_Ready(&DBSequence_Type) < 0)
7045#endif
7046 ) {
7047#if (PY_VERSION_HEX < 0x03000000)
7048 return;
7049#else
7050 return NULL;
7051#endif
7052 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007053
Mark Hammonda69d4092003-04-22 23:13:27 +00007054#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007055 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00007056 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007057#endif
7058
7059 /* Create the module and add the functions */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007060#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007061 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007062#else
7063 m=PyModule_Create(&bsddbmodule);
7064#endif
7065 if (m == NULL) {
7066#if (PY_VERSION_HEX < 0x03000000)
7067 return;
7068#else
7069 return NULL;
7070#endif
7071 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007072
7073 /* Add some symbolic constants to the module */
7074 d = PyModule_GetDict(m);
7075 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
7076 PyDict_SetItemString(d, "cvsid", cvsid_s);
7077 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
7078 Py_DECREF(pybsddb_version_s);
7079 pybsddb_version_s = NULL;
7080 Py_DECREF(cvsid_s);
7081 cvsid_s = NULL;
7082 Py_DECREF(db_version_s);
7083 db_version_s = NULL;
7084
7085 ADD_INT(d, DB_VERSION_MAJOR);
7086 ADD_INT(d, DB_VERSION_MINOR);
7087 ADD_INT(d, DB_VERSION_PATCH);
7088
7089 ADD_INT(d, DB_MAX_PAGES);
7090 ADD_INT(d, DB_MAX_RECORDS);
7091
Gregory P. Smith41631e82003-09-21 00:08:14 +00007092#if (DBVER >= 42)
7093 ADD_INT(d, DB_RPCCLIENT);
7094#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007095 ADD_INT(d, DB_CLIENT);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007096 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
Gregory P. Smith41631e82003-09-21 00:08:14 +00007097 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
7098#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007099 ADD_INT(d, DB_XA_CREATE);
7100
7101 ADD_INT(d, DB_CREATE);
7102 ADD_INT(d, DB_NOMMAP);
7103 ADD_INT(d, DB_THREAD);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007104#if (DBVER >= 45)
7105 ADD_INT(d, DB_MULTIVERSION);
7106#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007107
7108 ADD_INT(d, DB_FORCE);
7109 ADD_INT(d, DB_INIT_CDB);
7110 ADD_INT(d, DB_INIT_LOCK);
7111 ADD_INT(d, DB_INIT_LOG);
7112 ADD_INT(d, DB_INIT_MPOOL);
7113 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007114 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007115
Jesus Ceaef9764f2008-05-13 18:45:46 +00007116 ADD_INT(d, DB_XIDDATASIZE);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007117
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007118 ADD_INT(d, DB_RECOVER);
7119 ADD_INT(d, DB_RECOVER_FATAL);
7120 ADD_INT(d, DB_TXN_NOSYNC);
7121 ADD_INT(d, DB_USE_ENVIRON);
7122 ADD_INT(d, DB_USE_ENVIRON_ROOT);
7123
7124 ADD_INT(d, DB_LOCKDOWN);
7125 ADD_INT(d, DB_PRIVATE);
7126 ADD_INT(d, DB_SYSTEM_MEM);
7127
7128 ADD_INT(d, DB_TXN_SYNC);
7129 ADD_INT(d, DB_TXN_NOWAIT);
7130
7131 ADD_INT(d, DB_EXCL);
7132 ADD_INT(d, DB_FCNTL_LOCKING);
7133 ADD_INT(d, DB_ODDFILESIZE);
7134 ADD_INT(d, DB_RDWRMASTER);
7135 ADD_INT(d, DB_RDONLY);
7136 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007137 ADD_INT(d, DB_EXTENT);
7138 ADD_INT(d, DB_CDB_ALLDB);
7139 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007140 ADD_INT(d, DB_UPGRADE);
7141
7142 ADD_INT(d, DB_AGGRESSIVE);
7143 ADD_INT(d, DB_NOORDERCHK);
7144 ADD_INT(d, DB_ORDERCHKONLY);
7145 ADD_INT(d, DB_PR_PAGE);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007146
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007147 ADD_INT(d, DB_PR_RECOVERYTEST);
7148 ADD_INT(d, DB_SALVAGE);
7149
7150 ADD_INT(d, DB_LOCK_NORUN);
7151 ADD_INT(d, DB_LOCK_DEFAULT);
7152 ADD_INT(d, DB_LOCK_OLDEST);
7153 ADD_INT(d, DB_LOCK_RANDOM);
7154 ADD_INT(d, DB_LOCK_YOUNGEST);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007155 ADD_INT(d, DB_LOCK_MAXLOCKS);
7156 ADD_INT(d, DB_LOCK_MINLOCKS);
7157 ADD_INT(d, DB_LOCK_MINWRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007158
Jesus Ceaef9764f2008-05-13 18:45:46 +00007159 ADD_INT(d, DB_LOCK_EXPIRE);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007160#if (DBVER >= 43)
7161 ADD_INT(d, DB_LOCK_MAXWRITE);
7162#endif
7163
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007164 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007165
7166 ADD_INT(d, DB_LOCK_DUMP);
7167 ADD_INT(d, DB_LOCK_GET);
7168 ADD_INT(d, DB_LOCK_INHERIT);
7169 ADD_INT(d, DB_LOCK_PUT);
7170 ADD_INT(d, DB_LOCK_PUT_ALL);
7171 ADD_INT(d, DB_LOCK_PUT_OBJ);
7172
7173 ADD_INT(d, DB_LOCK_NG);
7174 ADD_INT(d, DB_LOCK_READ);
7175 ADD_INT(d, DB_LOCK_WRITE);
7176 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007177 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007178 ADD_INT(d, DB_LOCK_IWRITE);
7179 ADD_INT(d, DB_LOCK_IREAD);
7180 ADD_INT(d, DB_LOCK_IWR);
Gregory P. Smith29602d22006-01-24 09:46:48 +00007181#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007182 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00007183#else
7184 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
7185#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007186 ADD_INT(d, DB_LOCK_WWRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007187
7188 ADD_INT(d, DB_LOCK_RECORD);
7189 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007190 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007191 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007192
7193 ADD_INT(d, DB_LOCK_NOWAIT);
7194 ADD_INT(d, DB_LOCK_RECORD);
7195 ADD_INT(d, DB_LOCK_UPGRADE);
7196
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007197 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007198#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007199 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007200#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007201 ADD_INT(d, DB_LSTAT_FREE);
7202 ADD_INT(d, DB_LSTAT_HELD);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007203
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007204 ADD_INT(d, DB_LSTAT_PENDING);
7205 ADD_INT(d, DB_LSTAT_WAITING);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007206
7207 ADD_INT(d, DB_ARCH_ABS);
7208 ADD_INT(d, DB_ARCH_DATA);
7209 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00007210#if (DBVER >= 42)
7211 ADD_INT(d, DB_ARCH_REMOVE);
7212#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007213
7214 ADD_INT(d, DB_BTREE);
7215 ADD_INT(d, DB_HASH);
7216 ADD_INT(d, DB_RECNO);
7217 ADD_INT(d, DB_QUEUE);
7218 ADD_INT(d, DB_UNKNOWN);
7219
7220 ADD_INT(d, DB_DUP);
7221 ADD_INT(d, DB_DUPSORT);
7222 ADD_INT(d, DB_RECNUM);
7223 ADD_INT(d, DB_RENUMBER);
7224 ADD_INT(d, DB_REVSPLITOFF);
7225 ADD_INT(d, DB_SNAPSHOT);
7226
7227 ADD_INT(d, DB_JOIN_NOSORT);
7228
7229 ADD_INT(d, DB_AFTER);
7230 ADD_INT(d, DB_APPEND);
7231 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007232#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007233 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007234#endif
Jesus Ceaca3939c2008-05-22 15:27:38 +00007235
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007236#if (DBVER >= 41)
7237 _addIntToDict(d, "DB_CHECKPOINT", 0);
7238#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007239 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007240 ADD_INT(d, DB_CURLSN);
7241#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007242#if (DBVER <= 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007243 ADD_INT(d, DB_COMMIT);
7244#endif
7245 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007246 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007247 ADD_INT(d, DB_CURRENT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007248 ADD_INT(d, DB_FAST_STAT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007249 ADD_INT(d, DB_FIRST);
7250 ADD_INT(d, DB_FLUSH);
7251 ADD_INT(d, DB_GET_BOTH);
7252 ADD_INT(d, DB_GET_RECNO);
7253 ADD_INT(d, DB_JOIN_ITEM);
7254 ADD_INT(d, DB_KEYFIRST);
7255 ADD_INT(d, DB_KEYLAST);
7256 ADD_INT(d, DB_LAST);
7257 ADD_INT(d, DB_NEXT);
7258 ADD_INT(d, DB_NEXT_DUP);
7259 ADD_INT(d, DB_NEXT_NODUP);
7260 ADD_INT(d, DB_NODUPDATA);
7261 ADD_INT(d, DB_NOOVERWRITE);
7262 ADD_INT(d, DB_NOSYNC);
7263 ADD_INT(d, DB_POSITION);
7264 ADD_INT(d, DB_PREV);
7265 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007266#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007267 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007268#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007269 ADD_INT(d, DB_SET);
7270 ADD_INT(d, DB_SET_RANGE);
7271 ADD_INT(d, DB_SET_RECNO);
7272 ADD_INT(d, DB_WRITECURSOR);
7273
7274 ADD_INT(d, DB_OPFLAGS_MASK);
7275 ADD_INT(d, DB_RMW);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007276 ADD_INT(d, DB_DIRTY_READ);
7277 ADD_INT(d, DB_MULTIPLE);
7278 ADD_INT(d, DB_MULTIPLE_KEY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007279
Gregory P. Smith29602d22006-01-24 09:46:48 +00007280#if (DBVER >= 44)
7281 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
7282 ADD_INT(d, DB_READ_COMMITTED);
7283#endif
7284
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007285 ADD_INT(d, DB_DONOTINDEX);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007286
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007287#if (DBVER >= 41)
7288 _addIntToDict(d, "DB_INCOMPLETE", 0);
7289#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007290 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007291#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007292 ADD_INT(d, DB_KEYEMPTY);
7293 ADD_INT(d, DB_KEYEXIST);
7294 ADD_INT(d, DB_LOCK_DEADLOCK);
7295 ADD_INT(d, DB_LOCK_NOTGRANTED);
7296 ADD_INT(d, DB_NOSERVER);
7297 ADD_INT(d, DB_NOSERVER_HOME);
7298 ADD_INT(d, DB_NOSERVER_ID);
7299 ADD_INT(d, DB_NOTFOUND);
7300 ADD_INT(d, DB_OLD_VERSION);
7301 ADD_INT(d, DB_RUNRECOVERY);
7302 ADD_INT(d, DB_VERIFY_BAD);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007303 ADD_INT(d, DB_PAGE_NOTFOUND);
7304 ADD_INT(d, DB_SECONDARY_BAD);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007305 ADD_INT(d, DB_STAT_CLEAR);
7306 ADD_INT(d, DB_REGION_INIT);
7307 ADD_INT(d, DB_NOLOCKING);
7308 ADD_INT(d, DB_YIELDCPU);
7309 ADD_INT(d, DB_PANIC_ENVIRONMENT);
7310 ADD_INT(d, DB_NOPANIC);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007311
Jesus Ceaef9764f2008-05-13 18:45:46 +00007312#if (DBVER >= 41)
7313 ADD_INT(d, DB_OVERWRITE);
7314#endif
7315
Gregory P. Smithaae141a2007-11-01 21:08:14 +00007316#ifdef DB_REGISTER
7317 ADD_INT(d, DB_REGISTER);
7318#endif
7319
Gregory P. Smith41631e82003-09-21 00:08:14 +00007320#if (DBVER >= 42)
7321 ADD_INT(d, DB_TIME_NOTGRANTED);
7322 ADD_INT(d, DB_TXN_NOT_DURABLE);
7323 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
Gregory P. Smith41631e82003-09-21 00:08:14 +00007324 ADD_INT(d, DB_DIRECT_DB);
7325 ADD_INT(d, DB_INIT_REP);
7326 ADD_INT(d, DB_ENCRYPT);
7327 ADD_INT(d, DB_CHKSUM);
7328#endif
7329
Jesus Ceaca3939c2008-05-22 15:27:38 +00007330#if (DBVER >= 42) && (DBVER < 47)
7331 ADD_INT(d, DB_LOG_AUTOREMOVE);
7332 ADD_INT(d, DB_DIRECT_LOG);
7333#endif
7334
7335#if (DBVER >= 47)
7336 ADD_INT(d, DB_LOG_DIRECT);
7337 ADD_INT(d, DB_LOG_DSYNC);
7338 ADD_INT(d, DB_LOG_IN_MEMORY);
7339 ADD_INT(d, DB_LOG_AUTO_REMOVE);
7340 ADD_INT(d, DB_LOG_ZERO);
7341#endif
7342
Jesus Ceaef9764f2008-05-13 18:45:46 +00007343#if (DBVER >= 44)
7344 ADD_INT(d, DB_DSYNC_DB);
7345#endif
7346
7347#if (DBVER >= 45)
7348 ADD_INT(d, DB_TXN_SNAPSHOT);
7349#endif
7350
Jesus Ceaef9764f2008-05-13 18:45:46 +00007351 ADD_INT(d, DB_VERB_DEADLOCK);
7352#if (DBVER >= 46)
7353 ADD_INT(d, DB_VERB_FILEOPS);
7354 ADD_INT(d, DB_VERB_FILEOPS_ALL);
7355#endif
7356 ADD_INT(d, DB_VERB_RECOVERY);
7357#if (DBVER >= 44)
7358 ADD_INT(d, DB_VERB_REGISTER);
7359#endif
7360 ADD_INT(d, DB_VERB_REPLICATION);
7361 ADD_INT(d, DB_VERB_WAITSFOR);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007362
7363#if (DBVER >= 45)
7364 ADD_INT(d, DB_EVENT_PANIC);
7365 ADD_INT(d, DB_EVENT_REP_CLIENT);
7366#if (DBVER >= 46)
7367 ADD_INT(d, DB_EVENT_REP_ELECTED);
7368#endif
7369 ADD_INT(d, DB_EVENT_REP_MASTER);
7370 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
7371#if (DBVER >= 46)
7372 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
7373#endif
7374 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
7375 ADD_INT(d, DB_EVENT_WRITE_FAILED);
7376#endif
7377
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007378 ADD_INT(d, DB_REP_DUPMASTER);
7379 ADD_INT(d, DB_REP_HOLDELECTION);
7380#if (DBVER >= 44)
7381 ADD_INT(d, DB_REP_IGNORE);
7382 ADD_INT(d, DB_REP_JOIN_FAILURE);
7383#endif
7384#if (DBVER >= 42)
7385 ADD_INT(d, DB_REP_ISPERM);
7386 ADD_INT(d, DB_REP_NOTPERM);
7387#endif
7388 ADD_INT(d, DB_REP_NEWSITE);
7389
Jesus Ceaef9764f2008-05-13 18:45:46 +00007390 ADD_INT(d, DB_REP_MASTER);
7391 ADD_INT(d, DB_REP_CLIENT);
7392#if (DBVER >= 45)
7393 ADD_INT(d, DB_REP_ELECTION);
7394
7395 ADD_INT(d, DB_REP_ACK_TIMEOUT);
7396 ADD_INT(d, DB_REP_CONNECTION_RETRY);
7397 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
7398 ADD_INT(d, DB_REP_ELECTION_RETRY);
7399#endif
7400#if (DBVER >= 46)
7401 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
7402 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
7403#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00007404
7405#if (DBVER >= 45)
7406 ADD_INT(d, DB_REPMGR_PEER);
7407 ADD_INT(d, DB_REPMGR_ACKS_ALL);
7408 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
7409 ADD_INT(d, DB_REPMGR_ACKS_NONE);
7410 ADD_INT(d, DB_REPMGR_ACKS_ONE);
7411 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
7412 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
7413 ADD_INT(d, DB_REPMGR_CONNECTED);
7414 ADD_INT(d, DB_REPMGR_DISCONNECTED);
7415 ADD_INT(d, DB_STAT_CLEAR);
7416 ADD_INT(d, DB_STAT_ALL);
7417#endif
7418
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007419#if (DBVER >= 43)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007420 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00007421 ADD_INT(d, DB_SEQ_DEC);
7422 ADD_INT(d, DB_SEQ_INC);
7423 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007424#endif
7425
Jesus Ceaca3939c2008-05-22 15:27:38 +00007426#if (DBVER >= 43) && (DBVER < 47)
7427 ADD_INT(d, DB_LOG_INMEMORY);
7428 ADD_INT(d, DB_DSYNC_LOG);
7429#endif
7430
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007431#if (DBVER >= 41)
7432 ADD_INT(d, DB_ENCRYPT_AES);
7433 ADD_INT(d, DB_AUTO_COMMIT);
7434#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00007435 /* allow Berkeley DB 4.1 aware apps to run on older versions */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007436 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
7437#endif
7438
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007439 ADD_INT(d, EINVAL);
7440 ADD_INT(d, EACCES);
7441 ADD_INT(d, ENOSPC);
7442 ADD_INT(d, ENOMEM);
7443 ADD_INT(d, EAGAIN);
7444 ADD_INT(d, EBUSY);
7445 ADD_INT(d, EEXIST);
7446 ADD_INT(d, ENOENT);
7447 ADD_INT(d, EPERM);
7448
Barry Warsaw1baa9822003-03-31 19:51:29 +00007449 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
7450 ADD_INT(d, DB_SET_TXN_TIMEOUT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007451
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007452 /* The exception name must be correct for pickled exception *
7453 * objects to unpickle properly. */
7454#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
7455#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
7456#else
7457#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
7458#endif
7459
7460 /* All the rest of the exceptions derive only from DBError */
7461#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
7462 PyDict_SetItemString(d, #name, name)
7463
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007464 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007465 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
7466 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007467
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007468#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithe9477062005-06-04 06:46:59 +00007469 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
7470 * from both DBError and KeyError, since the API only supports
7471 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007472 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00007473 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
7474 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007475 Py_file_input, d, d);
7476 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00007477 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007478 PyDict_DelItemString(d, "KeyError");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007479#else
7480 /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
7481 ** derive from several classes. We use this new API only for Python 3.0,
7482 ** though.
7483 */
7484 {
7485 PyObject* bases;
7486
7487 bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
7488
7489#define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
7490 PyDict_SetItemString(d, #name, name)
7491 MAKE_EX2(DBNotFoundError);
7492 MAKE_EX2(DBKeyEmptyError);
7493
7494#undef MAKE_EX2
7495
7496 Py_XDECREF(bases);
7497 }
7498#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007499
7500
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007501#if !INCOMPLETE_IS_WARNING
7502 MAKE_EX(DBIncompleteError);
7503#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00007504 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007505 MAKE_EX(DBKeyEmptyError);
7506 MAKE_EX(DBKeyExistError);
7507 MAKE_EX(DBLockDeadlockError);
7508 MAKE_EX(DBLockNotGrantedError);
7509 MAKE_EX(DBOldVersionError);
7510 MAKE_EX(DBRunRecoveryError);
7511 MAKE_EX(DBVerifyBadError);
7512 MAKE_EX(DBNoServerError);
7513 MAKE_EX(DBNoServerHomeError);
7514 MAKE_EX(DBNoServerIDError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007515 MAKE_EX(DBPageNotFoundError);
7516 MAKE_EX(DBSecondaryBadError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007517
7518 MAKE_EX(DBInvalidArgError);
7519 MAKE_EX(DBAccessError);
7520 MAKE_EX(DBNoSpaceError);
7521 MAKE_EX(DBNoMemoryError);
7522 MAKE_EX(DBAgainError);
7523 MAKE_EX(DBBusyError);
7524 MAKE_EX(DBFileExistsError);
7525 MAKE_EX(DBNoSuchFileError);
7526 MAKE_EX(DBPermissionsError);
7527
Jesus Ceaef9764f2008-05-13 18:45:46 +00007528#if (DBVER >= 42)
7529 MAKE_EX(DBRepHandleDeadError);
7530#endif
7531
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007532 MAKE_EX(DBRepUnavailError);
7533
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007534#undef MAKE_EX
7535
Gregory P. Smith39250532007-10-09 06:02:21 +00007536 /* Initiliase the C API structure and add it to the module */
7537 bsddb_api.db_type = &DB_Type;
7538 bsddb_api.dbcursor_type = &DBCursor_Type;
7539 bsddb_api.dbenv_type = &DBEnv_Type;
7540 bsddb_api.dbtxn_type = &DBTxn_Type;
7541 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007542#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00007543 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007544#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00007545 bsddb_api.makeDBError = makeDBError;
7546
7547 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7548 PyDict_SetItemString(d, "api", py_api);
7549 Py_DECREF(py_api);
7550
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007551 /* Check for errors */
7552 if (PyErr_Occurred()) {
7553 PyErr_Print();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007554 Py_FatalError("can't initialize module _bsddb/_pybsddb");
7555 Py_DECREF(m);
7556 m = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007557 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007558#if (PY_VERSION_HEX < 0x03000000)
7559 return;
7560#else
7561 return m;
7562#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007563}
Gregory P. Smith41631e82003-09-21 00:08:14 +00007564
7565/* allow this module to be named _pybsddb so that it can be installed
7566 * and imported on top of python >= 2.3 that includes its own older
7567 * copy of the library named _bsddb without importing the old version. */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007568#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007569DL_EXPORT(void) init_pybsddb(void)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007570#else
7571PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */
7572#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00007573{
7574 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007575#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007576 init_bsddb();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007577#else
7578 return PyInit__bsddb(); /* Note the two underscores */
7579#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00007580}
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007581