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