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