blob: 9ae8e52b0613312d0ac6061f0f24009e0e9ed8e8 [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
Matthias Klose54cc5392010-03-15 12:46:18 +0000218#if (DBVER < 48)
219#define DB_GID_SIZE DB_XIDDATASIZE
220#endif
221
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000222
223/* --------------------------------------------------------------------- */
224/* Structure definitions */
225
Gregory P. Smith39250532007-10-09 06:02:21 +0000226#if PYTHON_API_VERSION < 1010
227#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000228#endif
229
Gregory P. Smith31c50652004-06-28 01:20:40 +0000230
Gregory P. Smith39250532007-10-09 06:02:21 +0000231/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000232#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000233#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000234
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000235
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000236/* See comment in Python 2.6 "object.h" */
237#ifndef staticforward
238#define staticforward static
239#endif
240#ifndef statichere
241#define statichere static
242#endif
243
244staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
245 DBLock_Type;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000246#if (DBVER >= 43)
247staticforward PyTypeObject DBSequence_Type;
248#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000249
Martin v. Löwis83c92012008-04-24 13:17:24 +0000250#ifndef Py_TYPE
Gregory P. Smithfc006692007-11-05 09:06:28 +0000251/* for compatibility with Python 2.5 and earlier */
Christian Heimese93237d2007-12-19 02:37:44 +0000252#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
Gregory P. Smithfc006692007-11-05 09:06:28 +0000253#endif
254
Christian Heimese93237d2007-12-19 02:37:44 +0000255#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
256#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
257#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
258#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
259#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000260#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +0000261#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000262#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000263
Jesus Ceaef9764f2008-05-13 18:45:46 +0000264#if (DBVER < 46)
265 #define _DBC_close(dbc) dbc->c_close(dbc)
266 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
267 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
268 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
269 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
270 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
271 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
272#else
273 #define _DBC_close(dbc) dbc->close(dbc)
274 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
275 #define _DBC_del(dbc,a) dbc->del(dbc,a)
276 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
277 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
278 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
279 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
280#endif
281
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000282
283/* --------------------------------------------------------------------- */
284/* Utility macros and functions */
285
Jesus Ceaef9764f2008-05-13 18:45:46 +0000286#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
287 { \
288 object->sibling_next=backlink; \
289 object->sibling_prev_p=&(backlink); \
290 backlink=object; \
291 if (object->sibling_next) { \
292 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
293 } \
294 }
295
296#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
297 { \
298 if (object->sibling_next) { \
299 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
300 } \
301 *(object->sibling_prev_p)=object->sibling_next; \
302 }
303
304#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
305 { \
306 if (object->sibling_next) { \
307 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
308 } \
309 if (object->sibling_prev_p) { \
310 *(object->sibling_prev_p)=object->sibling_next; \
311 } \
312 }
313
314#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
315 { \
316 object->sibling_next_txn=backlink; \
317 object->sibling_prev_p_txn=&(backlink); \
318 backlink=object; \
319 if (object->sibling_next_txn) { \
320 object->sibling_next_txn->sibling_prev_p_txn= \
321 &(object->sibling_next_txn); \
322 } \
323 }
324
325#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
326 { \
327 if (object->sibling_next_txn) { \
328 object->sibling_next_txn->sibling_prev_p_txn= \
329 object->sibling_prev_p_txn; \
330 } \
331 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
332 }
333
334
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000335#define RETURN_IF_ERR() \
336 if (makeDBError(err)) { \
337 return NULL; \
338 }
339
340#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
341
Gregory P. Smithe2767172003-11-02 08:06:29 +0000342#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
343 if ((nonNull) == NULL) { \
344 PyObject *errTuple = NULL; \
345 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000346 if (errTuple) { \
347 PyErr_SetObject((pyErrObj), errTuple); \
348 Py_DECREF(errTuple); \
349 } \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000350 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000351 }
352
Gregory P. Smithe2767172003-11-02 08:06:29 +0000353#define CHECK_DB_NOT_CLOSED(dbobj) \
354 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
355
356#define CHECK_ENV_NOT_CLOSED(env) \
357 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000358
359#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000360 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000361
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000362#if (DBVER >= 43)
363#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
364 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
365#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000366
367#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
368 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
369
370#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
371
372#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000373 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000374
375
376static int makeDBError(int err);
377
378
379/* Return the access method type of the DBObject */
380static int _DB_get_type(DBObject* self)
381{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000382 DBTYPE type;
383 int err;
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000384
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000385 err = self->db->get_type(self->db, &type);
386 if (makeDBError(err)) {
387 return -1;
388 }
389 return type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000390}
391
392
393/* Create a DBT structure (containing key and data values) from Python
394 strings. Returns 1 on success, 0 on an error. */
395static int make_dbt(PyObject* obj, DBT* dbt)
396{
397 CLEAR_DBT(*dbt);
398 if (obj == Py_None) {
399 /* no need to do anything, the structure has already been zeroed */
400 }
401 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
402 PyErr_SetString(PyExc_TypeError,
Jesus Cea4907d272008-08-31 14:00:51 +0000403#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000404 "Data values must be of type string or None.");
Jesus Cea4907d272008-08-31 14:00:51 +0000405#else
406 "Data values must be of type bytes or None.");
407#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000408 return 0;
409 }
410 return 1;
411}
412
413
414/* Recno and Queue DBs can have integer keys. This function figures out
415 what's been given, verifies that it's allowed, and then makes the DBT.
416
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000417 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000418static int
419make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000420{
421 db_recno_t recno;
422 int type;
423
424 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000425 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000426 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000427 if (type == -1)
428 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000429 if (type == DB_RECNO || type == DB_QUEUE) {
430 PyErr_SetString(
431 PyExc_TypeError,
432 "None keys not allowed for Recno and Queue DB's");
433 return 0;
434 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000435 /* no need to do anything, the structure has already been zeroed */
436 }
437
Christian Heimes593daf52008-05-26 12:51:38 +0000438 else if (PyBytes_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000439 /* verify access method type */
440 type = _DB_get_type(self);
441 if (type == -1)
442 return 0;
443 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000444 PyErr_SetString(
445 PyExc_TypeError,
Jesus Cea4907d272008-08-31 14:00:51 +0000446#if (PY_VERSION_HEX < 0x03000000)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000447 "String keys not allowed for Recno and Queue DB's");
Jesus Cea4907d272008-08-31 14:00:51 +0000448#else
449 "Bytes keys not allowed for Recno and Queue DB's");
450#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000451 return 0;
452 }
453
Gregory P. Smith10bed542007-10-09 06:50:43 +0000454 /*
455 * NOTE(gps): I don't like doing a data copy here, it seems
456 * wasteful. But without a clean way to tell FREE_DBT if it
457 * should free key->data or not we have to. Other places in
458 * the code check for DB_THREAD and forceably set DBT_MALLOC
459 * when we otherwise would leave flags 0 to indicate that.
460 */
Christian Heimes593daf52008-05-26 12:51:38 +0000461 key->data = malloc(PyBytes_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000462 if (key->data == NULL) {
463 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
464 return 0;
465 }
Christian Heimes593daf52008-05-26 12:51:38 +0000466 memcpy(key->data, PyBytes_AS_STRING(keyobj),
467 PyBytes_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000468 key->flags = DB_DBT_REALLOC;
Christian Heimes593daf52008-05-26 12:51:38 +0000469 key->size = PyBytes_GET_SIZE(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000470 }
471
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000472 else if (NUMBER_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000473 /* verify access method type */
474 type = _DB_get_type(self);
475 if (type == -1)
476 return 0;
477 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000478 /* if BTREE then an Integer key is allowed with the
479 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000480 *pflags |= DB_SET_RECNO;
481 }
482 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000483 PyErr_SetString(
484 PyExc_TypeError,
485 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000486 return 0;
487 }
488
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000489 /* Make a key out of the requested recno, use allocated space so DB
490 * will be able to realloc room for the real key if needed. */
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000491 recno = NUMBER_AsLong(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000492 key->data = malloc(sizeof(db_recno_t));
493 if (key->data == NULL) {
494 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
495 return 0;
496 }
497 key->ulen = key->size = sizeof(db_recno_t);
498 memcpy(key->data, &recno, sizeof(db_recno_t));
499 key->flags = DB_DBT_REALLOC;
500 }
501 else {
502 PyErr_Format(PyExc_TypeError,
Jesus Cea4907d272008-08-31 14:00:51 +0000503#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000504 "String or Integer object expected for key, %s found",
Jesus Cea4907d272008-08-31 14:00:51 +0000505#else
506 "Bytes or Integer object expected for key, %s found",
507#endif
Christian Heimese93237d2007-12-19 02:37:44 +0000508 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000509 return 0;
510 }
511
512 return 1;
513}
514
515
516/* Add partial record access to an existing DBT data struct.
517 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
518 and the data storage/retrieval will be done using dlen and doff. */
519static int add_partial_dbt(DBT* d, int dlen, int doff) {
520 /* if neither were set we do nothing (-1 is the default value) */
521 if ((dlen == -1) && (doff == -1)) {
522 return 1;
523 }
524
525 if ((dlen < 0) || (doff < 0)) {
526 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
527 return 0;
528 }
529
530 d->flags = d->flags | DB_DBT_PARTIAL;
531 d->dlen = (unsigned int) dlen;
532 d->doff = (unsigned int) doff;
533 return 1;
534}
535
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000536/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
537/* TODO: make this use the native libc strlcpy() when available (BSD) */
538unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
539{
540 unsigned int srclen, copylen;
541
542 srclen = strlen(src);
543 if (n <= 0)
544 return srclen;
545 copylen = (srclen > n-1) ? n-1 : srclen;
546 /* populate dest[0] thru dest[copylen-1] */
547 memcpy(dest, src, copylen);
548 /* guarantee null termination */
549 dest[copylen] = 0;
550
551 return srclen;
552}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000553
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000554/* Callback used to save away more information about errors from the DB
555 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000556static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000557#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000558static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000559#else
560static void _db_errorCallback(const DB_ENV *db_env,
561 const char* prefix, const char* msg)
562#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000563{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000564 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000565}
566
567
Jesus Ceaef9764f2008-05-13 18:45:46 +0000568/*
569** We need these functions because some results
570** are undefined if pointer is NULL. Some other
571** give None instead of "".
572**
573** This functions are static and will be
574** -I hope- inlined.
575*/
576static const char *DummyString = "This string is a simple placeholder";
577static PyObject *Build_PyString(const char *p,int s)
578{
579 if (!p) {
580 p=DummyString;
581 assert(s==0);
582 }
Christian Heimes593daf52008-05-26 12:51:38 +0000583 return PyBytes_FromStringAndSize(p,s);
Jesus Ceaef9764f2008-05-13 18:45:46 +0000584}
585
586static PyObject *BuildValue_S(const void *p,int s)
587{
588 if (!p) {
589 p=DummyString;
590 assert(s==0);
591 }
Jesus Cea4907d272008-08-31 14:00:51 +0000592 return PyBytes_FromStringAndSize(p, s);
Jesus Ceaef9764f2008-05-13 18:45:46 +0000593}
594
595static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
596{
Jesus Cea4907d272008-08-31 14:00:51 +0000597PyObject *a, *b, *r;
598
Jesus Ceaef9764f2008-05-13 18:45:46 +0000599 if (!p1) {
600 p1=DummyString;
601 assert(s1==0);
602 }
603 if (!p2) {
604 p2=DummyString;
605 assert(s2==0);
606 }
Jesus Cea4907d272008-08-31 14:00:51 +0000607
608 if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
609 return NULL;
610 }
611 if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
612 Py_DECREF(a);
613 return NULL;
614 }
615
616#if (PY_VERSION_HEX >= 0x02040000)
617 r = PyTuple_Pack(2, a, b) ;
618#else
619 r = Py_BuildValue("OO", a, b);
620#endif
621 Py_DECREF(a);
622 Py_DECREF(b);
623 return r;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000624}
625
626static PyObject *BuildValue_IS(int i,const void *p,int s)
627{
Jesus Cea4907d272008-08-31 14:00:51 +0000628 PyObject *a, *r;
629
Jesus Ceaef9764f2008-05-13 18:45:46 +0000630 if (!p) {
631 p=DummyString;
632 assert(s==0);
633 }
Jesus Cea4907d272008-08-31 14:00:51 +0000634
635 if (!(a = PyBytes_FromStringAndSize(p, s))) {
636 return NULL;
637 }
638
639 r = Py_BuildValue("iO", i, a);
640 Py_DECREF(a);
641 return r;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000642}
643
Jesus Cea4907d272008-08-31 14:00:51 +0000644static PyObject *BuildValue_LS(long l,const void *p,int s)
Jesus Ceaef9764f2008-05-13 18:45:46 +0000645{
Jesus Cea4907d272008-08-31 14:00:51 +0000646 PyObject *a, *r;
647
Jesus Ceaef9764f2008-05-13 18:45:46 +0000648 if (!p) {
649 p=DummyString;
650 assert(s==0);
651 }
Jesus Cea4907d272008-08-31 14:00:51 +0000652
653 if (!(a = PyBytes_FromStringAndSize(p, s))) {
654 return NULL;
655 }
656
657 r = Py_BuildValue("lO", l, a);
658 Py_DECREF(a);
659 return r;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000660}
661
662
663
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000664/* make a nice exception object to raise for errors. */
665static int makeDBError(int err)
666{
667 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000668 PyObject *errObj = NULL;
669 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000670 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000671 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000672
673 switch (err) {
674 case 0: /* successful, no error */ break;
675
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000676#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000677 case DB_INCOMPLETE:
678#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000679 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
680 /* Ensure that bytes_left never goes negative */
681 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
682 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
683 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000684 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000685 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000686 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000687 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000688 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000689
690#else /* do an exception instead */
691 errObj = DBIncompleteError;
692#endif
693 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000694#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000695
696 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
697 case DB_KEYEXIST: errObj = DBKeyExistError; break;
698 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
699 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
700 case DB_NOTFOUND: errObj = DBNotFoundError; break;
701 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
702 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
703 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
704 case DB_NOSERVER: errObj = DBNoServerError; break;
705 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
706 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000707 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
708 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000709 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000710
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000711#if (DBVER >= 43)
712 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
713 case ENOMEM: errObj = PyExc_MemoryError; break;
714#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000715 case EINVAL: errObj = DBInvalidArgError; break;
716 case EACCES: errObj = DBAccessError; break;
717 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000718 case EAGAIN: errObj = DBAgainError; break;
719 case EBUSY : errObj = DBBusyError; break;
720 case EEXIST: errObj = DBFileExistsError; break;
721 case ENOENT: errObj = DBNoSuchFileError; break;
722 case EPERM : errObj = DBPermissionsError; break;
723
Jesus Ceaef9764f2008-05-13 18:45:46 +0000724#if (DBVER >= 42)
725 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
726#endif
727
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000728 case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
729
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000730 default: errObj = DBError; break;
731 }
732
733 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000734 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
735 /* Ensure that bytes_left never goes negative */
736 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
737 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
738 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000739 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000740 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000741 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000742 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000743
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000744 errTuple = Py_BuildValue("(is)", err, errTxt);
745 if (errTuple == NULL) {
746 Py_DECREF(errObj);
747 return !0;
748 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000749 PyErr_SetObject(errObj, errTuple);
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000750 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000751 }
752
753 return ((errObj != NULL) || exceptionRaised);
754}
755
756
757
758/* set a type exception */
759static void makeTypeError(char* expected, PyObject* found)
760{
761 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimese93237d2007-12-19 02:37:44 +0000762 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000763}
764
765
766/* verify that an obj is either None or a DBTxn, and set the txn pointer */
767static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
768{
769 if (txnobj == Py_None || txnobj == NULL) {
770 *txn = NULL;
771 return 1;
772 }
773 if (DBTxnObject_Check(txnobj)) {
774 *txn = ((DBTxnObject*)txnobj)->txn;
775 return 1;
776 }
777 else
778 makeTypeError("DBTxn", txnobj);
779 return 0;
780}
781
782
783/* Delete a key from a database
784 Returns 0 on success, -1 on an error. */
785static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
786{
787 int err;
788
789 MYDB_BEGIN_ALLOW_THREADS;
790 err = self->db->del(self->db, txn, key, 0);
791 MYDB_END_ALLOW_THREADS;
792 if (makeDBError(err)) {
793 return -1;
794 }
795 self->haveStat = 0;
796 return 0;
797}
798
799
800/* Store a key into a database
801 Returns 0 on success, -1 on an error. */
802static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
803{
804 int err;
805
806 MYDB_BEGIN_ALLOW_THREADS;
807 err = self->db->put(self->db, txn, key, data, flags);
808 MYDB_END_ALLOW_THREADS;
809 if (makeDBError(err)) {
810 return -1;
811 }
812 self->haveStat = 0;
813 return 0;
814}
815
816/* Get a key/data pair from a cursor */
817static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
818 PyObject *args, PyObject *kwargs, char *format)
819{
820 int err;
821 PyObject* retval = NULL;
822 DBT key, data;
823 int dlen = -1;
824 int doff = -1;
825 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000826 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000827
828 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
829 &flags, &dlen, &doff))
830 return NULL;
831
832 CHECK_CURSOR_NOT_CLOSED(self);
833
834 flags |= extra_flags;
835 CLEAR_DBT(key);
836 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000837 if (!add_partial_dbt(&data, dlen, doff))
838 return NULL;
839
840 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000841 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000842 MYDB_END_ALLOW_THREADS;
843
Gregory P. Smithe9477062005-06-04 06:46:59 +0000844 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
845 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000846 Py_INCREF(Py_None);
847 retval = Py_None;
848 }
849 else if (makeDBError(err)) {
850 retval = NULL;
851 }
852 else { /* otherwise, success! */
853
854 /* if Recno or Queue, return the key as an Int */
855 switch (_DB_get_type(self->mydb)) {
856 case -1:
857 retval = NULL;
858 break;
859
860 case DB_RECNO:
861 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000862 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000863 break;
864 case DB_HASH:
865 case DB_BTREE:
866 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000867 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000868 break;
869 }
870 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000871 return retval;
872}
873
874
875/* add an integer to a dictionary using the given name as a key */
876static void _addIntToDict(PyObject* dict, char *name, int value)
877{
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000878 PyObject* v = NUMBER_FromLong((long) value);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000879 if (!v || PyDict_SetItemString(dict, name, v))
880 PyErr_Clear();
881
882 Py_XDECREF(v);
883}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000884
885/* The same, when the value is a time_t */
886static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
887{
888 PyObject* v;
889 /* if the value fits in regular int, use that. */
Jesus Ceaef9764f2008-05-13 18:45:46 +0000890#ifdef PY_LONG_LONG
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000891 if (sizeof(time_t) > sizeof(long))
892 v = PyLong_FromLongLong((PY_LONG_LONG) value);
893 else
894#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000895 v = NUMBER_FromLong((long) value);
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000896 if (!v || PyDict_SetItemString(dict, name, v))
897 PyErr_Clear();
898
899 Py_XDECREF(v);
900}
901
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000902#if (DBVER >= 43)
903/* add an db_seq_t to a dictionary using the given name as a key */
904static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
905{
906 PyObject* v = PyLong_FromLongLong(value);
907 if (!v || PyDict_SetItemString(dict, name, v))
908 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000909
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000910 Py_XDECREF(v);
911}
912#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000913
Jesus Ceaef9764f2008-05-13 18:45:46 +0000914static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
915{
916 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
917 if (!v || PyDict_SetItemString(dict, name, v))
918 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000919
Jesus Ceaef9764f2008-05-13 18:45:46 +0000920 Py_XDECREF(v);
921}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000922
923/* --------------------------------------------------------------------- */
924/* Allocators and deallocators */
925
926static DBObject*
927newDBObject(DBEnvObject* arg, int flags)
928{
929 DBObject* self;
930 DB_ENV* db_env = NULL;
931 int err;
932
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000933 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000934 if (self == NULL)
935 return NULL;
936
937 self->haveStat = 0;
938 self->flags = 0;
939 self->setflags = 0;
940 self->myenvobj = NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000941 self->db = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000942 self->children_cursors = NULL;
943#if (DBVER >=43)
944 self->children_sequences = NULL;
945#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000946 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000947 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000948 self->primaryDBType = 0;
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000949 Py_INCREF(Py_None);
Jesus Cea4907d272008-08-31 14:00:51 +0000950 self->private_obj = Py_None;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000951 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000952
953 /* keep a reference to our python DBEnv object */
954 if (arg) {
955 Py_INCREF(arg);
956 self->myenvobj = arg;
957 db_env = arg->db_env;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000958 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
959 } else {
960 self->sibling_prev_p=NULL;
961 self->sibling_next=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000962 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000963 self->txn=NULL;
964 self->sibling_prev_p_txn=NULL;
965 self->sibling_next_txn=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000966
967 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000968 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000969 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000970 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
971 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000972
973 MYDB_BEGIN_ALLOW_THREADS;
974 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000975 if (self->db != NULL) {
976 self->db->set_errcall(self->db, _db_errorCallback);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000977 self->db->app_private = (void*)self;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000978 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000979 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000980 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
981 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000982 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000983 if (makeDBError(err)) {
984 if (self->myenvobj) {
985 Py_DECREF(self->myenvobj);
986 self->myenvobj = NULL;
987 }
Gregory P. Smith664782e2008-05-17 06:12:02 +0000988 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000989 self = NULL;
990 }
991 return self;
992}
993
994
Jesus Ceaef9764f2008-05-13 18:45:46 +0000995/* Forward declaration */
Jesus Cea5cd5f122008-09-23 18:54:08 +0000996static PyObject *DB_close_internal(DBObject* self, int flags, int do_not_close);
Jesus Ceaef9764f2008-05-13 18:45:46 +0000997
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000998static void
999DB_dealloc(DBObject* self)
1000{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001001 PyObject *dummy;
1002
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001003 if (self->db != NULL) {
Jesus Cea5cd5f122008-09-23 18:54:08 +00001004 dummy=DB_close_internal(self, 0, 0);
1005 /*
1006 ** Raising exceptions while doing
1007 ** garbage collection is a fatal error.
1008 */
1009 if (dummy)
1010 Py_DECREF(dummy);
1011 else
1012 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001013 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001014 if (self->in_weakreflist != NULL) {
1015 PyObject_ClearWeakRefs((PyObject *) self);
1016 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001017 if (self->myenvobj) {
1018 Py_DECREF(self->myenvobj);
1019 self->myenvobj = NULL;
1020 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001021 if (self->associateCallback != NULL) {
1022 Py_DECREF(self->associateCallback);
1023 self->associateCallback = NULL;
1024 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001025 if (self->btCompareCallback != NULL) {
1026 Py_DECREF(self->btCompareCallback);
1027 self->btCompareCallback = NULL;
1028 }
Jesus Cea4907d272008-08-31 14:00:51 +00001029 Py_DECREF(self->private_obj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001030 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001031}
1032
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001033static DBCursorObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001034newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001035{
Neal Norwitzb4a55812004-07-09 23:30:57 +00001036 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001037 if (self == NULL)
1038 return NULL;
1039
1040 self->dbc = dbc;
1041 self->mydb = db;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001042
1043 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
1044 if (txn && ((PyObject *)txn!=Py_None)) {
1045 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
1046 self->txn=txn;
1047 } else {
1048 self->txn=NULL;
1049 }
1050
Gregory P. Smitha703a212003-11-03 01:04:41 +00001051 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001052 Py_INCREF(self->mydb);
1053 return self;
1054}
1055
1056
Jesus Ceaef9764f2008-05-13 18:45:46 +00001057/* Forward declaration */
1058static PyObject *DBC_close_internal(DBCursorObject* self);
1059
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001060static void
1061DBCursor_dealloc(DBCursorObject* self)
1062{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001063 PyObject *dummy;
Gregory P. Smitha703a212003-11-03 01:04:41 +00001064
Jesus Ceaef9764f2008-05-13 18:45:46 +00001065 if (self->dbc != NULL) {
Jesus Cea5cd5f122008-09-23 18:54:08 +00001066 dummy=DBC_close_internal(self);
1067 /*
1068 ** Raising exceptions while doing
1069 ** garbage collection is a fatal error.
1070 */
1071 if (dummy)
1072 Py_DECREF(dummy);
1073 else
1074 PyErr_Clear();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001075 }
Gregory P. Smitha703a212003-11-03 01:04:41 +00001076 if (self->in_weakreflist != NULL) {
1077 PyObject_ClearWeakRefs((PyObject *) self);
1078 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001079 Py_DECREF(self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001080 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001081}
1082
1083
1084static DBEnvObject*
1085newDBEnvObject(int flags)
1086{
1087 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001088 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001089 if (self == NULL)
1090 return NULL;
1091
Jesus Cea5cd5f122008-09-23 18:54:08 +00001092 self->db_env = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001093 self->closed = 1;
1094 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001095 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1096 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001097 self->children_dbs = NULL;
1098 self->children_txns = NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001099 Py_INCREF(Py_None);
Jesus Cea4907d272008-08-31 14:00:51 +00001100 self->private_obj = Py_None;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001101 Py_INCREF(Py_None);
1102 self->rep_transport = Py_None;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001103 self->in_weakreflist = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001104 self->event_notifyCallback = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001105
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001106 MYDB_BEGIN_ALLOW_THREADS;
1107 err = db_env_create(&self->db_env, flags);
1108 MYDB_END_ALLOW_THREADS;
1109 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001110 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001111 self = NULL;
1112 }
1113 else {
1114 self->db_env->set_errcall(self->db_env, _db_errorCallback);
Jesus Cea4907d272008-08-31 14:00:51 +00001115 self->db_env->app_private = self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001116 }
1117 return self;
1118}
1119
Jesus Ceaef9764f2008-05-13 18:45:46 +00001120/* Forward declaration */
1121static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001122
1123static void
1124DBEnv_dealloc(DBEnvObject* self)
1125{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001126 PyObject *dummy;
1127
Jesus Ceaac25fab2008-09-03 17:50:32 +00001128 if (self->db_env) {
Jesus Cea5cd5f122008-09-23 18:54:08 +00001129 dummy=DBEnv_close_internal(self, 0);
1130 /*
1131 ** Raising exceptions while doing
1132 ** garbage collection is a fatal error.
1133 */
1134 if (dummy)
1135 Py_DECREF(dummy);
1136 else
1137 PyErr_Clear();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001138 }
1139
Jesus Ceaef9764f2008-05-13 18:45:46 +00001140 Py_XDECREF(self->event_notifyCallback);
1141 self->event_notifyCallback = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001142
Gregory P. Smith31c50652004-06-28 01:20:40 +00001143 if (self->in_weakreflist != NULL) {
1144 PyObject_ClearWeakRefs((PyObject *) self);
1145 }
Jesus Cea4907d272008-08-31 14:00:51 +00001146 Py_DECREF(self->private_obj);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001147 Py_DECREF(self->rep_transport);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001148 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001149}
1150
1151
1152static DBTxnObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001153newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001154{
1155 int err;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001156 DB_TXN *parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001157
Neal Norwitzb4a55812004-07-09 23:30:57 +00001158 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001159 if (self == NULL)
1160 return NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001161
Gregory P. Smith31c50652004-06-28 01:20:40 +00001162 self->in_weakreflist = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001163 self->children_txns = NULL;
1164 self->children_dbs = NULL;
1165 self->children_cursors = NULL;
1166 self->children_sequences = NULL;
1167 self->flag_prepare = 0;
1168 self->parent_txn = NULL;
1169 self->env = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001170
Jesus Ceaef9764f2008-05-13 18:45:46 +00001171 if (parent && ((PyObject *)parent!=Py_None)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001172 parent_txn = parent->txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001173 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001174
1175 if (txn) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001176 self->txn = txn;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001177 } else {
1178 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001179 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001180 MYDB_END_ALLOW_THREADS;
1181
1182 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001183 Py_DECREF(self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001184 return NULL;
1185 }
1186 }
1187
Gregory P. Smith664782e2008-05-17 06:12:02 +00001188 /* Can't use 'parent' because could be 'parent==Py_None' */
1189 if (parent_txn) {
1190 self->parent_txn = parent;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001191 Py_INCREF(parent);
1192 self->env = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001193 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001194 } else {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001195 self->parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001196 Py_INCREF(myenv);
1197 self->env = myenv;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001198 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001199 }
1200
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001201 return self;
1202}
1203
Jesus Ceaef9764f2008-05-13 18:45:46 +00001204/* Forward declaration */
1205static PyObject *
1206DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001207
1208static void
1209DBTxn_dealloc(DBTxnObject* self)
1210{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001211 PyObject *dummy;
1212
1213 if (self->txn) {
1214 int flag_prepare = self->flag_prepare;
Jesus Cea5cd5f122008-09-23 18:54:08 +00001215
Jesus Ceaef9764f2008-05-13 18:45:46 +00001216 dummy=DBTxn_abort_discard_internal(self,0);
Jesus Cea5cd5f122008-09-23 18:54:08 +00001217 /*
1218 ** Raising exceptions while doing
1219 ** garbage collection is a fatal error.
1220 */
1221 if (dummy)
1222 Py_DECREF(dummy);
1223 else
1224 PyErr_Clear();
1225
Jesus Ceaef9764f2008-05-13 18:45:46 +00001226 if (!flag_prepare) {
1227 PyErr_Warn(PyExc_RuntimeWarning,
1228 "DBTxn aborted in destructor. No prior commit() or abort().");
1229 }
1230 }
1231
Gregory P. Smith31c50652004-06-28 01:20:40 +00001232 if (self->in_weakreflist != NULL) {
1233 PyObject_ClearWeakRefs((PyObject *) self);
1234 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001235
Jesus Ceaef9764f2008-05-13 18:45:46 +00001236 if (self->env) {
1237 Py_DECREF(self->env);
1238 } else {
1239 Py_DECREF(self->parent_txn);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001240 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001241 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242}
1243
1244
1245static DBLockObject*
1246newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1247 db_lockmode_t lock_mode, int flags)
1248{
1249 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001250 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001251 if (self == NULL)
1252 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001253 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001254
1255 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001256 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1257 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001258 MYDB_END_ALLOW_THREADS;
1259 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001260 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001261 self = NULL;
1262 }
1263
1264 return self;
1265}
1266
1267
1268static void
1269DBLock_dealloc(DBLockObject* self)
1270{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001271 if (self->in_weakreflist != NULL) {
1272 PyObject_ClearWeakRefs((PyObject *) self);
1273 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001274 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001275
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001276 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001277}
1278
1279
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001280#if (DBVER >= 43)
1281static DBSequenceObject*
1282newDBSequenceObject(DBObject* mydb, int flags)
1283{
1284 int err;
1285 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1286 if (self == NULL)
1287 return NULL;
1288 Py_INCREF(mydb);
1289 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001290
Jesus Ceaef9764f2008-05-13 18:45:46 +00001291 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
Gregory P. Smith664782e2008-05-17 06:12:02 +00001292 self->txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001293
1294 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001295
1296 MYDB_BEGIN_ALLOW_THREADS;
1297 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1298 MYDB_END_ALLOW_THREADS;
1299 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001300 Py_DECREF(self);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001301 self = NULL;
1302 }
1303
1304 return self;
1305}
1306
Jesus Ceaef9764f2008-05-13 18:45:46 +00001307/* Forward declaration */
1308static PyObject
1309*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001310
1311static void
1312DBSequence_dealloc(DBSequenceObject* self)
1313{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001314 PyObject *dummy;
1315
1316 if (self->sequence != NULL) {
1317 dummy=DBSequence_close_internal(self,0,0);
Jesus Cea5cd5f122008-09-23 18:54:08 +00001318 /*
1319 ** Raising exceptions while doing
1320 ** garbage collection is a fatal error.
1321 */
1322 if (dummy)
1323 Py_DECREF(dummy);
1324 else
1325 PyErr_Clear();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001326 }
1327
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001328 if (self->in_weakreflist != NULL) {
1329 PyObject_ClearWeakRefs((PyObject *) self);
1330 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001331
1332 Py_DECREF(self->mydb);
1333 PyObject_Del(self);
1334}
1335#endif
1336
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001337/* --------------------------------------------------------------------- */
1338/* DB methods */
1339
1340static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00001341DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001342{
1343 PyObject* txnobj = NULL;
1344 PyObject* dataobj;
1345 db_recno_t recno;
1346 DBT key, data;
1347 DB_TXN *txn = NULL;
Jesus Cea4907d272008-08-31 14:00:51 +00001348 static char* kwnames[] = { "data", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001349
Jesus Cea4907d272008-08-31 14:00:51 +00001350 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
1351 &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001352 return NULL;
1353
1354 CHECK_DB_NOT_CLOSED(self);
1355
1356 /* make a dummy key out of a recno */
1357 recno = 0;
1358 CLEAR_DBT(key);
1359 key.data = &recno;
1360 key.size = sizeof(recno);
1361 key.ulen = key.size;
1362 key.flags = DB_DBT_USERMEM;
1363
1364 if (!make_dbt(dataobj, &data)) return NULL;
1365 if (!checkTxnObj(txnobj, &txn)) return NULL;
1366
1367 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1368 return NULL;
1369
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001370 return NUMBER_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001371}
1372
1373
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001374static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001375_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1376 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001377{
1378 int retval = DB_DONOTINDEX;
1379 DBObject* secondaryDB = (DBObject*)db->app_private;
1380 PyObject* callback = secondaryDB->associateCallback;
1381 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001382 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001383 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001384
1385
1386 if (callback != NULL) {
1387 MYDB_BEGIN_BLOCK_THREADS;
1388
Thomas Woutersb3153832006-03-08 01:47:19 +00001389 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceaef9764f2008-05-13 18:45:46 +00001390 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
Thomas Woutersb3153832006-03-08 01:47:19 +00001391 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001392 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001393 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001394 result = PyEval_CallObject(callback, args);
1395 }
1396 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001397 PyErr_Print();
1398 }
1399 else if (result == Py_None) {
1400 retval = DB_DONOTINDEX;
1401 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001402 else if (NUMBER_Check(result)) {
1403 retval = NUMBER_AsLong(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001404 }
Christian Heimes593daf52008-05-26 12:51:38 +00001405 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001406 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001407 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001408
1409 CLEAR_DBT(*secKey);
Christian Heimes593daf52008-05-26 12:51:38 +00001410 PyBytes_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001411 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1412 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001413 if (secKey->data) {
1414 memcpy(secKey->data, data, size);
1415 secKey->size = size;
1416 retval = 0;
1417 }
1418 else {
1419 PyErr_SetString(PyExc_MemoryError,
1420 "malloc failed in _db_associateCallback");
1421 PyErr_Print();
1422 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001423 }
1424 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001425 PyErr_SetString(
1426 PyExc_TypeError,
1427 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001428 PyErr_Print();
1429 }
1430
Thomas Woutersb3153832006-03-08 01:47:19 +00001431 Py_XDECREF(args);
1432 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001433
1434 MYDB_END_BLOCK_THREADS;
1435 }
1436 return retval;
1437}
1438
1439
1440static PyObject*
1441DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1442{
1443 int err, flags=0;
1444 DBObject* secondaryDB;
1445 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001446#if (DBVER >= 41)
1447 PyObject *txnobj = NULL;
1448 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001449 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001450 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001451#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001452 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001453#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001454
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001455#if (DBVER >= 41)
1456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1457 &secondaryDB, &callback, &flags,
1458 &txnobj)) {
1459#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001460 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001461 &secondaryDB, &callback, &flags)) {
1462#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001463 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001464 }
1465
1466#if (DBVER >= 41)
1467 if (!checkTxnObj(txnobj, &txn)) return NULL;
1468#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001469
1470 CHECK_DB_NOT_CLOSED(self);
1471 if (!DBObject_Check(secondaryDB)) {
1472 makeTypeError("DB", (PyObject*)secondaryDB);
1473 return NULL;
1474 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001475 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001476 if (callback == Py_None) {
1477 callback = NULL;
1478 }
1479 else if (!PyCallable_Check(callback)) {
1480 makeTypeError("Callable", callback);
1481 return NULL;
1482 }
1483
1484 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001485 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001486 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001487 secondaryDB->associateCallback = callback;
1488 secondaryDB->primaryDBType = _DB_get_type(self);
1489
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001490 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1491 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1492 * The global interepreter lock is not initialized until the first
1493 * thread is created using thread.start_new_thread() or fork() is
1494 * called. that would cause the ALLOW_THREADS here to segfault due
1495 * to a null pointer reference if no threads or child processes
1496 * have been created. This works around that and is a no-op if
1497 * threads have already been initialized.
1498 * (see pybsddb-users mailing list post on 2002-08-07)
1499 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001500#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001501 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001502#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001503 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001504#if (DBVER >= 41)
1505 err = self->db->associate(self->db,
1506 txn,
1507 secondaryDB->db,
1508 _db_associateCallback,
1509 flags);
1510#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001511 err = self->db->associate(self->db,
1512 secondaryDB->db,
1513 _db_associateCallback,
1514 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001515#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001516 MYDB_END_ALLOW_THREADS;
1517
1518 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001519 Py_XDECREF(secondaryDB->associateCallback);
1520 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001521 secondaryDB->primaryDBType = 0;
1522 }
1523
1524 RETURN_IF_ERR();
1525 RETURN_NONE();
1526}
1527
1528
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001529static PyObject*
Jesus Cea5cd5f122008-09-23 18:54:08 +00001530DB_close_internal(DBObject* self, int flags, int do_not_close)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001531{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001532 PyObject *dummy;
Jesus Cea5cd5f122008-09-23 18:54:08 +00001533 int err = 0;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001534
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001535 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001536 /* Can be NULL if db is not in an environment */
1537 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
Jesus Cea4907d272008-08-31 14:00:51 +00001538
Jesus Ceaef9764f2008-05-13 18:45:46 +00001539 if (self->txn) {
1540 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1541 self->txn=NULL;
1542 }
1543
1544 while(self->children_cursors) {
1545 dummy=DBC_close_internal(self->children_cursors);
1546 Py_XDECREF(dummy);
1547 }
1548
1549#if (DBVER >= 43)
1550 while(self->children_sequences) {
1551 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1552 Py_XDECREF(dummy);
1553 }
1554#endif
1555
Jesus Cea5cd5f122008-09-23 18:54:08 +00001556 /*
1557 ** "do_not_close" is used to dispose all related objects in the
1558 ** tree, without actually releasing the "root" object.
1559 ** This is done, for example, because function calls like
1560 ** "DB.verify()" implicitly close the underlying handle. So
1561 ** the handle doesn't need to be closed, but related objects
1562 ** must be cleaned up.
1563 */
1564 if (!do_not_close) {
1565 MYDB_BEGIN_ALLOW_THREADS;
1566 err = self->db->close(self->db, flags);
1567 MYDB_END_ALLOW_THREADS;
1568 self->db = NULL;
1569 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001570 RETURN_IF_ERR();
1571 }
1572 RETURN_NONE();
1573}
1574
Jesus Ceaef9764f2008-05-13 18:45:46 +00001575static PyObject*
1576DB_close(DBObject* self, PyObject* args)
1577{
1578 int flags=0;
1579 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1580 return NULL;
Jesus Cea5cd5f122008-09-23 18:54:08 +00001581 return DB_close_internal(self, flags, 0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001582}
1583
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001584
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001585static PyObject*
1586_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1587{
1588 int err, flags=0, type;
1589 PyObject* txnobj = NULL;
1590 PyObject* retval = NULL;
1591 DBT key, data;
1592 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001593 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001594
1595 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1596 &txnobj, &flags))
1597 return NULL;
1598
1599 CHECK_DB_NOT_CLOSED(self);
1600 type = _DB_get_type(self);
1601 if (type == -1)
1602 return NULL;
1603 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001604 PyErr_SetString(PyExc_TypeError,
1605 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001606 return NULL;
1607 }
1608 if (!checkTxnObj(txnobj, &txn))
1609 return NULL;
1610
1611 CLEAR_DBT(key);
1612 CLEAR_DBT(data);
1613 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001614 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001615 data.flags = DB_DBT_MALLOC;
1616 key.flags = DB_DBT_MALLOC;
1617 }
1618
1619 MYDB_BEGIN_ALLOW_THREADS;
1620 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1621 MYDB_END_ALLOW_THREADS;
1622
Gregory P. Smithe9477062005-06-04 06:46:59 +00001623 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1624 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001625 err = 0;
1626 Py_INCREF(Py_None);
1627 retval = Py_None;
1628 }
1629 else if (!err) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001630 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001631 FREE_DBT(key);
1632 FREE_DBT(data);
1633 }
1634
1635 RETURN_IF_ERR();
1636 return retval;
1637}
1638
1639static PyObject*
1640DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1641{
1642 return _DB_consume(self, args, kwargs, DB_CONSUME);
1643}
1644
1645static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001646DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1647 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001648{
1649 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1650}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001651
1652
1653static PyObject*
1654DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1655{
1656 int err, flags=0;
1657 DBC* dbc;
1658 PyObject* txnobj = NULL;
1659 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001660 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001661
1662 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1663 &txnobj, &flags))
1664 return NULL;
1665 CHECK_DB_NOT_CLOSED(self);
1666 if (!checkTxnObj(txnobj, &txn))
1667 return NULL;
1668
1669 MYDB_BEGIN_ALLOW_THREADS;
1670 err = self->db->cursor(self->db, txn, &dbc, flags);
1671 MYDB_END_ALLOW_THREADS;
1672 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001673 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001674}
1675
1676
1677static PyObject*
1678DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1679{
1680 PyObject* txnobj = NULL;
1681 int flags = 0;
1682 PyObject* keyobj;
1683 DBT key;
1684 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001685 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001686
1687 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1688 &keyobj, &txnobj, &flags))
1689 return NULL;
1690 CHECK_DB_NOT_CLOSED(self);
1691 if (!make_key_dbt(self, keyobj, &key, NULL))
1692 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001693 if (!checkTxnObj(txnobj, &txn)) {
1694 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001695 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001696 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001697
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001698 if (-1 == _DB_delete(self, txn, &key, 0)) {
1699 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001700 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001701 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001702
1703 FREE_DBT(key);
1704 RETURN_NONE();
1705}
1706
1707
1708static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001709DB_fd(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001710{
1711 int err, the_fd;
1712
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001713 CHECK_DB_NOT_CLOSED(self);
1714
1715 MYDB_BEGIN_ALLOW_THREADS;
1716 err = self->db->fd(self->db, &the_fd);
1717 MYDB_END_ALLOW_THREADS;
1718 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001719 return NUMBER_FromLong(the_fd);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001720}
1721
1722
1723static PyObject*
1724DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1725{
1726 int err, flags=0;
1727 PyObject* txnobj = NULL;
1728 PyObject* keyobj;
1729 PyObject* dfltobj = NULL;
1730 PyObject* retval = NULL;
1731 int dlen = -1;
1732 int doff = -1;
1733 DBT key, data;
1734 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001735 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001736 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001737
1738 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001739 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1740 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001741 return NULL;
1742
1743 CHECK_DB_NOT_CLOSED(self);
1744 if (!make_key_dbt(self, keyobj, &key, &flags))
1745 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001746 if (!checkTxnObj(txnobj, &txn)) {
1747 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001748 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001749 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001750
1751 CLEAR_DBT(data);
1752 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001753 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001754 data.flags = DB_DBT_MALLOC;
1755 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001756 if (!add_partial_dbt(&data, dlen, doff)) {
1757 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001758 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001759 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001760
1761 MYDB_BEGIN_ALLOW_THREADS;
1762 err = self->db->get(self->db, txn, &key, &data, flags);
1763 MYDB_END_ALLOW_THREADS;
1764
Gregory P. Smithe9477062005-06-04 06:46:59 +00001765 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001766 err = 0;
1767 Py_INCREF(dfltobj);
1768 retval = dfltobj;
1769 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001770 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1771 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001772 err = 0;
1773 Py_INCREF(Py_None);
1774 retval = Py_None;
1775 }
1776 else if (!err) {
1777 if (flags & DB_SET_RECNO) /* return both key and data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001778 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001779 else /* return just the data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001780 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001781 FREE_DBT(data);
1782 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001783 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001784
1785 RETURN_IF_ERR();
1786 return retval;
1787}
1788
Gregory P. Smith19699a92004-06-28 04:06:49 +00001789static PyObject*
1790DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1791{
1792 int err, flags=0;
1793 PyObject* txnobj = NULL;
1794 PyObject* keyobj;
1795 PyObject* dfltobj = NULL;
1796 PyObject* retval = NULL;
1797 int dlen = -1;
1798 int doff = -1;
1799 DBT key, pkey, data;
1800 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001801 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001802 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001803
1804 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1805 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1806 &doff))
1807 return NULL;
1808
1809 CHECK_DB_NOT_CLOSED(self);
1810 if (!make_key_dbt(self, keyobj, &key, &flags))
1811 return NULL;
1812 if (!checkTxnObj(txnobj, &txn)) {
1813 FREE_DBT(key);
1814 return NULL;
1815 }
1816
1817 CLEAR_DBT(data);
1818 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001819 /* Tell Berkeley DB to malloc the return value (thread safe) */
Gregory P. Smith19699a92004-06-28 04:06:49 +00001820 data.flags = DB_DBT_MALLOC;
1821 }
1822 if (!add_partial_dbt(&data, dlen, doff)) {
1823 FREE_DBT(key);
1824 return NULL;
1825 }
1826
1827 CLEAR_DBT(pkey);
1828 pkey.flags = DB_DBT_MALLOC;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001829
Gregory P. Smith19699a92004-06-28 04:06:49 +00001830 MYDB_BEGIN_ALLOW_THREADS;
1831 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1832 MYDB_END_ALLOW_THREADS;
1833
Gregory P. Smithe9477062005-06-04 06:46:59 +00001834 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001835 err = 0;
1836 Py_INCREF(dfltobj);
1837 retval = dfltobj;
1838 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001839 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1840 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001841 err = 0;
1842 Py_INCREF(Py_None);
1843 retval = Py_None;
1844 }
1845 else if (!err) {
1846 PyObject *pkeyObj;
1847 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001848 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001849
1850 if (self->primaryDBType == DB_RECNO ||
1851 self->primaryDBType == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001852 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001853 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001854 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001855
1856 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1857 {
1858 PyObject *keyObj;
1859 int type = _DB_get_type(self);
1860 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001861 keyObj = NUMBER_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001862 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001863 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001864#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001865 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001866#else
1867 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1868#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001869 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001870 }
1871 else /* return just the pkey and data */
1872 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001873#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001874 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001875#else
1876 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1877#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001878 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001879 Py_DECREF(dataObj);
1880 Py_DECREF(pkeyObj);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001881 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001882 FREE_DBT(data);
1883 }
1884 FREE_DBT(key);
1885
1886 RETURN_IF_ERR();
1887 return retval;
1888}
1889
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001890
1891/* Return size of entry */
1892static PyObject*
1893DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1894{
1895 int err, flags=0;
1896 PyObject* txnobj = NULL;
1897 PyObject* keyobj;
1898 PyObject* retval = NULL;
1899 DBT key, data;
1900 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001901 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001902
1903 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1904 &keyobj, &txnobj))
1905 return NULL;
1906 CHECK_DB_NOT_CLOSED(self);
1907 if (!make_key_dbt(self, keyobj, &key, &flags))
1908 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001909 if (!checkTxnObj(txnobj, &txn)) {
1910 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001911 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001912 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001913 CLEAR_DBT(data);
1914
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001915 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1916 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001917 data.flags = DB_DBT_USERMEM;
1918 data.ulen = 0;
1919 MYDB_BEGIN_ALLOW_THREADS;
1920 err = self->db->get(self->db, txn, &key, &data, flags);
1921 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001922 if (err == DB_BUFFER_SMALL) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001923 retval = NUMBER_FromLong((long)data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001924 err = 0;
1925 }
1926
1927 FREE_DBT(key);
1928 FREE_DBT(data);
1929 RETURN_IF_ERR();
1930 return retval;
1931}
1932
1933
1934static PyObject*
1935DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1936{
1937 int err, flags=0;
1938 PyObject* txnobj = NULL;
1939 PyObject* keyobj;
1940 PyObject* dataobj;
1941 PyObject* retval = NULL;
1942 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001943 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001944 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001945 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001946
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001947 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1948 &keyobj, &dataobj, &txnobj, &flags))
1949 return NULL;
1950
1951 CHECK_DB_NOT_CLOSED(self);
1952 if (!make_key_dbt(self, keyobj, &key, NULL))
1953 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001954 if ( !make_dbt(dataobj, &data) ||
1955 !checkTxnObj(txnobj, &txn) )
1956 {
1957 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001958 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001959 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001960
1961 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001962 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001963
1964 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001965 /* Tell Berkeley DB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001966 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001967 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001968 }
1969
1970 MYDB_BEGIN_ALLOW_THREADS;
1971 err = self->db->get(self->db, txn, &key, &data, flags);
1972 MYDB_END_ALLOW_THREADS;
1973
Gregory P. Smithe9477062005-06-04 06:46:59 +00001974 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1975 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001976 err = 0;
1977 Py_INCREF(Py_None);
1978 retval = Py_None;
1979 }
1980 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001981 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001982 retval = Build_PyString(data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001983
1984 /* Even though the flags require DB_DBT_MALLOC, data is not always
1985 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1986 if (data.data != orig_data)
1987 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001988 }
1989
1990 FREE_DBT(key);
1991 RETURN_IF_ERR();
1992 return retval;
1993}
1994
1995
1996static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001997DB_get_byteswapped(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001998{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001999 int err = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002000 int retval = -1;
2001
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002002 CHECK_DB_NOT_CLOSED(self);
2003
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002004 MYDB_BEGIN_ALLOW_THREADS;
2005 err = self->db->get_byteswapped(self->db, &retval);
2006 MYDB_END_ALLOW_THREADS;
2007 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002008 return NUMBER_FromLong(retval);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002009}
2010
2011
2012static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002013DB_get_type(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002014{
2015 int type;
2016
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002017 CHECK_DB_NOT_CLOSED(self);
2018
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002019 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002020 if (type == -1)
2021 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002022 return NUMBER_FromLong(type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002023}
2024
2025
2026static PyObject*
2027DB_join(DBObject* self, PyObject* args)
2028{
2029 int err, flags=0;
2030 int length, x;
2031 PyObject* cursorsObj;
2032 DBC** cursors;
2033 DBC* dbc;
2034
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002035 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
2036 return NULL;
2037
2038 CHECK_DB_NOT_CLOSED(self);
2039
2040 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002041 PyErr_SetString(PyExc_TypeError,
2042 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002043 return NULL;
2044 }
2045
2046 length = PyObject_Length(cursorsObj);
2047 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00002048 if (!cursors) {
2049 PyErr_NoMemory();
2050 return NULL;
2051 }
2052
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002053 cursors[length] = NULL;
2054 for (x=0; x<length; x++) {
2055 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00002056 if (item == NULL) {
2057 free(cursors);
2058 return NULL;
2059 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002060 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002061 PyErr_SetString(PyExc_TypeError,
2062 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002063 free(cursors);
2064 return NULL;
2065 }
2066 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002067 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002068 }
2069
2070 MYDB_BEGIN_ALLOW_THREADS;
2071 err = self->db->join(self->db, cursors, &dbc, flags);
2072 MYDB_END_ALLOW_THREADS;
2073 free(cursors);
2074 RETURN_IF_ERR();
2075
Gregory P. Smith7441e652003-11-03 21:35:31 +00002076 /* FIXME: this is a buggy interface. The returned cursor
2077 contains internal references to the passed in cursors
2078 but does not hold python references to them or prevent
2079 them from being closed prematurely. This can cause
2080 python to crash when things are done in the wrong order. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00002081 return (PyObject*) newDBCursorObject(dbc, NULL, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002082}
2083
2084
2085static PyObject*
2086DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
2087{
2088 int err, flags=0;
2089 PyObject* txnobj = NULL;
2090 PyObject* keyobj;
2091 DBT key;
2092 DB_TXN *txn = NULL;
2093 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002094 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002095
2096 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
2097 &keyobj, &txnobj, &flags))
2098 return NULL;
2099 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002100 if (!make_dbt(keyobj, &key))
2101 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002102 return NULL;
2103 if (!checkTxnObj(txnobj, &txn))
2104 return NULL;
2105
2106 MYDB_BEGIN_ALLOW_THREADS;
2107 err = self->db->key_range(self->db, txn, &key, &range, flags);
2108 MYDB_END_ALLOW_THREADS;
2109
2110 RETURN_IF_ERR();
2111 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2112}
2113
2114
2115static PyObject*
2116DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2117{
2118 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2119 char* filename = NULL;
2120 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002121#if (DBVER >= 41)
2122 PyObject *txnobj = NULL;
2123 DB_TXN *txn = NULL;
2124 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002125 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002126 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2127 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00002128 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002129 "filename", "dbtype", "flags", "mode", "txn", NULL};
2130#else
2131 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002132 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002133 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2134 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002135 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002136 "filename", "dbtype", "flags", "mode", NULL};
2137#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002138
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002139#if (DBVER >= 41)
2140 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2141 &filename, &dbname, &type, &flags, &mode,
2142 &txnobj))
2143#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002144 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002145 &filename, &dbname, &type, &flags,
2146 &mode))
2147#endif
2148 {
2149 PyErr_Clear();
2150 type = DB_UNKNOWN; flags = 0; mode = 0660;
2151 filename = NULL; dbname = NULL;
2152#if (DBVER >= 41)
2153 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2154 kwnames_basic,
2155 &filename, &type, &flags, &mode,
2156 &txnobj))
2157 return NULL;
2158#else
2159 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2160 kwnames_basic,
2161 &filename, &type, &flags, &mode))
2162 return NULL;
2163#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002164 }
2165
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002166#if (DBVER >= 41)
2167 if (!checkTxnObj(txnobj, &txn)) return NULL;
2168#endif
2169
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002170 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002171 PyObject *t = Py_BuildValue("(is)", 0,
2172 "Cannot call open() twice for DB object");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002173 if (t) {
2174 PyErr_SetObject(DBError, t);
2175 Py_DECREF(t);
2176 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002177 return NULL;
2178 }
2179
Jesus Ceaef9764f2008-05-13 18:45:46 +00002180#if (DBVER >= 41)
2181 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2182 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2183 self->txn=(DBTxnObject *)txnobj;
2184 } else {
2185 self->txn=NULL;
2186 }
2187#else
2188 self->txn=NULL;
2189#endif
2190
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002191 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002192#if (DBVER >= 41)
2193 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2194#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002195 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002196#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002197 MYDB_END_ALLOW_THREADS;
2198 if (makeDBError(err)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002199 PyObject *dummy;
2200
Jesus Cea5cd5f122008-09-23 18:54:08 +00002201 dummy=DB_close_internal(self, 0, 0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002202 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002203 return NULL;
2204 }
2205
Gregory P. Smithfc006692007-11-05 09:06:28 +00002206#if (DBVER >= 42)
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002207 self->db->get_flags(self->db, &self->setflags);
Gregory P. Smithfc006692007-11-05 09:06:28 +00002208#endif
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002209
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002210 self->flags = flags;
Jesus Ceaef9764f2008-05-13 18:45:46 +00002211
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002212 RETURN_NONE();
2213}
2214
2215
2216static PyObject*
2217DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2218{
2219 int flags=0;
2220 PyObject* txnobj = NULL;
2221 int dlen = -1;
2222 int doff = -1;
2223 PyObject* keyobj, *dataobj, *retval;
2224 DBT key, data;
2225 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002226 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002227 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002228
2229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2230 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2231 return NULL;
2232
2233 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002234 if (!make_key_dbt(self, keyobj, &key, NULL))
2235 return NULL;
2236 if ( !make_dbt(dataobj, &data) ||
2237 !add_partial_dbt(&data, dlen, doff) ||
2238 !checkTxnObj(txnobj, &txn) )
2239 {
2240 FREE_DBT(key);
2241 return NULL;
2242 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002243
2244 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2245 FREE_DBT(key);
2246 return NULL;
2247 }
2248
2249 if (flags & DB_APPEND)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002250 retval = NUMBER_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002251 else {
2252 retval = Py_None;
2253 Py_INCREF(retval);
2254 }
2255 FREE_DBT(key);
2256 return retval;
2257}
2258
2259
2260
2261static PyObject*
2262DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2263{
2264 char* filename;
2265 char* database = NULL;
2266 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002267 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002268
2269 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2270 &filename, &database, &flags))
2271 return NULL;
2272 CHECK_DB_NOT_CLOSED(self);
2273
Jesus Cea4907d272008-08-31 14:00:51 +00002274 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
2275
2276 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002277 err = self->db->remove(self->db, filename, database, flags);
Jesus Cea4907d272008-08-31 14:00:51 +00002278 MYDB_END_ALLOW_THREADS;
2279
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002280 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002281 RETURN_IF_ERR();
2282 RETURN_NONE();
2283}
2284
2285
2286
2287static PyObject*
2288DB_rename(DBObject* self, PyObject* args)
2289{
2290 char* filename;
2291 char* database;
2292 char* newname;
2293 int err, flags=0;
2294
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002295 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2296 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002297 return NULL;
2298 CHECK_DB_NOT_CLOSED(self);
2299
2300 MYDB_BEGIN_ALLOW_THREADS;
2301 err = self->db->rename(self->db, filename, database, newname, flags);
2302 MYDB_END_ALLOW_THREADS;
2303 RETURN_IF_ERR();
2304 RETURN_NONE();
2305}
2306
2307
2308static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002309DB_get_private(DBObject* self)
2310{
2311 /* We can give out the private field even if db is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00002312 Py_INCREF(self->private_obj);
2313 return self->private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002314}
2315
2316static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00002317DB_set_private(DBObject* self, PyObject* private_obj)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002318{
2319 /* We can set the private field even if db is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00002320 Py_DECREF(self->private_obj);
2321 Py_INCREF(private_obj);
2322 self->private_obj = private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002323 RETURN_NONE();
2324}
2325
2326
2327static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002328DB_set_bt_minkey(DBObject* self, PyObject* args)
2329{
2330 int err, minkey;
2331
2332 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2333 return NULL;
2334 CHECK_DB_NOT_CLOSED(self);
2335
2336 MYDB_BEGIN_ALLOW_THREADS;
2337 err = self->db->set_bt_minkey(self->db, minkey);
2338 MYDB_END_ALLOW_THREADS;
2339 RETURN_IF_ERR();
2340 RETURN_NONE();
2341}
2342
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002343static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002344_default_cmp(const DBT *leftKey,
2345 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002346{
2347 int res;
2348 int lsize = leftKey->size, rsize = rightKey->size;
2349
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002350 res = memcmp(leftKey->data, rightKey->data,
Georg Brandlef1701f2006-03-07 14:57:48 +00002351 lsize < rsize ? lsize : rsize);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002352
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002353 if (res == 0) {
2354 if (lsize < rsize) {
2355 res = -1;
2356 }
2357 else if (lsize > rsize) {
2358 res = 1;
2359 }
2360 }
2361 return res;
2362}
2363
2364static int
Jesus Ceaef9764f2008-05-13 18:45:46 +00002365_db_compareCallback(DB* db,
Georg Brandlef1701f2006-03-07 14:57:48 +00002366 const DBT *leftKey,
2367 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002368{
2369 int res = 0;
2370 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002371 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002372 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002373
2374 if (self == NULL || self->btCompareCallback == NULL) {
2375 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002376 PyErr_SetString(PyExc_TypeError,
2377 (self == 0
2378 ? "DB_bt_compare db is NULL."
2379 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002380 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002381 PyErr_Print();
2382 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002383 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002384 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002385 MYDB_BEGIN_BLOCK_THREADS;
2386
Jesus Ceaef9764f2008-05-13 18:45:46 +00002387 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002388 if (args != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002389 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002390 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002391 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002392 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002393 PyErr_Print();
2394 res = _default_cmp(leftKey, rightKey);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002395 } else if (NUMBER_Check(result)) {
2396 res = NUMBER_AsLong(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002397 } else {
2398 PyErr_SetString(PyExc_TypeError,
2399 "DB_bt_compare callback MUST return an int.");
2400 /* we're in a callback within the DB code, we can't raise */
2401 PyErr_Print();
2402 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002403 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002404
Thomas Woutersb3153832006-03-08 01:47:19 +00002405 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002406 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002407
2408 MYDB_END_BLOCK_THREADS;
2409 }
2410 return res;
2411}
2412
2413static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002414DB_set_bt_compare(DBObject* self, PyObject* comparator)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002415{
2416 int err;
Thomas Woutersb3153832006-03-08 01:47:19 +00002417 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002418
Georg Brandlef1701f2006-03-07 14:57:48 +00002419 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002420
Georg Brandlef1701f2006-03-07 14:57:48 +00002421 if (!PyCallable_Check(comparator)) {
2422 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002423 return NULL;
2424 }
2425
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002426 /*
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002427 * Perform a test call of the comparator function with two empty
2428 * string objects here. verify that it returns an int (0).
2429 * err if not.
2430 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002431 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002432 result = PyEval_CallObject(comparator, tuple);
2433 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002434 if (result == NULL)
2435 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002436 if (!NUMBER_Check(result)) {
Florent Xiclunae7901c52010-03-01 20:45:01 +00002437 Py_DECREF(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002438 PyErr_SetString(PyExc_TypeError,
2439 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002440 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002441 } else if (NUMBER_AsLong(result) != 0) {
Florent Xiclunae7901c52010-03-01 20:45:01 +00002442 Py_DECREF(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002443 PyErr_SetString(PyExc_TypeError,
2444 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002445 return NULL;
2446 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002447 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002448
2449 /* We don't accept multiple set_bt_compare operations, in order to
2450 * simplify the code. This would have no real use, as one cannot
2451 * change the function once the db is opened anyway */
2452 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002453 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002454 return NULL;
2455 }
2456
Georg Brandlef1701f2006-03-07 14:57:48 +00002457 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002458 self->btCompareCallback = comparator;
2459
2460 /* This is to workaround a problem with un-initialized threads (see
2461 comment in DB_associate) */
2462#ifdef WITH_THREAD
2463 PyEval_InitThreads();
2464#endif
2465
Thomas Woutersb3153832006-03-08 01:47:19 +00002466 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002467
2468 if (err) {
2469 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002470 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002471 self->btCompareCallback = NULL;
2472 }
2473
Georg Brandlef1701f2006-03-07 14:57:48 +00002474 RETURN_IF_ERR();
2475 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002476}
2477
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002478
2479static PyObject*
2480DB_set_cachesize(DBObject* self, PyObject* args)
2481{
2482 int err;
2483 int gbytes = 0, bytes = 0, ncache = 0;
2484
2485 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2486 &gbytes,&bytes,&ncache))
2487 return NULL;
2488 CHECK_DB_NOT_CLOSED(self);
2489
2490 MYDB_BEGIN_ALLOW_THREADS;
2491 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2492 MYDB_END_ALLOW_THREADS;
2493 RETURN_IF_ERR();
2494 RETURN_NONE();
2495}
2496
2497
2498static PyObject*
2499DB_set_flags(DBObject* self, PyObject* args)
2500{
2501 int err, flags;
2502
2503 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2504 return NULL;
2505 CHECK_DB_NOT_CLOSED(self);
2506
2507 MYDB_BEGIN_ALLOW_THREADS;
2508 err = self->db->set_flags(self->db, flags);
2509 MYDB_END_ALLOW_THREADS;
2510 RETURN_IF_ERR();
2511
2512 self->setflags |= flags;
2513 RETURN_NONE();
2514}
2515
2516
2517static PyObject*
2518DB_set_h_ffactor(DBObject* self, PyObject* args)
2519{
2520 int err, ffactor;
2521
2522 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2523 return NULL;
2524 CHECK_DB_NOT_CLOSED(self);
2525
2526 MYDB_BEGIN_ALLOW_THREADS;
2527 err = self->db->set_h_ffactor(self->db, ffactor);
2528 MYDB_END_ALLOW_THREADS;
2529 RETURN_IF_ERR();
2530 RETURN_NONE();
2531}
2532
2533
2534static PyObject*
2535DB_set_h_nelem(DBObject* self, PyObject* args)
2536{
2537 int err, nelem;
2538
2539 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2540 return NULL;
2541 CHECK_DB_NOT_CLOSED(self);
2542
2543 MYDB_BEGIN_ALLOW_THREADS;
2544 err = self->db->set_h_nelem(self->db, nelem);
2545 MYDB_END_ALLOW_THREADS;
2546 RETURN_IF_ERR();
2547 RETURN_NONE();
2548}
2549
2550
2551static PyObject*
2552DB_set_lorder(DBObject* self, PyObject* args)
2553{
2554 int err, lorder;
2555
2556 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2557 return NULL;
2558 CHECK_DB_NOT_CLOSED(self);
2559
2560 MYDB_BEGIN_ALLOW_THREADS;
2561 err = self->db->set_lorder(self->db, lorder);
2562 MYDB_END_ALLOW_THREADS;
2563 RETURN_IF_ERR();
2564 RETURN_NONE();
2565}
2566
2567
2568static PyObject*
2569DB_set_pagesize(DBObject* self, PyObject* args)
2570{
2571 int err, pagesize;
2572
2573 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2574 return NULL;
2575 CHECK_DB_NOT_CLOSED(self);
2576
2577 MYDB_BEGIN_ALLOW_THREADS;
2578 err = self->db->set_pagesize(self->db, pagesize);
2579 MYDB_END_ALLOW_THREADS;
2580 RETURN_IF_ERR();
2581 RETURN_NONE();
2582}
2583
2584
2585static PyObject*
2586DB_set_re_delim(DBObject* self, PyObject* args)
2587{
2588 int err;
2589 char delim;
2590
2591 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2592 PyErr_Clear();
2593 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2594 return NULL;
2595 }
2596
2597 CHECK_DB_NOT_CLOSED(self);
2598
2599 MYDB_BEGIN_ALLOW_THREADS;
2600 err = self->db->set_re_delim(self->db, delim);
2601 MYDB_END_ALLOW_THREADS;
2602 RETURN_IF_ERR();
2603 RETURN_NONE();
2604}
2605
2606static PyObject*
2607DB_set_re_len(DBObject* self, PyObject* args)
2608{
2609 int err, len;
2610
2611 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2612 return NULL;
2613 CHECK_DB_NOT_CLOSED(self);
2614
2615 MYDB_BEGIN_ALLOW_THREADS;
2616 err = self->db->set_re_len(self->db, len);
2617 MYDB_END_ALLOW_THREADS;
2618 RETURN_IF_ERR();
2619 RETURN_NONE();
2620}
2621
2622
2623static PyObject*
2624DB_set_re_pad(DBObject* self, PyObject* args)
2625{
2626 int err;
2627 char pad;
2628
2629 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2630 PyErr_Clear();
2631 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2632 return NULL;
2633 }
2634 CHECK_DB_NOT_CLOSED(self);
2635
2636 MYDB_BEGIN_ALLOW_THREADS;
2637 err = self->db->set_re_pad(self->db, pad);
2638 MYDB_END_ALLOW_THREADS;
2639 RETURN_IF_ERR();
2640 RETURN_NONE();
2641}
2642
2643
2644static PyObject*
2645DB_set_re_source(DBObject* self, PyObject* args)
2646{
2647 int err;
2648 char *re_source;
2649
2650 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2651 return NULL;
2652 CHECK_DB_NOT_CLOSED(self);
2653
2654 MYDB_BEGIN_ALLOW_THREADS;
2655 err = self->db->set_re_source(self->db, re_source);
2656 MYDB_END_ALLOW_THREADS;
2657 RETURN_IF_ERR();
2658 RETURN_NONE();
2659}
2660
2661
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002662static PyObject*
2663DB_set_q_extentsize(DBObject* self, PyObject* args)
2664{
2665 int err;
2666 int extentsize;
2667
2668 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2669 return NULL;
2670 CHECK_DB_NOT_CLOSED(self);
2671
2672 MYDB_BEGIN_ALLOW_THREADS;
2673 err = self->db->set_q_extentsize(self->db, extentsize);
2674 MYDB_END_ALLOW_THREADS;
2675 RETURN_IF_ERR();
2676 RETURN_NONE();
2677}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002678
2679static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002680DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002681{
2682 int err, flags = 0, type;
2683 void* sp;
2684 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002685#if (DBVER >= 43)
2686 PyObject* txnobj = NULL;
2687 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002688 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002689#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002690 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002691#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002692
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002693#if (DBVER >= 43)
2694 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2695 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002696 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002697 if (!checkTxnObj(txnobj, &txn))
2698 return NULL;
2699#else
2700 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2701 return NULL;
2702#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002703 CHECK_DB_NOT_CLOSED(self);
2704
2705 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002706#if (DBVER >= 43)
2707 err = self->db->stat(self->db, txn, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002708#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002709 err = self->db->stat(self->db, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002710#endif
2711 MYDB_END_ALLOW_THREADS;
2712 RETURN_IF_ERR();
2713
2714 self->haveStat = 1;
2715
2716 /* Turn the stat structure into a dictionary */
2717 type = _DB_get_type(self);
2718 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2719 free(sp);
2720 return NULL;
2721 }
2722
2723#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2724#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2725#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2726
2727 switch (type) {
2728 case DB_HASH:
2729 MAKE_HASH_ENTRY(magic);
2730 MAKE_HASH_ENTRY(version);
2731 MAKE_HASH_ENTRY(nkeys);
2732 MAKE_HASH_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002733#if (DBVER >= 46)
2734 MAKE_HASH_ENTRY(pagecnt);
2735#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002736 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002737#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002738 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002739#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002740 MAKE_HASH_ENTRY(ffactor);
2741 MAKE_HASH_ENTRY(buckets);
2742 MAKE_HASH_ENTRY(free);
2743 MAKE_HASH_ENTRY(bfree);
2744 MAKE_HASH_ENTRY(bigpages);
2745 MAKE_HASH_ENTRY(big_bfree);
2746 MAKE_HASH_ENTRY(overflows);
2747 MAKE_HASH_ENTRY(ovfl_free);
2748 MAKE_HASH_ENTRY(dup);
2749 MAKE_HASH_ENTRY(dup_free);
2750 break;
2751
2752 case DB_BTREE:
2753 case DB_RECNO:
2754 MAKE_BT_ENTRY(magic);
2755 MAKE_BT_ENTRY(version);
2756 MAKE_BT_ENTRY(nkeys);
2757 MAKE_BT_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002758#if (DBVER >= 46)
2759 MAKE_BT_ENTRY(pagecnt);
2760#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002761 MAKE_BT_ENTRY(pagesize);
2762 MAKE_BT_ENTRY(minkey);
2763 MAKE_BT_ENTRY(re_len);
2764 MAKE_BT_ENTRY(re_pad);
2765 MAKE_BT_ENTRY(levels);
2766 MAKE_BT_ENTRY(int_pg);
2767 MAKE_BT_ENTRY(leaf_pg);
2768 MAKE_BT_ENTRY(dup_pg);
2769 MAKE_BT_ENTRY(over_pg);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002770#if (DBVER >= 43)
2771 MAKE_BT_ENTRY(empty_pg);
2772#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002773 MAKE_BT_ENTRY(free);
2774 MAKE_BT_ENTRY(int_pgfree);
2775 MAKE_BT_ENTRY(leaf_pgfree);
2776 MAKE_BT_ENTRY(dup_pgfree);
2777 MAKE_BT_ENTRY(over_pgfree);
2778 break;
2779
2780 case DB_QUEUE:
2781 MAKE_QUEUE_ENTRY(magic);
2782 MAKE_QUEUE_ENTRY(version);
2783 MAKE_QUEUE_ENTRY(nkeys);
2784 MAKE_QUEUE_ENTRY(ndata);
2785 MAKE_QUEUE_ENTRY(pagesize);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002786#if (DBVER >= 41)
Jesus Ceaef9764f2008-05-13 18:45:46 +00002787 MAKE_QUEUE_ENTRY(extentsize);
2788#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002789 MAKE_QUEUE_ENTRY(pages);
2790 MAKE_QUEUE_ENTRY(re_len);
2791 MAKE_QUEUE_ENTRY(re_pad);
2792 MAKE_QUEUE_ENTRY(pgfree);
2793#if (DBVER == 31)
2794 MAKE_QUEUE_ENTRY(start);
2795#endif
2796 MAKE_QUEUE_ENTRY(first_recno);
2797 MAKE_QUEUE_ENTRY(cur_recno);
2798 break;
2799
2800 default:
2801 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2802 Py_DECREF(d);
2803 d = NULL;
2804 }
2805
2806#undef MAKE_HASH_ENTRY
2807#undef MAKE_BT_ENTRY
2808#undef MAKE_QUEUE_ENTRY
2809
2810 free(sp);
2811 return d;
2812}
2813
2814static PyObject*
2815DB_sync(DBObject* self, PyObject* args)
2816{
2817 int err;
2818 int flags = 0;
2819
2820 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2821 return NULL;
2822 CHECK_DB_NOT_CLOSED(self);
2823
2824 MYDB_BEGIN_ALLOW_THREADS;
2825 err = self->db->sync(self->db, flags);
2826 MYDB_END_ALLOW_THREADS;
2827 RETURN_IF_ERR();
2828 RETURN_NONE();
2829}
2830
2831
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002832static PyObject*
2833DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2834{
2835 int err, flags=0;
2836 u_int32_t count=0;
2837 PyObject* txnobj = NULL;
2838 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002839 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002840
2841 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2842 &txnobj, &flags))
2843 return NULL;
2844 CHECK_DB_NOT_CLOSED(self);
2845 if (!checkTxnObj(txnobj, &txn))
2846 return NULL;
2847
2848 MYDB_BEGIN_ALLOW_THREADS;
2849 err = self->db->truncate(self->db, txn, &count, flags);
2850 MYDB_END_ALLOW_THREADS;
2851 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002852 return NUMBER_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002853}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002854
2855
2856static PyObject*
2857DB_upgrade(DBObject* self, PyObject* args)
2858{
2859 int err, flags=0;
2860 char *filename;
2861
2862 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2863 return NULL;
2864 CHECK_DB_NOT_CLOSED(self);
2865
2866 MYDB_BEGIN_ALLOW_THREADS;
2867 err = self->db->upgrade(self->db, filename, flags);
2868 MYDB_END_ALLOW_THREADS;
2869 RETURN_IF_ERR();
2870 RETURN_NONE();
2871}
2872
2873
2874static PyObject*
2875DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2876{
2877 int err, flags=0;
2878 char* fileName;
2879 char* dbName=NULL;
2880 char* outFileName=NULL;
2881 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002882 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002883 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002884
2885 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2886 &fileName, &dbName, &outFileName, &flags))
2887 return NULL;
2888
2889 CHECK_DB_NOT_CLOSED(self);
2890 if (outFileName)
2891 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002892 /* XXX(nnorwitz): it should probably be an exception if outFile
2893 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002894
Jesus Ceaef9764f2008-05-13 18:45:46 +00002895 { /* DB.verify acts as a DB handle destructor (like close) */
2896 PyObject *error;
2897
Jesus Cea5cd5f122008-09-23 18:54:08 +00002898 error=DB_close_internal(self, 0, 1);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002899 if (error ) {
2900 return error;
2901 }
2902 }
Gregory P. Smith41631e82003-09-21 00:08:14 +00002903
Jesus Cea5cd5f122008-09-23 18:54:08 +00002904 MYDB_BEGIN_ALLOW_THREADS;
2905 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2906 MYDB_END_ALLOW_THREADS;
2907
2908 self->db = NULL; /* Implicit close; related objects already released */
2909
2910 if (outFile)
2911 fclose(outFile);
2912
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002913 RETURN_IF_ERR();
2914 RETURN_NONE();
2915}
2916
2917
2918static PyObject*
2919DB_set_get_returns_none(DBObject* self, PyObject* args)
2920{
2921 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002922 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002923
2924 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2925 return NULL;
2926 CHECK_DB_NOT_CLOSED(self);
2927
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002928 if (self->moduleFlags.getReturnsNone)
2929 ++oldValue;
2930 if (self->moduleFlags.cursorSetReturnsNone)
2931 ++oldValue;
2932 self->moduleFlags.getReturnsNone = (flags >= 1);
2933 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002934 return NUMBER_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002935}
2936
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002937#if (DBVER >= 41)
2938static PyObject*
2939DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2940{
2941 int err;
2942 u_int32_t flags=0;
2943 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002944 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002945
2946 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2947 &passwd, &flags)) {
2948 return NULL;
2949 }
2950
2951 MYDB_BEGIN_ALLOW_THREADS;
2952 err = self->db->set_encrypt(self->db, passwd, flags);
2953 MYDB_END_ALLOW_THREADS;
2954
2955 RETURN_IF_ERR();
2956 RETURN_NONE();
2957}
2958#endif /* DBVER >= 41 */
2959
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002960
2961/*-------------------------------------------------------------- */
2962/* Mapping and Dictionary-like access routines */
2963
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002964Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002965{
2966 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002967 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002968 int flags = 0;
2969 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002970 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002971
2972 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002973 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002974 if (t) {
2975 PyErr_SetObject(DBError, t);
2976 Py_DECREF(t);
2977 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002978 return -1;
2979 }
2980
2981 if (self->haveStat) { /* Has the stat function been called recently? If
2982 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002983 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002984 }
2985
2986 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002987redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002988#if (DBVER >= 43)
2989 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002990#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002991 err = self->db->stat(self->db, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002992#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002993
2994 /* All the stat structures have matching fields upto the ndata field,
2995 so we can use any of them for the type cast */
2996 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2997
Jesus Ceaef9764f2008-05-13 18:45:46 +00002998 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002999 * redo a full stat to make sure.
3000 * Fixes SF python bug 1493322, pybsddb bug 1184012
3001 */
3002 if (size == 0 && (flags & DB_FAST_STAT)) {
3003 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00003004 if (!err)
3005 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00003006 goto redo_stat_for_length;
3007 }
3008
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003009 MYDB_END_ALLOW_THREADS;
3010
3011 if (err)
3012 return -1;
3013
3014 self->haveStat = 1;
3015
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003016 free(sp);
3017 return size;
3018}
3019
3020
3021PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
3022{
3023 int err;
3024 PyObject* retval;
3025 DBT key;
3026 DBT data;
3027
3028 CHECK_DB_NOT_CLOSED(self);
3029 if (!make_key_dbt(self, keyobj, &key, NULL))
3030 return NULL;
3031
3032 CLEAR_DBT(data);
3033 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003034 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003035 data.flags = DB_DBT_MALLOC;
3036 }
3037 MYDB_BEGIN_ALLOW_THREADS;
3038 err = self->db->get(self->db, NULL, &key, &data, 0);
3039 MYDB_END_ALLOW_THREADS;
3040 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3041 PyErr_SetObject(PyExc_KeyError, keyobj);
3042 retval = NULL;
3043 }
3044 else if (makeDBError(err)) {
3045 retval = NULL;
3046 }
3047 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003048 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003049 FREE_DBT(data);
3050 }
3051
3052 FREE_DBT(key);
3053 return retval;
3054}
3055
3056
3057static int
3058DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
3059{
3060 DBT key, data;
3061 int retval;
3062 int flags = 0;
3063
3064 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00003065 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003066 if (t) {
3067 PyErr_SetObject(DBError, t);
3068 Py_DECREF(t);
3069 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003070 return -1;
3071 }
3072
3073 if (!make_key_dbt(self, keyobj, &key, NULL))
3074 return -1;
3075
3076 if (dataobj != NULL) {
3077 if (!make_dbt(dataobj, &data))
3078 retval = -1;
3079 else {
3080 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003081 /* dictionaries shouldn't have duplicate keys */
3082 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003083 retval = _DB_put(self, NULL, &key, &data, flags);
3084
3085 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003086 /* try deleting any old record that matches and then PUT it
3087 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003088 _DB_delete(self, NULL, &key, 0);
3089 PyErr_Clear();
3090 retval = _DB_put(self, NULL, &key, &data, flags);
3091 }
3092 }
3093 }
3094 else {
3095 /* dataobj == NULL, so delete the key */
3096 retval = _DB_delete(self, NULL, &key, 0);
3097 }
3098 FREE_DBT(key);
3099 return retval;
3100}
3101
3102
3103static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00003104DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003105{
3106 int err;
3107 PyObject* keyobj;
3108 DBT key, data;
3109 PyObject* txnobj = NULL;
3110 DB_TXN *txn = NULL;
Jesus Cea4907d272008-08-31 14:00:51 +00003111 static char* kwnames[] = {"key","txn", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003112
Jesus Cea4907d272008-08-31 14:00:51 +00003113 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
3114 &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003115 return NULL;
Jesus Cea4907d272008-08-31 14:00:51 +00003116
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003117 CHECK_DB_NOT_CLOSED(self);
3118 if (!make_key_dbt(self, keyobj, &key, NULL))
3119 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003120 if (!checkTxnObj(txnobj, &txn)) {
3121 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003122 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003123 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003124
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003125 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003126 it has a record but can't allocate a buffer for the data. This saves
3127 having to deal with data we won't be using.
3128 */
3129 CLEAR_DBT(data);
3130 data.flags = DB_DBT_USERMEM;
3131
3132 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00003133 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003134 MYDB_END_ALLOW_THREADS;
3135 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003136
3137 if (err == DB_BUFFER_SMALL || err == 0) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003138 return NUMBER_FromLong(1);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003139 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003140 return NUMBER_FromLong(0);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003141 }
3142
3143 makeDBError(err);
3144 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003145}
3146
3147
3148#define _KEYS_LIST 1
3149#define _VALUES_LIST 2
3150#define _ITEMS_LIST 3
3151
3152static PyObject*
3153_DB_make_list(DBObject* self, DB_TXN* txn, int type)
3154{
3155 int err, dbtype;
3156 DBT key;
3157 DBT data;
3158 DBC *cursor;
3159 PyObject* list;
3160 PyObject* item = NULL;
3161
3162 CHECK_DB_NOT_CLOSED(self);
3163 CLEAR_DBT(key);
3164 CLEAR_DBT(data);
3165
3166 dbtype = _DB_get_type(self);
3167 if (dbtype == -1)
3168 return NULL;
3169
3170 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00003171 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003172 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003173
3174 /* get a cursor */
3175 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00003176 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003177 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00003178 if (makeDBError(err)) {
3179 Py_DECREF(list);
3180 return NULL;
3181 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003182
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003183 while (1) { /* use the cursor to traverse the DB, collecting items */
3184 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003185 err = _DBC_get(cursor, &key, &data, DB_NEXT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003186 MYDB_END_ALLOW_THREADS;
3187
3188 if (err) {
3189 /* for any error, break out of the loop */
3190 break;
3191 }
3192
3193 switch (type) {
3194 case _KEYS_LIST:
3195 switch(dbtype) {
3196 case DB_BTREE:
3197 case DB_HASH:
3198 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003199 item = Build_PyString(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003200 break;
3201 case DB_RECNO:
3202 case DB_QUEUE:
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003203 item = NUMBER_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003204 break;
3205 }
3206 break;
3207
3208 case _VALUES_LIST:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003209 item = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003210 break;
3211
3212 case _ITEMS_LIST:
3213 switch(dbtype) {
3214 case DB_BTREE:
3215 case DB_HASH:
3216 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003217 item = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003218 break;
3219 case DB_RECNO:
3220 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003221 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003222 break;
3223 }
3224 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00003225 default:
3226 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3227 item = NULL;
3228 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003229 }
3230 if (item == NULL) {
3231 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003232 list = NULL;
3233 goto done;
3234 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003235 if (PyList_Append(list, item)) {
3236 Py_DECREF(list);
3237 Py_DECREF(item);
3238 list = NULL;
3239 goto done;
3240 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003241 Py_DECREF(item);
3242 }
3243
Gregory P. Smithe9477062005-06-04 06:46:59 +00003244 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3245 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003246 Py_DECREF(list);
3247 list = NULL;
3248 }
3249
3250 done:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003251 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003252 _DBC_close(cursor);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003253 MYDB_END_ALLOW_THREADS;
3254 return list;
3255}
3256
3257
3258static PyObject*
3259DB_keys(DBObject* self, PyObject* args)
3260{
3261 PyObject* txnobj = NULL;
3262 DB_TXN *txn = NULL;
3263
Georg Brandl96a8c392006-05-29 21:04:52 +00003264 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003265 return NULL;
3266 if (!checkTxnObj(txnobj, &txn))
3267 return NULL;
3268 return _DB_make_list(self, txn, _KEYS_LIST);
3269}
3270
3271
3272static PyObject*
3273DB_items(DBObject* self, PyObject* args)
3274{
3275 PyObject* txnobj = NULL;
3276 DB_TXN *txn = NULL;
3277
Georg Brandl96a8c392006-05-29 21:04:52 +00003278 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003279 return NULL;
3280 if (!checkTxnObj(txnobj, &txn))
3281 return NULL;
3282 return _DB_make_list(self, txn, _ITEMS_LIST);
3283}
3284
3285
3286static PyObject*
3287DB_values(DBObject* self, PyObject* args)
3288{
3289 PyObject* txnobj = NULL;
3290 DB_TXN *txn = NULL;
3291
Georg Brandl96a8c392006-05-29 21:04:52 +00003292 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003293 return NULL;
3294 if (!checkTxnObj(txnobj, &txn))
3295 return NULL;
3296 return _DB_make_list(self, txn, _VALUES_LIST);
3297}
3298
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003299/* --------------------------------------------------------------------- */
3300/* DBCursor methods */
3301
3302
3303static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003304DBC_close_internal(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003305{
3306 int err = 0;
3307
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003308 if (self->dbc != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003309 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3310 if (self->txn) {
3311 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3312 self->txn=NULL;
3313 }
3314
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003315 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003316 err = _DBC_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003317 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003318 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003319 }
3320 RETURN_IF_ERR();
3321 RETURN_NONE();
3322}
3323
Jesus Ceaef9764f2008-05-13 18:45:46 +00003324static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003325DBC_close(DBCursorObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00003326{
Jesus Ceaef9764f2008-05-13 18:45:46 +00003327 return DBC_close_internal(self);
3328}
3329
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003330
3331static PyObject*
3332DBC_count(DBCursorObject* self, PyObject* args)
3333{
3334 int err = 0;
3335 db_recno_t count;
3336 int flags = 0;
3337
3338 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3339 return NULL;
3340
3341 CHECK_CURSOR_NOT_CLOSED(self);
3342
3343 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003344 err = _DBC_count(self->dbc, &count, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003345 MYDB_END_ALLOW_THREADS;
3346 RETURN_IF_ERR();
3347
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003348 return NUMBER_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003349}
3350
3351
3352static PyObject*
3353DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3354{
3355 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3356}
3357
3358
3359static PyObject*
3360DBC_delete(DBCursorObject* self, PyObject* args)
3361{
3362 int err, flags=0;
3363
3364 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3365 return NULL;
3366
3367 CHECK_CURSOR_NOT_CLOSED(self);
3368
3369 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003370 err = _DBC_del(self->dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003371 MYDB_END_ALLOW_THREADS;
3372 RETURN_IF_ERR();
3373
3374 self->mydb->haveStat = 0;
3375 RETURN_NONE();
3376}
3377
3378
3379static PyObject*
3380DBC_dup(DBCursorObject* self, PyObject* args)
3381{
3382 int err, flags =0;
3383 DBC* dbc = NULL;
3384
3385 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3386 return NULL;
3387
3388 CHECK_CURSOR_NOT_CLOSED(self);
3389
3390 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003391 err = _DBC_dup(self->dbc, &dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003392 MYDB_END_ALLOW_THREADS;
3393 RETURN_IF_ERR();
3394
Jesus Ceaef9764f2008-05-13 18:45:46 +00003395 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003396}
3397
3398static PyObject*
3399DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3400{
3401 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3402}
3403
3404
3405static PyObject*
3406DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3407{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003408 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003409 PyObject* keyobj = NULL;
3410 PyObject* dataobj = NULL;
3411 PyObject* retval = NULL;
3412 int dlen = -1;
3413 int doff = -1;
3414 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003415 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003416 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003417
3418 CLEAR_DBT(key);
3419 CLEAR_DBT(data);
3420 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003421 &flags, &dlen, &doff))
3422 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003423 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003424 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
Jesus Cea4907d272008-08-31 14:00:51 +00003425 &kwnames[1],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003426 &keyobj, &flags, &dlen, &doff))
3427 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003428 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003429 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3430 kwnames, &keyobj, &dataobj,
3431 &flags, &dlen, &doff))
3432 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003433 return NULL;
3434 }
3435 }
3436 }
3437
3438 CHECK_CURSOR_NOT_CLOSED(self);
3439
3440 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3441 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003442 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3443 (!add_partial_dbt(&data, dlen, doff)) )
3444 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003445 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003446 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003447 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003448
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003449 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003450 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003451 MYDB_END_ALLOW_THREADS;
3452
Gregory P. Smithe9477062005-06-04 06:46:59 +00003453 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3454 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003455 Py_INCREF(Py_None);
3456 retval = Py_None;
3457 }
3458 else if (makeDBError(err)) {
3459 retval = NULL;
3460 }
3461 else {
3462 switch (_DB_get_type(self->mydb)) {
3463 case -1:
3464 retval = NULL;
3465 break;
3466 case DB_BTREE:
3467 case DB_HASH:
3468 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003469 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003470 break;
3471 case DB_RECNO:
3472 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003473 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003474 break;
3475 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003476 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003477 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003478 return retval;
3479}
3480
Gregory P. Smith19699a92004-06-28 04:06:49 +00003481static PyObject*
3482DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3483{
3484 int err, flags=0;
3485 PyObject* keyobj = NULL;
3486 PyObject* dataobj = NULL;
3487 PyObject* retval = NULL;
3488 int dlen = -1;
3489 int doff = -1;
3490 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003491 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3492 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003493
3494 CLEAR_DBT(key);
3495 CLEAR_DBT(data);
3496 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3497 &flags, &dlen, &doff))
3498 {
3499 PyErr_Clear();
3500 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003501 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003502 &keyobj, &flags, &dlen, &doff))
3503 {
3504 PyErr_Clear();
3505 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3506 kwnames, &keyobj, &dataobj,
3507 &flags, &dlen, &doff))
3508 {
3509 return NULL;
3510 }
3511 }
3512 }
3513
3514 CHECK_CURSOR_NOT_CLOSED(self);
3515
3516 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3517 return NULL;
3518 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3519 (!add_partial_dbt(&data, dlen, doff)) ) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003520 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003521 return NULL;
3522 }
3523
Gregory P. Smith19699a92004-06-28 04:06:49 +00003524 CLEAR_DBT(pkey);
3525 pkey.flags = DB_DBT_MALLOC;
3526
3527 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003528 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003529 MYDB_END_ALLOW_THREADS;
3530
Gregory P. Smithe9477062005-06-04 06:46:59 +00003531 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3532 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003533 Py_INCREF(Py_None);
3534 retval = Py_None;
3535 }
3536 else if (makeDBError(err)) {
3537 retval = NULL;
3538 }
3539 else {
3540 PyObject *pkeyObj;
3541 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003542 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003543
3544 if (self->mydb->primaryDBType == DB_RECNO ||
3545 self->mydb->primaryDBType == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003546 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003547 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003548 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003549
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003550 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003551 {
3552 PyObject *keyObj;
3553 int type = _DB_get_type(self->mydb);
3554 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003555 keyObj = NUMBER_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003556 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003557 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003558#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003559 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003560#else
3561 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3562#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003563 Py_DECREF(keyObj);
Jesus Ceaef9764f2008-05-13 18:45:46 +00003564 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003565 }
3566 else /* return just the pkey and data */
3567 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003568#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003569 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003570#else
3571 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3572#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003573 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003574 Py_DECREF(dataObj);
3575 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003576 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003577 }
3578 /* the only time REALLOC should be set is if we used an integer
3579 * key that make_key_dbt malloc'd for us. always free these. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003580 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003581 FREE_DBT(key);
3582 }
3583 return retval;
3584}
3585
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003586
3587static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003588DBC_get_recno(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003589{
3590 int err;
3591 db_recno_t recno;
3592 DBT key;
3593 DBT data;
3594
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003595 CHECK_CURSOR_NOT_CLOSED(self);
3596
3597 CLEAR_DBT(key);
3598 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003599
3600 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003601 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003602 MYDB_END_ALLOW_THREADS;
3603 RETURN_IF_ERR();
3604
3605 recno = *((db_recno_t*)data.data);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003606 return NUMBER_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003607}
3608
3609
3610static PyObject*
3611DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3612{
3613 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3614}
3615
3616
3617static PyObject*
3618DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3619{
3620 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3621}
3622
3623
3624static PyObject*
3625DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3626{
3627 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3628}
3629
3630
3631static PyObject*
3632DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3633{
3634 int err, flags = 0;
3635 PyObject* keyobj, *dataobj;
3636 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003637 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003638 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003639 int dlen = -1;
3640 int doff = -1;
3641
3642 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3643 &keyobj, &dataobj, &flags, &dlen, &doff))
3644 return NULL;
3645
3646 CHECK_CURSOR_NOT_CLOSED(self);
3647
3648 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3649 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003650 if (!make_dbt(dataobj, &data) ||
3651 !add_partial_dbt(&data, dlen, doff) )
3652 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003653 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003654 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003655 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003656
3657 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003658 err = _DBC_put(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003659 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003660 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003661 RETURN_IF_ERR();
3662 self->mydb->haveStat = 0;
3663 RETURN_NONE();
3664}
3665
3666
3667static PyObject*
3668DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3669{
3670 int err, flags = 0;
3671 DBT key, data;
3672 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003673 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003674 int dlen = -1;
3675 int doff = -1;
3676
3677 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3678 &keyobj, &flags, &dlen, &doff))
3679 return NULL;
3680
3681 CHECK_CURSOR_NOT_CLOSED(self);
3682
3683 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3684 return NULL;
3685
3686 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003687 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003688 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003689 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003690 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003691
3692 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003693 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003694 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003695 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3696 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003697 Py_INCREF(Py_None);
3698 retval = Py_None;
3699 }
3700 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003701 retval = NULL;
3702 }
3703 else {
3704 switch (_DB_get_type(self->mydb)) {
3705 case -1:
3706 retval = NULL;
3707 break;
3708 case DB_BTREE:
3709 case DB_HASH:
3710 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003711 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003712 break;
3713 case DB_RECNO:
3714 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003715 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003716 break;
3717 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003718 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003719 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003720 /* the only time REALLOC should be set is if we used an integer
3721 * key that make_key_dbt malloc'd for us. always free these. */
3722 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003723 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003724 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003725
3726 return retval;
3727}
3728
3729
3730static PyObject*
3731DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3732{
3733 int err, flags = 0;
3734 DBT key, data;
3735 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003736 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003737 int dlen = -1;
3738 int doff = -1;
3739
3740 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3741 &keyobj, &flags, &dlen, &doff))
3742 return NULL;
3743
3744 CHECK_CURSOR_NOT_CLOSED(self);
3745
3746 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3747 return NULL;
3748
3749 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003750 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003751 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003752 return NULL;
3753 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003754 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003755 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003756 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003757 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3758 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003759 Py_INCREF(Py_None);
3760 retval = Py_None;
3761 }
3762 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003763 retval = NULL;
3764 }
3765 else {
3766 switch (_DB_get_type(self->mydb)) {
3767 case -1:
3768 retval = NULL;
3769 break;
3770 case DB_BTREE:
3771 case DB_HASH:
3772 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003773 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003774 break;
3775 case DB_RECNO:
3776 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003777 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003778 break;
3779 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003780 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003781 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003782 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003783 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003784 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003785 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003786 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003787
3788 return retval;
3789}
3790
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003791static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003792_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3793 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003794{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003795 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003796 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003797 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003798
Gregory P. Smith7441e652003-11-03 21:35:31 +00003799 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003800 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3801 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003802 if (!make_dbt(dataobj, &data)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003803 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003804 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003805 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003806
3807 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003808 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003809 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003810 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003811 Py_INCREF(Py_None);
3812 retval = Py_None;
3813 }
3814 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003815 retval = NULL;
3816 }
3817 else {
3818 switch (_DB_get_type(self->mydb)) {
3819 case -1:
3820 retval = NULL;
3821 break;
3822 case DB_BTREE:
3823 case DB_HASH:
3824 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003825 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003826 break;
3827 case DB_RECNO:
3828 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003829 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003830 break;
3831 }
3832 }
3833
Jesus Ceaef9764f2008-05-13 18:45:46 +00003834 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003835 return retval;
3836}
3837
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003838static PyObject*
3839DBC_get_both(DBCursorObject* self, PyObject* args)
3840{
3841 int flags=0;
3842 PyObject *keyobj, *dataobj;
3843
3844 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3845 return NULL;
3846
Gregory P. Smith7441e652003-11-03 21:35:31 +00003847 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003848 CHECK_CURSOR_NOT_CLOSED(self);
3849
3850 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3851 self->mydb->moduleFlags.getReturnsNone);
3852}
3853
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003854/* Return size of entry */
3855static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003856DBC_get_current_size(DBCursorObject* self)
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003857{
3858 int err, flags=DB_CURRENT;
3859 PyObject* retval = NULL;
3860 DBT key, data;
3861
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003862 CHECK_CURSOR_NOT_CLOSED(self);
3863 CLEAR_DBT(key);
3864 CLEAR_DBT(data);
3865
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003866 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003867 getting the record size. */
3868 data.flags = DB_DBT_USERMEM;
3869 data.ulen = 0;
3870 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003871 err = _DBC_get(self->dbc, &key, &data, flags);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003872 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003873 if (err == DB_BUFFER_SMALL || !err) {
3874 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003875 retval = NUMBER_FromLong((long)data.size);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003876 err = 0;
3877 }
3878
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003879 RETURN_IF_ERR();
3880 return retval;
3881}
3882
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003883static PyObject*
3884DBC_set_both(DBCursorObject* self, PyObject* args)
3885{
3886 int flags=0;
3887 PyObject *keyobj, *dataobj;
3888
3889 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3890 return NULL;
3891
Gregory P. Smith7441e652003-11-03 21:35:31 +00003892 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003893 CHECK_CURSOR_NOT_CLOSED(self);
3894
3895 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3896 self->mydb->moduleFlags.cursorSetReturnsNone);
3897}
3898
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003899
3900static PyObject*
3901DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3902{
3903 int err, irecno, flags=0;
3904 db_recno_t recno;
3905 DBT key, data;
3906 PyObject* retval;
3907 int dlen = -1;
3908 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003909 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003910
3911 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3912 &irecno, &flags, &dlen, &doff))
3913 return NULL;
3914
3915 CHECK_CURSOR_NOT_CLOSED(self);
3916
3917 CLEAR_DBT(key);
3918 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003919 /* use allocated space so DB will be able to realloc room for the real
3920 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003921 key.data = malloc(sizeof(db_recno_t));
3922 if (key.data == NULL) {
3923 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3924 return NULL;
3925 }
3926 key.size = sizeof(db_recno_t);
3927 key.ulen = key.size;
3928 memcpy(key.data, &recno, sizeof(db_recno_t));
3929 key.flags = DB_DBT_REALLOC;
3930
3931 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003932 if (!add_partial_dbt(&data, dlen, doff)) {
3933 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003934 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003935 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003936
3937 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003938 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003939 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003940 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3941 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003942 Py_INCREF(Py_None);
3943 retval = Py_None;
3944 }
3945 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003946 retval = NULL;
3947 }
3948 else { /* Can only be used for BTrees, so no need to return int key */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003949 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003950 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003951 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003952
3953 return retval;
3954}
3955
3956
3957static PyObject*
3958DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3959{
3960 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3961}
3962
3963
3964static PyObject*
3965DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3966{
3967 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3968}
3969
3970
3971static PyObject*
3972DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3973{
3974 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3975}
3976
3977
3978static PyObject*
3979DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3980{
3981 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3982}
3983
3984
3985static PyObject*
3986DBC_join_item(DBCursorObject* self, PyObject* args)
3987{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003988 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003989 DBT key, data;
3990 PyObject* retval;
3991
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003992 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003993 return NULL;
3994
3995 CHECK_CURSOR_NOT_CLOSED(self);
3996
3997 CLEAR_DBT(key);
3998 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003999
4000 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00004001 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004002 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00004003 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
4004 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004005 Py_INCREF(Py_None);
4006 retval = Py_None;
4007 }
4008 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004009 retval = NULL;
4010 }
4011 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00004012 retval = BuildValue_S(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004013 }
4014
4015 return retval;
4016}
4017
4018
4019
4020/* --------------------------------------------------------------------- */
4021/* DBEnv methods */
4022
4023
4024static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00004025DBEnv_close_internal(DBEnvObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004026{
Jesus Ceaef9764f2008-05-13 18:45:46 +00004027 PyObject *dummy;
4028 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004029
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004030 if (!self->closed) { /* Don't close more than once */
Jesus Ceaef9764f2008-05-13 18:45:46 +00004031 while(self->children_txns) {
4032 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
4033 Py_XDECREF(dummy);
4034 }
4035 while(self->children_dbs) {
Jesus Cea5cd5f122008-09-23 18:54:08 +00004036 dummy=DB_close_internal(self->children_dbs, 0, 0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004037 Py_XDECREF(dummy);
4038 }
Jesus Ceaac25fab2008-09-03 17:50:32 +00004039 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00004040
Jesus Ceaac25fab2008-09-03 17:50:32 +00004041 self->closed = 1;
4042 if (self->db_env) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004043 MYDB_BEGIN_ALLOW_THREADS;
4044 err = self->db_env->close(self->db_env, flags);
4045 MYDB_END_ALLOW_THREADS;
4046 /* after calling DBEnv->close, regardless of error, this DBEnv
Jesus Ceaef9764f2008-05-13 18:45:46 +00004047 * may not be accessed again (Berkeley DB docs). */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004048 self->db_env = NULL;
4049 RETURN_IF_ERR();
4050 }
4051 RETURN_NONE();
4052}
4053
Jesus Ceaef9764f2008-05-13 18:45:46 +00004054static PyObject*
4055DBEnv_close(DBEnvObject* self, PyObject* args)
4056{
4057 int flags = 0;
4058
4059 if (!PyArg_ParseTuple(args, "|i:close", &flags))
4060 return NULL;
Jesus Cea5cd5f122008-09-23 18:54:08 +00004061 return DBEnv_close_internal(self, flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004062}
4063
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004064
4065static PyObject*
4066DBEnv_open(DBEnvObject* self, PyObject* args)
4067{
4068 int err, flags=0, mode=0660;
4069 char *db_home;
4070
4071 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
4072 return NULL;
4073
4074 CHECK_ENV_NOT_CLOSED(self);
4075
4076 MYDB_BEGIN_ALLOW_THREADS;
4077 err = self->db_env->open(self->db_env, db_home, flags, mode);
4078 MYDB_END_ALLOW_THREADS;
4079 RETURN_IF_ERR();
4080 self->closed = 0;
4081 self->flags = flags;
4082 RETURN_NONE();
4083}
4084
4085
4086static PyObject*
4087DBEnv_remove(DBEnvObject* self, PyObject* args)
4088{
4089 int err, flags=0;
4090 char *db_home;
4091
4092 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
4093 return NULL;
4094 CHECK_ENV_NOT_CLOSED(self);
4095 MYDB_BEGIN_ALLOW_THREADS;
4096 err = self->db_env->remove(self->db_env, db_home, flags);
4097 MYDB_END_ALLOW_THREADS;
4098 RETURN_IF_ERR();
4099 RETURN_NONE();
4100}
4101
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004102#if (DBVER >= 41)
4103static PyObject*
4104DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4105{
4106 int err;
4107 u_int32_t flags=0;
4108 char *file = NULL;
4109 char *database = NULL;
4110 PyObject *txnobj = NULL;
4111 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004112 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004113 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004114
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004115 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004116 &file, &database, &txnobj, &flags)) {
4117 return NULL;
4118 }
4119 if (!checkTxnObj(txnobj, &txn)) {
4120 return NULL;
4121 }
4122 CHECK_ENV_NOT_CLOSED(self);
4123 MYDB_BEGIN_ALLOW_THREADS;
4124 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4125 MYDB_END_ALLOW_THREADS;
4126 RETURN_IF_ERR();
4127 RETURN_NONE();
4128}
4129
4130static PyObject*
4131DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4132{
4133 int err;
4134 u_int32_t flags=0;
4135 char *file = NULL;
4136 char *database = NULL;
4137 char *newname = NULL;
4138 PyObject *txnobj = NULL;
4139 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004140 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004141 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004142
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004144 &file, &database, &newname, &txnobj, &flags)) {
4145 return NULL;
4146 }
4147 if (!checkTxnObj(txnobj, &txn)) {
4148 return NULL;
4149 }
4150 CHECK_ENV_NOT_CLOSED(self);
4151 MYDB_BEGIN_ALLOW_THREADS;
4152 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4153 flags);
4154 MYDB_END_ALLOW_THREADS;
4155 RETURN_IF_ERR();
4156 RETURN_NONE();
4157}
4158
4159static PyObject*
4160DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4161{
4162 int err;
4163 u_int32_t flags=0;
4164 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004165 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004166
4167 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4168 &passwd, &flags)) {
4169 return NULL;
4170 }
4171
4172 MYDB_BEGIN_ALLOW_THREADS;
4173 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4174 MYDB_END_ALLOW_THREADS;
4175
4176 RETURN_IF_ERR();
4177 RETURN_NONE();
4178}
4179#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004180
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004181static PyObject*
4182DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4183{
4184 int err;
4185 u_int32_t flags=0;
4186 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004187 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004188
4189 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4190 &timeout, &flags)) {
4191 return NULL;
4192 }
4193
4194 MYDB_BEGIN_ALLOW_THREADS;
4195 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4196 MYDB_END_ALLOW_THREADS;
4197
4198 RETURN_IF_ERR();
4199 RETURN_NONE();
4200}
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004201
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004202static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004203DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4204{
4205 int err;
4206 long shm_key = 0;
4207
4208 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4209 return NULL;
4210 CHECK_ENV_NOT_CLOSED(self);
4211
4212 err = self->db_env->set_shm_key(self->db_env, shm_key);
4213 RETURN_IF_ERR();
4214 RETURN_NONE();
4215}
4216
4217static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004218DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4219{
4220 int err, gbytes=0, bytes=0, ncache=0;
4221
4222 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4223 &gbytes, &bytes, &ncache))
4224 return NULL;
4225 CHECK_ENV_NOT_CLOSED(self);
4226
4227 MYDB_BEGIN_ALLOW_THREADS;
4228 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4229 MYDB_END_ALLOW_THREADS;
4230 RETURN_IF_ERR();
4231 RETURN_NONE();
4232}
4233
4234
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004235static PyObject*
4236DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4237{
4238 int err, flags=0, onoff=0;
4239
4240 if (!PyArg_ParseTuple(args, "ii:set_flags",
4241 &flags, &onoff))
4242 return NULL;
4243 CHECK_ENV_NOT_CLOSED(self);
4244
4245 MYDB_BEGIN_ALLOW_THREADS;
4246 err = self->db_env->set_flags(self->db_env, flags, onoff);
4247 MYDB_END_ALLOW_THREADS;
4248 RETURN_IF_ERR();
4249 RETURN_NONE();
4250}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004251
4252
Jesus Ceaca3939c2008-05-22 15:27:38 +00004253#if (DBVER >= 47)
4254static PyObject*
4255DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
4256{
4257 int err, flags, onoff;
4258
4259 if (!PyArg_ParseTuple(args, "ii:log_set_config",
4260 &flags, &onoff))
4261 return NULL;
4262 CHECK_ENV_NOT_CLOSED(self);
4263
4264 MYDB_BEGIN_ALLOW_THREADS;
4265 err = self->db_env->log_set_config(self->db_env, flags, onoff);
4266 MYDB_END_ALLOW_THREADS;
4267 RETURN_IF_ERR();
4268 RETURN_NONE();
4269}
4270#endif /* DBVER >= 47 */
4271
4272
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004273static PyObject*
4274DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4275{
4276 int err;
4277 char *dir;
4278
4279 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4280 return NULL;
4281 CHECK_ENV_NOT_CLOSED(self);
4282
4283 MYDB_BEGIN_ALLOW_THREADS;
4284 err = self->db_env->set_data_dir(self->db_env, dir);
4285 MYDB_END_ALLOW_THREADS;
4286 RETURN_IF_ERR();
4287 RETURN_NONE();
4288}
4289
4290
4291static PyObject*
4292DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4293{
4294 int err, lg_bsize;
4295
4296 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4297 return NULL;
4298 CHECK_ENV_NOT_CLOSED(self);
4299
4300 MYDB_BEGIN_ALLOW_THREADS;
4301 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4302 MYDB_END_ALLOW_THREADS;
4303 RETURN_IF_ERR();
4304 RETURN_NONE();
4305}
4306
4307
4308static PyObject*
4309DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4310{
4311 int err;
4312 char *dir;
4313
4314 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4315 return NULL;
4316 CHECK_ENV_NOT_CLOSED(self);
4317
4318 MYDB_BEGIN_ALLOW_THREADS;
4319 err = self->db_env->set_lg_dir(self->db_env, dir);
4320 MYDB_END_ALLOW_THREADS;
4321 RETURN_IF_ERR();
4322 RETURN_NONE();
4323}
4324
4325static PyObject*
4326DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4327{
4328 int err, lg_max;
4329
4330 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4331 return NULL;
4332 CHECK_ENV_NOT_CLOSED(self);
4333
4334 MYDB_BEGIN_ALLOW_THREADS;
4335 err = self->db_env->set_lg_max(self->db_env, lg_max);
4336 MYDB_END_ALLOW_THREADS;
4337 RETURN_IF_ERR();
4338 RETURN_NONE();
4339}
4340
Jesus Ceaef9764f2008-05-13 18:45:46 +00004341#if (DBVER >= 42)
4342static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004343DBEnv_get_lg_max(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004344{
4345 int err;
4346 u_int32_t lg_max;
4347
Jesus Ceaef9764f2008-05-13 18:45:46 +00004348 CHECK_ENV_NOT_CLOSED(self);
4349
4350 MYDB_BEGIN_ALLOW_THREADS;
4351 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4352 MYDB_END_ALLOW_THREADS;
4353 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004354 return NUMBER_FromLong(lg_max);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004355}
4356#endif
4357
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004358
4359static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004360DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4361{
4362 int err, lg_max;
4363
4364 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4365 return NULL;
4366 CHECK_ENV_NOT_CLOSED(self);
4367
4368 MYDB_BEGIN_ALLOW_THREADS;
4369 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4370 MYDB_END_ALLOW_THREADS;
4371 RETURN_IF_ERR();
4372 RETURN_NONE();
4373}
4374
4375
4376static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004377DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4378{
4379 int err, lk_detect;
4380
4381 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4382 return NULL;
4383 CHECK_ENV_NOT_CLOSED(self);
4384
4385 MYDB_BEGIN_ALLOW_THREADS;
4386 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4387 MYDB_END_ALLOW_THREADS;
4388 RETURN_IF_ERR();
4389 RETURN_NONE();
4390}
4391
4392
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004393#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004394static PyObject*
4395DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4396{
4397 int err, max;
4398
4399 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4400 return NULL;
4401 CHECK_ENV_NOT_CLOSED(self);
4402
4403 MYDB_BEGIN_ALLOW_THREADS;
4404 err = self->db_env->set_lk_max(self->db_env, max);
4405 MYDB_END_ALLOW_THREADS;
4406 RETURN_IF_ERR();
4407 RETURN_NONE();
4408}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004409#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004410
4411
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004412
4413static PyObject*
4414DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4415{
4416 int err, max;
4417
4418 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4419 return NULL;
4420 CHECK_ENV_NOT_CLOSED(self);
4421
4422 MYDB_BEGIN_ALLOW_THREADS;
4423 err = self->db_env->set_lk_max_locks(self->db_env, max);
4424 MYDB_END_ALLOW_THREADS;
4425 RETURN_IF_ERR();
4426 RETURN_NONE();
4427}
4428
4429
4430static PyObject*
4431DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4432{
4433 int err, max;
4434
4435 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4436 return NULL;
4437 CHECK_ENV_NOT_CLOSED(self);
4438
4439 MYDB_BEGIN_ALLOW_THREADS;
4440 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4441 MYDB_END_ALLOW_THREADS;
4442 RETURN_IF_ERR();
4443 RETURN_NONE();
4444}
4445
4446
4447static PyObject*
4448DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4449{
4450 int err, max;
4451
4452 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4453 return NULL;
4454 CHECK_ENV_NOT_CLOSED(self);
4455
4456 MYDB_BEGIN_ALLOW_THREADS;
4457 err = self->db_env->set_lk_max_objects(self->db_env, max);
4458 MYDB_END_ALLOW_THREADS;
4459 RETURN_IF_ERR();
4460 RETURN_NONE();
4461}
4462
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004463
4464static PyObject*
4465DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4466{
4467 int err, mp_mmapsize;
4468
4469 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4470 return NULL;
4471 CHECK_ENV_NOT_CLOSED(self);
4472
4473 MYDB_BEGIN_ALLOW_THREADS;
4474 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4475 MYDB_END_ALLOW_THREADS;
4476 RETURN_IF_ERR();
4477 RETURN_NONE();
4478}
4479
4480
4481static PyObject*
4482DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4483{
4484 int err;
4485 char *dir;
4486
4487 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4488 return NULL;
4489 CHECK_ENV_NOT_CLOSED(self);
4490
4491 MYDB_BEGIN_ALLOW_THREADS;
4492 err = self->db_env->set_tmp_dir(self->db_env, dir);
4493 MYDB_END_ALLOW_THREADS;
4494 RETURN_IF_ERR();
4495 RETURN_NONE();
4496}
4497
4498
Jesus Ceaef9764f2008-05-13 18:45:46 +00004499static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004500DBEnv_txn_recover(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004501{
4502 int flags = DB_FIRST;
4503 int err, i;
4504 PyObject *list, *tuple, *gid;
4505 DBTxnObject *txn;
4506#define PREPLIST_LEN 16
4507 DB_PREPLIST preplist[PREPLIST_LEN];
Matthias Klose54cc5392010-03-15 12:46:18 +00004508#if (DBVER < 48)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004509 long retp;
Matthias Klose54cc5392010-03-15 12:46:18 +00004510#else
4511 u_int32_t retp;
4512#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004513
Jesus Ceaef9764f2008-05-13 18:45:46 +00004514 CHECK_ENV_NOT_CLOSED(self);
4515
4516 list=PyList_New(0);
4517 if (!list)
4518 return NULL;
4519 while (!0) {
4520 MYDB_BEGIN_ALLOW_THREADS
4521 err=self->db_env->txn_recover(self->db_env,
4522 preplist, PREPLIST_LEN, &retp, flags);
4523#undef PREPLIST_LEN
4524 MYDB_END_ALLOW_THREADS
4525 if (err) {
4526 Py_DECREF(list);
4527 RETURN_IF_ERR();
4528 }
4529 if (!retp) break;
4530 flags=DB_NEXT; /* Prepare for next loop pass */
4531 for (i=0; i<retp; i++) {
Christian Heimes593daf52008-05-26 12:51:38 +00004532 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
Matthias Klose54cc5392010-03-15 12:46:18 +00004533 DB_GID_SIZE);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004534 if (!gid) {
4535 Py_DECREF(list);
4536 return NULL;
4537 }
4538 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4539 if (!txn) {
4540 Py_DECREF(list);
4541 Py_DECREF(gid);
4542 return NULL;
4543 }
4544 txn->flag_prepare=1; /* Recover state */
4545 tuple=PyTuple_New(2);
4546 if (!tuple) {
4547 Py_DECREF(list);
4548 Py_DECREF(gid);
4549 Py_DECREF(txn);
4550 return NULL;
4551 }
4552 if (PyTuple_SetItem(tuple, 0, gid)) {
4553 Py_DECREF(list);
4554 Py_DECREF(gid);
4555 Py_DECREF(txn);
4556 Py_DECREF(tuple);
4557 return NULL;
4558 }
4559 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4560 Py_DECREF(list);
4561 Py_DECREF(txn);
4562 Py_DECREF(tuple); /* This delete the "gid" also */
4563 return NULL;
4564 }
4565 if (PyList_Append(list, tuple)) {
4566 Py_DECREF(list);
4567 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4568 return NULL;
4569 }
4570 Py_DECREF(tuple);
4571 }
4572 }
4573 return list;
4574}
Jesus Ceaef9764f2008-05-13 18:45:46 +00004575
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004576static PyObject*
4577DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4578{
4579 int flags = 0;
4580 PyObject* txnobj = NULL;
4581 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004582 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004583
4584 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4585 &txnobj, &flags))
4586 return NULL;
4587
4588 if (!checkTxnObj(txnobj, &txn))
4589 return NULL;
4590 CHECK_ENV_NOT_CLOSED(self);
4591
Jesus Ceaef9764f2008-05-13 18:45:46 +00004592 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004593}
4594
4595
4596static PyObject*
4597DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4598{
4599 int err, kbyte=0, min=0, flags=0;
4600
4601 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4602 return NULL;
4603 CHECK_ENV_NOT_CLOSED(self);
4604
4605 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004606 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004607 MYDB_END_ALLOW_THREADS;
4608 RETURN_IF_ERR();
4609 RETURN_NONE();
4610}
4611
4612
4613static PyObject*
4614DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4615{
4616 int err, max;
4617
4618 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4619 return NULL;
4620 CHECK_ENV_NOT_CLOSED(self);
4621
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004622 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004623 RETURN_IF_ERR();
4624 RETURN_NONE();
4625}
4626
4627
4628static PyObject*
4629DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4630{
4631 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004632 long stamp;
4633 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004634
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004635 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004636 return NULL;
4637 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004638 timestamp = (time_t)stamp;
4639 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004640 RETURN_IF_ERR();
4641 RETURN_NONE();
4642}
4643
4644
4645static PyObject*
4646DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4647{
4648 int err, atype, flags=0;
4649 int aborted = 0;
4650
4651 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4652 return NULL;
4653 CHECK_ENV_NOT_CLOSED(self);
4654
4655 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004656 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004657 MYDB_END_ALLOW_THREADS;
4658 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004659 return NUMBER_FromLong(aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004660}
4661
4662
4663static PyObject*
4664DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4665{
4666 int flags=0;
4667 int locker, lock_mode;
4668 DBT obj;
4669 PyObject* objobj;
4670
4671 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4672 return NULL;
4673
4674
4675 if (!make_dbt(objobj, &obj))
4676 return NULL;
4677
4678 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4679}
4680
4681
4682static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004683DBEnv_lock_id(DBEnvObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004684{
4685 int err;
4686 u_int32_t theID;
4687
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004688 CHECK_ENV_NOT_CLOSED(self);
4689 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004690 err = self->db_env->lock_id(self->db_env, &theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004691 MYDB_END_ALLOW_THREADS;
4692 RETURN_IF_ERR();
4693
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004694 return NUMBER_FromLong((long)theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004695}
4696
Gregory P. Smithac11e022007-11-05 02:56:31 +00004697static PyObject*
4698DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4699{
4700 int err;
4701 u_int32_t theID;
4702
4703 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4704 return NULL;
4705
4706 CHECK_ENV_NOT_CLOSED(self);
4707 MYDB_BEGIN_ALLOW_THREADS;
4708 err = self->db_env->lock_id_free(self->db_env, theID);
4709 MYDB_END_ALLOW_THREADS;
4710 RETURN_IF_ERR();
4711 RETURN_NONE();
4712}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004713
4714static PyObject*
4715DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4716{
4717 int err;
4718 DBLockObject* dblockobj;
4719
4720 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4721 return NULL;
4722
4723 CHECK_ENV_NOT_CLOSED(self);
4724 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004725 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004726 MYDB_END_ALLOW_THREADS;
4727 RETURN_IF_ERR();
4728 RETURN_NONE();
4729}
4730
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004731#if (DBVER >= 44)
4732static PyObject*
4733DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4734{
4735 int err;
4736 char *file;
4737 u_int32_t flags = 0;
4738 static char* kwnames[] = { "file", "flags", NULL};
4739
4740 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4741 &file, &flags))
4742 return NULL;
4743 CHECK_ENV_NOT_CLOSED(self);
4744
4745 MYDB_BEGIN_ALLOW_THREADS;
4746 err = self->db_env->lsn_reset(self->db_env, file, flags);
4747 MYDB_END_ALLOW_THREADS;
4748 RETURN_IF_ERR();
4749 RETURN_NONE();
4750}
4751#endif /* DBVER >= 4.4 */
4752
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004753static PyObject*
4754DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4755{
4756 int err;
4757 DB_LOG_STAT* statp = NULL;
4758 PyObject* d = NULL;
4759 u_int32_t flags = 0;
4760
4761 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4762 return NULL;
4763 CHECK_ENV_NOT_CLOSED(self);
4764
4765 MYDB_BEGIN_ALLOW_THREADS;
4766 err = self->db_env->log_stat(self->db_env, &statp, flags);
4767 MYDB_END_ALLOW_THREADS;
4768 RETURN_IF_ERR();
4769
4770 /* Turn the stat structure into a dictionary */
4771 d = PyDict_New();
4772 if (d == NULL) {
4773 if (statp)
4774 free(statp);
4775 return NULL;
4776 }
4777
4778#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4779
4780 MAKE_ENTRY(magic);
4781 MAKE_ENTRY(version);
4782 MAKE_ENTRY(mode);
4783 MAKE_ENTRY(lg_bsize);
4784#if (DBVER >= 44)
4785 MAKE_ENTRY(lg_size);
4786 MAKE_ENTRY(record);
4787#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004788#if (DBVER < 41)
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004789 MAKE_ENTRY(lg_max);
4790#endif
4791 MAKE_ENTRY(w_mbytes);
4792 MAKE_ENTRY(w_bytes);
4793 MAKE_ENTRY(wc_mbytes);
4794 MAKE_ENTRY(wc_bytes);
4795 MAKE_ENTRY(wcount);
4796 MAKE_ENTRY(wcount_fill);
4797#if (DBVER >= 44)
4798 MAKE_ENTRY(rcount);
4799#endif
4800 MAKE_ENTRY(scount);
4801 MAKE_ENTRY(cur_file);
4802 MAKE_ENTRY(cur_offset);
4803 MAKE_ENTRY(disk_file);
4804 MAKE_ENTRY(disk_offset);
4805 MAKE_ENTRY(maxcommitperflush);
4806 MAKE_ENTRY(mincommitperflush);
4807 MAKE_ENTRY(regsize);
4808 MAKE_ENTRY(region_wait);
4809 MAKE_ENTRY(region_nowait);
4810
4811#undef MAKE_ENTRY
4812 free(statp);
4813 return d;
4814} /* DBEnv_log_stat */
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004815
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004816
4817static PyObject*
4818DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4819{
4820 int err;
4821 DB_LOCK_STAT* sp;
4822 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004823 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004824
4825 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4826 return NULL;
4827 CHECK_ENV_NOT_CLOSED(self);
4828
4829 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004830 err = self->db_env->lock_stat(self->db_env, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004831 MYDB_END_ALLOW_THREADS;
4832 RETURN_IF_ERR();
4833
4834 /* Turn the stat structure into a dictionary */
4835 d = PyDict_New();
4836 if (d == NULL) {
4837 free(sp);
4838 return NULL;
4839 }
4840
4841#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4842
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004843#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004844 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004845#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004846#if (DBVER >=41)
4847 MAKE_ENTRY(id);
4848 MAKE_ENTRY(cur_maxid);
4849#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004850 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004851 MAKE_ENTRY(maxlocks);
4852 MAKE_ENTRY(maxlockers);
4853 MAKE_ENTRY(maxobjects);
4854 MAKE_ENTRY(nlocks);
4855 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004856 MAKE_ENTRY(nlockers);
4857 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004858 MAKE_ENTRY(nobjects);
4859 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004860 MAKE_ENTRY(nrequests);
4861 MAKE_ENTRY(nreleases);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004862#if (DBVER >= 44)
4863 MAKE_ENTRY(nupgrade);
4864 MAKE_ENTRY(ndowngrade);
4865#endif
Gregory P. Smith29602d22006-01-24 09:46:48 +00004866#if (DBVER < 44)
4867 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004868 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004869#else
4870 MAKE_ENTRY(lock_nowait);
4871 MAKE_ENTRY(lock_wait);
4872#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004873 MAKE_ENTRY(ndeadlocks);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004874#if (DBVER >= 41)
4875 MAKE_ENTRY(locktimeout);
4876 MAKE_ENTRY(txntimeout);
4877#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004878 MAKE_ENTRY(nlocktimeouts);
4879 MAKE_ENTRY(ntxntimeouts);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004880#if (DBVER >= 46)
4881 MAKE_ENTRY(objs_wait);
4882 MAKE_ENTRY(objs_nowait);
4883 MAKE_ENTRY(lockers_wait);
4884 MAKE_ENTRY(lockers_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004885#if (DBVER >= 47)
4886 MAKE_ENTRY(lock_wait);
4887 MAKE_ENTRY(lock_nowait);
4888#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00004889 MAKE_ENTRY(locks_wait);
4890 MAKE_ENTRY(locks_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004891#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004892 MAKE_ENTRY(hash_len);
4893#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004894 MAKE_ENTRY(regsize);
4895 MAKE_ENTRY(region_wait);
4896 MAKE_ENTRY(region_nowait);
4897
4898#undef MAKE_ENTRY
4899 free(sp);
4900 return d;
4901}
4902
Jesus Ceaef9764f2008-05-13 18:45:46 +00004903static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004904DBEnv_log_flush(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004905{
4906 int err;
4907
Jesus Ceaef9764f2008-05-13 18:45:46 +00004908 CHECK_ENV_NOT_CLOSED(self);
4909
4910 MYDB_BEGIN_ALLOW_THREADS
4911 err = self->db_env->log_flush(self->db_env, NULL);
4912 MYDB_END_ALLOW_THREADS
4913
4914 RETURN_IF_ERR();
4915 RETURN_NONE();
4916}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004917
4918static PyObject*
4919DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4920{
4921 int flags=0;
4922 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004923 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004924 PyObject* list;
4925 PyObject* item = NULL;
4926
4927 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4928 return NULL;
4929
4930 CHECK_ENV_NOT_CLOSED(self);
4931 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004932 err = self->db_env->log_archive(self->db_env, &log_list, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004933 MYDB_END_ALLOW_THREADS;
4934 RETURN_IF_ERR();
4935
Gregory P. Smithbad47452006-06-05 00:33:35 +00004936 list = PyList_New(0);
4937 if (list == NULL) {
4938 if (log_list)
4939 free(log_list);
4940 return NULL;
4941 }
4942
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004943 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004944 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004945 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Christian Heimes593daf52008-05-26 12:51:38 +00004946 item = PyBytes_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004947 if (item == NULL) {
4948 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004949 list = NULL;
4950 break;
4951 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004952 if (PyList_Append(list, item)) {
4953 Py_DECREF(list);
4954 list = NULL;
4955 Py_DECREF(item);
4956 break;
4957 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004958 Py_DECREF(item);
4959 }
4960 free(log_list_start);
4961 }
4962 return list;
4963}
4964
4965
4966static PyObject*
4967DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4968{
4969 int err;
4970 DB_TXN_STAT* sp;
4971 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004972 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004973
4974 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4975 return NULL;
4976 CHECK_ENV_NOT_CLOSED(self);
4977
4978 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004979 err = self->db_env->txn_stat(self->db_env, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004980 MYDB_END_ALLOW_THREADS;
4981 RETURN_IF_ERR();
4982
4983 /* Turn the stat structure into a dictionary */
4984 d = PyDict_New();
4985 if (d == NULL) {
4986 free(sp);
4987 return NULL;
4988 }
4989
Jesus Ceaef9764f2008-05-13 18:45:46 +00004990#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4991#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4992#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004993
Jesus Ceaef9764f2008-05-13 18:45:46 +00004994 MAKE_DB_LSN_ENTRY(last_ckp);
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004995 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004996 MAKE_ENTRY(last_txnid);
4997 MAKE_ENTRY(maxtxns);
4998 MAKE_ENTRY(nactive);
4999 MAKE_ENTRY(maxnactive);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005000#if (DBVER >= 45)
5001 MAKE_ENTRY(nsnapshot);
5002 MAKE_ENTRY(maxnsnapshot);
5003#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005004 MAKE_ENTRY(nbegins);
5005 MAKE_ENTRY(naborts);
5006 MAKE_ENTRY(ncommits);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005007 MAKE_ENTRY(nrestores);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005008 MAKE_ENTRY(regsize);
5009 MAKE_ENTRY(region_wait);
5010 MAKE_ENTRY(region_nowait);
5011
Jesus Ceaef9764f2008-05-13 18:45:46 +00005012#undef MAKE_DB_LSN_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005013#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00005014#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005015 free(sp);
5016 return d;
5017}
5018
5019
5020static PyObject*
5021DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
5022{
5023 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005024 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005025
5026 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
5027 return NULL;
5028 CHECK_ENV_NOT_CLOSED(self);
5029
Gregory P. Smith455d46f2003-07-09 04:45:59 +00005030 if (self->moduleFlags.getReturnsNone)
5031 ++oldValue;
5032 if (self->moduleFlags.cursorSetReturnsNone)
5033 ++oldValue;
5034 self->moduleFlags.getReturnsNone = (flags >= 1);
5035 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005036 return NUMBER_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005037}
5038
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005039static PyObject*
5040DBEnv_get_private(DBEnvObject* self)
5041{
5042 /* We can give out the private field even if dbenv is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00005043 Py_INCREF(self->private_obj);
5044 return self->private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005045}
5046
5047static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00005048DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005049{
5050 /* We can set the private field even if dbenv is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00005051 Py_DECREF(self->private_obj);
5052 Py_INCREF(private_obj);
5053 self->private_obj = private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005054 RETURN_NONE();
5055}
5056
5057
Matthias Klose54cc5392010-03-15 12:46:18 +00005058#if (DBVER < 48)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005059static PyObject*
Jesus Ceaca3939c2008-05-22 15:27:38 +00005060DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5061{
5062 int err;
5063 char *host;
5064 long cl_timeout=0, sv_timeout=0;
5065
5066 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
5067
5068 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
5069 &host, &cl_timeout, &sv_timeout))
5070 return NULL;
5071 CHECK_ENV_NOT_CLOSED(self);
5072
5073 MYDB_BEGIN_ALLOW_THREADS;
5074 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
5075 sv_timeout, 0);
5076 MYDB_END_ALLOW_THREADS;
5077 RETURN_IF_ERR();
5078 RETURN_NONE();
5079}
Matthias Klose54cc5392010-03-15 12:46:18 +00005080#endif
Jesus Ceaca3939c2008-05-22 15:27:38 +00005081
Jesus Ceaca3939c2008-05-22 15:27:38 +00005082static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005083DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
5084{
5085 int err;
5086 int which, onoff;
5087
5088 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
5089 return NULL;
5090 }
5091 CHECK_ENV_NOT_CLOSED(self);
5092 MYDB_BEGIN_ALLOW_THREADS;
5093 err = self->db_env->set_verbose(self->db_env, which, onoff);
5094 MYDB_END_ALLOW_THREADS;
5095 RETURN_IF_ERR();
5096 RETURN_NONE();
5097}
5098
5099#if (DBVER >= 42)
5100static PyObject*
5101DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
5102{
5103 int err;
5104 int which;
5105 int verbose;
5106
5107 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
5108 return NULL;
5109 }
5110 CHECK_ENV_NOT_CLOSED(self);
5111 MYDB_BEGIN_ALLOW_THREADS;
5112 err = self->db_env->get_verbose(self->db_env, which, &verbose);
5113 MYDB_END_ALLOW_THREADS;
5114 RETURN_IF_ERR();
5115 return PyBool_FromLong(verbose);
5116}
5117#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005118
5119#if (DBVER >= 45)
5120static void
5121_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
5122{
5123 DBEnvObject *dbenv;
5124 PyObject* callback;
5125 PyObject* args;
5126 PyObject* result = NULL;
5127
5128 MYDB_BEGIN_BLOCK_THREADS;
5129 dbenv = (DBEnvObject *)db_env->app_private;
5130 callback = dbenv->event_notifyCallback;
5131 if (callback) {
5132 if (event == DB_EVENT_REP_NEWMASTER) {
5133 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
5134 } else {
5135 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5136 }
5137 if (args) {
5138 result = PyEval_CallObject(callback, args);
5139 }
5140 if ((!args) || (!result)) {
5141 PyErr_Print();
5142 }
5143 Py_XDECREF(args);
5144 Py_XDECREF(result);
5145 }
5146 MYDB_END_BLOCK_THREADS;
5147}
5148#endif
5149
5150#if (DBVER >= 45)
5151static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005152DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005153{
5154 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005155
5156 CHECK_ENV_NOT_CLOSED(self);
5157
5158 if (!PyCallable_Check(notifyFunc)) {
5159 makeTypeError("Callable", notifyFunc);
5160 return NULL;
5161 }
5162
5163 Py_XDECREF(self->event_notifyCallback);
5164 Py_INCREF(notifyFunc);
5165 self->event_notifyCallback = notifyFunc;
5166
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005167 /* This is to workaround a problem with un-initialized threads (see
5168 comment in DB_associate) */
5169#ifdef WITH_THREAD
5170 PyEval_InitThreads();
5171#endif
5172
Jesus Ceaef9764f2008-05-13 18:45:46 +00005173 MYDB_BEGIN_ALLOW_THREADS;
5174 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5175 MYDB_END_ALLOW_THREADS;
5176
5177 if (err) {
5178 Py_DECREF(notifyFunc);
5179 self->event_notifyCallback = NULL;
5180 }
5181
5182 RETURN_IF_ERR();
5183 RETURN_NONE();
5184}
5185#endif
5186
5187
5188/* --------------------------------------------------------------------- */
5189/* REPLICATION METHODS: Base Replication */
5190
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005191
5192static PyObject*
5193DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
5194{
5195 int err;
5196 PyObject *control_py, *rec_py;
5197 DBT control, rec;
5198 int envid;
5199#if (DBVER >= 42)
5200 DB_LSN lsn;
5201#endif
5202
5203 if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
5204 &rec_py, &envid))
5205 return NULL;
5206 CHECK_ENV_NOT_CLOSED(self);
5207
5208 if (!make_dbt(control_py, &control))
5209 return NULL;
5210 if (!make_dbt(rec_py, &rec))
5211 return NULL;
5212
5213 MYDB_BEGIN_ALLOW_THREADS;
5214#if (DBVER >= 46)
5215 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5216 envid, &lsn);
5217#else
5218#if (DBVER >= 42)
5219 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5220 &envid, &lsn);
5221#else
5222 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5223 &envid);
5224#endif
5225#endif
5226 MYDB_END_ALLOW_THREADS;
5227 switch (err) {
5228 case DB_REP_NEWMASTER :
5229 return Py_BuildValue("(iO)", envid, Py_None);
5230 break;
5231
5232 case DB_REP_DUPMASTER :
5233 case DB_REP_HOLDELECTION :
5234#if (DBVER >= 44)
5235 case DB_REP_IGNORE :
5236 case DB_REP_JOIN_FAILURE :
5237#endif
5238 return Py_BuildValue("(iO)", err, Py_None);
5239 break;
5240 case DB_REP_NEWSITE :
Jesus Cea4907d272008-08-31 14:00:51 +00005241 {
5242 PyObject *tmp, *r;
5243
5244 if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
5245 return NULL;
5246 }
5247
5248 r = Py_BuildValue("(iO)", err, tmp);
5249 Py_DECREF(tmp);
5250 return r;
5251 break;
5252 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005253#if (DBVER >= 42)
5254 case DB_REP_NOTPERM :
5255 case DB_REP_ISPERM :
5256 return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
5257 break;
5258#endif
5259 }
5260 RETURN_IF_ERR();
5261 return Py_BuildValue("(OO)", Py_None, Py_None);
5262}
5263
5264static int
5265_DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
5266 const DB_LSN *lsn, int envid, u_int32_t flags)
5267{
5268 DBEnvObject *dbenv;
5269 PyObject* rep_transport;
5270 PyObject* args;
Jesus Cea4907d272008-08-31 14:00:51 +00005271 PyObject *a, *b;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005272 PyObject* result = NULL;
5273 int ret=0;
5274
5275 MYDB_BEGIN_BLOCK_THREADS;
5276 dbenv = (DBEnvObject *)db_env->app_private;
5277 rep_transport = dbenv->rep_transport;
5278
Jesus Cea4907d272008-08-31 14:00:51 +00005279 /*
5280 ** The errors in 'a' or 'b' are detected in "Py_BuildValue".
5281 */
5282 a = PyBytes_FromStringAndSize(control->data, control->size);
5283 b = PyBytes_FromStringAndSize(rec->data, rec->size);
5284
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005285 args = Py_BuildValue(
5286#if (PY_VERSION_HEX >= 0x02040000)
Jesus Cea4907d272008-08-31 14:00:51 +00005287 "(OOO(ll)iI)",
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005288#else
Jesus Cea4907d272008-08-31 14:00:51 +00005289 "(OOO(ll)ii)",
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005290#endif
5291 dbenv,
Jesus Cea4907d272008-08-31 14:00:51 +00005292 a, b,
5293 lsn->file, lsn->offset, envid, flags);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005294 if (args) {
5295 result = PyEval_CallObject(rep_transport, args);
5296 }
5297
5298 if ((!args) || (!result)) {
5299 PyErr_Print();
5300 ret = -1;
5301 }
Jesus Cea4907d272008-08-31 14:00:51 +00005302 Py_XDECREF(a);
5303 Py_XDECREF(b);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005304 Py_XDECREF(args);
5305 Py_XDECREF(result);
5306 MYDB_END_BLOCK_THREADS;
5307 return ret;
5308}
5309
5310#if (DBVER <= 41)
5311static int
5312_DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec,
5313 int envid, u_int32_t flags)
5314{
5315 DB_LSN lsn;
5316
5317 lsn.file = -1; /* Dummy values */
5318 lsn.offset = -1;
5319 return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid,
5320 flags);
5321}
5322#endif
5323
5324static PyObject*
5325DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
5326{
5327 int err;
5328 int envid;
5329 PyObject *rep_transport;
5330
5331 if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
5332 return NULL;
5333 CHECK_ENV_NOT_CLOSED(self);
5334 if (!PyCallable_Check(rep_transport)) {
5335 makeTypeError("Callable", rep_transport);
5336 return NULL;
5337 }
5338
5339 MYDB_BEGIN_ALLOW_THREADS;
5340#if (DBVER >=45)
5341 err = self->db_env->rep_set_transport(self->db_env, envid,
5342 &_DBEnv_rep_transportCallback);
5343#else
5344#if (DBVER >= 42)
5345 err = self->db_env->set_rep_transport(self->db_env, envid,
5346 &_DBEnv_rep_transportCallback);
5347#else
5348 err = self->db_env->set_rep_transport(self->db_env, envid,
5349 &_DBEnv_rep_transportCallbackOLD);
5350#endif
5351#endif
5352 MYDB_END_ALLOW_THREADS;
5353 RETURN_IF_ERR();
5354
5355 Py_DECREF(self->rep_transport);
5356 Py_INCREF(rep_transport);
5357 self->rep_transport = rep_transport;
5358 RETURN_NONE();
5359}
5360
5361#if (DBVER >= 47)
5362static PyObject*
5363DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
5364{
5365 int err;
5366 unsigned int minimum, maximum;
5367
5368 if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
5369 return NULL;
5370 CHECK_ENV_NOT_CLOSED(self);
5371
5372 MYDB_BEGIN_ALLOW_THREADS;
5373 err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
5374 MYDB_END_ALLOW_THREADS;
5375 RETURN_IF_ERR();
5376 RETURN_NONE();
5377}
5378
5379static PyObject*
5380DBEnv_rep_get_request(DBEnvObject* self)
5381{
5382 int err;
5383 u_int32_t minimum, maximum;
5384
5385 CHECK_ENV_NOT_CLOSED(self);
5386 MYDB_BEGIN_ALLOW_THREADS;
5387 err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
5388 MYDB_END_ALLOW_THREADS;
5389 RETURN_IF_ERR();
5390#if (PY_VERSION_HEX >= 0x02040000)
5391 return Py_BuildValue("II", minimum, maximum);
5392#else
5393 return Py_BuildValue("ii", minimum, maximum);
5394#endif
5395}
5396#endif
5397
5398#if (DBVER >= 45)
5399static PyObject*
5400DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
5401{
5402 int err;
5403 int limit;
5404
5405 if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
5406 return NULL;
5407 CHECK_ENV_NOT_CLOSED(self);
5408
5409 MYDB_BEGIN_ALLOW_THREADS;
5410 err = self->db_env->rep_set_limit(self->db_env, 0, limit);
5411 MYDB_END_ALLOW_THREADS;
5412 RETURN_IF_ERR();
5413 RETURN_NONE();
5414}
5415
5416static PyObject*
5417DBEnv_rep_get_limit(DBEnvObject* self)
5418{
5419 int err;
5420 u_int32_t gbytes, bytes;
5421
5422 CHECK_ENV_NOT_CLOSED(self);
5423 MYDB_BEGIN_ALLOW_THREADS;
5424 err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
5425 MYDB_END_ALLOW_THREADS;
5426 RETURN_IF_ERR();
5427 return NUMBER_FromLong(bytes);
5428}
5429#endif
5430
5431#if (DBVER >= 44)
5432static PyObject*
5433DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
5434{
5435 int err;
5436 int which;
5437 int onoff;
5438
5439 if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
5440 return NULL;
5441 CHECK_ENV_NOT_CLOSED(self);
5442
5443 MYDB_BEGIN_ALLOW_THREADS;
5444 err = self->db_env->rep_set_config(self->db_env, which, onoff);
5445 MYDB_END_ALLOW_THREADS;
5446 RETURN_IF_ERR();
5447 RETURN_NONE();
5448}
5449
5450static PyObject*
5451DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
5452{
5453 int err;
5454 int which;
5455 int onoff;
5456
5457 if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
5458 return NULL;
5459 }
5460 CHECK_ENV_NOT_CLOSED(self);
5461 MYDB_BEGIN_ALLOW_THREADS;
5462 err = self->db_env->rep_get_config(self->db_env, which, &onoff);
5463 MYDB_END_ALLOW_THREADS;
5464 RETURN_IF_ERR();
5465 return PyBool_FromLong(onoff);
5466}
5467#endif
5468
5469#if (DBVER >= 46)
5470static PyObject*
5471DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
5472{
5473 int err;
5474 u_int32_t nsites, nvotes;
5475
5476 if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
5477 return NULL;
5478 }
5479 CHECK_ENV_NOT_CLOSED(self);
5480 MYDB_BEGIN_ALLOW_THREADS;
5481 err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0);
5482 MYDB_END_ALLOW_THREADS;
5483 RETURN_IF_ERR();
5484 RETURN_NONE();
5485}
5486#endif
5487
5488static PyObject*
5489DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5490{
5491 int err;
5492 PyObject *cdata_py = Py_None;
5493 DBT cdata;
5494 int flags;
5495 static char* kwnames[] = {"flags","cdata", NULL};
5496
5497 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5498 "i|O:rep_start", kwnames, &flags, &cdata_py))
5499 {
5500 return NULL;
5501 }
5502 CHECK_ENV_NOT_CLOSED(self);
5503
5504 if (!make_dbt(cdata_py, &cdata))
5505 return NULL;
5506
5507 MYDB_BEGIN_ALLOW_THREADS;
5508 err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
5509 flags);
5510 MYDB_END_ALLOW_THREADS;
5511 RETURN_IF_ERR();
5512 RETURN_NONE();
5513}
5514
5515#if (DBVER >= 44)
5516static PyObject*
5517DBEnv_rep_sync(DBEnvObject* self)
5518{
5519 int err;
5520
5521 CHECK_ENV_NOT_CLOSED(self);
5522 MYDB_BEGIN_ALLOW_THREADS;
5523 err = self->db_env->rep_sync(self->db_env, 0);
5524 MYDB_END_ALLOW_THREADS;
5525 RETURN_IF_ERR();
5526 RETURN_NONE();
5527}
5528#endif
5529
5530
Jesus Ceaef9764f2008-05-13 18:45:46 +00005531#if (DBVER >= 45)
5532static PyObject*
5533DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5534{
5535 int err;
5536 int nsites;
5537
5538 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5539 return NULL;
5540 }
5541 CHECK_ENV_NOT_CLOSED(self);
5542 MYDB_BEGIN_ALLOW_THREADS;
5543 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5544 MYDB_END_ALLOW_THREADS;
5545 RETURN_IF_ERR();
5546 RETURN_NONE();
5547}
5548
5549static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005550DBEnv_rep_get_nsites(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005551{
5552 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005553#if (DBVER >= 47)
5554 u_int32_t nsites;
5555#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005556 int nsites;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005557#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005558
Jesus Ceaef9764f2008-05-13 18:45:46 +00005559 CHECK_ENV_NOT_CLOSED(self);
5560 MYDB_BEGIN_ALLOW_THREADS;
5561 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5562 MYDB_END_ALLOW_THREADS;
5563 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005564 return NUMBER_FromLong(nsites);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005565}
5566
5567static PyObject*
5568DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5569{
5570 int err;
5571 int priority;
5572
5573 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5574 return NULL;
5575 }
5576 CHECK_ENV_NOT_CLOSED(self);
5577 MYDB_BEGIN_ALLOW_THREADS;
5578 err = self->db_env->rep_set_priority(self->db_env, priority);
5579 MYDB_END_ALLOW_THREADS;
5580 RETURN_IF_ERR();
5581 RETURN_NONE();
5582}
5583
5584static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005585DBEnv_rep_get_priority(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005586{
5587 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005588#if (DBVER >= 47)
5589 u_int32_t priority;
5590#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005591 int priority;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005592#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005593
Jesus Ceaef9764f2008-05-13 18:45:46 +00005594 CHECK_ENV_NOT_CLOSED(self);
5595 MYDB_BEGIN_ALLOW_THREADS;
5596 err = self->db_env->rep_get_priority(self->db_env, &priority);
5597 MYDB_END_ALLOW_THREADS;
5598 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005599 return NUMBER_FromLong(priority);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005600}
5601
5602static PyObject*
5603DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5604{
5605 int err;
5606 int which, timeout;
5607
5608 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5609 return NULL;
5610 }
5611 CHECK_ENV_NOT_CLOSED(self);
5612 MYDB_BEGIN_ALLOW_THREADS;
5613 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5614 MYDB_END_ALLOW_THREADS;
5615 RETURN_IF_ERR();
5616 RETURN_NONE();
5617}
5618
5619static PyObject*
5620DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5621{
5622 int err;
5623 int which;
5624 u_int32_t timeout;
5625
5626 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5627 return NULL;
5628 }
5629 CHECK_ENV_NOT_CLOSED(self);
5630 MYDB_BEGIN_ALLOW_THREADS;
5631 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5632 MYDB_END_ALLOW_THREADS;
5633 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005634 return NUMBER_FromLong(timeout);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005635}
5636#endif
5637
5638/* --------------------------------------------------------------------- */
5639/* REPLICATION METHODS: Replication Manager */
5640
5641#if (DBVER >= 45)
5642static PyObject*
5643DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5644 kwargs)
5645{
5646 int err;
5647 int nthreads, flags;
5648 static char* kwnames[] = {"nthreads","flags", NULL};
5649
5650 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5651 "ii:repmgr_start", kwnames, &nthreads, &flags))
5652 {
5653 return NULL;
5654 }
5655 CHECK_ENV_NOT_CLOSED(self);
5656 MYDB_BEGIN_ALLOW_THREADS;
5657 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5658 MYDB_END_ALLOW_THREADS;
5659 RETURN_IF_ERR();
5660 RETURN_NONE();
5661}
5662
5663static PyObject*
5664DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5665 kwargs)
5666{
5667 int err;
5668 char *host;
5669 int port;
5670 int flags = 0;
5671 static char* kwnames[] = {"host", "port", "flags", NULL};
5672
5673 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5674 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5675 {
5676 return NULL;
5677 }
5678 CHECK_ENV_NOT_CLOSED(self);
5679 MYDB_BEGIN_ALLOW_THREADS;
5680 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5681 MYDB_END_ALLOW_THREADS;
5682 RETURN_IF_ERR();
5683 RETURN_NONE();
5684}
5685
5686static PyObject*
5687DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5688 kwargs)
5689{
5690 int err;
5691 char *host;
5692 int port;
5693 int flags = 0;
5694 int eidp;
5695 static char* kwnames[] = {"host", "port", "flags", NULL};
5696
5697 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5698 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5699 {
5700 return NULL;
5701 }
5702 CHECK_ENV_NOT_CLOSED(self);
5703 MYDB_BEGIN_ALLOW_THREADS;
5704 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5705 MYDB_END_ALLOW_THREADS;
5706 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005707 return NUMBER_FromLong(eidp);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005708}
5709
5710static PyObject*
5711DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5712{
5713 int err;
5714 int ack_policy;
5715
5716 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5717 {
5718 return NULL;
5719 }
5720 CHECK_ENV_NOT_CLOSED(self);
5721 MYDB_BEGIN_ALLOW_THREADS;
5722 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5723 MYDB_END_ALLOW_THREADS;
5724 RETURN_IF_ERR();
5725 RETURN_NONE();
5726}
5727
5728static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005729DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005730{
5731 int err;
5732 int ack_policy;
5733
Jesus Ceaef9764f2008-05-13 18:45:46 +00005734 CHECK_ENV_NOT_CLOSED(self);
5735 MYDB_BEGIN_ALLOW_THREADS;
5736 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5737 MYDB_END_ALLOW_THREADS;
5738 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005739 return NUMBER_FromLong(ack_policy);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005740}
5741
5742static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005743DBEnv_repmgr_site_list(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005744{
5745 int err;
5746 unsigned int countp;
5747 DB_REPMGR_SITE *listp;
5748 PyObject *stats, *key, *tuple;
5749
Jesus Ceaef9764f2008-05-13 18:45:46 +00005750 CHECK_ENV_NOT_CLOSED(self);
5751 MYDB_BEGIN_ALLOW_THREADS;
5752 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5753 MYDB_END_ALLOW_THREADS;
5754 RETURN_IF_ERR();
5755
5756 stats=PyDict_New();
5757 if (stats == NULL) {
5758 free(listp);
5759 return NULL;
5760 }
5761
5762 for(;countp--;) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005763 key=NUMBER_FromLong(listp[countp].eid);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005764 if(!key) {
5765 Py_DECREF(stats);
5766 free(listp);
5767 return NULL;
5768 }
5769#if (PY_VERSION_HEX >= 0x02040000)
5770 tuple=Py_BuildValue("(sII)", listp[countp].host,
5771 listp[countp].port, listp[countp].status);
5772#else
5773 tuple=Py_BuildValue("(sii)", listp[countp].host,
5774 listp[countp].port, listp[countp].status);
5775#endif
5776 if(!tuple) {
5777 Py_DECREF(key);
5778 Py_DECREF(stats);
5779 free(listp);
5780 return NULL;
5781 }
5782 if(PyDict_SetItem(stats, key, tuple)) {
5783 Py_DECREF(key);
5784 Py_DECREF(tuple);
5785 Py_DECREF(stats);
5786 free(listp);
5787 return NULL;
5788 }
Florent Xiclunae7901c52010-03-01 20:45:01 +00005789 Py_DECREF(key);
5790 Py_DECREF(tuple);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005791 }
5792 free(listp);
5793 return stats;
5794}
5795#endif
5796
5797#if (DBVER >= 46)
5798static PyObject*
5799DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5800{
5801 int err;
5802 int flags=0;
5803 static char* kwnames[] = { "flags", NULL };
5804
5805 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5806 kwnames, &flags))
5807 {
5808 return NULL;
5809 }
5810 CHECK_ENV_NOT_CLOSED(self);
5811 MYDB_BEGIN_ALLOW_THREADS;
5812 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5813 MYDB_END_ALLOW_THREADS;
5814 RETURN_IF_ERR();
5815 RETURN_NONE();
5816}
5817
5818static PyObject*
5819DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5820{
5821 int err;
5822 int flags=0;
5823 DB_REPMGR_STAT *statp;
5824 PyObject *stats;
5825 static char* kwnames[] = { "flags", NULL };
5826
5827 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5828 kwnames, &flags))
5829 {
5830 return NULL;
5831 }
5832 CHECK_ENV_NOT_CLOSED(self);
5833 MYDB_BEGIN_ALLOW_THREADS;
5834 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5835 MYDB_END_ALLOW_THREADS;
5836 RETURN_IF_ERR();
5837
5838 stats=PyDict_New();
5839 if (stats == NULL) {
5840 free(statp);
5841 return NULL;
5842 }
5843
5844#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5845
5846 MAKE_ENTRY(perm_failed);
5847 MAKE_ENTRY(msgs_queued);
5848 MAKE_ENTRY(msgs_dropped);
5849 MAKE_ENTRY(connection_drop);
5850 MAKE_ENTRY(connect_fail);
5851
5852#undef MAKE_ENTRY
5853
5854 free(statp);
5855 return stats;
5856}
5857#endif
5858
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005859
5860/* --------------------------------------------------------------------- */
5861/* DBTxn methods */
5862
5863
Jesus Ceaef9764f2008-05-13 18:45:46 +00005864static void _close_transaction_cursors(DBTxnObject* txn)
5865{
5866 PyObject *dummy;
5867
5868 while(txn->children_cursors) {
5869 PyErr_Warn(PyExc_RuntimeWarning,
5870 "Must close cursors before resolving a transaction.");
5871 dummy=DBC_close_internal(txn->children_cursors);
5872 Py_XDECREF(dummy);
5873 }
5874}
5875
5876static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5877{
5878 DBObject *db;
5879#if (DBVER >= 43)
5880 DBSequenceObject *dbs;
5881#endif
5882
5883 while (txn->children_dbs) {
5884 db=txn->children_dbs;
5885 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5886 if (txn->parent_txn) {
5887 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5888 db->txn=txn->parent_txn;
5889 } else {
5890 /* The db is already linked to its environment,
5891 ** so nothing to do.
5892 */
5893 db->txn=NULL;
5894 }
5895 }
5896
5897#if (DBVER >= 43)
5898 while (txn->children_sequences) {
5899 dbs=txn->children_sequences;
5900 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5901 if (txn->parent_txn) {
5902 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5903 dbs->txn=txn->parent_txn;
5904 } else {
5905 /* The sequence is already linked to its
5906 ** parent db. Nothing to do.
5907 */
5908 dbs->txn=NULL;
5909 }
5910 }
5911#endif
5912}
5913
5914
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005915static PyObject*
5916DBTxn_commit(DBTxnObject* self, PyObject* args)
5917{
5918 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005919 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005920
5921 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5922 return NULL;
5923
Jesus Ceaef9764f2008-05-13 18:45:46 +00005924 _close_transaction_cursors(self);
5925
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005926 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005927 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005928 "after txn_commit, txn_abort "
5929 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005930 if (t) {
5931 PyErr_SetObject(DBError, t);
5932 Py_DECREF(t);
5933 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005934 return NULL;
5935 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005936 self->flag_prepare=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005937 txn = self->txn;
5938 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005939
5940 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5941
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005942 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005943 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005944 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005945
5946 _promote_transaction_dbs_and_sequences(self);
5947
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005948 RETURN_IF_ERR();
5949 RETURN_NONE();
5950}
5951
5952static PyObject*
5953DBTxn_prepare(DBTxnObject* self, PyObject* args)
5954{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005955 int err;
5956 char* gid=NULL;
5957 int gid_size=0;
5958
5959 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
5960 return NULL;
5961
Matthias Klose54cc5392010-03-15 12:46:18 +00005962 if (gid_size != DB_GID_SIZE) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005963 PyErr_SetString(PyExc_TypeError,
Matthias Klose54cc5392010-03-15 12:46:18 +00005964 "gid must be DB_GID_SIZE bytes long");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005965 return NULL;
5966 }
5967
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005968 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005969 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005970 "after txn_commit, txn_abort "
5971 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005972 if (t) {
5973 PyErr_SetObject(DBError, t);
5974 Py_DECREF(t);
5975 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005976 return NULL;
5977 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005978 self->flag_prepare=1; /* Prepare state */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005979 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005980 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005981 MYDB_END_ALLOW_THREADS;
5982 RETURN_IF_ERR();
5983 RETURN_NONE();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005984}
5985
5986
5987static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005988DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005989{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005990 PyObject *dummy;
5991 int err=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005992 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005993
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005994 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005995 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005996 "after txn_commit, txn_abort "
5997 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005998 if (t) {
5999 PyErr_SetObject(DBError, t);
6000 Py_DECREF(t);
6001 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00006002 return NULL;
6003 }
6004 txn = self->txn;
6005 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00006006
6007 _close_transaction_cursors(self);
6008#if (DBVER >= 43)
6009 while (self->children_sequences) {
6010 dummy=DBSequence_close_internal(self->children_sequences,0,0);
6011 Py_XDECREF(dummy);
6012 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006013#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00006014 while (self->children_dbs) {
Jesus Cea5cd5f122008-09-23 18:54:08 +00006015 dummy=DB_close_internal(self->children_dbs, 0, 0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006016 Py_XDECREF(dummy);
6017 }
6018
6019 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
6020
6021 MYDB_BEGIN_ALLOW_THREADS;
6022 if (discard) {
6023 assert(!self->flag_prepare);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006024 err = txn->discard(txn,0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006025 } else {
6026 /*
6027 ** If the transaction is in the "prepare" or "recover" state,
6028 ** we better do not implicitly abort it.
6029 */
6030 if (!self->flag_prepare) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00006031 err = txn->abort(txn);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006032 }
6033 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006034 MYDB_END_ALLOW_THREADS;
6035 RETURN_IF_ERR();
6036 RETURN_NONE();
6037}
6038
Jesus Ceaef9764f2008-05-13 18:45:46 +00006039static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006040DBTxn_abort(DBTxnObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006041{
Jesus Ceaef9764f2008-05-13 18:45:46 +00006042 self->flag_prepare=0;
6043 _close_transaction_cursors(self);
6044
6045 return DBTxn_abort_discard_internal(self,0);
6046}
6047
6048static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006049DBTxn_discard(DBTxnObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006050{
Jesus Ceaef9764f2008-05-13 18:45:46 +00006051 self->flag_prepare=0;
6052 _close_transaction_cursors(self);
6053
6054 return DBTxn_abort_discard_internal(self,1);
6055}
6056
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006057
6058static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006059DBTxn_id(DBTxnObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006060{
6061 int id;
6062
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00006063 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00006064 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00006065 "after txn_commit, txn_abort "
6066 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006067 if (t) {
6068 PyErr_SetObject(DBError, t);
6069 Py_DECREF(t);
6070 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00006071 return NULL;
6072 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006073 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006074 id = self->txn->id(self->txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006075 MYDB_END_ALLOW_THREADS;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006076 return NUMBER_FromLong(id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006077}
6078
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006079#if (DBVER >= 43)
6080/* --------------------------------------------------------------------- */
6081/* DBSequence methods */
6082
6083
6084static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00006085DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006086{
Jesus Ceaef9764f2008-05-13 18:45:46 +00006087 int err=0;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006088
Jesus Ceaef9764f2008-05-13 18:45:46 +00006089 if (self->sequence!=NULL) {
6090 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
6091 if (self->txn) {
6092 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
6093 self->txn=NULL;
6094 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006095
Jesus Cea5cd5f122008-09-23 18:54:08 +00006096 /*
6097 ** "do_not_close" is used to dispose all related objects in the
6098 ** tree, without actually releasing the "root" object.
6099 ** This is done, for example, because function calls like
6100 ** "DBSequence.remove()" implicitly close the underlying handle. So
6101 ** the handle doesn't need to be closed, but related objects
6102 ** must be cleaned up.
6103 */
Jesus Ceaef9764f2008-05-13 18:45:46 +00006104 if (!do_not_close) {
6105 MYDB_BEGIN_ALLOW_THREADS
6106 err = self->sequence->close(self->sequence, flags);
6107 MYDB_END_ALLOW_THREADS
6108 }
6109 self->sequence = NULL;
6110
6111 RETURN_IF_ERR();
6112 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006113
6114 RETURN_NONE();
6115}
6116
6117static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00006118DBSequence_close(DBSequenceObject* self, PyObject* args)
6119{
6120 int flags=0;
6121 if (!PyArg_ParseTuple(args,"|i:close", &flags))
6122 return NULL;
6123
6124 return DBSequence_close_internal(self,flags,0);
6125}
6126
6127static PyObject*
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006128DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6129{
6130 int err, flags = 0;
6131 int delta = 1;
6132 db_seq_t value;
6133 PyObject *txnobj = NULL;
6134 DB_TXN *txn = NULL;
6135 static char* kwnames[] = {"delta", "txn", "flags", NULL };
6136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
6137 return NULL;
6138 CHECK_SEQUENCE_NOT_CLOSED(self)
6139
6140 if (!checkTxnObj(txnobj, &txn))
6141 return NULL;
6142
6143 MYDB_BEGIN_ALLOW_THREADS
6144 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
6145 MYDB_END_ALLOW_THREADS
6146
6147 RETURN_IF_ERR();
6148 return PyLong_FromLongLong(value);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006149}
6150
6151static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006152DBSequence_get_dbp(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006153{
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006154 CHECK_SEQUENCE_NOT_CLOSED(self)
6155 Py_INCREF(self->mydb);
6156 return (PyObject* )self->mydb;
6157}
6158
6159static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006160DBSequence_get_key(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006161{
6162 int err;
6163 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00006164 PyObject *retval = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006165
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006166 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006167 CHECK_SEQUENCE_NOT_CLOSED(self)
6168 MYDB_BEGIN_ALLOW_THREADS
6169 err = self->sequence->get_key(self->sequence, &key);
6170 MYDB_END_ALLOW_THREADS
6171
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006172 if (!err)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006173 retval = Build_PyString(key.data, key.size);
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006174
6175 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006176 RETURN_IF_ERR();
6177
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006178 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006179}
6180
6181static PyObject*
6182DBSequence_init_value(DBSequenceObject* self, PyObject* args)
6183{
6184 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006185 PY_LONG_LONG value;
6186 db_seq_t value2;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006187 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006188 return NULL;
6189 CHECK_SEQUENCE_NOT_CLOSED(self)
6190
Jesus Ceaef9764f2008-05-13 18:45:46 +00006191 value2=value; /* If truncation, compiler should show a warning */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006192 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006193 err = self->sequence->initial_value(self->sequence, value2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006194 MYDB_END_ALLOW_THREADS
6195
6196 RETURN_IF_ERR();
6197
6198 RETURN_NONE();
6199}
6200
6201static PyObject*
6202DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6203{
6204 int err, flags = 0;
6205 PyObject* keyobj;
6206 PyObject *txnobj = NULL;
6207 DB_TXN *txn = NULL;
6208 DBT key;
6209
6210 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006211 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006212 return NULL;
6213
6214 if (!checkTxnObj(txnobj, &txn))
6215 return NULL;
6216
6217 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
6218 return NULL;
6219
6220 MYDB_BEGIN_ALLOW_THREADS
6221 err = self->sequence->open(self->sequence, txn, &key, flags);
6222 MYDB_END_ALLOW_THREADS
6223
Jesus Ceaac25fab2008-09-03 17:50:32 +00006224 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006225 RETURN_IF_ERR();
6226
Jesus Ceaef9764f2008-05-13 18:45:46 +00006227 if (txn) {
6228 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
6229 self->txn=(DBTxnObject *)txnobj;
6230 }
6231
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006232 RETURN_NONE();
6233}
6234
6235static PyObject*
6236DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6237{
Jesus Ceaef9764f2008-05-13 18:45:46 +00006238 PyObject *dummy;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006239 int err, flags = 0;
6240 PyObject *txnobj = NULL;
6241 DB_TXN *txn = NULL;
6242
6243 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006244 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006245 return NULL;
6246
6247 if (!checkTxnObj(txnobj, &txn))
6248 return NULL;
6249
6250 CHECK_SEQUENCE_NOT_CLOSED(self)
6251
6252 MYDB_BEGIN_ALLOW_THREADS
6253 err = self->sequence->remove(self->sequence, txn, flags);
6254 MYDB_END_ALLOW_THREADS
6255
Jesus Ceaef9764f2008-05-13 18:45:46 +00006256 dummy=DBSequence_close_internal(self,flags,1);
6257 Py_XDECREF(dummy);
6258
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006259 RETURN_IF_ERR();
6260 RETURN_NONE();
6261}
6262
6263static PyObject*
6264DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
6265{
6266 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006267 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006268 return NULL;
6269 CHECK_SEQUENCE_NOT_CLOSED(self)
6270
6271 MYDB_BEGIN_ALLOW_THREADS
6272 err = self->sequence->set_cachesize(self->sequence, size);
6273 MYDB_END_ALLOW_THREADS
6274
6275 RETURN_IF_ERR();
6276 RETURN_NONE();
6277}
6278
6279static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006280DBSequence_get_cachesize(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006281{
6282 int err, size;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006283
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006284 CHECK_SEQUENCE_NOT_CLOSED(self)
6285
6286 MYDB_BEGIN_ALLOW_THREADS
6287 err = self->sequence->get_cachesize(self->sequence, &size);
6288 MYDB_END_ALLOW_THREADS
6289
6290 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006291 return NUMBER_FromLong(size);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006292}
6293
6294static PyObject*
6295DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
6296{
6297 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006298 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006299 return NULL;
6300 CHECK_SEQUENCE_NOT_CLOSED(self)
6301
6302 MYDB_BEGIN_ALLOW_THREADS
6303 err = self->sequence->set_flags(self->sequence, flags);
6304 MYDB_END_ALLOW_THREADS
6305
6306 RETURN_IF_ERR();
6307 RETURN_NONE();
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006308}
6309
6310static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006311DBSequence_get_flags(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006312{
6313 unsigned int flags;
6314 int err;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006315
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006316 CHECK_SEQUENCE_NOT_CLOSED(self)
6317
6318 MYDB_BEGIN_ALLOW_THREADS
6319 err = self->sequence->get_flags(self->sequence, &flags);
6320 MYDB_END_ALLOW_THREADS
6321
6322 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006323 return NUMBER_FromLong((int)flags);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006324}
6325
6326static PyObject*
6327DBSequence_set_range(DBSequenceObject* self, PyObject* args)
6328{
6329 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006330 PY_LONG_LONG min, max;
6331 db_seq_t min2, max2;
Tim Petersbb21b2c2006-06-06 15:50:17 +00006332 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006333 return NULL;
6334 CHECK_SEQUENCE_NOT_CLOSED(self)
6335
Jesus Ceaef9764f2008-05-13 18:45:46 +00006336 min2=min; /* If truncation, compiler should show a warning */
6337 max2=max;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006338 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006339 err = self->sequence->set_range(self->sequence, min2, max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006340 MYDB_END_ALLOW_THREADS
6341
6342 RETURN_IF_ERR();
6343 RETURN_NONE();
6344}
6345
6346static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006347DBSequence_get_range(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006348{
6349 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006350 PY_LONG_LONG min, max;
6351 db_seq_t min2, max2;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006352
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006353 CHECK_SEQUENCE_NOT_CLOSED(self)
6354
6355 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006356 err = self->sequence->get_range(self->sequence, &min2, &max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006357 MYDB_END_ALLOW_THREADS
6358
6359 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00006360 min=min2; /* If truncation, compiler should show a warning */
6361 max=max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006362 return Py_BuildValue("(LL)", min, max);
6363}
6364
6365static PyObject*
6366DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6367{
6368 int err, flags = 0;
6369 DB_SEQUENCE_STAT* sp = NULL;
6370 PyObject* dict_stat;
6371 static char* kwnames[] = {"flags", NULL };
6372 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
6373 return NULL;
6374 CHECK_SEQUENCE_NOT_CLOSED(self);
6375
6376 MYDB_BEGIN_ALLOW_THREADS;
6377 err = self->sequence->stat(self->sequence, &sp, flags);
6378 MYDB_END_ALLOW_THREADS;
6379 RETURN_IF_ERR();
6380
6381 if ((dict_stat = PyDict_New()) == NULL) {
6382 free(sp);
6383 return NULL;
6384 }
6385
6386
6387#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
6388#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
6389
6390 MAKE_INT_ENTRY(wait);
6391 MAKE_INT_ENTRY(nowait);
6392 MAKE_LONG_LONG_ENTRY(current);
6393 MAKE_LONG_LONG_ENTRY(value);
6394 MAKE_LONG_LONG_ENTRY(last_value);
6395 MAKE_LONG_LONG_ENTRY(min);
6396 MAKE_LONG_LONG_ENTRY(max);
6397 MAKE_INT_ENTRY(cache_size);
6398 MAKE_INT_ENTRY(flags);
6399
6400#undef MAKE_INT_ENTRY
6401#undef MAKE_LONG_LONG_ENTRY
6402
6403 free(sp);
6404 return dict_stat;
6405}
6406#endif
6407
6408
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006409/* --------------------------------------------------------------------- */
6410/* Method definition tables and type objects */
6411
6412static PyMethodDef DB_methods[] = {
Jesus Cea4907d272008-08-31 14:00:51 +00006413 {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006414 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006415 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006416 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
6417 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006418 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
6419 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006420 {"fd", (PyCFunction)DB_fd, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006421 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00006422 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006423 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006424 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006425 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006426 {"get_type", (PyCFunction)DB_get_type, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006427 {"join", (PyCFunction)DB_join, METH_VARARGS},
6428 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
Jesus Cea4907d272008-08-31 14:00:51 +00006429 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006430 {"items", (PyCFunction)DB_items, METH_VARARGS},
6431 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6432 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6433 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6434 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6435 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6436 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006437 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006438 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006439#if (DBVER >= 41)
6440 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6441#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006442 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6443 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6444 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6445 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6446 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6447 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6448 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6449 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6450 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006451 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
6452 {"set_private", (PyCFunction)DB_set_private, METH_O},
6453 {"get_private", (PyCFunction)DB_get_private, METH_NOARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006454 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006455 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006456 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006457 {"type", (PyCFunction)DB_get_type, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006458 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6459 {"values", (PyCFunction)DB_values, METH_VARARGS},
6460 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6461 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6462 {NULL, NULL} /* sentinel */
6463};
6464
6465
6466static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00006467 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006468 (binaryfunc)DB_subscript, /*mp_subscript*/
6469 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6470};
6471
6472
6473static PyMethodDef DBCursor_methods[] = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006474 {"close", (PyCFunction)DBC_close, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006475 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6476 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6477 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6478 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6479 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6480 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00006481 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006482 {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006483 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6484 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6485 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6486 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6487 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6488 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6489 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006490 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00006491 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006492 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6493 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6494 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6495 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6496 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6497 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6498 {NULL, NULL} /* sentinel */
6499};
6500
6501
6502static PyMethodDef DBEnv_methods[] = {
6503 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6504 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6505 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006506#if (DBVER >= 41)
6507 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6508 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6509 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6510#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00006511 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00006512 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006513 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6514 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006515 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Jesus Ceaca3939c2008-05-22 15:27:38 +00006516#if (DBVER >= 47)
6517 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
6518#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006519 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6520 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6521 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006522#if (DBVER >= 42)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006523 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006524#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00006525 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006526 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006527#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006528 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006529#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006530 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6531 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6532 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006533 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6534 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6535 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6536 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6537 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6538 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00006539 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006540 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6541 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006542 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS},
Gregory P. Smithac11e022007-11-05 02:56:31 +00006543 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006544 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6545 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6546 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006547 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006548 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00006549#if (DBVER >= 44)
6550 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6551#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006552 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006553 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS},
Matthias Klose54cc5392010-03-15 12:46:18 +00006554#if (DBVER < 48)
Jesus Ceaca3939c2008-05-22 15:27:38 +00006555 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
6556 METH_VARARGS||METH_KEYWORDS},
Matthias Klose54cc5392010-03-15 12:46:18 +00006557#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00006558 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6559#if (DBVER >= 42)
6560 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6561#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006562 {"set_private", (PyCFunction)DBEnv_set_private, METH_O},
6563 {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS},
6564 {"rep_start", (PyCFunction)DBEnv_rep_start,
6565 METH_VARARGS|METH_KEYWORDS},
6566 {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
6567 {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
6568 METH_VARARGS},
6569#if (DBVER >= 46)
6570 {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS},
6571#endif
6572#if (DBVER >= 44)
6573 {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS},
6574 {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS},
6575 {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006576#endif
6577#if (DBVER >= 45)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006578 {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS},
6579 {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS},
6580#endif
6581#if (DBVER >= 47)
6582 {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS},
6583 {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS},
6584#endif
6585#if (DBVER >= 45)
6586 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006587#endif
6588#if (DBVER >= 45)
6589 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006590 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006591 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006592 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006593 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6594 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6595#endif
6596#if (DBVER >= 45)
6597 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6598 METH_VARARGS|METH_KEYWORDS},
6599 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6600 METH_VARARGS|METH_KEYWORDS},
6601 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6602 METH_VARARGS|METH_KEYWORDS},
6603 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6604 METH_VARARGS},
6605 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006606 METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006607 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006608 METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006609#endif
6610#if (DBVER >= 46)
6611 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6612 METH_VARARGS|METH_KEYWORDS},
6613 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6614 METH_VARARGS|METH_KEYWORDS},
6615#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006616 {NULL, NULL} /* sentinel */
6617};
6618
6619
6620static PyMethodDef DBTxn_methods[] = {
6621 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6622 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006623 {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS},
6624 {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS},
6625 {"id", (PyCFunction)DBTxn_id, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006626 {NULL, NULL} /* sentinel */
6627};
6628
6629
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006630#if (DBVER >= 43)
6631static PyMethodDef DBSequence_methods[] = {
6632 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6633 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006634 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS},
6635 {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006636 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6637 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6638 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6639 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006640 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006641 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006642 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006643 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006644 {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006645 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6646 {NULL, NULL} /* sentinel */
6647};
6648#endif
6649
6650
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006651static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006652DBEnv_db_home_get(DBEnvObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006653{
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006654 const char *home = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006655
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006656 CHECK_ENV_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006657
Jesus Ceaef9764f2008-05-13 18:45:46 +00006658#if (DBVER >= 42)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006659 self->db_env->get_home(self->db_env, &home);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006660#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006661 home=self->db_env->db_home;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006662#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006663
6664 if (home == NULL) {
6665 RETURN_NONE();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006666 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006667 return PyBytes_FromString(home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006668}
6669
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006670static PyGetSetDef DBEnv_getsets[] = {
6671 {"db_home", (getter)DBEnv_db_home_get, NULL,},
6672 {NULL}
6673};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006674
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006675
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006676statichere PyTypeObject DB_Type = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006677#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006678 PyObject_HEAD_INIT(NULL)
6679 0, /*ob_size*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006680#else
6681 PyVarObject_HEAD_INIT(NULL, 0)
6682#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006683 "DB", /*tp_name*/
6684 sizeof(DBObject), /*tp_basicsize*/
6685 0, /*tp_itemsize*/
6686 /* methods */
6687 (destructor)DB_dealloc, /*tp_dealloc*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006688 0, /*tp_print*/
6689 0, /*tp_getattr*/
6690 0, /*tp_setattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006691 0, /*tp_compare*/
6692 0, /*tp_repr*/
6693 0, /*tp_as_number*/
6694 0, /*tp_as_sequence*/
6695 &DB_mapping,/*tp_as_mapping*/
6696 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006697 0, /* tp_call */
6698 0, /* tp_str */
6699 0, /* tp_getattro */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006700 0, /* tp_setattro */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006701 0, /* tp_as_buffer */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006702#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith31c50652004-06-28 01:20:40 +00006703 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006704#else
6705 Py_TPFLAGS_DEFAULT, /* tp_flags */
6706#endif
6707 0, /* tp_doc */
6708 0, /* tp_traverse */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006709 0, /* tp_clear */
6710 0, /* tp_richcompare */
6711 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006712 0, /*tp_iter*/
6713 0, /*tp_iternext*/
6714 DB_methods, /*tp_methods*/
6715 0, /*tp_members*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006716};
6717
6718
6719statichere PyTypeObject DBCursor_Type = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006720#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006721 PyObject_HEAD_INIT(NULL)
6722 0, /*ob_size*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006723#else
6724 PyVarObject_HEAD_INIT(NULL, 0)
6725#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006726 "DBCursor", /*tp_name*/
6727 sizeof(DBCursorObject), /*tp_basicsize*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006728 0, /*tp_itemsize*/
6729 /* methods */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006730 (destructor)DBCursor_dealloc,/*tp_dealloc*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006731 0, /*tp_print*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006732 0, /*tp_getattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006733 0, /*tp_setattr*/
6734 0, /*tp_compare*/
6735 0, /*tp_repr*/
6736 0, /*tp_as_number*/
6737 0, /*tp_as_sequence*/
6738 0, /*tp_as_mapping*/
6739 0, /*tp_hash*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006740 0, /*tp_call*/
6741 0, /*tp_str*/
6742 0, /*tp_getattro*/
6743 0, /*tp_setattro*/
6744 0, /*tp_as_buffer*/
6745#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith31c50652004-06-28 01:20:40 +00006746 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006747#else
6748 Py_TPFLAGS_DEFAULT, /* tp_flags */
6749#endif
6750 0, /* tp_doc */
6751 0, /* tp_traverse */
6752 0, /* tp_clear */
6753 0, /* tp_richcompare */
6754 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
6755 0, /*tp_iter*/
6756 0, /*tp_iternext*/
6757 DBCursor_methods, /*tp_methods*/
6758 0, /*tp_members*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006759};
6760
6761
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006762statichere PyTypeObject DBEnv_Type = {
6763#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006764 PyObject_HEAD_INIT(NULL)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006765 0, /*ob_size*/
6766#else
6767 PyVarObject_HEAD_INIT(NULL, 0)
6768#endif
6769 "DBEnv", /*tp_name*/
6770 sizeof(DBEnvObject), /*tp_basicsize*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006771 0, /*tp_itemsize*/
6772 /* methods */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006773 (destructor)DBEnv_dealloc, /*tp_dealloc*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006774 0, /*tp_print*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006775 0, /*tp_getattr*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006776 0, /*tp_setattr*/
6777 0, /*tp_compare*/
6778 0, /*tp_repr*/
6779 0, /*tp_as_number*/
6780 0, /*tp_as_sequence*/
6781 0, /*tp_as_mapping*/
6782 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006783 0, /* tp_call */
6784 0, /* tp_str */
6785 0, /* tp_getattro */
6786 0, /* tp_setattro */
6787 0, /* tp_as_buffer */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006788#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006789 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006790#else
6791 Py_TPFLAGS_DEFAULT, /* tp_flags */
6792#endif
6793 0, /* tp_doc */
6794 0, /* tp_traverse */
6795 0, /* tp_clear */
6796 0, /* tp_richcompare */
6797 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
6798 0, /* tp_iter */
6799 0, /* tp_iternext */
6800 DBEnv_methods, /* tp_methods */
6801 0, /* tp_members */
6802 DBEnv_getsets, /* tp_getsets */
6803};
6804
6805statichere PyTypeObject DBTxn_Type = {
6806#if (PY_VERSION_HEX < 0x03000000)
6807 PyObject_HEAD_INIT(NULL)
6808 0, /*ob_size*/
6809#else
6810 PyVarObject_HEAD_INIT(NULL, 0)
6811#endif
6812 "DBTxn", /*tp_name*/
6813 sizeof(DBTxnObject), /*tp_basicsize*/
6814 0, /*tp_itemsize*/
6815 /* methods */
6816 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6817 0, /*tp_print*/
6818 0, /*tp_getattr*/
6819 0, /*tp_setattr*/
6820 0, /*tp_compare*/
6821 0, /*tp_repr*/
6822 0, /*tp_as_number*/
6823 0, /*tp_as_sequence*/
6824 0, /*tp_as_mapping*/
6825 0, /*tp_hash*/
6826 0, /* tp_call */
6827 0, /* tp_str */
6828 0, /* tp_getattro */
6829 0, /* tp_setattro */
6830 0, /* tp_as_buffer */
6831#if (PY_VERSION_HEX < 0x03000000)
6832 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6833#else
6834 Py_TPFLAGS_DEFAULT, /* tp_flags */
6835#endif
6836 0, /* tp_doc */
6837 0, /* tp_traverse */
6838 0, /* tp_clear */
6839 0, /* tp_richcompare */
6840 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
6841 0, /*tp_iter*/
6842 0, /*tp_iternext*/
6843 DBTxn_methods, /*tp_methods*/
6844 0, /*tp_members*/
6845};
6846
6847
6848statichere PyTypeObject DBLock_Type = {
6849#if (PY_VERSION_HEX < 0x03000000)
6850 PyObject_HEAD_INIT(NULL)
6851 0, /*ob_size*/
6852#else
6853 PyVarObject_HEAD_INIT(NULL, 0)
6854#endif
6855 "DBLock", /*tp_name*/
6856 sizeof(DBLockObject), /*tp_basicsize*/
6857 0, /*tp_itemsize*/
6858 /* methods */
6859 (destructor)DBLock_dealloc, /*tp_dealloc*/
6860 0, /*tp_print*/
6861 0, /*tp_getattr*/
6862 0, /*tp_setattr*/
6863 0, /*tp_compare*/
6864 0, /*tp_repr*/
6865 0, /*tp_as_number*/
6866 0, /*tp_as_sequence*/
6867 0, /*tp_as_mapping*/
6868 0, /*tp_hash*/
6869 0, /* tp_call */
6870 0, /* tp_str */
6871 0, /* tp_getattro */
6872 0, /* tp_setattro */
6873 0, /* tp_as_buffer */
6874#if (PY_VERSION_HEX < 0x03000000)
6875 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6876#else
6877 Py_TPFLAGS_DEFAULT, /* tp_flags */
6878#endif
6879 0, /* tp_doc */
6880 0, /* tp_traverse */
6881 0, /* tp_clear */
6882 0, /* tp_richcompare */
6883 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
6884};
6885
6886#if (DBVER >= 43)
6887statichere PyTypeObject DBSequence_Type = {
6888#if (PY_VERSION_HEX < 0x03000000)
6889 PyObject_HEAD_INIT(NULL)
6890 0, /*ob_size*/
6891#else
6892 PyVarObject_HEAD_INIT(NULL, 0)
6893#endif
6894 "DBSequence", /*tp_name*/
6895 sizeof(DBSequenceObject), /*tp_basicsize*/
6896 0, /*tp_itemsize*/
6897 /* methods */
6898 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6899 0, /*tp_print*/
6900 0, /*tp_getattr*/
6901 0, /*tp_setattr*/
6902 0, /*tp_compare*/
6903 0, /*tp_repr*/
6904 0, /*tp_as_number*/
6905 0, /*tp_as_sequence*/
6906 0, /*tp_as_mapping*/
6907 0, /*tp_hash*/
6908 0, /* tp_call */
6909 0, /* tp_str */
6910 0, /* tp_getattro */
6911 0, /* tp_setattro */
6912 0, /* tp_as_buffer */
6913#if (PY_VERSION_HEX < 0x03000000)
6914 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6915#else
6916 Py_TPFLAGS_DEFAULT, /* tp_flags */
6917#endif
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006918 0, /* tp_doc */
6919 0, /* tp_traverse */
6920 0, /* tp_clear */
6921 0, /* tp_richcompare */
6922 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006923 0, /*tp_iter*/
6924 0, /*tp_iternext*/
6925 DBSequence_methods, /*tp_methods*/
6926 0, /*tp_members*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006927};
6928#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006929
6930/* --------------------------------------------------------------------- */
6931/* Module-level functions */
6932
6933static PyObject*
6934DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6935{
6936 PyObject* dbenvobj = NULL;
6937 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00006938 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006939
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006940 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6941 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006942 return NULL;
6943 if (dbenvobj == Py_None)
6944 dbenvobj = NULL;
6945 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6946 makeTypeError("DBEnv", dbenvobj);
6947 return NULL;
6948 }
6949
6950 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6951}
6952
6953
6954static PyObject*
6955DBEnv_construct(PyObject* self, PyObject* args)
6956{
6957 int flags = 0;
6958 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6959 return (PyObject* )newDBEnvObject(flags);
6960}
6961
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006962#if (DBVER >= 43)
6963static PyObject*
6964DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6965{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006966 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006967 int flags = 0;
6968 static char* kwnames[] = { "db", "flags", NULL};
6969
6970 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6971 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006972 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006973 makeTypeError("DB", dbobj);
6974 return NULL;
6975 }
6976 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6977}
6978#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006979
6980static char bsddb_version_doc[] =
6981"Returns a tuple of major, minor, and patch release numbers of the\n\
6982underlying DB library.";
6983
6984static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006985bsddb_version(PyObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006986{
6987 int major, minor, patch;
6988
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006989 db_version(&major, &minor, &patch);
6990 return Py_BuildValue("(iii)", major, minor, patch);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006991}
6992
6993
6994/* List of functions defined in the module */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006995static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006996 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6997 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006998#if (DBVER >= 43)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006999 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007000#endif
7001 {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007002 {NULL, NULL} /* sentinel */
7003};
7004
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007005
Gregory P. Smith39250532007-10-09 06:02:21 +00007006/* API structure */
7007static BSDDB_api bsddb_api;
7008
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007009
7010/* --------------------------------------------------------------------- */
7011/* Module initialization */
7012
7013
7014/* Convenience routine to export an integer value.
7015 * Errors are silently ignored, for better or for worse...
7016 */
7017#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
7018
Gregory P. Smith41631e82003-09-21 00:08:14 +00007019#define MODULE_NAME_MAX_LEN 11
7020static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007021
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007022#if (PY_VERSION_HEX >= 0x03000000)
7023static struct PyModuleDef bsddbmodule = {
7024 PyModuleDef_HEAD_INIT,
7025 _bsddbModuleName, /* Name of module */
7026 NULL, /* module documentation, may be NULL */
7027 -1, /* size of per-interpreter state of the module,
7028 or -1 if the module keeps state in global variables. */
7029 bsddb_methods,
7030 NULL, /* Reload */
7031 NULL, /* Traverse */
7032 NULL, /* Clear */
7033 NULL /* Free */
7034};
7035#endif
7036
7037
7038#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007039DL_EXPORT(void) init_bsddb(void)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007040#else
7041PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */
7042#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007043{
7044 PyObject* m;
7045 PyObject* d;
Christian Heimes593daf52008-05-26 12:51:38 +00007046 PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
7047 PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
7048 PyObject* cvsid_s = PyBytes_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00007049 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007050
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007051 /* Initialize object types */
7052 if ((PyType_Ready(&DB_Type) < 0)
7053 || (PyType_Ready(&DBCursor_Type) < 0)
7054 || (PyType_Ready(&DBEnv_Type) < 0)
7055 || (PyType_Ready(&DBTxn_Type) < 0)
7056 || (PyType_Ready(&DBLock_Type) < 0)
7057#if (DBVER >= 43)
7058 || (PyType_Ready(&DBSequence_Type) < 0)
7059#endif
7060 ) {
7061#if (PY_VERSION_HEX < 0x03000000)
7062 return;
7063#else
7064 return NULL;
7065#endif
7066 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007067
Mark Hammonda69d4092003-04-22 23:13:27 +00007068#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007069 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00007070 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007071#endif
7072
7073 /* Create the module and add the functions */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007074#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007075 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007076#else
7077 m=PyModule_Create(&bsddbmodule);
7078#endif
7079 if (m == NULL) {
7080#if (PY_VERSION_HEX < 0x03000000)
7081 return;
7082#else
7083 return NULL;
7084#endif
7085 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007086
7087 /* Add some symbolic constants to the module */
7088 d = PyModule_GetDict(m);
7089 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
7090 PyDict_SetItemString(d, "cvsid", cvsid_s);
7091 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
7092 Py_DECREF(pybsddb_version_s);
7093 pybsddb_version_s = NULL;
7094 Py_DECREF(cvsid_s);
7095 cvsid_s = NULL;
7096 Py_DECREF(db_version_s);
7097 db_version_s = NULL;
7098
7099 ADD_INT(d, DB_VERSION_MAJOR);
7100 ADD_INT(d, DB_VERSION_MINOR);
7101 ADD_INT(d, DB_VERSION_PATCH);
7102
7103 ADD_INT(d, DB_MAX_PAGES);
7104 ADD_INT(d, DB_MAX_RECORDS);
7105
Matthias Klose54cc5392010-03-15 12:46:18 +00007106#if (DBVER < 48)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007107#if (DBVER >= 42)
7108 ADD_INT(d, DB_RPCCLIENT);
7109#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007110 ADD_INT(d, DB_CLIENT);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007111 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
Gregory P. Smith41631e82003-09-21 00:08:14 +00007112 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
7113#endif
Matthias Klose54cc5392010-03-15 12:46:18 +00007114#endif
7115
7116#if (DBVER < 48)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007117 ADD_INT(d, DB_XA_CREATE);
Matthias Klose54cc5392010-03-15 12:46:18 +00007118#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007119
7120 ADD_INT(d, DB_CREATE);
7121 ADD_INT(d, DB_NOMMAP);
7122 ADD_INT(d, DB_THREAD);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007123#if (DBVER >= 45)
7124 ADD_INT(d, DB_MULTIVERSION);
7125#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007126
7127 ADD_INT(d, DB_FORCE);
7128 ADD_INT(d, DB_INIT_CDB);
7129 ADD_INT(d, DB_INIT_LOCK);
7130 ADD_INT(d, DB_INIT_LOG);
7131 ADD_INT(d, DB_INIT_MPOOL);
7132 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007133 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007134
Matthias Klose54cc5392010-03-15 12:46:18 +00007135#if (DBVER >= 48)
7136 ADD_INT(d, DB_GID_SIZE);
7137#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00007138 ADD_INT(d, DB_XIDDATASIZE);
Matthias Klose54cc5392010-03-15 12:46:18 +00007139 /* Allow new code to work in old BDB releases */
7140 _addIntToDict(d, "DB_GID_SIZE", DB_XIDDATASIZE);
7141#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00007142
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007143 ADD_INT(d, DB_RECOVER);
7144 ADD_INT(d, DB_RECOVER_FATAL);
7145 ADD_INT(d, DB_TXN_NOSYNC);
7146 ADD_INT(d, DB_USE_ENVIRON);
7147 ADD_INT(d, DB_USE_ENVIRON_ROOT);
7148
7149 ADD_INT(d, DB_LOCKDOWN);
7150 ADD_INT(d, DB_PRIVATE);
7151 ADD_INT(d, DB_SYSTEM_MEM);
7152
7153 ADD_INT(d, DB_TXN_SYNC);
7154 ADD_INT(d, DB_TXN_NOWAIT);
7155
7156 ADD_INT(d, DB_EXCL);
7157 ADD_INT(d, DB_FCNTL_LOCKING);
7158 ADD_INT(d, DB_ODDFILESIZE);
7159 ADD_INT(d, DB_RDWRMASTER);
7160 ADD_INT(d, DB_RDONLY);
7161 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007162 ADD_INT(d, DB_EXTENT);
7163 ADD_INT(d, DB_CDB_ALLDB);
7164 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007165 ADD_INT(d, DB_UPGRADE);
7166
7167 ADD_INT(d, DB_AGGRESSIVE);
7168 ADD_INT(d, DB_NOORDERCHK);
7169 ADD_INT(d, DB_ORDERCHKONLY);
7170 ADD_INT(d, DB_PR_PAGE);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007171
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007172 ADD_INT(d, DB_PR_RECOVERYTEST);
7173 ADD_INT(d, DB_SALVAGE);
7174
7175 ADD_INT(d, DB_LOCK_NORUN);
7176 ADD_INT(d, DB_LOCK_DEFAULT);
7177 ADD_INT(d, DB_LOCK_OLDEST);
7178 ADD_INT(d, DB_LOCK_RANDOM);
7179 ADD_INT(d, DB_LOCK_YOUNGEST);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007180 ADD_INT(d, DB_LOCK_MAXLOCKS);
7181 ADD_INT(d, DB_LOCK_MINLOCKS);
7182 ADD_INT(d, DB_LOCK_MINWRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007183
Jesus Ceaef9764f2008-05-13 18:45:46 +00007184 ADD_INT(d, DB_LOCK_EXPIRE);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007185#if (DBVER >= 43)
7186 ADD_INT(d, DB_LOCK_MAXWRITE);
7187#endif
7188
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007189 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007190
7191 ADD_INT(d, DB_LOCK_DUMP);
7192 ADD_INT(d, DB_LOCK_GET);
7193 ADD_INT(d, DB_LOCK_INHERIT);
7194 ADD_INT(d, DB_LOCK_PUT);
7195 ADD_INT(d, DB_LOCK_PUT_ALL);
7196 ADD_INT(d, DB_LOCK_PUT_OBJ);
7197
7198 ADD_INT(d, DB_LOCK_NG);
7199 ADD_INT(d, DB_LOCK_READ);
7200 ADD_INT(d, DB_LOCK_WRITE);
7201 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007202 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007203 ADD_INT(d, DB_LOCK_IWRITE);
7204 ADD_INT(d, DB_LOCK_IREAD);
7205 ADD_INT(d, DB_LOCK_IWR);
Gregory P. Smith29602d22006-01-24 09:46:48 +00007206#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007207 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00007208#else
7209 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
7210#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007211 ADD_INT(d, DB_LOCK_WWRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007212
7213 ADD_INT(d, DB_LOCK_RECORD);
7214 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007215 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007216 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007217
7218 ADD_INT(d, DB_LOCK_NOWAIT);
7219 ADD_INT(d, DB_LOCK_RECORD);
7220 ADD_INT(d, DB_LOCK_UPGRADE);
7221
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007222 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007223#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007224 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007225#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007226 ADD_INT(d, DB_LSTAT_FREE);
7227 ADD_INT(d, DB_LSTAT_HELD);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007228
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007229 ADD_INT(d, DB_LSTAT_PENDING);
7230 ADD_INT(d, DB_LSTAT_WAITING);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007231
7232 ADD_INT(d, DB_ARCH_ABS);
7233 ADD_INT(d, DB_ARCH_DATA);
7234 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00007235#if (DBVER >= 42)
7236 ADD_INT(d, DB_ARCH_REMOVE);
7237#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007238
7239 ADD_INT(d, DB_BTREE);
7240 ADD_INT(d, DB_HASH);
7241 ADD_INT(d, DB_RECNO);
7242 ADD_INT(d, DB_QUEUE);
7243 ADD_INT(d, DB_UNKNOWN);
7244
7245 ADD_INT(d, DB_DUP);
7246 ADD_INT(d, DB_DUPSORT);
7247 ADD_INT(d, DB_RECNUM);
7248 ADD_INT(d, DB_RENUMBER);
7249 ADD_INT(d, DB_REVSPLITOFF);
7250 ADD_INT(d, DB_SNAPSHOT);
7251
7252 ADD_INT(d, DB_JOIN_NOSORT);
7253
7254 ADD_INT(d, DB_AFTER);
7255 ADD_INT(d, DB_APPEND);
7256 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007257#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007258 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007259#endif
Jesus Ceaca3939c2008-05-22 15:27:38 +00007260
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007261#if (DBVER >= 41)
7262 _addIntToDict(d, "DB_CHECKPOINT", 0);
7263#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007264 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007265 ADD_INT(d, DB_CURLSN);
7266#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007267#if (DBVER <= 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007268 ADD_INT(d, DB_COMMIT);
7269#endif
7270 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007271 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007272 ADD_INT(d, DB_CURRENT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007273 ADD_INT(d, DB_FAST_STAT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007274 ADD_INT(d, DB_FIRST);
7275 ADD_INT(d, DB_FLUSH);
7276 ADD_INT(d, DB_GET_BOTH);
7277 ADD_INT(d, DB_GET_RECNO);
7278 ADD_INT(d, DB_JOIN_ITEM);
7279 ADD_INT(d, DB_KEYFIRST);
7280 ADD_INT(d, DB_KEYLAST);
7281 ADD_INT(d, DB_LAST);
7282 ADD_INT(d, DB_NEXT);
7283 ADD_INT(d, DB_NEXT_DUP);
7284 ADD_INT(d, DB_NEXT_NODUP);
7285 ADD_INT(d, DB_NODUPDATA);
7286 ADD_INT(d, DB_NOOVERWRITE);
7287 ADD_INT(d, DB_NOSYNC);
7288 ADD_INT(d, DB_POSITION);
7289 ADD_INT(d, DB_PREV);
7290 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007291#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007292 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007293#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007294 ADD_INT(d, DB_SET);
7295 ADD_INT(d, DB_SET_RANGE);
7296 ADD_INT(d, DB_SET_RECNO);
7297 ADD_INT(d, DB_WRITECURSOR);
7298
7299 ADD_INT(d, DB_OPFLAGS_MASK);
7300 ADD_INT(d, DB_RMW);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007301 ADD_INT(d, DB_DIRTY_READ);
7302 ADD_INT(d, DB_MULTIPLE);
7303 ADD_INT(d, DB_MULTIPLE_KEY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007304
Gregory P. Smith29602d22006-01-24 09:46:48 +00007305#if (DBVER >= 44)
7306 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
7307 ADD_INT(d, DB_READ_COMMITTED);
7308#endif
7309
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007310 ADD_INT(d, DB_DONOTINDEX);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007311
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007312#if (DBVER >= 41)
7313 _addIntToDict(d, "DB_INCOMPLETE", 0);
7314#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007315 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007316#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007317 ADD_INT(d, DB_KEYEMPTY);
7318 ADD_INT(d, DB_KEYEXIST);
7319 ADD_INT(d, DB_LOCK_DEADLOCK);
7320 ADD_INT(d, DB_LOCK_NOTGRANTED);
7321 ADD_INT(d, DB_NOSERVER);
7322 ADD_INT(d, DB_NOSERVER_HOME);
7323 ADD_INT(d, DB_NOSERVER_ID);
7324 ADD_INT(d, DB_NOTFOUND);
7325 ADD_INT(d, DB_OLD_VERSION);
7326 ADD_INT(d, DB_RUNRECOVERY);
7327 ADD_INT(d, DB_VERIFY_BAD);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007328 ADD_INT(d, DB_PAGE_NOTFOUND);
7329 ADD_INT(d, DB_SECONDARY_BAD);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007330 ADD_INT(d, DB_STAT_CLEAR);
7331 ADD_INT(d, DB_REGION_INIT);
7332 ADD_INT(d, DB_NOLOCKING);
7333 ADD_INT(d, DB_YIELDCPU);
7334 ADD_INT(d, DB_PANIC_ENVIRONMENT);
7335 ADD_INT(d, DB_NOPANIC);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007336
Jesus Ceaef9764f2008-05-13 18:45:46 +00007337#if (DBVER >= 41)
7338 ADD_INT(d, DB_OVERWRITE);
7339#endif
7340
Gregory P. Smithaae141a2007-11-01 21:08:14 +00007341#ifdef DB_REGISTER
7342 ADD_INT(d, DB_REGISTER);
7343#endif
7344
Gregory P. Smith41631e82003-09-21 00:08:14 +00007345#if (DBVER >= 42)
7346 ADD_INT(d, DB_TIME_NOTGRANTED);
7347 ADD_INT(d, DB_TXN_NOT_DURABLE);
7348 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
Gregory P. Smith41631e82003-09-21 00:08:14 +00007349 ADD_INT(d, DB_DIRECT_DB);
7350 ADD_INT(d, DB_INIT_REP);
7351 ADD_INT(d, DB_ENCRYPT);
7352 ADD_INT(d, DB_CHKSUM);
7353#endif
7354
Jesus Ceaca3939c2008-05-22 15:27:38 +00007355#if (DBVER >= 42) && (DBVER < 47)
7356 ADD_INT(d, DB_LOG_AUTOREMOVE);
7357 ADD_INT(d, DB_DIRECT_LOG);
7358#endif
7359
7360#if (DBVER >= 47)
7361 ADD_INT(d, DB_LOG_DIRECT);
7362 ADD_INT(d, DB_LOG_DSYNC);
7363 ADD_INT(d, DB_LOG_IN_MEMORY);
7364 ADD_INT(d, DB_LOG_AUTO_REMOVE);
7365 ADD_INT(d, DB_LOG_ZERO);
7366#endif
7367
Jesus Ceaef9764f2008-05-13 18:45:46 +00007368#if (DBVER >= 44)
7369 ADD_INT(d, DB_DSYNC_DB);
7370#endif
7371
7372#if (DBVER >= 45)
7373 ADD_INT(d, DB_TXN_SNAPSHOT);
7374#endif
7375
Jesus Ceaef9764f2008-05-13 18:45:46 +00007376 ADD_INT(d, DB_VERB_DEADLOCK);
7377#if (DBVER >= 46)
7378 ADD_INT(d, DB_VERB_FILEOPS);
7379 ADD_INT(d, DB_VERB_FILEOPS_ALL);
7380#endif
7381 ADD_INT(d, DB_VERB_RECOVERY);
7382#if (DBVER >= 44)
7383 ADD_INT(d, DB_VERB_REGISTER);
7384#endif
7385 ADD_INT(d, DB_VERB_REPLICATION);
7386 ADD_INT(d, DB_VERB_WAITSFOR);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007387
7388#if (DBVER >= 45)
7389 ADD_INT(d, DB_EVENT_PANIC);
7390 ADD_INT(d, DB_EVENT_REP_CLIENT);
7391#if (DBVER >= 46)
7392 ADD_INT(d, DB_EVENT_REP_ELECTED);
7393#endif
7394 ADD_INT(d, DB_EVENT_REP_MASTER);
7395 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
7396#if (DBVER >= 46)
7397 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
7398#endif
7399 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
7400 ADD_INT(d, DB_EVENT_WRITE_FAILED);
7401#endif
7402
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007403 ADD_INT(d, DB_REP_DUPMASTER);
7404 ADD_INT(d, DB_REP_HOLDELECTION);
7405#if (DBVER >= 44)
7406 ADD_INT(d, DB_REP_IGNORE);
7407 ADD_INT(d, DB_REP_JOIN_FAILURE);
7408#endif
7409#if (DBVER >= 42)
7410 ADD_INT(d, DB_REP_ISPERM);
7411 ADD_INT(d, DB_REP_NOTPERM);
7412#endif
7413 ADD_INT(d, DB_REP_NEWSITE);
7414
Jesus Ceaef9764f2008-05-13 18:45:46 +00007415 ADD_INT(d, DB_REP_MASTER);
7416 ADD_INT(d, DB_REP_CLIENT);
7417#if (DBVER >= 45)
7418 ADD_INT(d, DB_REP_ELECTION);
7419
7420 ADD_INT(d, DB_REP_ACK_TIMEOUT);
7421 ADD_INT(d, DB_REP_CONNECTION_RETRY);
7422 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
7423 ADD_INT(d, DB_REP_ELECTION_RETRY);
7424#endif
7425#if (DBVER >= 46)
7426 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
7427 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
7428#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00007429
7430#if (DBVER >= 45)
7431 ADD_INT(d, DB_REPMGR_PEER);
7432 ADD_INT(d, DB_REPMGR_ACKS_ALL);
7433 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
7434 ADD_INT(d, DB_REPMGR_ACKS_NONE);
7435 ADD_INT(d, DB_REPMGR_ACKS_ONE);
7436 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
7437 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
7438 ADD_INT(d, DB_REPMGR_CONNECTED);
7439 ADD_INT(d, DB_REPMGR_DISCONNECTED);
7440 ADD_INT(d, DB_STAT_CLEAR);
7441 ADD_INT(d, DB_STAT_ALL);
7442#endif
7443
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007444#if (DBVER >= 43)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007445 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00007446 ADD_INT(d, DB_SEQ_DEC);
7447 ADD_INT(d, DB_SEQ_INC);
7448 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007449#endif
7450
Jesus Ceaca3939c2008-05-22 15:27:38 +00007451#if (DBVER >= 43) && (DBVER < 47)
7452 ADD_INT(d, DB_LOG_INMEMORY);
7453 ADD_INT(d, DB_DSYNC_LOG);
7454#endif
7455
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007456#if (DBVER >= 41)
7457 ADD_INT(d, DB_ENCRYPT_AES);
7458 ADD_INT(d, DB_AUTO_COMMIT);
7459#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00007460 /* allow Berkeley DB 4.1 aware apps to run on older versions */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007461 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
7462#endif
7463
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007464 ADD_INT(d, EINVAL);
7465 ADD_INT(d, EACCES);
7466 ADD_INT(d, ENOSPC);
7467 ADD_INT(d, ENOMEM);
7468 ADD_INT(d, EAGAIN);
7469 ADD_INT(d, EBUSY);
7470 ADD_INT(d, EEXIST);
7471 ADD_INT(d, ENOENT);
7472 ADD_INT(d, EPERM);
7473
Barry Warsaw1baa9822003-03-31 19:51:29 +00007474 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
7475 ADD_INT(d, DB_SET_TXN_TIMEOUT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007476
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007477 /* The exception name must be correct for pickled exception *
7478 * objects to unpickle properly. */
7479#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
7480#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
7481#else
7482#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
7483#endif
7484
7485 /* All the rest of the exceptions derive only from DBError */
7486#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
7487 PyDict_SetItemString(d, #name, name)
7488
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007489 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007490 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
7491 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007492
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007493#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithe9477062005-06-04 06:46:59 +00007494 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
7495 * from both DBError and KeyError, since the API only supports
7496 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007497 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00007498 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
7499 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007500 Py_file_input, d, d);
7501 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00007502 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007503 PyDict_DelItemString(d, "KeyError");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007504#else
7505 /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
7506 ** derive from several classes. We use this new API only for Python 3.0,
7507 ** though.
7508 */
7509 {
7510 PyObject* bases;
7511
7512 bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
7513
7514#define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
7515 PyDict_SetItemString(d, #name, name)
7516 MAKE_EX2(DBNotFoundError);
7517 MAKE_EX2(DBKeyEmptyError);
7518
7519#undef MAKE_EX2
7520
7521 Py_XDECREF(bases);
7522 }
7523#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007524
7525
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007526#if !INCOMPLETE_IS_WARNING
7527 MAKE_EX(DBIncompleteError);
7528#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00007529 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007530 MAKE_EX(DBKeyEmptyError);
7531 MAKE_EX(DBKeyExistError);
7532 MAKE_EX(DBLockDeadlockError);
7533 MAKE_EX(DBLockNotGrantedError);
7534 MAKE_EX(DBOldVersionError);
7535 MAKE_EX(DBRunRecoveryError);
7536 MAKE_EX(DBVerifyBadError);
7537 MAKE_EX(DBNoServerError);
7538 MAKE_EX(DBNoServerHomeError);
7539 MAKE_EX(DBNoServerIDError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007540 MAKE_EX(DBPageNotFoundError);
7541 MAKE_EX(DBSecondaryBadError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007542
7543 MAKE_EX(DBInvalidArgError);
7544 MAKE_EX(DBAccessError);
7545 MAKE_EX(DBNoSpaceError);
7546 MAKE_EX(DBNoMemoryError);
7547 MAKE_EX(DBAgainError);
7548 MAKE_EX(DBBusyError);
7549 MAKE_EX(DBFileExistsError);
7550 MAKE_EX(DBNoSuchFileError);
7551 MAKE_EX(DBPermissionsError);
7552
Jesus Ceaef9764f2008-05-13 18:45:46 +00007553#if (DBVER >= 42)
7554 MAKE_EX(DBRepHandleDeadError);
7555#endif
7556
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007557 MAKE_EX(DBRepUnavailError);
7558
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007559#undef MAKE_EX
7560
Gregory P. Smith39250532007-10-09 06:02:21 +00007561 /* Initiliase the C API structure and add it to the module */
7562 bsddb_api.db_type = &DB_Type;
7563 bsddb_api.dbcursor_type = &DBCursor_Type;
7564 bsddb_api.dbenv_type = &DBEnv_Type;
7565 bsddb_api.dbtxn_type = &DBTxn_Type;
7566 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007567#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00007568 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007569#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00007570 bsddb_api.makeDBError = makeDBError;
7571
7572 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7573 PyDict_SetItemString(d, "api", py_api);
7574 Py_DECREF(py_api);
7575
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007576 /* Check for errors */
7577 if (PyErr_Occurred()) {
7578 PyErr_Print();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007579 Py_FatalError("can't initialize module _bsddb/_pybsddb");
7580 Py_DECREF(m);
7581 m = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007582 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007583#if (PY_VERSION_HEX < 0x03000000)
7584 return;
7585#else
7586 return m;
7587#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007588}
Gregory P. Smith41631e82003-09-21 00:08:14 +00007589
7590/* allow this module to be named _pybsddb so that it can be installed
7591 * and imported on top of python >= 2.3 that includes its own older
7592 * copy of the library named _bsddb without importing the old version. */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007593#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007594DL_EXPORT(void) init_pybsddb(void)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007595#else
7596PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */
7597#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00007598{
7599 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007600#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007601 init_bsddb();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007602#else
7603 return PyInit__bsddb(); /* Note the two underscores */
7604#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00007605}