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