blob: 5834d51259a5706b3f8b2bc6fa2d8f506a42ab2e [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
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +000078#define PY_BSDDB_VERSION "3.4.2"
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000079
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
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +000083static char *orig_rcs_id = "/Id: _db.c,v 1.48 2002/11/21 19:11:19 greg Exp /";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000084static 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
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001015 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1016 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1017 * The global interepreter lock is not initialized until the first
1018 * thread is created using thread.start_new_thread() or fork() is
1019 * called. that would cause the ALLOW_THREADS here to segfault due
1020 * to a null pointer reference if no threads or child processes
1021 * have been created. This works around that and is a no-op if
1022 * threads have already been initialized.
1023 * (see pybsddb-users mailing list post on 2002-08-07)
1024 */
1025 PyEval_InitThreads();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001026 MYDB_BEGIN_ALLOW_THREADS;
1027 err = self->db->associate(self->db,
1028 secondaryDB->db,
1029 _db_associateCallback,
1030 flags);
1031 MYDB_END_ALLOW_THREADS;
1032
1033 if (err) {
1034 Py_DECREF(self->associateCallback);
1035 self->associateCallback = NULL;
1036 secondaryDB->primaryDBType = 0;
1037 }
1038
1039 RETURN_IF_ERR();
1040 RETURN_NONE();
1041}
1042
1043
1044#endif
1045
1046
1047static PyObject*
1048DB_close(DBObject* self, PyObject* args)
1049{
1050 int err, flags=0;
1051 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1052 return NULL;
1053 if (self->db != NULL) {
1054 if (self->myenvobj)
1055 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1056 MYDB_BEGIN_ALLOW_THREADS;
1057 err = self->db->close(self->db, flags);
1058 MYDB_END_ALLOW_THREADS;
1059 self->db = NULL;
1060 RETURN_IF_ERR();
1061 }
1062 RETURN_NONE();
1063}
1064
1065
1066#if (DBVER >= 32)
1067static PyObject*
1068_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1069{
1070 int err, flags=0, type;
1071 PyObject* txnobj = NULL;
1072 PyObject* retval = NULL;
1073 DBT key, data;
1074 DB_TXN *txn = NULL;
1075 char* kwnames[] = { "txn", "flags", NULL };
1076
1077 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1078 &txnobj, &flags))
1079 return NULL;
1080
1081 CHECK_DB_NOT_CLOSED(self);
1082 type = _DB_get_type(self);
1083 if (type == -1)
1084 return NULL;
1085 if (type != DB_QUEUE) {
1086 PyErr_SetString(PyExc_TypeError, "Consume methods only allowed for Queue DB's");
1087 return NULL;
1088 }
1089 if (!checkTxnObj(txnobj, &txn))
1090 return NULL;
1091
1092 CLEAR_DBT(key);
1093 CLEAR_DBT(data);
1094 if (CHECK_DBFLAG(self, DB_THREAD)) {
1095 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1096 data.flags = DB_DBT_MALLOC;
1097 key.flags = DB_DBT_MALLOC;
1098 }
1099
1100 MYDB_BEGIN_ALLOW_THREADS;
1101 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1102 MYDB_END_ALLOW_THREADS;
1103
1104 if ((err == DB_NOTFOUND) && self->getReturnsNone) {
1105 err = 0;
1106 Py_INCREF(Py_None);
1107 retval = Py_None;
1108 }
1109 else if (!err) {
1110 retval = Py_BuildValue("s#s#", key.data, key.size, data.data, data.size);
1111 FREE_DBT(key);
1112 FREE_DBT(data);
1113 }
1114
1115 RETURN_IF_ERR();
1116 return retval;
1117}
1118
1119static PyObject*
1120DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1121{
1122 return _DB_consume(self, args, kwargs, DB_CONSUME);
1123}
1124
1125static PyObject*
1126DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1127{
1128 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1129}
1130#endif
1131
1132
1133
1134static PyObject*
1135DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1136{
1137 int err, flags=0;
1138 DBC* dbc;
1139 PyObject* txnobj = NULL;
1140 DB_TXN *txn = NULL;
1141 char* kwnames[] = { "txn", "flags", NULL };
1142
1143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1144 &txnobj, &flags))
1145 return NULL;
1146 CHECK_DB_NOT_CLOSED(self);
1147 if (!checkTxnObj(txnobj, &txn))
1148 return NULL;
1149
1150 MYDB_BEGIN_ALLOW_THREADS;
1151 err = self->db->cursor(self->db, txn, &dbc, flags);
1152 MYDB_END_ALLOW_THREADS;
1153 RETURN_IF_ERR();
1154 return (PyObject*) newDBCursorObject(dbc, self);
1155}
1156
1157
1158static PyObject*
1159DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1160{
1161 PyObject* txnobj = NULL;
1162 int flags = 0;
1163 PyObject* keyobj;
1164 DBT key;
1165 DB_TXN *txn = NULL;
1166 char* kwnames[] = { "key", "txn", "flags", NULL };
1167
1168 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1169 &keyobj, &txnobj, &flags))
1170 return NULL;
1171 CHECK_DB_NOT_CLOSED(self);
1172 if (!make_key_dbt(self, keyobj, &key, NULL))
1173 return NULL;
1174 if (!checkTxnObj(txnobj, &txn))
1175 return NULL;
1176
1177 if (-1 == _DB_delete(self, txn, &key, 0))
1178 return NULL;
1179
1180 FREE_DBT(key);
1181 RETURN_NONE();
1182}
1183
1184
1185static PyObject*
1186DB_fd(DBObject* self, PyObject* args)
1187{
1188 int err, the_fd;
1189
1190 if (!PyArg_ParseTuple(args,":fd"))
1191 return NULL;
1192 CHECK_DB_NOT_CLOSED(self);
1193
1194 MYDB_BEGIN_ALLOW_THREADS;
1195 err = self->db->fd(self->db, &the_fd);
1196 MYDB_END_ALLOW_THREADS;
1197 RETURN_IF_ERR();
1198 return PyInt_FromLong(the_fd);
1199}
1200
1201
1202static PyObject*
1203DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1204{
1205 int err, flags=0;
1206 PyObject* txnobj = NULL;
1207 PyObject* keyobj;
1208 PyObject* dfltobj = NULL;
1209 PyObject* retval = NULL;
1210 int dlen = -1;
1211 int doff = -1;
1212 DBT key, data;
1213 DB_TXN *txn = NULL;
1214 char* kwnames[] = { "key", "default", "txn", "flags", "dlen", "doff", NULL };
1215
1216 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1217 &keyobj, &dfltobj, &txnobj, &flags, &dlen, &doff))
1218 return NULL;
1219
1220 CHECK_DB_NOT_CLOSED(self);
1221 if (!make_key_dbt(self, keyobj, &key, &flags))
1222 return NULL;
1223 if (!checkTxnObj(txnobj, &txn))
1224 return NULL;
1225
1226 CLEAR_DBT(data);
1227 if (CHECK_DBFLAG(self, DB_THREAD)) {
1228 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1229 data.flags = DB_DBT_MALLOC;
1230 }
1231 if (!add_partial_dbt(&data, dlen, doff))
1232 return NULL;
1233
1234 MYDB_BEGIN_ALLOW_THREADS;
1235 err = self->db->get(self->db, txn, &key, &data, flags);
1236 MYDB_END_ALLOW_THREADS;
1237
1238 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1239 err = 0;
1240 Py_INCREF(dfltobj);
1241 retval = dfltobj;
1242 }
1243 else if ((err == DB_NOTFOUND) && self->getReturnsNone) {
1244 err = 0;
1245 Py_INCREF(Py_None);
1246 retval = Py_None;
1247 }
1248 else if (!err) {
1249 if (flags & DB_SET_RECNO) /* return both key and data */
1250 retval = Py_BuildValue("s#s#", key.data, key.size, data.data, data.size);
1251 else /* return just the data */
1252 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1253 FREE_DBT(key);
1254 FREE_DBT(data);
1255 }
1256
1257 RETURN_IF_ERR();
1258 return retval;
1259}
1260
1261
1262/* Return size of entry */
1263static PyObject*
1264DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1265{
1266 int err, flags=0;
1267 PyObject* txnobj = NULL;
1268 PyObject* keyobj;
1269 PyObject* retval = NULL;
1270 DBT key, data;
1271 DB_TXN *txn = NULL;
1272 char* kwnames[] = { "key", "txn", NULL };
1273
1274 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1275 &keyobj, &txnobj))
1276 return NULL;
1277 CHECK_DB_NOT_CLOSED(self);
1278 if (!make_key_dbt(self, keyobj, &key, &flags))
1279 return NULL;
1280 if (!checkTxnObj(txnobj, &txn))
1281 return NULL;
1282 CLEAR_DBT(data);
1283
1284 /* We don't allocate any memory, forcing a ENOMEM error and thus
1285 getting the record size. */
1286 data.flags = DB_DBT_USERMEM;
1287 data.ulen = 0;
1288 MYDB_BEGIN_ALLOW_THREADS;
1289 err = self->db->get(self->db, txn, &key, &data, flags);
1290 MYDB_END_ALLOW_THREADS;
1291 if (err == ENOMEM) {
1292 retval = PyInt_FromLong((long)data.size);
1293 err = 0;
1294 }
1295
1296 FREE_DBT(key);
1297 FREE_DBT(data);
1298 RETURN_IF_ERR();
1299 return retval;
1300}
1301
1302
1303static PyObject*
1304DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1305{
1306 int err, flags=0;
1307 PyObject* txnobj = NULL;
1308 PyObject* keyobj;
1309 PyObject* dataobj;
1310 PyObject* retval = NULL;
1311 DBT key, data;
1312 DB_TXN *txn = NULL;
1313 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1314
1315
1316 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1317 &keyobj, &dataobj, &txnobj, &flags))
1318 return NULL;
1319
1320 CHECK_DB_NOT_CLOSED(self);
1321 if (!make_key_dbt(self, keyobj, &key, NULL))
1322 return NULL;
1323 if (!make_dbt(dataobj, &data))
1324 return NULL;
1325 if (!checkTxnObj(txnobj, &txn))
1326 return NULL;
1327
1328 flags |= DB_GET_BOTH;
1329
1330 if (CHECK_DBFLAG(self, DB_THREAD)) {
1331 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1332 data.flags = DB_DBT_MALLOC;
1333 /* TODO: Is this flag needed? We're passing a data object that should
1334 match what's in the DB, so there should be no need to malloc.
1335 We run the risk of freeing something twice! Check this. */
1336 }
1337
1338 MYDB_BEGIN_ALLOW_THREADS;
1339 err = self->db->get(self->db, txn, &key, &data, flags);
1340 MYDB_END_ALLOW_THREADS;
1341
1342 if ((err == DB_NOTFOUND) && self->getReturnsNone) {
1343 err = 0;
1344 Py_INCREF(Py_None);
1345 retval = Py_None;
1346 }
1347 else if (!err) {
1348 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1349 FREE_DBT(data); /* Only if retrieval was successful */
1350 }
1351
1352 FREE_DBT(key);
1353 RETURN_IF_ERR();
1354 return retval;
1355}
1356
1357
1358static PyObject*
1359DB_get_byteswapped(DBObject* self, PyObject* args)
1360{
1361#if (DBVER >= 33)
1362 int err = 0;
1363#endif
1364 int retval = -1;
1365
1366 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1367 return NULL;
1368 CHECK_DB_NOT_CLOSED(self);
1369
1370#if (DBVER >= 33)
1371 MYDB_BEGIN_ALLOW_THREADS;
1372 err = self->db->get_byteswapped(self->db, &retval);
1373 MYDB_END_ALLOW_THREADS;
1374 RETURN_IF_ERR();
1375#else
1376 MYDB_BEGIN_ALLOW_THREADS;
1377 retval = self->db->get_byteswapped(self->db);
1378 MYDB_END_ALLOW_THREADS;
1379#endif
1380 return PyInt_FromLong(retval);
1381}
1382
1383
1384static PyObject*
1385DB_get_type(DBObject* self, PyObject* args)
1386{
1387 int type;
1388
1389 if (!PyArg_ParseTuple(args,":get_type"))
1390 return NULL;
1391 CHECK_DB_NOT_CLOSED(self);
1392
1393 MYDB_BEGIN_ALLOW_THREADS;
1394 type = _DB_get_type(self);
1395 MYDB_END_ALLOW_THREADS;
1396 if (type == -1)
1397 return NULL;
1398 return PyInt_FromLong(type);
1399}
1400
1401
1402static PyObject*
1403DB_join(DBObject* self, PyObject* args)
1404{
1405 int err, flags=0;
1406 int length, x;
1407 PyObject* cursorsObj;
1408 DBC** cursors;
1409 DBC* dbc;
1410
1411
1412 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1413 return NULL;
1414
1415 CHECK_DB_NOT_CLOSED(self);
1416
1417 if (!PySequence_Check(cursorsObj)) {
1418 PyErr_SetString(PyExc_TypeError, "Sequence of DBCursor objects expected");
1419 return NULL;
1420 }
1421
1422 length = PyObject_Length(cursorsObj);
1423 cursors = malloc((length+1) * sizeof(DBC*));
1424 cursors[length] = NULL;
1425 for (x=0; x<length; x++) {
1426 PyObject* item = PySequence_GetItem(cursorsObj, x);
1427 if (!DBCursorObject_Check(item)) {
1428 PyErr_SetString(PyExc_TypeError, "Sequence of DBCursor objects expected");
1429 free(cursors);
1430 return NULL;
1431 }
1432 cursors[x] = ((DBCursorObject*)item)->dbc;
1433 }
1434
1435 MYDB_BEGIN_ALLOW_THREADS;
1436 err = self->db->join(self->db, cursors, &dbc, flags);
1437 MYDB_END_ALLOW_THREADS;
1438 free(cursors);
1439 RETURN_IF_ERR();
1440
1441 return (PyObject*) newDBCursorObject(dbc, self);
1442}
1443
1444
1445static PyObject*
1446DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1447{
1448 int err, flags=0;
1449 PyObject* txnobj = NULL;
1450 PyObject* keyobj;
1451 DBT key;
1452 DB_TXN *txn = NULL;
1453 DB_KEY_RANGE range;
1454 char* kwnames[] = { "key", "txn", "flags", NULL };
1455
1456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1457 &keyobj, &txnobj, &flags))
1458 return NULL;
1459 CHECK_DB_NOT_CLOSED(self);
1460 if (!make_dbt(keyobj, &key)) /* BTree only, don't need to allow for an int key */
1461 return NULL;
1462 if (!checkTxnObj(txnobj, &txn))
1463 return NULL;
1464
1465 MYDB_BEGIN_ALLOW_THREADS;
1466 err = self->db->key_range(self->db, txn, &key, &range, flags);
1467 MYDB_END_ALLOW_THREADS;
1468
1469 RETURN_IF_ERR();
1470 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1471}
1472
1473
1474static PyObject*
1475DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1476{
1477 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1478 char* filename = NULL;
1479 char* dbname = NULL;
1480 char* kwnames[] = { "filename", "dbname", "dbtype", "flags", "mode", NULL };
1481 char* kwnames2[] = { "filename", "dbtype", "flags", "mode", NULL };
1482
1483 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1484 &filename, &dbname, &type, &flags, &mode)) {
1485 PyErr_Clear();
1486 type = DB_UNKNOWN; flags = 0; mode = 0660;
1487 filename = NULL; dbname = NULL;
1488 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open", kwnames2,
1489 &filename, &type, &flags, &mode))
1490 return NULL;
1491 }
1492
1493 if (NULL == self->db) {
1494 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1495 "Cannot call open() twice for DB object"));
1496 return NULL;
1497 }
1498
1499 MYDB_BEGIN_ALLOW_THREADS;
1500 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1501 MYDB_END_ALLOW_THREADS;
1502 if (makeDBError(err)) {
1503 self->db = NULL;
1504 return NULL;
1505 }
1506
1507 self->flags = flags;
1508 RETURN_NONE();
1509}
1510
1511
1512static PyObject*
1513DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1514{
1515 int flags=0;
1516 PyObject* txnobj = NULL;
1517 int dlen = -1;
1518 int doff = -1;
1519 PyObject* keyobj, *dataobj, *retval;
1520 DBT key, data;
1521 DB_TXN *txn = NULL;
1522 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1523
1524 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1525 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1526 return NULL;
1527
1528 CHECK_DB_NOT_CLOSED(self);
1529 if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL;
1530 if (!make_dbt(dataobj, &data)) return NULL;
1531 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
1532 if (!checkTxnObj(txnobj, &txn)) return NULL;
1533
1534 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1535 FREE_DBT(key);
1536 return NULL;
1537 }
1538
1539 if (flags & DB_APPEND)
1540 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1541 else {
1542 retval = Py_None;
1543 Py_INCREF(retval);
1544 }
1545 FREE_DBT(key);
1546 return retval;
1547}
1548
1549
1550
1551static PyObject*
1552DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1553{
1554 char* filename;
1555 char* database = NULL;
1556 int err, flags=0;
1557 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1558
1559 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1560 &filename, &database, &flags))
1561 return NULL;
1562 CHECK_DB_NOT_CLOSED(self);
1563
1564 MYDB_BEGIN_ALLOW_THREADS;
1565 err = self->db->remove(self->db, filename, database, flags);
1566 MYDB_END_ALLOW_THREADS;
1567 RETURN_IF_ERR();
1568 RETURN_NONE();
1569}
1570
1571
1572
1573static PyObject*
1574DB_rename(DBObject* self, PyObject* args)
1575{
1576 char* filename;
1577 char* database;
1578 char* newname;
1579 int err, flags=0;
1580
1581 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname, &flags))
1582 return NULL;
1583 CHECK_DB_NOT_CLOSED(self);
1584
1585 MYDB_BEGIN_ALLOW_THREADS;
1586 err = self->db->rename(self->db, filename, database, newname, flags);
1587 MYDB_END_ALLOW_THREADS;
1588 RETURN_IF_ERR();
1589 RETURN_NONE();
1590}
1591
1592
1593static PyObject*
1594DB_set_bt_minkey(DBObject* self, PyObject* args)
1595{
1596 int err, minkey;
1597
1598 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1599 return NULL;
1600 CHECK_DB_NOT_CLOSED(self);
1601
1602 MYDB_BEGIN_ALLOW_THREADS;
1603 err = self->db->set_bt_minkey(self->db, minkey);
1604 MYDB_END_ALLOW_THREADS;
1605 RETURN_IF_ERR();
1606 RETURN_NONE();
1607}
1608
1609
1610static PyObject*
1611DB_set_cachesize(DBObject* self, PyObject* args)
1612{
1613 int err;
1614 int gbytes = 0, bytes = 0, ncache = 0;
1615
1616 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1617 &gbytes,&bytes,&ncache))
1618 return NULL;
1619 CHECK_DB_NOT_CLOSED(self);
1620
1621 MYDB_BEGIN_ALLOW_THREADS;
1622 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1623 MYDB_END_ALLOW_THREADS;
1624 RETURN_IF_ERR();
1625 RETURN_NONE();
1626}
1627
1628
1629static PyObject*
1630DB_set_flags(DBObject* self, PyObject* args)
1631{
1632 int err, flags;
1633
1634 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
1635 return NULL;
1636 CHECK_DB_NOT_CLOSED(self);
1637
1638 MYDB_BEGIN_ALLOW_THREADS;
1639 err = self->db->set_flags(self->db, flags);
1640 MYDB_END_ALLOW_THREADS;
1641 RETURN_IF_ERR();
1642
1643 self->setflags |= flags;
1644 RETURN_NONE();
1645}
1646
1647
1648static PyObject*
1649DB_set_h_ffactor(DBObject* self, PyObject* args)
1650{
1651 int err, ffactor;
1652
1653 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
1654 return NULL;
1655 CHECK_DB_NOT_CLOSED(self);
1656
1657 MYDB_BEGIN_ALLOW_THREADS;
1658 err = self->db->set_h_ffactor(self->db, ffactor);
1659 MYDB_END_ALLOW_THREADS;
1660 RETURN_IF_ERR();
1661 RETURN_NONE();
1662}
1663
1664
1665static PyObject*
1666DB_set_h_nelem(DBObject* self, PyObject* args)
1667{
1668 int err, nelem;
1669
1670 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
1671 return NULL;
1672 CHECK_DB_NOT_CLOSED(self);
1673
1674 MYDB_BEGIN_ALLOW_THREADS;
1675 err = self->db->set_h_nelem(self->db, nelem);
1676 MYDB_END_ALLOW_THREADS;
1677 RETURN_IF_ERR();
1678 RETURN_NONE();
1679}
1680
1681
1682static PyObject*
1683DB_set_lorder(DBObject* self, PyObject* args)
1684{
1685 int err, lorder;
1686
1687 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
1688 return NULL;
1689 CHECK_DB_NOT_CLOSED(self);
1690
1691 MYDB_BEGIN_ALLOW_THREADS;
1692 err = self->db->set_lorder(self->db, lorder);
1693 MYDB_END_ALLOW_THREADS;
1694 RETURN_IF_ERR();
1695 RETURN_NONE();
1696}
1697
1698
1699static PyObject*
1700DB_set_pagesize(DBObject* self, PyObject* args)
1701{
1702 int err, pagesize;
1703
1704 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
1705 return NULL;
1706 CHECK_DB_NOT_CLOSED(self);
1707
1708 MYDB_BEGIN_ALLOW_THREADS;
1709 err = self->db->set_pagesize(self->db, pagesize);
1710 MYDB_END_ALLOW_THREADS;
1711 RETURN_IF_ERR();
1712 RETURN_NONE();
1713}
1714
1715
1716static PyObject*
1717DB_set_re_delim(DBObject* self, PyObject* args)
1718{
1719 int err;
1720 char delim;
1721
1722 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
1723 PyErr_Clear();
1724 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
1725 return NULL;
1726 }
1727
1728 CHECK_DB_NOT_CLOSED(self);
1729
1730 MYDB_BEGIN_ALLOW_THREADS;
1731 err = self->db->set_re_delim(self->db, delim);
1732 MYDB_END_ALLOW_THREADS;
1733 RETURN_IF_ERR();
1734 RETURN_NONE();
1735}
1736
1737static PyObject*
1738DB_set_re_len(DBObject* self, PyObject* args)
1739{
1740 int err, len;
1741
1742 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
1743 return NULL;
1744 CHECK_DB_NOT_CLOSED(self);
1745
1746 MYDB_BEGIN_ALLOW_THREADS;
1747 err = self->db->set_re_len(self->db, len);
1748 MYDB_END_ALLOW_THREADS;
1749 RETURN_IF_ERR();
1750 RETURN_NONE();
1751}
1752
1753
1754static PyObject*
1755DB_set_re_pad(DBObject* self, PyObject* args)
1756{
1757 int err;
1758 char pad;
1759
1760 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
1761 PyErr_Clear();
1762 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
1763 return NULL;
1764 }
1765 CHECK_DB_NOT_CLOSED(self);
1766
1767 MYDB_BEGIN_ALLOW_THREADS;
1768 err = self->db->set_re_pad(self->db, pad);
1769 MYDB_END_ALLOW_THREADS;
1770 RETURN_IF_ERR();
1771 RETURN_NONE();
1772}
1773
1774
1775static PyObject*
1776DB_set_re_source(DBObject* self, PyObject* args)
1777{
1778 int err;
1779 char *re_source;
1780
1781 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
1782 return NULL;
1783 CHECK_DB_NOT_CLOSED(self);
1784
1785 MYDB_BEGIN_ALLOW_THREADS;
1786 err = self->db->set_re_source(self->db, re_source);
1787 MYDB_END_ALLOW_THREADS;
1788 RETURN_IF_ERR();
1789 RETURN_NONE();
1790}
1791
1792
1793#if (DBVER >= 32)
1794static PyObject*
1795DB_set_q_extentsize(DBObject* self, PyObject* args)
1796{
1797 int err;
1798 int extentsize;
1799
1800 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
1801 return NULL;
1802 CHECK_DB_NOT_CLOSED(self);
1803
1804 MYDB_BEGIN_ALLOW_THREADS;
1805 err = self->db->set_q_extentsize(self->db, extentsize);
1806 MYDB_END_ALLOW_THREADS;
1807 RETURN_IF_ERR();
1808 RETURN_NONE();
1809}
1810#endif
1811
1812static PyObject*
1813DB_stat(DBObject* self, PyObject* args)
1814{
1815 int err, flags = 0, type;
1816 void* sp;
1817 PyObject* d;
1818
1819
1820 if (!PyArg_ParseTuple(args, "|i:stat", &flags))
1821 return NULL;
1822 CHECK_DB_NOT_CLOSED(self);
1823
1824 MYDB_BEGIN_ALLOW_THREADS;
1825#if (DBVER >= 33)
1826 err = self->db->stat(self->db, &sp, flags);
1827#else
1828 err = self->db->stat(self->db, &sp, NULL, flags);
1829#endif
1830 MYDB_END_ALLOW_THREADS;
1831 RETURN_IF_ERR();
1832
1833 self->haveStat = 1;
1834
1835 /* Turn the stat structure into a dictionary */
1836 type = _DB_get_type(self);
1837 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
1838 free(sp);
1839 return NULL;
1840 }
1841
1842#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
1843#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
1844#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
1845
1846 switch (type) {
1847 case DB_HASH:
1848 MAKE_HASH_ENTRY(magic);
1849 MAKE_HASH_ENTRY(version);
1850 MAKE_HASH_ENTRY(nkeys);
1851 MAKE_HASH_ENTRY(ndata);
1852 MAKE_HASH_ENTRY(pagesize);
1853 MAKE_HASH_ENTRY(nelem);
1854 MAKE_HASH_ENTRY(ffactor);
1855 MAKE_HASH_ENTRY(buckets);
1856 MAKE_HASH_ENTRY(free);
1857 MAKE_HASH_ENTRY(bfree);
1858 MAKE_HASH_ENTRY(bigpages);
1859 MAKE_HASH_ENTRY(big_bfree);
1860 MAKE_HASH_ENTRY(overflows);
1861 MAKE_HASH_ENTRY(ovfl_free);
1862 MAKE_HASH_ENTRY(dup);
1863 MAKE_HASH_ENTRY(dup_free);
1864 break;
1865
1866 case DB_BTREE:
1867 case DB_RECNO:
1868 MAKE_BT_ENTRY(magic);
1869 MAKE_BT_ENTRY(version);
1870 MAKE_BT_ENTRY(nkeys);
1871 MAKE_BT_ENTRY(ndata);
1872 MAKE_BT_ENTRY(pagesize);
1873 MAKE_BT_ENTRY(minkey);
1874 MAKE_BT_ENTRY(re_len);
1875 MAKE_BT_ENTRY(re_pad);
1876 MAKE_BT_ENTRY(levels);
1877 MAKE_BT_ENTRY(int_pg);
1878 MAKE_BT_ENTRY(leaf_pg);
1879 MAKE_BT_ENTRY(dup_pg);
1880 MAKE_BT_ENTRY(over_pg);
1881 MAKE_BT_ENTRY(free);
1882 MAKE_BT_ENTRY(int_pgfree);
1883 MAKE_BT_ENTRY(leaf_pgfree);
1884 MAKE_BT_ENTRY(dup_pgfree);
1885 MAKE_BT_ENTRY(over_pgfree);
1886 break;
1887
1888 case DB_QUEUE:
1889 MAKE_QUEUE_ENTRY(magic);
1890 MAKE_QUEUE_ENTRY(version);
1891 MAKE_QUEUE_ENTRY(nkeys);
1892 MAKE_QUEUE_ENTRY(ndata);
1893 MAKE_QUEUE_ENTRY(pagesize);
1894 MAKE_QUEUE_ENTRY(pages);
1895 MAKE_QUEUE_ENTRY(re_len);
1896 MAKE_QUEUE_ENTRY(re_pad);
1897 MAKE_QUEUE_ENTRY(pgfree);
1898#if (DBVER == 31)
1899 MAKE_QUEUE_ENTRY(start);
1900#endif
1901 MAKE_QUEUE_ENTRY(first_recno);
1902 MAKE_QUEUE_ENTRY(cur_recno);
1903 break;
1904
1905 default:
1906 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
1907 Py_DECREF(d);
1908 d = NULL;
1909 }
1910
1911#undef MAKE_HASH_ENTRY
1912#undef MAKE_BT_ENTRY
1913#undef MAKE_QUEUE_ENTRY
1914
1915 free(sp);
1916 return d;
1917}
1918
1919static PyObject*
1920DB_sync(DBObject* self, PyObject* args)
1921{
1922 int err;
1923 int flags = 0;
1924
1925 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
1926 return NULL;
1927 CHECK_DB_NOT_CLOSED(self);
1928
1929 MYDB_BEGIN_ALLOW_THREADS;
1930 err = self->db->sync(self->db, flags);
1931 MYDB_END_ALLOW_THREADS;
1932 RETURN_IF_ERR();
1933 RETURN_NONE();
1934}
1935
1936
1937#if (DBVER >= 33)
1938static PyObject*
1939DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
1940{
1941 int err, flags=0;
1942 u_int32_t count=0;
1943 PyObject* txnobj = NULL;
1944 DB_TXN *txn = NULL;
1945 char* kwnames[] = { "txn", "flags", NULL };
1946
1947 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1948 &txnobj, &flags))
1949 return NULL;
1950 CHECK_DB_NOT_CLOSED(self);
1951 if (!checkTxnObj(txnobj, &txn))
1952 return NULL;
1953
1954 MYDB_BEGIN_ALLOW_THREADS;
1955 err = self->db->truncate(self->db, txn, &count, flags);
1956 MYDB_END_ALLOW_THREADS;
1957 RETURN_IF_ERR();
1958 return PyInt_FromLong(count);
1959}
1960#endif
1961
1962
1963static PyObject*
1964DB_upgrade(DBObject* self, PyObject* args)
1965{
1966 int err, flags=0;
1967 char *filename;
1968
1969 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
1970 return NULL;
1971 CHECK_DB_NOT_CLOSED(self);
1972
1973 MYDB_BEGIN_ALLOW_THREADS;
1974 err = self->db->upgrade(self->db, filename, flags);
1975 MYDB_END_ALLOW_THREADS;
1976 RETURN_IF_ERR();
1977 RETURN_NONE();
1978}
1979
1980
1981static PyObject*
1982DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
1983{
1984 int err, flags=0;
1985 char* fileName;
1986 char* dbName=NULL;
1987 char* outFileName=NULL;
1988 FILE* outFile=NULL;
1989 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
1990
1991 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
1992 &fileName, &dbName, &outFileName, &flags))
1993 return NULL;
1994
1995 CHECK_DB_NOT_CLOSED(self);
1996 if (outFileName)
1997 outFile = fopen(outFileName, "w");
1998
1999 MYDB_BEGIN_ALLOW_THREADS;
2000 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2001 MYDB_END_ALLOW_THREADS;
2002 if (outFileName)
2003 fclose(outFile);
2004 RETURN_IF_ERR();
2005 RETURN_NONE();
2006}
2007
2008
2009static PyObject*
2010DB_set_get_returns_none(DBObject* self, PyObject* args)
2011{
2012 int flags=0;
2013 int oldValue;
2014
2015 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2016 return NULL;
2017 CHECK_DB_NOT_CLOSED(self);
2018
2019 oldValue = self->getReturnsNone;
2020 self->getReturnsNone = flags;
2021 return PyInt_FromLong(oldValue);
2022}
2023
2024
2025/*-------------------------------------------------------------- */
2026/* Mapping and Dictionary-like access routines */
2027
2028int DB_length(DBObject* self)
2029{
2030 int err;
2031 long size = 0;
2032 int flags = 0;
2033 void* sp;
2034
2035 if (self->db == NULL) {
2036 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, "DB object has been closed"));
2037 return -1;
2038 }
2039
2040 if (self->haveStat) { /* Has the stat function been called recently? If
2041 so, we can use the cached value. */
2042 flags = DB_CACHED_COUNTS;
2043 }
2044
2045 MYDB_BEGIN_ALLOW_THREADS;
2046#if (DBVER >= 33)
2047 err = self->db->stat(self->db, &sp, flags);
2048#else
2049 err = self->db->stat(self->db, &sp, NULL, flags);
2050#endif
2051 MYDB_END_ALLOW_THREADS;
2052
2053 if (err)
2054 return -1;
2055
2056 self->haveStat = 1;
2057
2058 /* All the stat structures have matching fields upto the ndata field,
2059 so we can use any of them for the type cast */
2060 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2061 free(sp);
2062 return size;
2063}
2064
2065
2066PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2067{
2068 int err;
2069 PyObject* retval;
2070 DBT key;
2071 DBT data;
2072
2073 CHECK_DB_NOT_CLOSED(self);
2074 if (!make_key_dbt(self, keyobj, &key, NULL))
2075 return NULL;
2076
2077 CLEAR_DBT(data);
2078 if (CHECK_DBFLAG(self, DB_THREAD)) {
2079 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2080 data.flags = DB_DBT_MALLOC;
2081 }
2082 MYDB_BEGIN_ALLOW_THREADS;
2083 err = self->db->get(self->db, NULL, &key, &data, 0);
2084 MYDB_END_ALLOW_THREADS;
2085 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2086 PyErr_SetObject(PyExc_KeyError, keyobj);
2087 retval = NULL;
2088 }
2089 else if (makeDBError(err)) {
2090 retval = NULL;
2091 }
2092 else {
2093 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2094 FREE_DBT(data);
2095 }
2096
2097 FREE_DBT(key);
2098 return retval;
2099}
2100
2101
2102static int
2103DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2104{
2105 DBT key, data;
2106 int retval;
2107 int flags = 0;
2108
2109 if (self->db == NULL) {
2110 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, "DB object has been closed"));
2111 return -1;
2112 }
2113
2114 if (!make_key_dbt(self, keyobj, &key, NULL))
2115 return -1;
2116
2117 if (dataobj != NULL) {
2118 if (!make_dbt(dataobj, &data))
2119 retval = -1;
2120 else {
2121 if (self->setflags & (DB_DUP|DB_DUPSORT))
2122 flags = DB_NOOVERWRITE; /* dictionaries shouldn't have duplicate keys */
2123 retval = _DB_put(self, NULL, &key, &data, flags);
2124
2125 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2126 /* try deleting any old record that matches and then PUT it again... */
2127 _DB_delete(self, NULL, &key, 0);
2128 PyErr_Clear();
2129 retval = _DB_put(self, NULL, &key, &data, flags);
2130 }
2131 }
2132 }
2133 else {
2134 /* dataobj == NULL, so delete the key */
2135 retval = _DB_delete(self, NULL, &key, 0);
2136 }
2137 FREE_DBT(key);
2138 return retval;
2139}
2140
2141
2142static PyObject*
2143DB_has_key(DBObject* self, PyObject* args)
2144{
2145 int err;
2146 PyObject* keyobj;
2147 DBT key, data;
2148 PyObject* txnobj = NULL;
2149 DB_TXN *txn = NULL;
2150
2151 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj ))
2152 return NULL;
2153 CHECK_DB_NOT_CLOSED(self);
2154 if (!make_key_dbt(self, keyobj, &key, NULL))
2155 return NULL;
2156 if (!checkTxnObj(txnobj, &txn))
2157 return NULL;
2158
2159 /* This causes ENOMEM to be returned when the db has the key because
2160 it has a record but can't allocate a buffer for the data. This saves
2161 having to deal with data we won't be using.
2162 */
2163 CLEAR_DBT(data);
2164 data.flags = DB_DBT_USERMEM;
2165
2166 MYDB_BEGIN_ALLOW_THREADS;
2167 err = self->db->get(self->db, NULL, &key, &data, 0);
2168 MYDB_END_ALLOW_THREADS;
2169 FREE_DBT(key);
2170 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2171}
2172
2173
2174#define _KEYS_LIST 1
2175#define _VALUES_LIST 2
2176#define _ITEMS_LIST 3
2177
2178static PyObject*
2179_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2180{
2181 int err, dbtype;
2182 DBT key;
2183 DBT data;
2184 DBC *cursor;
2185 PyObject* list;
2186 PyObject* item = NULL;
2187
2188 CHECK_DB_NOT_CLOSED(self);
2189 CLEAR_DBT(key);
2190 CLEAR_DBT(data);
2191
2192 dbtype = _DB_get_type(self);
2193 if (dbtype == -1)
2194 return NULL;
2195
2196 list = PyList_New(0);
2197 if (list == NULL) {
2198 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2199 return NULL;
2200 }
2201
2202 /* get a cursor */
2203 MYDB_BEGIN_ALLOW_THREADS;
2204 err = self->db->cursor(self->db, NULL, &cursor, 0);
2205 MYDB_END_ALLOW_THREADS;
2206 RETURN_IF_ERR();
2207
2208 if (CHECK_DBFLAG(self, DB_THREAD)) {
2209 key.flags = DB_DBT_REALLOC;
2210 data.flags = DB_DBT_REALLOC;
2211 }
2212
2213 while (1) { /* use the cursor to traverse the DB, collecting items */
2214 MYDB_BEGIN_ALLOW_THREADS;
2215 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2216 MYDB_END_ALLOW_THREADS;
2217
2218 if (err) {
2219 /* for any error, break out of the loop */
2220 break;
2221 }
2222
2223 switch (type) {
2224 case _KEYS_LIST:
2225 switch(dbtype) {
2226 case DB_BTREE:
2227 case DB_HASH:
2228 default:
2229 item = PyString_FromStringAndSize((char*)key.data, key.size);
2230 break;
2231 case DB_RECNO:
2232 case DB_QUEUE:
2233 item = PyInt_FromLong(*((db_recno_t*)key.data));
2234 break;
2235 }
2236 break;
2237
2238 case _VALUES_LIST:
2239 item = PyString_FromStringAndSize((char*)data.data, data.size);
2240 break;
2241
2242 case _ITEMS_LIST:
2243 switch(dbtype) {
2244 case DB_BTREE:
2245 case DB_HASH:
2246 default:
2247 item = Py_BuildValue("s#s#", key.data, key.size, data.data, data.size);
2248 break;
2249 case DB_RECNO:
2250 case DB_QUEUE:
2251 item = Py_BuildValue("is#", *((db_recno_t*)key.data), data.data, data.size);
2252 break;
2253 }
2254 break;
2255 }
2256 if (item == NULL) {
2257 Py_DECREF(list);
2258 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2259 list = NULL;
2260 goto done;
2261 }
2262 PyList_Append(list, item);
2263 Py_DECREF(item);
2264 }
2265
2266 /* DB_NOTFOUND is okay, it just means we got to the end */
2267 if (err != DB_NOTFOUND && makeDBError(err)) {
2268 Py_DECREF(list);
2269 list = NULL;
2270 }
2271
2272 done:
2273 FREE_DBT(key);
2274 FREE_DBT(data);
2275 MYDB_BEGIN_ALLOW_THREADS;
2276 cursor->c_close(cursor);
2277 MYDB_END_ALLOW_THREADS;
2278 return list;
2279}
2280
2281
2282static PyObject*
2283DB_keys(DBObject* self, PyObject* args)
2284{
2285 PyObject* txnobj = NULL;
2286 DB_TXN *txn = NULL;
2287
2288 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2289 return NULL;
2290 if (!checkTxnObj(txnobj, &txn))
2291 return NULL;
2292 return _DB_make_list(self, txn, _KEYS_LIST);
2293}
2294
2295
2296static PyObject*
2297DB_items(DBObject* self, PyObject* args)
2298{
2299 PyObject* txnobj = NULL;
2300 DB_TXN *txn = NULL;
2301
2302 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2303 return NULL;
2304 if (!checkTxnObj(txnobj, &txn))
2305 return NULL;
2306 return _DB_make_list(self, txn, _ITEMS_LIST);
2307}
2308
2309
2310static PyObject*
2311DB_values(DBObject* self, PyObject* args)
2312{
2313 PyObject* txnobj = NULL;
2314 DB_TXN *txn = NULL;
2315
2316 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2317 return NULL;
2318 if (!checkTxnObj(txnobj, &txn))
2319 return NULL;
2320 return _DB_make_list(self, txn, _VALUES_LIST);
2321}
2322
2323
2324/* --------------------------------------------------------------------- */
2325/* DBCursor methods */
2326
2327
2328static PyObject*
2329DBC_close(DBCursorObject* self, PyObject* args)
2330{
2331 int err = 0;
2332
2333 if (!PyArg_ParseTuple(args, ":close"))
2334 return NULL;
2335
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002336 if (self->dbc != NULL) {
2337 MYDB_BEGIN_ALLOW_THREADS;
2338 err = self->dbc->c_close(self->dbc);
2339 self->dbc = NULL;
2340 MYDB_END_ALLOW_THREADS;
2341 }
2342 RETURN_IF_ERR();
2343 RETURN_NONE();
2344}
2345
2346
2347static PyObject*
2348DBC_count(DBCursorObject* self, PyObject* args)
2349{
2350 int err = 0;
2351 db_recno_t count;
2352 int flags = 0;
2353
2354 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2355 return NULL;
2356
2357 CHECK_CURSOR_NOT_CLOSED(self);
2358
2359 MYDB_BEGIN_ALLOW_THREADS;
2360 err = self->dbc->c_count(self->dbc, &count, flags);
2361 MYDB_END_ALLOW_THREADS;
2362 RETURN_IF_ERR();
2363
2364 return PyInt_FromLong(count);
2365}
2366
2367
2368static PyObject*
2369DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2370{
2371 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2372}
2373
2374
2375static PyObject*
2376DBC_delete(DBCursorObject* self, PyObject* args)
2377{
2378 int err, flags=0;
2379
2380 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2381 return NULL;
2382
2383 CHECK_CURSOR_NOT_CLOSED(self);
2384
2385 MYDB_BEGIN_ALLOW_THREADS;
2386 err = self->dbc->c_del(self->dbc, flags);
2387 MYDB_END_ALLOW_THREADS;
2388 RETURN_IF_ERR();
2389
2390 self->mydb->haveStat = 0;
2391 RETURN_NONE();
2392}
2393
2394
2395static PyObject*
2396DBC_dup(DBCursorObject* self, PyObject* args)
2397{
2398 int err, flags =0;
2399 DBC* dbc = NULL;
2400
2401 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2402 return NULL;
2403
2404 CHECK_CURSOR_NOT_CLOSED(self);
2405
2406 MYDB_BEGIN_ALLOW_THREADS;
2407 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2408 MYDB_END_ALLOW_THREADS;
2409 RETURN_IF_ERR();
2410
2411 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2412}
2413
2414static PyObject*
2415DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2416{
2417 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2418}
2419
2420
2421static PyObject*
2422DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2423{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00002424 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002425 PyObject* keyobj = NULL;
2426 PyObject* dataobj = NULL;
2427 PyObject* retval = NULL;
2428 int dlen = -1;
2429 int doff = -1;
2430 DBT key, data;
2431 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2432
2433 CLEAR_DBT(key);
2434 CLEAR_DBT(data);
2435 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
2436 &flags, &dlen, &doff)) {
2437 PyErr_Clear();
2438 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get", &kwnames[1],
2439 &keyobj, &flags, &dlen, &doff)) {
2440 PyErr_Clear();
2441 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get", kwnames,
2442 &keyobj, &dataobj, &flags, &dlen, &doff)) {
2443 return NULL;
2444 }
2445 }
2446 }
2447
2448 CHECK_CURSOR_NOT_CLOSED(self);
2449
2450 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2451 return NULL;
2452 if (dataobj && !make_dbt(dataobj, &data))
2453 return NULL;
2454 if (!add_partial_dbt(&data, dlen, doff))
2455 return NULL;
2456
2457 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2458 data.flags = DB_DBT_MALLOC;
2459 key.flags = DB_DBT_MALLOC;
2460 }
2461
2462 MYDB_BEGIN_ALLOW_THREADS;
2463 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2464 MYDB_END_ALLOW_THREADS;
2465
2466
2467 if ((err == DB_NOTFOUND) && self->mydb->getReturnsNone) {
2468 Py_INCREF(Py_None);
2469 retval = Py_None;
2470 }
2471 else if (makeDBError(err)) {
2472 retval = NULL;
2473 }
2474 else {
2475 switch (_DB_get_type(self->mydb)) {
2476 case -1:
2477 retval = NULL;
2478 break;
2479 case DB_BTREE:
2480 case DB_HASH:
2481 default:
2482 retval = Py_BuildValue("s#s#", key.data, key.size,
2483 data.data, data.size);
2484 break;
2485 case DB_RECNO:
2486 case DB_QUEUE:
2487 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2488 data.data, data.size);
2489 break;
2490 }
2491 FREE_DBT(key);
2492 FREE_DBT(data);
2493 }
2494 return retval;
2495}
2496
2497
2498static PyObject*
2499DBC_get_recno(DBCursorObject* self, PyObject* args)
2500{
2501 int err;
2502 db_recno_t recno;
2503 DBT key;
2504 DBT data;
2505
2506 if (!PyArg_ParseTuple(args, ":get_recno"))
2507 return NULL;
2508
2509 CHECK_CURSOR_NOT_CLOSED(self);
2510
2511 CLEAR_DBT(key);
2512 CLEAR_DBT(data);
2513 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2514 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2515 data.flags = DB_DBT_MALLOC;
2516 key.flags = DB_DBT_MALLOC;
2517 }
2518
2519 MYDB_BEGIN_ALLOW_THREADS;
2520 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
2521 MYDB_END_ALLOW_THREADS;
2522 RETURN_IF_ERR();
2523
2524 recno = *((db_recno_t*)data.data);
2525 FREE_DBT(key);
2526 FREE_DBT(data);
2527 return PyInt_FromLong(recno);
2528}
2529
2530
2531static PyObject*
2532DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2533{
2534 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
2535}
2536
2537
2538static PyObject*
2539DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2540{
2541 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
2542}
2543
2544
2545static PyObject*
2546DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2547{
2548 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
2549}
2550
2551
2552static PyObject*
2553DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2554{
2555 int err, flags = 0;
2556 PyObject* keyobj, *dataobj;
2557 DBT key, data;
2558 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
2559 int dlen = -1;
2560 int doff = -1;
2561
2562 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
2563 &keyobj, &dataobj, &flags, &dlen, &doff))
2564 return NULL;
2565
2566 CHECK_CURSOR_NOT_CLOSED(self);
2567
2568 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2569 return NULL;
2570 if (!make_dbt(dataobj, &data))
2571 return NULL;
2572 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
2573
2574 MYDB_BEGIN_ALLOW_THREADS;
2575 err = self->dbc->c_put(self->dbc, &key, &data, flags);
2576 MYDB_END_ALLOW_THREADS;
2577 FREE_DBT(key);
2578 RETURN_IF_ERR();
2579 self->mydb->haveStat = 0;
2580 RETURN_NONE();
2581}
2582
2583
2584static PyObject*
2585DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2586{
2587 int err, flags = 0;
2588 DBT key, data;
2589 PyObject* retval, *keyobj;
2590 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2591 int dlen = -1;
2592 int doff = -1;
2593
2594 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
2595 &keyobj, &flags, &dlen, &doff))
2596 return NULL;
2597
2598 CHECK_CURSOR_NOT_CLOSED(self);
2599
2600 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2601 return NULL;
2602
2603 CLEAR_DBT(data);
2604 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2605 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2606 data.flags = DB_DBT_MALLOC;
2607 }
2608 if (!add_partial_dbt(&data, dlen, doff))
2609 return NULL;
2610
2611 MYDB_BEGIN_ALLOW_THREADS;
2612 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
2613 MYDB_END_ALLOW_THREADS;
2614 if (makeDBError(err)) {
2615 retval = NULL;
2616 }
2617 else {
2618 switch (_DB_get_type(self->mydb)) {
2619 case -1:
2620 retval = NULL;
2621 break;
2622 case DB_BTREE:
2623 case DB_HASH:
2624 default:
2625 retval = Py_BuildValue("s#s#", key.data, key.size,
2626 data.data, data.size);
2627 break;
2628 case DB_RECNO:
2629 case DB_QUEUE:
2630 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2631 data.data, data.size);
2632 break;
2633 }
2634 FREE_DBT(key);
2635 FREE_DBT(data);
2636 }
2637
2638 return retval;
2639}
2640
2641
2642static PyObject*
2643DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2644{
2645 int err, flags = 0;
2646 DBT key, data;
2647 PyObject* retval, *keyobj;
2648 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2649 int dlen = -1;
2650 int doff = -1;
2651
2652 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
2653 &keyobj, &flags, &dlen, &doff))
2654 return NULL;
2655
2656 CHECK_CURSOR_NOT_CLOSED(self);
2657
2658 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2659 return NULL;
2660
2661 CLEAR_DBT(data);
2662 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2663 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2664 data.flags = DB_DBT_MALLOC;
2665 key.flags = DB_DBT_MALLOC;
2666 }
2667 if (!add_partial_dbt(&data, dlen, doff))
2668 return NULL;
2669 MYDB_BEGIN_ALLOW_THREADS;
2670 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
2671 MYDB_END_ALLOW_THREADS;
2672 if (makeDBError(err)) {
2673 retval = NULL;
2674 }
2675 else {
2676 switch (_DB_get_type(self->mydb)) {
2677 case -1:
2678 retval = NULL;
2679 break;
2680 case DB_BTREE:
2681 case DB_HASH:
2682 default:
2683 retval = Py_BuildValue("s#s#", key.data, key.size,
2684 data.data, data.size);
2685 break;
2686 case DB_RECNO:
2687 case DB_QUEUE:
2688 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2689 data.data, data.size);
2690 break;
2691 }
2692 FREE_DBT(key);
2693 FREE_DBT(data);
2694 }
2695
2696 return retval;
2697}
2698
2699
2700static PyObject*
2701DBC_get_both(DBCursorObject* self, PyObject* args)
2702{
2703 int err, flags=0;
2704 DBT key, data;
2705 PyObject* retval, *keyobj, *dataobj;
2706
2707 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
2708 return NULL;
2709
2710 CHECK_CURSOR_NOT_CLOSED(self);
2711
2712 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2713 return NULL;
2714 if (!make_dbt(dataobj, &data))
2715 return NULL;
2716
2717 MYDB_BEGIN_ALLOW_THREADS;
2718 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
2719 MYDB_END_ALLOW_THREADS;
2720 if (makeDBError(err)) {
2721 retval = NULL;
2722 }
2723 else {
2724 switch (_DB_get_type(self->mydb)) {
2725 case -1:
2726 retval = NULL;
2727 break;
2728 case DB_BTREE:
2729 case DB_HASH:
2730 default:
2731 retval = Py_BuildValue("s#s#", key.data, key.size,
2732 data.data, data.size);
2733 break;
2734 case DB_RECNO:
2735 case DB_QUEUE:
2736 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2737 data.data, data.size);
2738 break;
2739 }
2740 }
2741
2742 FREE_DBT(key);
2743 return retval;
2744}
2745
2746
2747static PyObject*
2748DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2749{
2750 int err, irecno, flags=0;
2751 db_recno_t recno;
2752 DBT key, data;
2753 PyObject* retval;
2754 int dlen = -1;
2755 int doff = -1;
2756 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
2757
2758 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
2759 &irecno, &flags, &dlen, &doff))
2760 return NULL;
2761
2762 CHECK_CURSOR_NOT_CLOSED(self);
2763
2764 CLEAR_DBT(key);
2765 recno = (db_recno_t) irecno;
2766 /* use allocated space so DB will be able to realloc room for the real key */
2767 key.data = malloc(sizeof(db_recno_t));
2768 if (key.data == NULL) {
2769 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
2770 return NULL;
2771 }
2772 key.size = sizeof(db_recno_t);
2773 key.ulen = key.size;
2774 memcpy(key.data, &recno, sizeof(db_recno_t));
2775 key.flags = DB_DBT_REALLOC;
2776
2777 CLEAR_DBT(data);
2778 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2779 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2780 data.flags = DB_DBT_MALLOC;
2781 }
2782 if (!add_partial_dbt(&data, dlen, doff))
2783 return NULL;
2784
2785 MYDB_BEGIN_ALLOW_THREADS;
2786 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
2787 MYDB_END_ALLOW_THREADS;
2788 if (makeDBError(err)) {
2789 retval = NULL;
2790 }
2791 else { /* Can only be used for BTrees, so no need to return int key */
2792 retval = Py_BuildValue("s#s#", key.data, key.size,
2793 data.data, data.size);
2794 FREE_DBT(key);
2795 FREE_DBT(data);
2796 }
2797
2798 return retval;
2799}
2800
2801
2802static PyObject*
2803DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2804{
2805 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
2806}
2807
2808
2809static PyObject*
2810DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2811{
2812 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
2813}
2814
2815
2816static PyObject*
2817DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2818{
2819 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
2820}
2821
2822
2823static PyObject*
2824DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2825{
2826 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
2827}
2828
2829
2830static PyObject*
2831DBC_join_item(DBCursorObject* self, PyObject* args)
2832{
2833 int err;
2834 DBT key, data;
2835 PyObject* retval;
2836
2837 if (!PyArg_ParseTuple(args, ":join_item"))
2838 return NULL;
2839
2840 CHECK_CURSOR_NOT_CLOSED(self);
2841
2842 CLEAR_DBT(key);
2843 CLEAR_DBT(data);
2844 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2845 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2846 key.flags = DB_DBT_MALLOC;
2847 }
2848
2849 MYDB_BEGIN_ALLOW_THREADS;
2850 err = self->dbc->c_get(self->dbc, &key, &data, DB_JOIN_ITEM);
2851 MYDB_END_ALLOW_THREADS;
2852 if (makeDBError(err)) {
2853 retval = NULL;
2854 }
2855 else {
2856 retval = Py_BuildValue("s#s#", key.data, key.size);
2857 FREE_DBT(key);
2858 }
2859
2860 return retval;
2861}
2862
2863
2864
2865/* --------------------------------------------------------------------- */
2866/* DBEnv methods */
2867
2868
2869static PyObject*
2870DBEnv_close(DBEnvObject* self, PyObject* args)
2871{
2872 int err, flags = 0;
2873
2874 if (!PyArg_ParseTuple(args, "|i:close", &flags))
2875 return NULL;
2876 if (!self->closed) { /* Don't close more than once */
2877 MYDB_BEGIN_ALLOW_THREADS;
2878 err = self->db_env->close(self->db_env, flags);
2879 MYDB_END_ALLOW_THREADS;
2880 /* after calling DBEnv->close, regardless of error, this DBEnv
2881 * may not be accessed again (BerkeleyDB docs). */
2882 self->closed = 1;
2883 self->db_env = NULL;
2884 RETURN_IF_ERR();
2885 }
2886 RETURN_NONE();
2887}
2888
2889
2890static PyObject*
2891DBEnv_open(DBEnvObject* self, PyObject* args)
2892{
2893 int err, flags=0, mode=0660;
2894 char *db_home;
2895
2896 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
2897 return NULL;
2898
2899 CHECK_ENV_NOT_CLOSED(self);
2900
2901 MYDB_BEGIN_ALLOW_THREADS;
2902 err = self->db_env->open(self->db_env, db_home, flags, mode);
2903 MYDB_END_ALLOW_THREADS;
2904 RETURN_IF_ERR();
2905 self->closed = 0;
2906 self->flags = flags;
2907 RETURN_NONE();
2908}
2909
2910
2911static PyObject*
2912DBEnv_remove(DBEnvObject* self, PyObject* args)
2913{
2914 int err, flags=0;
2915 char *db_home;
2916
2917 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
2918 return NULL;
2919 CHECK_ENV_NOT_CLOSED(self);
2920 MYDB_BEGIN_ALLOW_THREADS;
2921 err = self->db_env->remove(self->db_env, db_home, flags);
2922 MYDB_END_ALLOW_THREADS;
2923 RETURN_IF_ERR();
2924 RETURN_NONE();
2925}
2926
2927
2928static PyObject*
2929DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
2930{
2931 int err, gbytes=0, bytes=0, ncache=0;
2932
2933 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
2934 &gbytes, &bytes, &ncache))
2935 return NULL;
2936 CHECK_ENV_NOT_CLOSED(self);
2937
2938 MYDB_BEGIN_ALLOW_THREADS;
2939 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
2940 MYDB_END_ALLOW_THREADS;
2941 RETURN_IF_ERR();
2942 RETURN_NONE();
2943}
2944
2945
2946#if (DBVER >= 32)
2947static PyObject*
2948DBEnv_set_flags(DBEnvObject* self, PyObject* args)
2949{
2950 int err, flags=0, onoff=0;
2951
2952 if (!PyArg_ParseTuple(args, "ii:set_flags",
2953 &flags, &onoff))
2954 return NULL;
2955 CHECK_ENV_NOT_CLOSED(self);
2956
2957 MYDB_BEGIN_ALLOW_THREADS;
2958 err = self->db_env->set_flags(self->db_env, flags, onoff);
2959 MYDB_END_ALLOW_THREADS;
2960 RETURN_IF_ERR();
2961 RETURN_NONE();
2962}
2963#endif
2964
2965
2966static PyObject*
2967DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
2968{
2969 int err;
2970 char *dir;
2971
2972 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
2973 return NULL;
2974 CHECK_ENV_NOT_CLOSED(self);
2975
2976 MYDB_BEGIN_ALLOW_THREADS;
2977 err = self->db_env->set_data_dir(self->db_env, dir);
2978 MYDB_END_ALLOW_THREADS;
2979 RETURN_IF_ERR();
2980 RETURN_NONE();
2981}
2982
2983
2984static PyObject*
2985DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
2986{
2987 int err, lg_bsize;
2988
2989 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
2990 return NULL;
2991 CHECK_ENV_NOT_CLOSED(self);
2992
2993 MYDB_BEGIN_ALLOW_THREADS;
2994 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
2995 MYDB_END_ALLOW_THREADS;
2996 RETURN_IF_ERR();
2997 RETURN_NONE();
2998}
2999
3000
3001static PyObject*
3002DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3003{
3004 int err;
3005 char *dir;
3006
3007 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3008 return NULL;
3009 CHECK_ENV_NOT_CLOSED(self);
3010
3011 MYDB_BEGIN_ALLOW_THREADS;
3012 err = self->db_env->set_lg_dir(self->db_env, dir);
3013 MYDB_END_ALLOW_THREADS;
3014 RETURN_IF_ERR();
3015 RETURN_NONE();
3016}
3017
3018static PyObject*
3019DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3020{
3021 int err, lg_max;
3022
3023 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3024 return NULL;
3025 CHECK_ENV_NOT_CLOSED(self);
3026
3027 MYDB_BEGIN_ALLOW_THREADS;
3028 err = self->db_env->set_lg_max(self->db_env, lg_max);
3029 MYDB_END_ALLOW_THREADS;
3030 RETURN_IF_ERR();
3031 RETURN_NONE();
3032}
3033
3034
3035static PyObject*
3036DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3037{
3038 int err, lk_detect;
3039
3040 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3041 return NULL;
3042 CHECK_ENV_NOT_CLOSED(self);
3043
3044 MYDB_BEGIN_ALLOW_THREADS;
3045 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3046 MYDB_END_ALLOW_THREADS;
3047 RETURN_IF_ERR();
3048 RETURN_NONE();
3049}
3050
3051
3052static PyObject*
3053DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3054{
3055 int err, max;
3056
3057 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3058 return NULL;
3059 CHECK_ENV_NOT_CLOSED(self);
3060
3061 MYDB_BEGIN_ALLOW_THREADS;
3062 err = self->db_env->set_lk_max(self->db_env, max);
3063 MYDB_END_ALLOW_THREADS;
3064 RETURN_IF_ERR();
3065 RETURN_NONE();
3066}
3067
3068
3069#if (DBVER >= 32)
3070
3071static PyObject*
3072DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3073{
3074 int err, max;
3075
3076 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3077 return NULL;
3078 CHECK_ENV_NOT_CLOSED(self);
3079
3080 MYDB_BEGIN_ALLOW_THREADS;
3081 err = self->db_env->set_lk_max_locks(self->db_env, max);
3082 MYDB_END_ALLOW_THREADS;
3083 RETURN_IF_ERR();
3084 RETURN_NONE();
3085}
3086
3087
3088static PyObject*
3089DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3090{
3091 int err, max;
3092
3093 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3094 return NULL;
3095 CHECK_ENV_NOT_CLOSED(self);
3096
3097 MYDB_BEGIN_ALLOW_THREADS;
3098 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3099 MYDB_END_ALLOW_THREADS;
3100 RETURN_IF_ERR();
3101 RETURN_NONE();
3102}
3103
3104
3105static PyObject*
3106DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3107{
3108 int err, max;
3109
3110 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3111 return NULL;
3112 CHECK_ENV_NOT_CLOSED(self);
3113
3114 MYDB_BEGIN_ALLOW_THREADS;
3115 err = self->db_env->set_lk_max_objects(self->db_env, max);
3116 MYDB_END_ALLOW_THREADS;
3117 RETURN_IF_ERR();
3118 RETURN_NONE();
3119}
3120
3121#endif
3122
3123
3124static PyObject*
3125DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3126{
3127 int err, mp_mmapsize;
3128
3129 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3130 return NULL;
3131 CHECK_ENV_NOT_CLOSED(self);
3132
3133 MYDB_BEGIN_ALLOW_THREADS;
3134 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3135 MYDB_END_ALLOW_THREADS;
3136 RETURN_IF_ERR();
3137 RETURN_NONE();
3138}
3139
3140
3141static PyObject*
3142DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3143{
3144 int err;
3145 char *dir;
3146
3147 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3148 return NULL;
3149 CHECK_ENV_NOT_CLOSED(self);
3150
3151 MYDB_BEGIN_ALLOW_THREADS;
3152 err = self->db_env->set_tmp_dir(self->db_env, dir);
3153 MYDB_END_ALLOW_THREADS;
3154 RETURN_IF_ERR();
3155 RETURN_NONE();
3156}
3157
3158
3159static PyObject*
3160DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3161{
3162 int flags = 0;
3163 PyObject* txnobj = NULL;
3164 DB_TXN *txn = NULL;
3165 char* kwnames[] = { "parent", "flags", NULL };
3166
3167 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3168 &txnobj, &flags))
3169 return NULL;
3170
3171 if (!checkTxnObj(txnobj, &txn))
3172 return NULL;
3173 CHECK_ENV_NOT_CLOSED(self);
3174
3175 return (PyObject*)newDBTxnObject(self, txn, flags);
3176}
3177
3178
3179static PyObject*
3180DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3181{
3182 int err, kbyte=0, min=0, flags=0;
3183
3184 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3185 return NULL;
3186 CHECK_ENV_NOT_CLOSED(self);
3187
3188 MYDB_BEGIN_ALLOW_THREADS;
3189#if (DBVER >= 40)
3190 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3191#else
3192 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3193#endif
3194 MYDB_END_ALLOW_THREADS;
3195 RETURN_IF_ERR();
3196 RETURN_NONE();
3197}
3198
3199
3200static PyObject*
3201DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3202{
3203 int err, max;
3204
3205 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3206 return NULL;
3207 CHECK_ENV_NOT_CLOSED(self);
3208
3209 MYDB_BEGIN_ALLOW_THREADS;
3210 err = self->db_env->set_tx_max(self->db_env, max);
3211 MYDB_END_ALLOW_THREADS;
3212 RETURN_IF_ERR();
3213 RETURN_NONE();
3214}
3215
3216
3217static PyObject*
3218DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3219{
3220 int err, atype, flags=0;
3221 int aborted = 0;
3222
3223 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3224 return NULL;
3225 CHECK_ENV_NOT_CLOSED(self);
3226
3227 MYDB_BEGIN_ALLOW_THREADS;
3228#if (DBVER >= 40)
3229 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3230#else
3231 err = lock_detect(self->db_env, flags, atype, &aborted);
3232#endif
3233 MYDB_END_ALLOW_THREADS;
3234 RETURN_IF_ERR();
3235 return PyInt_FromLong(aborted);
3236}
3237
3238
3239static PyObject*
3240DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3241{
3242 int flags=0;
3243 int locker, lock_mode;
3244 DBT obj;
3245 PyObject* objobj;
3246
3247 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3248 return NULL;
3249
3250
3251 if (!make_dbt(objobj, &obj))
3252 return NULL;
3253
3254 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3255}
3256
3257
3258static PyObject*
3259DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3260{
3261 int err;
3262 u_int32_t theID;
3263
3264 if (!PyArg_ParseTuple(args, ":lock_id"))
3265 return NULL;
3266
3267 CHECK_ENV_NOT_CLOSED(self);
3268 MYDB_BEGIN_ALLOW_THREADS;
3269#if (DBVER >= 40)
3270 err = self->db_env->lock_id(self->db_env, &theID);
3271#else
3272 err = lock_id(self->db_env, &theID);
3273#endif
3274 MYDB_END_ALLOW_THREADS;
3275 RETURN_IF_ERR();
3276
3277 return PyInt_FromLong((long)theID);
3278}
3279
3280
3281static PyObject*
3282DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3283{
3284 int err;
3285 DBLockObject* dblockobj;
3286
3287 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3288 return NULL;
3289
3290 CHECK_ENV_NOT_CLOSED(self);
3291 MYDB_BEGIN_ALLOW_THREADS;
3292#if (DBVER >= 40)
3293 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3294#else
3295 err = lock_put(self->db_env, &dblockobj->lock);
3296#endif
3297 MYDB_END_ALLOW_THREADS;
3298 RETURN_IF_ERR();
3299 RETURN_NONE();
3300}
3301
3302
3303static PyObject*
3304DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
3305{
3306 int err;
3307 DB_LOCK_STAT* sp;
3308 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003309 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003310
3311 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
3312 return NULL;
3313 CHECK_ENV_NOT_CLOSED(self);
3314
3315 MYDB_BEGIN_ALLOW_THREADS;
3316#if (DBVER >= 40)
3317 err = self->db_env->lock_stat(self->db_env, &sp, flags);
3318#else
3319#if (DBVER >= 33)
3320 err = lock_stat(self->db_env, &sp);
3321#else
3322 err = lock_stat(self->db_env, &sp, NULL);
3323#endif
3324#endif
3325 MYDB_END_ALLOW_THREADS;
3326 RETURN_IF_ERR();
3327
3328 /* Turn the stat structure into a dictionary */
3329 d = PyDict_New();
3330 if (d == NULL) {
3331 free(sp);
3332 return NULL;
3333 }
3334
3335#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3336
3337 MAKE_ENTRY(lastid);
3338 MAKE_ENTRY(nmodes);
3339#if (DBVER >= 32)
3340 MAKE_ENTRY(maxlocks);
3341 MAKE_ENTRY(maxlockers);
3342 MAKE_ENTRY(maxobjects);
3343 MAKE_ENTRY(nlocks);
3344 MAKE_ENTRY(maxnlocks);
3345#endif
3346 MAKE_ENTRY(nlockers);
3347 MAKE_ENTRY(maxnlockers);
3348#if (DBVER >= 32)
3349 MAKE_ENTRY(nobjects);
3350 MAKE_ENTRY(maxnobjects);
3351#endif
3352 MAKE_ENTRY(nrequests);
3353 MAKE_ENTRY(nreleases);
3354 MAKE_ENTRY(nnowaits);
3355 MAKE_ENTRY(nconflicts);
3356 MAKE_ENTRY(ndeadlocks);
3357 MAKE_ENTRY(regsize);
3358 MAKE_ENTRY(region_wait);
3359 MAKE_ENTRY(region_nowait);
3360
3361#undef MAKE_ENTRY
3362 free(sp);
3363 return d;
3364}
3365
3366
3367static PyObject*
3368DBEnv_log_archive(DBEnvObject* self, PyObject* args)
3369{
3370 int flags=0;
3371 int err;
3372 char **log_list_start, **log_list;
3373 PyObject* list;
3374 PyObject* item = NULL;
3375
3376 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
3377 return NULL;
3378
3379 CHECK_ENV_NOT_CLOSED(self);
3380 MYDB_BEGIN_ALLOW_THREADS;
3381#if (DBVER >= 40)
3382 err = self->db_env->log_archive(self->db_env, &log_list, flags);
3383#elif (DBVER == 33)
3384 err = log_archive(self->db_env, &log_list, flags);
3385#else
3386 err = log_archive(self->db_env, &log_list, flags, NULL);
3387#endif
3388 MYDB_END_ALLOW_THREADS;
3389 RETURN_IF_ERR();
3390
3391 list = PyList_New(0);
3392 if (list == NULL) {
3393 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
3394 return NULL;
3395 }
3396
3397 if (log_list) {
3398 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
3399 item = PyString_FromString (*log_list);
3400 if (item == NULL) {
3401 Py_DECREF(list);
3402 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
3403 list = NULL;
3404 break;
3405 }
3406 PyList_Append(list, item);
3407 Py_DECREF(item);
3408 }
3409 free(log_list_start);
3410 }
3411 return list;
3412}
3413
3414
3415static PyObject*
3416DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
3417{
3418 int err;
3419 DB_TXN_STAT* sp;
3420 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003421 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003422
3423 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
3424 return NULL;
3425 CHECK_ENV_NOT_CLOSED(self);
3426
3427 MYDB_BEGIN_ALLOW_THREADS;
3428#if (DBVER >= 40)
3429 err = self->db_env->txn_stat(self->db_env, &sp, flags);
3430#elif (DBVER == 33)
3431 err = txn_stat(self->db_env, &sp);
3432#else
3433 err = txn_stat(self->db_env, &sp, NULL);
3434#endif
3435 MYDB_END_ALLOW_THREADS;
3436 RETURN_IF_ERR();
3437
3438 /* Turn the stat structure into a dictionary */
3439 d = PyDict_New();
3440 if (d == NULL) {
3441 free(sp);
3442 return NULL;
3443 }
3444
3445#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3446
3447 MAKE_ENTRY(time_ckp);
3448 MAKE_ENTRY(last_txnid);
3449 MAKE_ENTRY(maxtxns);
3450 MAKE_ENTRY(nactive);
3451 MAKE_ENTRY(maxnactive);
3452 MAKE_ENTRY(nbegins);
3453 MAKE_ENTRY(naborts);
3454 MAKE_ENTRY(ncommits);
3455 MAKE_ENTRY(regsize);
3456 MAKE_ENTRY(region_wait);
3457 MAKE_ENTRY(region_nowait);
3458
3459#undef MAKE_ENTRY
3460 free(sp);
3461 return d;
3462}
3463
3464
3465static PyObject*
3466DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
3467{
3468 int flags=0;
3469 int oldValue;
3470
3471 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
3472 return NULL;
3473 CHECK_ENV_NOT_CLOSED(self);
3474
3475 oldValue = self->getReturnsNone;
3476 self->getReturnsNone = flags;
3477 return PyInt_FromLong(oldValue);
3478}
3479
3480
3481/* --------------------------------------------------------------------- */
3482/* DBTxn methods */
3483
3484
3485static PyObject*
3486DBTxn_commit(DBTxnObject* self, PyObject* args)
3487{
3488 int flags=0, err;
3489
3490 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
3491 return NULL;
3492
3493 MYDB_BEGIN_ALLOW_THREADS;
3494#if (DBVER >= 40)
3495 err = self->txn->commit(self->txn, flags);
3496#else
3497 err = txn_commit(self->txn, flags);
3498#endif
3499 MYDB_END_ALLOW_THREADS;
3500 RETURN_IF_ERR();
3501 RETURN_NONE();
3502}
3503
3504static PyObject*
3505DBTxn_prepare(DBTxnObject* self, PyObject* args)
3506{
3507#if (DBVER >= 33)
3508 int err;
3509 char* gid=NULL;
3510 int gid_size=0;
3511
3512 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
3513 return NULL;
3514
3515 if (gid_size != DB_XIDDATASIZE) {
3516 PyErr_SetString(PyExc_TypeError,
3517 "gid must be DB_XIDDATASIZE bytes long");
3518 return NULL;
3519 }
3520
3521 MYDB_BEGIN_ALLOW_THREADS;
3522#if (DBVER >= 40)
3523 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
3524#else
3525 err = txn_prepare(self->txn, (u_int8_t*)gid);
3526#endif
3527 MYDB_END_ALLOW_THREADS;
3528 RETURN_IF_ERR();
3529 RETURN_NONE();
3530#else
3531 int err;
3532
3533 if (!PyArg_ParseTuple(args, ":prepare"))
3534 return NULL;
3535
3536 MYDB_BEGIN_ALLOW_THREADS;
3537 err = txn_prepare(self->txn);
3538 MYDB_END_ALLOW_THREADS;
3539 RETURN_IF_ERR();
3540 RETURN_NONE();
3541#endif
3542}
3543
3544
3545static PyObject*
3546DBTxn_abort(DBTxnObject* self, PyObject* args)
3547{
3548 int err;
3549
3550 if (!PyArg_ParseTuple(args, ":abort"))
3551 return NULL;
3552
3553 MYDB_BEGIN_ALLOW_THREADS;
3554#if (DBVER >= 40)
3555 err = self->txn->abort(self->txn);
3556#else
3557 err = txn_abort(self->txn);
3558#endif
3559 MYDB_END_ALLOW_THREADS;
3560 RETURN_IF_ERR();
3561 RETURN_NONE();
3562}
3563
3564
3565static PyObject*
3566DBTxn_id(DBTxnObject* self, PyObject* args)
3567{
3568 int id;
3569
3570 if (!PyArg_ParseTuple(args, ":id"))
3571 return NULL;
3572
3573 MYDB_BEGIN_ALLOW_THREADS;
3574#if (DBVER >= 40)
3575 id = self->txn->id(self->txn);
3576#else
3577 id = txn_id(self->txn);
3578#endif
3579 MYDB_END_ALLOW_THREADS;
3580 return PyInt_FromLong(id);
3581}
3582
3583/* --------------------------------------------------------------------- */
3584/* Method definition tables and type objects */
3585
3586static PyMethodDef DB_methods[] = {
3587 {"append", (PyCFunction)DB_append, METH_VARARGS},
3588#if (DBVER >= 33)
3589 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
3590#endif
3591 {"close", (PyCFunction)DB_close, METH_VARARGS},
3592#if (DBVER >= 32)
3593 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
3594 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
3595#endif
3596 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
3597 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
3598 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
3599 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
3600 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
3601 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
3602 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
3603 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
3604 {"join", (PyCFunction)DB_join, METH_VARARGS},
3605 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
3606 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
3607 {"items", (PyCFunction)DB_items, METH_VARARGS},
3608 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
3609 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
3610 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
3611 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
3612 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
3613 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
3614 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
3615 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
3616 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
3617 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
3618 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
3619 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
3620 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
3621 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
3622 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
3623 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
3624#if (DBVER >= 32)
3625 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
3626#endif
3627 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
3628 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
3629#if (DBVER >= 33)
3630 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
3631#endif
3632 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
3633 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
3634 {"values", (PyCFunction)DB_values, METH_VARARGS},
3635 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
3636 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
3637 {NULL, NULL} /* sentinel */
3638};
3639
3640
3641static PyMappingMethods DB_mapping = {
3642 (inquiry)DB_length, /*mp_length*/
3643 (binaryfunc)DB_subscript, /*mp_subscript*/
3644 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
3645};
3646
3647
3648static PyMethodDef DBCursor_methods[] = {
3649 {"close", (PyCFunction)DBC_close, METH_VARARGS},
3650 {"count", (PyCFunction)DBC_count, METH_VARARGS},
3651 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
3652 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
3653 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
3654 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
3655 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
3656 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
3657 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
3658 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
3659 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
3660 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
3661 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
3662 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
3663 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
3664 {"set_both", (PyCFunction)DBC_get_both, METH_VARARGS},
3665 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
3666 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
3667 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
3668 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
3669 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
3670 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
3671 {NULL, NULL} /* sentinel */
3672};
3673
3674
3675static PyMethodDef DBEnv_methods[] = {
3676 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
3677 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
3678 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
3679 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
3680 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
3681#if (DBVER >= 32)
3682 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
3683#endif
3684 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
3685 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
3686 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
3687 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
3688 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
3689#if (DBVER >= 32)
3690 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
3691 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
3692 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
3693#endif
3694 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
3695 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
3696 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
3697 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
3698 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
3699 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
3700 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
3701 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
3702 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
3703 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
3704 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
3705 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
3706 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
3707 {NULL, NULL} /* sentinel */
3708};
3709
3710
3711static PyMethodDef DBTxn_methods[] = {
3712 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
3713 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
3714 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
3715 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
3716 {NULL, NULL} /* sentinel */
3717};
3718
3719
3720static PyObject*
3721DB_getattr(DBObject* self, char *name)
3722{
3723 return Py_FindMethod(DB_methods, (PyObject* )self, name);
3724}
3725
3726
3727static PyObject*
3728DBEnv_getattr(DBEnvObject* self, char *name)
3729{
3730 if (!strcmp(name, "db_home")) {
3731 CHECK_ENV_NOT_CLOSED(self);
3732 if (self->db_env->db_home == NULL) {
3733 RETURN_NONE();
3734 }
3735 return PyString_FromString(self->db_env->db_home);
3736 }
3737
3738 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
3739}
3740
3741
3742static PyObject*
3743DBCursor_getattr(DBCursorObject* self, char *name)
3744{
3745 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
3746}
3747
3748static PyObject*
3749DBTxn_getattr(DBTxnObject* self, char *name)
3750{
3751 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
3752}
3753
3754static PyObject*
3755DBLock_getattr(DBLockObject* self, char *name)
3756{
3757 return NULL;
3758}
3759
3760statichere PyTypeObject DB_Type = {
3761 PyObject_HEAD_INIT(NULL)
3762 0, /*ob_size*/
3763 "DB", /*tp_name*/
3764 sizeof(DBObject), /*tp_basicsize*/
3765 0, /*tp_itemsize*/
3766 /* methods */
3767 (destructor)DB_dealloc, /*tp_dealloc*/
3768 0, /*tp_print*/
3769 (getattrfunc)DB_getattr, /*tp_getattr*/
3770 0, /*tp_setattr*/
3771 0, /*tp_compare*/
3772 0, /*tp_repr*/
3773 0, /*tp_as_number*/
3774 0, /*tp_as_sequence*/
3775 &DB_mapping,/*tp_as_mapping*/
3776 0, /*tp_hash*/
3777};
3778
3779
3780statichere PyTypeObject DBCursor_Type = {
3781 PyObject_HEAD_INIT(NULL)
3782 0, /*ob_size*/
3783 "DBCursor", /*tp_name*/
3784 sizeof(DBCursorObject), /*tp_basicsize*/
3785 0, /*tp_itemsize*/
3786 /* methods */
3787 (destructor)DBCursor_dealloc,/*tp_dealloc*/
3788 0, /*tp_print*/
3789 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
3790 0, /*tp_setattr*/
3791 0, /*tp_compare*/
3792 0, /*tp_repr*/
3793 0, /*tp_as_number*/
3794 0, /*tp_as_sequence*/
3795 0, /*tp_as_mapping*/
3796 0, /*tp_hash*/
3797};
3798
3799
3800statichere PyTypeObject DBEnv_Type = {
3801 PyObject_HEAD_INIT(NULL)
3802 0, /*ob_size*/
3803 "DBEnv", /*tp_name*/
3804 sizeof(DBEnvObject), /*tp_basicsize*/
3805 0, /*tp_itemsize*/
3806 /* methods */
3807 (destructor)DBEnv_dealloc, /*tp_dealloc*/
3808 0, /*tp_print*/
3809 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
3810 0, /*tp_setattr*/
3811 0, /*tp_compare*/
3812 0, /*tp_repr*/
3813 0, /*tp_as_number*/
3814 0, /*tp_as_sequence*/
3815 0, /*tp_as_mapping*/
3816 0, /*tp_hash*/
3817};
3818
3819statichere PyTypeObject DBTxn_Type = {
3820 PyObject_HEAD_INIT(NULL)
3821 0, /*ob_size*/
3822 "DBTxn", /*tp_name*/
3823 sizeof(DBTxnObject), /*tp_basicsize*/
3824 0, /*tp_itemsize*/
3825 /* methods */
3826 (destructor)DBTxn_dealloc, /*tp_dealloc*/
3827 0, /*tp_print*/
3828 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
3829 0, /*tp_setattr*/
3830 0, /*tp_compare*/
3831 0, /*tp_repr*/
3832 0, /*tp_as_number*/
3833 0, /*tp_as_sequence*/
3834 0, /*tp_as_mapping*/
3835 0, /*tp_hash*/
3836};
3837
3838
3839statichere PyTypeObject DBLock_Type = {
3840 PyObject_HEAD_INIT(NULL)
3841 0, /*ob_size*/
3842 "DBLock", /*tp_name*/
3843 sizeof(DBLockObject), /*tp_basicsize*/
3844 0, /*tp_itemsize*/
3845 /* methods */
3846 (destructor)DBLock_dealloc, /*tp_dealloc*/
3847 0, /*tp_print*/
3848 (getattrfunc)DBLock_getattr, /*tp_getattr*/
3849 0, /*tp_setattr*/
3850 0, /*tp_compare*/
3851 0, /*tp_repr*/
3852 0, /*tp_as_number*/
3853 0, /*tp_as_sequence*/
3854 0, /*tp_as_mapping*/
3855 0, /*tp_hash*/
3856};
3857
3858
3859/* --------------------------------------------------------------------- */
3860/* Module-level functions */
3861
3862static PyObject*
3863DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
3864{
3865 PyObject* dbenvobj = NULL;
3866 int flags = 0;
3867 char* kwnames[] = { "dbEnv", "flags", NULL};
3868
3869 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames, &dbenvobj, &flags))
3870 return NULL;
3871 if (dbenvobj == Py_None)
3872 dbenvobj = NULL;
3873 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
3874 makeTypeError("DBEnv", dbenvobj);
3875 return NULL;
3876 }
3877
3878 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
3879}
3880
3881
3882static PyObject*
3883DBEnv_construct(PyObject* self, PyObject* args)
3884{
3885 int flags = 0;
3886 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
3887 return (PyObject* )newDBEnvObject(flags);
3888}
3889
3890
3891static char bsddb_version_doc[] =
3892"Returns a tuple of major, minor, and patch release numbers of the\n\
3893underlying DB library.";
3894
3895static PyObject*
3896bsddb_version(PyObject* self, PyObject* args)
3897{
3898 int major, minor, patch;
3899
3900 if (!PyArg_ParseTuple(args, ":version"))
3901 return NULL;
3902 db_version(&major, &minor, &patch);
3903 return Py_BuildValue("(iii)", major, minor, patch);
3904}
3905
3906
3907/* List of functions defined in the module */
3908
3909static PyMethodDef bsddb_methods[] = {
3910 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
3911 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
3912 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
3913 {NULL, NULL} /* sentinel */
3914};
3915
3916
3917/* --------------------------------------------------------------------- */
3918/* Module initialization */
3919
3920
3921/* Convenience routine to export an integer value.
3922 * Errors are silently ignored, for better or for worse...
3923 */
3924#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
3925
3926
3927
3928DL_EXPORT(void) init_bsddb(void)
3929{
3930 PyObject* m;
3931 PyObject* d;
3932 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
3933 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
3934 PyObject* cvsid_s = PyString_FromString( rcs_id );
3935
3936 /* Initialize the type of the new type objects here; doing it here
3937 is required for portability to Windows without requiring C++. */
3938 DB_Type.ob_type = &PyType_Type;
3939 DBCursor_Type.ob_type = &PyType_Type;
3940 DBEnv_Type.ob_type = &PyType_Type;
3941 DBTxn_Type.ob_type = &PyType_Type;
3942 DBLock_Type.ob_type = &PyType_Type;
3943
3944
3945#ifdef WITH_THREAD
3946 /* Save the current interpreter, so callbacks can do the right thing. */
3947 _db_interpreterState = PyThreadState_Get()->interp;
3948#endif
3949
3950 /* Create the module and add the functions */
3951 m = Py_InitModule("_bsddb", bsddb_methods);
3952
3953 /* Add some symbolic constants to the module */
3954 d = PyModule_GetDict(m);
3955 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
3956 PyDict_SetItemString(d, "cvsid", cvsid_s);
3957 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
3958 Py_DECREF(pybsddb_version_s);
3959 pybsddb_version_s = NULL;
3960 Py_DECREF(cvsid_s);
3961 cvsid_s = NULL;
3962 Py_DECREF(db_version_s);
3963 db_version_s = NULL;
3964
3965 ADD_INT(d, DB_VERSION_MAJOR);
3966 ADD_INT(d, DB_VERSION_MINOR);
3967 ADD_INT(d, DB_VERSION_PATCH);
3968
3969 ADD_INT(d, DB_MAX_PAGES);
3970 ADD_INT(d, DB_MAX_RECORDS);
3971
3972 ADD_INT(d, DB_CLIENT);
3973 ADD_INT(d, DB_XA_CREATE);
3974
3975 ADD_INT(d, DB_CREATE);
3976 ADD_INT(d, DB_NOMMAP);
3977 ADD_INT(d, DB_THREAD);
3978
3979 ADD_INT(d, DB_FORCE);
3980 ADD_INT(d, DB_INIT_CDB);
3981 ADD_INT(d, DB_INIT_LOCK);
3982 ADD_INT(d, DB_INIT_LOG);
3983 ADD_INT(d, DB_INIT_MPOOL);
3984 ADD_INT(d, DB_INIT_TXN);
3985#if (DBVER >= 32)
3986 ADD_INT(d, DB_JOINENV);
3987#endif
3988
3989 ADD_INT(d, DB_RECOVER);
3990 ADD_INT(d, DB_RECOVER_FATAL);
3991 ADD_INT(d, DB_TXN_NOSYNC);
3992 ADD_INT(d, DB_USE_ENVIRON);
3993 ADD_INT(d, DB_USE_ENVIRON_ROOT);
3994
3995 ADD_INT(d, DB_LOCKDOWN);
3996 ADD_INT(d, DB_PRIVATE);
3997 ADD_INT(d, DB_SYSTEM_MEM);
3998
3999 ADD_INT(d, DB_TXN_SYNC);
4000 ADD_INT(d, DB_TXN_NOWAIT);
4001
4002 ADD_INT(d, DB_EXCL);
4003 ADD_INT(d, DB_FCNTL_LOCKING);
4004 ADD_INT(d, DB_ODDFILESIZE);
4005 ADD_INT(d, DB_RDWRMASTER);
4006 ADD_INT(d, DB_RDONLY);
4007 ADD_INT(d, DB_TRUNCATE);
4008#if (DBVER >= 32)
4009 ADD_INT(d, DB_EXTENT);
4010 ADD_INT(d, DB_CDB_ALLDB);
4011 ADD_INT(d, DB_VERIFY);
4012#endif
4013 ADD_INT(d, DB_UPGRADE);
4014
4015 ADD_INT(d, DB_AGGRESSIVE);
4016 ADD_INT(d, DB_NOORDERCHK);
4017 ADD_INT(d, DB_ORDERCHKONLY);
4018 ADD_INT(d, DB_PR_PAGE);
4019#if ! (DBVER >= 33)
4020 ADD_INT(d, DB_VRFY_FLAGMASK);
4021 ADD_INT(d, DB_PR_HEADERS);
4022#endif
4023 ADD_INT(d, DB_PR_RECOVERYTEST);
4024 ADD_INT(d, DB_SALVAGE);
4025
4026 ADD_INT(d, DB_LOCK_NORUN);
4027 ADD_INT(d, DB_LOCK_DEFAULT);
4028 ADD_INT(d, DB_LOCK_OLDEST);
4029 ADD_INT(d, DB_LOCK_RANDOM);
4030 ADD_INT(d, DB_LOCK_YOUNGEST);
4031#if (DBVER >= 33)
4032 ADD_INT(d, DB_LOCK_MAXLOCKS);
4033 ADD_INT(d, DB_LOCK_MINLOCKS);
4034 ADD_INT(d, DB_LOCK_MINWRITE);
4035#endif
4036
4037
4038#if (DBVER >= 33)
4039 _addIntToDict(d, "DB_LOCK_CONFLICT", 0); /* docs say to use zero instead */
4040#else
4041 ADD_INT(d, DB_LOCK_CONFLICT);
4042#endif
4043
4044 ADD_INT(d, DB_LOCK_DUMP);
4045 ADD_INT(d, DB_LOCK_GET);
4046 ADD_INT(d, DB_LOCK_INHERIT);
4047 ADD_INT(d, DB_LOCK_PUT);
4048 ADD_INT(d, DB_LOCK_PUT_ALL);
4049 ADD_INT(d, DB_LOCK_PUT_OBJ);
4050
4051 ADD_INT(d, DB_LOCK_NG);
4052 ADD_INT(d, DB_LOCK_READ);
4053 ADD_INT(d, DB_LOCK_WRITE);
4054 ADD_INT(d, DB_LOCK_NOWAIT);
4055#if (DBVER >= 32)
4056 ADD_INT(d, DB_LOCK_WAIT);
4057#endif
4058 ADD_INT(d, DB_LOCK_IWRITE);
4059 ADD_INT(d, DB_LOCK_IREAD);
4060 ADD_INT(d, DB_LOCK_IWR);
4061#if (DBVER >= 33)
4062 ADD_INT(d, DB_LOCK_DIRTY);
4063 ADD_INT(d, DB_LOCK_WWRITE);
4064#endif
4065
4066 ADD_INT(d, DB_LOCK_RECORD);
4067 ADD_INT(d, DB_LOCK_UPGRADE);
4068#if (DBVER >= 32)
4069 ADD_INT(d, DB_LOCK_SWITCH);
4070#endif
4071#if (DBVER >= 33)
4072 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4073#endif
4074
4075 ADD_INT(d, DB_LOCK_NOWAIT);
4076 ADD_INT(d, DB_LOCK_RECORD);
4077 ADD_INT(d, DB_LOCK_UPGRADE);
4078
4079#if (DBVER >= 33)
4080 ADD_INT(d, DB_LSTAT_ABORTED);
4081 ADD_INT(d, DB_LSTAT_ERR);
4082 ADD_INT(d, DB_LSTAT_FREE);
4083 ADD_INT(d, DB_LSTAT_HELD);
4084#if (DBVER == 33)
4085 ADD_INT(d, DB_LSTAT_NOGRANT);
4086#endif
4087 ADD_INT(d, DB_LSTAT_PENDING);
4088 ADD_INT(d, DB_LSTAT_WAITING);
4089#endif
4090
4091 ADD_INT(d, DB_ARCH_ABS);
4092 ADD_INT(d, DB_ARCH_DATA);
4093 ADD_INT(d, DB_ARCH_LOG);
4094
4095 ADD_INT(d, DB_BTREE);
4096 ADD_INT(d, DB_HASH);
4097 ADD_INT(d, DB_RECNO);
4098 ADD_INT(d, DB_QUEUE);
4099 ADD_INT(d, DB_UNKNOWN);
4100
4101 ADD_INT(d, DB_DUP);
4102 ADD_INT(d, DB_DUPSORT);
4103 ADD_INT(d, DB_RECNUM);
4104 ADD_INT(d, DB_RENUMBER);
4105 ADD_INT(d, DB_REVSPLITOFF);
4106 ADD_INT(d, DB_SNAPSHOT);
4107
4108 ADD_INT(d, DB_JOIN_NOSORT);
4109
4110 ADD_INT(d, DB_AFTER);
4111 ADD_INT(d, DB_APPEND);
4112 ADD_INT(d, DB_BEFORE);
4113 ADD_INT(d, DB_CACHED_COUNTS);
4114 ADD_INT(d, DB_CHECKPOINT);
4115#if (DBVER >= 33)
4116 ADD_INT(d, DB_COMMIT);
4117#endif
4118 ADD_INT(d, DB_CONSUME);
4119#if (DBVER >= 32)
4120 ADD_INT(d, DB_CONSUME_WAIT);
4121#endif
4122 ADD_INT(d, DB_CURLSN);
4123 ADD_INT(d, DB_CURRENT);
4124#if (DBVER >= 33)
4125 ADD_INT(d, DB_FAST_STAT);
4126#endif
4127 ADD_INT(d, DB_FIRST);
4128 ADD_INT(d, DB_FLUSH);
4129 ADD_INT(d, DB_GET_BOTH);
4130 ADD_INT(d, DB_GET_RECNO);
4131 ADD_INT(d, DB_JOIN_ITEM);
4132 ADD_INT(d, DB_KEYFIRST);
4133 ADD_INT(d, DB_KEYLAST);
4134 ADD_INT(d, DB_LAST);
4135 ADD_INT(d, DB_NEXT);
4136 ADD_INT(d, DB_NEXT_DUP);
4137 ADD_INT(d, DB_NEXT_NODUP);
4138 ADD_INT(d, DB_NODUPDATA);
4139 ADD_INT(d, DB_NOOVERWRITE);
4140 ADD_INT(d, DB_NOSYNC);
4141 ADD_INT(d, DB_POSITION);
4142 ADD_INT(d, DB_PREV);
4143 ADD_INT(d, DB_PREV_NODUP);
4144 ADD_INT(d, DB_RECORDCOUNT);
4145 ADD_INT(d, DB_SET);
4146 ADD_INT(d, DB_SET_RANGE);
4147 ADD_INT(d, DB_SET_RECNO);
4148 ADD_INT(d, DB_WRITECURSOR);
4149
4150 ADD_INT(d, DB_OPFLAGS_MASK);
4151 ADD_INT(d, DB_RMW);
4152#if (DBVER >= 33)
4153 ADD_INT(d, DB_DIRTY_READ);
4154 ADD_INT(d, DB_MULTIPLE);
4155 ADD_INT(d, DB_MULTIPLE_KEY);
4156#endif
4157
4158#if (DBVER >= 33)
4159 ADD_INT(d, DB_DONOTINDEX);
4160#endif
4161
4162 ADD_INT(d, DB_INCOMPLETE);
4163 ADD_INT(d, DB_KEYEMPTY);
4164 ADD_INT(d, DB_KEYEXIST);
4165 ADD_INT(d, DB_LOCK_DEADLOCK);
4166 ADD_INT(d, DB_LOCK_NOTGRANTED);
4167 ADD_INT(d, DB_NOSERVER);
4168 ADD_INT(d, DB_NOSERVER_HOME);
4169 ADD_INT(d, DB_NOSERVER_ID);
4170 ADD_INT(d, DB_NOTFOUND);
4171 ADD_INT(d, DB_OLD_VERSION);
4172 ADD_INT(d, DB_RUNRECOVERY);
4173 ADD_INT(d, DB_VERIFY_BAD);
4174#if (DBVER >= 33)
4175 ADD_INT(d, DB_PAGE_NOTFOUND);
4176 ADD_INT(d, DB_SECONDARY_BAD);
4177#endif
4178#if (DBVER >= 40)
4179 ADD_INT(d, DB_STAT_CLEAR);
4180 ADD_INT(d, DB_REGION_INIT);
4181 ADD_INT(d, DB_NOLOCKING);
4182 ADD_INT(d, DB_YIELDCPU);
4183 ADD_INT(d, DB_PANIC_ENVIRONMENT);
4184 ADD_INT(d, DB_NOPANIC);
4185#endif
4186
4187 ADD_INT(d, EINVAL);
4188 ADD_INT(d, EACCES);
4189 ADD_INT(d, ENOSPC);
4190 ADD_INT(d, ENOMEM);
4191 ADD_INT(d, EAGAIN);
4192 ADD_INT(d, EBUSY);
4193 ADD_INT(d, EEXIST);
4194 ADD_INT(d, ENOENT);
4195 ADD_INT(d, EPERM);
4196
4197
4198
4199 /* The base exception class is DBError */
4200 DBError = PyErr_NewException("bsddb3._db.DBError", NULL, NULL);
4201 PyDict_SetItemString(d, "DBError", DBError);
4202
4203 /* Some magic to make DBNotFoundError derive from both DBError and
4204 KeyError, since the API only supports using one base class. */
4205 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
4206 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
4207 Py_file_input, d, d);
4208 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
4209 PyDict_DelItemString(d, "KeyError");
4210
4211
4212 /* All the rest of the exceptions derive only from DBError */
4213#define MAKE_EX(name) name = PyErr_NewException("bsddb3._db." #name, DBError, NULL); \
4214 PyDict_SetItemString(d, #name, name)
4215
4216#if !INCOMPLETE_IS_WARNING
4217 MAKE_EX(DBIncompleteError);
4218#endif
4219 MAKE_EX(DBKeyEmptyError);
4220 MAKE_EX(DBKeyExistError);
4221 MAKE_EX(DBLockDeadlockError);
4222 MAKE_EX(DBLockNotGrantedError);
4223 MAKE_EX(DBOldVersionError);
4224 MAKE_EX(DBRunRecoveryError);
4225 MAKE_EX(DBVerifyBadError);
4226 MAKE_EX(DBNoServerError);
4227 MAKE_EX(DBNoServerHomeError);
4228 MAKE_EX(DBNoServerIDError);
4229#if (DBVER >= 33)
4230 MAKE_EX(DBPageNotFoundError);
4231 MAKE_EX(DBSecondaryBadError);
4232#endif
4233
4234 MAKE_EX(DBInvalidArgError);
4235 MAKE_EX(DBAccessError);
4236 MAKE_EX(DBNoSpaceError);
4237 MAKE_EX(DBNoMemoryError);
4238 MAKE_EX(DBAgainError);
4239 MAKE_EX(DBBusyError);
4240 MAKE_EX(DBFileExistsError);
4241 MAKE_EX(DBNoSuchFileError);
4242 MAKE_EX(DBPermissionsError);
4243
4244#undef MAKE_EX
4245
4246 /* Check for errors */
4247 if (PyErr_Occurred()) {
4248 PyErr_Print();
4249 Py_FatalError("can't initialize module _db");
4250 }
4251}
4252
4253
4254