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