blob: 9324d76b3c2322940eed8cbe4cf8fb6143203642 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Jesus Ceaef9764f2008-05-13 18:45:46 +000039 * to compile with Berkeley DB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
Gregory P. Smithf8057852007-09-09 20:25:00 +000042 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * Berkeley DB 2.7.x.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000045 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
Jesus Ceaef9764f2008-05-13 18:45:46 +000051 * Gregory P. Smith <greg@krypto.org> was once again the maintainer.
52 *
Jesus Ceaca3939c2008-05-22 15:27:38 +000053 * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>.
Jesus Ceaef9764f2008-05-13 18:45:46 +000054 * Jesus Cea licenses this code to PSF under a Contributor Agreement.
Barry Warsaw9a0d7792002-12-30 20:53:52 +000055 *
56 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000057 * Things can change faster than the header of this file is updated. This
58 * file is shared with the PyBSDDB project at SourceForge:
59 *
60 * http://pybsddb.sf.net
61 *
62 * This file should remain backward compatible with Python 2.1, but see PEP
63 * 291 for the most current backward compatibility requirements:
64 *
65 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000066 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000067 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000068 *
69 * DB (Database)
70 * DBCursor (Database Cursor)
71 * DBEnv (database environment)
72 * DBTxn (An explicit database transaction)
73 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000074 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000075 *
76 */
77
78/* --------------------------------------------------------------------- */
79
80/*
81 * Portions of this module, associated unit tests and build scripts are the
82 * result of a contract with The Written Word (http://thewrittenword.com/)
83 * Many thanks go out to them for causing me to raise the bar on quality and
84 * functionality, resulting in a better bsddb3 package for all of us to use.
85 *
86 * --Robin
87 */
88
89/* --------------------------------------------------------------------- */
90
Gregory P. Smitha703a212003-11-03 01:04:41 +000091#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000092#include <Python.h>
Gregory P. Smith39250532007-10-09 06:02:21 +000093
94#define COMPILING_BSDDB_C
95#include "bsddb.h"
96#undef COMPILING_BSDDB_C
97
98static char *rcs_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000099
100/* --------------------------------------------------------------------- */
101/* Various macro definitions */
102
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000103#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000104typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#endif
106
Gregory P. Smith572226c2008-05-26 19:03:35 +0000107#if (PY_VERSION_HEX < 0x02060000) /* really: before python trunk r63675 */
108/* This code now uses PyBytes* API function names instead of PyString*.
109 * These #defines map to their equivalent on earlier python versions. */
110#define PyBytes_FromStringAndSize PyString_FromStringAndSize
111#define PyBytes_FromString PyString_FromString
112#define PyBytes_AsStringAndSize PyString_AsStringAndSize
113#define PyBytes_Check PyString_Check
114#define PyBytes_GET_SIZE PyString_GET_SIZE
115#define PyBytes_AS_STRING PyString_AS_STRING
116#endif
117
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000118#if (PY_VERSION_HEX >= 0x03000000)
119#define NUMBER_Check PyLong_Check
120#define NUMBER_AsLong PyLong_AsLong
121#define NUMBER_FromLong PyLong_FromLong
122#else
123#define NUMBER_Check PyInt_Check
124#define NUMBER_AsLong PyInt_AsLong
125#define NUMBER_FromLong PyInt_FromLong
126#endif
127
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000128#ifdef WITH_THREAD
129
130/* These are for when calling Python --> C */
131#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
132#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
133
Mark Hammonda69d4092003-04-22 23:13:27 +0000134/* For 2.3, use the PyGILState_ calls */
135#if (PY_VERSION_HEX >= 0x02030000)
136#define MYDB_USE_GILSTATE
137#endif
138
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000139/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000140#if defined(MYDB_USE_GILSTATE)
141#define MYDB_BEGIN_BLOCK_THREADS \
142 PyGILState_STATE __savestate = PyGILState_Ensure();
143#define MYDB_END_BLOCK_THREADS \
144 PyGILState_Release(__savestate);
145#else /* MYDB_USE_GILSTATE */
146/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000147static PyInterpreterState* _db_interpreterState = NULL;
148#define MYDB_BEGIN_BLOCK_THREADS { \
149 PyThreadState* prevState; \
150 PyThreadState* newState; \
151 PyEval_AcquireLock(); \
152 newState = PyThreadState_New(_db_interpreterState); \
153 prevState = PyThreadState_Swap(newState);
154
155#define MYDB_END_BLOCK_THREADS \
156 newState = PyThreadState_Swap(prevState); \
157 PyThreadState_Clear(newState); \
158 PyEval_ReleaseLock(); \
159 PyThreadState_Delete(newState); \
160 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000161#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000162
163#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000164/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000165#define MYDB_BEGIN_ALLOW_THREADS
166#define MYDB_END_ALLOW_THREADS
167#define MYDB_BEGIN_BLOCK_THREADS
168#define MYDB_END_BLOCK_THREADS
169
170#endif
171
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000172/* Should DB_INCOMPLETE be turned into a warning or an exception? */
173#define INCOMPLETE_IS_WARNING 1
174
175/* --------------------------------------------------------------------- */
176/* Exceptions */
177
178static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000179static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000180static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000181static PyObject* DBKeyExistError; /* DB_KEYEXIST */
182static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
183static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
184static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
185static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
186static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
187static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
188static PyObject* DBNoServerError; /* DB_NOSERVER */
189static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
190static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000191static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
192static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000193
194#if !INCOMPLETE_IS_WARNING
195static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
196#endif
197
198static PyObject* DBInvalidArgError; /* EINVAL */
199static PyObject* DBAccessError; /* EACCES */
200static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000201static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000202static PyObject* DBAgainError; /* EAGAIN */
203static PyObject* DBBusyError; /* EBUSY */
204static PyObject* DBFileExistsError; /* EEXIST */
205static PyObject* DBNoSuchFileError; /* ENOENT */
206static PyObject* DBPermissionsError; /* EPERM */
207
Jesus Ceaef9764f2008-05-13 18:45:46 +0000208#if (DBVER >= 42)
209static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
210#endif
211
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000212static PyObject* DBRepUnavailError; /* DB_REP_UNAVAIL */
213
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000214#if (DBVER < 43)
215#define DB_BUFFER_SMALL ENOMEM
216#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000217
218
219/* --------------------------------------------------------------------- */
220/* Structure definitions */
221
Gregory P. Smith39250532007-10-09 06:02:21 +0000222#if PYTHON_API_VERSION < 1010
223#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000224#endif
225
Gregory P. Smith31c50652004-06-28 01:20:40 +0000226
Gregory P. Smith39250532007-10-09 06:02:21 +0000227/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000228#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000229#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000230
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000231
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000232/* See comment in Python 2.6 "object.h" */
233#ifndef staticforward
234#define staticforward static
235#endif
236#ifndef statichere
237#define statichere static
238#endif
239
240staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
241 DBLock_Type;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000242#if (DBVER >= 43)
243staticforward PyTypeObject DBSequence_Type;
244#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000245
Martin v. Löwis83c92012008-04-24 13:17:24 +0000246#ifndef Py_TYPE
Gregory P. Smithfc006692007-11-05 09:06:28 +0000247/* for compatibility with Python 2.5 and earlier */
Christian Heimese93237d2007-12-19 02:37:44 +0000248#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
Gregory P. Smithfc006692007-11-05 09:06:28 +0000249#endif
250
Christian Heimese93237d2007-12-19 02:37:44 +0000251#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
252#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
253#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
254#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
255#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000256#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +0000257#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000258#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000259
Jesus Ceaef9764f2008-05-13 18:45:46 +0000260#if (DBVER < 46)
261 #define _DBC_close(dbc) dbc->c_close(dbc)
262 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
263 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
264 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
265 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
266 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
267 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
268#else
269 #define _DBC_close(dbc) dbc->close(dbc)
270 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
271 #define _DBC_del(dbc,a) dbc->del(dbc,a)
272 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
273 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
274 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
275 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
276#endif
277
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000278
279/* --------------------------------------------------------------------- */
280/* Utility macros and functions */
281
Jesus Ceaef9764f2008-05-13 18:45:46 +0000282#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
283 { \
284 object->sibling_next=backlink; \
285 object->sibling_prev_p=&(backlink); \
286 backlink=object; \
287 if (object->sibling_next) { \
288 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
289 } \
290 }
291
292#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
293 { \
294 if (object->sibling_next) { \
295 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
296 } \
297 *(object->sibling_prev_p)=object->sibling_next; \
298 }
299
300#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
301 { \
302 if (object->sibling_next) { \
303 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
304 } \
305 if (object->sibling_prev_p) { \
306 *(object->sibling_prev_p)=object->sibling_next; \
307 } \
308 }
309
310#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
311 { \
312 object->sibling_next_txn=backlink; \
313 object->sibling_prev_p_txn=&(backlink); \
314 backlink=object; \
315 if (object->sibling_next_txn) { \
316 object->sibling_next_txn->sibling_prev_p_txn= \
317 &(object->sibling_next_txn); \
318 } \
319 }
320
321#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
322 { \
323 if (object->sibling_next_txn) { \
324 object->sibling_next_txn->sibling_prev_p_txn= \
325 object->sibling_prev_p_txn; \
326 } \
327 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
328 }
329
330
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000331#define RETURN_IF_ERR() \
332 if (makeDBError(err)) { \
333 return NULL; \
334 }
335
336#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
337
Gregory P. Smithe2767172003-11-02 08:06:29 +0000338#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
339 if ((nonNull) == NULL) { \
340 PyObject *errTuple = NULL; \
341 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000342 if (errTuple) { \
343 PyErr_SetObject((pyErrObj), errTuple); \
344 Py_DECREF(errTuple); \
345 } \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000346 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000347 }
348
Gregory P. Smithe2767172003-11-02 08:06:29 +0000349#define CHECK_DB_NOT_CLOSED(dbobj) \
350 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
351
352#define CHECK_ENV_NOT_CLOSED(env) \
353 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000354
355#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000356 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000357
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000358#if (DBVER >= 43)
359#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
360 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
361#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000362
363#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
364 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
365
366#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
367
368#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000369 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000370
371
372static int makeDBError(int err);
373
374
375/* Return the access method type of the DBObject */
376static int _DB_get_type(DBObject* self)
377{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000378 DBTYPE type;
379 int err;
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000380
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000381 err = self->db->get_type(self->db, &type);
382 if (makeDBError(err)) {
383 return -1;
384 }
385 return type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000386}
387
388
389/* Create a DBT structure (containing key and data values) from Python
390 strings. Returns 1 on success, 0 on an error. */
391static int make_dbt(PyObject* obj, DBT* dbt)
392{
393 CLEAR_DBT(*dbt);
394 if (obj == Py_None) {
395 /* no need to do anything, the structure has already been zeroed */
396 }
397 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
398 PyErr_SetString(PyExc_TypeError,
Jesus Cea4907d272008-08-31 14:00:51 +0000399#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000400 "Data values must be of type string or None.");
Jesus Cea4907d272008-08-31 14:00:51 +0000401#else
402 "Data values must be of type bytes or None.");
403#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000404 return 0;
405 }
406 return 1;
407}
408
409
410/* Recno and Queue DBs can have integer keys. This function figures out
411 what's been given, verifies that it's allowed, and then makes the DBT.
412
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000413 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000414static int
415make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000416{
417 db_recno_t recno;
418 int type;
419
420 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000421 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000422 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000423 if (type == -1)
424 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000425 if (type == DB_RECNO || type == DB_QUEUE) {
426 PyErr_SetString(
427 PyExc_TypeError,
428 "None keys not allowed for Recno and Queue DB's");
429 return 0;
430 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000431 /* no need to do anything, the structure has already been zeroed */
432 }
433
Christian Heimes593daf52008-05-26 12:51:38 +0000434 else if (PyBytes_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000435 /* verify access method type */
436 type = _DB_get_type(self);
437 if (type == -1)
438 return 0;
439 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000440 PyErr_SetString(
441 PyExc_TypeError,
Jesus Cea4907d272008-08-31 14:00:51 +0000442#if (PY_VERSION_HEX < 0x03000000)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000443 "String keys not allowed for Recno and Queue DB's");
Jesus Cea4907d272008-08-31 14:00:51 +0000444#else
445 "Bytes keys not allowed for Recno and Queue DB's");
446#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000447 return 0;
448 }
449
Gregory P. Smith10bed542007-10-09 06:50:43 +0000450 /*
451 * NOTE(gps): I don't like doing a data copy here, it seems
452 * wasteful. But without a clean way to tell FREE_DBT if it
453 * should free key->data or not we have to. Other places in
454 * the code check for DB_THREAD and forceably set DBT_MALLOC
455 * when we otherwise would leave flags 0 to indicate that.
456 */
Christian Heimes593daf52008-05-26 12:51:38 +0000457 key->data = malloc(PyBytes_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000458 if (key->data == NULL) {
459 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
460 return 0;
461 }
Christian Heimes593daf52008-05-26 12:51:38 +0000462 memcpy(key->data, PyBytes_AS_STRING(keyobj),
463 PyBytes_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000464 key->flags = DB_DBT_REALLOC;
Christian Heimes593daf52008-05-26 12:51:38 +0000465 key->size = PyBytes_GET_SIZE(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000466 }
467
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000468 else if (NUMBER_Check(keyobj)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000469 /* verify access method type */
470 type = _DB_get_type(self);
471 if (type == -1)
472 return 0;
473 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000474 /* if BTREE then an Integer key is allowed with the
475 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000476 *pflags |= DB_SET_RECNO;
477 }
478 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000479 PyErr_SetString(
480 PyExc_TypeError,
481 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000482 return 0;
483 }
484
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000485 /* Make a key out of the requested recno, use allocated space so DB
486 * will be able to realloc room for the real key if needed. */
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000487 recno = NUMBER_AsLong(keyobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000488 key->data = malloc(sizeof(db_recno_t));
489 if (key->data == NULL) {
490 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
491 return 0;
492 }
493 key->ulen = key->size = sizeof(db_recno_t);
494 memcpy(key->data, &recno, sizeof(db_recno_t));
495 key->flags = DB_DBT_REALLOC;
496 }
497 else {
498 PyErr_Format(PyExc_TypeError,
Jesus Cea4907d272008-08-31 14:00:51 +0000499#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000500 "String or Integer object expected for key, %s found",
Jesus Cea4907d272008-08-31 14:00:51 +0000501#else
502 "Bytes or Integer object expected for key, %s found",
503#endif
Christian Heimese93237d2007-12-19 02:37:44 +0000504 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000505 return 0;
506 }
507
508 return 1;
509}
510
511
512/* Add partial record access to an existing DBT data struct.
513 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
514 and the data storage/retrieval will be done using dlen and doff. */
515static int add_partial_dbt(DBT* d, int dlen, int doff) {
516 /* if neither were set we do nothing (-1 is the default value) */
517 if ((dlen == -1) && (doff == -1)) {
518 return 1;
519 }
520
521 if ((dlen < 0) || (doff < 0)) {
522 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
523 return 0;
524 }
525
526 d->flags = d->flags | DB_DBT_PARTIAL;
527 d->dlen = (unsigned int) dlen;
528 d->doff = (unsigned int) doff;
529 return 1;
530}
531
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000532/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
533/* TODO: make this use the native libc strlcpy() when available (BSD) */
534unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
535{
536 unsigned int srclen, copylen;
537
538 srclen = strlen(src);
539 if (n <= 0)
540 return srclen;
541 copylen = (srclen > n-1) ? n-1 : srclen;
542 /* populate dest[0] thru dest[copylen-1] */
543 memcpy(dest, src, copylen);
544 /* guarantee null termination */
545 dest[copylen] = 0;
546
547 return srclen;
548}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000549
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000550/* Callback used to save away more information about errors from the DB
551 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000552static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000553#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000554static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000555#else
556static void _db_errorCallback(const DB_ENV *db_env,
557 const char* prefix, const char* msg)
558#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000559{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000560 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000561}
562
563
Jesus Ceaef9764f2008-05-13 18:45:46 +0000564/*
565** We need these functions because some results
566** are undefined if pointer is NULL. Some other
567** give None instead of "".
568**
569** This functions are static and will be
570** -I hope- inlined.
571*/
572static const char *DummyString = "This string is a simple placeholder";
573static PyObject *Build_PyString(const char *p,int s)
574{
575 if (!p) {
576 p=DummyString;
577 assert(s==0);
578 }
Christian Heimes593daf52008-05-26 12:51:38 +0000579 return PyBytes_FromStringAndSize(p,s);
Jesus Ceaef9764f2008-05-13 18:45:46 +0000580}
581
582static PyObject *BuildValue_S(const void *p,int s)
583{
584 if (!p) {
585 p=DummyString;
586 assert(s==0);
587 }
Jesus Cea4907d272008-08-31 14:00:51 +0000588 return PyBytes_FromStringAndSize(p, s);
Jesus Ceaef9764f2008-05-13 18:45:46 +0000589}
590
591static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
592{
Jesus Cea4907d272008-08-31 14:00:51 +0000593PyObject *a, *b, *r;
594
Jesus Ceaef9764f2008-05-13 18:45:46 +0000595 if (!p1) {
596 p1=DummyString;
597 assert(s1==0);
598 }
599 if (!p2) {
600 p2=DummyString;
601 assert(s2==0);
602 }
Jesus Cea4907d272008-08-31 14:00:51 +0000603
604 if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
605 return NULL;
606 }
607 if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
608 Py_DECREF(a);
609 return NULL;
610 }
611
612#if (PY_VERSION_HEX >= 0x02040000)
613 r = PyTuple_Pack(2, a, b) ;
614#else
615 r = Py_BuildValue("OO", a, b);
616#endif
617 Py_DECREF(a);
618 Py_DECREF(b);
619 return r;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000620}
621
622static PyObject *BuildValue_IS(int i,const void *p,int s)
623{
Jesus Cea4907d272008-08-31 14:00:51 +0000624 PyObject *a, *r;
625
Jesus Ceaef9764f2008-05-13 18:45:46 +0000626 if (!p) {
627 p=DummyString;
628 assert(s==0);
629 }
Jesus Cea4907d272008-08-31 14:00:51 +0000630
631 if (!(a = PyBytes_FromStringAndSize(p, s))) {
632 return NULL;
633 }
634
635 r = Py_BuildValue("iO", i, a);
636 Py_DECREF(a);
637 return r;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000638}
639
Jesus Cea4907d272008-08-31 14:00:51 +0000640static PyObject *BuildValue_LS(long l,const void *p,int s)
Jesus Ceaef9764f2008-05-13 18:45:46 +0000641{
Jesus Cea4907d272008-08-31 14:00:51 +0000642 PyObject *a, *r;
643
Jesus Ceaef9764f2008-05-13 18:45:46 +0000644 if (!p) {
645 p=DummyString;
646 assert(s==0);
647 }
Jesus Cea4907d272008-08-31 14:00:51 +0000648
649 if (!(a = PyBytes_FromStringAndSize(p, s))) {
650 return NULL;
651 }
652
653 r = Py_BuildValue("lO", l, a);
654 Py_DECREF(a);
655 return r;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000656}
657
658
659
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000660/* make a nice exception object to raise for errors. */
661static int makeDBError(int err)
662{
663 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000664 PyObject *errObj = NULL;
665 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000666 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000667 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000668
669 switch (err) {
670 case 0: /* successful, no error */ break;
671
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000672#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000673 case DB_INCOMPLETE:
674#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000675 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
676 /* Ensure that bytes_left never goes negative */
677 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
678 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
679 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000680 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000681 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000682 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000683 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000684 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000685
686#else /* do an exception instead */
687 errObj = DBIncompleteError;
688#endif
689 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000690#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000691
692 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
693 case DB_KEYEXIST: errObj = DBKeyExistError; break;
694 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
695 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
696 case DB_NOTFOUND: errObj = DBNotFoundError; break;
697 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
698 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
699 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
700 case DB_NOSERVER: errObj = DBNoServerError; break;
701 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
702 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000703 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
704 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000705 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000706
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000707#if (DBVER >= 43)
708 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
709 case ENOMEM: errObj = PyExc_MemoryError; break;
710#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000711 case EINVAL: errObj = DBInvalidArgError; break;
712 case EACCES: errObj = DBAccessError; break;
713 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000714 case EAGAIN: errObj = DBAgainError; break;
715 case EBUSY : errObj = DBBusyError; break;
716 case EEXIST: errObj = DBFileExistsError; break;
717 case ENOENT: errObj = DBNoSuchFileError; break;
718 case EPERM : errObj = DBPermissionsError; break;
719
Jesus Ceaef9764f2008-05-13 18:45:46 +0000720#if (DBVER >= 42)
721 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
722#endif
723
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000724 case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
725
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000726 default: errObj = DBError; break;
727 }
728
729 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000730 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
731 /* Ensure that bytes_left never goes negative */
732 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
733 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
734 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000735 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000736 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000737 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000738 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000739
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000740 errTuple = Py_BuildValue("(is)", err, errTxt);
741 if (errTuple == NULL) {
742 Py_DECREF(errObj);
743 return !0;
744 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000745 PyErr_SetObject(errObj, errTuple);
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000746 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000747 }
748
749 return ((errObj != NULL) || exceptionRaised);
750}
751
752
753
754/* set a type exception */
755static void makeTypeError(char* expected, PyObject* found)
756{
757 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimese93237d2007-12-19 02:37:44 +0000758 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000759}
760
761
762/* verify that an obj is either None or a DBTxn, and set the txn pointer */
763static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
764{
765 if (txnobj == Py_None || txnobj == NULL) {
766 *txn = NULL;
767 return 1;
768 }
769 if (DBTxnObject_Check(txnobj)) {
770 *txn = ((DBTxnObject*)txnobj)->txn;
771 return 1;
772 }
773 else
774 makeTypeError("DBTxn", txnobj);
775 return 0;
776}
777
778
779/* Delete a key from a database
780 Returns 0 on success, -1 on an error. */
781static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
782{
783 int err;
784
785 MYDB_BEGIN_ALLOW_THREADS;
786 err = self->db->del(self->db, txn, key, 0);
787 MYDB_END_ALLOW_THREADS;
788 if (makeDBError(err)) {
789 return -1;
790 }
791 self->haveStat = 0;
792 return 0;
793}
794
795
796/* Store a key into a database
797 Returns 0 on success, -1 on an error. */
798static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
799{
800 int err;
801
802 MYDB_BEGIN_ALLOW_THREADS;
803 err = self->db->put(self->db, txn, key, data, flags);
804 MYDB_END_ALLOW_THREADS;
805 if (makeDBError(err)) {
806 return -1;
807 }
808 self->haveStat = 0;
809 return 0;
810}
811
812/* Get a key/data pair from a cursor */
813static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
814 PyObject *args, PyObject *kwargs, char *format)
815{
816 int err;
817 PyObject* retval = NULL;
818 DBT key, data;
819 int dlen = -1;
820 int doff = -1;
821 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000822 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000823
824 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
825 &flags, &dlen, &doff))
826 return NULL;
827
828 CHECK_CURSOR_NOT_CLOSED(self);
829
830 flags |= extra_flags;
831 CLEAR_DBT(key);
832 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000833 if (!add_partial_dbt(&data, dlen, doff))
834 return NULL;
835
836 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000837 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000838 MYDB_END_ALLOW_THREADS;
839
Gregory P. Smithe9477062005-06-04 06:46:59 +0000840 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
841 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000842 Py_INCREF(Py_None);
843 retval = Py_None;
844 }
845 else if (makeDBError(err)) {
846 retval = NULL;
847 }
848 else { /* otherwise, success! */
849
850 /* if Recno or Queue, return the key as an Int */
851 switch (_DB_get_type(self->mydb)) {
852 case -1:
853 retval = NULL;
854 break;
855
856 case DB_RECNO:
857 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000858 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000859 break;
860 case DB_HASH:
861 case DB_BTREE:
862 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000863 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000864 break;
865 }
866 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000867 return retval;
868}
869
870
871/* add an integer to a dictionary using the given name as a key */
872static void _addIntToDict(PyObject* dict, char *name, int value)
873{
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000874 PyObject* v = NUMBER_FromLong((long) value);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000875 if (!v || PyDict_SetItemString(dict, name, v))
876 PyErr_Clear();
877
878 Py_XDECREF(v);
879}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000880
881/* The same, when the value is a time_t */
882static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
883{
884 PyObject* v;
885 /* if the value fits in regular int, use that. */
Jesus Ceaef9764f2008-05-13 18:45:46 +0000886#ifdef PY_LONG_LONG
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000887 if (sizeof(time_t) > sizeof(long))
888 v = PyLong_FromLongLong((PY_LONG_LONG) value);
889 else
890#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000891 v = NUMBER_FromLong((long) value);
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000892 if (!v || PyDict_SetItemString(dict, name, v))
893 PyErr_Clear();
894
895 Py_XDECREF(v);
896}
897
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000898#if (DBVER >= 43)
899/* add an db_seq_t to a dictionary using the given name as a key */
900static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
901{
902 PyObject* v = PyLong_FromLongLong(value);
903 if (!v || PyDict_SetItemString(dict, name, v))
904 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000905
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000906 Py_XDECREF(v);
907}
908#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000909
Jesus Ceaef9764f2008-05-13 18:45:46 +0000910static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
911{
912 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
913 if (!v || PyDict_SetItemString(dict, name, v))
914 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000915
Jesus Ceaef9764f2008-05-13 18:45:46 +0000916 Py_XDECREF(v);
917}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000918
919/* --------------------------------------------------------------------- */
920/* Allocators and deallocators */
921
922static DBObject*
923newDBObject(DBEnvObject* arg, int flags)
924{
925 DBObject* self;
926 DB_ENV* db_env = NULL;
927 int err;
928
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000929 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000930 if (self == NULL)
931 return NULL;
932
933 self->haveStat = 0;
934 self->flags = 0;
935 self->setflags = 0;
936 self->myenvobj = NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000937 self->db = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000938 self->children_cursors = NULL;
939#if (DBVER >=43)
940 self->children_sequences = NULL;
941#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000943 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000944 self->primaryDBType = 0;
Jesus Ceac5a11fa2008-07-23 11:38:42 +0000945 Py_INCREF(Py_None);
Jesus Cea4907d272008-08-31 14:00:51 +0000946 self->private_obj = Py_None;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000947 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000948
949 /* keep a reference to our python DBEnv object */
950 if (arg) {
951 Py_INCREF(arg);
952 self->myenvobj = arg;
953 db_env = arg->db_env;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000954 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
955 } else {
956 self->sibling_prev_p=NULL;
957 self->sibling_next=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000958 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000959 self->txn=NULL;
960 self->sibling_prev_p_txn=NULL;
961 self->sibling_next_txn=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000962
963 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000964 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000965 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000966 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
967 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000968
969 MYDB_BEGIN_ALLOW_THREADS;
970 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000971 if (self->db != NULL) {
972 self->db->set_errcall(self->db, _db_errorCallback);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000973 self->db->app_private = (void*)self;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000974 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000975 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000976 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
977 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000978 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000979 if (makeDBError(err)) {
980 if (self->myenvobj) {
981 Py_DECREF(self->myenvobj);
982 self->myenvobj = NULL;
983 }
Gregory P. Smith664782e2008-05-17 06:12:02 +0000984 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000985 self = NULL;
986 }
987 return self;
988}
989
990
Jesus Ceaef9764f2008-05-13 18:45:46 +0000991/* Forward declaration */
992static PyObject *DB_close_internal(DBObject* self, int flags);
993
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000994static void
995DB_dealloc(DBObject* self)
996{
Jesus Ceaef9764f2008-05-13 18:45:46 +0000997 PyObject *dummy;
998
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000999 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001000 dummy=DB_close_internal(self,0);
1001 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001002 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001003 if (self->in_weakreflist != NULL) {
1004 PyObject_ClearWeakRefs((PyObject *) self);
1005 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001006 if (self->myenvobj) {
1007 Py_DECREF(self->myenvobj);
1008 self->myenvobj = NULL;
1009 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001010 if (self->associateCallback != NULL) {
1011 Py_DECREF(self->associateCallback);
1012 self->associateCallback = NULL;
1013 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00001014 if (self->btCompareCallback != NULL) {
1015 Py_DECREF(self->btCompareCallback);
1016 self->btCompareCallback = NULL;
1017 }
Jesus Cea4907d272008-08-31 14:00:51 +00001018 Py_DECREF(self->private_obj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001019 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001020}
1021
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001022static DBCursorObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001023newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001024{
Neal Norwitzb4a55812004-07-09 23:30:57 +00001025 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001026 if (self == NULL)
1027 return NULL;
1028
1029 self->dbc = dbc;
1030 self->mydb = db;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001031
1032 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
1033 if (txn && ((PyObject *)txn!=Py_None)) {
1034 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
1035 self->txn=txn;
1036 } else {
1037 self->txn=NULL;
1038 }
1039
Gregory P. Smitha703a212003-11-03 01:04:41 +00001040 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001041 Py_INCREF(self->mydb);
1042 return self;
1043}
1044
1045
Jesus Ceaef9764f2008-05-13 18:45:46 +00001046/* Forward declaration */
1047static PyObject *DBC_close_internal(DBCursorObject* self);
1048
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001049static void
1050DBCursor_dealloc(DBCursorObject* self)
1051{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001052 PyObject *dummy;
Gregory P. Smitha703a212003-11-03 01:04:41 +00001053
Jesus Ceaef9764f2008-05-13 18:45:46 +00001054 if (self->dbc != NULL) {
1055 dummy=DBC_close_internal(self);
1056 Py_XDECREF(dummy);
1057 }
Gregory P. Smitha703a212003-11-03 01:04:41 +00001058 if (self->in_weakreflist != NULL) {
1059 PyObject_ClearWeakRefs((PyObject *) self);
1060 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001061 Py_DECREF(self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001062 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001063}
1064
1065
1066static DBEnvObject*
1067newDBEnvObject(int flags)
1068{
1069 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001070 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001071 if (self == NULL)
1072 return NULL;
1073
1074 self->closed = 1;
1075 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001076 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1077 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001078 self->children_dbs = NULL;
1079 self->children_txns = NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001080 Py_INCREF(Py_None);
Jesus Cea4907d272008-08-31 14:00:51 +00001081 self->private_obj = Py_None;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001082 Py_INCREF(Py_None);
1083 self->rep_transport = Py_None;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001084 self->in_weakreflist = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001085 self->event_notifyCallback = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001086
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001087 MYDB_BEGIN_ALLOW_THREADS;
1088 err = db_env_create(&self->db_env, flags);
1089 MYDB_END_ALLOW_THREADS;
1090 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001091 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001092 self = NULL;
1093 }
1094 else {
1095 self->db_env->set_errcall(self->db_env, _db_errorCallback);
Jesus Cea4907d272008-08-31 14:00:51 +00001096 self->db_env->app_private = self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001097 }
1098 return self;
1099}
1100
Jesus Ceaef9764f2008-05-13 18:45:46 +00001101/* Forward declaration */
1102static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001103
1104static void
1105DBEnv_dealloc(DBEnvObject* self)
1106{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001107 PyObject *dummy;
1108
Jesus Ceaac25fab2008-09-03 17:50:32 +00001109 if (self->db_env) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001110 dummy=DBEnv_close_internal(self,0);
1111 Py_XDECREF(dummy);
1112 }
1113
Jesus Ceaef9764f2008-05-13 18:45:46 +00001114 Py_XDECREF(self->event_notifyCallback);
1115 self->event_notifyCallback = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001116
Gregory P. Smith31c50652004-06-28 01:20:40 +00001117 if (self->in_weakreflist != NULL) {
1118 PyObject_ClearWeakRefs((PyObject *) self);
1119 }
Jesus Cea4907d272008-08-31 14:00:51 +00001120 Py_DECREF(self->private_obj);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001121 Py_DECREF(self->rep_transport);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001122 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001123}
1124
1125
1126static DBTxnObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001127newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001128{
1129 int err;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001130 DB_TXN *parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001131
Neal Norwitzb4a55812004-07-09 23:30:57 +00001132 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001133 if (self == NULL)
1134 return NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001135
Gregory P. Smith31c50652004-06-28 01:20:40 +00001136 self->in_weakreflist = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001137 self->children_txns = NULL;
1138 self->children_dbs = NULL;
1139 self->children_cursors = NULL;
1140 self->children_sequences = NULL;
1141 self->flag_prepare = 0;
1142 self->parent_txn = NULL;
1143 self->env = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001144
Jesus Ceaef9764f2008-05-13 18:45:46 +00001145 if (parent && ((PyObject *)parent!=Py_None)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001146 parent_txn = parent->txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001147 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001148
1149 if (txn) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001150 self->txn = txn;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001151 } else {
1152 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001153 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001154 MYDB_END_ALLOW_THREADS;
1155
1156 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001157 Py_DECREF(self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001158 return NULL;
1159 }
1160 }
1161
Gregory P. Smith664782e2008-05-17 06:12:02 +00001162 /* Can't use 'parent' because could be 'parent==Py_None' */
1163 if (parent_txn) {
1164 self->parent_txn = parent;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001165 Py_INCREF(parent);
1166 self->env = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001167 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001168 } else {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001169 self->parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001170 Py_INCREF(myenv);
1171 self->env = myenv;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001172 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001173 }
1174
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001175 return self;
1176}
1177
Jesus Ceaef9764f2008-05-13 18:45:46 +00001178/* Forward declaration */
1179static PyObject *
1180DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001181
1182static void
1183DBTxn_dealloc(DBTxnObject* self)
1184{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001185 PyObject *dummy;
1186
1187 if (self->txn) {
1188 int flag_prepare = self->flag_prepare;
1189 dummy=DBTxn_abort_discard_internal(self,0);
1190 Py_XDECREF(dummy);
1191 if (!flag_prepare) {
1192 PyErr_Warn(PyExc_RuntimeWarning,
1193 "DBTxn aborted in destructor. No prior commit() or abort().");
1194 }
1195 }
1196
Gregory P. Smith31c50652004-06-28 01:20:40 +00001197 if (self->in_weakreflist != NULL) {
1198 PyObject_ClearWeakRefs((PyObject *) self);
1199 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001200
Jesus Ceaef9764f2008-05-13 18:45:46 +00001201 if (self->env) {
1202 Py_DECREF(self->env);
1203 } else {
1204 Py_DECREF(self->parent_txn);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001205 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001206 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001207}
1208
1209
1210static DBLockObject*
1211newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1212 db_lockmode_t lock_mode, int flags)
1213{
1214 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001215 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001216 if (self == NULL)
1217 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001218 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001219
1220 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001221 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1222 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001223 MYDB_END_ALLOW_THREADS;
1224 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001225 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001226 self = NULL;
1227 }
1228
1229 return self;
1230}
1231
1232
1233static void
1234DBLock_dealloc(DBLockObject* self)
1235{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001236 if (self->in_weakreflist != NULL) {
1237 PyObject_ClearWeakRefs((PyObject *) self);
1238 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001239 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001240
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001241 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001242}
1243
1244
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001245#if (DBVER >= 43)
1246static DBSequenceObject*
1247newDBSequenceObject(DBObject* mydb, int flags)
1248{
1249 int err;
1250 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1251 if (self == NULL)
1252 return NULL;
1253 Py_INCREF(mydb);
1254 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001255
Jesus Ceaef9764f2008-05-13 18:45:46 +00001256 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
Gregory P. Smith664782e2008-05-17 06:12:02 +00001257 self->txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001258
1259 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001260
1261 MYDB_BEGIN_ALLOW_THREADS;
1262 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1263 MYDB_END_ALLOW_THREADS;
1264 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001265 Py_DECREF(self);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001266 self = NULL;
1267 }
1268
1269 return self;
1270}
1271
Jesus Ceaef9764f2008-05-13 18:45:46 +00001272/* Forward declaration */
1273static PyObject
1274*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001275
1276static void
1277DBSequence_dealloc(DBSequenceObject* self)
1278{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001279 PyObject *dummy;
1280
1281 if (self->sequence != NULL) {
1282 dummy=DBSequence_close_internal(self,0,0);
1283 Py_XDECREF(dummy);
1284 }
1285
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001286 if (self->in_weakreflist != NULL) {
1287 PyObject_ClearWeakRefs((PyObject *) self);
1288 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001289
1290 Py_DECREF(self->mydb);
1291 PyObject_Del(self);
1292}
1293#endif
1294
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001295/* --------------------------------------------------------------------- */
1296/* DB methods */
1297
1298static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00001299DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001300{
1301 PyObject* txnobj = NULL;
1302 PyObject* dataobj;
1303 db_recno_t recno;
1304 DBT key, data;
1305 DB_TXN *txn = NULL;
Jesus Cea4907d272008-08-31 14:00:51 +00001306 static char* kwnames[] = { "data", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001307
Jesus Cea4907d272008-08-31 14:00:51 +00001308 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
1309 &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001310 return NULL;
1311
1312 CHECK_DB_NOT_CLOSED(self);
1313
1314 /* make a dummy key out of a recno */
1315 recno = 0;
1316 CLEAR_DBT(key);
1317 key.data = &recno;
1318 key.size = sizeof(recno);
1319 key.ulen = key.size;
1320 key.flags = DB_DBT_USERMEM;
1321
1322 if (!make_dbt(dataobj, &data)) return NULL;
1323 if (!checkTxnObj(txnobj, &txn)) return NULL;
1324
1325 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1326 return NULL;
1327
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001328 return NUMBER_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001329}
1330
1331
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001332static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001333_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1334 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001335{
1336 int retval = DB_DONOTINDEX;
1337 DBObject* secondaryDB = (DBObject*)db->app_private;
1338 PyObject* callback = secondaryDB->associateCallback;
1339 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001340 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001341 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001342
1343
1344 if (callback != NULL) {
1345 MYDB_BEGIN_BLOCK_THREADS;
1346
Thomas Woutersb3153832006-03-08 01:47:19 +00001347 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceaef9764f2008-05-13 18:45:46 +00001348 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
Thomas Woutersb3153832006-03-08 01:47:19 +00001349 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001350 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001351 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001352 result = PyEval_CallObject(callback, args);
1353 }
1354 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001355 PyErr_Print();
1356 }
1357 else if (result == Py_None) {
1358 retval = DB_DONOTINDEX;
1359 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001360 else if (NUMBER_Check(result)) {
1361 retval = NUMBER_AsLong(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001362 }
Christian Heimes593daf52008-05-26 12:51:38 +00001363 else if (PyBytes_Check(result)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001364 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001365 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001366
1367 CLEAR_DBT(*secKey);
Christian Heimes593daf52008-05-26 12:51:38 +00001368 PyBytes_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001369 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1370 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001371 if (secKey->data) {
1372 memcpy(secKey->data, data, size);
1373 secKey->size = size;
1374 retval = 0;
1375 }
1376 else {
1377 PyErr_SetString(PyExc_MemoryError,
1378 "malloc failed in _db_associateCallback");
1379 PyErr_Print();
1380 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001381 }
1382 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001383 PyErr_SetString(
1384 PyExc_TypeError,
1385 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001386 PyErr_Print();
1387 }
1388
Thomas Woutersb3153832006-03-08 01:47:19 +00001389 Py_XDECREF(args);
1390 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001391
1392 MYDB_END_BLOCK_THREADS;
1393 }
1394 return retval;
1395}
1396
1397
1398static PyObject*
1399DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1400{
1401 int err, flags=0;
1402 DBObject* secondaryDB;
1403 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001404#if (DBVER >= 41)
1405 PyObject *txnobj = NULL;
1406 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001407 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001408 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001409#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001410 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001411#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001412
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001413#if (DBVER >= 41)
1414 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1415 &secondaryDB, &callback, &flags,
1416 &txnobj)) {
1417#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001418 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001419 &secondaryDB, &callback, &flags)) {
1420#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001421 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001422 }
1423
1424#if (DBVER >= 41)
1425 if (!checkTxnObj(txnobj, &txn)) return NULL;
1426#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427
1428 CHECK_DB_NOT_CLOSED(self);
1429 if (!DBObject_Check(secondaryDB)) {
1430 makeTypeError("DB", (PyObject*)secondaryDB);
1431 return NULL;
1432 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001433 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001434 if (callback == Py_None) {
1435 callback = NULL;
1436 }
1437 else if (!PyCallable_Check(callback)) {
1438 makeTypeError("Callable", callback);
1439 return NULL;
1440 }
1441
1442 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001443 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001444 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001445 secondaryDB->associateCallback = callback;
1446 secondaryDB->primaryDBType = _DB_get_type(self);
1447
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001448 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1449 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1450 * The global interepreter lock is not initialized until the first
1451 * thread is created using thread.start_new_thread() or fork() is
1452 * called. that would cause the ALLOW_THREADS here to segfault due
1453 * to a null pointer reference if no threads or child processes
1454 * have been created. This works around that and is a no-op if
1455 * threads have already been initialized.
1456 * (see pybsddb-users mailing list post on 2002-08-07)
1457 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001458#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001459 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001460#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001461 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001462#if (DBVER >= 41)
1463 err = self->db->associate(self->db,
1464 txn,
1465 secondaryDB->db,
1466 _db_associateCallback,
1467 flags);
1468#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001469 err = self->db->associate(self->db,
1470 secondaryDB->db,
1471 _db_associateCallback,
1472 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001473#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001474 MYDB_END_ALLOW_THREADS;
1475
1476 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001477 Py_XDECREF(secondaryDB->associateCallback);
1478 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001479 secondaryDB->primaryDBType = 0;
1480 }
1481
1482 RETURN_IF_ERR();
1483 RETURN_NONE();
1484}
1485
1486
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001487static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001488DB_close_internal(DBObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001489{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001490 PyObject *dummy;
1491 int err;
1492
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001493 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001494 /* Can be NULL if db is not in an environment */
1495 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
Jesus Cea4907d272008-08-31 14:00:51 +00001496
Jesus Ceaef9764f2008-05-13 18:45:46 +00001497 if (self->txn) {
1498 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1499 self->txn=NULL;
1500 }
1501
1502 while(self->children_cursors) {
1503 dummy=DBC_close_internal(self->children_cursors);
1504 Py_XDECREF(dummy);
1505 }
1506
1507#if (DBVER >= 43)
1508 while(self->children_sequences) {
1509 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1510 Py_XDECREF(dummy);
1511 }
1512#endif
1513
1514 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001515 err = self->db->close(self->db, flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001516 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001517 self->db = NULL;
1518 RETURN_IF_ERR();
1519 }
1520 RETURN_NONE();
1521}
1522
Jesus Ceaef9764f2008-05-13 18:45:46 +00001523static PyObject*
1524DB_close(DBObject* self, PyObject* args)
1525{
1526 int flags=0;
1527 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1528 return NULL;
1529 return DB_close_internal(self,flags);
1530}
1531
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001532
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001533static PyObject*
1534_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1535{
1536 int err, flags=0, type;
1537 PyObject* txnobj = NULL;
1538 PyObject* retval = NULL;
1539 DBT key, data;
1540 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001541 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001542
1543 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1544 &txnobj, &flags))
1545 return NULL;
1546
1547 CHECK_DB_NOT_CLOSED(self);
1548 type = _DB_get_type(self);
1549 if (type == -1)
1550 return NULL;
1551 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001552 PyErr_SetString(PyExc_TypeError,
1553 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001554 return NULL;
1555 }
1556 if (!checkTxnObj(txnobj, &txn))
1557 return NULL;
1558
1559 CLEAR_DBT(key);
1560 CLEAR_DBT(data);
1561 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001562 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001563 data.flags = DB_DBT_MALLOC;
1564 key.flags = DB_DBT_MALLOC;
1565 }
1566
1567 MYDB_BEGIN_ALLOW_THREADS;
1568 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1569 MYDB_END_ALLOW_THREADS;
1570
Gregory P. Smithe9477062005-06-04 06:46:59 +00001571 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1572 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001573 err = 0;
1574 Py_INCREF(Py_None);
1575 retval = Py_None;
1576 }
1577 else if (!err) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001578 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001579 FREE_DBT(key);
1580 FREE_DBT(data);
1581 }
1582
1583 RETURN_IF_ERR();
1584 return retval;
1585}
1586
1587static PyObject*
1588DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1589{
1590 return _DB_consume(self, args, kwargs, DB_CONSUME);
1591}
1592
1593static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001594DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1595 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001596{
1597 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1598}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001599
1600
1601static PyObject*
1602DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1603{
1604 int err, flags=0;
1605 DBC* dbc;
1606 PyObject* txnobj = NULL;
1607 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001608 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001609
1610 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1611 &txnobj, &flags))
1612 return NULL;
1613 CHECK_DB_NOT_CLOSED(self);
1614 if (!checkTxnObj(txnobj, &txn))
1615 return NULL;
1616
1617 MYDB_BEGIN_ALLOW_THREADS;
1618 err = self->db->cursor(self->db, txn, &dbc, flags);
1619 MYDB_END_ALLOW_THREADS;
1620 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001621 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001622}
1623
1624
1625static PyObject*
1626DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1627{
1628 PyObject* txnobj = NULL;
1629 int flags = 0;
1630 PyObject* keyobj;
1631 DBT key;
1632 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001633 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001634
1635 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1636 &keyobj, &txnobj, &flags))
1637 return NULL;
1638 CHECK_DB_NOT_CLOSED(self);
1639 if (!make_key_dbt(self, keyobj, &key, NULL))
1640 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001641 if (!checkTxnObj(txnobj, &txn)) {
1642 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001643 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001644 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001645
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001646 if (-1 == _DB_delete(self, txn, &key, 0)) {
1647 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001648 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001649 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001650
1651 FREE_DBT(key);
1652 RETURN_NONE();
1653}
1654
1655
1656static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001657DB_fd(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001658{
1659 int err, the_fd;
1660
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001661 CHECK_DB_NOT_CLOSED(self);
1662
1663 MYDB_BEGIN_ALLOW_THREADS;
1664 err = self->db->fd(self->db, &the_fd);
1665 MYDB_END_ALLOW_THREADS;
1666 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001667 return NUMBER_FromLong(the_fd);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001668}
1669
1670
1671static PyObject*
1672DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1673{
1674 int err, flags=0;
1675 PyObject* txnobj = NULL;
1676 PyObject* keyobj;
1677 PyObject* dfltobj = NULL;
1678 PyObject* retval = NULL;
1679 int dlen = -1;
1680 int doff = -1;
1681 DBT key, data;
1682 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001683 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001684 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001685
1686 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001687 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1688 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001689 return NULL;
1690
1691 CHECK_DB_NOT_CLOSED(self);
1692 if (!make_key_dbt(self, keyobj, &key, &flags))
1693 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001694 if (!checkTxnObj(txnobj, &txn)) {
1695 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001696 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001697 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001698
1699 CLEAR_DBT(data);
1700 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001701 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001702 data.flags = DB_DBT_MALLOC;
1703 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001704 if (!add_partial_dbt(&data, dlen, doff)) {
1705 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001706 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001707 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001708
1709 MYDB_BEGIN_ALLOW_THREADS;
1710 err = self->db->get(self->db, txn, &key, &data, flags);
1711 MYDB_END_ALLOW_THREADS;
1712
Gregory P. Smithe9477062005-06-04 06:46:59 +00001713 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001714 err = 0;
1715 Py_INCREF(dfltobj);
1716 retval = dfltobj;
1717 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001718 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1719 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001720 err = 0;
1721 Py_INCREF(Py_None);
1722 retval = Py_None;
1723 }
1724 else if (!err) {
1725 if (flags & DB_SET_RECNO) /* return both key and data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001726 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001727 else /* return just the data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001728 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001729 FREE_DBT(data);
1730 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001731 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001732
1733 RETURN_IF_ERR();
1734 return retval;
1735}
1736
Gregory P. Smith19699a92004-06-28 04:06:49 +00001737static PyObject*
1738DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1739{
1740 int err, flags=0;
1741 PyObject* txnobj = NULL;
1742 PyObject* keyobj;
1743 PyObject* dfltobj = NULL;
1744 PyObject* retval = NULL;
1745 int dlen = -1;
1746 int doff = -1;
1747 DBT key, pkey, data;
1748 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001749 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001750 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001751
1752 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1753 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1754 &doff))
1755 return NULL;
1756
1757 CHECK_DB_NOT_CLOSED(self);
1758 if (!make_key_dbt(self, keyobj, &key, &flags))
1759 return NULL;
1760 if (!checkTxnObj(txnobj, &txn)) {
1761 FREE_DBT(key);
1762 return NULL;
1763 }
1764
1765 CLEAR_DBT(data);
1766 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001767 /* Tell Berkeley DB to malloc the return value (thread safe) */
Gregory P. Smith19699a92004-06-28 04:06:49 +00001768 data.flags = DB_DBT_MALLOC;
1769 }
1770 if (!add_partial_dbt(&data, dlen, doff)) {
1771 FREE_DBT(key);
1772 return NULL;
1773 }
1774
1775 CLEAR_DBT(pkey);
1776 pkey.flags = DB_DBT_MALLOC;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001777
Gregory P. Smith19699a92004-06-28 04:06:49 +00001778 MYDB_BEGIN_ALLOW_THREADS;
1779 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1780 MYDB_END_ALLOW_THREADS;
1781
Gregory P. Smithe9477062005-06-04 06:46:59 +00001782 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001783 err = 0;
1784 Py_INCREF(dfltobj);
1785 retval = dfltobj;
1786 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001787 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1788 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001789 err = 0;
1790 Py_INCREF(Py_None);
1791 retval = Py_None;
1792 }
1793 else if (!err) {
1794 PyObject *pkeyObj;
1795 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001796 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001797
1798 if (self->primaryDBType == DB_RECNO ||
1799 self->primaryDBType == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001800 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001801 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001802 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001803
1804 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1805 {
1806 PyObject *keyObj;
1807 int type = _DB_get_type(self);
1808 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001809 keyObj = NUMBER_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001810 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001811 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001812#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001813 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001814#else
1815 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1816#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001817 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001818 }
1819 else /* return just the pkey and data */
1820 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001821#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001822 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001823#else
1824 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1825#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001826 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001827 Py_DECREF(dataObj);
1828 Py_DECREF(pkeyObj);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001829 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001830 FREE_DBT(data);
1831 }
1832 FREE_DBT(key);
1833
1834 RETURN_IF_ERR();
1835 return retval;
1836}
1837
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001838
1839/* Return size of entry */
1840static PyObject*
1841DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1842{
1843 int err, flags=0;
1844 PyObject* txnobj = NULL;
1845 PyObject* keyobj;
1846 PyObject* retval = NULL;
1847 DBT key, data;
1848 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001849 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001850
1851 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1852 &keyobj, &txnobj))
1853 return NULL;
1854 CHECK_DB_NOT_CLOSED(self);
1855 if (!make_key_dbt(self, keyobj, &key, &flags))
1856 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001857 if (!checkTxnObj(txnobj, &txn)) {
1858 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001859 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001860 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001861 CLEAR_DBT(data);
1862
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001863 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1864 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001865 data.flags = DB_DBT_USERMEM;
1866 data.ulen = 0;
1867 MYDB_BEGIN_ALLOW_THREADS;
1868 err = self->db->get(self->db, txn, &key, &data, flags);
1869 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001870 if (err == DB_BUFFER_SMALL) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001871 retval = NUMBER_FromLong((long)data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001872 err = 0;
1873 }
1874
1875 FREE_DBT(key);
1876 FREE_DBT(data);
1877 RETURN_IF_ERR();
1878 return retval;
1879}
1880
1881
1882static PyObject*
1883DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1884{
1885 int err, flags=0;
1886 PyObject* txnobj = NULL;
1887 PyObject* keyobj;
1888 PyObject* dataobj;
1889 PyObject* retval = NULL;
1890 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001891 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001892 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001893 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001894
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001895 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1896 &keyobj, &dataobj, &txnobj, &flags))
1897 return NULL;
1898
1899 CHECK_DB_NOT_CLOSED(self);
1900 if (!make_key_dbt(self, keyobj, &key, NULL))
1901 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001902 if ( !make_dbt(dataobj, &data) ||
1903 !checkTxnObj(txnobj, &txn) )
1904 {
1905 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001906 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001907 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001908
1909 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001910 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001911
1912 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001913 /* Tell Berkeley DB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001914 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001915 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001916 }
1917
1918 MYDB_BEGIN_ALLOW_THREADS;
1919 err = self->db->get(self->db, txn, &key, &data, flags);
1920 MYDB_END_ALLOW_THREADS;
1921
Gregory P. Smithe9477062005-06-04 06:46:59 +00001922 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1923 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001924 err = 0;
1925 Py_INCREF(Py_None);
1926 retval = Py_None;
1927 }
1928 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001929 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001930 retval = Build_PyString(data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001931
1932 /* Even though the flags require DB_DBT_MALLOC, data is not always
1933 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1934 if (data.data != orig_data)
1935 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001936 }
1937
1938 FREE_DBT(key);
1939 RETURN_IF_ERR();
1940 return retval;
1941}
1942
1943
1944static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001945DB_get_byteswapped(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001946{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001947 int err = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001948 int retval = -1;
1949
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001950 CHECK_DB_NOT_CLOSED(self);
1951
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001952 MYDB_BEGIN_ALLOW_THREADS;
1953 err = self->db->get_byteswapped(self->db, &retval);
1954 MYDB_END_ALLOW_THREADS;
1955 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001956 return NUMBER_FromLong(retval);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001957}
1958
1959
1960static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001961DB_get_type(DBObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001962{
1963 int type;
1964
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001965 CHECK_DB_NOT_CLOSED(self);
1966
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001967 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001968 if (type == -1)
1969 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00001970 return NUMBER_FromLong(type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001971}
1972
1973
1974static PyObject*
1975DB_join(DBObject* self, PyObject* args)
1976{
1977 int err, flags=0;
1978 int length, x;
1979 PyObject* cursorsObj;
1980 DBC** cursors;
1981 DBC* dbc;
1982
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001983 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1984 return NULL;
1985
1986 CHECK_DB_NOT_CLOSED(self);
1987
1988 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001989 PyErr_SetString(PyExc_TypeError,
1990 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001991 return NULL;
1992 }
1993
1994 length = PyObject_Length(cursorsObj);
1995 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001996 if (!cursors) {
1997 PyErr_NoMemory();
1998 return NULL;
1999 }
2000
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002001 cursors[length] = NULL;
2002 for (x=0; x<length; x++) {
2003 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00002004 if (item == NULL) {
2005 free(cursors);
2006 return NULL;
2007 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002008 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002009 PyErr_SetString(PyExc_TypeError,
2010 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002011 free(cursors);
2012 return NULL;
2013 }
2014 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002015 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002016 }
2017
2018 MYDB_BEGIN_ALLOW_THREADS;
2019 err = self->db->join(self->db, cursors, &dbc, flags);
2020 MYDB_END_ALLOW_THREADS;
2021 free(cursors);
2022 RETURN_IF_ERR();
2023
Gregory P. Smith7441e652003-11-03 21:35:31 +00002024 /* FIXME: this is a buggy interface. The returned cursor
2025 contains internal references to the passed in cursors
2026 but does not hold python references to them or prevent
2027 them from being closed prematurely. This can cause
2028 python to crash when things are done in the wrong order. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00002029 return (PyObject*) newDBCursorObject(dbc, NULL, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002030}
2031
2032
2033static PyObject*
2034DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
2035{
2036 int err, flags=0;
2037 PyObject* txnobj = NULL;
2038 PyObject* keyobj;
2039 DBT key;
2040 DB_TXN *txn = NULL;
2041 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002042 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002043
2044 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
2045 &keyobj, &txnobj, &flags))
2046 return NULL;
2047 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002048 if (!make_dbt(keyobj, &key))
2049 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002050 return NULL;
2051 if (!checkTxnObj(txnobj, &txn))
2052 return NULL;
2053
2054 MYDB_BEGIN_ALLOW_THREADS;
2055 err = self->db->key_range(self->db, txn, &key, &range, flags);
2056 MYDB_END_ALLOW_THREADS;
2057
2058 RETURN_IF_ERR();
2059 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2060}
2061
2062
2063static PyObject*
2064DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2065{
2066 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2067 char* filename = NULL;
2068 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002069#if (DBVER >= 41)
2070 PyObject *txnobj = NULL;
2071 DB_TXN *txn = NULL;
2072 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002073 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002074 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2075 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00002076 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002077 "filename", "dbtype", "flags", "mode", "txn", NULL};
2078#else
2079 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002080 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002081 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2082 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002083 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002084 "filename", "dbtype", "flags", "mode", NULL};
2085#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002086
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002087#if (DBVER >= 41)
2088 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2089 &filename, &dbname, &type, &flags, &mode,
2090 &txnobj))
2091#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002092 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002093 &filename, &dbname, &type, &flags,
2094 &mode))
2095#endif
2096 {
2097 PyErr_Clear();
2098 type = DB_UNKNOWN; flags = 0; mode = 0660;
2099 filename = NULL; dbname = NULL;
2100#if (DBVER >= 41)
2101 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2102 kwnames_basic,
2103 &filename, &type, &flags, &mode,
2104 &txnobj))
2105 return NULL;
2106#else
2107 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2108 kwnames_basic,
2109 &filename, &type, &flags, &mode))
2110 return NULL;
2111#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002112 }
2113
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002114#if (DBVER >= 41)
2115 if (!checkTxnObj(txnobj, &txn)) return NULL;
2116#endif
2117
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002118 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002119 PyObject *t = Py_BuildValue("(is)", 0,
2120 "Cannot call open() twice for DB object");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002121 if (t) {
2122 PyErr_SetObject(DBError, t);
2123 Py_DECREF(t);
2124 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002125 return NULL;
2126 }
2127
Jesus Ceaef9764f2008-05-13 18:45:46 +00002128#if (DBVER >= 41)
2129 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2130 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2131 self->txn=(DBTxnObject *)txnobj;
2132 } else {
2133 self->txn=NULL;
2134 }
2135#else
2136 self->txn=NULL;
2137#endif
2138
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002139 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002140#if (DBVER >= 41)
2141 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2142#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002143 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002144#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002145 MYDB_END_ALLOW_THREADS;
2146 if (makeDBError(err)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002147 PyObject *dummy;
2148
2149 dummy=DB_close_internal(self,0);
2150 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002151 return NULL;
2152 }
2153
Gregory P. Smithfc006692007-11-05 09:06:28 +00002154#if (DBVER >= 42)
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002155 self->db->get_flags(self->db, &self->setflags);
Gregory P. Smithfc006692007-11-05 09:06:28 +00002156#endif
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002157
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002158 self->flags = flags;
Jesus Ceaef9764f2008-05-13 18:45:46 +00002159
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002160 RETURN_NONE();
2161}
2162
2163
2164static PyObject*
2165DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2166{
2167 int flags=0;
2168 PyObject* txnobj = NULL;
2169 int dlen = -1;
2170 int doff = -1;
2171 PyObject* keyobj, *dataobj, *retval;
2172 DBT key, data;
2173 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002174 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002175 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002176
2177 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2178 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2179 return NULL;
2180
2181 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002182 if (!make_key_dbt(self, keyobj, &key, NULL))
2183 return NULL;
2184 if ( !make_dbt(dataobj, &data) ||
2185 !add_partial_dbt(&data, dlen, doff) ||
2186 !checkTxnObj(txnobj, &txn) )
2187 {
2188 FREE_DBT(key);
2189 return NULL;
2190 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002191
2192 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2193 FREE_DBT(key);
2194 return NULL;
2195 }
2196
2197 if (flags & DB_APPEND)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002198 retval = NUMBER_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002199 else {
2200 retval = Py_None;
2201 Py_INCREF(retval);
2202 }
2203 FREE_DBT(key);
2204 return retval;
2205}
2206
2207
2208
2209static PyObject*
2210DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2211{
2212 char* filename;
2213 char* database = NULL;
2214 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002215 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002216
2217 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2218 &filename, &database, &flags))
2219 return NULL;
2220 CHECK_DB_NOT_CLOSED(self);
2221
Jesus Cea4907d272008-08-31 14:00:51 +00002222 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
2223
2224 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002225 err = self->db->remove(self->db, filename, database, flags);
Jesus Cea4907d272008-08-31 14:00:51 +00002226 MYDB_END_ALLOW_THREADS;
2227
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002228 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002229 RETURN_IF_ERR();
2230 RETURN_NONE();
2231}
2232
2233
2234
2235static PyObject*
2236DB_rename(DBObject* self, PyObject* args)
2237{
2238 char* filename;
2239 char* database;
2240 char* newname;
2241 int err, flags=0;
2242
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002243 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2244 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002245 return NULL;
2246 CHECK_DB_NOT_CLOSED(self);
2247
2248 MYDB_BEGIN_ALLOW_THREADS;
2249 err = self->db->rename(self->db, filename, database, newname, flags);
2250 MYDB_END_ALLOW_THREADS;
2251 RETURN_IF_ERR();
2252 RETURN_NONE();
2253}
2254
2255
2256static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002257DB_get_private(DBObject* self)
2258{
2259 /* We can give out the private field even if db is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00002260 Py_INCREF(self->private_obj);
2261 return self->private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002262}
2263
2264static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00002265DB_set_private(DBObject* self, PyObject* private_obj)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002266{
2267 /* We can set the private field even if db is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00002268 Py_DECREF(self->private_obj);
2269 Py_INCREF(private_obj);
2270 self->private_obj = private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002271 RETURN_NONE();
2272}
2273
2274
2275static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002276DB_set_bt_minkey(DBObject* self, PyObject* args)
2277{
2278 int err, minkey;
2279
2280 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2281 return NULL;
2282 CHECK_DB_NOT_CLOSED(self);
2283
2284 MYDB_BEGIN_ALLOW_THREADS;
2285 err = self->db->set_bt_minkey(self->db, minkey);
2286 MYDB_END_ALLOW_THREADS;
2287 RETURN_IF_ERR();
2288 RETURN_NONE();
2289}
2290
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002291static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002292_default_cmp(const DBT *leftKey,
2293 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002294{
2295 int res;
2296 int lsize = leftKey->size, rsize = rightKey->size;
2297
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002298 res = memcmp(leftKey->data, rightKey->data,
Georg Brandlef1701f2006-03-07 14:57:48 +00002299 lsize < rsize ? lsize : rsize);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002300
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002301 if (res == 0) {
2302 if (lsize < rsize) {
2303 res = -1;
2304 }
2305 else if (lsize > rsize) {
2306 res = 1;
2307 }
2308 }
2309 return res;
2310}
2311
2312static int
Jesus Ceaef9764f2008-05-13 18:45:46 +00002313_db_compareCallback(DB* db,
Georg Brandlef1701f2006-03-07 14:57:48 +00002314 const DBT *leftKey,
2315 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002316{
2317 int res = 0;
2318 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002319 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002320 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002321
2322 if (self == NULL || self->btCompareCallback == NULL) {
2323 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002324 PyErr_SetString(PyExc_TypeError,
2325 (self == 0
2326 ? "DB_bt_compare db is NULL."
2327 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002328 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002329 PyErr_Print();
2330 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002331 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002332 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002333 MYDB_BEGIN_BLOCK_THREADS;
2334
Jesus Ceaef9764f2008-05-13 18:45:46 +00002335 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002336 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002337 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002338 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002339 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002340 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002341 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002342 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002343 PyErr_Print();
2344 res = _default_cmp(leftKey, rightKey);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002345 } else if (NUMBER_Check(result)) {
2346 res = NUMBER_AsLong(result);
Georg Brandlef1701f2006-03-07 14:57:48 +00002347 } else {
2348 PyErr_SetString(PyExc_TypeError,
2349 "DB_bt_compare callback MUST return an int.");
2350 /* we're in a callback within the DB code, we can't raise */
2351 PyErr_Print();
2352 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002353 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002354
Thomas Woutersb3153832006-03-08 01:47:19 +00002355 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002356 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002357
2358 MYDB_END_BLOCK_THREADS;
2359 }
2360 return res;
2361}
2362
2363static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002364DB_set_bt_compare(DBObject* self, PyObject* comparator)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002365{
2366 int err;
Thomas Woutersb3153832006-03-08 01:47:19 +00002367 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002368
Georg Brandlef1701f2006-03-07 14:57:48 +00002369 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002370
Georg Brandlef1701f2006-03-07 14:57:48 +00002371 if (!PyCallable_Check(comparator)) {
2372 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002373 return NULL;
2374 }
2375
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002376 /*
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002377 * Perform a test call of the comparator function with two empty
2378 * string objects here. verify that it returns an int (0).
2379 * err if not.
2380 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002381 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002382 result = PyEval_CallObject(comparator, tuple);
2383 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002384 if (result == NULL)
2385 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002386 if (!NUMBER_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002387 PyErr_SetString(PyExc_TypeError,
2388 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002389 return NULL;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002390 } else if (NUMBER_AsLong(result) != 0) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002391 PyErr_SetString(PyExc_TypeError,
2392 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002393 return NULL;
2394 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002395 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002396
2397 /* We don't accept multiple set_bt_compare operations, in order to
2398 * simplify the code. This would have no real use, as one cannot
2399 * change the function once the db is opened anyway */
2400 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002401 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002402 return NULL;
2403 }
2404
Georg Brandlef1701f2006-03-07 14:57:48 +00002405 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002406 self->btCompareCallback = comparator;
2407
2408 /* This is to workaround a problem with un-initialized threads (see
2409 comment in DB_associate) */
2410#ifdef WITH_THREAD
2411 PyEval_InitThreads();
2412#endif
2413
Thomas Woutersb3153832006-03-08 01:47:19 +00002414 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002415
2416 if (err) {
2417 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002418 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002419 self->btCompareCallback = NULL;
2420 }
2421
Georg Brandlef1701f2006-03-07 14:57:48 +00002422 RETURN_IF_ERR();
2423 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002424}
2425
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002426
2427static PyObject*
2428DB_set_cachesize(DBObject* self, PyObject* args)
2429{
2430 int err;
2431 int gbytes = 0, bytes = 0, ncache = 0;
2432
2433 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2434 &gbytes,&bytes,&ncache))
2435 return NULL;
2436 CHECK_DB_NOT_CLOSED(self);
2437
2438 MYDB_BEGIN_ALLOW_THREADS;
2439 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2440 MYDB_END_ALLOW_THREADS;
2441 RETURN_IF_ERR();
2442 RETURN_NONE();
2443}
2444
2445
2446static PyObject*
2447DB_set_flags(DBObject* self, PyObject* args)
2448{
2449 int err, flags;
2450
2451 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2452 return NULL;
2453 CHECK_DB_NOT_CLOSED(self);
2454
2455 MYDB_BEGIN_ALLOW_THREADS;
2456 err = self->db->set_flags(self->db, flags);
2457 MYDB_END_ALLOW_THREADS;
2458 RETURN_IF_ERR();
2459
2460 self->setflags |= flags;
2461 RETURN_NONE();
2462}
2463
2464
2465static PyObject*
2466DB_set_h_ffactor(DBObject* self, PyObject* args)
2467{
2468 int err, ffactor;
2469
2470 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2471 return NULL;
2472 CHECK_DB_NOT_CLOSED(self);
2473
2474 MYDB_BEGIN_ALLOW_THREADS;
2475 err = self->db->set_h_ffactor(self->db, ffactor);
2476 MYDB_END_ALLOW_THREADS;
2477 RETURN_IF_ERR();
2478 RETURN_NONE();
2479}
2480
2481
2482static PyObject*
2483DB_set_h_nelem(DBObject* self, PyObject* args)
2484{
2485 int err, nelem;
2486
2487 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2488 return NULL;
2489 CHECK_DB_NOT_CLOSED(self);
2490
2491 MYDB_BEGIN_ALLOW_THREADS;
2492 err = self->db->set_h_nelem(self->db, nelem);
2493 MYDB_END_ALLOW_THREADS;
2494 RETURN_IF_ERR();
2495 RETURN_NONE();
2496}
2497
2498
2499static PyObject*
2500DB_set_lorder(DBObject* self, PyObject* args)
2501{
2502 int err, lorder;
2503
2504 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2505 return NULL;
2506 CHECK_DB_NOT_CLOSED(self);
2507
2508 MYDB_BEGIN_ALLOW_THREADS;
2509 err = self->db->set_lorder(self->db, lorder);
2510 MYDB_END_ALLOW_THREADS;
2511 RETURN_IF_ERR();
2512 RETURN_NONE();
2513}
2514
2515
2516static PyObject*
2517DB_set_pagesize(DBObject* self, PyObject* args)
2518{
2519 int err, pagesize;
2520
2521 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2522 return NULL;
2523 CHECK_DB_NOT_CLOSED(self);
2524
2525 MYDB_BEGIN_ALLOW_THREADS;
2526 err = self->db->set_pagesize(self->db, pagesize);
2527 MYDB_END_ALLOW_THREADS;
2528 RETURN_IF_ERR();
2529 RETURN_NONE();
2530}
2531
2532
2533static PyObject*
2534DB_set_re_delim(DBObject* self, PyObject* args)
2535{
2536 int err;
2537 char delim;
2538
2539 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2540 PyErr_Clear();
2541 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2542 return NULL;
2543 }
2544
2545 CHECK_DB_NOT_CLOSED(self);
2546
2547 MYDB_BEGIN_ALLOW_THREADS;
2548 err = self->db->set_re_delim(self->db, delim);
2549 MYDB_END_ALLOW_THREADS;
2550 RETURN_IF_ERR();
2551 RETURN_NONE();
2552}
2553
2554static PyObject*
2555DB_set_re_len(DBObject* self, PyObject* args)
2556{
2557 int err, len;
2558
2559 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2560 return NULL;
2561 CHECK_DB_NOT_CLOSED(self);
2562
2563 MYDB_BEGIN_ALLOW_THREADS;
2564 err = self->db->set_re_len(self->db, len);
2565 MYDB_END_ALLOW_THREADS;
2566 RETURN_IF_ERR();
2567 RETURN_NONE();
2568}
2569
2570
2571static PyObject*
2572DB_set_re_pad(DBObject* self, PyObject* args)
2573{
2574 int err;
2575 char pad;
2576
2577 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2578 PyErr_Clear();
2579 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2580 return NULL;
2581 }
2582 CHECK_DB_NOT_CLOSED(self);
2583
2584 MYDB_BEGIN_ALLOW_THREADS;
2585 err = self->db->set_re_pad(self->db, pad);
2586 MYDB_END_ALLOW_THREADS;
2587 RETURN_IF_ERR();
2588 RETURN_NONE();
2589}
2590
2591
2592static PyObject*
2593DB_set_re_source(DBObject* self, PyObject* args)
2594{
2595 int err;
2596 char *re_source;
2597
2598 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2599 return NULL;
2600 CHECK_DB_NOT_CLOSED(self);
2601
2602 MYDB_BEGIN_ALLOW_THREADS;
2603 err = self->db->set_re_source(self->db, re_source);
2604 MYDB_END_ALLOW_THREADS;
2605 RETURN_IF_ERR();
2606 RETURN_NONE();
2607}
2608
2609
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002610static PyObject*
2611DB_set_q_extentsize(DBObject* self, PyObject* args)
2612{
2613 int err;
2614 int extentsize;
2615
2616 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2617 return NULL;
2618 CHECK_DB_NOT_CLOSED(self);
2619
2620 MYDB_BEGIN_ALLOW_THREADS;
2621 err = self->db->set_q_extentsize(self->db, extentsize);
2622 MYDB_END_ALLOW_THREADS;
2623 RETURN_IF_ERR();
2624 RETURN_NONE();
2625}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002626
2627static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002628DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002629{
2630 int err, flags = 0, type;
2631 void* sp;
2632 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002633#if (DBVER >= 43)
2634 PyObject* txnobj = NULL;
2635 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002636 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002637#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002638 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002639#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002640
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002641#if (DBVER >= 43)
2642 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2643 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002644 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002645 if (!checkTxnObj(txnobj, &txn))
2646 return NULL;
2647#else
2648 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2649 return NULL;
2650#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002651 CHECK_DB_NOT_CLOSED(self);
2652
2653 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002654#if (DBVER >= 43)
2655 err = self->db->stat(self->db, txn, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002656#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002657 err = self->db->stat(self->db, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002658#endif
2659 MYDB_END_ALLOW_THREADS;
2660 RETURN_IF_ERR();
2661
2662 self->haveStat = 1;
2663
2664 /* Turn the stat structure into a dictionary */
2665 type = _DB_get_type(self);
2666 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2667 free(sp);
2668 return NULL;
2669 }
2670
2671#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2672#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2673#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2674
2675 switch (type) {
2676 case DB_HASH:
2677 MAKE_HASH_ENTRY(magic);
2678 MAKE_HASH_ENTRY(version);
2679 MAKE_HASH_ENTRY(nkeys);
2680 MAKE_HASH_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002681#if (DBVER >= 46)
2682 MAKE_HASH_ENTRY(pagecnt);
2683#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002684 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002685#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002686 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002687#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002688 MAKE_HASH_ENTRY(ffactor);
2689 MAKE_HASH_ENTRY(buckets);
2690 MAKE_HASH_ENTRY(free);
2691 MAKE_HASH_ENTRY(bfree);
2692 MAKE_HASH_ENTRY(bigpages);
2693 MAKE_HASH_ENTRY(big_bfree);
2694 MAKE_HASH_ENTRY(overflows);
2695 MAKE_HASH_ENTRY(ovfl_free);
2696 MAKE_HASH_ENTRY(dup);
2697 MAKE_HASH_ENTRY(dup_free);
2698 break;
2699
2700 case DB_BTREE:
2701 case DB_RECNO:
2702 MAKE_BT_ENTRY(magic);
2703 MAKE_BT_ENTRY(version);
2704 MAKE_BT_ENTRY(nkeys);
2705 MAKE_BT_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002706#if (DBVER >= 46)
2707 MAKE_BT_ENTRY(pagecnt);
2708#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002709 MAKE_BT_ENTRY(pagesize);
2710 MAKE_BT_ENTRY(minkey);
2711 MAKE_BT_ENTRY(re_len);
2712 MAKE_BT_ENTRY(re_pad);
2713 MAKE_BT_ENTRY(levels);
2714 MAKE_BT_ENTRY(int_pg);
2715 MAKE_BT_ENTRY(leaf_pg);
2716 MAKE_BT_ENTRY(dup_pg);
2717 MAKE_BT_ENTRY(over_pg);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002718#if (DBVER >= 43)
2719 MAKE_BT_ENTRY(empty_pg);
2720#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002721 MAKE_BT_ENTRY(free);
2722 MAKE_BT_ENTRY(int_pgfree);
2723 MAKE_BT_ENTRY(leaf_pgfree);
2724 MAKE_BT_ENTRY(dup_pgfree);
2725 MAKE_BT_ENTRY(over_pgfree);
2726 break;
2727
2728 case DB_QUEUE:
2729 MAKE_QUEUE_ENTRY(magic);
2730 MAKE_QUEUE_ENTRY(version);
2731 MAKE_QUEUE_ENTRY(nkeys);
2732 MAKE_QUEUE_ENTRY(ndata);
2733 MAKE_QUEUE_ENTRY(pagesize);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002734#if (DBVER >= 41)
Jesus Ceaef9764f2008-05-13 18:45:46 +00002735 MAKE_QUEUE_ENTRY(extentsize);
2736#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002737 MAKE_QUEUE_ENTRY(pages);
2738 MAKE_QUEUE_ENTRY(re_len);
2739 MAKE_QUEUE_ENTRY(re_pad);
2740 MAKE_QUEUE_ENTRY(pgfree);
2741#if (DBVER == 31)
2742 MAKE_QUEUE_ENTRY(start);
2743#endif
2744 MAKE_QUEUE_ENTRY(first_recno);
2745 MAKE_QUEUE_ENTRY(cur_recno);
2746 break;
2747
2748 default:
2749 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2750 Py_DECREF(d);
2751 d = NULL;
2752 }
2753
2754#undef MAKE_HASH_ENTRY
2755#undef MAKE_BT_ENTRY
2756#undef MAKE_QUEUE_ENTRY
2757
2758 free(sp);
2759 return d;
2760}
2761
2762static PyObject*
2763DB_sync(DBObject* self, PyObject* args)
2764{
2765 int err;
2766 int flags = 0;
2767
2768 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2769 return NULL;
2770 CHECK_DB_NOT_CLOSED(self);
2771
2772 MYDB_BEGIN_ALLOW_THREADS;
2773 err = self->db->sync(self->db, flags);
2774 MYDB_END_ALLOW_THREADS;
2775 RETURN_IF_ERR();
2776 RETURN_NONE();
2777}
2778
2779
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002780static PyObject*
2781DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2782{
2783 int err, flags=0;
2784 u_int32_t count=0;
2785 PyObject* txnobj = NULL;
2786 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002787 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002788
2789 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2790 &txnobj, &flags))
2791 return NULL;
2792 CHECK_DB_NOT_CLOSED(self);
2793 if (!checkTxnObj(txnobj, &txn))
2794 return NULL;
2795
2796 MYDB_BEGIN_ALLOW_THREADS;
2797 err = self->db->truncate(self->db, txn, &count, flags);
2798 MYDB_END_ALLOW_THREADS;
2799 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002800 return NUMBER_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002801}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002802
2803
2804static PyObject*
2805DB_upgrade(DBObject* self, PyObject* args)
2806{
2807 int err, flags=0;
2808 char *filename;
2809
2810 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2811 return NULL;
2812 CHECK_DB_NOT_CLOSED(self);
2813
2814 MYDB_BEGIN_ALLOW_THREADS;
2815 err = self->db->upgrade(self->db, filename, flags);
2816 MYDB_END_ALLOW_THREADS;
2817 RETURN_IF_ERR();
2818 RETURN_NONE();
2819}
2820
2821
2822static PyObject*
2823DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2824{
2825 int err, flags=0;
2826 char* fileName;
2827 char* dbName=NULL;
2828 char* outFileName=NULL;
2829 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002830 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002831 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002832
2833 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2834 &fileName, &dbName, &outFileName, &flags))
2835 return NULL;
2836
2837 CHECK_DB_NOT_CLOSED(self);
2838 if (outFileName)
2839 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002840 /* XXX(nnorwitz): it should probably be an exception if outFile
2841 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002842
2843 MYDB_BEGIN_ALLOW_THREADS;
2844 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2845 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002846 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002847 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002848
Jesus Ceaef9764f2008-05-13 18:45:46 +00002849 { /* DB.verify acts as a DB handle destructor (like close) */
2850 PyObject *error;
2851
2852 error=DB_close_internal(self,0);
2853 if (error ) {
2854 return error;
2855 }
2856 }
Gregory P. Smith41631e82003-09-21 00:08:14 +00002857
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002858 RETURN_IF_ERR();
2859 RETURN_NONE();
2860}
2861
2862
2863static PyObject*
2864DB_set_get_returns_none(DBObject* self, PyObject* args)
2865{
2866 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002867 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002868
2869 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2870 return NULL;
2871 CHECK_DB_NOT_CLOSED(self);
2872
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002873 if (self->moduleFlags.getReturnsNone)
2874 ++oldValue;
2875 if (self->moduleFlags.cursorSetReturnsNone)
2876 ++oldValue;
2877 self->moduleFlags.getReturnsNone = (flags >= 1);
2878 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002879 return NUMBER_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002880}
2881
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002882#if (DBVER >= 41)
2883static PyObject*
2884DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2885{
2886 int err;
2887 u_int32_t flags=0;
2888 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002889 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002890
2891 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2892 &passwd, &flags)) {
2893 return NULL;
2894 }
2895
2896 MYDB_BEGIN_ALLOW_THREADS;
2897 err = self->db->set_encrypt(self->db, passwd, flags);
2898 MYDB_END_ALLOW_THREADS;
2899
2900 RETURN_IF_ERR();
2901 RETURN_NONE();
2902}
2903#endif /* DBVER >= 41 */
2904
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002905
2906/*-------------------------------------------------------------- */
2907/* Mapping and Dictionary-like access routines */
2908
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002909Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002910{
2911 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002912 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002913 int flags = 0;
2914 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002915 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002916
2917 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002918 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002919 if (t) {
2920 PyErr_SetObject(DBError, t);
2921 Py_DECREF(t);
2922 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002923 return -1;
2924 }
2925
2926 if (self->haveStat) { /* Has the stat function been called recently? If
2927 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002928 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002929 }
2930
2931 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002932redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002933#if (DBVER >= 43)
2934 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002935#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00002936 err = self->db->stat(self->db, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002937#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002938
2939 /* All the stat structures have matching fields upto the ndata field,
2940 so we can use any of them for the type cast */
2941 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2942
Jesus Ceaef9764f2008-05-13 18:45:46 +00002943 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002944 * redo a full stat to make sure.
2945 * Fixes SF python bug 1493322, pybsddb bug 1184012
2946 */
2947 if (size == 0 && (flags & DB_FAST_STAT)) {
2948 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002949 if (!err)
2950 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002951 goto redo_stat_for_length;
2952 }
2953
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002954 MYDB_END_ALLOW_THREADS;
2955
2956 if (err)
2957 return -1;
2958
2959 self->haveStat = 1;
2960
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002961 free(sp);
2962 return size;
2963}
2964
2965
2966PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2967{
2968 int err;
2969 PyObject* retval;
2970 DBT key;
2971 DBT data;
2972
2973 CHECK_DB_NOT_CLOSED(self);
2974 if (!make_key_dbt(self, keyobj, &key, NULL))
2975 return NULL;
2976
2977 CLEAR_DBT(data);
2978 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002979 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002980 data.flags = DB_DBT_MALLOC;
2981 }
2982 MYDB_BEGIN_ALLOW_THREADS;
2983 err = self->db->get(self->db, NULL, &key, &data, 0);
2984 MYDB_END_ALLOW_THREADS;
2985 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2986 PyErr_SetObject(PyExc_KeyError, keyobj);
2987 retval = NULL;
2988 }
2989 else if (makeDBError(err)) {
2990 retval = NULL;
2991 }
2992 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002993 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002994 FREE_DBT(data);
2995 }
2996
2997 FREE_DBT(key);
2998 return retval;
2999}
3000
3001
3002static int
3003DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
3004{
3005 DBT key, data;
3006 int retval;
3007 int flags = 0;
3008
3009 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00003010 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003011 if (t) {
3012 PyErr_SetObject(DBError, t);
3013 Py_DECREF(t);
3014 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003015 return -1;
3016 }
3017
3018 if (!make_key_dbt(self, keyobj, &key, NULL))
3019 return -1;
3020
3021 if (dataobj != NULL) {
3022 if (!make_dbt(dataobj, &data))
3023 retval = -1;
3024 else {
3025 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003026 /* dictionaries shouldn't have duplicate keys */
3027 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003028 retval = _DB_put(self, NULL, &key, &data, flags);
3029
3030 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003031 /* try deleting any old record that matches and then PUT it
3032 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003033 _DB_delete(self, NULL, &key, 0);
3034 PyErr_Clear();
3035 retval = _DB_put(self, NULL, &key, &data, flags);
3036 }
3037 }
3038 }
3039 else {
3040 /* dataobj == NULL, so delete the key */
3041 retval = _DB_delete(self, NULL, &key, 0);
3042 }
3043 FREE_DBT(key);
3044 return retval;
3045}
3046
3047
3048static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00003049DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003050{
3051 int err;
3052 PyObject* keyobj;
3053 DBT key, data;
3054 PyObject* txnobj = NULL;
3055 DB_TXN *txn = NULL;
Jesus Cea4907d272008-08-31 14:00:51 +00003056 static char* kwnames[] = {"key","txn", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003057
Jesus Cea4907d272008-08-31 14:00:51 +00003058 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
3059 &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003060 return NULL;
Jesus Cea4907d272008-08-31 14:00:51 +00003061
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003062 CHECK_DB_NOT_CLOSED(self);
3063 if (!make_key_dbt(self, keyobj, &key, NULL))
3064 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003065 if (!checkTxnObj(txnobj, &txn)) {
3066 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003067 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003068 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003069
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003070 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003071 it has a record but can't allocate a buffer for the data. This saves
3072 having to deal with data we won't be using.
3073 */
3074 CLEAR_DBT(data);
3075 data.flags = DB_DBT_USERMEM;
3076
3077 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00003078 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003079 MYDB_END_ALLOW_THREADS;
3080 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003081
3082 if (err == DB_BUFFER_SMALL || err == 0) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003083 return NUMBER_FromLong(1);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003084 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003085 return NUMBER_FromLong(0);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003086 }
3087
3088 makeDBError(err);
3089 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003090}
3091
3092
3093#define _KEYS_LIST 1
3094#define _VALUES_LIST 2
3095#define _ITEMS_LIST 3
3096
3097static PyObject*
3098_DB_make_list(DBObject* self, DB_TXN* txn, int type)
3099{
3100 int err, dbtype;
3101 DBT key;
3102 DBT data;
3103 DBC *cursor;
3104 PyObject* list;
3105 PyObject* item = NULL;
3106
3107 CHECK_DB_NOT_CLOSED(self);
3108 CLEAR_DBT(key);
3109 CLEAR_DBT(data);
3110
3111 dbtype = _DB_get_type(self);
3112 if (dbtype == -1)
3113 return NULL;
3114
3115 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00003116 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003117 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003118
3119 /* get a cursor */
3120 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00003121 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003122 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00003123 if (makeDBError(err)) {
3124 Py_DECREF(list);
3125 return NULL;
3126 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003127
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003128 while (1) { /* use the cursor to traverse the DB, collecting items */
3129 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003130 err = _DBC_get(cursor, &key, &data, DB_NEXT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003131 MYDB_END_ALLOW_THREADS;
3132
3133 if (err) {
3134 /* for any error, break out of the loop */
3135 break;
3136 }
3137
3138 switch (type) {
3139 case _KEYS_LIST:
3140 switch(dbtype) {
3141 case DB_BTREE:
3142 case DB_HASH:
3143 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003144 item = Build_PyString(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003145 break;
3146 case DB_RECNO:
3147 case DB_QUEUE:
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003148 item = NUMBER_FromLong(*((db_recno_t*)key.data));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003149 break;
3150 }
3151 break;
3152
3153 case _VALUES_LIST:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003154 item = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003155 break;
3156
3157 case _ITEMS_LIST:
3158 switch(dbtype) {
3159 case DB_BTREE:
3160 case DB_HASH:
3161 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003162 item = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003163 break;
3164 case DB_RECNO:
3165 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003166 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003167 break;
3168 }
3169 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00003170 default:
3171 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3172 item = NULL;
3173 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003174 }
3175 if (item == NULL) {
3176 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003177 list = NULL;
3178 goto done;
3179 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003180 if (PyList_Append(list, item)) {
3181 Py_DECREF(list);
3182 Py_DECREF(item);
3183 list = NULL;
3184 goto done;
3185 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003186 Py_DECREF(item);
3187 }
3188
Gregory P. Smithe9477062005-06-04 06:46:59 +00003189 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3190 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003191 Py_DECREF(list);
3192 list = NULL;
3193 }
3194
3195 done:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003196 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003197 _DBC_close(cursor);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003198 MYDB_END_ALLOW_THREADS;
3199 return list;
3200}
3201
3202
3203static PyObject*
3204DB_keys(DBObject* self, PyObject* args)
3205{
3206 PyObject* txnobj = NULL;
3207 DB_TXN *txn = NULL;
3208
Georg Brandl96a8c392006-05-29 21:04:52 +00003209 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003210 return NULL;
3211 if (!checkTxnObj(txnobj, &txn))
3212 return NULL;
3213 return _DB_make_list(self, txn, _KEYS_LIST);
3214}
3215
3216
3217static PyObject*
3218DB_items(DBObject* self, PyObject* args)
3219{
3220 PyObject* txnobj = NULL;
3221 DB_TXN *txn = NULL;
3222
Georg Brandl96a8c392006-05-29 21:04:52 +00003223 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003224 return NULL;
3225 if (!checkTxnObj(txnobj, &txn))
3226 return NULL;
3227 return _DB_make_list(self, txn, _ITEMS_LIST);
3228}
3229
3230
3231static PyObject*
3232DB_values(DBObject* self, PyObject* args)
3233{
3234 PyObject* txnobj = NULL;
3235 DB_TXN *txn = NULL;
3236
Georg Brandl96a8c392006-05-29 21:04:52 +00003237 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003238 return NULL;
3239 if (!checkTxnObj(txnobj, &txn))
3240 return NULL;
3241 return _DB_make_list(self, txn, _VALUES_LIST);
3242}
3243
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003244/* --------------------------------------------------------------------- */
3245/* DBCursor methods */
3246
3247
3248static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003249DBC_close_internal(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003250{
3251 int err = 0;
3252
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003253 if (self->dbc != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003254 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3255 if (self->txn) {
3256 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3257 self->txn=NULL;
3258 }
3259
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003260 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003261 err = _DBC_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003262 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003263 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003264 }
3265 RETURN_IF_ERR();
3266 RETURN_NONE();
3267}
3268
Jesus Ceaef9764f2008-05-13 18:45:46 +00003269static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003270DBC_close(DBCursorObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00003271{
Jesus Ceaef9764f2008-05-13 18:45:46 +00003272 return DBC_close_internal(self);
3273}
3274
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003275
3276static PyObject*
3277DBC_count(DBCursorObject* self, PyObject* args)
3278{
3279 int err = 0;
3280 db_recno_t count;
3281 int flags = 0;
3282
3283 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3284 return NULL;
3285
3286 CHECK_CURSOR_NOT_CLOSED(self);
3287
3288 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003289 err = _DBC_count(self->dbc, &count, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003290 MYDB_END_ALLOW_THREADS;
3291 RETURN_IF_ERR();
3292
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003293 return NUMBER_FromLong(count);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003294}
3295
3296
3297static PyObject*
3298DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3299{
3300 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3301}
3302
3303
3304static PyObject*
3305DBC_delete(DBCursorObject* self, PyObject* args)
3306{
3307 int err, flags=0;
3308
3309 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3310 return NULL;
3311
3312 CHECK_CURSOR_NOT_CLOSED(self);
3313
3314 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003315 err = _DBC_del(self->dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003316 MYDB_END_ALLOW_THREADS;
3317 RETURN_IF_ERR();
3318
3319 self->mydb->haveStat = 0;
3320 RETURN_NONE();
3321}
3322
3323
3324static PyObject*
3325DBC_dup(DBCursorObject* self, PyObject* args)
3326{
3327 int err, flags =0;
3328 DBC* dbc = NULL;
3329
3330 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3331 return NULL;
3332
3333 CHECK_CURSOR_NOT_CLOSED(self);
3334
3335 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003336 err = _DBC_dup(self->dbc, &dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003337 MYDB_END_ALLOW_THREADS;
3338 RETURN_IF_ERR();
3339
Jesus Ceaef9764f2008-05-13 18:45:46 +00003340 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003341}
3342
3343static PyObject*
3344DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3345{
3346 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3347}
3348
3349
3350static PyObject*
3351DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3352{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003353 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003354 PyObject* keyobj = NULL;
3355 PyObject* dataobj = NULL;
3356 PyObject* retval = NULL;
3357 int dlen = -1;
3358 int doff = -1;
3359 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003360 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003361 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003362
3363 CLEAR_DBT(key);
3364 CLEAR_DBT(data);
3365 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003366 &flags, &dlen, &doff))
3367 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003368 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003369 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
Jesus Cea4907d272008-08-31 14:00:51 +00003370 &kwnames[1],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003371 &keyobj, &flags, &dlen, &doff))
3372 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003373 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003374 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3375 kwnames, &keyobj, &dataobj,
3376 &flags, &dlen, &doff))
3377 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003378 return NULL;
3379 }
3380 }
3381 }
3382
3383 CHECK_CURSOR_NOT_CLOSED(self);
3384
3385 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3386 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003387 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3388 (!add_partial_dbt(&data, dlen, doff)) )
3389 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003390 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003391 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003392 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003393
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003394 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003395 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003396 MYDB_END_ALLOW_THREADS;
3397
Gregory P. Smithe9477062005-06-04 06:46:59 +00003398 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3399 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003400 Py_INCREF(Py_None);
3401 retval = Py_None;
3402 }
3403 else if (makeDBError(err)) {
3404 retval = NULL;
3405 }
3406 else {
3407 switch (_DB_get_type(self->mydb)) {
3408 case -1:
3409 retval = NULL;
3410 break;
3411 case DB_BTREE:
3412 case DB_HASH:
3413 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003414 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003415 break;
3416 case DB_RECNO:
3417 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003418 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003419 break;
3420 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003421 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003422 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003423 return retval;
3424}
3425
Gregory P. Smith19699a92004-06-28 04:06:49 +00003426static PyObject*
3427DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3428{
3429 int err, flags=0;
3430 PyObject* keyobj = NULL;
3431 PyObject* dataobj = NULL;
3432 PyObject* retval = NULL;
3433 int dlen = -1;
3434 int doff = -1;
3435 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003436 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3437 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003438
3439 CLEAR_DBT(key);
3440 CLEAR_DBT(data);
3441 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3442 &flags, &dlen, &doff))
3443 {
3444 PyErr_Clear();
3445 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003446 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003447 &keyobj, &flags, &dlen, &doff))
3448 {
3449 PyErr_Clear();
3450 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3451 kwnames, &keyobj, &dataobj,
3452 &flags, &dlen, &doff))
3453 {
3454 return NULL;
3455 }
3456 }
3457 }
3458
3459 CHECK_CURSOR_NOT_CLOSED(self);
3460
3461 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3462 return NULL;
3463 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3464 (!add_partial_dbt(&data, dlen, doff)) ) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003465 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003466 return NULL;
3467 }
3468
Gregory P. Smith19699a92004-06-28 04:06:49 +00003469 CLEAR_DBT(pkey);
3470 pkey.flags = DB_DBT_MALLOC;
3471
3472 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003473 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003474 MYDB_END_ALLOW_THREADS;
3475
Gregory P. Smithe9477062005-06-04 06:46:59 +00003476 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3477 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003478 Py_INCREF(Py_None);
3479 retval = Py_None;
3480 }
3481 else if (makeDBError(err)) {
3482 retval = NULL;
3483 }
3484 else {
3485 PyObject *pkeyObj;
3486 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003487 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003488
3489 if (self->mydb->primaryDBType == DB_RECNO ||
3490 self->mydb->primaryDBType == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003491 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003492 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003493 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003494
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003495 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003496 {
3497 PyObject *keyObj;
3498 int type = _DB_get_type(self->mydb);
3499 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003500 keyObj = NUMBER_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003501 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003502 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003503#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003504 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003505#else
3506 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3507#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003508 Py_DECREF(keyObj);
Jesus Ceaef9764f2008-05-13 18:45:46 +00003509 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003510 }
3511 else /* return just the pkey and data */
3512 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003513#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003514 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003515#else
3516 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3517#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003518 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003519 Py_DECREF(dataObj);
3520 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003521 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003522 }
3523 /* the only time REALLOC should be set is if we used an integer
3524 * key that make_key_dbt malloc'd for us. always free these. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003525 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003526 FREE_DBT(key);
3527 }
3528 return retval;
3529}
3530
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003531
3532static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003533DBC_get_recno(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003534{
3535 int err;
3536 db_recno_t recno;
3537 DBT key;
3538 DBT data;
3539
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003540 CHECK_CURSOR_NOT_CLOSED(self);
3541
3542 CLEAR_DBT(key);
3543 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003544
3545 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003546 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003547 MYDB_END_ALLOW_THREADS;
3548 RETURN_IF_ERR();
3549
3550 recno = *((db_recno_t*)data.data);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003551 return NUMBER_FromLong(recno);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003552}
3553
3554
3555static PyObject*
3556DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3557{
3558 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3559}
3560
3561
3562static PyObject*
3563DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3564{
3565 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3566}
3567
3568
3569static PyObject*
3570DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3571{
3572 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3573}
3574
3575
3576static PyObject*
3577DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3578{
3579 int err, flags = 0;
3580 PyObject* keyobj, *dataobj;
3581 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003582 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003583 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003584 int dlen = -1;
3585 int doff = -1;
3586
3587 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3588 &keyobj, &dataobj, &flags, &dlen, &doff))
3589 return NULL;
3590
3591 CHECK_CURSOR_NOT_CLOSED(self);
3592
3593 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3594 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003595 if (!make_dbt(dataobj, &data) ||
3596 !add_partial_dbt(&data, dlen, doff) )
3597 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003598 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003599 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003600 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003601
3602 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003603 err = _DBC_put(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003604 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003605 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003606 RETURN_IF_ERR();
3607 self->mydb->haveStat = 0;
3608 RETURN_NONE();
3609}
3610
3611
3612static PyObject*
3613DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3614{
3615 int err, flags = 0;
3616 DBT key, data;
3617 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003618 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003619 int dlen = -1;
3620 int doff = -1;
3621
3622 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3623 &keyobj, &flags, &dlen, &doff))
3624 return NULL;
3625
3626 CHECK_CURSOR_NOT_CLOSED(self);
3627
3628 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3629 return NULL;
3630
3631 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003632 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003633 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003634 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003635 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003636
3637 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003638 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003639 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003640 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3641 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003642 Py_INCREF(Py_None);
3643 retval = Py_None;
3644 }
3645 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003646 retval = NULL;
3647 }
3648 else {
3649 switch (_DB_get_type(self->mydb)) {
3650 case -1:
3651 retval = NULL;
3652 break;
3653 case DB_BTREE:
3654 case DB_HASH:
3655 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003656 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003657 break;
3658 case DB_RECNO:
3659 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003660 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003661 break;
3662 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003663 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003664 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003665 /* the only time REALLOC should be set is if we used an integer
3666 * key that make_key_dbt malloc'd for us. always free these. */
3667 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003668 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003669 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003670
3671 return retval;
3672}
3673
3674
3675static PyObject*
3676DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3677{
3678 int err, flags = 0;
3679 DBT key, data;
3680 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003681 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003682 int dlen = -1;
3683 int doff = -1;
3684
3685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3686 &keyobj, &flags, &dlen, &doff))
3687 return NULL;
3688
3689 CHECK_CURSOR_NOT_CLOSED(self);
3690
3691 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3692 return NULL;
3693
3694 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003695 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003696 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003697 return NULL;
3698 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003699 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003700 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003701 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003702 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3703 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003704 Py_INCREF(Py_None);
3705 retval = Py_None;
3706 }
3707 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003708 retval = NULL;
3709 }
3710 else {
3711 switch (_DB_get_type(self->mydb)) {
3712 case -1:
3713 retval = NULL;
3714 break;
3715 case DB_BTREE:
3716 case DB_HASH:
3717 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003718 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003719 break;
3720 case DB_RECNO:
3721 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003722 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003723 break;
3724 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003725 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003726 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003727 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003728 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003729 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003730 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003731 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003732
3733 return retval;
3734}
3735
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003736static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003737_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3738 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003739{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003740 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003741 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003742 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003743
Gregory P. Smith7441e652003-11-03 21:35:31 +00003744 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003745 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3746 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003747 if (!make_dbt(dataobj, &data)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003748 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003749 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003750 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003751
3752 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003753 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003754 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003755 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003756 Py_INCREF(Py_None);
3757 retval = Py_None;
3758 }
3759 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003760 retval = NULL;
3761 }
3762 else {
3763 switch (_DB_get_type(self->mydb)) {
3764 case -1:
3765 retval = NULL;
3766 break;
3767 case DB_BTREE:
3768 case DB_HASH:
3769 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003770 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003771 break;
3772 case DB_RECNO:
3773 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003774 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003775 break;
3776 }
3777 }
3778
Jesus Ceaef9764f2008-05-13 18:45:46 +00003779 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003780 return retval;
3781}
3782
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003783static PyObject*
3784DBC_get_both(DBCursorObject* self, PyObject* args)
3785{
3786 int flags=0;
3787 PyObject *keyobj, *dataobj;
3788
3789 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3790 return NULL;
3791
Gregory P. Smith7441e652003-11-03 21:35:31 +00003792 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003793 CHECK_CURSOR_NOT_CLOSED(self);
3794
3795 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3796 self->mydb->moduleFlags.getReturnsNone);
3797}
3798
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003799/* Return size of entry */
3800static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003801DBC_get_current_size(DBCursorObject* self)
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003802{
3803 int err, flags=DB_CURRENT;
3804 PyObject* retval = NULL;
3805 DBT key, data;
3806
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003807 CHECK_CURSOR_NOT_CLOSED(self);
3808 CLEAR_DBT(key);
3809 CLEAR_DBT(data);
3810
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003811 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003812 getting the record size. */
3813 data.flags = DB_DBT_USERMEM;
3814 data.ulen = 0;
3815 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003816 err = _DBC_get(self->dbc, &key, &data, flags);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003817 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003818 if (err == DB_BUFFER_SMALL || !err) {
3819 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00003820 retval = NUMBER_FromLong((long)data.size);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003821 err = 0;
3822 }
3823
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003824 RETURN_IF_ERR();
3825 return retval;
3826}
3827
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003828static PyObject*
3829DBC_set_both(DBCursorObject* self, PyObject* args)
3830{
3831 int flags=0;
3832 PyObject *keyobj, *dataobj;
3833
3834 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3835 return NULL;
3836
Gregory P. Smith7441e652003-11-03 21:35:31 +00003837 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003838 CHECK_CURSOR_NOT_CLOSED(self);
3839
3840 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3841 self->mydb->moduleFlags.cursorSetReturnsNone);
3842}
3843
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003844
3845static PyObject*
3846DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3847{
3848 int err, irecno, flags=0;
3849 db_recno_t recno;
3850 DBT key, data;
3851 PyObject* retval;
3852 int dlen = -1;
3853 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003854 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003855
3856 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3857 &irecno, &flags, &dlen, &doff))
3858 return NULL;
3859
3860 CHECK_CURSOR_NOT_CLOSED(self);
3861
3862 CLEAR_DBT(key);
3863 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003864 /* use allocated space so DB will be able to realloc room for the real
3865 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003866 key.data = malloc(sizeof(db_recno_t));
3867 if (key.data == NULL) {
3868 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3869 return NULL;
3870 }
3871 key.size = sizeof(db_recno_t);
3872 key.ulen = key.size;
3873 memcpy(key.data, &recno, sizeof(db_recno_t));
3874 key.flags = DB_DBT_REALLOC;
3875
3876 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003877 if (!add_partial_dbt(&data, dlen, doff)) {
3878 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003879 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003880 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003881
3882 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003883 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003884 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003885 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3886 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003887 Py_INCREF(Py_None);
3888 retval = Py_None;
3889 }
3890 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003891 retval = NULL;
3892 }
3893 else { /* Can only be used for BTrees, so no need to return int key */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003894 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003895 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003896 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003897
3898 return retval;
3899}
3900
3901
3902static PyObject*
3903DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3904{
3905 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3906}
3907
3908
3909static PyObject*
3910DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3911{
3912 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3913}
3914
3915
3916static PyObject*
3917DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3918{
3919 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3920}
3921
3922
3923static PyObject*
3924DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3925{
3926 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3927}
3928
3929
3930static PyObject*
3931DBC_join_item(DBCursorObject* self, PyObject* args)
3932{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003933 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003934 DBT key, data;
3935 PyObject* retval;
3936
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003937 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003938 return NULL;
3939
3940 CHECK_CURSOR_NOT_CLOSED(self);
3941
3942 CLEAR_DBT(key);
3943 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003944
3945 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003946 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003947 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003948 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3949 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003950 Py_INCREF(Py_None);
3951 retval = Py_None;
3952 }
3953 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003954 retval = NULL;
3955 }
3956 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003957 retval = BuildValue_S(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003958 }
3959
3960 return retval;
3961}
3962
3963
3964
3965/* --------------------------------------------------------------------- */
3966/* DBEnv methods */
3967
3968
3969static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003970DBEnv_close_internal(DBEnvObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003971{
Jesus Ceaef9764f2008-05-13 18:45:46 +00003972 PyObject *dummy;
3973 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003974
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003975 if (!self->closed) { /* Don't close more than once */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003976 while(self->children_txns) {
3977 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
3978 Py_XDECREF(dummy);
3979 }
3980 while(self->children_dbs) {
3981 dummy=DB_close_internal(self->children_dbs,0);
3982 Py_XDECREF(dummy);
3983 }
Jesus Ceaac25fab2008-09-03 17:50:32 +00003984 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003985
Jesus Ceaac25fab2008-09-03 17:50:32 +00003986 self->closed = 1;
3987 if (self->db_env) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003988 MYDB_BEGIN_ALLOW_THREADS;
3989 err = self->db_env->close(self->db_env, flags);
3990 MYDB_END_ALLOW_THREADS;
3991 /* after calling DBEnv->close, regardless of error, this DBEnv
Jesus Ceaef9764f2008-05-13 18:45:46 +00003992 * may not be accessed again (Berkeley DB docs). */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003993 self->db_env = NULL;
3994 RETURN_IF_ERR();
3995 }
3996 RETURN_NONE();
3997}
3998
Jesus Ceaef9764f2008-05-13 18:45:46 +00003999static PyObject*
4000DBEnv_close(DBEnvObject* self, PyObject* args)
4001{
4002 int flags = 0;
4003
4004 if (!PyArg_ParseTuple(args, "|i:close", &flags))
4005 return NULL;
4006 return DBEnv_close_internal(self,flags);
4007}
4008
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004009
4010static PyObject*
4011DBEnv_open(DBEnvObject* self, PyObject* args)
4012{
4013 int err, flags=0, mode=0660;
4014 char *db_home;
4015
4016 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
4017 return NULL;
4018
4019 CHECK_ENV_NOT_CLOSED(self);
4020
4021 MYDB_BEGIN_ALLOW_THREADS;
4022 err = self->db_env->open(self->db_env, db_home, flags, mode);
4023 MYDB_END_ALLOW_THREADS;
4024 RETURN_IF_ERR();
4025 self->closed = 0;
4026 self->flags = flags;
4027 RETURN_NONE();
4028}
4029
4030
4031static PyObject*
4032DBEnv_remove(DBEnvObject* self, PyObject* args)
4033{
4034 int err, flags=0;
4035 char *db_home;
4036
4037 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
4038 return NULL;
4039 CHECK_ENV_NOT_CLOSED(self);
4040 MYDB_BEGIN_ALLOW_THREADS;
4041 err = self->db_env->remove(self->db_env, db_home, flags);
4042 MYDB_END_ALLOW_THREADS;
4043 RETURN_IF_ERR();
4044 RETURN_NONE();
4045}
4046
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004047#if (DBVER >= 41)
4048static PyObject*
4049DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4050{
4051 int err;
4052 u_int32_t flags=0;
4053 char *file = NULL;
4054 char *database = NULL;
4055 PyObject *txnobj = NULL;
4056 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004057 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004058 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004059
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004060 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004061 &file, &database, &txnobj, &flags)) {
4062 return NULL;
4063 }
4064 if (!checkTxnObj(txnobj, &txn)) {
4065 return NULL;
4066 }
4067 CHECK_ENV_NOT_CLOSED(self);
4068 MYDB_BEGIN_ALLOW_THREADS;
4069 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4070 MYDB_END_ALLOW_THREADS;
4071 RETURN_IF_ERR();
4072 RETURN_NONE();
4073}
4074
4075static PyObject*
4076DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4077{
4078 int err;
4079 u_int32_t flags=0;
4080 char *file = NULL;
4081 char *database = NULL;
4082 char *newname = NULL;
4083 PyObject *txnobj = NULL;
4084 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004085 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004086 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004087
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004088 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004089 &file, &database, &newname, &txnobj, &flags)) {
4090 return NULL;
4091 }
4092 if (!checkTxnObj(txnobj, &txn)) {
4093 return NULL;
4094 }
4095 CHECK_ENV_NOT_CLOSED(self);
4096 MYDB_BEGIN_ALLOW_THREADS;
4097 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4098 flags);
4099 MYDB_END_ALLOW_THREADS;
4100 RETURN_IF_ERR();
4101 RETURN_NONE();
4102}
4103
4104static PyObject*
4105DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4106{
4107 int err;
4108 u_int32_t flags=0;
4109 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004110 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004111
4112 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4113 &passwd, &flags)) {
4114 return NULL;
4115 }
4116
4117 MYDB_BEGIN_ALLOW_THREADS;
4118 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4119 MYDB_END_ALLOW_THREADS;
4120
4121 RETURN_IF_ERR();
4122 RETURN_NONE();
4123}
4124#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004125
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004126static PyObject*
4127DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4128{
4129 int err;
4130 u_int32_t flags=0;
4131 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004132 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004133
4134 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4135 &timeout, &flags)) {
4136 return NULL;
4137 }
4138
4139 MYDB_BEGIN_ALLOW_THREADS;
4140 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4141 MYDB_END_ALLOW_THREADS;
4142
4143 RETURN_IF_ERR();
4144 RETURN_NONE();
4145}
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004146
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004147static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004148DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4149{
4150 int err;
4151 long shm_key = 0;
4152
4153 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4154 return NULL;
4155 CHECK_ENV_NOT_CLOSED(self);
4156
4157 err = self->db_env->set_shm_key(self->db_env, shm_key);
4158 RETURN_IF_ERR();
4159 RETURN_NONE();
4160}
4161
4162static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004163DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4164{
4165 int err, gbytes=0, bytes=0, ncache=0;
4166
4167 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4168 &gbytes, &bytes, &ncache))
4169 return NULL;
4170 CHECK_ENV_NOT_CLOSED(self);
4171
4172 MYDB_BEGIN_ALLOW_THREADS;
4173 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4174 MYDB_END_ALLOW_THREADS;
4175 RETURN_IF_ERR();
4176 RETURN_NONE();
4177}
4178
4179
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004180static PyObject*
4181DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4182{
4183 int err, flags=0, onoff=0;
4184
4185 if (!PyArg_ParseTuple(args, "ii:set_flags",
4186 &flags, &onoff))
4187 return NULL;
4188 CHECK_ENV_NOT_CLOSED(self);
4189
4190 MYDB_BEGIN_ALLOW_THREADS;
4191 err = self->db_env->set_flags(self->db_env, flags, onoff);
4192 MYDB_END_ALLOW_THREADS;
4193 RETURN_IF_ERR();
4194 RETURN_NONE();
4195}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004196
4197
Jesus Ceaca3939c2008-05-22 15:27:38 +00004198#if (DBVER >= 47)
4199static PyObject*
4200DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
4201{
4202 int err, flags, onoff;
4203
4204 if (!PyArg_ParseTuple(args, "ii:log_set_config",
4205 &flags, &onoff))
4206 return NULL;
4207 CHECK_ENV_NOT_CLOSED(self);
4208
4209 MYDB_BEGIN_ALLOW_THREADS;
4210 err = self->db_env->log_set_config(self->db_env, flags, onoff);
4211 MYDB_END_ALLOW_THREADS;
4212 RETURN_IF_ERR();
4213 RETURN_NONE();
4214}
4215#endif /* DBVER >= 47 */
4216
4217
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004218static PyObject*
4219DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4220{
4221 int err;
4222 char *dir;
4223
4224 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4225 return NULL;
4226 CHECK_ENV_NOT_CLOSED(self);
4227
4228 MYDB_BEGIN_ALLOW_THREADS;
4229 err = self->db_env->set_data_dir(self->db_env, dir);
4230 MYDB_END_ALLOW_THREADS;
4231 RETURN_IF_ERR();
4232 RETURN_NONE();
4233}
4234
4235
4236static PyObject*
4237DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4238{
4239 int err, lg_bsize;
4240
4241 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4242 return NULL;
4243 CHECK_ENV_NOT_CLOSED(self);
4244
4245 MYDB_BEGIN_ALLOW_THREADS;
4246 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4247 MYDB_END_ALLOW_THREADS;
4248 RETURN_IF_ERR();
4249 RETURN_NONE();
4250}
4251
4252
4253static PyObject*
4254DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4255{
4256 int err;
4257 char *dir;
4258
4259 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4260 return NULL;
4261 CHECK_ENV_NOT_CLOSED(self);
4262
4263 MYDB_BEGIN_ALLOW_THREADS;
4264 err = self->db_env->set_lg_dir(self->db_env, dir);
4265 MYDB_END_ALLOW_THREADS;
4266 RETURN_IF_ERR();
4267 RETURN_NONE();
4268}
4269
4270static PyObject*
4271DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4272{
4273 int err, lg_max;
4274
4275 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4276 return NULL;
4277 CHECK_ENV_NOT_CLOSED(self);
4278
4279 MYDB_BEGIN_ALLOW_THREADS;
4280 err = self->db_env->set_lg_max(self->db_env, lg_max);
4281 MYDB_END_ALLOW_THREADS;
4282 RETURN_IF_ERR();
4283 RETURN_NONE();
4284}
4285
Jesus Ceaef9764f2008-05-13 18:45:46 +00004286#if (DBVER >= 42)
4287static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004288DBEnv_get_lg_max(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004289{
4290 int err;
4291 u_int32_t lg_max;
4292
Jesus Ceaef9764f2008-05-13 18:45:46 +00004293 CHECK_ENV_NOT_CLOSED(self);
4294
4295 MYDB_BEGIN_ALLOW_THREADS;
4296 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4297 MYDB_END_ALLOW_THREADS;
4298 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004299 return NUMBER_FromLong(lg_max);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004300}
4301#endif
4302
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004303
4304static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004305DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4306{
4307 int err, lg_max;
4308
4309 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4310 return NULL;
4311 CHECK_ENV_NOT_CLOSED(self);
4312
4313 MYDB_BEGIN_ALLOW_THREADS;
4314 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4315 MYDB_END_ALLOW_THREADS;
4316 RETURN_IF_ERR();
4317 RETURN_NONE();
4318}
4319
4320
4321static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004322DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4323{
4324 int err, lk_detect;
4325
4326 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4327 return NULL;
4328 CHECK_ENV_NOT_CLOSED(self);
4329
4330 MYDB_BEGIN_ALLOW_THREADS;
4331 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4332 MYDB_END_ALLOW_THREADS;
4333 RETURN_IF_ERR();
4334 RETURN_NONE();
4335}
4336
4337
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004338#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004339static PyObject*
4340DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4341{
4342 int err, max;
4343
4344 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4345 return NULL;
4346 CHECK_ENV_NOT_CLOSED(self);
4347
4348 MYDB_BEGIN_ALLOW_THREADS;
4349 err = self->db_env->set_lk_max(self->db_env, max);
4350 MYDB_END_ALLOW_THREADS;
4351 RETURN_IF_ERR();
4352 RETURN_NONE();
4353}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004354#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004355
4356
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004357
4358static PyObject*
4359DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4360{
4361 int err, max;
4362
4363 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4364 return NULL;
4365 CHECK_ENV_NOT_CLOSED(self);
4366
4367 MYDB_BEGIN_ALLOW_THREADS;
4368 err = self->db_env->set_lk_max_locks(self->db_env, max);
4369 MYDB_END_ALLOW_THREADS;
4370 RETURN_IF_ERR();
4371 RETURN_NONE();
4372}
4373
4374
4375static PyObject*
4376DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4377{
4378 int err, max;
4379
4380 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4381 return NULL;
4382 CHECK_ENV_NOT_CLOSED(self);
4383
4384 MYDB_BEGIN_ALLOW_THREADS;
4385 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4386 MYDB_END_ALLOW_THREADS;
4387 RETURN_IF_ERR();
4388 RETURN_NONE();
4389}
4390
4391
4392static PyObject*
4393DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4394{
4395 int err, max;
4396
4397 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4398 return NULL;
4399 CHECK_ENV_NOT_CLOSED(self);
4400
4401 MYDB_BEGIN_ALLOW_THREADS;
4402 err = self->db_env->set_lk_max_objects(self->db_env, max);
4403 MYDB_END_ALLOW_THREADS;
4404 RETURN_IF_ERR();
4405 RETURN_NONE();
4406}
4407
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004408
4409static PyObject*
4410DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4411{
4412 int err, mp_mmapsize;
4413
4414 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4415 return NULL;
4416 CHECK_ENV_NOT_CLOSED(self);
4417
4418 MYDB_BEGIN_ALLOW_THREADS;
4419 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4420 MYDB_END_ALLOW_THREADS;
4421 RETURN_IF_ERR();
4422 RETURN_NONE();
4423}
4424
4425
4426static PyObject*
4427DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4428{
4429 int err;
4430 char *dir;
4431
4432 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4433 return NULL;
4434 CHECK_ENV_NOT_CLOSED(self);
4435
4436 MYDB_BEGIN_ALLOW_THREADS;
4437 err = self->db_env->set_tmp_dir(self->db_env, dir);
4438 MYDB_END_ALLOW_THREADS;
4439 RETURN_IF_ERR();
4440 RETURN_NONE();
4441}
4442
4443
Jesus Ceaef9764f2008-05-13 18:45:46 +00004444static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004445DBEnv_txn_recover(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004446{
4447 int flags = DB_FIRST;
4448 int err, i;
4449 PyObject *list, *tuple, *gid;
4450 DBTxnObject *txn;
4451#define PREPLIST_LEN 16
4452 DB_PREPLIST preplist[PREPLIST_LEN];
4453 long retp;
4454
Jesus Ceaef9764f2008-05-13 18:45:46 +00004455 CHECK_ENV_NOT_CLOSED(self);
4456
4457 list=PyList_New(0);
4458 if (!list)
4459 return NULL;
4460 while (!0) {
4461 MYDB_BEGIN_ALLOW_THREADS
4462 err=self->db_env->txn_recover(self->db_env,
4463 preplist, PREPLIST_LEN, &retp, flags);
4464#undef PREPLIST_LEN
4465 MYDB_END_ALLOW_THREADS
4466 if (err) {
4467 Py_DECREF(list);
4468 RETURN_IF_ERR();
4469 }
4470 if (!retp) break;
4471 flags=DB_NEXT; /* Prepare for next loop pass */
4472 for (i=0; i<retp; i++) {
Christian Heimes593daf52008-05-26 12:51:38 +00004473 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
Jesus Ceaef9764f2008-05-13 18:45:46 +00004474 DB_XIDDATASIZE);
4475 if (!gid) {
4476 Py_DECREF(list);
4477 return NULL;
4478 }
4479 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4480 if (!txn) {
4481 Py_DECREF(list);
4482 Py_DECREF(gid);
4483 return NULL;
4484 }
4485 txn->flag_prepare=1; /* Recover state */
4486 tuple=PyTuple_New(2);
4487 if (!tuple) {
4488 Py_DECREF(list);
4489 Py_DECREF(gid);
4490 Py_DECREF(txn);
4491 return NULL;
4492 }
4493 if (PyTuple_SetItem(tuple, 0, gid)) {
4494 Py_DECREF(list);
4495 Py_DECREF(gid);
4496 Py_DECREF(txn);
4497 Py_DECREF(tuple);
4498 return NULL;
4499 }
4500 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4501 Py_DECREF(list);
4502 Py_DECREF(txn);
4503 Py_DECREF(tuple); /* This delete the "gid" also */
4504 return NULL;
4505 }
4506 if (PyList_Append(list, tuple)) {
4507 Py_DECREF(list);
4508 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4509 return NULL;
4510 }
4511 Py_DECREF(tuple);
4512 }
4513 }
4514 return list;
4515}
Jesus Ceaef9764f2008-05-13 18:45:46 +00004516
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004517static PyObject*
4518DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4519{
4520 int flags = 0;
4521 PyObject* txnobj = NULL;
4522 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004523 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004524
4525 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4526 &txnobj, &flags))
4527 return NULL;
4528
4529 if (!checkTxnObj(txnobj, &txn))
4530 return NULL;
4531 CHECK_ENV_NOT_CLOSED(self);
4532
Jesus Ceaef9764f2008-05-13 18:45:46 +00004533 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004534}
4535
4536
4537static PyObject*
4538DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4539{
4540 int err, kbyte=0, min=0, flags=0;
4541
4542 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4543 return NULL;
4544 CHECK_ENV_NOT_CLOSED(self);
4545
4546 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004547 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004548 MYDB_END_ALLOW_THREADS;
4549 RETURN_IF_ERR();
4550 RETURN_NONE();
4551}
4552
4553
4554static PyObject*
4555DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4556{
4557 int err, max;
4558
4559 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4560 return NULL;
4561 CHECK_ENV_NOT_CLOSED(self);
4562
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004563 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004564 RETURN_IF_ERR();
4565 RETURN_NONE();
4566}
4567
4568
4569static PyObject*
4570DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4571{
4572 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004573 long stamp;
4574 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004575
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004576 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004577 return NULL;
4578 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004579 timestamp = (time_t)stamp;
4580 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004581 RETURN_IF_ERR();
4582 RETURN_NONE();
4583}
4584
4585
4586static PyObject*
4587DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4588{
4589 int err, atype, flags=0;
4590 int aborted = 0;
4591
4592 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4593 return NULL;
4594 CHECK_ENV_NOT_CLOSED(self);
4595
4596 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004597 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004598 MYDB_END_ALLOW_THREADS;
4599 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004600 return NUMBER_FromLong(aborted);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004601}
4602
4603
4604static PyObject*
4605DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4606{
4607 int flags=0;
4608 int locker, lock_mode;
4609 DBT obj;
4610 PyObject* objobj;
4611
4612 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4613 return NULL;
4614
4615
4616 if (!make_dbt(objobj, &obj))
4617 return NULL;
4618
4619 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4620}
4621
4622
4623static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004624DBEnv_lock_id(DBEnvObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004625{
4626 int err;
4627 u_int32_t theID;
4628
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004629 CHECK_ENV_NOT_CLOSED(self);
4630 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004631 err = self->db_env->lock_id(self->db_env, &theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004632 MYDB_END_ALLOW_THREADS;
4633 RETURN_IF_ERR();
4634
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004635 return NUMBER_FromLong((long)theID);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004636}
4637
Gregory P. Smithac11e022007-11-05 02:56:31 +00004638static PyObject*
4639DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4640{
4641 int err;
4642 u_int32_t theID;
4643
4644 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4645 return NULL;
4646
4647 CHECK_ENV_NOT_CLOSED(self);
4648 MYDB_BEGIN_ALLOW_THREADS;
4649 err = self->db_env->lock_id_free(self->db_env, theID);
4650 MYDB_END_ALLOW_THREADS;
4651 RETURN_IF_ERR();
4652 RETURN_NONE();
4653}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004654
4655static PyObject*
4656DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4657{
4658 int err;
4659 DBLockObject* dblockobj;
4660
4661 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4662 return NULL;
4663
4664 CHECK_ENV_NOT_CLOSED(self);
4665 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004666 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004667 MYDB_END_ALLOW_THREADS;
4668 RETURN_IF_ERR();
4669 RETURN_NONE();
4670}
4671
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004672#if (DBVER >= 44)
4673static PyObject*
4674DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4675{
4676 int err;
4677 char *file;
4678 u_int32_t flags = 0;
4679 static char* kwnames[] = { "file", "flags", NULL};
4680
4681 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4682 &file, &flags))
4683 return NULL;
4684 CHECK_ENV_NOT_CLOSED(self);
4685
4686 MYDB_BEGIN_ALLOW_THREADS;
4687 err = self->db_env->lsn_reset(self->db_env, file, flags);
4688 MYDB_END_ALLOW_THREADS;
4689 RETURN_IF_ERR();
4690 RETURN_NONE();
4691}
4692#endif /* DBVER >= 4.4 */
4693
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004694static PyObject*
4695DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4696{
4697 int err;
4698 DB_LOG_STAT* statp = NULL;
4699 PyObject* d = NULL;
4700 u_int32_t flags = 0;
4701
4702 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4703 return NULL;
4704 CHECK_ENV_NOT_CLOSED(self);
4705
4706 MYDB_BEGIN_ALLOW_THREADS;
4707 err = self->db_env->log_stat(self->db_env, &statp, flags);
4708 MYDB_END_ALLOW_THREADS;
4709 RETURN_IF_ERR();
4710
4711 /* Turn the stat structure into a dictionary */
4712 d = PyDict_New();
4713 if (d == NULL) {
4714 if (statp)
4715 free(statp);
4716 return NULL;
4717 }
4718
4719#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4720
4721 MAKE_ENTRY(magic);
4722 MAKE_ENTRY(version);
4723 MAKE_ENTRY(mode);
4724 MAKE_ENTRY(lg_bsize);
4725#if (DBVER >= 44)
4726 MAKE_ENTRY(lg_size);
4727 MAKE_ENTRY(record);
4728#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004729#if (DBVER < 41)
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004730 MAKE_ENTRY(lg_max);
4731#endif
4732 MAKE_ENTRY(w_mbytes);
4733 MAKE_ENTRY(w_bytes);
4734 MAKE_ENTRY(wc_mbytes);
4735 MAKE_ENTRY(wc_bytes);
4736 MAKE_ENTRY(wcount);
4737 MAKE_ENTRY(wcount_fill);
4738#if (DBVER >= 44)
4739 MAKE_ENTRY(rcount);
4740#endif
4741 MAKE_ENTRY(scount);
4742 MAKE_ENTRY(cur_file);
4743 MAKE_ENTRY(cur_offset);
4744 MAKE_ENTRY(disk_file);
4745 MAKE_ENTRY(disk_offset);
4746 MAKE_ENTRY(maxcommitperflush);
4747 MAKE_ENTRY(mincommitperflush);
4748 MAKE_ENTRY(regsize);
4749 MAKE_ENTRY(region_wait);
4750 MAKE_ENTRY(region_nowait);
4751
4752#undef MAKE_ENTRY
4753 free(statp);
4754 return d;
4755} /* DBEnv_log_stat */
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004756
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004757
4758static PyObject*
4759DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4760{
4761 int err;
4762 DB_LOCK_STAT* sp;
4763 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004764 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004765
4766 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4767 return NULL;
4768 CHECK_ENV_NOT_CLOSED(self);
4769
4770 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004771 err = self->db_env->lock_stat(self->db_env, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004772 MYDB_END_ALLOW_THREADS;
4773 RETURN_IF_ERR();
4774
4775 /* Turn the stat structure into a dictionary */
4776 d = PyDict_New();
4777 if (d == NULL) {
4778 free(sp);
4779 return NULL;
4780 }
4781
4782#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4783
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004784#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004785 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004786#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004787#if (DBVER >=41)
4788 MAKE_ENTRY(id);
4789 MAKE_ENTRY(cur_maxid);
4790#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004791 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004792 MAKE_ENTRY(maxlocks);
4793 MAKE_ENTRY(maxlockers);
4794 MAKE_ENTRY(maxobjects);
4795 MAKE_ENTRY(nlocks);
4796 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004797 MAKE_ENTRY(nlockers);
4798 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004799 MAKE_ENTRY(nobjects);
4800 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004801 MAKE_ENTRY(nrequests);
4802 MAKE_ENTRY(nreleases);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004803#if (DBVER >= 44)
4804 MAKE_ENTRY(nupgrade);
4805 MAKE_ENTRY(ndowngrade);
4806#endif
Gregory P. Smith29602d22006-01-24 09:46:48 +00004807#if (DBVER < 44)
4808 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004809 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004810#else
4811 MAKE_ENTRY(lock_nowait);
4812 MAKE_ENTRY(lock_wait);
4813#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004814 MAKE_ENTRY(ndeadlocks);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004815#if (DBVER >= 41)
4816 MAKE_ENTRY(locktimeout);
4817 MAKE_ENTRY(txntimeout);
4818#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004819 MAKE_ENTRY(nlocktimeouts);
4820 MAKE_ENTRY(ntxntimeouts);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004821#if (DBVER >= 46)
4822 MAKE_ENTRY(objs_wait);
4823 MAKE_ENTRY(objs_nowait);
4824 MAKE_ENTRY(lockers_wait);
4825 MAKE_ENTRY(lockers_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004826#if (DBVER >= 47)
4827 MAKE_ENTRY(lock_wait);
4828 MAKE_ENTRY(lock_nowait);
4829#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00004830 MAKE_ENTRY(locks_wait);
4831 MAKE_ENTRY(locks_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004832#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004833 MAKE_ENTRY(hash_len);
4834#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004835 MAKE_ENTRY(regsize);
4836 MAKE_ENTRY(region_wait);
4837 MAKE_ENTRY(region_nowait);
4838
4839#undef MAKE_ENTRY
4840 free(sp);
4841 return d;
4842}
4843
Jesus Ceaef9764f2008-05-13 18:45:46 +00004844static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004845DBEnv_log_flush(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00004846{
4847 int err;
4848
Jesus Ceaef9764f2008-05-13 18:45:46 +00004849 CHECK_ENV_NOT_CLOSED(self);
4850
4851 MYDB_BEGIN_ALLOW_THREADS
4852 err = self->db_env->log_flush(self->db_env, NULL);
4853 MYDB_END_ALLOW_THREADS
4854
4855 RETURN_IF_ERR();
4856 RETURN_NONE();
4857}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004858
4859static PyObject*
4860DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4861{
4862 int flags=0;
4863 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004864 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004865 PyObject* list;
4866 PyObject* item = NULL;
4867
4868 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4869 return NULL;
4870
4871 CHECK_ENV_NOT_CLOSED(self);
4872 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004873 err = self->db_env->log_archive(self->db_env, &log_list, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004874 MYDB_END_ALLOW_THREADS;
4875 RETURN_IF_ERR();
4876
Gregory P. Smithbad47452006-06-05 00:33:35 +00004877 list = PyList_New(0);
4878 if (list == NULL) {
4879 if (log_list)
4880 free(log_list);
4881 return NULL;
4882 }
4883
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004884 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004885 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004886 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
Christian Heimes593daf52008-05-26 12:51:38 +00004887 item = PyBytes_FromString (*log_list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004888 if (item == NULL) {
4889 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004890 list = NULL;
4891 break;
4892 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004893 if (PyList_Append(list, item)) {
4894 Py_DECREF(list);
4895 list = NULL;
4896 Py_DECREF(item);
4897 break;
4898 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004899 Py_DECREF(item);
4900 }
4901 free(log_list_start);
4902 }
4903 return list;
4904}
4905
4906
4907static PyObject*
4908DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4909{
4910 int err;
4911 DB_TXN_STAT* sp;
4912 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004913 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004914
4915 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4916 return NULL;
4917 CHECK_ENV_NOT_CLOSED(self);
4918
4919 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004920 err = self->db_env->txn_stat(self->db_env, &sp, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004921 MYDB_END_ALLOW_THREADS;
4922 RETURN_IF_ERR();
4923
4924 /* Turn the stat structure into a dictionary */
4925 d = PyDict_New();
4926 if (d == NULL) {
4927 free(sp);
4928 return NULL;
4929 }
4930
Jesus Ceaef9764f2008-05-13 18:45:46 +00004931#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4932#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4933#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004934
Jesus Ceaef9764f2008-05-13 18:45:46 +00004935 MAKE_DB_LSN_ENTRY(last_ckp);
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004936 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004937 MAKE_ENTRY(last_txnid);
4938 MAKE_ENTRY(maxtxns);
4939 MAKE_ENTRY(nactive);
4940 MAKE_ENTRY(maxnactive);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004941#if (DBVER >= 45)
4942 MAKE_ENTRY(nsnapshot);
4943 MAKE_ENTRY(maxnsnapshot);
4944#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004945 MAKE_ENTRY(nbegins);
4946 MAKE_ENTRY(naborts);
4947 MAKE_ENTRY(ncommits);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004948 MAKE_ENTRY(nrestores);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004949 MAKE_ENTRY(regsize);
4950 MAKE_ENTRY(region_wait);
4951 MAKE_ENTRY(region_nowait);
4952
Jesus Ceaef9764f2008-05-13 18:45:46 +00004953#undef MAKE_DB_LSN_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004954#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004955#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004956 free(sp);
4957 return d;
4958}
4959
4960
4961static PyObject*
4962DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4963{
4964 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004965 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004966
4967 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4968 return NULL;
4969 CHECK_ENV_NOT_CLOSED(self);
4970
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004971 if (self->moduleFlags.getReturnsNone)
4972 ++oldValue;
4973 if (self->moduleFlags.cursorSetReturnsNone)
4974 ++oldValue;
4975 self->moduleFlags.getReturnsNone = (flags >= 1);
4976 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004977 return NUMBER_FromLong(oldValue);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004978}
4979
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004980static PyObject*
4981DBEnv_get_private(DBEnvObject* self)
4982{
4983 /* We can give out the private field even if dbenv is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00004984 Py_INCREF(self->private_obj);
4985 return self->private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004986}
4987
4988static PyObject*
Jesus Cea4907d272008-08-31 14:00:51 +00004989DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004990{
4991 /* We can set the private field even if dbenv is closed */
Jesus Cea4907d272008-08-31 14:00:51 +00004992 Py_DECREF(self->private_obj);
4993 Py_INCREF(private_obj);
4994 self->private_obj = private_obj;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00004995 RETURN_NONE();
4996}
4997
4998
Jesus Ceaef9764f2008-05-13 18:45:46 +00004999static PyObject*
Jesus Ceaca3939c2008-05-22 15:27:38 +00005000DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5001{
5002 int err;
5003 char *host;
5004 long cl_timeout=0, sv_timeout=0;
5005
5006 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
5007
5008 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
5009 &host, &cl_timeout, &sv_timeout))
5010 return NULL;
5011 CHECK_ENV_NOT_CLOSED(self);
5012
5013 MYDB_BEGIN_ALLOW_THREADS;
5014 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
5015 sv_timeout, 0);
5016 MYDB_END_ALLOW_THREADS;
5017 RETURN_IF_ERR();
5018 RETURN_NONE();
5019}
Jesus Ceaca3939c2008-05-22 15:27:38 +00005020
Jesus Ceaca3939c2008-05-22 15:27:38 +00005021static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005022DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
5023{
5024 int err;
5025 int which, onoff;
5026
5027 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
5028 return NULL;
5029 }
5030 CHECK_ENV_NOT_CLOSED(self);
5031 MYDB_BEGIN_ALLOW_THREADS;
5032 err = self->db_env->set_verbose(self->db_env, which, onoff);
5033 MYDB_END_ALLOW_THREADS;
5034 RETURN_IF_ERR();
5035 RETURN_NONE();
5036}
5037
5038#if (DBVER >= 42)
5039static PyObject*
5040DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
5041{
5042 int err;
5043 int which;
5044 int verbose;
5045
5046 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
5047 return NULL;
5048 }
5049 CHECK_ENV_NOT_CLOSED(self);
5050 MYDB_BEGIN_ALLOW_THREADS;
5051 err = self->db_env->get_verbose(self->db_env, which, &verbose);
5052 MYDB_END_ALLOW_THREADS;
5053 RETURN_IF_ERR();
5054 return PyBool_FromLong(verbose);
5055}
5056#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005057
5058#if (DBVER >= 45)
5059static void
5060_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
5061{
5062 DBEnvObject *dbenv;
5063 PyObject* callback;
5064 PyObject* args;
5065 PyObject* result = NULL;
5066
5067 MYDB_BEGIN_BLOCK_THREADS;
5068 dbenv = (DBEnvObject *)db_env->app_private;
5069 callback = dbenv->event_notifyCallback;
5070 if (callback) {
5071 if (event == DB_EVENT_REP_NEWMASTER) {
5072 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
5073 } else {
5074 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5075 }
5076 if (args) {
5077 result = PyEval_CallObject(callback, args);
5078 }
5079 if ((!args) || (!result)) {
5080 PyErr_Print();
5081 }
5082 Py_XDECREF(args);
5083 Py_XDECREF(result);
5084 }
5085 MYDB_END_BLOCK_THREADS;
5086}
5087#endif
5088
5089#if (DBVER >= 45)
5090static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005091DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005092{
5093 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005094
5095 CHECK_ENV_NOT_CLOSED(self);
5096
5097 if (!PyCallable_Check(notifyFunc)) {
5098 makeTypeError("Callable", notifyFunc);
5099 return NULL;
5100 }
5101
5102 Py_XDECREF(self->event_notifyCallback);
5103 Py_INCREF(notifyFunc);
5104 self->event_notifyCallback = notifyFunc;
5105
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005106 /* This is to workaround a problem with un-initialized threads (see
5107 comment in DB_associate) */
5108#ifdef WITH_THREAD
5109 PyEval_InitThreads();
5110#endif
5111
Jesus Ceaef9764f2008-05-13 18:45:46 +00005112 MYDB_BEGIN_ALLOW_THREADS;
5113 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5114 MYDB_END_ALLOW_THREADS;
5115
5116 if (err) {
5117 Py_DECREF(notifyFunc);
5118 self->event_notifyCallback = NULL;
5119 }
5120
5121 RETURN_IF_ERR();
5122 RETURN_NONE();
5123}
5124#endif
5125
5126
5127/* --------------------------------------------------------------------- */
5128/* REPLICATION METHODS: Base Replication */
5129
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005130
5131static PyObject*
5132DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
5133{
5134 int err;
5135 PyObject *control_py, *rec_py;
5136 DBT control, rec;
5137 int envid;
5138#if (DBVER >= 42)
5139 DB_LSN lsn;
5140#endif
5141
5142 if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
5143 &rec_py, &envid))
5144 return NULL;
5145 CHECK_ENV_NOT_CLOSED(self);
5146
5147 if (!make_dbt(control_py, &control))
5148 return NULL;
5149 if (!make_dbt(rec_py, &rec))
5150 return NULL;
5151
5152 MYDB_BEGIN_ALLOW_THREADS;
5153#if (DBVER >= 46)
5154 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5155 envid, &lsn);
5156#else
5157#if (DBVER >= 42)
5158 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5159 &envid, &lsn);
5160#else
5161 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5162 &envid);
5163#endif
5164#endif
5165 MYDB_END_ALLOW_THREADS;
5166 switch (err) {
5167 case DB_REP_NEWMASTER :
5168 return Py_BuildValue("(iO)", envid, Py_None);
5169 break;
5170
5171 case DB_REP_DUPMASTER :
5172 case DB_REP_HOLDELECTION :
5173#if (DBVER >= 44)
5174 case DB_REP_IGNORE :
5175 case DB_REP_JOIN_FAILURE :
5176#endif
5177 return Py_BuildValue("(iO)", err, Py_None);
5178 break;
5179 case DB_REP_NEWSITE :
Jesus Cea4907d272008-08-31 14:00:51 +00005180 {
5181 PyObject *tmp, *r;
5182
5183 if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
5184 return NULL;
5185 }
5186
5187 r = Py_BuildValue("(iO)", err, tmp);
5188 Py_DECREF(tmp);
5189 return r;
5190 break;
5191 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005192#if (DBVER >= 42)
5193 case DB_REP_NOTPERM :
5194 case DB_REP_ISPERM :
5195 return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
5196 break;
5197#endif
5198 }
5199 RETURN_IF_ERR();
5200 return Py_BuildValue("(OO)", Py_None, Py_None);
5201}
5202
5203static int
5204_DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
5205 const DB_LSN *lsn, int envid, u_int32_t flags)
5206{
5207 DBEnvObject *dbenv;
5208 PyObject* rep_transport;
5209 PyObject* args;
Jesus Cea4907d272008-08-31 14:00:51 +00005210 PyObject *a, *b;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005211 PyObject* result = NULL;
5212 int ret=0;
5213
5214 MYDB_BEGIN_BLOCK_THREADS;
5215 dbenv = (DBEnvObject *)db_env->app_private;
5216 rep_transport = dbenv->rep_transport;
5217
Jesus Cea4907d272008-08-31 14:00:51 +00005218 /*
5219 ** The errors in 'a' or 'b' are detected in "Py_BuildValue".
5220 */
5221 a = PyBytes_FromStringAndSize(control->data, control->size);
5222 b = PyBytes_FromStringAndSize(rec->data, rec->size);
5223
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005224 args = Py_BuildValue(
5225#if (PY_VERSION_HEX >= 0x02040000)
Jesus Cea4907d272008-08-31 14:00:51 +00005226 "(OOO(ll)iI)",
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005227#else
Jesus Cea4907d272008-08-31 14:00:51 +00005228 "(OOO(ll)ii)",
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005229#endif
5230 dbenv,
Jesus Cea4907d272008-08-31 14:00:51 +00005231 a, b,
5232 lsn->file, lsn->offset, envid, flags);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005233 if (args) {
5234 result = PyEval_CallObject(rep_transport, args);
5235 }
5236
5237 if ((!args) || (!result)) {
5238 PyErr_Print();
5239 ret = -1;
5240 }
Jesus Cea4907d272008-08-31 14:00:51 +00005241 Py_XDECREF(a);
5242 Py_XDECREF(b);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005243 Py_XDECREF(args);
5244 Py_XDECREF(result);
5245 MYDB_END_BLOCK_THREADS;
5246 return ret;
5247}
5248
5249#if (DBVER <= 41)
5250static int
5251_DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec,
5252 int envid, u_int32_t flags)
5253{
5254 DB_LSN lsn;
5255
5256 lsn.file = -1; /* Dummy values */
5257 lsn.offset = -1;
5258 return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid,
5259 flags);
5260}
5261#endif
5262
5263static PyObject*
5264DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
5265{
5266 int err;
5267 int envid;
5268 PyObject *rep_transport;
5269
5270 if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
5271 return NULL;
5272 CHECK_ENV_NOT_CLOSED(self);
5273 if (!PyCallable_Check(rep_transport)) {
5274 makeTypeError("Callable", rep_transport);
5275 return NULL;
5276 }
5277
5278 MYDB_BEGIN_ALLOW_THREADS;
5279#if (DBVER >=45)
5280 err = self->db_env->rep_set_transport(self->db_env, envid,
5281 &_DBEnv_rep_transportCallback);
5282#else
5283#if (DBVER >= 42)
5284 err = self->db_env->set_rep_transport(self->db_env, envid,
5285 &_DBEnv_rep_transportCallback);
5286#else
5287 err = self->db_env->set_rep_transport(self->db_env, envid,
5288 &_DBEnv_rep_transportCallbackOLD);
5289#endif
5290#endif
5291 MYDB_END_ALLOW_THREADS;
5292 RETURN_IF_ERR();
5293
5294 Py_DECREF(self->rep_transport);
5295 Py_INCREF(rep_transport);
5296 self->rep_transport = rep_transport;
5297 RETURN_NONE();
5298}
5299
5300#if (DBVER >= 47)
5301static PyObject*
5302DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
5303{
5304 int err;
5305 unsigned int minimum, maximum;
5306
5307 if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
5308 return NULL;
5309 CHECK_ENV_NOT_CLOSED(self);
5310
5311 MYDB_BEGIN_ALLOW_THREADS;
5312 err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
5313 MYDB_END_ALLOW_THREADS;
5314 RETURN_IF_ERR();
5315 RETURN_NONE();
5316}
5317
5318static PyObject*
5319DBEnv_rep_get_request(DBEnvObject* self)
5320{
5321 int err;
5322 u_int32_t minimum, maximum;
5323
5324 CHECK_ENV_NOT_CLOSED(self);
5325 MYDB_BEGIN_ALLOW_THREADS;
5326 err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
5327 MYDB_END_ALLOW_THREADS;
5328 RETURN_IF_ERR();
5329#if (PY_VERSION_HEX >= 0x02040000)
5330 return Py_BuildValue("II", minimum, maximum);
5331#else
5332 return Py_BuildValue("ii", minimum, maximum);
5333#endif
5334}
5335#endif
5336
5337#if (DBVER >= 45)
5338static PyObject*
5339DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
5340{
5341 int err;
5342 int limit;
5343
5344 if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
5345 return NULL;
5346 CHECK_ENV_NOT_CLOSED(self);
5347
5348 MYDB_BEGIN_ALLOW_THREADS;
5349 err = self->db_env->rep_set_limit(self->db_env, 0, limit);
5350 MYDB_END_ALLOW_THREADS;
5351 RETURN_IF_ERR();
5352 RETURN_NONE();
5353}
5354
5355static PyObject*
5356DBEnv_rep_get_limit(DBEnvObject* self)
5357{
5358 int err;
5359 u_int32_t gbytes, bytes;
5360
5361 CHECK_ENV_NOT_CLOSED(self);
5362 MYDB_BEGIN_ALLOW_THREADS;
5363 err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
5364 MYDB_END_ALLOW_THREADS;
5365 RETURN_IF_ERR();
5366 return NUMBER_FromLong(bytes);
5367}
5368#endif
5369
5370#if (DBVER >= 44)
5371static PyObject*
5372DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
5373{
5374 int err;
5375 int which;
5376 int onoff;
5377
5378 if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
5379 return NULL;
5380 CHECK_ENV_NOT_CLOSED(self);
5381
5382 MYDB_BEGIN_ALLOW_THREADS;
5383 err = self->db_env->rep_set_config(self->db_env, which, onoff);
5384 MYDB_END_ALLOW_THREADS;
5385 RETURN_IF_ERR();
5386 RETURN_NONE();
5387}
5388
5389static PyObject*
5390DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
5391{
5392 int err;
5393 int which;
5394 int onoff;
5395
5396 if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
5397 return NULL;
5398 }
5399 CHECK_ENV_NOT_CLOSED(self);
5400 MYDB_BEGIN_ALLOW_THREADS;
5401 err = self->db_env->rep_get_config(self->db_env, which, &onoff);
5402 MYDB_END_ALLOW_THREADS;
5403 RETURN_IF_ERR();
5404 return PyBool_FromLong(onoff);
5405}
5406#endif
5407
5408#if (DBVER >= 46)
5409static PyObject*
5410DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
5411{
5412 int err;
5413 u_int32_t nsites, nvotes;
5414
5415 if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
5416 return NULL;
5417 }
5418 CHECK_ENV_NOT_CLOSED(self);
5419 MYDB_BEGIN_ALLOW_THREADS;
5420 err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0);
5421 MYDB_END_ALLOW_THREADS;
5422 RETURN_IF_ERR();
5423 RETURN_NONE();
5424}
5425#endif
5426
5427static PyObject*
5428DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5429{
5430 int err;
5431 PyObject *cdata_py = Py_None;
5432 DBT cdata;
5433 int flags;
5434 static char* kwnames[] = {"flags","cdata", NULL};
5435
5436 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5437 "i|O:rep_start", kwnames, &flags, &cdata_py))
5438 {
5439 return NULL;
5440 }
5441 CHECK_ENV_NOT_CLOSED(self);
5442
5443 if (!make_dbt(cdata_py, &cdata))
5444 return NULL;
5445
5446 MYDB_BEGIN_ALLOW_THREADS;
5447 err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
5448 flags);
5449 MYDB_END_ALLOW_THREADS;
5450 RETURN_IF_ERR();
5451 RETURN_NONE();
5452}
5453
5454#if (DBVER >= 44)
5455static PyObject*
5456DBEnv_rep_sync(DBEnvObject* self)
5457{
5458 int err;
5459
5460 CHECK_ENV_NOT_CLOSED(self);
5461 MYDB_BEGIN_ALLOW_THREADS;
5462 err = self->db_env->rep_sync(self->db_env, 0);
5463 MYDB_END_ALLOW_THREADS;
5464 RETURN_IF_ERR();
5465 RETURN_NONE();
5466}
5467#endif
5468
5469
Jesus Ceaef9764f2008-05-13 18:45:46 +00005470#if (DBVER >= 45)
5471static PyObject*
5472DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5473{
5474 int err;
5475 int nsites;
5476
5477 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5478 return NULL;
5479 }
5480 CHECK_ENV_NOT_CLOSED(self);
5481 MYDB_BEGIN_ALLOW_THREADS;
5482 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5483 MYDB_END_ALLOW_THREADS;
5484 RETURN_IF_ERR();
5485 RETURN_NONE();
5486}
5487
5488static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005489DBEnv_rep_get_nsites(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005490{
5491 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005492#if (DBVER >= 47)
5493 u_int32_t nsites;
5494#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005495 int nsites;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005496#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005497
Jesus Ceaef9764f2008-05-13 18:45:46 +00005498 CHECK_ENV_NOT_CLOSED(self);
5499 MYDB_BEGIN_ALLOW_THREADS;
5500 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5501 MYDB_END_ALLOW_THREADS;
5502 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005503 return NUMBER_FromLong(nsites);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005504}
5505
5506static PyObject*
5507DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5508{
5509 int err;
5510 int priority;
5511
5512 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5513 return NULL;
5514 }
5515 CHECK_ENV_NOT_CLOSED(self);
5516 MYDB_BEGIN_ALLOW_THREADS;
5517 err = self->db_env->rep_set_priority(self->db_env, priority);
5518 MYDB_END_ALLOW_THREADS;
5519 RETURN_IF_ERR();
5520 RETURN_NONE();
5521}
5522
5523static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005524DBEnv_rep_get_priority(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005525{
5526 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005527#if (DBVER >= 47)
5528 u_int32_t priority;
5529#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005530 int priority;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005531#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005532
Jesus Ceaef9764f2008-05-13 18:45:46 +00005533 CHECK_ENV_NOT_CLOSED(self);
5534 MYDB_BEGIN_ALLOW_THREADS;
5535 err = self->db_env->rep_get_priority(self->db_env, &priority);
5536 MYDB_END_ALLOW_THREADS;
5537 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005538 return NUMBER_FromLong(priority);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005539}
5540
5541static PyObject*
5542DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5543{
5544 int err;
5545 int which, timeout;
5546
5547 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5548 return NULL;
5549 }
5550 CHECK_ENV_NOT_CLOSED(self);
5551 MYDB_BEGIN_ALLOW_THREADS;
5552 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5553 MYDB_END_ALLOW_THREADS;
5554 RETURN_IF_ERR();
5555 RETURN_NONE();
5556}
5557
5558static PyObject*
5559DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5560{
5561 int err;
5562 int which;
5563 u_int32_t timeout;
5564
5565 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5566 return NULL;
5567 }
5568 CHECK_ENV_NOT_CLOSED(self);
5569 MYDB_BEGIN_ALLOW_THREADS;
5570 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5571 MYDB_END_ALLOW_THREADS;
5572 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005573 return NUMBER_FromLong(timeout);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005574}
5575#endif
5576
5577/* --------------------------------------------------------------------- */
5578/* REPLICATION METHODS: Replication Manager */
5579
5580#if (DBVER >= 45)
5581static PyObject*
5582DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5583 kwargs)
5584{
5585 int err;
5586 int nthreads, flags;
5587 static char* kwnames[] = {"nthreads","flags", NULL};
5588
5589 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5590 "ii:repmgr_start", kwnames, &nthreads, &flags))
5591 {
5592 return NULL;
5593 }
5594 CHECK_ENV_NOT_CLOSED(self);
5595 MYDB_BEGIN_ALLOW_THREADS;
5596 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5597 MYDB_END_ALLOW_THREADS;
5598 RETURN_IF_ERR();
5599 RETURN_NONE();
5600}
5601
5602static PyObject*
5603DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5604 kwargs)
5605{
5606 int err;
5607 char *host;
5608 int port;
5609 int flags = 0;
5610 static char* kwnames[] = {"host", "port", "flags", NULL};
5611
5612 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5613 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5614 {
5615 return NULL;
5616 }
5617 CHECK_ENV_NOT_CLOSED(self);
5618 MYDB_BEGIN_ALLOW_THREADS;
5619 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5620 MYDB_END_ALLOW_THREADS;
5621 RETURN_IF_ERR();
5622 RETURN_NONE();
5623}
5624
5625static PyObject*
5626DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5627 kwargs)
5628{
5629 int err;
5630 char *host;
5631 int port;
5632 int flags = 0;
5633 int eidp;
5634 static char* kwnames[] = {"host", "port", "flags", NULL};
5635
5636 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5637 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5638 {
5639 return NULL;
5640 }
5641 CHECK_ENV_NOT_CLOSED(self);
5642 MYDB_BEGIN_ALLOW_THREADS;
5643 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5644 MYDB_END_ALLOW_THREADS;
5645 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005646 return NUMBER_FromLong(eidp);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005647}
5648
5649static PyObject*
5650DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5651{
5652 int err;
5653 int ack_policy;
5654
5655 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5656 {
5657 return NULL;
5658 }
5659 CHECK_ENV_NOT_CLOSED(self);
5660 MYDB_BEGIN_ALLOW_THREADS;
5661 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5662 MYDB_END_ALLOW_THREADS;
5663 RETURN_IF_ERR();
5664 RETURN_NONE();
5665}
5666
5667static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005668DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005669{
5670 int err;
5671 int ack_policy;
5672
Jesus Ceaef9764f2008-05-13 18:45:46 +00005673 CHECK_ENV_NOT_CLOSED(self);
5674 MYDB_BEGIN_ALLOW_THREADS;
5675 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5676 MYDB_END_ALLOW_THREADS;
5677 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005678 return NUMBER_FromLong(ack_policy);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005679}
5680
5681static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005682DBEnv_repmgr_site_list(DBEnvObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005683{
5684 int err;
5685 unsigned int countp;
5686 DB_REPMGR_SITE *listp;
5687 PyObject *stats, *key, *tuple;
5688
Jesus Ceaef9764f2008-05-13 18:45:46 +00005689 CHECK_ENV_NOT_CLOSED(self);
5690 MYDB_BEGIN_ALLOW_THREADS;
5691 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5692 MYDB_END_ALLOW_THREADS;
5693 RETURN_IF_ERR();
5694
5695 stats=PyDict_New();
5696 if (stats == NULL) {
5697 free(listp);
5698 return NULL;
5699 }
5700
5701 for(;countp--;) {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005702 key=NUMBER_FromLong(listp[countp].eid);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005703 if(!key) {
5704 Py_DECREF(stats);
5705 free(listp);
5706 return NULL;
5707 }
5708#if (PY_VERSION_HEX >= 0x02040000)
5709 tuple=Py_BuildValue("(sII)", listp[countp].host,
5710 listp[countp].port, listp[countp].status);
5711#else
5712 tuple=Py_BuildValue("(sii)", listp[countp].host,
5713 listp[countp].port, listp[countp].status);
5714#endif
5715 if(!tuple) {
5716 Py_DECREF(key);
5717 Py_DECREF(stats);
5718 free(listp);
5719 return NULL;
5720 }
5721 if(PyDict_SetItem(stats, key, tuple)) {
5722 Py_DECREF(key);
5723 Py_DECREF(tuple);
5724 Py_DECREF(stats);
5725 free(listp);
5726 return NULL;
5727 }
5728 }
5729 free(listp);
5730 return stats;
5731}
5732#endif
5733
5734#if (DBVER >= 46)
5735static PyObject*
5736DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5737{
5738 int err;
5739 int flags=0;
5740 static char* kwnames[] = { "flags", NULL };
5741
5742 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5743 kwnames, &flags))
5744 {
5745 return NULL;
5746 }
5747 CHECK_ENV_NOT_CLOSED(self);
5748 MYDB_BEGIN_ALLOW_THREADS;
5749 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5750 MYDB_END_ALLOW_THREADS;
5751 RETURN_IF_ERR();
5752 RETURN_NONE();
5753}
5754
5755static PyObject*
5756DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5757{
5758 int err;
5759 int flags=0;
5760 DB_REPMGR_STAT *statp;
5761 PyObject *stats;
5762 static char* kwnames[] = { "flags", NULL };
5763
5764 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5765 kwnames, &flags))
5766 {
5767 return NULL;
5768 }
5769 CHECK_ENV_NOT_CLOSED(self);
5770 MYDB_BEGIN_ALLOW_THREADS;
5771 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5772 MYDB_END_ALLOW_THREADS;
5773 RETURN_IF_ERR();
5774
5775 stats=PyDict_New();
5776 if (stats == NULL) {
5777 free(statp);
5778 return NULL;
5779 }
5780
5781#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5782
5783 MAKE_ENTRY(perm_failed);
5784 MAKE_ENTRY(msgs_queued);
5785 MAKE_ENTRY(msgs_dropped);
5786 MAKE_ENTRY(connection_drop);
5787 MAKE_ENTRY(connect_fail);
5788
5789#undef MAKE_ENTRY
5790
5791 free(statp);
5792 return stats;
5793}
5794#endif
5795
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005796
5797/* --------------------------------------------------------------------- */
5798/* DBTxn methods */
5799
5800
Jesus Ceaef9764f2008-05-13 18:45:46 +00005801static void _close_transaction_cursors(DBTxnObject* txn)
5802{
5803 PyObject *dummy;
5804
5805 while(txn->children_cursors) {
5806 PyErr_Warn(PyExc_RuntimeWarning,
5807 "Must close cursors before resolving a transaction.");
5808 dummy=DBC_close_internal(txn->children_cursors);
5809 Py_XDECREF(dummy);
5810 }
5811}
5812
5813static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5814{
5815 DBObject *db;
5816#if (DBVER >= 43)
5817 DBSequenceObject *dbs;
5818#endif
5819
5820 while (txn->children_dbs) {
5821 db=txn->children_dbs;
5822 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5823 if (txn->parent_txn) {
5824 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5825 db->txn=txn->parent_txn;
5826 } else {
5827 /* The db is already linked to its environment,
5828 ** so nothing to do.
5829 */
5830 db->txn=NULL;
5831 }
5832 }
5833
5834#if (DBVER >= 43)
5835 while (txn->children_sequences) {
5836 dbs=txn->children_sequences;
5837 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5838 if (txn->parent_txn) {
5839 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5840 dbs->txn=txn->parent_txn;
5841 } else {
5842 /* The sequence is already linked to its
5843 ** parent db. Nothing to do.
5844 */
5845 dbs->txn=NULL;
5846 }
5847 }
5848#endif
5849}
5850
5851
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005852static PyObject*
5853DBTxn_commit(DBTxnObject* self, PyObject* args)
5854{
5855 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005856 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005857
5858 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5859 return NULL;
5860
Jesus Ceaef9764f2008-05-13 18:45:46 +00005861 _close_transaction_cursors(self);
5862
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005863 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005864 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005865 "after txn_commit, txn_abort "
5866 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005867 if (t) {
5868 PyErr_SetObject(DBError, t);
5869 Py_DECREF(t);
5870 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005871 return NULL;
5872 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005873 self->flag_prepare=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005874 txn = self->txn;
5875 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005876
5877 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5878
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005879 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005880 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005881 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005882
5883 _promote_transaction_dbs_and_sequences(self);
5884
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005885 RETURN_IF_ERR();
5886 RETURN_NONE();
5887}
5888
5889static PyObject*
5890DBTxn_prepare(DBTxnObject* self, PyObject* args)
5891{
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005892 int err;
5893 char* gid=NULL;
5894 int gid_size=0;
5895
5896 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
5897 return NULL;
5898
5899 if (gid_size != DB_XIDDATASIZE) {
5900 PyErr_SetString(PyExc_TypeError,
5901 "gid must be DB_XIDDATASIZE bytes long");
5902 return NULL;
5903 }
5904
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005905 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005906 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005907 "after txn_commit, txn_abort "
5908 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005909 if (t) {
5910 PyErr_SetObject(DBError, t);
5911 Py_DECREF(t);
5912 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005913 return NULL;
5914 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005915 self->flag_prepare=1; /* Prepare state */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005916 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005917 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005918 MYDB_END_ALLOW_THREADS;
5919 RETURN_IF_ERR();
5920 RETURN_NONE();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005921}
5922
5923
5924static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005925DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005926{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005927 PyObject *dummy;
5928 int err=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005929 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005930
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005931 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005932 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005933 "after txn_commit, txn_abort "
5934 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005935 if (t) {
5936 PyErr_SetObject(DBError, t);
5937 Py_DECREF(t);
5938 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005939 return NULL;
5940 }
5941 txn = self->txn;
5942 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005943
5944 _close_transaction_cursors(self);
5945#if (DBVER >= 43)
5946 while (self->children_sequences) {
5947 dummy=DBSequence_close_internal(self->children_sequences,0,0);
5948 Py_XDECREF(dummy);
5949 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005950#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005951 while (self->children_dbs) {
5952 dummy=DB_close_internal(self->children_dbs,0);
5953 Py_XDECREF(dummy);
5954 }
5955
5956 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5957
5958 MYDB_BEGIN_ALLOW_THREADS;
5959 if (discard) {
5960 assert(!self->flag_prepare);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005961 err = txn->discard(txn,0);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005962 } else {
5963 /*
5964 ** If the transaction is in the "prepare" or "recover" state,
5965 ** we better do not implicitly abort it.
5966 */
5967 if (!self->flag_prepare) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00005968 err = txn->abort(txn);
Jesus Ceaef9764f2008-05-13 18:45:46 +00005969 }
5970 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005971 MYDB_END_ALLOW_THREADS;
5972 RETURN_IF_ERR();
5973 RETURN_NONE();
5974}
5975
Jesus Ceaef9764f2008-05-13 18:45:46 +00005976static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005977DBTxn_abort(DBTxnObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005978{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005979 self->flag_prepare=0;
5980 _close_transaction_cursors(self);
5981
5982 return DBTxn_abort_discard_internal(self,0);
5983}
5984
5985static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005986DBTxn_discard(DBTxnObject* self)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005987{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005988 self->flag_prepare=0;
5989 _close_transaction_cursors(self);
5990
5991 return DBTxn_abort_discard_internal(self,1);
5992}
5993
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005994
5995static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00005996DBTxn_id(DBTxnObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005997{
5998 int id;
5999
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00006000 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00006001 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00006002 "after txn_commit, txn_abort "
6003 "or txn_discard");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006004 if (t) {
6005 PyErr_SetObject(DBError, t);
6006 Py_DECREF(t);
6007 }
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00006008 return NULL;
6009 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006010 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006011 id = self->txn->id(self->txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006012 MYDB_END_ALLOW_THREADS;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006013 return NUMBER_FromLong(id);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006014}
6015
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006016#if (DBVER >= 43)
6017/* --------------------------------------------------------------------- */
6018/* DBSequence methods */
6019
6020
6021static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00006022DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006023{
Jesus Ceaef9764f2008-05-13 18:45:46 +00006024 int err=0;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006025
Jesus Ceaef9764f2008-05-13 18:45:46 +00006026 if (self->sequence!=NULL) {
6027 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
6028 if (self->txn) {
6029 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
6030 self->txn=NULL;
6031 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006032
Jesus Ceaef9764f2008-05-13 18:45:46 +00006033 if (!do_not_close) {
6034 MYDB_BEGIN_ALLOW_THREADS
6035 err = self->sequence->close(self->sequence, flags);
6036 MYDB_END_ALLOW_THREADS
6037 }
6038 self->sequence = NULL;
6039
6040 RETURN_IF_ERR();
6041 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006042
6043 RETURN_NONE();
6044}
6045
6046static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00006047DBSequence_close(DBSequenceObject* self, PyObject* args)
6048{
6049 int flags=0;
6050 if (!PyArg_ParseTuple(args,"|i:close", &flags))
6051 return NULL;
6052
6053 return DBSequence_close_internal(self,flags,0);
6054}
6055
6056static PyObject*
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006057DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6058{
6059 int err, flags = 0;
6060 int delta = 1;
6061 db_seq_t value;
6062 PyObject *txnobj = NULL;
6063 DB_TXN *txn = NULL;
6064 static char* kwnames[] = {"delta", "txn", "flags", NULL };
6065 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
6066 return NULL;
6067 CHECK_SEQUENCE_NOT_CLOSED(self)
6068
6069 if (!checkTxnObj(txnobj, &txn))
6070 return NULL;
6071
6072 MYDB_BEGIN_ALLOW_THREADS
6073 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
6074 MYDB_END_ALLOW_THREADS
6075
6076 RETURN_IF_ERR();
6077 return PyLong_FromLongLong(value);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006078}
6079
6080static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006081DBSequence_get_dbp(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006082{
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006083 CHECK_SEQUENCE_NOT_CLOSED(self)
6084 Py_INCREF(self->mydb);
6085 return (PyObject* )self->mydb;
6086}
6087
6088static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006089DBSequence_get_key(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006090{
6091 int err;
6092 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00006093 PyObject *retval = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006094
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006095 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006096 CHECK_SEQUENCE_NOT_CLOSED(self)
6097 MYDB_BEGIN_ALLOW_THREADS
6098 err = self->sequence->get_key(self->sequence, &key);
6099 MYDB_END_ALLOW_THREADS
6100
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006101 if (!err)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006102 retval = Build_PyString(key.data, key.size);
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006103
6104 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006105 RETURN_IF_ERR();
6106
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00006107 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006108}
6109
6110static PyObject*
6111DBSequence_init_value(DBSequenceObject* self, PyObject* args)
6112{
6113 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006114 PY_LONG_LONG value;
6115 db_seq_t value2;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006116 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006117 return NULL;
6118 CHECK_SEQUENCE_NOT_CLOSED(self)
6119
Jesus Ceaef9764f2008-05-13 18:45:46 +00006120 value2=value; /* If truncation, compiler should show a warning */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006121 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006122 err = self->sequence->initial_value(self->sequence, value2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006123 MYDB_END_ALLOW_THREADS
6124
6125 RETURN_IF_ERR();
6126
6127 RETURN_NONE();
6128}
6129
6130static PyObject*
6131DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6132{
6133 int err, flags = 0;
6134 PyObject* keyobj;
6135 PyObject *txnobj = NULL;
6136 DB_TXN *txn = NULL;
6137 DBT key;
6138
6139 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006140 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006141 return NULL;
6142
6143 if (!checkTxnObj(txnobj, &txn))
6144 return NULL;
6145
6146 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
6147 return NULL;
6148
6149 MYDB_BEGIN_ALLOW_THREADS
6150 err = self->sequence->open(self->sequence, txn, &key, flags);
6151 MYDB_END_ALLOW_THREADS
6152
Jesus Ceaac25fab2008-09-03 17:50:32 +00006153 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006154 RETURN_IF_ERR();
6155
Jesus Ceaef9764f2008-05-13 18:45:46 +00006156 if (txn) {
6157 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
6158 self->txn=(DBTxnObject *)txnobj;
6159 }
6160
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006161 RETURN_NONE();
6162}
6163
6164static PyObject*
6165DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6166{
Jesus Ceaef9764f2008-05-13 18:45:46 +00006167 PyObject *dummy;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006168 int err, flags = 0;
6169 PyObject *txnobj = NULL;
6170 DB_TXN *txn = NULL;
6171
6172 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006173 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006174 return NULL;
6175
6176 if (!checkTxnObj(txnobj, &txn))
6177 return NULL;
6178
6179 CHECK_SEQUENCE_NOT_CLOSED(self)
6180
6181 MYDB_BEGIN_ALLOW_THREADS
6182 err = self->sequence->remove(self->sequence, txn, flags);
6183 MYDB_END_ALLOW_THREADS
6184
Jesus Ceaef9764f2008-05-13 18:45:46 +00006185 dummy=DBSequence_close_internal(self,flags,1);
6186 Py_XDECREF(dummy);
6187
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006188 RETURN_IF_ERR();
6189 RETURN_NONE();
6190}
6191
6192static PyObject*
6193DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
6194{
6195 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006196 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006197 return NULL;
6198 CHECK_SEQUENCE_NOT_CLOSED(self)
6199
6200 MYDB_BEGIN_ALLOW_THREADS
6201 err = self->sequence->set_cachesize(self->sequence, size);
6202 MYDB_END_ALLOW_THREADS
6203
6204 RETURN_IF_ERR();
6205 RETURN_NONE();
6206}
6207
6208static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006209DBSequence_get_cachesize(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006210{
6211 int err, size;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006212
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006213 CHECK_SEQUENCE_NOT_CLOSED(self)
6214
6215 MYDB_BEGIN_ALLOW_THREADS
6216 err = self->sequence->get_cachesize(self->sequence, &size);
6217 MYDB_END_ALLOW_THREADS
6218
6219 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006220 return NUMBER_FromLong(size);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006221}
6222
6223static PyObject*
6224DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
6225{
6226 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00006227 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006228 return NULL;
6229 CHECK_SEQUENCE_NOT_CLOSED(self)
6230
6231 MYDB_BEGIN_ALLOW_THREADS
6232 err = self->sequence->set_flags(self->sequence, flags);
6233 MYDB_END_ALLOW_THREADS
6234
6235 RETURN_IF_ERR();
6236 RETURN_NONE();
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006237}
6238
6239static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006240DBSequence_get_flags(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006241{
6242 unsigned int flags;
6243 int err;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006244
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006245 CHECK_SEQUENCE_NOT_CLOSED(self)
6246
6247 MYDB_BEGIN_ALLOW_THREADS
6248 err = self->sequence->get_flags(self->sequence, &flags);
6249 MYDB_END_ALLOW_THREADS
6250
6251 RETURN_IF_ERR();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006252 return NUMBER_FromLong((int)flags);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006253}
6254
6255static PyObject*
6256DBSequence_set_range(DBSequenceObject* self, PyObject* args)
6257{
6258 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006259 PY_LONG_LONG min, max;
6260 db_seq_t min2, max2;
Tim Petersbb21b2c2006-06-06 15:50:17 +00006261 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006262 return NULL;
6263 CHECK_SEQUENCE_NOT_CLOSED(self)
6264
Jesus Ceaef9764f2008-05-13 18:45:46 +00006265 min2=min; /* If truncation, compiler should show a warning */
6266 max2=max;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006267 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006268 err = self->sequence->set_range(self->sequence, min2, max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006269 MYDB_END_ALLOW_THREADS
6270
6271 RETURN_IF_ERR();
6272 RETURN_NONE();
6273}
6274
6275static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006276DBSequence_get_range(DBSequenceObject* self)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006277{
6278 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006279 PY_LONG_LONG min, max;
6280 db_seq_t min2, max2;
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006281
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006282 CHECK_SEQUENCE_NOT_CLOSED(self)
6283
6284 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00006285 err = self->sequence->get_range(self->sequence, &min2, &max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006286 MYDB_END_ALLOW_THREADS
6287
6288 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00006289 min=min2; /* If truncation, compiler should show a warning */
6290 max=max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006291 return Py_BuildValue("(LL)", min, max);
6292}
6293
6294static PyObject*
6295DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6296{
6297 int err, flags = 0;
6298 DB_SEQUENCE_STAT* sp = NULL;
6299 PyObject* dict_stat;
6300 static char* kwnames[] = {"flags", NULL };
6301 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
6302 return NULL;
6303 CHECK_SEQUENCE_NOT_CLOSED(self);
6304
6305 MYDB_BEGIN_ALLOW_THREADS;
6306 err = self->sequence->stat(self->sequence, &sp, flags);
6307 MYDB_END_ALLOW_THREADS;
6308 RETURN_IF_ERR();
6309
6310 if ((dict_stat = PyDict_New()) == NULL) {
6311 free(sp);
6312 return NULL;
6313 }
6314
6315
6316#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
6317#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
6318
6319 MAKE_INT_ENTRY(wait);
6320 MAKE_INT_ENTRY(nowait);
6321 MAKE_LONG_LONG_ENTRY(current);
6322 MAKE_LONG_LONG_ENTRY(value);
6323 MAKE_LONG_LONG_ENTRY(last_value);
6324 MAKE_LONG_LONG_ENTRY(min);
6325 MAKE_LONG_LONG_ENTRY(max);
6326 MAKE_INT_ENTRY(cache_size);
6327 MAKE_INT_ENTRY(flags);
6328
6329#undef MAKE_INT_ENTRY
6330#undef MAKE_LONG_LONG_ENTRY
6331
6332 free(sp);
6333 return dict_stat;
6334}
6335#endif
6336
6337
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006338/* --------------------------------------------------------------------- */
6339/* Method definition tables and type objects */
6340
6341static PyMethodDef DB_methods[] = {
Jesus Cea4907d272008-08-31 14:00:51 +00006342 {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006343 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006344 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006345 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
6346 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006347 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
6348 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006349 {"fd", (PyCFunction)DB_fd, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006350 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00006351 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006352 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006353 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006354 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006355 {"get_type", (PyCFunction)DB_get_type, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006356 {"join", (PyCFunction)DB_join, METH_VARARGS},
6357 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
Jesus Cea4907d272008-08-31 14:00:51 +00006358 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006359 {"items", (PyCFunction)DB_items, METH_VARARGS},
6360 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6361 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6362 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6363 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6364 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6365 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006366 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006367 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006368#if (DBVER >= 41)
6369 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6370#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006371 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6372 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6373 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6374 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6375 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6376 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6377 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6378 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6379 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006380 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
6381 {"set_private", (PyCFunction)DB_set_private, METH_O},
6382 {"get_private", (PyCFunction)DB_get_private, METH_NOARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006383 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006384 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006385 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006386 {"type", (PyCFunction)DB_get_type, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006387 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6388 {"values", (PyCFunction)DB_values, METH_VARARGS},
6389 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6390 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6391 {NULL, NULL} /* sentinel */
6392};
6393
6394
6395static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00006396 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006397 (binaryfunc)DB_subscript, /*mp_subscript*/
6398 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6399};
6400
6401
6402static PyMethodDef DBCursor_methods[] = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006403 {"close", (PyCFunction)DBC_close, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006404 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6405 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6406 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6407 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6408 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6409 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith19699a92004-06-28 04:06:49 +00006410 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006411 {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006412 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6413 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6414 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6415 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6416 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6417 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6418 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006419 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00006420 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006421 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6422 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6423 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6424 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6425 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6426 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6427 {NULL, NULL} /* sentinel */
6428};
6429
6430
6431static PyMethodDef DBEnv_methods[] = {
6432 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6433 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6434 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006435#if (DBVER >= 41)
6436 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6437 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6438 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6439#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00006440 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00006441 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006442 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6443 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006444 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Jesus Ceaca3939c2008-05-22 15:27:38 +00006445#if (DBVER >= 47)
6446 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
6447#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006448 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6449 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6450 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006451#if (DBVER >= 42)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006452 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006453#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00006454 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006455 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006456#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006457 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006458#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006459 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6460 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6461 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006462 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6463 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6464 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6465 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6466 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6467 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00006468 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006469 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6470 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006471 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS},
Gregory P. Smithac11e022007-11-05 02:56:31 +00006472 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006473 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6474 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6475 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006476 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006477 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00006478#if (DBVER >= 44)
6479 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6480#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006481 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006482 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS},
Jesus Ceaca3939c2008-05-22 15:27:38 +00006483 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
6484 METH_VARARGS||METH_KEYWORDS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006485 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6486#if (DBVER >= 42)
6487 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6488#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006489 {"set_private", (PyCFunction)DBEnv_set_private, METH_O},
6490 {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS},
6491 {"rep_start", (PyCFunction)DBEnv_rep_start,
6492 METH_VARARGS|METH_KEYWORDS},
6493 {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
6494 {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
6495 METH_VARARGS},
6496#if (DBVER >= 46)
6497 {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS},
6498#endif
6499#if (DBVER >= 44)
6500 {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS},
6501 {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS},
6502 {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006503#endif
6504#if (DBVER >= 45)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006505 {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS},
6506 {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS},
6507#endif
6508#if (DBVER >= 47)
6509 {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS},
6510 {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS},
6511#endif
6512#if (DBVER >= 45)
6513 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006514#endif
6515#if (DBVER >= 45)
6516 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006517 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006518 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006519 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006520 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6521 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6522#endif
6523#if (DBVER >= 45)
6524 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6525 METH_VARARGS|METH_KEYWORDS},
6526 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6527 METH_VARARGS|METH_KEYWORDS},
6528 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6529 METH_VARARGS|METH_KEYWORDS},
6530 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6531 METH_VARARGS},
6532 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006533 METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006534 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006535 METH_NOARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006536#endif
6537#if (DBVER >= 46)
6538 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6539 METH_VARARGS|METH_KEYWORDS},
6540 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6541 METH_VARARGS|METH_KEYWORDS},
6542#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006543 {NULL, NULL} /* sentinel */
6544};
6545
6546
6547static PyMethodDef DBTxn_methods[] = {
6548 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6549 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006550 {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS},
6551 {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS},
6552 {"id", (PyCFunction)DBTxn_id, METH_NOARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006553 {NULL, NULL} /* sentinel */
6554};
6555
6556
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006557#if (DBVER >= 43)
6558static PyMethodDef DBSequence_methods[] = {
6559 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6560 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006561 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS},
6562 {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006563 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6564 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6565 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6566 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006567 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006568 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006569 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006570 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006571 {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006572 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6573 {NULL, NULL} /* sentinel */
6574};
6575#endif
6576
6577
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006578static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006579DBEnv_db_home_get(DBEnvObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006580{
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006581 const char *home = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006582
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006583 CHECK_ENV_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006584
Jesus Ceaef9764f2008-05-13 18:45:46 +00006585#if (DBVER >= 42)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006586 self->db_env->get_home(self->db_env, &home);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006587#else
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006588 home=self->db_env->db_home;
Jesus Ceaef9764f2008-05-13 18:45:46 +00006589#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006590
6591 if (home == NULL) {
6592 RETURN_NONE();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006593 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006594 return PyBytes_FromString(home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006595}
6596
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006597static PyGetSetDef DBEnv_getsets[] = {
6598 {"db_home", (getter)DBEnv_db_home_get, NULL,},
6599 {NULL}
6600};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006601
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006602
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006603statichere PyTypeObject DB_Type = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006604#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006605 PyObject_HEAD_INIT(NULL)
6606 0, /*ob_size*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006607#else
6608 PyVarObject_HEAD_INIT(NULL, 0)
6609#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006610 "DB", /*tp_name*/
6611 sizeof(DBObject), /*tp_basicsize*/
6612 0, /*tp_itemsize*/
6613 /* methods */
6614 (destructor)DB_dealloc, /*tp_dealloc*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006615 0, /*tp_print*/
6616 0, /*tp_getattr*/
6617 0, /*tp_setattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006618 0, /*tp_compare*/
6619 0, /*tp_repr*/
6620 0, /*tp_as_number*/
6621 0, /*tp_as_sequence*/
6622 &DB_mapping,/*tp_as_mapping*/
6623 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006624 0, /* tp_call */
6625 0, /* tp_str */
6626 0, /* tp_getattro */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006627 0, /* tp_setattro */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006628 0, /* tp_as_buffer */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006629#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith31c50652004-06-28 01:20:40 +00006630 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006631#else
6632 Py_TPFLAGS_DEFAULT, /* tp_flags */
6633#endif
6634 0, /* tp_doc */
6635 0, /* tp_traverse */
Gregory P. Smith31c50652004-06-28 01:20:40 +00006636 0, /* tp_clear */
6637 0, /* tp_richcompare */
6638 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006639 0, /*tp_iter*/
6640 0, /*tp_iternext*/
6641 DB_methods, /*tp_methods*/
6642 0, /*tp_members*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006643};
6644
6645
6646statichere PyTypeObject DBCursor_Type = {
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006647#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006648 PyObject_HEAD_INIT(NULL)
6649 0, /*ob_size*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006650#else
6651 PyVarObject_HEAD_INIT(NULL, 0)
6652#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006653 "DBCursor", /*tp_name*/
6654 sizeof(DBCursorObject), /*tp_basicsize*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006655 0, /*tp_itemsize*/
6656 /* methods */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006657 (destructor)DBCursor_dealloc,/*tp_dealloc*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006658 0, /*tp_print*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006659 0, /*tp_getattr*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006660 0, /*tp_setattr*/
6661 0, /*tp_compare*/
6662 0, /*tp_repr*/
6663 0, /*tp_as_number*/
6664 0, /*tp_as_sequence*/
6665 0, /*tp_as_mapping*/
6666 0, /*tp_hash*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006667 0, /*tp_call*/
6668 0, /*tp_str*/
6669 0, /*tp_getattro*/
6670 0, /*tp_setattro*/
6671 0, /*tp_as_buffer*/
6672#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith31c50652004-06-28 01:20:40 +00006673 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006674#else
6675 Py_TPFLAGS_DEFAULT, /* tp_flags */
6676#endif
6677 0, /* tp_doc */
6678 0, /* tp_traverse */
6679 0, /* tp_clear */
6680 0, /* tp_richcompare */
6681 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
6682 0, /*tp_iter*/
6683 0, /*tp_iternext*/
6684 DBCursor_methods, /*tp_methods*/
6685 0, /*tp_members*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006686};
6687
6688
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006689statichere PyTypeObject DBEnv_Type = {
6690#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006691 PyObject_HEAD_INIT(NULL)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006692 0, /*ob_size*/
6693#else
6694 PyVarObject_HEAD_INIT(NULL, 0)
6695#endif
6696 "DBEnv", /*tp_name*/
6697 sizeof(DBEnvObject), /*tp_basicsize*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006698 0, /*tp_itemsize*/
6699 /* methods */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006700 (destructor)DBEnv_dealloc, /*tp_dealloc*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006701 0, /*tp_print*/
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006702 0, /*tp_getattr*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006703 0, /*tp_setattr*/
6704 0, /*tp_compare*/
6705 0, /*tp_repr*/
6706 0, /*tp_as_number*/
6707 0, /*tp_as_sequence*/
6708 0, /*tp_as_mapping*/
6709 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006710 0, /* tp_call */
6711 0, /* tp_str */
6712 0, /* tp_getattro */
6713 0, /* tp_setattro */
6714 0, /* tp_as_buffer */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006715#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006716 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006717#else
6718 Py_TPFLAGS_DEFAULT, /* tp_flags */
6719#endif
6720 0, /* tp_doc */
6721 0, /* tp_traverse */
6722 0, /* tp_clear */
6723 0, /* tp_richcompare */
6724 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
6725 0, /* tp_iter */
6726 0, /* tp_iternext */
6727 DBEnv_methods, /* tp_methods */
6728 0, /* tp_members */
6729 DBEnv_getsets, /* tp_getsets */
6730};
6731
6732statichere PyTypeObject DBTxn_Type = {
6733#if (PY_VERSION_HEX < 0x03000000)
6734 PyObject_HEAD_INIT(NULL)
6735 0, /*ob_size*/
6736#else
6737 PyVarObject_HEAD_INIT(NULL, 0)
6738#endif
6739 "DBTxn", /*tp_name*/
6740 sizeof(DBTxnObject), /*tp_basicsize*/
6741 0, /*tp_itemsize*/
6742 /* methods */
6743 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6744 0, /*tp_print*/
6745 0, /*tp_getattr*/
6746 0, /*tp_setattr*/
6747 0, /*tp_compare*/
6748 0, /*tp_repr*/
6749 0, /*tp_as_number*/
6750 0, /*tp_as_sequence*/
6751 0, /*tp_as_mapping*/
6752 0, /*tp_hash*/
6753 0, /* tp_call */
6754 0, /* tp_str */
6755 0, /* tp_getattro */
6756 0, /* tp_setattro */
6757 0, /* tp_as_buffer */
6758#if (PY_VERSION_HEX < 0x03000000)
6759 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6760#else
6761 Py_TPFLAGS_DEFAULT, /* tp_flags */
6762#endif
6763 0, /* tp_doc */
6764 0, /* tp_traverse */
6765 0, /* tp_clear */
6766 0, /* tp_richcompare */
6767 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
6768 0, /*tp_iter*/
6769 0, /*tp_iternext*/
6770 DBTxn_methods, /*tp_methods*/
6771 0, /*tp_members*/
6772};
6773
6774
6775statichere PyTypeObject DBLock_Type = {
6776#if (PY_VERSION_HEX < 0x03000000)
6777 PyObject_HEAD_INIT(NULL)
6778 0, /*ob_size*/
6779#else
6780 PyVarObject_HEAD_INIT(NULL, 0)
6781#endif
6782 "DBLock", /*tp_name*/
6783 sizeof(DBLockObject), /*tp_basicsize*/
6784 0, /*tp_itemsize*/
6785 /* methods */
6786 (destructor)DBLock_dealloc, /*tp_dealloc*/
6787 0, /*tp_print*/
6788 0, /*tp_getattr*/
6789 0, /*tp_setattr*/
6790 0, /*tp_compare*/
6791 0, /*tp_repr*/
6792 0, /*tp_as_number*/
6793 0, /*tp_as_sequence*/
6794 0, /*tp_as_mapping*/
6795 0, /*tp_hash*/
6796 0, /* tp_call */
6797 0, /* tp_str */
6798 0, /* tp_getattro */
6799 0, /* tp_setattro */
6800 0, /* tp_as_buffer */
6801#if (PY_VERSION_HEX < 0x03000000)
6802 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6803#else
6804 Py_TPFLAGS_DEFAULT, /* tp_flags */
6805#endif
6806 0, /* tp_doc */
6807 0, /* tp_traverse */
6808 0, /* tp_clear */
6809 0, /* tp_richcompare */
6810 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
6811};
6812
6813#if (DBVER >= 43)
6814statichere PyTypeObject DBSequence_Type = {
6815#if (PY_VERSION_HEX < 0x03000000)
6816 PyObject_HEAD_INIT(NULL)
6817 0, /*ob_size*/
6818#else
6819 PyVarObject_HEAD_INIT(NULL, 0)
6820#endif
6821 "DBSequence", /*tp_name*/
6822 sizeof(DBSequenceObject), /*tp_basicsize*/
6823 0, /*tp_itemsize*/
6824 /* methods */
6825 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6826 0, /*tp_print*/
6827 0, /*tp_getattr*/
6828 0, /*tp_setattr*/
6829 0, /*tp_compare*/
6830 0, /*tp_repr*/
6831 0, /*tp_as_number*/
6832 0, /*tp_as_sequence*/
6833 0, /*tp_as_mapping*/
6834 0, /*tp_hash*/
6835 0, /* tp_call */
6836 0, /* tp_str */
6837 0, /* tp_getattro */
6838 0, /* tp_setattro */
6839 0, /* tp_as_buffer */
6840#if (PY_VERSION_HEX < 0x03000000)
6841 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6842#else
6843 Py_TPFLAGS_DEFAULT, /* tp_flags */
6844#endif
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006845 0, /* tp_doc */
6846 0, /* tp_traverse */
6847 0, /* tp_clear */
6848 0, /* tp_richcompare */
6849 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006850 0, /*tp_iter*/
6851 0, /*tp_iternext*/
6852 DBSequence_methods, /*tp_methods*/
6853 0, /*tp_members*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006854};
6855#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006856
6857/* --------------------------------------------------------------------- */
6858/* Module-level functions */
6859
6860static PyObject*
6861DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6862{
6863 PyObject* dbenvobj = NULL;
6864 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00006865 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006866
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006867 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6868 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006869 return NULL;
6870 if (dbenvobj == Py_None)
6871 dbenvobj = NULL;
6872 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6873 makeTypeError("DBEnv", dbenvobj);
6874 return NULL;
6875 }
6876
6877 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6878}
6879
6880
6881static PyObject*
6882DBEnv_construct(PyObject* self, PyObject* args)
6883{
6884 int flags = 0;
6885 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6886 return (PyObject* )newDBEnvObject(flags);
6887}
6888
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006889#if (DBVER >= 43)
6890static PyObject*
6891DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6892{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006893 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006894 int flags = 0;
6895 static char* kwnames[] = { "db", "flags", NULL};
6896
6897 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6898 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006899 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006900 makeTypeError("DB", dbobj);
6901 return NULL;
6902 }
6903 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6904}
6905#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006906
6907static char bsddb_version_doc[] =
6908"Returns a tuple of major, minor, and patch release numbers of the\n\
6909underlying DB library.";
6910
6911static PyObject*
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006912bsddb_version(PyObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006913{
6914 int major, minor, patch;
6915
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006916 db_version(&major, &minor, &patch);
6917 return Py_BuildValue("(iii)", major, minor, patch);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006918}
6919
6920
6921/* List of functions defined in the module */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006922static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006923 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6924 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006925#if (DBVER >= 43)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006926 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006927#endif
6928 {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006929 {NULL, NULL} /* sentinel */
6930};
6931
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006932
Gregory P. Smith39250532007-10-09 06:02:21 +00006933/* API structure */
6934static BSDDB_api bsddb_api;
6935
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006936
6937/* --------------------------------------------------------------------- */
6938/* Module initialization */
6939
6940
6941/* Convenience routine to export an integer value.
6942 * Errors are silently ignored, for better or for worse...
6943 */
6944#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
6945
Gregory P. Smith41631e82003-09-21 00:08:14 +00006946#define MODULE_NAME_MAX_LEN 11
6947static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006948
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006949#if (PY_VERSION_HEX >= 0x03000000)
6950static struct PyModuleDef bsddbmodule = {
6951 PyModuleDef_HEAD_INIT,
6952 _bsddbModuleName, /* Name of module */
6953 NULL, /* module documentation, may be NULL */
6954 -1, /* size of per-interpreter state of the module,
6955 or -1 if the module keeps state in global variables. */
6956 bsddb_methods,
6957 NULL, /* Reload */
6958 NULL, /* Traverse */
6959 NULL, /* Clear */
6960 NULL /* Free */
6961};
6962#endif
6963
6964
6965#if (PY_VERSION_HEX < 0x03000000)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006966DL_EXPORT(void) init_bsddb(void)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006967#else
6968PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */
6969#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006970{
6971 PyObject* m;
6972 PyObject* d;
Christian Heimes593daf52008-05-26 12:51:38 +00006973 PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
6974 PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
6975 PyObject* cvsid_s = PyBytes_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00006976 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006977
Jesus Ceac5a11fa2008-07-23 11:38:42 +00006978 /* Initialize object types */
6979 if ((PyType_Ready(&DB_Type) < 0)
6980 || (PyType_Ready(&DBCursor_Type) < 0)
6981 || (PyType_Ready(&DBEnv_Type) < 0)
6982 || (PyType_Ready(&DBTxn_Type) < 0)
6983 || (PyType_Ready(&DBLock_Type) < 0)
6984#if (DBVER >= 43)
6985 || (PyType_Ready(&DBSequence_Type) < 0)
6986#endif
6987 ) {
6988#if (PY_VERSION_HEX < 0x03000000)
6989 return;
6990#else
6991 return NULL;
6992#endif
6993 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006994
Mark Hammonda69d4092003-04-22 23:13:27 +00006995#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006996 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00006997 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006998#endif
6999
7000 /* Create the module and add the functions */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007001#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007002 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007003#else
7004 m=PyModule_Create(&bsddbmodule);
7005#endif
7006 if (m == NULL) {
7007#if (PY_VERSION_HEX < 0x03000000)
7008 return;
7009#else
7010 return NULL;
7011#endif
7012 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007013
7014 /* Add some symbolic constants to the module */
7015 d = PyModule_GetDict(m);
7016 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
7017 PyDict_SetItemString(d, "cvsid", cvsid_s);
7018 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
7019 Py_DECREF(pybsddb_version_s);
7020 pybsddb_version_s = NULL;
7021 Py_DECREF(cvsid_s);
7022 cvsid_s = NULL;
7023 Py_DECREF(db_version_s);
7024 db_version_s = NULL;
7025
7026 ADD_INT(d, DB_VERSION_MAJOR);
7027 ADD_INT(d, DB_VERSION_MINOR);
7028 ADD_INT(d, DB_VERSION_PATCH);
7029
7030 ADD_INT(d, DB_MAX_PAGES);
7031 ADD_INT(d, DB_MAX_RECORDS);
7032
Gregory P. Smith41631e82003-09-21 00:08:14 +00007033#if (DBVER >= 42)
7034 ADD_INT(d, DB_RPCCLIENT);
7035#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007036 ADD_INT(d, DB_CLIENT);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007037 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
Gregory P. Smith41631e82003-09-21 00:08:14 +00007038 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
7039#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007040 ADD_INT(d, DB_XA_CREATE);
7041
7042 ADD_INT(d, DB_CREATE);
7043 ADD_INT(d, DB_NOMMAP);
7044 ADD_INT(d, DB_THREAD);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007045#if (DBVER >= 45)
7046 ADD_INT(d, DB_MULTIVERSION);
7047#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007048
7049 ADD_INT(d, DB_FORCE);
7050 ADD_INT(d, DB_INIT_CDB);
7051 ADD_INT(d, DB_INIT_LOCK);
7052 ADD_INT(d, DB_INIT_LOG);
7053 ADD_INT(d, DB_INIT_MPOOL);
7054 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007055 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007056
Jesus Ceaef9764f2008-05-13 18:45:46 +00007057 ADD_INT(d, DB_XIDDATASIZE);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007058
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007059 ADD_INT(d, DB_RECOVER);
7060 ADD_INT(d, DB_RECOVER_FATAL);
7061 ADD_INT(d, DB_TXN_NOSYNC);
7062 ADD_INT(d, DB_USE_ENVIRON);
7063 ADD_INT(d, DB_USE_ENVIRON_ROOT);
7064
7065 ADD_INT(d, DB_LOCKDOWN);
7066 ADD_INT(d, DB_PRIVATE);
7067 ADD_INT(d, DB_SYSTEM_MEM);
7068
7069 ADD_INT(d, DB_TXN_SYNC);
7070 ADD_INT(d, DB_TXN_NOWAIT);
7071
7072 ADD_INT(d, DB_EXCL);
7073 ADD_INT(d, DB_FCNTL_LOCKING);
7074 ADD_INT(d, DB_ODDFILESIZE);
7075 ADD_INT(d, DB_RDWRMASTER);
7076 ADD_INT(d, DB_RDONLY);
7077 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007078 ADD_INT(d, DB_EXTENT);
7079 ADD_INT(d, DB_CDB_ALLDB);
7080 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007081 ADD_INT(d, DB_UPGRADE);
7082
7083 ADD_INT(d, DB_AGGRESSIVE);
7084 ADD_INT(d, DB_NOORDERCHK);
7085 ADD_INT(d, DB_ORDERCHKONLY);
7086 ADD_INT(d, DB_PR_PAGE);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007087
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007088 ADD_INT(d, DB_PR_RECOVERYTEST);
7089 ADD_INT(d, DB_SALVAGE);
7090
7091 ADD_INT(d, DB_LOCK_NORUN);
7092 ADD_INT(d, DB_LOCK_DEFAULT);
7093 ADD_INT(d, DB_LOCK_OLDEST);
7094 ADD_INT(d, DB_LOCK_RANDOM);
7095 ADD_INT(d, DB_LOCK_YOUNGEST);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007096 ADD_INT(d, DB_LOCK_MAXLOCKS);
7097 ADD_INT(d, DB_LOCK_MINLOCKS);
7098 ADD_INT(d, DB_LOCK_MINWRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007099
Jesus Ceaef9764f2008-05-13 18:45:46 +00007100 ADD_INT(d, DB_LOCK_EXPIRE);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007101#if (DBVER >= 43)
7102 ADD_INT(d, DB_LOCK_MAXWRITE);
7103#endif
7104
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007105 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007106
7107 ADD_INT(d, DB_LOCK_DUMP);
7108 ADD_INT(d, DB_LOCK_GET);
7109 ADD_INT(d, DB_LOCK_INHERIT);
7110 ADD_INT(d, DB_LOCK_PUT);
7111 ADD_INT(d, DB_LOCK_PUT_ALL);
7112 ADD_INT(d, DB_LOCK_PUT_OBJ);
7113
7114 ADD_INT(d, DB_LOCK_NG);
7115 ADD_INT(d, DB_LOCK_READ);
7116 ADD_INT(d, DB_LOCK_WRITE);
7117 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007118 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007119 ADD_INT(d, DB_LOCK_IWRITE);
7120 ADD_INT(d, DB_LOCK_IREAD);
7121 ADD_INT(d, DB_LOCK_IWR);
Gregory P. Smith29602d22006-01-24 09:46:48 +00007122#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007123 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00007124#else
7125 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
7126#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007127 ADD_INT(d, DB_LOCK_WWRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007128
7129 ADD_INT(d, DB_LOCK_RECORD);
7130 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007131 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007132 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007133
7134 ADD_INT(d, DB_LOCK_NOWAIT);
7135 ADD_INT(d, DB_LOCK_RECORD);
7136 ADD_INT(d, DB_LOCK_UPGRADE);
7137
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007138 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007139#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007140 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007141#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007142 ADD_INT(d, DB_LSTAT_FREE);
7143 ADD_INT(d, DB_LSTAT_HELD);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007144
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007145 ADD_INT(d, DB_LSTAT_PENDING);
7146 ADD_INT(d, DB_LSTAT_WAITING);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007147
7148 ADD_INT(d, DB_ARCH_ABS);
7149 ADD_INT(d, DB_ARCH_DATA);
7150 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00007151#if (DBVER >= 42)
7152 ADD_INT(d, DB_ARCH_REMOVE);
7153#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007154
7155 ADD_INT(d, DB_BTREE);
7156 ADD_INT(d, DB_HASH);
7157 ADD_INT(d, DB_RECNO);
7158 ADD_INT(d, DB_QUEUE);
7159 ADD_INT(d, DB_UNKNOWN);
7160
7161 ADD_INT(d, DB_DUP);
7162 ADD_INT(d, DB_DUPSORT);
7163 ADD_INT(d, DB_RECNUM);
7164 ADD_INT(d, DB_RENUMBER);
7165 ADD_INT(d, DB_REVSPLITOFF);
7166 ADD_INT(d, DB_SNAPSHOT);
7167
7168 ADD_INT(d, DB_JOIN_NOSORT);
7169
7170 ADD_INT(d, DB_AFTER);
7171 ADD_INT(d, DB_APPEND);
7172 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007173#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007174 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007175#endif
Jesus Ceaca3939c2008-05-22 15:27:38 +00007176
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007177#if (DBVER >= 41)
7178 _addIntToDict(d, "DB_CHECKPOINT", 0);
7179#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007180 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007181 ADD_INT(d, DB_CURLSN);
7182#endif
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007183#if (DBVER <= 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007184 ADD_INT(d, DB_COMMIT);
7185#endif
7186 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007187 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007188 ADD_INT(d, DB_CURRENT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007189 ADD_INT(d, DB_FAST_STAT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007190 ADD_INT(d, DB_FIRST);
7191 ADD_INT(d, DB_FLUSH);
7192 ADD_INT(d, DB_GET_BOTH);
7193 ADD_INT(d, DB_GET_RECNO);
7194 ADD_INT(d, DB_JOIN_ITEM);
7195 ADD_INT(d, DB_KEYFIRST);
7196 ADD_INT(d, DB_KEYLAST);
7197 ADD_INT(d, DB_LAST);
7198 ADD_INT(d, DB_NEXT);
7199 ADD_INT(d, DB_NEXT_DUP);
7200 ADD_INT(d, DB_NEXT_NODUP);
7201 ADD_INT(d, DB_NODUPDATA);
7202 ADD_INT(d, DB_NOOVERWRITE);
7203 ADD_INT(d, DB_NOSYNC);
7204 ADD_INT(d, DB_POSITION);
7205 ADD_INT(d, DB_PREV);
7206 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007207#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007208 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00007209#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007210 ADD_INT(d, DB_SET);
7211 ADD_INT(d, DB_SET_RANGE);
7212 ADD_INT(d, DB_SET_RECNO);
7213 ADD_INT(d, DB_WRITECURSOR);
7214
7215 ADD_INT(d, DB_OPFLAGS_MASK);
7216 ADD_INT(d, DB_RMW);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007217 ADD_INT(d, DB_DIRTY_READ);
7218 ADD_INT(d, DB_MULTIPLE);
7219 ADD_INT(d, DB_MULTIPLE_KEY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007220
Gregory P. Smith29602d22006-01-24 09:46:48 +00007221#if (DBVER >= 44)
7222 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
7223 ADD_INT(d, DB_READ_COMMITTED);
7224#endif
7225
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007226 ADD_INT(d, DB_DONOTINDEX);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007227
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007228#if (DBVER >= 41)
7229 _addIntToDict(d, "DB_INCOMPLETE", 0);
7230#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007231 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007232#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007233 ADD_INT(d, DB_KEYEMPTY);
7234 ADD_INT(d, DB_KEYEXIST);
7235 ADD_INT(d, DB_LOCK_DEADLOCK);
7236 ADD_INT(d, DB_LOCK_NOTGRANTED);
7237 ADD_INT(d, DB_NOSERVER);
7238 ADD_INT(d, DB_NOSERVER_HOME);
7239 ADD_INT(d, DB_NOSERVER_ID);
7240 ADD_INT(d, DB_NOTFOUND);
7241 ADD_INT(d, DB_OLD_VERSION);
7242 ADD_INT(d, DB_RUNRECOVERY);
7243 ADD_INT(d, DB_VERIFY_BAD);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007244 ADD_INT(d, DB_PAGE_NOTFOUND);
7245 ADD_INT(d, DB_SECONDARY_BAD);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007246 ADD_INT(d, DB_STAT_CLEAR);
7247 ADD_INT(d, DB_REGION_INIT);
7248 ADD_INT(d, DB_NOLOCKING);
7249 ADD_INT(d, DB_YIELDCPU);
7250 ADD_INT(d, DB_PANIC_ENVIRONMENT);
7251 ADD_INT(d, DB_NOPANIC);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007252
Jesus Ceaef9764f2008-05-13 18:45:46 +00007253#if (DBVER >= 41)
7254 ADD_INT(d, DB_OVERWRITE);
7255#endif
7256
Gregory P. Smithaae141a2007-11-01 21:08:14 +00007257#ifdef DB_REGISTER
7258 ADD_INT(d, DB_REGISTER);
7259#endif
7260
Gregory P. Smith41631e82003-09-21 00:08:14 +00007261#if (DBVER >= 42)
7262 ADD_INT(d, DB_TIME_NOTGRANTED);
7263 ADD_INT(d, DB_TXN_NOT_DURABLE);
7264 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
Gregory P. Smith41631e82003-09-21 00:08:14 +00007265 ADD_INT(d, DB_DIRECT_DB);
7266 ADD_INT(d, DB_INIT_REP);
7267 ADD_INT(d, DB_ENCRYPT);
7268 ADD_INT(d, DB_CHKSUM);
7269#endif
7270
Jesus Ceaca3939c2008-05-22 15:27:38 +00007271#if (DBVER >= 42) && (DBVER < 47)
7272 ADD_INT(d, DB_LOG_AUTOREMOVE);
7273 ADD_INT(d, DB_DIRECT_LOG);
7274#endif
7275
7276#if (DBVER >= 47)
7277 ADD_INT(d, DB_LOG_DIRECT);
7278 ADD_INT(d, DB_LOG_DSYNC);
7279 ADD_INT(d, DB_LOG_IN_MEMORY);
7280 ADD_INT(d, DB_LOG_AUTO_REMOVE);
7281 ADD_INT(d, DB_LOG_ZERO);
7282#endif
7283
Jesus Ceaef9764f2008-05-13 18:45:46 +00007284#if (DBVER >= 44)
7285 ADD_INT(d, DB_DSYNC_DB);
7286#endif
7287
7288#if (DBVER >= 45)
7289 ADD_INT(d, DB_TXN_SNAPSHOT);
7290#endif
7291
Jesus Ceaef9764f2008-05-13 18:45:46 +00007292 ADD_INT(d, DB_VERB_DEADLOCK);
7293#if (DBVER >= 46)
7294 ADD_INT(d, DB_VERB_FILEOPS);
7295 ADD_INT(d, DB_VERB_FILEOPS_ALL);
7296#endif
7297 ADD_INT(d, DB_VERB_RECOVERY);
7298#if (DBVER >= 44)
7299 ADD_INT(d, DB_VERB_REGISTER);
7300#endif
7301 ADD_INT(d, DB_VERB_REPLICATION);
7302 ADD_INT(d, DB_VERB_WAITSFOR);
Jesus Ceaef9764f2008-05-13 18:45:46 +00007303
7304#if (DBVER >= 45)
7305 ADD_INT(d, DB_EVENT_PANIC);
7306 ADD_INT(d, DB_EVENT_REP_CLIENT);
7307#if (DBVER >= 46)
7308 ADD_INT(d, DB_EVENT_REP_ELECTED);
7309#endif
7310 ADD_INT(d, DB_EVENT_REP_MASTER);
7311 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
7312#if (DBVER >= 46)
7313 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
7314#endif
7315 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
7316 ADD_INT(d, DB_EVENT_WRITE_FAILED);
7317#endif
7318
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007319 ADD_INT(d, DB_REP_DUPMASTER);
7320 ADD_INT(d, DB_REP_HOLDELECTION);
7321#if (DBVER >= 44)
7322 ADD_INT(d, DB_REP_IGNORE);
7323 ADD_INT(d, DB_REP_JOIN_FAILURE);
7324#endif
7325#if (DBVER >= 42)
7326 ADD_INT(d, DB_REP_ISPERM);
7327 ADD_INT(d, DB_REP_NOTPERM);
7328#endif
7329 ADD_INT(d, DB_REP_NEWSITE);
7330
Jesus Ceaef9764f2008-05-13 18:45:46 +00007331 ADD_INT(d, DB_REP_MASTER);
7332 ADD_INT(d, DB_REP_CLIENT);
7333#if (DBVER >= 45)
7334 ADD_INT(d, DB_REP_ELECTION);
7335
7336 ADD_INT(d, DB_REP_ACK_TIMEOUT);
7337 ADD_INT(d, DB_REP_CONNECTION_RETRY);
7338 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
7339 ADD_INT(d, DB_REP_ELECTION_RETRY);
7340#endif
7341#if (DBVER >= 46)
7342 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
7343 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
7344#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00007345
7346#if (DBVER >= 45)
7347 ADD_INT(d, DB_REPMGR_PEER);
7348 ADD_INT(d, DB_REPMGR_ACKS_ALL);
7349 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
7350 ADD_INT(d, DB_REPMGR_ACKS_NONE);
7351 ADD_INT(d, DB_REPMGR_ACKS_ONE);
7352 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
7353 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
7354 ADD_INT(d, DB_REPMGR_CONNECTED);
7355 ADD_INT(d, DB_REPMGR_DISCONNECTED);
7356 ADD_INT(d, DB_STAT_CLEAR);
7357 ADD_INT(d, DB_STAT_ALL);
7358#endif
7359
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007360#if (DBVER >= 43)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007361 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00007362 ADD_INT(d, DB_SEQ_DEC);
7363 ADD_INT(d, DB_SEQ_INC);
7364 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007365#endif
7366
Jesus Ceaca3939c2008-05-22 15:27:38 +00007367#if (DBVER >= 43) && (DBVER < 47)
7368 ADD_INT(d, DB_LOG_INMEMORY);
7369 ADD_INT(d, DB_DSYNC_LOG);
7370#endif
7371
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007372#if (DBVER >= 41)
7373 ADD_INT(d, DB_ENCRYPT_AES);
7374 ADD_INT(d, DB_AUTO_COMMIT);
7375#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00007376 /* allow Berkeley DB 4.1 aware apps to run on older versions */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007377 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
7378#endif
7379
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007380 ADD_INT(d, EINVAL);
7381 ADD_INT(d, EACCES);
7382 ADD_INT(d, ENOSPC);
7383 ADD_INT(d, ENOMEM);
7384 ADD_INT(d, EAGAIN);
7385 ADD_INT(d, EBUSY);
7386 ADD_INT(d, EEXIST);
7387 ADD_INT(d, ENOENT);
7388 ADD_INT(d, EPERM);
7389
Barry Warsaw1baa9822003-03-31 19:51:29 +00007390 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
7391 ADD_INT(d, DB_SET_TXN_TIMEOUT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007392
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007393 /* The exception name must be correct for pickled exception *
7394 * objects to unpickle properly. */
7395#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
7396#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
7397#else
7398#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
7399#endif
7400
7401 /* All the rest of the exceptions derive only from DBError */
7402#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
7403 PyDict_SetItemString(d, #name, name)
7404
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007405 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007406 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
7407 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007408
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007409#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smithe9477062005-06-04 06:46:59 +00007410 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
7411 * from both DBError and KeyError, since the API only supports
7412 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007413 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00007414 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
7415 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007416 Py_file_input, d, d);
7417 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00007418 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007419 PyDict_DelItemString(d, "KeyError");
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007420#else
7421 /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
7422 ** derive from several classes. We use this new API only for Python 3.0,
7423 ** though.
7424 */
7425 {
7426 PyObject* bases;
7427
7428 bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
7429
7430#define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
7431 PyDict_SetItemString(d, #name, name)
7432 MAKE_EX2(DBNotFoundError);
7433 MAKE_EX2(DBKeyEmptyError);
7434
7435#undef MAKE_EX2
7436
7437 Py_XDECREF(bases);
7438 }
7439#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007440
7441
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007442#if !INCOMPLETE_IS_WARNING
7443 MAKE_EX(DBIncompleteError);
7444#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00007445 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007446 MAKE_EX(DBKeyEmptyError);
7447 MAKE_EX(DBKeyExistError);
7448 MAKE_EX(DBLockDeadlockError);
7449 MAKE_EX(DBLockNotGrantedError);
7450 MAKE_EX(DBOldVersionError);
7451 MAKE_EX(DBRunRecoveryError);
7452 MAKE_EX(DBVerifyBadError);
7453 MAKE_EX(DBNoServerError);
7454 MAKE_EX(DBNoServerHomeError);
7455 MAKE_EX(DBNoServerIDError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007456 MAKE_EX(DBPageNotFoundError);
7457 MAKE_EX(DBSecondaryBadError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007458
7459 MAKE_EX(DBInvalidArgError);
7460 MAKE_EX(DBAccessError);
7461 MAKE_EX(DBNoSpaceError);
7462 MAKE_EX(DBNoMemoryError);
7463 MAKE_EX(DBAgainError);
7464 MAKE_EX(DBBusyError);
7465 MAKE_EX(DBFileExistsError);
7466 MAKE_EX(DBNoSuchFileError);
7467 MAKE_EX(DBPermissionsError);
7468
Jesus Ceaef9764f2008-05-13 18:45:46 +00007469#if (DBVER >= 42)
7470 MAKE_EX(DBRepHandleDeadError);
7471#endif
7472
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007473 MAKE_EX(DBRepUnavailError);
7474
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007475#undef MAKE_EX
7476
Gregory P. Smith39250532007-10-09 06:02:21 +00007477 /* Initiliase the C API structure and add it to the module */
7478 bsddb_api.db_type = &DB_Type;
7479 bsddb_api.dbcursor_type = &DBCursor_Type;
7480 bsddb_api.dbenv_type = &DBEnv_Type;
7481 bsddb_api.dbtxn_type = &DBTxn_Type;
7482 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007483#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00007484 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007485#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00007486 bsddb_api.makeDBError = makeDBError;
7487
7488 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7489 PyDict_SetItemString(d, "api", py_api);
7490 Py_DECREF(py_api);
7491
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007492 /* Check for errors */
7493 if (PyErr_Occurred()) {
7494 PyErr_Print();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007495 Py_FatalError("can't initialize module _bsddb/_pybsddb");
7496 Py_DECREF(m);
7497 m = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007498 }
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007499#if (PY_VERSION_HEX < 0x03000000)
7500 return;
7501#else
7502 return m;
7503#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007504}
Gregory P. Smith41631e82003-09-21 00:08:14 +00007505
7506/* allow this module to be named _pybsddb so that it can be installed
7507 * and imported on top of python >= 2.3 that includes its own older
7508 * copy of the library named _bsddb without importing the old version. */
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007509#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007510DL_EXPORT(void) init_pybsddb(void)
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007511#else
7512PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */
7513#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00007514{
7515 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007516#if (PY_VERSION_HEX < 0x03000000)
Gregory P. Smith41631e82003-09-21 00:08:14 +00007517 init_bsddb();
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007518#else
7519 return PyInit__bsddb(); /* Note the two underscores */
7520#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00007521}
Jesus Ceac5a11fa2008-07-23 11:38:42 +00007522