blob: 6cf733f69f3a9438b05776ee3e1603e468c30c96 [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
Gregory P. Smith41631e82003-09-21 00:08:14 +000039 * to compile with BerkeleyDB 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
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
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 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
64 * This module contains 5 types:
65 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
71 *
72 */
73
74/* --------------------------------------------------------------------- */
75
76/*
77 * Portions of this module, associated unit tests and build scripts are the
78 * result of a contract with The Written Word (http://thewrittenword.com/)
79 * Many thanks go out to them for causing me to raise the bar on quality and
80 * functionality, resulting in a better bsddb3 package for all of us to use.
81 *
82 * --Robin
83 */
84
85/* --------------------------------------------------------------------- */
86
87#include <Python.h>
88#include <db.h>
89
90/* --------------------------------------------------------------------- */
91/* Various macro definitions */
92
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000093/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
94#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
95
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +000096#define PY_BSDDB_VERSION "4.2.2"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000097static char *rcs_id = "$Id$";
98
99
100#ifdef WITH_THREAD
101
102/* These are for when calling Python --> C */
103#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
104#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
105
Mark Hammonda69d4092003-04-22 23:13:27 +0000106/* For 2.3, use the PyGILState_ calls */
107#if (PY_VERSION_HEX >= 0x02030000)
108#define MYDB_USE_GILSTATE
109#endif
110
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000111/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000112#if defined(MYDB_USE_GILSTATE)
113#define MYDB_BEGIN_BLOCK_THREADS \
114 PyGILState_STATE __savestate = PyGILState_Ensure();
115#define MYDB_END_BLOCK_THREADS \
116 PyGILState_Release(__savestate);
117#else /* MYDB_USE_GILSTATE */
118/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000119static PyInterpreterState* _db_interpreterState = NULL;
120#define MYDB_BEGIN_BLOCK_THREADS { \
121 PyThreadState* prevState; \
122 PyThreadState* newState; \
123 PyEval_AcquireLock(); \
124 newState = PyThreadState_New(_db_interpreterState); \
125 prevState = PyThreadState_Swap(newState);
126
127#define MYDB_END_BLOCK_THREADS \
128 newState = PyThreadState_Swap(prevState); \
129 PyThreadState_Clear(newState); \
130 PyEval_ReleaseLock(); \
131 PyThreadState_Delete(newState); \
132 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000133#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000134
135#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000136/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000137#define MYDB_BEGIN_ALLOW_THREADS
138#define MYDB_END_ALLOW_THREADS
139#define MYDB_BEGIN_BLOCK_THREADS
140#define MYDB_END_BLOCK_THREADS
141
142#endif
143
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000144/* Should DB_INCOMPLETE be turned into a warning or an exception? */
145#define INCOMPLETE_IS_WARNING 1
146
147/* --------------------------------------------------------------------- */
148/* Exceptions */
149
150static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000151static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000152static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY */
153static PyObject* DBKeyExistError; /* DB_KEYEXIST */
154static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
155static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
156static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
157static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
158static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
159static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
160static PyObject* DBNoServerError; /* DB_NOSERVER */
161static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
162static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
163#if (DBVER >= 33)
164static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
165static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
166#endif
167
168#if !INCOMPLETE_IS_WARNING
169static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
170#endif
171
172static PyObject* DBInvalidArgError; /* EINVAL */
173static PyObject* DBAccessError; /* EACCES */
174static PyObject* DBNoSpaceError; /* ENOSPC */
175static PyObject* DBNoMemoryError; /* ENOMEM */
176static PyObject* DBAgainError; /* EAGAIN */
177static PyObject* DBBusyError; /* EBUSY */
178static PyObject* DBFileExistsError; /* EEXIST */
179static PyObject* DBNoSuchFileError; /* ENOENT */
180static PyObject* DBPermissionsError; /* EPERM */
181
182
183
184/* --------------------------------------------------------------------- */
185/* Structure definitions */
186
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000187struct behaviourFlags {
188 /* What is the default behaviour when DB->get or DBCursor->get returns a
189 DB_NOTFOUND error? Return None or raise an exception? */
190 unsigned int getReturnsNone : 1;
191 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
192 * returns a DB_NOTFOUND error? Return None or raise an exception? */
193 unsigned int cursorSetReturnsNone : 1;
194};
195
196#define DEFAULT_GET_RETURNS_NONE 1
197#define DEFAULT_CURSOR_SET_RETURNS_NONE 0 /* 0 in pybsddb < 4.2, python < 2.4 */
198
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000199typedef struct {
200 PyObject_HEAD
201 DB_ENV* db_env;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000202 u_int32_t flags; /* saved flags from open() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000203 int closed;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000204 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000205} DBEnvObject;
206
207
208typedef struct {
209 PyObject_HEAD
210 DB* db;
211 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000212 u_int32_t flags; /* saved flags from open() */
213 u_int32_t setflags; /* saved flags from set_flags() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000214 int haveStat;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000215 struct behaviourFlags moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000216#if (DBVER >= 33)
217 PyObject* associateCallback;
218 int primaryDBType;
219#endif
220} DBObject;
221
222
223typedef struct {
224 PyObject_HEAD
225 DBC* dbc;
226 DBObject* mydb;
227} DBCursorObject;
228
229
230typedef struct {
231 PyObject_HEAD
232 DB_TXN* txn;
233} DBTxnObject;
234
235
236typedef struct {
237 PyObject_HEAD
238 DB_LOCK lock;
239} DBLockObject;
240
241
242
243staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
244
245#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
246#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
247#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
248#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
249#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
250
251
252/* --------------------------------------------------------------------- */
253/* Utility macros and functions */
254
255#define RETURN_IF_ERR() \
256 if (makeDBError(err)) { \
257 return NULL; \
258 }
259
260#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
261
Gregory P. Smithe2767172003-11-02 08:06:29 +0000262#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
263 if ((nonNull) == NULL) { \
264 PyObject *errTuple = NULL; \
265 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
266 PyErr_SetObject((pyErrObj), errTuple); \
267 Py_DECREF(errTuple); \
268 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000269 }
270
Gregory P. Smithe2767172003-11-02 08:06:29 +0000271#define CHECK_DB_NOT_CLOSED(dbobj) \
272 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
273
274#define CHECK_ENV_NOT_CLOSED(env) \
275 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000276
277#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000278 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000279
280
281#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
282 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
283
284#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
285
286#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
287 dbt.data != NULL) { free(dbt.data); }
288
289
290static int makeDBError(int err);
291
292
293/* Return the access method type of the DBObject */
294static int _DB_get_type(DBObject* self)
295{
296#if (DBVER >= 33)
297 DBTYPE type;
298 int err;
299 err = self->db->get_type(self->db, &type);
300 if (makeDBError(err)) {
301 return -1;
302 }
303 return type;
304#else
305 return self->db->get_type(self->db);
306#endif
307}
308
309
310/* Create a DBT structure (containing key and data values) from Python
311 strings. Returns 1 on success, 0 on an error. */
312static int make_dbt(PyObject* obj, DBT* dbt)
313{
314 CLEAR_DBT(*dbt);
315 if (obj == Py_None) {
316 /* no need to do anything, the structure has already been zeroed */
317 }
318 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
319 PyErr_SetString(PyExc_TypeError,
320 "Key and Data values must be of type string or None.");
321 return 0;
322 }
323 return 1;
324}
325
326
327/* Recno and Queue DBs can have integer keys. This function figures out
328 what's been given, verifies that it's allowed, and then makes the DBT.
329
330 Caller should call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000331static int
332make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000333{
334 db_recno_t recno;
335 int type;
336
337 CLEAR_DBT(*key);
338 if (keyobj == Py_None) { /* TODO: is None really okay for keys? */
339 /* no need to do anything, the structure has already been zeroed */
340 }
341
342 else if (PyString_Check(keyobj)) {
343 /* verify access method type */
344 type = _DB_get_type(self);
345 if (type == -1)
346 return 0;
347 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000348 PyErr_SetString(
349 PyExc_TypeError,
350 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000351 return 0;
352 }
353
354 key->data = PyString_AS_STRING(keyobj);
355 key->size = PyString_GET_SIZE(keyobj);
356 }
357
358 else if (PyInt_Check(keyobj)) {
359 /* verify access method type */
360 type = _DB_get_type(self);
361 if (type == -1)
362 return 0;
363 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000364 /* if BTREE then an Integer key is allowed with the
365 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000366 *pflags |= DB_SET_RECNO;
367 }
368 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000369 PyErr_SetString(
370 PyExc_TypeError,
371 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000372 return 0;
373 }
374
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000375 /* Make a key out of the requested recno, use allocated space so DB
376 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000377 recno = PyInt_AS_LONG(keyobj);
378 key->data = malloc(sizeof(db_recno_t));
379 if (key->data == NULL) {
380 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
381 return 0;
382 }
383 key->ulen = key->size = sizeof(db_recno_t);
384 memcpy(key->data, &recno, sizeof(db_recno_t));
385 key->flags = DB_DBT_REALLOC;
386 }
387 else {
388 PyErr_Format(PyExc_TypeError,
389 "String or Integer object expected for key, %s found",
390 keyobj->ob_type->tp_name);
391 return 0;
392 }
393
394 return 1;
395}
396
397
398/* Add partial record access to an existing DBT data struct.
399 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
400 and the data storage/retrieval will be done using dlen and doff. */
401static int add_partial_dbt(DBT* d, int dlen, int doff) {
402 /* if neither were set we do nothing (-1 is the default value) */
403 if ((dlen == -1) && (doff == -1)) {
404 return 1;
405 }
406
407 if ((dlen < 0) || (doff < 0)) {
408 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
409 return 0;
410 }
411
412 d->flags = d->flags | DB_DBT_PARTIAL;
413 d->dlen = (unsigned int) dlen;
414 d->doff = (unsigned int) doff;
415 return 1;
416}
417
418
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000419/* Callback used to save away more information about errors from the DB
420 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000421static char _db_errmsg[1024];
422static void _db_errorCallback(const char* prefix, char* msg)
423{
424 strcpy(_db_errmsg, msg);
425}
426
427
428/* make a nice exception object to raise for errors. */
429static int makeDBError(int err)
430{
431 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000432 PyObject *errObj = NULL;
433 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000434 int exceptionRaised = 0;
435
436 switch (err) {
437 case 0: /* successful, no error */ break;
438
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000439#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000440 case DB_INCOMPLETE:
441#if INCOMPLETE_IS_WARNING
442 strcpy(errTxt, db_strerror(err));
443 if (_db_errmsg[0]) {
444 strcat(errTxt, " -- ");
445 strcat(errTxt, _db_errmsg);
446 _db_errmsg[0] = 0;
447 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000448/* if Python 2.1 or better use warning framework */
449#if PYTHON_API_VERSION >= 1010
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000450 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
451#else
452 fprintf(stderr, errTxt);
453 fprintf(stderr, "\n");
454#endif
455
456#else /* do an exception instead */
457 errObj = DBIncompleteError;
458#endif
459 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000460#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000461
462 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
463 case DB_KEYEXIST: errObj = DBKeyExistError; break;
464 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
465 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
466 case DB_NOTFOUND: errObj = DBNotFoundError; break;
467 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
468 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
469 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
470 case DB_NOSERVER: errObj = DBNoServerError; break;
471 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
472 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
473#if (DBVER >= 33)
474 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
475 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
476#endif
477
478 case EINVAL: errObj = DBInvalidArgError; break;
479 case EACCES: errObj = DBAccessError; break;
480 case ENOSPC: errObj = DBNoSpaceError; break;
481 case ENOMEM: errObj = DBNoMemoryError; break;
482 case EAGAIN: errObj = DBAgainError; break;
483 case EBUSY : errObj = DBBusyError; break;
484 case EEXIST: errObj = DBFileExistsError; break;
485 case ENOENT: errObj = DBNoSuchFileError; break;
486 case EPERM : errObj = DBPermissionsError; break;
487
488 default: errObj = DBError; break;
489 }
490
491 if (errObj != NULL) {
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +0000492 /* FIXME this needs proper bounds checking on errTxt */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000493 strcpy(errTxt, db_strerror(err));
494 if (_db_errmsg[0]) {
495 strcat(errTxt, " -- ");
496 strcat(errTxt, _db_errmsg);
497 _db_errmsg[0] = 0;
498 }
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000499
500 errTuple = Py_BuildValue("(is)", err, errTxt);
501 PyErr_SetObject(errObj, errTuple);
502 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000503 }
504
505 return ((errObj != NULL) || exceptionRaised);
506}
507
508
509
510/* set a type exception */
511static void makeTypeError(char* expected, PyObject* found)
512{
513 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
514 expected, found->ob_type->tp_name);
515}
516
517
518/* verify that an obj is either None or a DBTxn, and set the txn pointer */
519static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
520{
521 if (txnobj == Py_None || txnobj == NULL) {
522 *txn = NULL;
523 return 1;
524 }
525 if (DBTxnObject_Check(txnobj)) {
526 *txn = ((DBTxnObject*)txnobj)->txn;
527 return 1;
528 }
529 else
530 makeTypeError("DBTxn", txnobj);
531 return 0;
532}
533
534
535/* Delete a key from a database
536 Returns 0 on success, -1 on an error. */
537static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
538{
539 int err;
540
541 MYDB_BEGIN_ALLOW_THREADS;
542 err = self->db->del(self->db, txn, key, 0);
543 MYDB_END_ALLOW_THREADS;
544 if (makeDBError(err)) {
545 return -1;
546 }
547 self->haveStat = 0;
548 return 0;
549}
550
551
552/* Store a key into a database
553 Returns 0 on success, -1 on an error. */
554static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
555{
556 int err;
557
558 MYDB_BEGIN_ALLOW_THREADS;
559 err = self->db->put(self->db, txn, key, data, flags);
560 MYDB_END_ALLOW_THREADS;
561 if (makeDBError(err)) {
562 return -1;
563 }
564 self->haveStat = 0;
565 return 0;
566}
567
568/* Get a key/data pair from a cursor */
569static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
570 PyObject *args, PyObject *kwargs, char *format)
571{
572 int err;
573 PyObject* retval = NULL;
574 DBT key, data;
575 int dlen = -1;
576 int doff = -1;
577 int flags = 0;
578 char* kwnames[] = { "flags", "dlen", "doff", NULL };
579
580 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
581 &flags, &dlen, &doff))
582 return NULL;
583
584 CHECK_CURSOR_NOT_CLOSED(self);
585
586 flags |= extra_flags;
587 CLEAR_DBT(key);
588 CLEAR_DBT(data);
589 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
590 /* Tell BerkeleyDB to malloc the return value (thread safe) */
591 data.flags = DB_DBT_MALLOC;
592 key.flags = DB_DBT_MALLOC;
593 }
594 if (!add_partial_dbt(&data, dlen, doff))
595 return NULL;
596
597 MYDB_BEGIN_ALLOW_THREADS;
598 err = self->dbc->c_get(self->dbc, &key, &data, flags);
599 MYDB_END_ALLOW_THREADS;
600
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000601 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000602 Py_INCREF(Py_None);
603 retval = Py_None;
604 }
605 else if (makeDBError(err)) {
606 retval = NULL;
607 }
608 else { /* otherwise, success! */
609
610 /* if Recno or Queue, return the key as an Int */
611 switch (_DB_get_type(self->mydb)) {
612 case -1:
613 retval = NULL;
614 break;
615
616 case DB_RECNO:
617 case DB_QUEUE:
618 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
619 data.data, data.size);
620 break;
621 case DB_HASH:
622 case DB_BTREE:
623 default:
624 retval = Py_BuildValue("s#s#", key.data, key.size,
625 data.data, data.size);
626 break;
627 }
628 }
629 if (!err) {
630 FREE_DBT(key);
631 FREE_DBT(data);
632 }
633 return retval;
634}
635
636
637/* add an integer to a dictionary using the given name as a key */
638static void _addIntToDict(PyObject* dict, char *name, int value)
639{
640 PyObject* v = PyInt_FromLong((long) value);
641 if (!v || PyDict_SetItemString(dict, name, v))
642 PyErr_Clear();
643
644 Py_XDECREF(v);
645}
646
647
648
649
650/* --------------------------------------------------------------------- */
651/* Allocators and deallocators */
652
653static DBObject*
654newDBObject(DBEnvObject* arg, int flags)
655{
656 DBObject* self;
657 DB_ENV* db_env = NULL;
658 int err;
659
660#if PYTHON_API_VERSION <= 1007
661 /* 1.5 compatibility */
662 self = PyObject_NEW(DBObject, &DB_Type);
663#else
664 self = PyObject_New(DBObject, &DB_Type);
665#endif
666
667 if (self == NULL)
668 return NULL;
669
670 self->haveStat = 0;
671 self->flags = 0;
672 self->setflags = 0;
673 self->myenvobj = NULL;
674#if (DBVER >= 33)
675 self->associateCallback = NULL;
676 self->primaryDBType = 0;
677#endif
678
679 /* keep a reference to our python DBEnv object */
680 if (arg) {
681 Py_INCREF(arg);
682 self->myenvobj = arg;
683 db_env = arg->db_env;
684 }
685
686 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000687 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000688 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000689 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
690 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000691
692 MYDB_BEGIN_ALLOW_THREADS;
693 err = db_create(&self->db, db_env, flags);
694 self->db->set_errcall(self->db, _db_errorCallback);
695#if (DBVER >= 33)
696 self->db->app_private = (void*)self;
697#endif
698 MYDB_END_ALLOW_THREADS;
699 if (makeDBError(err)) {
700 if (self->myenvobj) {
701 Py_DECREF(self->myenvobj);
702 self->myenvobj = NULL;
703 }
704 self = NULL;
705 }
706 return self;
707}
708
709
710static void
711DB_dealloc(DBObject* self)
712{
713 if (self->db != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000714 /* avoid closing a DB when its DBEnv has been closed out from under
715 * it */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000716 if (!self->myenvobj ||
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000717 (self->myenvobj && self->myenvobj->db_env))
718 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000719 MYDB_BEGIN_ALLOW_THREADS;
720 self->db->close(self->db, 0);
721 MYDB_END_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000722 /* if Python 2.1 or better use warning framework */
723#if PYTHON_API_VERSION >= 1010
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000724 } else {
725 PyErr_Warn(PyExc_RuntimeWarning,
726 "DB could not be closed in destructor: DBEnv already closed");
727#endif
728 }
729 self->db = NULL;
730 }
731 if (self->myenvobj) {
732 Py_DECREF(self->myenvobj);
733 self->myenvobj = NULL;
734 }
735#if (DBVER >= 33)
736 if (self->associateCallback != NULL) {
737 Py_DECREF(self->associateCallback);
738 self->associateCallback = NULL;
739 }
740#endif
741#if PYTHON_API_VERSION <= 1007
742 PyMem_DEL(self);
743#else
744 PyObject_Del(self);
745#endif
746}
747
748
749static DBCursorObject*
750newDBCursorObject(DBC* dbc, DBObject* db)
751{
752 DBCursorObject* self;
753#if PYTHON_API_VERSION <= 1007
754 self = PyObject_NEW(DBCursorObject, &DBCursor_Type);
755#else
756 self = PyObject_New(DBCursorObject, &DBCursor_Type);
757#endif
758 if (self == NULL)
759 return NULL;
760
761 self->dbc = dbc;
762 self->mydb = db;
763 Py_INCREF(self->mydb);
764 return self;
765}
766
767
768static void
769DBCursor_dealloc(DBCursorObject* self)
770{
771 int err;
772 if (self->dbc != NULL) {
773 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis35c38ea2003-07-15 19:12:54 +0000774 /* If the underlying database has been closed, we don't
775 need to do anything. If the environment has been closed
776 we need to leak, as BerkeleyDB will crash trying to access
777 the environment. There was an exception when the
778 user closed the environment even though there still was
779 a database open. */
780 if (self->mydb->db && self->mydb->myenvobj &&
781 !self->mydb->myenvobj->closed)
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000782 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000783 self->dbc = NULL;
784 MYDB_END_ALLOW_THREADS;
785 }
786 Py_XDECREF( self->mydb );
787#if PYTHON_API_VERSION <= 1007
788 PyMem_DEL(self);
789#else
790 PyObject_Del(self);
791#endif
792}
793
794
795static DBEnvObject*
796newDBEnvObject(int flags)
797{
798 int err;
799 DBEnvObject* self;
800#if PYTHON_API_VERSION <= 1007
801 self = PyObject_NEW(DBEnvObject, &DBEnv_Type);
802#else
803 self = PyObject_New(DBEnvObject, &DBEnv_Type);
804#endif
805
806 if (self == NULL)
807 return NULL;
808
809 self->closed = 1;
810 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000811 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
812 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000813
814 MYDB_BEGIN_ALLOW_THREADS;
815 err = db_env_create(&self->db_env, flags);
816 MYDB_END_ALLOW_THREADS;
817 if (makeDBError(err)) {
818 self = NULL;
819 }
820 else {
821 self->db_env->set_errcall(self->db_env, _db_errorCallback);
822 }
823 return self;
824}
825
826
827static void
828DBEnv_dealloc(DBEnvObject* self)
829{
830 if (!self->closed) {
831 MYDB_BEGIN_ALLOW_THREADS;
832 self->db_env->close(self->db_env, 0);
833 MYDB_END_ALLOW_THREADS;
834 }
835#if PYTHON_API_VERSION <= 1007
836 PyMem_DEL(self);
837#else
838 PyObject_Del(self);
839#endif
840}
841
842
843static DBTxnObject*
844newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
845{
846 int err;
847 DBTxnObject* self;
848
849#if PYTHON_API_VERSION <= 1007
850 self = PyObject_NEW(DBTxnObject, &DBTxn_Type);
851#else
852 self = PyObject_New(DBTxnObject, &DBTxn_Type);
853#endif
854 if (self == NULL)
855 return NULL;
856
857 MYDB_BEGIN_ALLOW_THREADS;
858#if (DBVER >= 40)
859 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
860#else
861 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
862#endif
863 MYDB_END_ALLOW_THREADS;
864 if (makeDBError(err)) {
865 self = NULL;
866 }
867 return self;
868}
869
870
871static void
872DBTxn_dealloc(DBTxnObject* self)
873{
874 /* XXX nothing to do for transaction objects?!? */
875
876 /* TODO: if it hasn't been commited, should we abort it? */
877
878#if PYTHON_API_VERSION <= 1007
879 PyMem_DEL(self);
880#else
881 PyObject_Del(self);
882#endif
883}
884
885
886static DBLockObject*
887newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
888 db_lockmode_t lock_mode, int flags)
889{
890 int err;
891 DBLockObject* self;
892
893#if PYTHON_API_VERSION <= 1007
894 self = PyObject_NEW(DBLockObject, &DBLock_Type);
895#else
896 self = PyObject_New(DBLockObject, &DBLock_Type);
897#endif
898 if (self == NULL)
899 return NULL;
900
901 MYDB_BEGIN_ALLOW_THREADS;
902#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000903 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
904 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000905#else
906 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
907#endif
908 MYDB_END_ALLOW_THREADS;
909 if (makeDBError(err)) {
910 self = NULL;
911 }
912
913 return self;
914}
915
916
917static void
918DBLock_dealloc(DBLockObject* self)
919{
920 /* TODO: if it hasn't been released, should we do it? */
921
922#if PYTHON_API_VERSION <= 1007
923 PyMem_DEL(self);
924#else
925 PyObject_Del(self);
926#endif
927}
928
929
930/* --------------------------------------------------------------------- */
931/* DB methods */
932
933static PyObject*
934DB_append(DBObject* self, PyObject* args)
935{
936 PyObject* txnobj = NULL;
937 PyObject* dataobj;
938 db_recno_t recno;
939 DBT key, data;
940 DB_TXN *txn = NULL;
941
942 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
943 return NULL;
944
945 CHECK_DB_NOT_CLOSED(self);
946
947 /* make a dummy key out of a recno */
948 recno = 0;
949 CLEAR_DBT(key);
950 key.data = &recno;
951 key.size = sizeof(recno);
952 key.ulen = key.size;
953 key.flags = DB_DBT_USERMEM;
954
955 if (!make_dbt(dataobj, &data)) return NULL;
956 if (!checkTxnObj(txnobj, &txn)) return NULL;
957
958 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
959 return NULL;
960
961 return PyInt_FromLong(recno);
962}
963
964
965#if (DBVER >= 33)
966
967static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000968_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
969 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000970{
971 int retval = DB_DONOTINDEX;
972 DBObject* secondaryDB = (DBObject*)db->app_private;
973 PyObject* callback = secondaryDB->associateCallback;
974 int type = secondaryDB->primaryDBType;
975 PyObject* key;
976 PyObject* data;
977 PyObject* args;
978 PyObject* result;
979
980
981 if (callback != NULL) {
982 MYDB_BEGIN_BLOCK_THREADS;
983
984 if (type == DB_RECNO || type == DB_QUEUE) {
985 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
986 }
987 else {
988 key = PyString_FromStringAndSize(priKey->data, priKey->size);
989 }
990 data = PyString_FromStringAndSize(priData->data, priData->size);
991 args = PyTuple_New(2);
992 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
993 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
994
995 result = PyEval_CallObject(callback, args);
996
997 if (result == NULL) {
998 PyErr_Print();
999 }
1000 else if (result == Py_None) {
1001 retval = DB_DONOTINDEX;
1002 }
1003 else if (PyInt_Check(result)) {
1004 retval = PyInt_AsLong(result);
1005 }
1006 else if (PyString_Check(result)) {
1007 char* data;
1008 int size;
1009
1010 CLEAR_DBT(*secKey);
1011#if PYTHON_API_VERSION <= 1007
1012 /* 1.5 compatibility */
1013 size = PyString_Size(result);
1014 data = PyString_AsString(result);
1015#else
1016 PyString_AsStringAndSize(result, &data, &size);
1017#endif
1018 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1019 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001020 if (secKey->data) {
1021 memcpy(secKey->data, data, size);
1022 secKey->size = size;
1023 retval = 0;
1024 }
1025 else {
1026 PyErr_SetString(PyExc_MemoryError,
1027 "malloc failed in _db_associateCallback");
1028 PyErr_Print();
1029 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001030 }
1031 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001032 PyErr_SetString(
1033 PyExc_TypeError,
1034 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001035 PyErr_Print();
1036 }
1037
1038 Py_DECREF(args);
1039 if (result) {
1040 Py_DECREF(result);
1041 }
1042
1043 MYDB_END_BLOCK_THREADS;
1044 }
1045 return retval;
1046}
1047
1048
1049static PyObject*
1050DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1051{
1052 int err, flags=0;
1053 DBObject* secondaryDB;
1054 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001055#if (DBVER >= 41)
1056 PyObject *txnobj = NULL;
1057 DB_TXN *txn = NULL;
1058 char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL};
1059#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001060 char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001061#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001062
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001063#if (DBVER >= 41)
1064 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1065 &secondaryDB, &callback, &flags,
1066 &txnobj)) {
1067#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001068 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001069 &secondaryDB, &callback, &flags)) {
1070#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001071 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001072 }
1073
1074#if (DBVER >= 41)
1075 if (!checkTxnObj(txnobj, &txn)) return NULL;
1076#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001077
1078 CHECK_DB_NOT_CLOSED(self);
1079 if (!DBObject_Check(secondaryDB)) {
1080 makeTypeError("DB", (PyObject*)secondaryDB);
1081 return NULL;
1082 }
1083 if (callback == Py_None) {
1084 callback = NULL;
1085 }
1086 else if (!PyCallable_Check(callback)) {
1087 makeTypeError("Callable", callback);
1088 return NULL;
1089 }
1090
1091 /* Save a reference to the callback in the secondary DB. */
1092 if (self->associateCallback != NULL) {
1093 Py_DECREF(self->associateCallback);
1094 }
1095 Py_INCREF(callback);
1096 secondaryDB->associateCallback = callback;
1097 secondaryDB->primaryDBType = _DB_get_type(self);
1098
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001099 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1100 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1101 * The global interepreter lock is not initialized until the first
1102 * thread is created using thread.start_new_thread() or fork() is
1103 * called. that would cause the ALLOW_THREADS here to segfault due
1104 * to a null pointer reference if no threads or child processes
1105 * have been created. This works around that and is a no-op if
1106 * threads have already been initialized.
1107 * (see pybsddb-users mailing list post on 2002-08-07)
1108 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001109#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001110 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001111#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001112 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001113#if (DBVER >= 41)
1114 err = self->db->associate(self->db,
1115 txn,
1116 secondaryDB->db,
1117 _db_associateCallback,
1118 flags);
1119#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001120 err = self->db->associate(self->db,
1121 secondaryDB->db,
1122 _db_associateCallback,
1123 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001124#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001125 MYDB_END_ALLOW_THREADS;
1126
1127 if (err) {
1128 Py_DECREF(self->associateCallback);
1129 self->associateCallback = NULL;
1130 secondaryDB->primaryDBType = 0;
1131 }
1132
1133 RETURN_IF_ERR();
1134 RETURN_NONE();
1135}
1136
1137
1138#endif
1139
1140
1141static PyObject*
1142DB_close(DBObject* self, PyObject* args)
1143{
1144 int err, flags=0;
1145 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1146 return NULL;
1147 if (self->db != NULL) {
1148 if (self->myenvobj)
1149 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001150 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001151 self->db = NULL;
1152 RETURN_IF_ERR();
1153 }
1154 RETURN_NONE();
1155}
1156
1157
1158#if (DBVER >= 32)
1159static PyObject*
1160_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1161{
1162 int err, flags=0, type;
1163 PyObject* txnobj = NULL;
1164 PyObject* retval = NULL;
1165 DBT key, data;
1166 DB_TXN *txn = NULL;
1167 char* kwnames[] = { "txn", "flags", NULL };
1168
1169 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1170 &txnobj, &flags))
1171 return NULL;
1172
1173 CHECK_DB_NOT_CLOSED(self);
1174 type = _DB_get_type(self);
1175 if (type == -1)
1176 return NULL;
1177 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001178 PyErr_SetString(PyExc_TypeError,
1179 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001180 return NULL;
1181 }
1182 if (!checkTxnObj(txnobj, &txn))
1183 return NULL;
1184
1185 CLEAR_DBT(key);
1186 CLEAR_DBT(data);
1187 if (CHECK_DBFLAG(self, DB_THREAD)) {
1188 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1189 data.flags = DB_DBT_MALLOC;
1190 key.flags = DB_DBT_MALLOC;
1191 }
1192
1193 MYDB_BEGIN_ALLOW_THREADS;
1194 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1195 MYDB_END_ALLOW_THREADS;
1196
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001197 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001198 err = 0;
1199 Py_INCREF(Py_None);
1200 retval = Py_None;
1201 }
1202 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001203 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1204 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001205 FREE_DBT(key);
1206 FREE_DBT(data);
1207 }
1208
1209 RETURN_IF_ERR();
1210 return retval;
1211}
1212
1213static PyObject*
1214DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1215{
1216 return _DB_consume(self, args, kwargs, DB_CONSUME);
1217}
1218
1219static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001220DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1221 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001222{
1223 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1224}
1225#endif
1226
1227
1228
1229static PyObject*
1230DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1231{
1232 int err, flags=0;
1233 DBC* dbc;
1234 PyObject* txnobj = NULL;
1235 DB_TXN *txn = NULL;
1236 char* kwnames[] = { "txn", "flags", NULL };
1237
1238 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1239 &txnobj, &flags))
1240 return NULL;
1241 CHECK_DB_NOT_CLOSED(self);
1242 if (!checkTxnObj(txnobj, &txn))
1243 return NULL;
1244
1245 MYDB_BEGIN_ALLOW_THREADS;
1246 err = self->db->cursor(self->db, txn, &dbc, flags);
1247 MYDB_END_ALLOW_THREADS;
1248 RETURN_IF_ERR();
1249 return (PyObject*) newDBCursorObject(dbc, self);
1250}
1251
1252
1253static PyObject*
1254DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1255{
1256 PyObject* txnobj = NULL;
1257 int flags = 0;
1258 PyObject* keyobj;
1259 DBT key;
1260 DB_TXN *txn = NULL;
1261 char* kwnames[] = { "key", "txn", "flags", NULL };
1262
1263 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1264 &keyobj, &txnobj, &flags))
1265 return NULL;
1266 CHECK_DB_NOT_CLOSED(self);
1267 if (!make_key_dbt(self, keyobj, &key, NULL))
1268 return NULL;
1269 if (!checkTxnObj(txnobj, &txn))
1270 return NULL;
1271
1272 if (-1 == _DB_delete(self, txn, &key, 0))
1273 return NULL;
1274
1275 FREE_DBT(key);
1276 RETURN_NONE();
1277}
1278
1279
1280static PyObject*
1281DB_fd(DBObject* self, PyObject* args)
1282{
1283 int err, the_fd;
1284
1285 if (!PyArg_ParseTuple(args,":fd"))
1286 return NULL;
1287 CHECK_DB_NOT_CLOSED(self);
1288
1289 MYDB_BEGIN_ALLOW_THREADS;
1290 err = self->db->fd(self->db, &the_fd);
1291 MYDB_END_ALLOW_THREADS;
1292 RETURN_IF_ERR();
1293 return PyInt_FromLong(the_fd);
1294}
1295
1296
1297static PyObject*
1298DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1299{
1300 int err, flags=0;
1301 PyObject* txnobj = NULL;
1302 PyObject* keyobj;
1303 PyObject* dfltobj = NULL;
1304 PyObject* retval = NULL;
1305 int dlen = -1;
1306 int doff = -1;
1307 DBT key, data;
1308 DB_TXN *txn = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001309 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001310
1311 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001312 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1313 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001314 return NULL;
1315
1316 CHECK_DB_NOT_CLOSED(self);
1317 if (!make_key_dbt(self, keyobj, &key, &flags))
1318 return NULL;
1319 if (!checkTxnObj(txnobj, &txn))
1320 return NULL;
1321
1322 CLEAR_DBT(data);
1323 if (CHECK_DBFLAG(self, DB_THREAD)) {
1324 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1325 data.flags = DB_DBT_MALLOC;
1326 }
1327 if (!add_partial_dbt(&data, dlen, doff))
1328 return NULL;
1329
1330 MYDB_BEGIN_ALLOW_THREADS;
1331 err = self->db->get(self->db, txn, &key, &data, flags);
1332 MYDB_END_ALLOW_THREADS;
1333
1334 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1335 err = 0;
1336 Py_INCREF(dfltobj);
1337 retval = dfltobj;
1338 }
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001339 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001340 err = 0;
1341 Py_INCREF(Py_None);
1342 retval = Py_None;
1343 }
1344 else if (!err) {
1345 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001346 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1347 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001348 else /* return just the data */
1349 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1350 FREE_DBT(key);
1351 FREE_DBT(data);
1352 }
1353
1354 RETURN_IF_ERR();
1355 return retval;
1356}
1357
1358
1359/* Return size of entry */
1360static PyObject*
1361DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1362{
1363 int err, flags=0;
1364 PyObject* txnobj = NULL;
1365 PyObject* keyobj;
1366 PyObject* retval = NULL;
1367 DBT key, data;
1368 DB_TXN *txn = NULL;
1369 char* kwnames[] = { "key", "txn", NULL };
1370
1371 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1372 &keyobj, &txnobj))
1373 return NULL;
1374 CHECK_DB_NOT_CLOSED(self);
1375 if (!make_key_dbt(self, keyobj, &key, &flags))
1376 return NULL;
1377 if (!checkTxnObj(txnobj, &txn))
1378 return NULL;
1379 CLEAR_DBT(data);
1380
1381 /* We don't allocate any memory, forcing a ENOMEM error and thus
1382 getting the record size. */
1383 data.flags = DB_DBT_USERMEM;
1384 data.ulen = 0;
1385 MYDB_BEGIN_ALLOW_THREADS;
1386 err = self->db->get(self->db, txn, &key, &data, flags);
1387 MYDB_END_ALLOW_THREADS;
1388 if (err == ENOMEM) {
1389 retval = PyInt_FromLong((long)data.size);
1390 err = 0;
1391 }
1392
1393 FREE_DBT(key);
1394 FREE_DBT(data);
1395 RETURN_IF_ERR();
1396 return retval;
1397}
1398
1399
1400static PyObject*
1401DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1402{
1403 int err, flags=0;
1404 PyObject* txnobj = NULL;
1405 PyObject* keyobj;
1406 PyObject* dataobj;
1407 PyObject* retval = NULL;
1408 DBT key, data;
1409 DB_TXN *txn = NULL;
1410 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1411
1412
1413 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1414 &keyobj, &dataobj, &txnobj, &flags))
1415 return NULL;
1416
1417 CHECK_DB_NOT_CLOSED(self);
1418 if (!make_key_dbt(self, keyobj, &key, NULL))
1419 return NULL;
1420 if (!make_dbt(dataobj, &data))
1421 return NULL;
1422 if (!checkTxnObj(txnobj, &txn))
1423 return NULL;
1424
1425 flags |= DB_GET_BOTH;
1426
1427 if (CHECK_DBFLAG(self, DB_THREAD)) {
1428 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1429 data.flags = DB_DBT_MALLOC;
1430 /* TODO: Is this flag needed? We're passing a data object that should
1431 match what's in the DB, so there should be no need to malloc.
1432 We run the risk of freeing something twice! Check this. */
1433 }
1434
1435 MYDB_BEGIN_ALLOW_THREADS;
1436 err = self->db->get(self->db, txn, &key, &data, flags);
1437 MYDB_END_ALLOW_THREADS;
1438
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001439 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001440 err = 0;
1441 Py_INCREF(Py_None);
1442 retval = Py_None;
1443 }
1444 else if (!err) {
1445 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1446 FREE_DBT(data); /* Only if retrieval was successful */
1447 }
1448
1449 FREE_DBT(key);
1450 RETURN_IF_ERR();
1451 return retval;
1452}
1453
1454
1455static PyObject*
1456DB_get_byteswapped(DBObject* self, PyObject* args)
1457{
1458#if (DBVER >= 33)
1459 int err = 0;
1460#endif
1461 int retval = -1;
1462
1463 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1464 return NULL;
1465 CHECK_DB_NOT_CLOSED(self);
1466
1467#if (DBVER >= 33)
1468 MYDB_BEGIN_ALLOW_THREADS;
1469 err = self->db->get_byteswapped(self->db, &retval);
1470 MYDB_END_ALLOW_THREADS;
1471 RETURN_IF_ERR();
1472#else
1473 MYDB_BEGIN_ALLOW_THREADS;
1474 retval = self->db->get_byteswapped(self->db);
1475 MYDB_END_ALLOW_THREADS;
1476#endif
1477 return PyInt_FromLong(retval);
1478}
1479
1480
1481static PyObject*
1482DB_get_type(DBObject* self, PyObject* args)
1483{
1484 int type;
1485
1486 if (!PyArg_ParseTuple(args,":get_type"))
1487 return NULL;
1488 CHECK_DB_NOT_CLOSED(self);
1489
1490 MYDB_BEGIN_ALLOW_THREADS;
1491 type = _DB_get_type(self);
1492 MYDB_END_ALLOW_THREADS;
1493 if (type == -1)
1494 return NULL;
1495 return PyInt_FromLong(type);
1496}
1497
1498
1499static PyObject*
1500DB_join(DBObject* self, PyObject* args)
1501{
1502 int err, flags=0;
1503 int length, x;
1504 PyObject* cursorsObj;
1505 DBC** cursors;
1506 DBC* dbc;
1507
1508
1509 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1510 return NULL;
1511
1512 CHECK_DB_NOT_CLOSED(self);
1513
1514 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001515 PyErr_SetString(PyExc_TypeError,
1516 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001517 return NULL;
1518 }
1519
1520 length = PyObject_Length(cursorsObj);
1521 cursors = malloc((length+1) * sizeof(DBC*));
1522 cursors[length] = NULL;
1523 for (x=0; x<length; x++) {
1524 PyObject* item = PySequence_GetItem(cursorsObj, x);
1525 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001526 PyErr_SetString(PyExc_TypeError,
1527 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001528 free(cursors);
1529 return NULL;
1530 }
1531 cursors[x] = ((DBCursorObject*)item)->dbc;
1532 }
1533
1534 MYDB_BEGIN_ALLOW_THREADS;
1535 err = self->db->join(self->db, cursors, &dbc, flags);
1536 MYDB_END_ALLOW_THREADS;
1537 free(cursors);
1538 RETURN_IF_ERR();
1539
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001540 // FIXME: this is a buggy interface. The returned cursor
1541 // contains internal references to the passed in cursors
1542 // but does not hold python references to them or prevent
1543 // them from being closed prematurely. This can cause
1544 // python to crash when things are done in the wrong order.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001545 return (PyObject*) newDBCursorObject(dbc, self);
1546}
1547
1548
1549static PyObject*
1550DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1551{
1552 int err, flags=0;
1553 PyObject* txnobj = NULL;
1554 PyObject* keyobj;
1555 DBT key;
1556 DB_TXN *txn = NULL;
1557 DB_KEY_RANGE range;
1558 char* kwnames[] = { "key", "txn", "flags", NULL };
1559
1560 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1561 &keyobj, &txnobj, &flags))
1562 return NULL;
1563 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001564 if (!make_dbt(keyobj, &key))
1565 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001566 return NULL;
1567 if (!checkTxnObj(txnobj, &txn))
1568 return NULL;
1569
1570 MYDB_BEGIN_ALLOW_THREADS;
1571 err = self->db->key_range(self->db, txn, &key, &range, flags);
1572 MYDB_END_ALLOW_THREADS;
1573
1574 RETURN_IF_ERR();
1575 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1576}
1577
1578
1579static PyObject*
1580DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1581{
1582 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1583 char* filename = NULL;
1584 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001585#if (DBVER >= 41)
1586 PyObject *txnobj = NULL;
1587 DB_TXN *txn = NULL;
1588 /* with dbname */
1589 char* kwnames[] = {
1590 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1591 /* without dbname */
1592 char* kwnames_basic[] = {
1593 "filename", "dbtype", "flags", "mode", "txn", NULL};
1594#else
1595 /* with dbname */
1596 char* kwnames[] = {
1597 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1598 /* without dbname */
1599 char* kwnames_basic[] = {
1600 "filename", "dbtype", "flags", "mode", NULL};
1601#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001602
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001603#if (DBVER >= 41)
1604 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1605 &filename, &dbname, &type, &flags, &mode,
1606 &txnobj))
1607#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001608 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001609 &filename, &dbname, &type, &flags,
1610 &mode))
1611#endif
1612 {
1613 PyErr_Clear();
1614 type = DB_UNKNOWN; flags = 0; mode = 0660;
1615 filename = NULL; dbname = NULL;
1616#if (DBVER >= 41)
1617 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1618 kwnames_basic,
1619 &filename, &type, &flags, &mode,
1620 &txnobj))
1621 return NULL;
1622#else
1623 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1624 kwnames_basic,
1625 &filename, &type, &flags, &mode))
1626 return NULL;
1627#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001628 }
1629
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001630#if (DBVER >= 41)
1631 if (!checkTxnObj(txnobj, &txn)) return NULL;
1632#endif
1633
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001634 if (NULL == self->db) {
1635 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1636 "Cannot call open() twice for DB object"));
1637 return NULL;
1638 }
1639
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001640#if 0 && (DBVER >= 41)
1641 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1642 && (self->myenvobj->flags & DB_INIT_TXN))
1643 {
1644 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1645 * explicitly passed) but we are in a transaction ready environment:
1646 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1647 * to work on BerkeleyDB 4.1 without needing to modify their
1648 * DBEnv or DB open calls.
1649 * TODO make this behaviour of the library configurable.
1650 */
1651 flags |= DB_AUTO_COMMIT;
1652 }
1653#endif
1654
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001655 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001656#if (DBVER >= 41)
1657 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1658#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001659 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001660#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001661 MYDB_END_ALLOW_THREADS;
1662 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001663 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001664 self->db = NULL;
1665 return NULL;
1666 }
1667
1668 self->flags = flags;
1669 RETURN_NONE();
1670}
1671
1672
1673static PyObject*
1674DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1675{
1676 int flags=0;
1677 PyObject* txnobj = NULL;
1678 int dlen = -1;
1679 int doff = -1;
1680 PyObject* keyobj, *dataobj, *retval;
1681 DBT key, data;
1682 DB_TXN *txn = NULL;
1683 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1684
1685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1686 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1687 return NULL;
1688
1689 CHECK_DB_NOT_CLOSED(self);
1690 if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL;
1691 if (!make_dbt(dataobj, &data)) return NULL;
1692 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
1693 if (!checkTxnObj(txnobj, &txn)) return NULL;
1694
1695 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1696 FREE_DBT(key);
1697 return NULL;
1698 }
1699
1700 if (flags & DB_APPEND)
1701 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1702 else {
1703 retval = Py_None;
1704 Py_INCREF(retval);
1705 }
1706 FREE_DBT(key);
1707 return retval;
1708}
1709
1710
1711
1712static PyObject*
1713DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1714{
1715 char* filename;
1716 char* database = NULL;
1717 int err, flags=0;
1718 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1719
1720 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1721 &filename, &database, &flags))
1722 return NULL;
1723 CHECK_DB_NOT_CLOSED(self);
1724
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001725 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001726 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001727 RETURN_IF_ERR();
1728 RETURN_NONE();
1729}
1730
1731
1732
1733static PyObject*
1734DB_rename(DBObject* self, PyObject* args)
1735{
1736 char* filename;
1737 char* database;
1738 char* newname;
1739 int err, flags=0;
1740
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001741 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1742 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001743 return NULL;
1744 CHECK_DB_NOT_CLOSED(self);
1745
1746 MYDB_BEGIN_ALLOW_THREADS;
1747 err = self->db->rename(self->db, filename, database, newname, flags);
1748 MYDB_END_ALLOW_THREADS;
1749 RETURN_IF_ERR();
1750 RETURN_NONE();
1751}
1752
1753
1754static PyObject*
1755DB_set_bt_minkey(DBObject* self, PyObject* args)
1756{
1757 int err, minkey;
1758
1759 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1760 return NULL;
1761 CHECK_DB_NOT_CLOSED(self);
1762
1763 MYDB_BEGIN_ALLOW_THREADS;
1764 err = self->db->set_bt_minkey(self->db, minkey);
1765 MYDB_END_ALLOW_THREADS;
1766 RETURN_IF_ERR();
1767 RETURN_NONE();
1768}
1769
1770
1771static PyObject*
1772DB_set_cachesize(DBObject* self, PyObject* args)
1773{
1774 int err;
1775 int gbytes = 0, bytes = 0, ncache = 0;
1776
1777 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1778 &gbytes,&bytes,&ncache))
1779 return NULL;
1780 CHECK_DB_NOT_CLOSED(self);
1781
1782 MYDB_BEGIN_ALLOW_THREADS;
1783 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1784 MYDB_END_ALLOW_THREADS;
1785 RETURN_IF_ERR();
1786 RETURN_NONE();
1787}
1788
1789
1790static PyObject*
1791DB_set_flags(DBObject* self, PyObject* args)
1792{
1793 int err, flags;
1794
1795 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
1796 return NULL;
1797 CHECK_DB_NOT_CLOSED(self);
1798
1799 MYDB_BEGIN_ALLOW_THREADS;
1800 err = self->db->set_flags(self->db, flags);
1801 MYDB_END_ALLOW_THREADS;
1802 RETURN_IF_ERR();
1803
1804 self->setflags |= flags;
1805 RETURN_NONE();
1806}
1807
1808
1809static PyObject*
1810DB_set_h_ffactor(DBObject* self, PyObject* args)
1811{
1812 int err, ffactor;
1813
1814 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
1815 return NULL;
1816 CHECK_DB_NOT_CLOSED(self);
1817
1818 MYDB_BEGIN_ALLOW_THREADS;
1819 err = self->db->set_h_ffactor(self->db, ffactor);
1820 MYDB_END_ALLOW_THREADS;
1821 RETURN_IF_ERR();
1822 RETURN_NONE();
1823}
1824
1825
1826static PyObject*
1827DB_set_h_nelem(DBObject* self, PyObject* args)
1828{
1829 int err, nelem;
1830
1831 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
1832 return NULL;
1833 CHECK_DB_NOT_CLOSED(self);
1834
1835 MYDB_BEGIN_ALLOW_THREADS;
1836 err = self->db->set_h_nelem(self->db, nelem);
1837 MYDB_END_ALLOW_THREADS;
1838 RETURN_IF_ERR();
1839 RETURN_NONE();
1840}
1841
1842
1843static PyObject*
1844DB_set_lorder(DBObject* self, PyObject* args)
1845{
1846 int err, lorder;
1847
1848 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
1849 return NULL;
1850 CHECK_DB_NOT_CLOSED(self);
1851
1852 MYDB_BEGIN_ALLOW_THREADS;
1853 err = self->db->set_lorder(self->db, lorder);
1854 MYDB_END_ALLOW_THREADS;
1855 RETURN_IF_ERR();
1856 RETURN_NONE();
1857}
1858
1859
1860static PyObject*
1861DB_set_pagesize(DBObject* self, PyObject* args)
1862{
1863 int err, pagesize;
1864
1865 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
1866 return NULL;
1867 CHECK_DB_NOT_CLOSED(self);
1868
1869 MYDB_BEGIN_ALLOW_THREADS;
1870 err = self->db->set_pagesize(self->db, pagesize);
1871 MYDB_END_ALLOW_THREADS;
1872 RETURN_IF_ERR();
1873 RETURN_NONE();
1874}
1875
1876
1877static PyObject*
1878DB_set_re_delim(DBObject* self, PyObject* args)
1879{
1880 int err;
1881 char delim;
1882
1883 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
1884 PyErr_Clear();
1885 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
1886 return NULL;
1887 }
1888
1889 CHECK_DB_NOT_CLOSED(self);
1890
1891 MYDB_BEGIN_ALLOW_THREADS;
1892 err = self->db->set_re_delim(self->db, delim);
1893 MYDB_END_ALLOW_THREADS;
1894 RETURN_IF_ERR();
1895 RETURN_NONE();
1896}
1897
1898static PyObject*
1899DB_set_re_len(DBObject* self, PyObject* args)
1900{
1901 int err, len;
1902
1903 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
1904 return NULL;
1905 CHECK_DB_NOT_CLOSED(self);
1906
1907 MYDB_BEGIN_ALLOW_THREADS;
1908 err = self->db->set_re_len(self->db, len);
1909 MYDB_END_ALLOW_THREADS;
1910 RETURN_IF_ERR();
1911 RETURN_NONE();
1912}
1913
1914
1915static PyObject*
1916DB_set_re_pad(DBObject* self, PyObject* args)
1917{
1918 int err;
1919 char pad;
1920
1921 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
1922 PyErr_Clear();
1923 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
1924 return NULL;
1925 }
1926 CHECK_DB_NOT_CLOSED(self);
1927
1928 MYDB_BEGIN_ALLOW_THREADS;
1929 err = self->db->set_re_pad(self->db, pad);
1930 MYDB_END_ALLOW_THREADS;
1931 RETURN_IF_ERR();
1932 RETURN_NONE();
1933}
1934
1935
1936static PyObject*
1937DB_set_re_source(DBObject* self, PyObject* args)
1938{
1939 int err;
1940 char *re_source;
1941
1942 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
1943 return NULL;
1944 CHECK_DB_NOT_CLOSED(self);
1945
1946 MYDB_BEGIN_ALLOW_THREADS;
1947 err = self->db->set_re_source(self->db, re_source);
1948 MYDB_END_ALLOW_THREADS;
1949 RETURN_IF_ERR();
1950 RETURN_NONE();
1951}
1952
1953
1954#if (DBVER >= 32)
1955static PyObject*
1956DB_set_q_extentsize(DBObject* self, PyObject* args)
1957{
1958 int err;
1959 int extentsize;
1960
1961 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
1962 return NULL;
1963 CHECK_DB_NOT_CLOSED(self);
1964
1965 MYDB_BEGIN_ALLOW_THREADS;
1966 err = self->db->set_q_extentsize(self->db, extentsize);
1967 MYDB_END_ALLOW_THREADS;
1968 RETURN_IF_ERR();
1969 RETURN_NONE();
1970}
1971#endif
1972
1973static PyObject*
1974DB_stat(DBObject* self, PyObject* args)
1975{
1976 int err, flags = 0, type;
1977 void* sp;
1978 PyObject* d;
1979
1980
1981 if (!PyArg_ParseTuple(args, "|i:stat", &flags))
1982 return NULL;
1983 CHECK_DB_NOT_CLOSED(self);
1984
1985 MYDB_BEGIN_ALLOW_THREADS;
1986#if (DBVER >= 33)
1987 err = self->db->stat(self->db, &sp, flags);
1988#else
1989 err = self->db->stat(self->db, &sp, NULL, flags);
1990#endif
1991 MYDB_END_ALLOW_THREADS;
1992 RETURN_IF_ERR();
1993
1994 self->haveStat = 1;
1995
1996 /* Turn the stat structure into a dictionary */
1997 type = _DB_get_type(self);
1998 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
1999 free(sp);
2000 return NULL;
2001 }
2002
2003#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2004#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2005#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2006
2007 switch (type) {
2008 case DB_HASH:
2009 MAKE_HASH_ENTRY(magic);
2010 MAKE_HASH_ENTRY(version);
2011 MAKE_HASH_ENTRY(nkeys);
2012 MAKE_HASH_ENTRY(ndata);
2013 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002014#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002015 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002016#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002017 MAKE_HASH_ENTRY(ffactor);
2018 MAKE_HASH_ENTRY(buckets);
2019 MAKE_HASH_ENTRY(free);
2020 MAKE_HASH_ENTRY(bfree);
2021 MAKE_HASH_ENTRY(bigpages);
2022 MAKE_HASH_ENTRY(big_bfree);
2023 MAKE_HASH_ENTRY(overflows);
2024 MAKE_HASH_ENTRY(ovfl_free);
2025 MAKE_HASH_ENTRY(dup);
2026 MAKE_HASH_ENTRY(dup_free);
2027 break;
2028
2029 case DB_BTREE:
2030 case DB_RECNO:
2031 MAKE_BT_ENTRY(magic);
2032 MAKE_BT_ENTRY(version);
2033 MAKE_BT_ENTRY(nkeys);
2034 MAKE_BT_ENTRY(ndata);
2035 MAKE_BT_ENTRY(pagesize);
2036 MAKE_BT_ENTRY(minkey);
2037 MAKE_BT_ENTRY(re_len);
2038 MAKE_BT_ENTRY(re_pad);
2039 MAKE_BT_ENTRY(levels);
2040 MAKE_BT_ENTRY(int_pg);
2041 MAKE_BT_ENTRY(leaf_pg);
2042 MAKE_BT_ENTRY(dup_pg);
2043 MAKE_BT_ENTRY(over_pg);
2044 MAKE_BT_ENTRY(free);
2045 MAKE_BT_ENTRY(int_pgfree);
2046 MAKE_BT_ENTRY(leaf_pgfree);
2047 MAKE_BT_ENTRY(dup_pgfree);
2048 MAKE_BT_ENTRY(over_pgfree);
2049 break;
2050
2051 case DB_QUEUE:
2052 MAKE_QUEUE_ENTRY(magic);
2053 MAKE_QUEUE_ENTRY(version);
2054 MAKE_QUEUE_ENTRY(nkeys);
2055 MAKE_QUEUE_ENTRY(ndata);
2056 MAKE_QUEUE_ENTRY(pagesize);
2057 MAKE_QUEUE_ENTRY(pages);
2058 MAKE_QUEUE_ENTRY(re_len);
2059 MAKE_QUEUE_ENTRY(re_pad);
2060 MAKE_QUEUE_ENTRY(pgfree);
2061#if (DBVER == 31)
2062 MAKE_QUEUE_ENTRY(start);
2063#endif
2064 MAKE_QUEUE_ENTRY(first_recno);
2065 MAKE_QUEUE_ENTRY(cur_recno);
2066 break;
2067
2068 default:
2069 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2070 Py_DECREF(d);
2071 d = NULL;
2072 }
2073
2074#undef MAKE_HASH_ENTRY
2075#undef MAKE_BT_ENTRY
2076#undef MAKE_QUEUE_ENTRY
2077
2078 free(sp);
2079 return d;
2080}
2081
2082static PyObject*
2083DB_sync(DBObject* self, PyObject* args)
2084{
2085 int err;
2086 int flags = 0;
2087
2088 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2089 return NULL;
2090 CHECK_DB_NOT_CLOSED(self);
2091
2092 MYDB_BEGIN_ALLOW_THREADS;
2093 err = self->db->sync(self->db, flags);
2094 MYDB_END_ALLOW_THREADS;
2095 RETURN_IF_ERR();
2096 RETURN_NONE();
2097}
2098
2099
2100#if (DBVER >= 33)
2101static PyObject*
2102DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2103{
2104 int err, flags=0;
2105 u_int32_t count=0;
2106 PyObject* txnobj = NULL;
2107 DB_TXN *txn = NULL;
2108 char* kwnames[] = { "txn", "flags", NULL };
2109
2110 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2111 &txnobj, &flags))
2112 return NULL;
2113 CHECK_DB_NOT_CLOSED(self);
2114 if (!checkTxnObj(txnobj, &txn))
2115 return NULL;
2116
2117 MYDB_BEGIN_ALLOW_THREADS;
2118 err = self->db->truncate(self->db, txn, &count, flags);
2119 MYDB_END_ALLOW_THREADS;
2120 RETURN_IF_ERR();
2121 return PyInt_FromLong(count);
2122}
2123#endif
2124
2125
2126static PyObject*
2127DB_upgrade(DBObject* self, PyObject* args)
2128{
2129 int err, flags=0;
2130 char *filename;
2131
2132 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2133 return NULL;
2134 CHECK_DB_NOT_CLOSED(self);
2135
2136 MYDB_BEGIN_ALLOW_THREADS;
2137 err = self->db->upgrade(self->db, filename, flags);
2138 MYDB_END_ALLOW_THREADS;
2139 RETURN_IF_ERR();
2140 RETURN_NONE();
2141}
2142
2143
2144static PyObject*
2145DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2146{
2147 int err, flags=0;
2148 char* fileName;
2149 char* dbName=NULL;
2150 char* outFileName=NULL;
2151 FILE* outFile=NULL;
2152 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2153
2154 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2155 &fileName, &dbName, &outFileName, &flags))
2156 return NULL;
2157
2158 CHECK_DB_NOT_CLOSED(self);
2159 if (outFileName)
2160 outFile = fopen(outFileName, "w");
2161
2162 MYDB_BEGIN_ALLOW_THREADS;
2163 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2164 MYDB_END_ALLOW_THREADS;
2165 if (outFileName)
2166 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002167
2168 /* DB.verify acts as a DB handle destructor (like close); this was
2169 * documented in BerkeleyDB 4.2 but had the undocumented effect
2170 * of not being safe in prior versions while still requiring an explicit
2171 * DB.close call afterwards. Lets call close for the user to emulate
2172 * the safe 4.2 behaviour. */
2173#if (DBVER <= 41)
2174 self->db->close(self->db, 0);
2175#endif
2176 self->db = NULL;
2177
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002178 RETURN_IF_ERR();
2179 RETURN_NONE();
2180}
2181
2182
2183static PyObject*
2184DB_set_get_returns_none(DBObject* self, PyObject* args)
2185{
2186 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002187 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002188
2189 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2190 return NULL;
2191 CHECK_DB_NOT_CLOSED(self);
2192
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002193 if (self->moduleFlags.getReturnsNone)
2194 ++oldValue;
2195 if (self->moduleFlags.cursorSetReturnsNone)
2196 ++oldValue;
2197 self->moduleFlags.getReturnsNone = (flags >= 1);
2198 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002199 return PyInt_FromLong(oldValue);
2200}
2201
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002202#if (DBVER >= 41)
2203static PyObject*
2204DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2205{
2206 int err;
2207 u_int32_t flags=0;
2208 char *passwd = NULL;
2209 char* kwnames[] = { "passwd", "flags", NULL };
2210
2211 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2212 &passwd, &flags)) {
2213 return NULL;
2214 }
2215
2216 MYDB_BEGIN_ALLOW_THREADS;
2217 err = self->db->set_encrypt(self->db, passwd, flags);
2218 MYDB_END_ALLOW_THREADS;
2219
2220 RETURN_IF_ERR();
2221 RETURN_NONE();
2222}
2223#endif /* DBVER >= 41 */
2224
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002225
2226/*-------------------------------------------------------------- */
2227/* Mapping and Dictionary-like access routines */
2228
2229int DB_length(DBObject* self)
2230{
2231 int err;
2232 long size = 0;
2233 int flags = 0;
2234 void* sp;
2235
2236 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002237 PyErr_SetObject(DBError,
2238 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002239 return -1;
2240 }
2241
2242 if (self->haveStat) { /* Has the stat function been called recently? If
2243 so, we can use the cached value. */
2244 flags = DB_CACHED_COUNTS;
2245 }
2246
2247 MYDB_BEGIN_ALLOW_THREADS;
2248#if (DBVER >= 33)
2249 err = self->db->stat(self->db, &sp, flags);
2250#else
2251 err = self->db->stat(self->db, &sp, NULL, flags);
2252#endif
2253 MYDB_END_ALLOW_THREADS;
2254
2255 if (err)
2256 return -1;
2257
2258 self->haveStat = 1;
2259
2260 /* All the stat structures have matching fields upto the ndata field,
2261 so we can use any of them for the type cast */
2262 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2263 free(sp);
2264 return size;
2265}
2266
2267
2268PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2269{
2270 int err;
2271 PyObject* retval;
2272 DBT key;
2273 DBT data;
2274
2275 CHECK_DB_NOT_CLOSED(self);
2276 if (!make_key_dbt(self, keyobj, &key, NULL))
2277 return NULL;
2278
2279 CLEAR_DBT(data);
2280 if (CHECK_DBFLAG(self, DB_THREAD)) {
2281 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2282 data.flags = DB_DBT_MALLOC;
2283 }
2284 MYDB_BEGIN_ALLOW_THREADS;
2285 err = self->db->get(self->db, NULL, &key, &data, 0);
2286 MYDB_END_ALLOW_THREADS;
2287 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2288 PyErr_SetObject(PyExc_KeyError, keyobj);
2289 retval = NULL;
2290 }
2291 else if (makeDBError(err)) {
2292 retval = NULL;
2293 }
2294 else {
2295 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2296 FREE_DBT(data);
2297 }
2298
2299 FREE_DBT(key);
2300 return retval;
2301}
2302
2303
2304static int
2305DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2306{
2307 DBT key, data;
2308 int retval;
2309 int flags = 0;
2310
2311 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002312 PyErr_SetObject(DBError,
2313 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002314 return -1;
2315 }
2316
2317 if (!make_key_dbt(self, keyobj, &key, NULL))
2318 return -1;
2319
2320 if (dataobj != NULL) {
2321 if (!make_dbt(dataobj, &data))
2322 retval = -1;
2323 else {
2324 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002325 /* dictionaries shouldn't have duplicate keys */
2326 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002327 retval = _DB_put(self, NULL, &key, &data, flags);
2328
2329 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002330 /* try deleting any old record that matches and then PUT it
2331 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002332 _DB_delete(self, NULL, &key, 0);
2333 PyErr_Clear();
2334 retval = _DB_put(self, NULL, &key, &data, flags);
2335 }
2336 }
2337 }
2338 else {
2339 /* dataobj == NULL, so delete the key */
2340 retval = _DB_delete(self, NULL, &key, 0);
2341 }
2342 FREE_DBT(key);
2343 return retval;
2344}
2345
2346
2347static PyObject*
2348DB_has_key(DBObject* self, PyObject* args)
2349{
2350 int err;
2351 PyObject* keyobj;
2352 DBT key, data;
2353 PyObject* txnobj = NULL;
2354 DB_TXN *txn = NULL;
2355
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002356 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002357 return NULL;
2358 CHECK_DB_NOT_CLOSED(self);
2359 if (!make_key_dbt(self, keyobj, &key, NULL))
2360 return NULL;
2361 if (!checkTxnObj(txnobj, &txn))
2362 return NULL;
2363
2364 /* This causes ENOMEM to be returned when the db has the key because
2365 it has a record but can't allocate a buffer for the data. This saves
2366 having to deal with data we won't be using.
2367 */
2368 CLEAR_DBT(data);
2369 data.flags = DB_DBT_USERMEM;
2370
2371 MYDB_BEGIN_ALLOW_THREADS;
2372 err = self->db->get(self->db, NULL, &key, &data, 0);
2373 MYDB_END_ALLOW_THREADS;
2374 FREE_DBT(key);
2375 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2376}
2377
2378
2379#define _KEYS_LIST 1
2380#define _VALUES_LIST 2
2381#define _ITEMS_LIST 3
2382
2383static PyObject*
2384_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2385{
2386 int err, dbtype;
2387 DBT key;
2388 DBT data;
2389 DBC *cursor;
2390 PyObject* list;
2391 PyObject* item = NULL;
2392
2393 CHECK_DB_NOT_CLOSED(self);
2394 CLEAR_DBT(key);
2395 CLEAR_DBT(data);
2396
2397 dbtype = _DB_get_type(self);
2398 if (dbtype == -1)
2399 return NULL;
2400
2401 list = PyList_New(0);
2402 if (list == NULL) {
2403 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2404 return NULL;
2405 }
2406
2407 /* get a cursor */
2408 MYDB_BEGIN_ALLOW_THREADS;
2409 err = self->db->cursor(self->db, NULL, &cursor, 0);
2410 MYDB_END_ALLOW_THREADS;
2411 RETURN_IF_ERR();
2412
2413 if (CHECK_DBFLAG(self, DB_THREAD)) {
2414 key.flags = DB_DBT_REALLOC;
2415 data.flags = DB_DBT_REALLOC;
2416 }
2417
2418 while (1) { /* use the cursor to traverse the DB, collecting items */
2419 MYDB_BEGIN_ALLOW_THREADS;
2420 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2421 MYDB_END_ALLOW_THREADS;
2422
2423 if (err) {
2424 /* for any error, break out of the loop */
2425 break;
2426 }
2427
2428 switch (type) {
2429 case _KEYS_LIST:
2430 switch(dbtype) {
2431 case DB_BTREE:
2432 case DB_HASH:
2433 default:
2434 item = PyString_FromStringAndSize((char*)key.data, key.size);
2435 break;
2436 case DB_RECNO:
2437 case DB_QUEUE:
2438 item = PyInt_FromLong(*((db_recno_t*)key.data));
2439 break;
2440 }
2441 break;
2442
2443 case _VALUES_LIST:
2444 item = PyString_FromStringAndSize((char*)data.data, data.size);
2445 break;
2446
2447 case _ITEMS_LIST:
2448 switch(dbtype) {
2449 case DB_BTREE:
2450 case DB_HASH:
2451 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002452 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2453 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002454 break;
2455 case DB_RECNO:
2456 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002457 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2458 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002459 break;
2460 }
2461 break;
2462 }
2463 if (item == NULL) {
2464 Py_DECREF(list);
2465 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2466 list = NULL;
2467 goto done;
2468 }
2469 PyList_Append(list, item);
2470 Py_DECREF(item);
2471 }
2472
2473 /* DB_NOTFOUND is okay, it just means we got to the end */
2474 if (err != DB_NOTFOUND && makeDBError(err)) {
2475 Py_DECREF(list);
2476 list = NULL;
2477 }
2478
2479 done:
2480 FREE_DBT(key);
2481 FREE_DBT(data);
2482 MYDB_BEGIN_ALLOW_THREADS;
2483 cursor->c_close(cursor);
2484 MYDB_END_ALLOW_THREADS;
2485 return list;
2486}
2487
2488
2489static PyObject*
2490DB_keys(DBObject* self, PyObject* args)
2491{
2492 PyObject* txnobj = NULL;
2493 DB_TXN *txn = NULL;
2494
2495 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2496 return NULL;
2497 if (!checkTxnObj(txnobj, &txn))
2498 return NULL;
2499 return _DB_make_list(self, txn, _KEYS_LIST);
2500}
2501
2502
2503static PyObject*
2504DB_items(DBObject* self, PyObject* args)
2505{
2506 PyObject* txnobj = NULL;
2507 DB_TXN *txn = NULL;
2508
2509 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2510 return NULL;
2511 if (!checkTxnObj(txnobj, &txn))
2512 return NULL;
2513 return _DB_make_list(self, txn, _ITEMS_LIST);
2514}
2515
2516
2517static PyObject*
2518DB_values(DBObject* self, PyObject* args)
2519{
2520 PyObject* txnobj = NULL;
2521 DB_TXN *txn = NULL;
2522
2523 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2524 return NULL;
2525 if (!checkTxnObj(txnobj, &txn))
2526 return NULL;
2527 return _DB_make_list(self, txn, _VALUES_LIST);
2528}
2529
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002530/* --------------------------------------------------------------------- */
2531/* DBCursor methods */
2532
2533
2534static PyObject*
2535DBC_close(DBCursorObject* self, PyObject* args)
2536{
2537 int err = 0;
2538
2539 if (!PyArg_ParseTuple(args, ":close"))
2540 return NULL;
2541
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002542 if (self->dbc != NULL) {
2543 MYDB_BEGIN_ALLOW_THREADS;
2544 err = self->dbc->c_close(self->dbc);
2545 self->dbc = NULL;
2546 MYDB_END_ALLOW_THREADS;
2547 }
2548 RETURN_IF_ERR();
2549 RETURN_NONE();
2550}
2551
2552
2553static PyObject*
2554DBC_count(DBCursorObject* self, PyObject* args)
2555{
2556 int err = 0;
2557 db_recno_t count;
2558 int flags = 0;
2559
2560 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2561 return NULL;
2562
2563 CHECK_CURSOR_NOT_CLOSED(self);
2564
2565 MYDB_BEGIN_ALLOW_THREADS;
2566 err = self->dbc->c_count(self->dbc, &count, flags);
2567 MYDB_END_ALLOW_THREADS;
2568 RETURN_IF_ERR();
2569
2570 return PyInt_FromLong(count);
2571}
2572
2573
2574static PyObject*
2575DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2576{
2577 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2578}
2579
2580
2581static PyObject*
2582DBC_delete(DBCursorObject* self, PyObject* args)
2583{
2584 int err, flags=0;
2585
2586 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2587 return NULL;
2588
2589 CHECK_CURSOR_NOT_CLOSED(self);
2590
2591 MYDB_BEGIN_ALLOW_THREADS;
2592 err = self->dbc->c_del(self->dbc, flags);
2593 MYDB_END_ALLOW_THREADS;
2594 RETURN_IF_ERR();
2595
2596 self->mydb->haveStat = 0;
2597 RETURN_NONE();
2598}
2599
2600
2601static PyObject*
2602DBC_dup(DBCursorObject* self, PyObject* args)
2603{
2604 int err, flags =0;
2605 DBC* dbc = NULL;
2606
2607 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2608 return NULL;
2609
2610 CHECK_CURSOR_NOT_CLOSED(self);
2611
2612 MYDB_BEGIN_ALLOW_THREADS;
2613 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2614 MYDB_END_ALLOW_THREADS;
2615 RETURN_IF_ERR();
2616
2617 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2618}
2619
2620static PyObject*
2621DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2622{
2623 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2624}
2625
2626
2627static PyObject*
2628DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2629{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00002630 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002631 PyObject* keyobj = NULL;
2632 PyObject* dataobj = NULL;
2633 PyObject* retval = NULL;
2634 int dlen = -1;
2635 int doff = -1;
2636 DBT key, data;
2637 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2638
2639 CLEAR_DBT(key);
2640 CLEAR_DBT(data);
2641 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002642 &flags, &dlen, &doff))
2643 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002644 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002645 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2646 &kwnames[1],
2647 &keyobj, &flags, &dlen, &doff))
2648 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002649 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002650 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2651 kwnames, &keyobj, &dataobj,
2652 &flags, &dlen, &doff))
2653 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002654 return NULL;
2655 }
2656 }
2657 }
2658
2659 CHECK_CURSOR_NOT_CLOSED(self);
2660
2661 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2662 return NULL;
2663 if (dataobj && !make_dbt(dataobj, &data))
2664 return NULL;
2665 if (!add_partial_dbt(&data, dlen, doff))
2666 return NULL;
2667
2668 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2669 data.flags = DB_DBT_MALLOC;
2670 key.flags = DB_DBT_MALLOC;
2671 }
2672
2673 MYDB_BEGIN_ALLOW_THREADS;
2674 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2675 MYDB_END_ALLOW_THREADS;
2676
2677
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002678 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002679 Py_INCREF(Py_None);
2680 retval = Py_None;
2681 }
2682 else if (makeDBError(err)) {
2683 retval = NULL;
2684 }
2685 else {
2686 switch (_DB_get_type(self->mydb)) {
2687 case -1:
2688 retval = NULL;
2689 break;
2690 case DB_BTREE:
2691 case DB_HASH:
2692 default:
2693 retval = Py_BuildValue("s#s#", key.data, key.size,
2694 data.data, data.size);
2695 break;
2696 case DB_RECNO:
2697 case DB_QUEUE:
2698 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2699 data.data, data.size);
2700 break;
2701 }
2702 FREE_DBT(key);
2703 FREE_DBT(data);
2704 }
2705 return retval;
2706}
2707
2708
2709static PyObject*
2710DBC_get_recno(DBCursorObject* self, PyObject* args)
2711{
2712 int err;
2713 db_recno_t recno;
2714 DBT key;
2715 DBT data;
2716
2717 if (!PyArg_ParseTuple(args, ":get_recno"))
2718 return NULL;
2719
2720 CHECK_CURSOR_NOT_CLOSED(self);
2721
2722 CLEAR_DBT(key);
2723 CLEAR_DBT(data);
2724 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2725 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2726 data.flags = DB_DBT_MALLOC;
2727 key.flags = DB_DBT_MALLOC;
2728 }
2729
2730 MYDB_BEGIN_ALLOW_THREADS;
2731 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
2732 MYDB_END_ALLOW_THREADS;
2733 RETURN_IF_ERR();
2734
2735 recno = *((db_recno_t*)data.data);
2736 FREE_DBT(key);
2737 FREE_DBT(data);
2738 return PyInt_FromLong(recno);
2739}
2740
2741
2742static PyObject*
2743DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2744{
2745 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
2746}
2747
2748
2749static PyObject*
2750DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2751{
2752 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
2753}
2754
2755
2756static PyObject*
2757DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2758{
2759 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
2760}
2761
2762
2763static PyObject*
2764DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2765{
2766 int err, flags = 0;
2767 PyObject* keyobj, *dataobj;
2768 DBT key, data;
2769 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
2770 int dlen = -1;
2771 int doff = -1;
2772
2773 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
2774 &keyobj, &dataobj, &flags, &dlen, &doff))
2775 return NULL;
2776
2777 CHECK_CURSOR_NOT_CLOSED(self);
2778
2779 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2780 return NULL;
2781 if (!make_dbt(dataobj, &data))
2782 return NULL;
2783 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
2784
2785 MYDB_BEGIN_ALLOW_THREADS;
2786 err = self->dbc->c_put(self->dbc, &key, &data, flags);
2787 MYDB_END_ALLOW_THREADS;
2788 FREE_DBT(key);
2789 RETURN_IF_ERR();
2790 self->mydb->haveStat = 0;
2791 RETURN_NONE();
2792}
2793
2794
2795static PyObject*
2796DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2797{
2798 int err, flags = 0;
2799 DBT key, data;
2800 PyObject* retval, *keyobj;
2801 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2802 int dlen = -1;
2803 int doff = -1;
2804
2805 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
2806 &keyobj, &flags, &dlen, &doff))
2807 return NULL;
2808
2809 CHECK_CURSOR_NOT_CLOSED(self);
2810
2811 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2812 return NULL;
2813
2814 CLEAR_DBT(data);
2815 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2816 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2817 data.flags = DB_DBT_MALLOC;
2818 }
2819 if (!add_partial_dbt(&data, dlen, doff))
2820 return NULL;
2821
2822 MYDB_BEGIN_ALLOW_THREADS;
2823 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
2824 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002825 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2826 Py_INCREF(Py_None);
2827 retval = Py_None;
2828 }
2829 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002830 retval = NULL;
2831 }
2832 else {
2833 switch (_DB_get_type(self->mydb)) {
2834 case -1:
2835 retval = NULL;
2836 break;
2837 case DB_BTREE:
2838 case DB_HASH:
2839 default:
2840 retval = Py_BuildValue("s#s#", key.data, key.size,
2841 data.data, data.size);
2842 break;
2843 case DB_RECNO:
2844 case DB_QUEUE:
2845 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2846 data.data, data.size);
2847 break;
2848 }
2849 FREE_DBT(key);
2850 FREE_DBT(data);
2851 }
2852
2853 return retval;
2854}
2855
2856
2857static PyObject*
2858DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2859{
2860 int err, flags = 0;
2861 DBT key, data;
2862 PyObject* retval, *keyobj;
2863 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2864 int dlen = -1;
2865 int doff = -1;
2866
2867 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
2868 &keyobj, &flags, &dlen, &doff))
2869 return NULL;
2870
2871 CHECK_CURSOR_NOT_CLOSED(self);
2872
2873 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2874 return NULL;
2875
2876 CLEAR_DBT(data);
2877 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2878 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2879 data.flags = DB_DBT_MALLOC;
2880 key.flags = DB_DBT_MALLOC;
2881 }
2882 if (!add_partial_dbt(&data, dlen, doff))
2883 return NULL;
2884 MYDB_BEGIN_ALLOW_THREADS;
2885 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
2886 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002887 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2888 Py_INCREF(Py_None);
2889 retval = Py_None;
2890 }
2891 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002892 retval = NULL;
2893 }
2894 else {
2895 switch (_DB_get_type(self->mydb)) {
2896 case -1:
2897 retval = NULL;
2898 break;
2899 case DB_BTREE:
2900 case DB_HASH:
2901 default:
2902 retval = Py_BuildValue("s#s#", key.data, key.size,
2903 data.data, data.size);
2904 break;
2905 case DB_RECNO:
2906 case DB_QUEUE:
2907 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2908 data.data, data.size);
2909 break;
2910 }
2911 FREE_DBT(key);
2912 FREE_DBT(data);
2913 }
2914
2915 return retval;
2916}
2917
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002918static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002919_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
2920 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002921{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002922 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002923 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002924 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002925
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002926 // the caller did this: CHECK_CURSOR_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002927 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2928 return NULL;
2929 if (!make_dbt(dataobj, &data))
2930 return NULL;
2931
2932 MYDB_BEGIN_ALLOW_THREADS;
2933 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
2934 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002935 if ((err == DB_NOTFOUND) && returnsNone) {
2936 Py_INCREF(Py_None);
2937 retval = Py_None;
2938 }
2939 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002940 retval = NULL;
2941 }
2942 else {
2943 switch (_DB_get_type(self->mydb)) {
2944 case -1:
2945 retval = NULL;
2946 break;
2947 case DB_BTREE:
2948 case DB_HASH:
2949 default:
2950 retval = Py_BuildValue("s#s#", key.data, key.size,
2951 data.data, data.size);
2952 break;
2953 case DB_RECNO:
2954 case DB_QUEUE:
2955 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2956 data.data, data.size);
2957 break;
2958 }
2959 }
2960
2961 FREE_DBT(key);
2962 return retval;
2963}
2964
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002965static PyObject*
2966DBC_get_both(DBCursorObject* self, PyObject* args)
2967{
2968 int flags=0;
2969 PyObject *keyobj, *dataobj;
2970
2971 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
2972 return NULL;
2973
2974 // if the cursor is closed, self->mydb may be invalid
2975 CHECK_CURSOR_NOT_CLOSED(self);
2976
2977 return _DBC_get_set_both(self, keyobj, dataobj, flags,
2978 self->mydb->moduleFlags.getReturnsNone);
2979}
2980
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00002981/* Return size of entry */
2982static PyObject*
2983DBC_get_current_size(DBCursorObject* self, PyObject* args)
2984{
2985 int err, flags=DB_CURRENT;
2986 PyObject* retval = NULL;
2987 DBT key, data;
2988
2989 if (!PyArg_ParseTuple(args, ":get_current_size"))
2990 return NULL;
2991 CHECK_CURSOR_NOT_CLOSED(self);
2992 CLEAR_DBT(key);
2993 CLEAR_DBT(data);
2994
2995 /* We don't allocate any memory, forcing a ENOMEM error and thus
2996 getting the record size. */
2997 data.flags = DB_DBT_USERMEM;
2998 data.ulen = 0;
2999 MYDB_BEGIN_ALLOW_THREADS;
3000 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3001 MYDB_END_ALLOW_THREADS;
3002 if (err == ENOMEM || !err) {
3003 /* ENOMEM means positive size, !err means zero length value */
3004 retval = PyInt_FromLong((long)data.size);
3005 err = 0;
3006 }
3007
3008 FREE_DBT(key);
3009 FREE_DBT(data);
3010 RETURN_IF_ERR();
3011 return retval;
3012}
3013
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003014static PyObject*
3015DBC_set_both(DBCursorObject* self, PyObject* args)
3016{
3017 int flags=0;
3018 PyObject *keyobj, *dataobj;
3019
3020 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3021 return NULL;
3022
3023 // if the cursor is closed, self->mydb may be invalid
3024 CHECK_CURSOR_NOT_CLOSED(self);
3025
3026 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3027 self->mydb->moduleFlags.cursorSetReturnsNone);
3028}
3029
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003030
3031static PyObject*
3032DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3033{
3034 int err, irecno, flags=0;
3035 db_recno_t recno;
3036 DBT key, data;
3037 PyObject* retval;
3038 int dlen = -1;
3039 int doff = -1;
3040 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3041
3042 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3043 &irecno, &flags, &dlen, &doff))
3044 return NULL;
3045
3046 CHECK_CURSOR_NOT_CLOSED(self);
3047
3048 CLEAR_DBT(key);
3049 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003050 /* use allocated space so DB will be able to realloc room for the real
3051 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003052 key.data = malloc(sizeof(db_recno_t));
3053 if (key.data == NULL) {
3054 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3055 return NULL;
3056 }
3057 key.size = sizeof(db_recno_t);
3058 key.ulen = key.size;
3059 memcpy(key.data, &recno, sizeof(db_recno_t));
3060 key.flags = DB_DBT_REALLOC;
3061
3062 CLEAR_DBT(data);
3063 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3064 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3065 data.flags = DB_DBT_MALLOC;
3066 }
3067 if (!add_partial_dbt(&data, dlen, doff))
3068 return NULL;
3069
3070 MYDB_BEGIN_ALLOW_THREADS;
3071 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3072 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003073 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3074 Py_INCREF(Py_None);
3075 retval = Py_None;
3076 }
3077 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003078 retval = NULL;
3079 }
3080 else { /* Can only be used for BTrees, so no need to return int key */
3081 retval = Py_BuildValue("s#s#", key.data, key.size,
3082 data.data, data.size);
3083 FREE_DBT(key);
3084 FREE_DBT(data);
3085 }
3086
3087 return retval;
3088}
3089
3090
3091static PyObject*
3092DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3093{
3094 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3095}
3096
3097
3098static PyObject*
3099DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3100{
3101 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3102}
3103
3104
3105static PyObject*
3106DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3107{
3108 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3109}
3110
3111
3112static PyObject*
3113DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3114{
3115 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3116}
3117
3118
3119static PyObject*
3120DBC_join_item(DBCursorObject* self, PyObject* args)
3121{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003122 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003123 DBT key, data;
3124 PyObject* retval;
3125
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003126 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003127 return NULL;
3128
3129 CHECK_CURSOR_NOT_CLOSED(self);
3130
3131 CLEAR_DBT(key);
3132 CLEAR_DBT(data);
3133 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3134 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3135 key.flags = DB_DBT_MALLOC;
3136 }
3137
3138 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003139 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003140 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003141 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3142 Py_INCREF(Py_None);
3143 retval = Py_None;
3144 }
3145 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003146 retval = NULL;
3147 }
3148 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003149 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003150 FREE_DBT(key);
3151 }
3152
3153 return retval;
3154}
3155
3156
3157
3158/* --------------------------------------------------------------------- */
3159/* DBEnv methods */
3160
3161
3162static PyObject*
3163DBEnv_close(DBEnvObject* self, PyObject* args)
3164{
3165 int err, flags = 0;
3166
3167 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3168 return NULL;
3169 if (!self->closed) { /* Don't close more than once */
3170 MYDB_BEGIN_ALLOW_THREADS;
3171 err = self->db_env->close(self->db_env, flags);
3172 MYDB_END_ALLOW_THREADS;
3173 /* after calling DBEnv->close, regardless of error, this DBEnv
3174 * may not be accessed again (BerkeleyDB docs). */
3175 self->closed = 1;
3176 self->db_env = NULL;
3177 RETURN_IF_ERR();
3178 }
3179 RETURN_NONE();
3180}
3181
3182
3183static PyObject*
3184DBEnv_open(DBEnvObject* self, PyObject* args)
3185{
3186 int err, flags=0, mode=0660;
3187 char *db_home;
3188
3189 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3190 return NULL;
3191
3192 CHECK_ENV_NOT_CLOSED(self);
3193
3194 MYDB_BEGIN_ALLOW_THREADS;
3195 err = self->db_env->open(self->db_env, db_home, flags, mode);
3196 MYDB_END_ALLOW_THREADS;
3197 RETURN_IF_ERR();
3198 self->closed = 0;
3199 self->flags = flags;
3200 RETURN_NONE();
3201}
3202
3203
3204static PyObject*
3205DBEnv_remove(DBEnvObject* self, PyObject* args)
3206{
3207 int err, flags=0;
3208 char *db_home;
3209
3210 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3211 return NULL;
3212 CHECK_ENV_NOT_CLOSED(self);
3213 MYDB_BEGIN_ALLOW_THREADS;
3214 err = self->db_env->remove(self->db_env, db_home, flags);
3215 MYDB_END_ALLOW_THREADS;
3216 RETURN_IF_ERR();
3217 RETURN_NONE();
3218}
3219
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003220#if (DBVER >= 41)
3221static PyObject*
3222DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3223{
3224 int err;
3225 u_int32_t flags=0;
3226 char *file = NULL;
3227 char *database = NULL;
3228 PyObject *txnobj = NULL;
3229 DB_TXN *txn = NULL;
3230 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3231
3232 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3233 &file, &database, &txnobj, &flags)) {
3234 return NULL;
3235 }
3236 if (!checkTxnObj(txnobj, &txn)) {
3237 return NULL;
3238 }
3239 CHECK_ENV_NOT_CLOSED(self);
3240 MYDB_BEGIN_ALLOW_THREADS;
3241 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3242 MYDB_END_ALLOW_THREADS;
3243 RETURN_IF_ERR();
3244 RETURN_NONE();
3245}
3246
3247static PyObject*
3248DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3249{
3250 int err;
3251 u_int32_t flags=0;
3252 char *file = NULL;
3253 char *database = NULL;
3254 char *newname = NULL;
3255 PyObject *txnobj = NULL;
3256 DB_TXN *txn = NULL;
3257 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3258
3259 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3260 &file, &database, &newname, &txnobj, &flags)) {
3261 return NULL;
3262 }
3263 if (!checkTxnObj(txnobj, &txn)) {
3264 return NULL;
3265 }
3266 CHECK_ENV_NOT_CLOSED(self);
3267 MYDB_BEGIN_ALLOW_THREADS;
3268 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3269 flags);
3270 MYDB_END_ALLOW_THREADS;
3271 RETURN_IF_ERR();
3272 RETURN_NONE();
3273}
3274
3275static PyObject*
3276DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3277{
3278 int err;
3279 u_int32_t flags=0;
3280 char *passwd = NULL;
3281 char* kwnames[] = { "passwd", "flags", NULL };
3282
3283 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3284 &passwd, &flags)) {
3285 return NULL;
3286 }
3287
3288 MYDB_BEGIN_ALLOW_THREADS;
3289 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3290 MYDB_END_ALLOW_THREADS;
3291
3292 RETURN_IF_ERR();
3293 RETURN_NONE();
3294}
3295#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003296
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003297#if (DBVER >= 40)
3298static PyObject*
3299DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3300{
3301 int err;
3302 u_int32_t flags=0;
3303 u_int32_t timeout = 0;
3304 char* kwnames[] = { "timeout", "flags", NULL };
3305
3306 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3307 &timeout, &flags)) {
3308 return NULL;
3309 }
3310
3311 MYDB_BEGIN_ALLOW_THREADS;
3312 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3313 MYDB_END_ALLOW_THREADS;
3314
3315 RETURN_IF_ERR();
3316 RETURN_NONE();
3317}
3318#endif /* DBVER >= 40 */
3319
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003320static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003321DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3322{
3323 int err;
3324 long shm_key = 0;
3325
3326 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3327 return NULL;
3328 CHECK_ENV_NOT_CLOSED(self);
3329
3330 err = self->db_env->set_shm_key(self->db_env, shm_key);
3331 RETURN_IF_ERR();
3332 RETURN_NONE();
3333}
3334
3335static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003336DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3337{
3338 int err, gbytes=0, bytes=0, ncache=0;
3339
3340 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3341 &gbytes, &bytes, &ncache))
3342 return NULL;
3343 CHECK_ENV_NOT_CLOSED(self);
3344
3345 MYDB_BEGIN_ALLOW_THREADS;
3346 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3347 MYDB_END_ALLOW_THREADS;
3348 RETURN_IF_ERR();
3349 RETURN_NONE();
3350}
3351
3352
3353#if (DBVER >= 32)
3354static PyObject*
3355DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3356{
3357 int err, flags=0, onoff=0;
3358
3359 if (!PyArg_ParseTuple(args, "ii:set_flags",
3360 &flags, &onoff))
3361 return NULL;
3362 CHECK_ENV_NOT_CLOSED(self);
3363
3364 MYDB_BEGIN_ALLOW_THREADS;
3365 err = self->db_env->set_flags(self->db_env, flags, onoff);
3366 MYDB_END_ALLOW_THREADS;
3367 RETURN_IF_ERR();
3368 RETURN_NONE();
3369}
3370#endif
3371
3372
3373static PyObject*
3374DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3375{
3376 int err;
3377 char *dir;
3378
3379 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3380 return NULL;
3381 CHECK_ENV_NOT_CLOSED(self);
3382
3383 MYDB_BEGIN_ALLOW_THREADS;
3384 err = self->db_env->set_data_dir(self->db_env, dir);
3385 MYDB_END_ALLOW_THREADS;
3386 RETURN_IF_ERR();
3387 RETURN_NONE();
3388}
3389
3390
3391static PyObject*
3392DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3393{
3394 int err, lg_bsize;
3395
3396 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3397 return NULL;
3398 CHECK_ENV_NOT_CLOSED(self);
3399
3400 MYDB_BEGIN_ALLOW_THREADS;
3401 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3402 MYDB_END_ALLOW_THREADS;
3403 RETURN_IF_ERR();
3404 RETURN_NONE();
3405}
3406
3407
3408static PyObject*
3409DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3410{
3411 int err;
3412 char *dir;
3413
3414 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3415 return NULL;
3416 CHECK_ENV_NOT_CLOSED(self);
3417
3418 MYDB_BEGIN_ALLOW_THREADS;
3419 err = self->db_env->set_lg_dir(self->db_env, dir);
3420 MYDB_END_ALLOW_THREADS;
3421 RETURN_IF_ERR();
3422 RETURN_NONE();
3423}
3424
3425static PyObject*
3426DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3427{
3428 int err, lg_max;
3429
3430 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3431 return NULL;
3432 CHECK_ENV_NOT_CLOSED(self);
3433
3434 MYDB_BEGIN_ALLOW_THREADS;
3435 err = self->db_env->set_lg_max(self->db_env, lg_max);
3436 MYDB_END_ALLOW_THREADS;
3437 RETURN_IF_ERR();
3438 RETURN_NONE();
3439}
3440
3441
3442static PyObject*
3443DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3444{
3445 int err, lk_detect;
3446
3447 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3448 return NULL;
3449 CHECK_ENV_NOT_CLOSED(self);
3450
3451 MYDB_BEGIN_ALLOW_THREADS;
3452 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3453 MYDB_END_ALLOW_THREADS;
3454 RETURN_IF_ERR();
3455 RETURN_NONE();
3456}
3457
3458
3459static PyObject*
3460DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3461{
3462 int err, max;
3463
3464 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3465 return NULL;
3466 CHECK_ENV_NOT_CLOSED(self);
3467
3468 MYDB_BEGIN_ALLOW_THREADS;
3469 err = self->db_env->set_lk_max(self->db_env, max);
3470 MYDB_END_ALLOW_THREADS;
3471 RETURN_IF_ERR();
3472 RETURN_NONE();
3473}
3474
3475
3476#if (DBVER >= 32)
3477
3478static PyObject*
3479DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3480{
3481 int err, max;
3482
3483 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3484 return NULL;
3485 CHECK_ENV_NOT_CLOSED(self);
3486
3487 MYDB_BEGIN_ALLOW_THREADS;
3488 err = self->db_env->set_lk_max_locks(self->db_env, max);
3489 MYDB_END_ALLOW_THREADS;
3490 RETURN_IF_ERR();
3491 RETURN_NONE();
3492}
3493
3494
3495static PyObject*
3496DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3497{
3498 int err, max;
3499
3500 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3501 return NULL;
3502 CHECK_ENV_NOT_CLOSED(self);
3503
3504 MYDB_BEGIN_ALLOW_THREADS;
3505 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3506 MYDB_END_ALLOW_THREADS;
3507 RETURN_IF_ERR();
3508 RETURN_NONE();
3509}
3510
3511
3512static PyObject*
3513DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3514{
3515 int err, max;
3516
3517 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3518 return NULL;
3519 CHECK_ENV_NOT_CLOSED(self);
3520
3521 MYDB_BEGIN_ALLOW_THREADS;
3522 err = self->db_env->set_lk_max_objects(self->db_env, max);
3523 MYDB_END_ALLOW_THREADS;
3524 RETURN_IF_ERR();
3525 RETURN_NONE();
3526}
3527
3528#endif
3529
3530
3531static PyObject*
3532DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3533{
3534 int err, mp_mmapsize;
3535
3536 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3537 return NULL;
3538 CHECK_ENV_NOT_CLOSED(self);
3539
3540 MYDB_BEGIN_ALLOW_THREADS;
3541 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3542 MYDB_END_ALLOW_THREADS;
3543 RETURN_IF_ERR();
3544 RETURN_NONE();
3545}
3546
3547
3548static PyObject*
3549DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3550{
3551 int err;
3552 char *dir;
3553
3554 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3555 return NULL;
3556 CHECK_ENV_NOT_CLOSED(self);
3557
3558 MYDB_BEGIN_ALLOW_THREADS;
3559 err = self->db_env->set_tmp_dir(self->db_env, dir);
3560 MYDB_END_ALLOW_THREADS;
3561 RETURN_IF_ERR();
3562 RETURN_NONE();
3563}
3564
3565
3566static PyObject*
3567DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3568{
3569 int flags = 0;
3570 PyObject* txnobj = NULL;
3571 DB_TXN *txn = NULL;
3572 char* kwnames[] = { "parent", "flags", NULL };
3573
3574 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3575 &txnobj, &flags))
3576 return NULL;
3577
3578 if (!checkTxnObj(txnobj, &txn))
3579 return NULL;
3580 CHECK_ENV_NOT_CLOSED(self);
3581
3582 return (PyObject*)newDBTxnObject(self, txn, flags);
3583}
3584
3585
3586static PyObject*
3587DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3588{
3589 int err, kbyte=0, min=0, flags=0;
3590
3591 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3592 return NULL;
3593 CHECK_ENV_NOT_CLOSED(self);
3594
3595 MYDB_BEGIN_ALLOW_THREADS;
3596#if (DBVER >= 40)
3597 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3598#else
3599 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3600#endif
3601 MYDB_END_ALLOW_THREADS;
3602 RETURN_IF_ERR();
3603 RETURN_NONE();
3604}
3605
3606
3607static PyObject*
3608DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3609{
3610 int err, max;
3611
3612 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3613 return NULL;
3614 CHECK_ENV_NOT_CLOSED(self);
3615
3616 MYDB_BEGIN_ALLOW_THREADS;
3617 err = self->db_env->set_tx_max(self->db_env, max);
3618 MYDB_END_ALLOW_THREADS;
3619 RETURN_IF_ERR();
3620 RETURN_NONE();
3621}
3622
3623
3624static PyObject*
3625DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3626{
3627 int err, atype, flags=0;
3628 int aborted = 0;
3629
3630 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3631 return NULL;
3632 CHECK_ENV_NOT_CLOSED(self);
3633
3634 MYDB_BEGIN_ALLOW_THREADS;
3635#if (DBVER >= 40)
3636 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3637#else
3638 err = lock_detect(self->db_env, flags, atype, &aborted);
3639#endif
3640 MYDB_END_ALLOW_THREADS;
3641 RETURN_IF_ERR();
3642 return PyInt_FromLong(aborted);
3643}
3644
3645
3646static PyObject*
3647DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3648{
3649 int flags=0;
3650 int locker, lock_mode;
3651 DBT obj;
3652 PyObject* objobj;
3653
3654 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3655 return NULL;
3656
3657
3658 if (!make_dbt(objobj, &obj))
3659 return NULL;
3660
3661 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3662}
3663
3664
3665static PyObject*
3666DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3667{
3668 int err;
3669 u_int32_t theID;
3670
3671 if (!PyArg_ParseTuple(args, ":lock_id"))
3672 return NULL;
3673
3674 CHECK_ENV_NOT_CLOSED(self);
3675 MYDB_BEGIN_ALLOW_THREADS;
3676#if (DBVER >= 40)
3677 err = self->db_env->lock_id(self->db_env, &theID);
3678#else
3679 err = lock_id(self->db_env, &theID);
3680#endif
3681 MYDB_END_ALLOW_THREADS;
3682 RETURN_IF_ERR();
3683
3684 return PyInt_FromLong((long)theID);
3685}
3686
3687
3688static PyObject*
3689DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3690{
3691 int err;
3692 DBLockObject* dblockobj;
3693
3694 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3695 return NULL;
3696
3697 CHECK_ENV_NOT_CLOSED(self);
3698 MYDB_BEGIN_ALLOW_THREADS;
3699#if (DBVER >= 40)
3700 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3701#else
3702 err = lock_put(self->db_env, &dblockobj->lock);
3703#endif
3704 MYDB_END_ALLOW_THREADS;
3705 RETURN_IF_ERR();
3706 RETURN_NONE();
3707}
3708
3709
3710static PyObject*
3711DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
3712{
3713 int err;
3714 DB_LOCK_STAT* sp;
3715 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003716 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003717
3718 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
3719 return NULL;
3720 CHECK_ENV_NOT_CLOSED(self);
3721
3722 MYDB_BEGIN_ALLOW_THREADS;
3723#if (DBVER >= 40)
3724 err = self->db_env->lock_stat(self->db_env, &sp, flags);
3725#else
3726#if (DBVER >= 33)
3727 err = lock_stat(self->db_env, &sp);
3728#else
3729 err = lock_stat(self->db_env, &sp, NULL);
3730#endif
3731#endif
3732 MYDB_END_ALLOW_THREADS;
3733 RETURN_IF_ERR();
3734
3735 /* Turn the stat structure into a dictionary */
3736 d = PyDict_New();
3737 if (d == NULL) {
3738 free(sp);
3739 return NULL;
3740 }
3741
3742#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3743
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003744#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003745 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003746#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003747 MAKE_ENTRY(nmodes);
3748#if (DBVER >= 32)
3749 MAKE_ENTRY(maxlocks);
3750 MAKE_ENTRY(maxlockers);
3751 MAKE_ENTRY(maxobjects);
3752 MAKE_ENTRY(nlocks);
3753 MAKE_ENTRY(maxnlocks);
3754#endif
3755 MAKE_ENTRY(nlockers);
3756 MAKE_ENTRY(maxnlockers);
3757#if (DBVER >= 32)
3758 MAKE_ENTRY(nobjects);
3759 MAKE_ENTRY(maxnobjects);
3760#endif
3761 MAKE_ENTRY(nrequests);
3762 MAKE_ENTRY(nreleases);
3763 MAKE_ENTRY(nnowaits);
3764 MAKE_ENTRY(nconflicts);
3765 MAKE_ENTRY(ndeadlocks);
3766 MAKE_ENTRY(regsize);
3767 MAKE_ENTRY(region_wait);
3768 MAKE_ENTRY(region_nowait);
3769
3770#undef MAKE_ENTRY
3771 free(sp);
3772 return d;
3773}
3774
3775
3776static PyObject*
3777DBEnv_log_archive(DBEnvObject* self, PyObject* args)
3778{
3779 int flags=0;
3780 int err;
3781 char **log_list_start, **log_list;
3782 PyObject* list;
3783 PyObject* item = NULL;
3784
3785 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
3786 return NULL;
3787
3788 CHECK_ENV_NOT_CLOSED(self);
3789 MYDB_BEGIN_ALLOW_THREADS;
3790#if (DBVER >= 40)
3791 err = self->db_env->log_archive(self->db_env, &log_list, flags);
3792#elif (DBVER == 33)
3793 err = log_archive(self->db_env, &log_list, flags);
3794#else
3795 err = log_archive(self->db_env, &log_list, flags, NULL);
3796#endif
3797 MYDB_END_ALLOW_THREADS;
3798 RETURN_IF_ERR();
3799
3800 list = PyList_New(0);
3801 if (list == NULL) {
3802 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
3803 return NULL;
3804 }
3805
3806 if (log_list) {
3807 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
3808 item = PyString_FromString (*log_list);
3809 if (item == NULL) {
3810 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003811 PyErr_SetString(PyExc_MemoryError,
3812 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003813 list = NULL;
3814 break;
3815 }
3816 PyList_Append(list, item);
3817 Py_DECREF(item);
3818 }
3819 free(log_list_start);
3820 }
3821 return list;
3822}
3823
3824
3825static PyObject*
3826DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
3827{
3828 int err;
3829 DB_TXN_STAT* sp;
3830 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003831 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003832
3833 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
3834 return NULL;
3835 CHECK_ENV_NOT_CLOSED(self);
3836
3837 MYDB_BEGIN_ALLOW_THREADS;
3838#if (DBVER >= 40)
3839 err = self->db_env->txn_stat(self->db_env, &sp, flags);
3840#elif (DBVER == 33)
3841 err = txn_stat(self->db_env, &sp);
3842#else
3843 err = txn_stat(self->db_env, &sp, NULL);
3844#endif
3845 MYDB_END_ALLOW_THREADS;
3846 RETURN_IF_ERR();
3847
3848 /* Turn the stat structure into a dictionary */
3849 d = PyDict_New();
3850 if (d == NULL) {
3851 free(sp);
3852 return NULL;
3853 }
3854
3855#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3856
3857 MAKE_ENTRY(time_ckp);
3858 MAKE_ENTRY(last_txnid);
3859 MAKE_ENTRY(maxtxns);
3860 MAKE_ENTRY(nactive);
3861 MAKE_ENTRY(maxnactive);
3862 MAKE_ENTRY(nbegins);
3863 MAKE_ENTRY(naborts);
3864 MAKE_ENTRY(ncommits);
3865 MAKE_ENTRY(regsize);
3866 MAKE_ENTRY(region_wait);
3867 MAKE_ENTRY(region_nowait);
3868
3869#undef MAKE_ENTRY
3870 free(sp);
3871 return d;
3872}
3873
3874
3875static PyObject*
3876DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
3877{
3878 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003879 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003880
3881 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
3882 return NULL;
3883 CHECK_ENV_NOT_CLOSED(self);
3884
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003885 if (self->moduleFlags.getReturnsNone)
3886 ++oldValue;
3887 if (self->moduleFlags.cursorSetReturnsNone)
3888 ++oldValue;
3889 self->moduleFlags.getReturnsNone = (flags >= 1);
3890 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003891 return PyInt_FromLong(oldValue);
3892}
3893
3894
3895/* --------------------------------------------------------------------- */
3896/* DBTxn methods */
3897
3898
3899static PyObject*
3900DBTxn_commit(DBTxnObject* self, PyObject* args)
3901{
3902 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003903 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003904
3905 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
3906 return NULL;
3907
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003908 if (!self->txn) {
3909 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3910 "DBTxn must not be used after txn_commit or txn_abort"));
3911 return NULL;
3912 }
3913 txn = self->txn;
3914 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003915 MYDB_BEGIN_ALLOW_THREADS;
3916#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003917 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003918#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003919 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003920#endif
3921 MYDB_END_ALLOW_THREADS;
3922 RETURN_IF_ERR();
3923 RETURN_NONE();
3924}
3925
3926static PyObject*
3927DBTxn_prepare(DBTxnObject* self, PyObject* args)
3928{
3929#if (DBVER >= 33)
3930 int err;
3931 char* gid=NULL;
3932 int gid_size=0;
3933
3934 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
3935 return NULL;
3936
3937 if (gid_size != DB_XIDDATASIZE) {
3938 PyErr_SetString(PyExc_TypeError,
3939 "gid must be DB_XIDDATASIZE bytes long");
3940 return NULL;
3941 }
3942
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003943 if (!self->txn) {
3944 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3945 "DBTxn must not be used after txn_commit or txn_abort"));
3946 return NULL;
3947 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003948 MYDB_BEGIN_ALLOW_THREADS;
3949#if (DBVER >= 40)
3950 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
3951#else
3952 err = txn_prepare(self->txn, (u_int8_t*)gid);
3953#endif
3954 MYDB_END_ALLOW_THREADS;
3955 RETURN_IF_ERR();
3956 RETURN_NONE();
3957#else
3958 int err;
3959
3960 if (!PyArg_ParseTuple(args, ":prepare"))
3961 return NULL;
3962
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003963 if (!self->txn) {
3964 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3965 "DBTxn must not be used after txn_commit or txn_abort"));
3966 return NULL;
3967 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003968 MYDB_BEGIN_ALLOW_THREADS;
3969 err = txn_prepare(self->txn);
3970 MYDB_END_ALLOW_THREADS;
3971 RETURN_IF_ERR();
3972 RETURN_NONE();
3973#endif
3974}
3975
3976
3977static PyObject*
3978DBTxn_abort(DBTxnObject* self, PyObject* args)
3979{
3980 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003981 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003982
3983 if (!PyArg_ParseTuple(args, ":abort"))
3984 return NULL;
3985
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003986 if (!self->txn) {
3987 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3988 "DBTxn must not be used after txn_commit or txn_abort"));
3989 return NULL;
3990 }
3991 txn = self->txn;
3992 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003993 MYDB_BEGIN_ALLOW_THREADS;
3994#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003995 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003996#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003997 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003998#endif
3999 MYDB_END_ALLOW_THREADS;
4000 RETURN_IF_ERR();
4001 RETURN_NONE();
4002}
4003
4004
4005static PyObject*
4006DBTxn_id(DBTxnObject* self, PyObject* args)
4007{
4008 int id;
4009
4010 if (!PyArg_ParseTuple(args, ":id"))
4011 return NULL;
4012
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00004013 if (!self->txn) {
4014 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4015 "DBTxn must not be used after txn_commit or txn_abort"));
4016 return NULL;
4017 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004018 MYDB_BEGIN_ALLOW_THREADS;
4019#if (DBVER >= 40)
4020 id = self->txn->id(self->txn);
4021#else
4022 id = txn_id(self->txn);
4023#endif
4024 MYDB_END_ALLOW_THREADS;
4025 return PyInt_FromLong(id);
4026}
4027
4028/* --------------------------------------------------------------------- */
4029/* Method definition tables and type objects */
4030
4031static PyMethodDef DB_methods[] = {
4032 {"append", (PyCFunction)DB_append, METH_VARARGS},
4033#if (DBVER >= 33)
4034 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4035#endif
4036 {"close", (PyCFunction)DB_close, METH_VARARGS},
4037#if (DBVER >= 32)
4038 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4039 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4040#endif
4041 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4042 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4043 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4044 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
4045 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4046 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4047 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4048 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4049 {"join", (PyCFunction)DB_join, METH_VARARGS},
4050 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4051 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4052 {"items", (PyCFunction)DB_items, METH_VARARGS},
4053 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4054 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4055 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4056 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4057 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4058 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4059 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004060#if (DBVER >= 41)
4061 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4062#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004063 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4064 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4065 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4066 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4067 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4068 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4069 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4070 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4071 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4072#if (DBVER >= 32)
4073 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4074#endif
4075 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4076 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4077#if (DBVER >= 33)
4078 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4079#endif
4080 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4081 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4082 {"values", (PyCFunction)DB_values, METH_VARARGS},
4083 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4084 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4085 {NULL, NULL} /* sentinel */
4086};
4087
4088
4089static PyMappingMethods DB_mapping = {
4090 (inquiry)DB_length, /*mp_length*/
4091 (binaryfunc)DB_subscript, /*mp_subscript*/
4092 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4093};
4094
4095
4096static PyMethodDef DBCursor_methods[] = {
4097 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4098 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4099 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4100 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4101 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4102 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4103 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4104 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4105 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4106 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4107 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4108 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4109 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4110 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4111 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00004112 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004113 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004114 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4115 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4116 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4117 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4118 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4119 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4120 {NULL, NULL} /* sentinel */
4121};
4122
4123
4124static PyMethodDef DBEnv_methods[] = {
4125 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4126 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4127 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004128#if (DBVER >= 41)
4129 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4130 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4131 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4132#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004133#if (DBVER >= 40)
4134 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4135#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004136 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004137 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4138 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4139#if (DBVER >= 32)
4140 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4141#endif
4142 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4143 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4144 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4145 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4146 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4147#if (DBVER >= 32)
4148 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4149 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4150 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4151#endif
4152 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4153 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4154 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4155 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4156 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4157 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4158 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4159 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4160 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4161 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4162 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4163 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4164 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4165 {NULL, NULL} /* sentinel */
4166};
4167
4168
4169static PyMethodDef DBTxn_methods[] = {
4170 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4171 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4172 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4173 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4174 {NULL, NULL} /* sentinel */
4175};
4176
4177
4178static PyObject*
4179DB_getattr(DBObject* self, char *name)
4180{
4181 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4182}
4183
4184
4185static PyObject*
4186DBEnv_getattr(DBEnvObject* self, char *name)
4187{
4188 if (!strcmp(name, "db_home")) {
4189 CHECK_ENV_NOT_CLOSED(self);
4190 if (self->db_env->db_home == NULL) {
4191 RETURN_NONE();
4192 }
4193 return PyString_FromString(self->db_env->db_home);
4194 }
4195
4196 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4197}
4198
4199
4200static PyObject*
4201DBCursor_getattr(DBCursorObject* self, char *name)
4202{
4203 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4204}
4205
4206static PyObject*
4207DBTxn_getattr(DBTxnObject* self, char *name)
4208{
4209 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4210}
4211
4212static PyObject*
4213DBLock_getattr(DBLockObject* self, char *name)
4214{
4215 return NULL;
4216}
4217
4218statichere PyTypeObject DB_Type = {
4219 PyObject_HEAD_INIT(NULL)
4220 0, /*ob_size*/
4221 "DB", /*tp_name*/
4222 sizeof(DBObject), /*tp_basicsize*/
4223 0, /*tp_itemsize*/
4224 /* methods */
4225 (destructor)DB_dealloc, /*tp_dealloc*/
4226 0, /*tp_print*/
4227 (getattrfunc)DB_getattr, /*tp_getattr*/
4228 0, /*tp_setattr*/
4229 0, /*tp_compare*/
4230 0, /*tp_repr*/
4231 0, /*tp_as_number*/
4232 0, /*tp_as_sequence*/
4233 &DB_mapping,/*tp_as_mapping*/
4234 0, /*tp_hash*/
4235};
4236
4237
4238statichere PyTypeObject DBCursor_Type = {
4239 PyObject_HEAD_INIT(NULL)
4240 0, /*ob_size*/
4241 "DBCursor", /*tp_name*/
4242 sizeof(DBCursorObject), /*tp_basicsize*/
4243 0, /*tp_itemsize*/
4244 /* methods */
4245 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4246 0, /*tp_print*/
4247 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4248 0, /*tp_setattr*/
4249 0, /*tp_compare*/
4250 0, /*tp_repr*/
4251 0, /*tp_as_number*/
4252 0, /*tp_as_sequence*/
4253 0, /*tp_as_mapping*/
4254 0, /*tp_hash*/
4255};
4256
4257
4258statichere PyTypeObject DBEnv_Type = {
4259 PyObject_HEAD_INIT(NULL)
4260 0, /*ob_size*/
4261 "DBEnv", /*tp_name*/
4262 sizeof(DBEnvObject), /*tp_basicsize*/
4263 0, /*tp_itemsize*/
4264 /* methods */
4265 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4266 0, /*tp_print*/
4267 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4268 0, /*tp_setattr*/
4269 0, /*tp_compare*/
4270 0, /*tp_repr*/
4271 0, /*tp_as_number*/
4272 0, /*tp_as_sequence*/
4273 0, /*tp_as_mapping*/
4274 0, /*tp_hash*/
4275};
4276
4277statichere PyTypeObject DBTxn_Type = {
4278 PyObject_HEAD_INIT(NULL)
4279 0, /*ob_size*/
4280 "DBTxn", /*tp_name*/
4281 sizeof(DBTxnObject), /*tp_basicsize*/
4282 0, /*tp_itemsize*/
4283 /* methods */
4284 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4285 0, /*tp_print*/
4286 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4287 0, /*tp_setattr*/
4288 0, /*tp_compare*/
4289 0, /*tp_repr*/
4290 0, /*tp_as_number*/
4291 0, /*tp_as_sequence*/
4292 0, /*tp_as_mapping*/
4293 0, /*tp_hash*/
4294};
4295
4296
4297statichere PyTypeObject DBLock_Type = {
4298 PyObject_HEAD_INIT(NULL)
4299 0, /*ob_size*/
4300 "DBLock", /*tp_name*/
4301 sizeof(DBLockObject), /*tp_basicsize*/
4302 0, /*tp_itemsize*/
4303 /* methods */
4304 (destructor)DBLock_dealloc, /*tp_dealloc*/
4305 0, /*tp_print*/
4306 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4307 0, /*tp_setattr*/
4308 0, /*tp_compare*/
4309 0, /*tp_repr*/
4310 0, /*tp_as_number*/
4311 0, /*tp_as_sequence*/
4312 0, /*tp_as_mapping*/
4313 0, /*tp_hash*/
4314};
4315
4316
4317/* --------------------------------------------------------------------- */
4318/* Module-level functions */
4319
4320static PyObject*
4321DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4322{
4323 PyObject* dbenvobj = NULL;
4324 int flags = 0;
4325 char* kwnames[] = { "dbEnv", "flags", NULL};
4326
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004327 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4328 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004329 return NULL;
4330 if (dbenvobj == Py_None)
4331 dbenvobj = NULL;
4332 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4333 makeTypeError("DBEnv", dbenvobj);
4334 return NULL;
4335 }
4336
4337 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4338}
4339
4340
4341static PyObject*
4342DBEnv_construct(PyObject* self, PyObject* args)
4343{
4344 int flags = 0;
4345 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4346 return (PyObject* )newDBEnvObject(flags);
4347}
4348
4349
4350static char bsddb_version_doc[] =
4351"Returns a tuple of major, minor, and patch release numbers of the\n\
4352underlying DB library.";
4353
4354static PyObject*
4355bsddb_version(PyObject* self, PyObject* args)
4356{
4357 int major, minor, patch;
4358
4359 if (!PyArg_ParseTuple(args, ":version"))
4360 return NULL;
4361 db_version(&major, &minor, &patch);
4362 return Py_BuildValue("(iii)", major, minor, patch);
4363}
4364
4365
4366/* List of functions defined in the module */
4367
4368static PyMethodDef bsddb_methods[] = {
4369 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4370 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4371 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4372 {NULL, NULL} /* sentinel */
4373};
4374
4375
4376/* --------------------------------------------------------------------- */
4377/* Module initialization */
4378
4379
4380/* Convenience routine to export an integer value.
4381 * Errors are silently ignored, for better or for worse...
4382 */
4383#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4384
Gregory P. Smith41631e82003-09-21 00:08:14 +00004385#define MODULE_NAME_MAX_LEN 11
4386static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004387
4388DL_EXPORT(void) init_bsddb(void)
4389{
4390 PyObject* m;
4391 PyObject* d;
4392 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4393 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4394 PyObject* cvsid_s = PyString_FromString( rcs_id );
4395
4396 /* Initialize the type of the new type objects here; doing it here
4397 is required for portability to Windows without requiring C++. */
4398 DB_Type.ob_type = &PyType_Type;
4399 DBCursor_Type.ob_type = &PyType_Type;
4400 DBEnv_Type.ob_type = &PyType_Type;
4401 DBTxn_Type.ob_type = &PyType_Type;
4402 DBLock_Type.ob_type = &PyType_Type;
4403
4404
Mark Hammonda69d4092003-04-22 23:13:27 +00004405#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004406 /* Save the current interpreter, so callbacks can do the right thing. */
4407 _db_interpreterState = PyThreadState_Get()->interp;
4408#endif
4409
4410 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00004411 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004412
4413 /* Add some symbolic constants to the module */
4414 d = PyModule_GetDict(m);
4415 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4416 PyDict_SetItemString(d, "cvsid", cvsid_s);
4417 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4418 Py_DECREF(pybsddb_version_s);
4419 pybsddb_version_s = NULL;
4420 Py_DECREF(cvsid_s);
4421 cvsid_s = NULL;
4422 Py_DECREF(db_version_s);
4423 db_version_s = NULL;
4424
4425 ADD_INT(d, DB_VERSION_MAJOR);
4426 ADD_INT(d, DB_VERSION_MINOR);
4427 ADD_INT(d, DB_VERSION_PATCH);
4428
4429 ADD_INT(d, DB_MAX_PAGES);
4430 ADD_INT(d, DB_MAX_RECORDS);
4431
Gregory P. Smith41631e82003-09-21 00:08:14 +00004432#if (DBVER >= 42)
4433 ADD_INT(d, DB_RPCCLIENT);
4434#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004435 ADD_INT(d, DB_CLIENT);
Gregory P. Smith41631e82003-09-21 00:08:14 +00004436 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
4437 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
4438#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004439 ADD_INT(d, DB_XA_CREATE);
4440
4441 ADD_INT(d, DB_CREATE);
4442 ADD_INT(d, DB_NOMMAP);
4443 ADD_INT(d, DB_THREAD);
4444
4445 ADD_INT(d, DB_FORCE);
4446 ADD_INT(d, DB_INIT_CDB);
4447 ADD_INT(d, DB_INIT_LOCK);
4448 ADD_INT(d, DB_INIT_LOG);
4449 ADD_INT(d, DB_INIT_MPOOL);
4450 ADD_INT(d, DB_INIT_TXN);
4451#if (DBVER >= 32)
4452 ADD_INT(d, DB_JOINENV);
4453#endif
4454
4455 ADD_INT(d, DB_RECOVER);
4456 ADD_INT(d, DB_RECOVER_FATAL);
4457 ADD_INT(d, DB_TXN_NOSYNC);
4458 ADD_INT(d, DB_USE_ENVIRON);
4459 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4460
4461 ADD_INT(d, DB_LOCKDOWN);
4462 ADD_INT(d, DB_PRIVATE);
4463 ADD_INT(d, DB_SYSTEM_MEM);
4464
4465 ADD_INT(d, DB_TXN_SYNC);
4466 ADD_INT(d, DB_TXN_NOWAIT);
4467
4468 ADD_INT(d, DB_EXCL);
4469 ADD_INT(d, DB_FCNTL_LOCKING);
4470 ADD_INT(d, DB_ODDFILESIZE);
4471 ADD_INT(d, DB_RDWRMASTER);
4472 ADD_INT(d, DB_RDONLY);
4473 ADD_INT(d, DB_TRUNCATE);
4474#if (DBVER >= 32)
4475 ADD_INT(d, DB_EXTENT);
4476 ADD_INT(d, DB_CDB_ALLDB);
4477 ADD_INT(d, DB_VERIFY);
4478#endif
4479 ADD_INT(d, DB_UPGRADE);
4480
4481 ADD_INT(d, DB_AGGRESSIVE);
4482 ADD_INT(d, DB_NOORDERCHK);
4483 ADD_INT(d, DB_ORDERCHKONLY);
4484 ADD_INT(d, DB_PR_PAGE);
4485#if ! (DBVER >= 33)
4486 ADD_INT(d, DB_VRFY_FLAGMASK);
4487 ADD_INT(d, DB_PR_HEADERS);
4488#endif
4489 ADD_INT(d, DB_PR_RECOVERYTEST);
4490 ADD_INT(d, DB_SALVAGE);
4491
4492 ADD_INT(d, DB_LOCK_NORUN);
4493 ADD_INT(d, DB_LOCK_DEFAULT);
4494 ADD_INT(d, DB_LOCK_OLDEST);
4495 ADD_INT(d, DB_LOCK_RANDOM);
4496 ADD_INT(d, DB_LOCK_YOUNGEST);
4497#if (DBVER >= 33)
4498 ADD_INT(d, DB_LOCK_MAXLOCKS);
4499 ADD_INT(d, DB_LOCK_MINLOCKS);
4500 ADD_INT(d, DB_LOCK_MINWRITE);
4501#endif
4502
4503
4504#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004505 /* docs say to use zero instead */
4506 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004507#else
4508 ADD_INT(d, DB_LOCK_CONFLICT);
4509#endif
4510
4511 ADD_INT(d, DB_LOCK_DUMP);
4512 ADD_INT(d, DB_LOCK_GET);
4513 ADD_INT(d, DB_LOCK_INHERIT);
4514 ADD_INT(d, DB_LOCK_PUT);
4515 ADD_INT(d, DB_LOCK_PUT_ALL);
4516 ADD_INT(d, DB_LOCK_PUT_OBJ);
4517
4518 ADD_INT(d, DB_LOCK_NG);
4519 ADD_INT(d, DB_LOCK_READ);
4520 ADD_INT(d, DB_LOCK_WRITE);
4521 ADD_INT(d, DB_LOCK_NOWAIT);
4522#if (DBVER >= 32)
4523 ADD_INT(d, DB_LOCK_WAIT);
4524#endif
4525 ADD_INT(d, DB_LOCK_IWRITE);
4526 ADD_INT(d, DB_LOCK_IREAD);
4527 ADD_INT(d, DB_LOCK_IWR);
4528#if (DBVER >= 33)
4529 ADD_INT(d, DB_LOCK_DIRTY);
4530 ADD_INT(d, DB_LOCK_WWRITE);
4531#endif
4532
4533 ADD_INT(d, DB_LOCK_RECORD);
4534 ADD_INT(d, DB_LOCK_UPGRADE);
4535#if (DBVER >= 32)
4536 ADD_INT(d, DB_LOCK_SWITCH);
4537#endif
4538#if (DBVER >= 33)
4539 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4540#endif
4541
4542 ADD_INT(d, DB_LOCK_NOWAIT);
4543 ADD_INT(d, DB_LOCK_RECORD);
4544 ADD_INT(d, DB_LOCK_UPGRADE);
4545
4546#if (DBVER >= 33)
4547 ADD_INT(d, DB_LSTAT_ABORTED);
4548 ADD_INT(d, DB_LSTAT_ERR);
4549 ADD_INT(d, DB_LSTAT_FREE);
4550 ADD_INT(d, DB_LSTAT_HELD);
4551#if (DBVER == 33)
4552 ADD_INT(d, DB_LSTAT_NOGRANT);
4553#endif
4554 ADD_INT(d, DB_LSTAT_PENDING);
4555 ADD_INT(d, DB_LSTAT_WAITING);
4556#endif
4557
4558 ADD_INT(d, DB_ARCH_ABS);
4559 ADD_INT(d, DB_ARCH_DATA);
4560 ADD_INT(d, DB_ARCH_LOG);
4561
4562 ADD_INT(d, DB_BTREE);
4563 ADD_INT(d, DB_HASH);
4564 ADD_INT(d, DB_RECNO);
4565 ADD_INT(d, DB_QUEUE);
4566 ADD_INT(d, DB_UNKNOWN);
4567
4568 ADD_INT(d, DB_DUP);
4569 ADD_INT(d, DB_DUPSORT);
4570 ADD_INT(d, DB_RECNUM);
4571 ADD_INT(d, DB_RENUMBER);
4572 ADD_INT(d, DB_REVSPLITOFF);
4573 ADD_INT(d, DB_SNAPSHOT);
4574
4575 ADD_INT(d, DB_JOIN_NOSORT);
4576
4577 ADD_INT(d, DB_AFTER);
4578 ADD_INT(d, DB_APPEND);
4579 ADD_INT(d, DB_BEFORE);
4580 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004581#if (DBVER >= 41)
4582 _addIntToDict(d, "DB_CHECKPOINT", 0);
4583#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004584 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004585 ADD_INT(d, DB_CURLSN);
4586#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00004587#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004588 ADD_INT(d, DB_COMMIT);
4589#endif
4590 ADD_INT(d, DB_CONSUME);
4591#if (DBVER >= 32)
4592 ADD_INT(d, DB_CONSUME_WAIT);
4593#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004594 ADD_INT(d, DB_CURRENT);
4595#if (DBVER >= 33)
4596 ADD_INT(d, DB_FAST_STAT);
4597#endif
4598 ADD_INT(d, DB_FIRST);
4599 ADD_INT(d, DB_FLUSH);
4600 ADD_INT(d, DB_GET_BOTH);
4601 ADD_INT(d, DB_GET_RECNO);
4602 ADD_INT(d, DB_JOIN_ITEM);
4603 ADD_INT(d, DB_KEYFIRST);
4604 ADD_INT(d, DB_KEYLAST);
4605 ADD_INT(d, DB_LAST);
4606 ADD_INT(d, DB_NEXT);
4607 ADD_INT(d, DB_NEXT_DUP);
4608 ADD_INT(d, DB_NEXT_NODUP);
4609 ADD_INT(d, DB_NODUPDATA);
4610 ADD_INT(d, DB_NOOVERWRITE);
4611 ADD_INT(d, DB_NOSYNC);
4612 ADD_INT(d, DB_POSITION);
4613 ADD_INT(d, DB_PREV);
4614 ADD_INT(d, DB_PREV_NODUP);
4615 ADD_INT(d, DB_RECORDCOUNT);
4616 ADD_INT(d, DB_SET);
4617 ADD_INT(d, DB_SET_RANGE);
4618 ADD_INT(d, DB_SET_RECNO);
4619 ADD_INT(d, DB_WRITECURSOR);
4620
4621 ADD_INT(d, DB_OPFLAGS_MASK);
4622 ADD_INT(d, DB_RMW);
4623#if (DBVER >= 33)
4624 ADD_INT(d, DB_DIRTY_READ);
4625 ADD_INT(d, DB_MULTIPLE);
4626 ADD_INT(d, DB_MULTIPLE_KEY);
4627#endif
4628
4629#if (DBVER >= 33)
4630 ADD_INT(d, DB_DONOTINDEX);
4631#endif
4632
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004633#if (DBVER >= 41)
4634 _addIntToDict(d, "DB_INCOMPLETE", 0);
4635#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004636 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004637#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004638 ADD_INT(d, DB_KEYEMPTY);
4639 ADD_INT(d, DB_KEYEXIST);
4640 ADD_INT(d, DB_LOCK_DEADLOCK);
4641 ADD_INT(d, DB_LOCK_NOTGRANTED);
4642 ADD_INT(d, DB_NOSERVER);
4643 ADD_INT(d, DB_NOSERVER_HOME);
4644 ADD_INT(d, DB_NOSERVER_ID);
4645 ADD_INT(d, DB_NOTFOUND);
4646 ADD_INT(d, DB_OLD_VERSION);
4647 ADD_INT(d, DB_RUNRECOVERY);
4648 ADD_INT(d, DB_VERIFY_BAD);
4649#if (DBVER >= 33)
4650 ADD_INT(d, DB_PAGE_NOTFOUND);
4651 ADD_INT(d, DB_SECONDARY_BAD);
4652#endif
4653#if (DBVER >= 40)
4654 ADD_INT(d, DB_STAT_CLEAR);
4655 ADD_INT(d, DB_REGION_INIT);
4656 ADD_INT(d, DB_NOLOCKING);
4657 ADD_INT(d, DB_YIELDCPU);
4658 ADD_INT(d, DB_PANIC_ENVIRONMENT);
4659 ADD_INT(d, DB_NOPANIC);
4660#endif
4661
Gregory P. Smith41631e82003-09-21 00:08:14 +00004662#if (DBVER >= 42)
4663 ADD_INT(d, DB_TIME_NOTGRANTED);
4664 ADD_INT(d, DB_TXN_NOT_DURABLE);
4665 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
4666 ADD_INT(d, DB_LOG_AUTOREMOVE);
4667 ADD_INT(d, DB_DIRECT_LOG);
4668 ADD_INT(d, DB_DIRECT_DB);
4669 ADD_INT(d, DB_INIT_REP);
4670 ADD_INT(d, DB_ENCRYPT);
4671 ADD_INT(d, DB_CHKSUM);
4672#endif
4673
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004674#if (DBVER >= 41)
4675 ADD_INT(d, DB_ENCRYPT_AES);
4676 ADD_INT(d, DB_AUTO_COMMIT);
4677#else
4678 /* allow berkeleydb 4.1 aware apps to run on older versions */
4679 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
4680#endif
4681
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004682 ADD_INT(d, EINVAL);
4683 ADD_INT(d, EACCES);
4684 ADD_INT(d, ENOSPC);
4685 ADD_INT(d, ENOMEM);
4686 ADD_INT(d, EAGAIN);
4687 ADD_INT(d, EBUSY);
4688 ADD_INT(d, EEXIST);
4689 ADD_INT(d, ENOENT);
4690 ADD_INT(d, EPERM);
4691
Barry Warsaw1baa9822003-03-31 19:51:29 +00004692#if (DBVER >= 40)
4693 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
4694 ADD_INT(d, DB_SET_TXN_TIMEOUT);
4695#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004696
4697 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004698 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004699 PyDict_SetItemString(d, "DBError", DBError);
4700
4701 /* Some magic to make DBNotFoundError derive from both DBError and
4702 KeyError, since the API only supports using one base class. */
4703 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
4704 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
4705 Py_file_input, d, d);
4706 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
4707 PyDict_DelItemString(d, "KeyError");
4708
4709
4710 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004711#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004712 PyDict_SetItemString(d, #name, name)
4713
4714#if !INCOMPLETE_IS_WARNING
4715 MAKE_EX(DBIncompleteError);
4716#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00004717 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004718 MAKE_EX(DBKeyEmptyError);
4719 MAKE_EX(DBKeyExistError);
4720 MAKE_EX(DBLockDeadlockError);
4721 MAKE_EX(DBLockNotGrantedError);
4722 MAKE_EX(DBOldVersionError);
4723 MAKE_EX(DBRunRecoveryError);
4724 MAKE_EX(DBVerifyBadError);
4725 MAKE_EX(DBNoServerError);
4726 MAKE_EX(DBNoServerHomeError);
4727 MAKE_EX(DBNoServerIDError);
4728#if (DBVER >= 33)
4729 MAKE_EX(DBPageNotFoundError);
4730 MAKE_EX(DBSecondaryBadError);
4731#endif
4732
4733 MAKE_EX(DBInvalidArgError);
4734 MAKE_EX(DBAccessError);
4735 MAKE_EX(DBNoSpaceError);
4736 MAKE_EX(DBNoMemoryError);
4737 MAKE_EX(DBAgainError);
4738 MAKE_EX(DBBusyError);
4739 MAKE_EX(DBFileExistsError);
4740 MAKE_EX(DBNoSuchFileError);
4741 MAKE_EX(DBPermissionsError);
4742
4743#undef MAKE_EX
4744
4745 /* Check for errors */
4746 if (PyErr_Occurred()) {
4747 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004748 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004749 }
4750}
Gregory P. Smith41631e82003-09-21 00:08:14 +00004751
4752/* allow this module to be named _pybsddb so that it can be installed
4753 * and imported on top of python >= 2.3 that includes its own older
4754 * copy of the library named _bsddb without importing the old version. */
4755DL_EXPORT(void) init_pybsddb(void)
4756{
4757 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
4758 init_bsddb();
4759}