source: vendor/python/2.5/Modules/_bsddb.c

Last change on this file was 3225, checked in by bird, 18 years ago

Python 2.5

File size: 162.3 KB
Line 
1/*----------------------------------------------------------------------
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. It has since been updated
39 * to compile with BerkeleyDB versions 3.2 through 4.2.
40 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
46 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
54 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
63 *
64 * This module contains 6 types:
65 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
71 * DBSequence (Sequence)
72 *
73 */
74
75/* --------------------------------------------------------------------- */
76
77/*
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
82 *
83 * --Robin
84 */
85
86/* --------------------------------------------------------------------- */
87
88#include <stddef.h> /* for offsetof() */
89#include <Python.h>
90#include <db.h>
91
92/* --------------------------------------------------------------------- */
93/* Various macro definitions */
94
95/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
97#if DB_VERSION_MINOR > 9
98#error "eek! DBVER can't handle minor versions > 9"
99#endif
100
101#define PY_BSDDB_VERSION "4.4.5"
102static char *rcs_id = "$Id: _bsddb.c 51251 2006-08-13 18:11:43Z neal.norwitz $";
103
104
105#if (PY_VERSION_HEX < 0x02050000)
106typedef int Py_ssize_t;
107#endif
108
109#ifdef WITH_THREAD
110
111/* These are for when calling Python --> C */
112#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
114
115/* For 2.3, use the PyGILState_ calls */
116#if (PY_VERSION_HEX >= 0x02030000)
117#define MYDB_USE_GILSTATE
118#endif
119
120/* and these are for calling C --> Python */
121#if defined(MYDB_USE_GILSTATE)
122#define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124#define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126#else /* MYDB_USE_GILSTATE */
127/* Pre GILState API - do it the long old way */
128static PyInterpreterState* _db_interpreterState = NULL;
129#define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
135
136#define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
141 }
142#endif /* MYDB_USE_GILSTATE */
143
144#else
145/* Compiled without threads - avoid all this cruft */
146#define MYDB_BEGIN_ALLOW_THREADS
147#define MYDB_END_ALLOW_THREADS
148#define MYDB_BEGIN_BLOCK_THREADS
149#define MYDB_END_BLOCK_THREADS
150
151#endif
152
153/* Should DB_INCOMPLETE be turned into a warning or an exception? */
154#define INCOMPLETE_IS_WARNING 1
155
156/* --------------------------------------------------------------------- */
157/* Exceptions */
158
159static PyObject* DBError; /* Base class, all others derive from this */
160static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
161static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
162static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169static PyObject* DBNoServerError; /* DB_NOSERVER */
170static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172#if (DBVER >= 33)
173static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175#endif
176
177#if !INCOMPLETE_IS_WARNING
178static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179#endif
180
181static PyObject* DBInvalidArgError; /* EINVAL */
182static PyObject* DBAccessError; /* EACCES */
183static PyObject* DBNoSpaceError; /* ENOSPC */
184static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
185static PyObject* DBAgainError; /* EAGAIN */
186static PyObject* DBBusyError; /* EBUSY */
187static PyObject* DBFileExistsError; /* EEXIST */
188static PyObject* DBNoSuchFileError; /* ENOENT */
189static PyObject* DBPermissionsError; /* EPERM */
190
191#if (DBVER < 43)
192#define DB_BUFFER_SMALL ENOMEM
193#endif
194
195
196/* --------------------------------------------------------------------- */
197/* Structure definitions */
198
199#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200#define HAVE_WEAKREF
201#else
202#undef HAVE_WEAKREF
203#endif
204
205/* if Python >= 2.1 better support warnings */
206#if PYTHON_API_VERSION >= 1010
207#define HAVE_WARNINGS
208#else
209#undef HAVE_WARNINGS
210#endif
211
212#if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214#define PyObject_New PyObject_NEW
215#define PyObject_Del PyMem_DEL
216#endif
217
218struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
224 unsigned int cursorSetReturnsNone : 1;
225};
226
227#define DEFAULT_GET_RETURNS_NONE 1
228#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
229
230typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
233 u_int32_t flags; /* saved flags from open() */
234 int closed;
235 struct behaviourFlags moduleFlags;
236#ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238#endif
239} DBEnvObject;
240
241
242typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
248 int haveStat;
249 struct behaviourFlags moduleFlags;
250#if (DBVER >= 33)
251 PyObject* associateCallback;
252 PyObject* btCompareCallback;
253 int primaryDBType;
254#endif
255#ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257#endif
258} DBObject;
259
260
261typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
265#ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267#endif
268} DBCursorObject;
269
270
271typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
274 PyObject *env;
275#ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277#endif
278} DBTxnObject;
279
280
281typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
284#ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286#endif
287} DBLockObject;
288
289#if (DBVER >= 43)
290typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294#ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296#endif
297} DBSequenceObject;
298staticforward PyTypeObject DBSequence_Type;
299#endif
300
301staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
302
303#define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
308#if (DBVER >= 43)
309#define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310#endif
311
312
313/* --------------------------------------------------------------------- */
314/* Utility macros and functions */
315
316#define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
319 }
320
321#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
322
323#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
330 }
331
332#define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
334
335#define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
337
338#define CHECK_CURSOR_NOT_CLOSED(curs) \
339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
340
341#if (DBVER >= 43)
342#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344#endif
345
346#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
348
349#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
350
351#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
353
354
355static int makeDBError(int err);
356
357
358/* Return the access method type of the DBObject */
359static int _DB_get_type(DBObject* self)
360{
361#if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
367 }
368 return type;
369#else
370 return self->db->get_type(self->db);
371#endif
372}
373
374
375/* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377static int make_dbt(PyObject* obj, DBT* dbt)
378{
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
382 }
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
385 "Data values must be of type string or None.");
386 return 0;
387 }
388 return 1;
389}
390
391
392/* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
394
395 Caller MUST call FREE_DBT(key) when done. */
396static int
397make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
398{
399 db_recno_t recno;
400 int type;
401
402 CLEAR_DBT(*key);
403 if (keyobj == Py_None) {
404 type = _DB_get_type(self);
405 if (type == -1)
406 return 0;
407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
412 }
413 /* no need to do anything, the structure has already been zeroed */
414 }
415
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
425 return 0;
426 }
427
428 key->data = PyString_AS_STRING(keyobj);
429 key->size = PyString_GET_SIZE(keyobj);
430 }
431
432 else if (PyInt_Check(keyobj)) {
433 /* verify access method type */
434 type = _DB_get_type(self);
435 if (type == -1)
436 return 0;
437 if (type == DB_BTREE && pflags != NULL) {
438 /* if BTREE then an Integer key is allowed with the
439 * DB_SET_RECNO flag */
440 *pflags |= DB_SET_RECNO;
441 }
442 else if (type != DB_RECNO && type != DB_QUEUE) {
443 PyErr_SetString(
444 PyExc_TypeError,
445 "Integer keys only allowed for Recno and Queue DB's");
446 return 0;
447 }
448
449 /* Make a key out of the requested recno, use allocated space so DB
450 * will be able to realloc room for the real key if needed. */
451 recno = PyInt_AS_LONG(keyobj);
452 key->data = malloc(sizeof(db_recno_t));
453 if (key->data == NULL) {
454 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
455 return 0;
456 }
457 key->ulen = key->size = sizeof(db_recno_t);
458 memcpy(key->data, &recno, sizeof(db_recno_t));
459 key->flags = DB_DBT_REALLOC;
460 }
461 else {
462 PyErr_Format(PyExc_TypeError,
463 "String or Integer object expected for key, %s found",
464 keyobj->ob_type->tp_name);
465 return 0;
466 }
467
468 return 1;
469}
470
471
472/* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
479 }
480
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
484 }
485
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
490}
491
492/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493/* TODO: make this use the native libc strlcpy() when available (BSD) */
494unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
495{
496 unsigned int srclen, copylen;
497
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
506
507 return srclen;
508}
509
510/* Callback used to save away more information about errors from the DB
511 * library. */
512static char _db_errmsg[1024];
513#if (DBVER <= 42)
514static void _db_errorCallback(const char* prefix, char* msg)
515#else
516static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518#endif
519{
520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
521}
522
523
524/* make a nice exception object to raise for errors. */
525static int makeDBError(int err)
526{
527 char errTxt[2048]; /* really big, just in case... */
528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
530 int exceptionRaised = 0;
531 unsigned int bytes_left;
532
533 switch (err) {
534 case 0: /* successful, no error */ break;
535
536#if (DBVER < 41)
537 case DB_INCOMPLETE:
538#if INCOMPLETE_IS_WARNING
539 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
540 /* Ensure that bytes_left never goes negative */
541 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
542 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
543 assert(bytes_left >= 0);
544 strcat(errTxt, " -- ");
545 strncat(errTxt, _db_errmsg, bytes_left);
546 }
547 _db_errmsg[0] = 0;
548#ifdef HAVE_WARNINGS
549 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
550#else
551 fprintf(stderr, errTxt);
552 fprintf(stderr, "\n");
553#endif
554
555#else /* do an exception instead */
556 errObj = DBIncompleteError;
557#endif
558 break;
559#endif /* DBVER < 41 */
560
561 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
562 case DB_KEYEXIST: errObj = DBKeyExistError; break;
563 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
564 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
565 case DB_NOTFOUND: errObj = DBNotFoundError; break;
566 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
567 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
568 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
569 case DB_NOSERVER: errObj = DBNoServerError; break;
570 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
571 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
572#if (DBVER >= 33)
573 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
574 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
575#endif
576 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
577
578#if (DBVER >= 43)
579 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
580 case ENOMEM: errObj = PyExc_MemoryError; break;
581#endif
582 case EINVAL: errObj = DBInvalidArgError; break;
583 case EACCES: errObj = DBAccessError; break;
584 case ENOSPC: errObj = DBNoSpaceError; break;
585 case EAGAIN: errObj = DBAgainError; break;
586 case EBUSY : errObj = DBBusyError; break;
587 case EEXIST: errObj = DBFileExistsError; break;
588 case ENOENT: errObj = DBNoSuchFileError; break;
589 case EPERM : errObj = DBPermissionsError; break;
590
591 default: errObj = DBError; break;
592 }
593
594 if (errObj != NULL) {
595 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
596 /* Ensure that bytes_left never goes negative */
597 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
598 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
599 assert(bytes_left >= 0);
600 strcat(errTxt, " -- ");
601 strncat(errTxt, _db_errmsg, bytes_left);
602 }
603 _db_errmsg[0] = 0;
604
605 errTuple = Py_BuildValue("(is)", err, errTxt);
606 PyErr_SetObject(errObj, errTuple);
607 Py_DECREF(errTuple);
608 }
609
610 return ((errObj != NULL) || exceptionRaised);
611}
612
613
614
615/* set a type exception */
616static void makeTypeError(char* expected, PyObject* found)
617{
618 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
619 expected, found->ob_type->tp_name);
620}
621
622
623/* verify that an obj is either None or a DBTxn, and set the txn pointer */
624static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
625{
626 if (txnobj == Py_None || txnobj == NULL) {
627 *txn = NULL;
628 return 1;
629 }
630 if (DBTxnObject_Check(txnobj)) {
631 *txn = ((DBTxnObject*)txnobj)->txn;
632 return 1;
633 }
634 else
635 makeTypeError("DBTxn", txnobj);
636 return 0;
637}
638
639
640/* Delete a key from a database
641 Returns 0 on success, -1 on an error. */
642static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
643{
644 int err;
645
646 MYDB_BEGIN_ALLOW_THREADS;
647 err = self->db->del(self->db, txn, key, 0);
648 MYDB_END_ALLOW_THREADS;
649 if (makeDBError(err)) {
650 return -1;
651 }
652 self->haveStat = 0;
653 return 0;
654}
655
656
657/* Store a key into a database
658 Returns 0 on success, -1 on an error. */
659static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
660{
661 int err;
662
663 MYDB_BEGIN_ALLOW_THREADS;
664 err = self->db->put(self->db, txn, key, data, flags);
665 MYDB_END_ALLOW_THREADS;
666 if (makeDBError(err)) {
667 return -1;
668 }
669 self->haveStat = 0;
670 return 0;
671}
672
673/* Get a key/data pair from a cursor */
674static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
675 PyObject *args, PyObject *kwargs, char *format)
676{
677 int err;
678 PyObject* retval = NULL;
679 DBT key, data;
680 int dlen = -1;
681 int doff = -1;
682 int flags = 0;
683 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
684
685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
686 &flags, &dlen, &doff))
687 return NULL;
688
689 CHECK_CURSOR_NOT_CLOSED(self);
690
691 flags |= extra_flags;
692 CLEAR_DBT(key);
693 CLEAR_DBT(data);
694 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
695 /* Tell BerkeleyDB to malloc the return value (thread safe) */
696 data.flags = DB_DBT_MALLOC;
697 key.flags = DB_DBT_MALLOC;
698 }
699 if (!add_partial_dbt(&data, dlen, doff))
700 return NULL;
701
702 MYDB_BEGIN_ALLOW_THREADS;
703 err = self->dbc->c_get(self->dbc, &key, &data, flags);
704 MYDB_END_ALLOW_THREADS;
705
706 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
707 && self->mydb->moduleFlags.getReturnsNone) {
708 Py_INCREF(Py_None);
709 retval = Py_None;
710 }
711 else if (makeDBError(err)) {
712 retval = NULL;
713 }
714 else { /* otherwise, success! */
715
716 /* if Recno or Queue, return the key as an Int */
717 switch (_DB_get_type(self->mydb)) {
718 case -1:
719 retval = NULL;
720 break;
721
722 case DB_RECNO:
723 case DB_QUEUE:
724 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
725 data.data, data.size);
726 break;
727 case DB_HASH:
728 case DB_BTREE:
729 default:
730 retval = Py_BuildValue("s#s#", key.data, key.size,
731 data.data, data.size);
732 break;
733 }
734 }
735 if (!err) {
736 FREE_DBT(key);
737 FREE_DBT(data);
738 }
739 return retval;
740}
741
742
743/* add an integer to a dictionary using the given name as a key */
744static void _addIntToDict(PyObject* dict, char *name, int value)
745{
746 PyObject* v = PyInt_FromLong((long) value);
747 if (!v || PyDict_SetItemString(dict, name, v))
748 PyErr_Clear();
749
750 Py_XDECREF(v);
751}
752#if (DBVER >= 43)
753/* add an db_seq_t to a dictionary using the given name as a key */
754static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
755{
756 PyObject* v = PyLong_FromLongLong(value);
757 if (!v || PyDict_SetItemString(dict, name, v))
758 PyErr_Clear();
759
760 Py_XDECREF(v);
761}
762#endif
763
764
765
766/* --------------------------------------------------------------------- */
767/* Allocators and deallocators */
768
769static DBObject*
770newDBObject(DBEnvObject* arg, int flags)
771{
772 DBObject* self;
773 DB_ENV* db_env = NULL;
774 int err;
775
776 self = PyObject_New(DBObject, &DB_Type);
777 if (self == NULL)
778 return NULL;
779
780 self->haveStat = 0;
781 self->flags = 0;
782 self->setflags = 0;
783 self->myenvobj = NULL;
784#if (DBVER >= 33)
785 self->associateCallback = NULL;
786 self->btCompareCallback = NULL;
787 self->primaryDBType = 0;
788#endif
789#ifdef HAVE_WEAKREF
790 self->in_weakreflist = NULL;
791#endif
792
793 /* keep a reference to our python DBEnv object */
794 if (arg) {
795 Py_INCREF(arg);
796 self->myenvobj = arg;
797 db_env = arg->db_env;
798 }
799
800 if (self->myenvobj)
801 self->moduleFlags = self->myenvobj->moduleFlags;
802 else
803 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
804 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
805
806 MYDB_BEGIN_ALLOW_THREADS;
807 err = db_create(&self->db, db_env, flags);
808 if (self->db != NULL) {
809 self->db->set_errcall(self->db, _db_errorCallback);
810#if (DBVER >= 33)
811 self->db->app_private = (void*)self;
812#endif
813 }
814 MYDB_END_ALLOW_THREADS;
815 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
816 * list so that a DBEnv can refuse to close without aborting any open
817 * DBTxns and closing any open DBs first. */
818 if (makeDBError(err)) {
819 if (self->myenvobj) {
820 Py_DECREF(self->myenvobj);
821 self->myenvobj = NULL;
822 }
823 PyObject_Del(self);
824 self = NULL;
825 }
826 return self;
827}
828
829
830static void
831DB_dealloc(DBObject* self)
832{
833 if (self->db != NULL) {
834 /* avoid closing a DB when its DBEnv has been closed out from under
835 * it */
836 if (!self->myenvobj ||
837 (self->myenvobj && self->myenvobj->db_env))
838 {
839 MYDB_BEGIN_ALLOW_THREADS;
840 self->db->close(self->db, 0);
841 MYDB_END_ALLOW_THREADS;
842#ifdef HAVE_WARNINGS
843 } else {
844 PyErr_Warn(PyExc_RuntimeWarning,
845 "DB could not be closed in destructor: DBEnv already closed");
846#endif
847 }
848 self->db = NULL;
849 }
850#ifdef HAVE_WEAKREF
851 if (self->in_weakreflist != NULL) {
852 PyObject_ClearWeakRefs((PyObject *) self);
853 }
854#endif
855 if (self->myenvobj) {
856 Py_DECREF(self->myenvobj);
857 self->myenvobj = NULL;
858 }
859#if (DBVER >= 33)
860 if (self->associateCallback != NULL) {
861 Py_DECREF(self->associateCallback);
862 self->associateCallback = NULL;
863 }
864 if (self->btCompareCallback != NULL) {
865 Py_DECREF(self->btCompareCallback);
866 self->btCompareCallback = NULL;
867 }
868#endif
869 PyObject_Del(self);
870}
871
872
873static DBCursorObject*
874newDBCursorObject(DBC* dbc, DBObject* db)
875{
876 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
877 if (self == NULL)
878 return NULL;
879
880 self->dbc = dbc;
881 self->mydb = db;
882#ifdef HAVE_WEAKREF
883 self->in_weakreflist = NULL;
884#endif
885 Py_INCREF(self->mydb);
886 return self;
887}
888
889
890static void
891DBCursor_dealloc(DBCursorObject* self)
892{
893 int err;
894
895#ifdef HAVE_WEAKREF
896 if (self->in_weakreflist != NULL) {
897 PyObject_ClearWeakRefs((PyObject *) self);
898 }
899#endif
900
901 if (self->dbc != NULL) {
902 MYDB_BEGIN_ALLOW_THREADS;
903 /* If the underlying database has been closed, we don't
904 need to do anything. If the environment has been closed
905 we need to leak, as BerkeleyDB will crash trying to access
906 the environment. There was an exception when the
907 user closed the environment even though there still was
908 a database open. */
909 if (self->mydb->db && self->mydb->myenvobj &&
910 !self->mydb->myenvobj->closed)
911 err = self->dbc->c_close(self->dbc);
912 self->dbc = NULL;
913 MYDB_END_ALLOW_THREADS;
914 }
915 Py_XDECREF( self->mydb );
916 PyObject_Del(self);
917}
918
919
920static DBEnvObject*
921newDBEnvObject(int flags)
922{
923 int err;
924 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
925 if (self == NULL)
926 return NULL;
927
928 self->closed = 1;
929 self->flags = flags;
930 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
931 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
932#ifdef HAVE_WEAKREF
933 self->in_weakreflist = NULL;
934#endif
935
936 MYDB_BEGIN_ALLOW_THREADS;
937 err = db_env_create(&self->db_env, flags);
938 MYDB_END_ALLOW_THREADS;
939 if (makeDBError(err)) {
940 PyObject_Del(self);
941 self = NULL;
942 }
943 else {
944 self->db_env->set_errcall(self->db_env, _db_errorCallback);
945 }
946 return self;
947}
948
949
950static void
951DBEnv_dealloc(DBEnvObject* self)
952{
953#ifdef HAVE_WEAKREF
954 if (self->in_weakreflist != NULL) {
955 PyObject_ClearWeakRefs((PyObject *) self);
956 }
957#endif
958
959 if (self->db_env && !self->closed) {
960 MYDB_BEGIN_ALLOW_THREADS;
961 self->db_env->close(self->db_env, 0);
962 MYDB_END_ALLOW_THREADS;
963 }
964 PyObject_Del(self);
965}
966
967
968static DBTxnObject*
969newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
970{
971 int err;
972 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
973 if (self == NULL)
974 return NULL;
975 Py_INCREF(myenv);
976 self->env = (PyObject*)myenv;
977#ifdef HAVE_WEAKREF
978 self->in_weakreflist = NULL;
979#endif
980
981 MYDB_BEGIN_ALLOW_THREADS;
982#if (DBVER >= 40)
983 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
984#else
985 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
986#endif
987 MYDB_END_ALLOW_THREADS;
988 if (makeDBError(err)) {
989 Py_DECREF(self->env);
990 PyObject_Del(self);
991 self = NULL;
992 }
993 return self;
994}
995
996
997static void
998DBTxn_dealloc(DBTxnObject* self)
999{
1000#ifdef HAVE_WEAKREF
1001 if (self->in_weakreflist != NULL) {
1002 PyObject_ClearWeakRefs((PyObject *) self);
1003 }
1004#endif
1005
1006#ifdef HAVE_WARNINGS
1007 if (self->txn) {
1008 /* it hasn't been finalized, abort it! */
1009 MYDB_BEGIN_ALLOW_THREADS;
1010#if (DBVER >= 40)
1011 self->txn->abort(self->txn);
1012#else
1013 txn_abort(self->txn);
1014#endif
1015 MYDB_END_ALLOW_THREADS;
1016 PyErr_Warn(PyExc_RuntimeWarning,
1017 "DBTxn aborted in destructor. No prior commit() or abort().");
1018 }
1019#endif
1020
1021 Py_DECREF(self->env);
1022 PyObject_Del(self);
1023}
1024
1025
1026static DBLockObject*
1027newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1028 db_lockmode_t lock_mode, int flags)
1029{
1030 int err;
1031 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
1032 if (self == NULL)
1033 return NULL;
1034#ifdef HAVE_WEAKREF
1035 self->in_weakreflist = NULL;
1036#endif
1037
1038 MYDB_BEGIN_ALLOW_THREADS;
1039#if (DBVER >= 40)
1040 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1041 &self->lock);
1042#else
1043 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1044#endif
1045 MYDB_END_ALLOW_THREADS;
1046 if (makeDBError(err)) {
1047 PyObject_Del(self);
1048 self = NULL;
1049 }
1050
1051 return self;
1052}
1053
1054
1055static void
1056DBLock_dealloc(DBLockObject* self)
1057{
1058#ifdef HAVE_WEAKREF
1059 if (self->in_weakreflist != NULL) {
1060 PyObject_ClearWeakRefs((PyObject *) self);
1061 }
1062#endif
1063 /* TODO: is this lock held? should we release it? */
1064
1065 PyObject_Del(self);
1066}
1067
1068
1069#if (DBVER >= 43)
1070static DBSequenceObject*
1071newDBSequenceObject(DBObject* mydb, int flags)
1072{
1073 int err;
1074 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1075 if (self == NULL)
1076 return NULL;
1077 Py_INCREF(mydb);
1078 self->mydb = mydb;
1079#ifdef HAVE_WEAKREF
1080 self->in_weakreflist = NULL;
1081#endif
1082
1083
1084 MYDB_BEGIN_ALLOW_THREADS;
1085 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1086 MYDB_END_ALLOW_THREADS;
1087 if (makeDBError(err)) {
1088 Py_DECREF(self->mydb);
1089 PyObject_Del(self);
1090 self = NULL;
1091 }
1092
1093 return self;
1094}
1095
1096
1097static void
1098DBSequence_dealloc(DBSequenceObject* self)
1099{
1100#ifdef HAVE_WEAKREF
1101 if (self->in_weakreflist != NULL) {
1102 PyObject_ClearWeakRefs((PyObject *) self);
1103 }
1104#endif
1105
1106 Py_DECREF(self->mydb);
1107 PyObject_Del(self);
1108}
1109#endif
1110
1111/* --------------------------------------------------------------------- */
1112/* DB methods */
1113
1114static PyObject*
1115DB_append(DBObject* self, PyObject* args)
1116{
1117 PyObject* txnobj = NULL;
1118 PyObject* dataobj;
1119 db_recno_t recno;
1120 DBT key, data;
1121 DB_TXN *txn = NULL;
1122
1123 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
1124 return NULL;
1125
1126 CHECK_DB_NOT_CLOSED(self);
1127
1128 /* make a dummy key out of a recno */
1129 recno = 0;
1130 CLEAR_DBT(key);
1131 key.data = &recno;
1132 key.size = sizeof(recno);
1133 key.ulen = key.size;
1134 key.flags = DB_DBT_USERMEM;
1135
1136 if (!make_dbt(dataobj, &data)) return NULL;
1137 if (!checkTxnObj(txnobj, &txn)) return NULL;
1138
1139 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1140 return NULL;
1141
1142 return PyInt_FromLong(recno);
1143}
1144
1145
1146#if (DBVER >= 33)
1147
1148static int
1149_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1150 DBT* secKey)
1151{
1152 int retval = DB_DONOTINDEX;
1153 DBObject* secondaryDB = (DBObject*)db->app_private;
1154 PyObject* callback = secondaryDB->associateCallback;
1155 int type = secondaryDB->primaryDBType;
1156 PyObject* args;
1157 PyObject* result = NULL;
1158
1159
1160 if (callback != NULL) {
1161 MYDB_BEGIN_BLOCK_THREADS;
1162
1163 if (type == DB_RECNO || type == DB_QUEUE)
1164 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1165 priData->data, priData->size);
1166 else
1167 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1168 priData->data, priData->size);
1169 if (args != NULL) {
1170 result = PyEval_CallObject(callback, args);
1171 }
1172 if (args == NULL || result == NULL) {
1173 PyErr_Print();
1174 }
1175 else if (result == Py_None) {
1176 retval = DB_DONOTINDEX;
1177 }
1178 else if (PyInt_Check(result)) {
1179 retval = PyInt_AsLong(result);
1180 }
1181 else if (PyString_Check(result)) {
1182 char* data;
1183 Py_ssize_t size;
1184
1185 CLEAR_DBT(*secKey);
1186#if PYTHON_API_VERSION <= 1007
1187 /* 1.5 compatibility */
1188 size = PyString_Size(result);
1189 data = PyString_AsString(result);
1190#else
1191 PyString_AsStringAndSize(result, &data, &size);
1192#endif
1193 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1194 secKey->data = malloc(size); /* TODO, check this */
1195 if (secKey->data) {
1196 memcpy(secKey->data, data, size);
1197 secKey->size = size;
1198 retval = 0;
1199 }
1200 else {
1201 PyErr_SetString(PyExc_MemoryError,
1202 "malloc failed in _db_associateCallback");
1203 PyErr_Print();
1204 }
1205 }
1206 else {
1207 PyErr_SetString(
1208 PyExc_TypeError,
1209 "DB associate callback should return DB_DONOTINDEX or string.");
1210 PyErr_Print();
1211 }
1212
1213 Py_XDECREF(args);
1214 Py_XDECREF(result);
1215
1216 MYDB_END_BLOCK_THREADS;
1217 }
1218 return retval;
1219}
1220
1221
1222static PyObject*
1223DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1224{
1225 int err, flags=0;
1226 DBObject* secondaryDB;
1227 PyObject* callback;
1228#if (DBVER >= 41)
1229 PyObject *txnobj = NULL;
1230 DB_TXN *txn = NULL;
1231 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1232 NULL};
1233#else
1234 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1235#endif
1236
1237#if (DBVER >= 41)
1238 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1239 &secondaryDB, &callback, &flags,
1240 &txnobj)) {
1241#else
1242 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1243 &secondaryDB, &callback, &flags)) {
1244#endif
1245 return NULL;
1246 }
1247
1248#if (DBVER >= 41)
1249 if (!checkTxnObj(txnobj, &txn)) return NULL;
1250#endif
1251
1252 CHECK_DB_NOT_CLOSED(self);
1253 if (!DBObject_Check(secondaryDB)) {
1254 makeTypeError("DB", (PyObject*)secondaryDB);
1255 return NULL;
1256 }
1257 CHECK_DB_NOT_CLOSED(secondaryDB);
1258 if (callback == Py_None) {
1259 callback = NULL;
1260 }
1261 else if (!PyCallable_Check(callback)) {
1262 makeTypeError("Callable", callback);
1263 return NULL;
1264 }
1265
1266 /* Save a reference to the callback in the secondary DB. */
1267 Py_XDECREF(secondaryDB->associateCallback);
1268 Py_XINCREF(callback);
1269 secondaryDB->associateCallback = callback;
1270 secondaryDB->primaryDBType = _DB_get_type(self);
1271
1272 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1273 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1274 * The global interepreter lock is not initialized until the first
1275 * thread is created using thread.start_new_thread() or fork() is
1276 * called. that would cause the ALLOW_THREADS here to segfault due
1277 * to a null pointer reference if no threads or child processes
1278 * have been created. This works around that and is a no-op if
1279 * threads have already been initialized.
1280 * (see pybsddb-users mailing list post on 2002-08-07)
1281 */
1282#ifdef WITH_THREAD
1283 PyEval_InitThreads();
1284#endif
1285 MYDB_BEGIN_ALLOW_THREADS;
1286#if (DBVER >= 41)
1287 err = self->db->associate(self->db,
1288 txn,
1289 secondaryDB->db,
1290 _db_associateCallback,
1291 flags);
1292#else
1293 err = self->db->associate(self->db,
1294 secondaryDB->db,
1295 _db_associateCallback,
1296 flags);
1297#endif
1298 MYDB_END_ALLOW_THREADS;
1299
1300 if (err) {
1301 Py_XDECREF(secondaryDB->associateCallback);
1302 secondaryDB->associateCallback = NULL;
1303 secondaryDB->primaryDBType = 0;
1304 }
1305
1306 RETURN_IF_ERR();
1307 RETURN_NONE();
1308}
1309
1310
1311#endif
1312
1313
1314static PyObject*
1315DB_close(DBObject* self, PyObject* args)
1316{
1317 int err, flags=0;
1318 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1319 return NULL;
1320 if (self->db != NULL) {
1321 if (self->myenvobj)
1322 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1323 err = self->db->close(self->db, flags);
1324 self->db = NULL;
1325 RETURN_IF_ERR();
1326 }
1327 RETURN_NONE();
1328}
1329
1330
1331#if (DBVER >= 32)
1332static PyObject*
1333_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1334{
1335 int err, flags=0, type;
1336 PyObject* txnobj = NULL;
1337 PyObject* retval = NULL;
1338 DBT key, data;
1339 DB_TXN *txn = NULL;
1340 static char* kwnames[] = { "txn", "flags", NULL };
1341
1342 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1343 &txnobj, &flags))
1344 return NULL;
1345
1346 CHECK_DB_NOT_CLOSED(self);
1347 type = _DB_get_type(self);
1348 if (type == -1)
1349 return NULL;
1350 if (type != DB_QUEUE) {
1351 PyErr_SetString(PyExc_TypeError,
1352 "Consume methods only allowed for Queue DB's");
1353 return NULL;
1354 }
1355 if (!checkTxnObj(txnobj, &txn))
1356 return NULL;
1357
1358 CLEAR_DBT(key);
1359 CLEAR_DBT(data);
1360 if (CHECK_DBFLAG(self, DB_THREAD)) {
1361 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1362 data.flags = DB_DBT_MALLOC;
1363 key.flags = DB_DBT_MALLOC;
1364 }
1365
1366 MYDB_BEGIN_ALLOW_THREADS;
1367 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1368 MYDB_END_ALLOW_THREADS;
1369
1370 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1371 && self->moduleFlags.getReturnsNone) {
1372 err = 0;
1373 Py_INCREF(Py_None);
1374 retval = Py_None;
1375 }
1376 else if (!err) {
1377 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1378 data.size);
1379 FREE_DBT(key);
1380 FREE_DBT(data);
1381 }
1382
1383 RETURN_IF_ERR();
1384 return retval;
1385}
1386
1387static PyObject*
1388DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1389{
1390 return _DB_consume(self, args, kwargs, DB_CONSUME);
1391}
1392
1393static PyObject*
1394DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1395 int consume_flag)
1396{
1397 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1398}
1399#endif
1400
1401
1402
1403static PyObject*
1404DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1405{
1406 int err, flags=0;
1407 DBC* dbc;
1408 PyObject* txnobj = NULL;
1409 DB_TXN *txn = NULL;
1410 static char* kwnames[] = { "txn", "flags", NULL };
1411
1412 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1413 &txnobj, &flags))
1414 return NULL;
1415 CHECK_DB_NOT_CLOSED(self);
1416 if (!checkTxnObj(txnobj, &txn))
1417 return NULL;
1418
1419 MYDB_BEGIN_ALLOW_THREADS;
1420 err = self->db->cursor(self->db, txn, &dbc, flags);
1421 MYDB_END_ALLOW_THREADS;
1422 RETURN_IF_ERR();
1423 return (PyObject*) newDBCursorObject(dbc, self);
1424}
1425
1426
1427static PyObject*
1428DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1429{
1430 PyObject* txnobj = NULL;
1431 int flags = 0;
1432 PyObject* keyobj;
1433 DBT key;
1434 DB_TXN *txn = NULL;
1435 static char* kwnames[] = { "key", "txn", "flags", NULL };
1436
1437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1438 &keyobj, &txnobj, &flags))
1439 return NULL;
1440 CHECK_DB_NOT_CLOSED(self);
1441 if (!make_key_dbt(self, keyobj, &key, NULL))
1442 return NULL;
1443 if (!checkTxnObj(txnobj, &txn)) {
1444 FREE_DBT(key);
1445 return NULL;
1446 }
1447
1448 if (-1 == _DB_delete(self, txn, &key, 0)) {
1449 FREE_DBT(key);
1450 return NULL;
1451 }
1452
1453 FREE_DBT(key);
1454 RETURN_NONE();
1455}
1456
1457
1458static PyObject*
1459DB_fd(DBObject* self, PyObject* args)
1460{
1461 int err, the_fd;
1462
1463 if (!PyArg_ParseTuple(args,":fd"))
1464 return NULL;
1465 CHECK_DB_NOT_CLOSED(self);
1466
1467 MYDB_BEGIN_ALLOW_THREADS;
1468 err = self->db->fd(self->db, &the_fd);
1469 MYDB_END_ALLOW_THREADS;
1470 RETURN_IF_ERR();
1471 return PyInt_FromLong(the_fd);
1472}
1473
1474
1475static PyObject*
1476DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1477{
1478 int err, flags=0;
1479 PyObject* txnobj = NULL;
1480 PyObject* keyobj;
1481 PyObject* dfltobj = NULL;
1482 PyObject* retval = NULL;
1483 int dlen = -1;
1484 int doff = -1;
1485 DBT key, data;
1486 DB_TXN *txn = NULL;
1487 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1488 "doff", NULL};
1489
1490 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1491 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1492 &doff))
1493 return NULL;
1494
1495 CHECK_DB_NOT_CLOSED(self);
1496 if (!make_key_dbt(self, keyobj, &key, &flags))
1497 return NULL;
1498 if (!checkTxnObj(txnobj, &txn)) {
1499 FREE_DBT(key);
1500 return NULL;
1501 }
1502
1503 CLEAR_DBT(data);
1504 if (CHECK_DBFLAG(self, DB_THREAD)) {
1505 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1506 data.flags = DB_DBT_MALLOC;
1507 }
1508 if (!add_partial_dbt(&data, dlen, doff)) {
1509 FREE_DBT(key);
1510 return NULL;
1511 }
1512
1513 MYDB_BEGIN_ALLOW_THREADS;
1514 err = self->db->get(self->db, txn, &key, &data, flags);
1515 MYDB_END_ALLOW_THREADS;
1516
1517 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1518 err = 0;
1519 Py_INCREF(dfltobj);
1520 retval = dfltobj;
1521 }
1522 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1523 && self->moduleFlags.getReturnsNone) {
1524 err = 0;
1525 Py_INCREF(Py_None);
1526 retval = Py_None;
1527 }
1528 else if (!err) {
1529 if (flags & DB_SET_RECNO) /* return both key and data */
1530 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1531 data.size);
1532 else /* return just the data */
1533 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1534 FREE_DBT(data);
1535 }
1536 FREE_DBT(key);
1537
1538 RETURN_IF_ERR();
1539 return retval;
1540}
1541
1542#if (DBVER >= 33)
1543static PyObject*
1544DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1545{
1546 int err, flags=0;
1547 PyObject* txnobj = NULL;
1548 PyObject* keyobj;
1549 PyObject* dfltobj = NULL;
1550 PyObject* retval = NULL;
1551 int dlen = -1;
1552 int doff = -1;
1553 DBT key, pkey, data;
1554 DB_TXN *txn = NULL;
1555 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1556 "doff", NULL};
1557
1558 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1559 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1560 &doff))
1561 return NULL;
1562
1563 CHECK_DB_NOT_CLOSED(self);
1564 if (!make_key_dbt(self, keyobj, &key, &flags))
1565 return NULL;
1566 if (!checkTxnObj(txnobj, &txn)) {
1567 FREE_DBT(key);
1568 return NULL;
1569 }
1570
1571 CLEAR_DBT(data);
1572 if (CHECK_DBFLAG(self, DB_THREAD)) {
1573 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1574 data.flags = DB_DBT_MALLOC;
1575 }
1576 if (!add_partial_dbt(&data, dlen, doff)) {
1577 FREE_DBT(key);
1578 return NULL;
1579 }
1580
1581 CLEAR_DBT(pkey);
1582 pkey.flags = DB_DBT_MALLOC;
1583
1584 MYDB_BEGIN_ALLOW_THREADS;
1585 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1586 MYDB_END_ALLOW_THREADS;
1587
1588 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1589 err = 0;
1590 Py_INCREF(dfltobj);
1591 retval = dfltobj;
1592 }
1593 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1594 && self->moduleFlags.getReturnsNone) {
1595 err = 0;
1596 Py_INCREF(Py_None);
1597 retval = Py_None;
1598 }
1599 else if (!err) {
1600 PyObject *pkeyObj;
1601 PyObject *dataObj;
1602 dataObj = PyString_FromStringAndSize(data.data, data.size);
1603
1604 if (self->primaryDBType == DB_RECNO ||
1605 self->primaryDBType == DB_QUEUE)
1606 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
1607 else
1608 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1609
1610 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1611 {
1612 PyObject *keyObj;
1613 int type = _DB_get_type(self);
1614 if (type == DB_RECNO || type == DB_QUEUE)
1615 keyObj = PyInt_FromLong(*(int *)key.data);
1616 else
1617 keyObj = PyString_FromStringAndSize(key.data, key.size);
1618#if (PY_VERSION_HEX >= 0x02040000)
1619 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
1620#else
1621 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1622#endif
1623 Py_DECREF(keyObj);
1624 }
1625 else /* return just the pkey and data */
1626 {
1627#if (PY_VERSION_HEX >= 0x02040000)
1628 retval = PyTuple_Pack(2, pkeyObj, dataObj);
1629#else
1630 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1631#endif
1632 }
1633 Py_DECREF(dataObj);
1634 Py_DECREF(pkeyObj);
1635 FREE_DBT(pkey);
1636 FREE_DBT(data);
1637 }
1638 FREE_DBT(key);
1639
1640 RETURN_IF_ERR();
1641 return retval;
1642}
1643#endif
1644
1645
1646/* Return size of entry */
1647static PyObject*
1648DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1649{
1650 int err, flags=0;
1651 PyObject* txnobj = NULL;
1652 PyObject* keyobj;
1653 PyObject* retval = NULL;
1654 DBT key, data;
1655 DB_TXN *txn = NULL;
1656 static char* kwnames[] = { "key", "txn", NULL };
1657
1658 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1659 &keyobj, &txnobj))
1660 return NULL;
1661 CHECK_DB_NOT_CLOSED(self);
1662 if (!make_key_dbt(self, keyobj, &key, &flags))
1663 return NULL;
1664 if (!checkTxnObj(txnobj, &txn)) {
1665 FREE_DBT(key);
1666 return NULL;
1667 }
1668 CLEAR_DBT(data);
1669
1670 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1671 thus getting the record size. */
1672 data.flags = DB_DBT_USERMEM;
1673 data.ulen = 0;
1674 MYDB_BEGIN_ALLOW_THREADS;
1675 err = self->db->get(self->db, txn, &key, &data, flags);
1676 MYDB_END_ALLOW_THREADS;
1677 if (err == DB_BUFFER_SMALL) {
1678 retval = PyInt_FromLong((long)data.size);
1679 err = 0;
1680 }
1681
1682 FREE_DBT(key);
1683 FREE_DBT(data);
1684 RETURN_IF_ERR();
1685 return retval;
1686}
1687
1688
1689static PyObject*
1690DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1691{
1692 int err, flags=0;
1693 PyObject* txnobj = NULL;
1694 PyObject* keyobj;
1695 PyObject* dataobj;
1696 PyObject* retval = NULL;
1697 DBT key, data;
1698 DB_TXN *txn = NULL;
1699 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1700
1701
1702 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1703 &keyobj, &dataobj, &txnobj, &flags))
1704 return NULL;
1705
1706 CHECK_DB_NOT_CLOSED(self);
1707 if (!make_key_dbt(self, keyobj, &key, NULL))
1708 return NULL;
1709 if ( !make_dbt(dataobj, &data) ||
1710 !checkTxnObj(txnobj, &txn) )
1711 {
1712 FREE_DBT(key);
1713 return NULL;
1714 }
1715
1716 flags |= DB_GET_BOTH;
1717
1718 if (CHECK_DBFLAG(self, DB_THREAD)) {
1719 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1720 data.flags = DB_DBT_MALLOC;
1721 /* TODO: Is this flag needed? We're passing a data object that should
1722 match what's in the DB, so there should be no need to malloc.
1723 We run the risk of freeing something twice! Check this. */
1724 }
1725
1726 MYDB_BEGIN_ALLOW_THREADS;
1727 err = self->db->get(self->db, txn, &key, &data, flags);
1728 MYDB_END_ALLOW_THREADS;
1729
1730 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1731 && self->moduleFlags.getReturnsNone) {
1732 err = 0;
1733 Py_INCREF(Py_None);
1734 retval = Py_None;
1735 }
1736 else if (!err) {
1737 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1738 FREE_DBT(data); /* Only if retrieval was successful */
1739 }
1740
1741 FREE_DBT(key);
1742 RETURN_IF_ERR();
1743 return retval;
1744}
1745
1746
1747static PyObject*
1748DB_get_byteswapped(DBObject* self, PyObject* args)
1749{
1750#if (DBVER >= 33)
1751 int err = 0;
1752#endif
1753 int retval = -1;
1754
1755 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1756 return NULL;
1757 CHECK_DB_NOT_CLOSED(self);
1758
1759#if (DBVER >= 33)
1760 MYDB_BEGIN_ALLOW_THREADS;
1761 err = self->db->get_byteswapped(self->db, &retval);
1762 MYDB_END_ALLOW_THREADS;
1763 RETURN_IF_ERR();
1764#else
1765 MYDB_BEGIN_ALLOW_THREADS;
1766 retval = self->db->get_byteswapped(self->db);
1767 MYDB_END_ALLOW_THREADS;
1768#endif
1769 return PyInt_FromLong(retval);
1770}
1771
1772
1773static PyObject*
1774DB_get_type(DBObject* self, PyObject* args)
1775{
1776 int type;
1777
1778 if (!PyArg_ParseTuple(args,":get_type"))
1779 return NULL;
1780 CHECK_DB_NOT_CLOSED(self);
1781
1782 MYDB_BEGIN_ALLOW_THREADS;
1783 type = _DB_get_type(self);
1784 MYDB_END_ALLOW_THREADS;
1785 if (type == -1)
1786 return NULL;
1787 return PyInt_FromLong(type);
1788}
1789
1790
1791static PyObject*
1792DB_join(DBObject* self, PyObject* args)
1793{
1794 int err, flags=0;
1795 int length, x;
1796 PyObject* cursorsObj;
1797 DBC** cursors;
1798 DBC* dbc;
1799
1800 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1801 return NULL;
1802
1803 CHECK_DB_NOT_CLOSED(self);
1804
1805 if (!PySequence_Check(cursorsObj)) {
1806 PyErr_SetString(PyExc_TypeError,
1807 "Sequence of DBCursor objects expected");
1808 return NULL;
1809 }
1810
1811 length = PyObject_Length(cursorsObj);
1812 cursors = malloc((length+1) * sizeof(DBC*));
1813 if (!cursors) {
1814 PyErr_NoMemory();
1815 return NULL;
1816 }
1817
1818 cursors[length] = NULL;
1819 for (x=0; x<length; x++) {
1820 PyObject* item = PySequence_GetItem(cursorsObj, x);
1821 if (item == NULL) {
1822 free(cursors);
1823 return NULL;
1824 }
1825 if (!DBCursorObject_Check(item)) {
1826 PyErr_SetString(PyExc_TypeError,
1827 "Sequence of DBCursor objects expected");
1828 free(cursors);
1829 return NULL;
1830 }
1831 cursors[x] = ((DBCursorObject*)item)->dbc;
1832 Py_DECREF(item);
1833 }
1834
1835 MYDB_BEGIN_ALLOW_THREADS;
1836 err = self->db->join(self->db, cursors, &dbc, flags);
1837 MYDB_END_ALLOW_THREADS;
1838 free(cursors);
1839 RETURN_IF_ERR();
1840
1841 /* FIXME: this is a buggy interface. The returned cursor
1842 contains internal references to the passed in cursors
1843 but does not hold python references to them or prevent
1844 them from being closed prematurely. This can cause
1845 python to crash when things are done in the wrong order. */
1846 return (PyObject*) newDBCursorObject(dbc, self);
1847}
1848
1849
1850static PyObject*
1851DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1852{
1853 int err, flags=0;
1854 PyObject* txnobj = NULL;
1855 PyObject* keyobj;
1856 DBT key;
1857 DB_TXN *txn = NULL;
1858 DB_KEY_RANGE range;
1859 static char* kwnames[] = { "key", "txn", "flags", NULL };
1860
1861 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1862 &keyobj, &txnobj, &flags))
1863 return NULL;
1864 CHECK_DB_NOT_CLOSED(self);
1865 if (!make_dbt(keyobj, &key))
1866 /* BTree only, don't need to allow for an int key */
1867 return NULL;
1868 if (!checkTxnObj(txnobj, &txn))
1869 return NULL;
1870
1871 MYDB_BEGIN_ALLOW_THREADS;
1872 err = self->db->key_range(self->db, txn, &key, &range, flags);
1873 MYDB_END_ALLOW_THREADS;
1874
1875 RETURN_IF_ERR();
1876 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1877}
1878
1879
1880static PyObject*
1881DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1882{
1883 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1884 char* filename = NULL;
1885 char* dbname = NULL;
1886#if (DBVER >= 41)
1887 PyObject *txnobj = NULL;
1888 DB_TXN *txn = NULL;
1889 /* with dbname */
1890 static char* kwnames[] = {
1891 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1892 /* without dbname */
1893 static char* kwnames_basic[] = {
1894 "filename", "dbtype", "flags", "mode", "txn", NULL};
1895#else
1896 /* with dbname */
1897 static char* kwnames[] = {
1898 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1899 /* without dbname */
1900 static char* kwnames_basic[] = {
1901 "filename", "dbtype", "flags", "mode", NULL};
1902#endif
1903
1904#if (DBVER >= 41)
1905 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1906 &filename, &dbname, &type, &flags, &mode,
1907 &txnobj))
1908#else
1909 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1910 &filename, &dbname, &type, &flags,
1911 &mode))
1912#endif
1913 {
1914 PyErr_Clear();
1915 type = DB_UNKNOWN; flags = 0; mode = 0660;
1916 filename = NULL; dbname = NULL;
1917#if (DBVER >= 41)
1918 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1919 kwnames_basic,
1920 &filename, &type, &flags, &mode,
1921 &txnobj))
1922 return NULL;
1923#else
1924 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1925 kwnames_basic,
1926 &filename, &type, &flags, &mode))
1927 return NULL;
1928#endif
1929 }
1930
1931#if (DBVER >= 41)
1932 if (!checkTxnObj(txnobj, &txn)) return NULL;
1933#endif
1934
1935 if (NULL == self->db) {
1936 PyObject *t = Py_BuildValue("(is)", 0,
1937 "Cannot call open() twice for DB object");
1938 PyErr_SetObject(DBError, t);
1939 Py_DECREF(t);
1940 return NULL;
1941 }
1942
1943#if 0 && (DBVER >= 41)
1944 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1945 && (self->myenvobj->flags & DB_INIT_TXN))
1946 {
1947 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1948 * explicitly passed) but we are in a transaction ready environment:
1949 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1950 * to work on BerkeleyDB 4.1 without needing to modify their
1951 * DBEnv or DB open calls.
1952 * TODO make this behaviour of the library configurable.
1953 */
1954 flags |= DB_AUTO_COMMIT;
1955 }
1956#endif
1957
1958 MYDB_BEGIN_ALLOW_THREADS;
1959#if (DBVER >= 41)
1960 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1961#else
1962 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1963#endif
1964 MYDB_END_ALLOW_THREADS;
1965 if (makeDBError(err)) {
1966 self->db->close(self->db, 0);
1967 self->db = NULL;
1968 return NULL;
1969 }
1970
1971 self->flags = flags;
1972 RETURN_NONE();
1973}
1974
1975
1976static PyObject*
1977DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1978{
1979 int flags=0;
1980 PyObject* txnobj = NULL;
1981 int dlen = -1;
1982 int doff = -1;
1983 PyObject* keyobj, *dataobj, *retval;
1984 DBT key, data;
1985 DB_TXN *txn = NULL;
1986 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
1987 "doff", NULL };
1988
1989 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1990 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1991 return NULL;
1992
1993 CHECK_DB_NOT_CLOSED(self);
1994 if (!make_key_dbt(self, keyobj, &key, NULL))
1995 return NULL;
1996 if ( !make_dbt(dataobj, &data) ||
1997 !add_partial_dbt(&data, dlen, doff) ||
1998 !checkTxnObj(txnobj, &txn) )
1999 {
2000 FREE_DBT(key);
2001 return NULL;
2002 }
2003
2004 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2005 FREE_DBT(key);
2006 return NULL;
2007 }
2008
2009 if (flags & DB_APPEND)
2010 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2011 else {
2012 retval = Py_None;
2013 Py_INCREF(retval);
2014 }
2015 FREE_DBT(key);
2016 return retval;
2017}
2018
2019
2020
2021static PyObject*
2022DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2023{
2024 char* filename;
2025 char* database = NULL;
2026 int err, flags=0;
2027 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
2028
2029 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2030 &filename, &database, &flags))
2031 return NULL;
2032 CHECK_DB_NOT_CLOSED(self);
2033
2034 err = self->db->remove(self->db, filename, database, flags);
2035 self->db = NULL;
2036 RETURN_IF_ERR();
2037 RETURN_NONE();
2038}
2039
2040
2041
2042static PyObject*
2043DB_rename(DBObject* self, PyObject* args)
2044{
2045 char* filename;
2046 char* database;
2047 char* newname;
2048 int err, flags=0;
2049
2050 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2051 &flags))
2052 return NULL;
2053 CHECK_DB_NOT_CLOSED(self);
2054
2055 MYDB_BEGIN_ALLOW_THREADS;
2056 err = self->db->rename(self->db, filename, database, newname, flags);
2057 MYDB_END_ALLOW_THREADS;
2058 RETURN_IF_ERR();
2059 RETURN_NONE();
2060}
2061
2062
2063static PyObject*
2064DB_set_bt_minkey(DBObject* self, PyObject* args)
2065{
2066 int err, minkey;
2067
2068 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2069 return NULL;
2070 CHECK_DB_NOT_CLOSED(self);
2071
2072 MYDB_BEGIN_ALLOW_THREADS;
2073 err = self->db->set_bt_minkey(self->db, minkey);
2074 MYDB_END_ALLOW_THREADS;
2075 RETURN_IF_ERR();
2076 RETURN_NONE();
2077}
2078
2079#if (DBVER >= 33)
2080static int
2081_default_cmp(const DBT *leftKey,
2082 const DBT *rightKey)
2083{
2084 int res;
2085 int lsize = leftKey->size, rsize = rightKey->size;
2086
2087 res = memcmp(leftKey->data, rightKey->data,
2088 lsize < rsize ? lsize : rsize);
2089
2090 if (res == 0) {
2091 if (lsize < rsize) {
2092 res = -1;
2093 }
2094 else if (lsize > rsize) {
2095 res = 1;
2096 }
2097 }
2098 return res;
2099}
2100
2101static int
2102_db_compareCallback(DB* db,
2103 const DBT *leftKey,
2104 const DBT *rightKey)
2105{
2106 int res = 0;
2107 PyObject *args;
2108 PyObject *result = NULL;
2109 DBObject *self = (DBObject *)db->app_private;
2110
2111 if (self == NULL || self->btCompareCallback == NULL) {
2112 MYDB_BEGIN_BLOCK_THREADS;
2113 PyErr_SetString(PyExc_TypeError,
2114 (self == 0
2115 ? "DB_bt_compare db is NULL."
2116 : "DB_bt_compare callback is NULL."));
2117 /* we're in a callback within the DB code, we can't raise */
2118 PyErr_Print();
2119 res = _default_cmp(leftKey, rightKey);
2120 MYDB_END_BLOCK_THREADS;
2121 } else {
2122 MYDB_BEGIN_BLOCK_THREADS;
2123
2124 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2125 rightKey->data, rightKey->size);
2126 if (args != NULL) {
2127 /* XXX(twouters) I highly doubt this INCREF is correct */
2128 Py_INCREF(self);
2129 result = PyEval_CallObject(self->btCompareCallback, args);
2130 }
2131 if (args == NULL || result == NULL) {
2132 /* we're in a callback within the DB code, we can't raise */
2133 PyErr_Print();
2134 res = _default_cmp(leftKey, rightKey);
2135 } else if (PyInt_Check(result)) {
2136 res = PyInt_AsLong(result);
2137 } else {
2138 PyErr_SetString(PyExc_TypeError,
2139 "DB_bt_compare callback MUST return an int.");
2140 /* we're in a callback within the DB code, we can't raise */
2141 PyErr_Print();
2142 res = _default_cmp(leftKey, rightKey);
2143 }
2144
2145 Py_XDECREF(args);
2146 Py_XDECREF(result);
2147
2148 MYDB_END_BLOCK_THREADS;
2149 }
2150 return res;
2151}
2152
2153static PyObject*
2154DB_set_bt_compare(DBObject* self, PyObject* args)
2155{
2156 int err;
2157 PyObject *comparator;
2158 PyObject *tuple, *result;
2159
2160 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
2161 return NULL;
2162
2163 CHECK_DB_NOT_CLOSED(self);
2164
2165 if (!PyCallable_Check(comparator)) {
2166 makeTypeError("Callable", comparator);
2167 return NULL;
2168 }
2169
2170 /*
2171 * Perform a test call of the comparator function with two empty
2172 * string objects here. verify that it returns an int (0).
2173 * err if not.
2174 */
2175 tuple = Py_BuildValue("(ss)", "", "");
2176 result = PyEval_CallObject(comparator, tuple);
2177 Py_DECREF(tuple);
2178 if (result == NULL)
2179 return NULL;
2180 if (!PyInt_Check(result)) {
2181 PyErr_SetString(PyExc_TypeError,
2182 "callback MUST return an int");
2183 return NULL;
2184 } else if (PyInt_AsLong(result) != 0) {
2185 PyErr_SetString(PyExc_TypeError,
2186 "callback failed to return 0 on two empty strings");
2187 return NULL;
2188 }
2189 Py_DECREF(result);
2190
2191 /* We don't accept multiple set_bt_compare operations, in order to
2192 * simplify the code. This would have no real use, as one cannot
2193 * change the function once the db is opened anyway */
2194 if (self->btCompareCallback != NULL) {
2195 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2196 return NULL;
2197 }
2198
2199 Py_INCREF(comparator);
2200 self->btCompareCallback = comparator;
2201
2202 /* This is to workaround a problem with un-initialized threads (see
2203 comment in DB_associate) */
2204#ifdef WITH_THREAD
2205 PyEval_InitThreads();
2206#endif
2207
2208 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2209
2210 if (err) {
2211 /* restore the old state in case of error */
2212 Py_DECREF(comparator);
2213 self->btCompareCallback = NULL;
2214 }
2215
2216 RETURN_IF_ERR();
2217 RETURN_NONE();
2218}
2219#endif /* DBVER >= 33 */
2220
2221
2222static PyObject*
2223DB_set_cachesize(DBObject* self, PyObject* args)
2224{
2225 int err;
2226 int gbytes = 0, bytes = 0, ncache = 0;
2227
2228 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2229 &gbytes,&bytes,&ncache))
2230 return NULL;
2231 CHECK_DB_NOT_CLOSED(self);
2232
2233 MYDB_BEGIN_ALLOW_THREADS;
2234 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2235 MYDB_END_ALLOW_THREADS;
2236 RETURN_IF_ERR();
2237 RETURN_NONE();
2238}
2239
2240
2241static PyObject*
2242DB_set_flags(DBObject* self, PyObject* args)
2243{
2244 int err, flags;
2245
2246 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2247 return NULL;
2248 CHECK_DB_NOT_CLOSED(self);
2249
2250 MYDB_BEGIN_ALLOW_THREADS;
2251 err = self->db->set_flags(self->db, flags);
2252 MYDB_END_ALLOW_THREADS;
2253 RETURN_IF_ERR();
2254
2255 self->setflags |= flags;
2256 RETURN_NONE();
2257}
2258
2259
2260static PyObject*
2261DB_set_h_ffactor(DBObject* self, PyObject* args)
2262{
2263 int err, ffactor;
2264
2265 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2266 return NULL;
2267 CHECK_DB_NOT_CLOSED(self);
2268
2269 MYDB_BEGIN_ALLOW_THREADS;
2270 err = self->db->set_h_ffactor(self->db, ffactor);
2271 MYDB_END_ALLOW_THREADS;
2272 RETURN_IF_ERR();
2273 RETURN_NONE();
2274}
2275
2276
2277static PyObject*
2278DB_set_h_nelem(DBObject* self, PyObject* args)
2279{
2280 int err, nelem;
2281
2282 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2283 return NULL;
2284 CHECK_DB_NOT_CLOSED(self);
2285
2286 MYDB_BEGIN_ALLOW_THREADS;
2287 err = self->db->set_h_nelem(self->db, nelem);
2288 MYDB_END_ALLOW_THREADS;
2289 RETURN_IF_ERR();
2290 RETURN_NONE();
2291}
2292
2293
2294static PyObject*
2295DB_set_lorder(DBObject* self, PyObject* args)
2296{
2297 int err, lorder;
2298
2299 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2300 return NULL;
2301 CHECK_DB_NOT_CLOSED(self);
2302
2303 MYDB_BEGIN_ALLOW_THREADS;
2304 err = self->db->set_lorder(self->db, lorder);
2305 MYDB_END_ALLOW_THREADS;
2306 RETURN_IF_ERR();
2307 RETURN_NONE();
2308}
2309
2310
2311static PyObject*
2312DB_set_pagesize(DBObject* self, PyObject* args)
2313{
2314 int err, pagesize;
2315
2316 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2317 return NULL;
2318 CHECK_DB_NOT_CLOSED(self);
2319
2320 MYDB_BEGIN_ALLOW_THREADS;
2321 err = self->db->set_pagesize(self->db, pagesize);
2322 MYDB_END_ALLOW_THREADS;
2323 RETURN_IF_ERR();
2324 RETURN_NONE();
2325}
2326
2327
2328static PyObject*
2329DB_set_re_delim(DBObject* self, PyObject* args)
2330{
2331 int err;
2332 char delim;
2333
2334 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2335 PyErr_Clear();
2336 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2337 return NULL;
2338 }
2339
2340 CHECK_DB_NOT_CLOSED(self);
2341
2342 MYDB_BEGIN_ALLOW_THREADS;
2343 err = self->db->set_re_delim(self->db, delim);
2344 MYDB_END_ALLOW_THREADS;
2345 RETURN_IF_ERR();
2346 RETURN_NONE();
2347}
2348
2349static PyObject*
2350DB_set_re_len(DBObject* self, PyObject* args)
2351{
2352 int err, len;
2353
2354 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2355 return NULL;
2356 CHECK_DB_NOT_CLOSED(self);
2357
2358 MYDB_BEGIN_ALLOW_THREADS;
2359 err = self->db->set_re_len(self->db, len);
2360 MYDB_END_ALLOW_THREADS;
2361 RETURN_IF_ERR();
2362 RETURN_NONE();
2363}
2364
2365
2366static PyObject*
2367DB_set_re_pad(DBObject* self, PyObject* args)
2368{
2369 int err;
2370 char pad;
2371
2372 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2373 PyErr_Clear();
2374 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2375 return NULL;
2376 }
2377 CHECK_DB_NOT_CLOSED(self);
2378
2379 MYDB_BEGIN_ALLOW_THREADS;
2380 err = self->db->set_re_pad(self->db, pad);
2381 MYDB_END_ALLOW_THREADS;
2382 RETURN_IF_ERR();
2383 RETURN_NONE();
2384}
2385
2386
2387static PyObject*
2388DB_set_re_source(DBObject* self, PyObject* args)
2389{
2390 int err;
2391 char *re_source;
2392
2393 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2394 return NULL;
2395 CHECK_DB_NOT_CLOSED(self);
2396
2397 MYDB_BEGIN_ALLOW_THREADS;
2398 err = self->db->set_re_source(self->db, re_source);
2399 MYDB_END_ALLOW_THREADS;
2400 RETURN_IF_ERR();
2401 RETURN_NONE();
2402}
2403
2404
2405#if (DBVER >= 32)
2406static PyObject*
2407DB_set_q_extentsize(DBObject* self, PyObject* args)
2408{
2409 int err;
2410 int extentsize;
2411
2412 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2413 return NULL;
2414 CHECK_DB_NOT_CLOSED(self);
2415
2416 MYDB_BEGIN_ALLOW_THREADS;
2417 err = self->db->set_q_extentsize(self->db, extentsize);
2418 MYDB_END_ALLOW_THREADS;
2419 RETURN_IF_ERR();
2420 RETURN_NONE();
2421}
2422#endif
2423
2424static PyObject*
2425DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2426{
2427 int err, flags = 0, type;
2428 void* sp;
2429 PyObject* d;
2430#if (DBVER >= 43)
2431 PyObject* txnobj = NULL;
2432 DB_TXN *txn = NULL;
2433 static char* kwnames[] = { "txn", "flags", NULL };
2434#else
2435 static char* kwnames[] = { "flags", NULL };
2436#endif
2437
2438#if (DBVER >= 43)
2439 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2440 &flags, &txnobj))
2441 return NULL;
2442 if (!checkTxnObj(txnobj, &txn))
2443 return NULL;
2444#else
2445 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2446 return NULL;
2447#endif
2448 CHECK_DB_NOT_CLOSED(self);
2449
2450 MYDB_BEGIN_ALLOW_THREADS;
2451#if (DBVER >= 43)
2452 err = self->db->stat(self->db, txn, &sp, flags);
2453#elif (DBVER >= 33)
2454 err = self->db->stat(self->db, &sp, flags);
2455#else
2456 err = self->db->stat(self->db, &sp, NULL, flags);
2457#endif
2458 MYDB_END_ALLOW_THREADS;
2459 RETURN_IF_ERR();
2460
2461 self->haveStat = 1;
2462
2463 /* Turn the stat structure into a dictionary */
2464 type = _DB_get_type(self);
2465 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2466 free(sp);
2467 return NULL;
2468 }
2469
2470#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2471#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2472#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2473
2474 switch (type) {
2475 case DB_HASH:
2476 MAKE_HASH_ENTRY(magic);
2477 MAKE_HASH_ENTRY(version);
2478 MAKE_HASH_ENTRY(nkeys);
2479 MAKE_HASH_ENTRY(ndata);
2480 MAKE_HASH_ENTRY(pagesize);
2481#if (DBVER < 41)
2482 MAKE_HASH_ENTRY(nelem);
2483#endif
2484 MAKE_HASH_ENTRY(ffactor);
2485 MAKE_HASH_ENTRY(buckets);
2486 MAKE_HASH_ENTRY(free);
2487 MAKE_HASH_ENTRY(bfree);
2488 MAKE_HASH_ENTRY(bigpages);
2489 MAKE_HASH_ENTRY(big_bfree);
2490 MAKE_HASH_ENTRY(overflows);
2491 MAKE_HASH_ENTRY(ovfl_free);
2492 MAKE_HASH_ENTRY(dup);
2493 MAKE_HASH_ENTRY(dup_free);
2494 break;
2495
2496 case DB_BTREE:
2497 case DB_RECNO:
2498 MAKE_BT_ENTRY(magic);
2499 MAKE_BT_ENTRY(version);
2500 MAKE_BT_ENTRY(nkeys);
2501 MAKE_BT_ENTRY(ndata);
2502 MAKE_BT_ENTRY(pagesize);
2503 MAKE_BT_ENTRY(minkey);
2504 MAKE_BT_ENTRY(re_len);
2505 MAKE_BT_ENTRY(re_pad);
2506 MAKE_BT_ENTRY(levels);
2507 MAKE_BT_ENTRY(int_pg);
2508 MAKE_BT_ENTRY(leaf_pg);
2509 MAKE_BT_ENTRY(dup_pg);
2510 MAKE_BT_ENTRY(over_pg);
2511 MAKE_BT_ENTRY(free);
2512 MAKE_BT_ENTRY(int_pgfree);
2513 MAKE_BT_ENTRY(leaf_pgfree);
2514 MAKE_BT_ENTRY(dup_pgfree);
2515 MAKE_BT_ENTRY(over_pgfree);
2516 break;
2517
2518 case DB_QUEUE:
2519 MAKE_QUEUE_ENTRY(magic);
2520 MAKE_QUEUE_ENTRY(version);
2521 MAKE_QUEUE_ENTRY(nkeys);
2522 MAKE_QUEUE_ENTRY(ndata);
2523 MAKE_QUEUE_ENTRY(pagesize);
2524 MAKE_QUEUE_ENTRY(pages);
2525 MAKE_QUEUE_ENTRY(re_len);
2526 MAKE_QUEUE_ENTRY(re_pad);
2527 MAKE_QUEUE_ENTRY(pgfree);
2528#if (DBVER == 31)
2529 MAKE_QUEUE_ENTRY(start);
2530#endif
2531 MAKE_QUEUE_ENTRY(first_recno);
2532 MAKE_QUEUE_ENTRY(cur_recno);
2533 break;
2534
2535 default:
2536 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2537 Py_DECREF(d);
2538 d = NULL;
2539 }
2540
2541#undef MAKE_HASH_ENTRY
2542#undef MAKE_BT_ENTRY
2543#undef MAKE_QUEUE_ENTRY
2544
2545 free(sp);
2546 return d;
2547}
2548
2549static PyObject*
2550DB_sync(DBObject* self, PyObject* args)
2551{
2552 int err;
2553 int flags = 0;
2554
2555 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2556 return NULL;
2557 CHECK_DB_NOT_CLOSED(self);
2558
2559 MYDB_BEGIN_ALLOW_THREADS;
2560 err = self->db->sync(self->db, flags);
2561 MYDB_END_ALLOW_THREADS;
2562 RETURN_IF_ERR();
2563 RETURN_NONE();
2564}
2565
2566
2567#if (DBVER >= 33)
2568static PyObject*
2569DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2570{
2571 int err, flags=0;
2572 u_int32_t count=0;
2573 PyObject* txnobj = NULL;
2574 DB_TXN *txn = NULL;
2575 static char* kwnames[] = { "txn", "flags", NULL };
2576
2577 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2578 &txnobj, &flags))
2579 return NULL;
2580 CHECK_DB_NOT_CLOSED(self);
2581 if (!checkTxnObj(txnobj, &txn))
2582 return NULL;
2583
2584 MYDB_BEGIN_ALLOW_THREADS;
2585 err = self->db->truncate(self->db, txn, &count, flags);
2586 MYDB_END_ALLOW_THREADS;
2587 RETURN_IF_ERR();
2588 return PyInt_FromLong(count);
2589}
2590#endif
2591
2592
2593static PyObject*
2594DB_upgrade(DBObject* self, PyObject* args)
2595{
2596 int err, flags=0;
2597 char *filename;
2598
2599 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2600 return NULL;
2601 CHECK_DB_NOT_CLOSED(self);
2602
2603 MYDB_BEGIN_ALLOW_THREADS;
2604 err = self->db->upgrade(self->db, filename, flags);
2605 MYDB_END_ALLOW_THREADS;
2606 RETURN_IF_ERR();
2607 RETURN_NONE();
2608}
2609
2610
2611static PyObject*
2612DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2613{
2614 int err, flags=0;
2615 char* fileName;
2616 char* dbName=NULL;
2617 char* outFileName=NULL;
2618 FILE* outFile=NULL;
2619 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2620 NULL };
2621
2622 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2623 &fileName, &dbName, &outFileName, &flags))
2624 return NULL;
2625
2626 CHECK_DB_NOT_CLOSED(self);
2627 if (outFileName)
2628 outFile = fopen(outFileName, "w");
2629 /* XXX(nnorwitz): it should probably be an exception if outFile
2630 can't be opened. */
2631
2632 MYDB_BEGIN_ALLOW_THREADS;
2633 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2634 MYDB_END_ALLOW_THREADS;
2635 if (outFile)
2636 fclose(outFile);
2637
2638 /* DB.verify acts as a DB handle destructor (like close); this was
2639 * documented in BerkeleyDB 4.2 but had the undocumented effect
2640 * of not being safe in prior versions while still requiring an explicit
2641 * DB.close call afterwards. Lets call close for the user to emulate
2642 * the safe 4.2 behaviour. */
2643#if (DBVER <= 41)
2644 self->db->close(self->db, 0);
2645#endif
2646 self->db = NULL;
2647
2648 RETURN_IF_ERR();
2649 RETURN_NONE();
2650}
2651
2652
2653static PyObject*
2654DB_set_get_returns_none(DBObject* self, PyObject* args)
2655{
2656 int flags=0;
2657 int oldValue=0;
2658
2659 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2660 return NULL;
2661 CHECK_DB_NOT_CLOSED(self);
2662
2663 if (self->moduleFlags.getReturnsNone)
2664 ++oldValue;
2665 if (self->moduleFlags.cursorSetReturnsNone)
2666 ++oldValue;
2667 self->moduleFlags.getReturnsNone = (flags >= 1);
2668 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2669 return PyInt_FromLong(oldValue);
2670}
2671
2672#if (DBVER >= 41)
2673static PyObject*
2674DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2675{
2676 int err;
2677 u_int32_t flags=0;
2678 char *passwd = NULL;
2679 static char* kwnames[] = { "passwd", "flags", NULL };
2680
2681 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2682 &passwd, &flags)) {
2683 return NULL;
2684 }
2685
2686 MYDB_BEGIN_ALLOW_THREADS;
2687 err = self->db->set_encrypt(self->db, passwd, flags);
2688 MYDB_END_ALLOW_THREADS;
2689
2690 RETURN_IF_ERR();
2691 RETURN_NONE();
2692}
2693#endif /* DBVER >= 41 */
2694
2695
2696/*-------------------------------------------------------------- */
2697/* Mapping and Dictionary-like access routines */
2698
2699Py_ssize_t DB_length(PyObject* _self)
2700{
2701 int err;
2702 Py_ssize_t size = 0;
2703 int flags = 0;
2704 void* sp;
2705 DBObject* self = (DBObject*)_self;
2706
2707 if (self->db == NULL) {
2708 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2709 PyErr_SetObject(DBError, t);
2710 Py_DECREF(t);
2711 return -1;
2712 }
2713
2714 if (self->haveStat) { /* Has the stat function been called recently? If
2715 so, we can use the cached value. */
2716 flags = DB_FAST_STAT;
2717 }
2718
2719 MYDB_BEGIN_ALLOW_THREADS;
2720redo_stat_for_length:
2721#if (DBVER >= 43)
2722 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2723#elif (DBVER >= 33)
2724 err = self->db->stat(self->db, &sp, flags);
2725#else
2726 err = self->db->stat(self->db, &sp, NULL, flags);
2727#endif
2728
2729 /* All the stat structures have matching fields upto the ndata field,
2730 so we can use any of them for the type cast */
2731 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2732
2733 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2734 * redo a full stat to make sure.
2735 * Fixes SF python bug 1493322, pybsddb bug 1184012
2736 */
2737 if (size == 0 && (flags & DB_FAST_STAT)) {
2738 flags = 0;
2739 if (!err)
2740 free(sp);
2741 goto redo_stat_for_length;
2742 }
2743
2744 MYDB_END_ALLOW_THREADS;
2745
2746 if (err)
2747 return -1;
2748
2749 self->haveStat = 1;
2750
2751 free(sp);
2752 return size;
2753}
2754
2755
2756PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2757{
2758 int err;
2759 PyObject* retval;
2760 DBT key;
2761 DBT data;
2762
2763 CHECK_DB_NOT_CLOSED(self);
2764 if (!make_key_dbt(self, keyobj, &key, NULL))
2765 return NULL;
2766
2767 CLEAR_DBT(data);
2768 if (CHECK_DBFLAG(self, DB_THREAD)) {
2769 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2770 data.flags = DB_DBT_MALLOC;
2771 }
2772 MYDB_BEGIN_ALLOW_THREADS;
2773 err = self->db->get(self->db, NULL, &key, &data, 0);
2774 MYDB_END_ALLOW_THREADS;
2775 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2776 PyErr_SetObject(PyExc_KeyError, keyobj);
2777 retval = NULL;
2778 }
2779 else if (makeDBError(err)) {
2780 retval = NULL;
2781 }
2782 else {
2783 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2784 FREE_DBT(data);
2785 }
2786
2787 FREE_DBT(key);
2788 return retval;
2789}
2790
2791
2792static int
2793DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2794{
2795 DBT key, data;
2796 int retval;
2797 int flags = 0;
2798
2799 if (self->db == NULL) {
2800 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2801 PyErr_SetObject(DBError, t);
2802 Py_DECREF(t);
2803 return -1;
2804 }
2805
2806 if (!make_key_dbt(self, keyobj, &key, NULL))
2807 return -1;
2808
2809 if (dataobj != NULL) {
2810 if (!make_dbt(dataobj, &data))
2811 retval = -1;
2812 else {
2813 if (self->setflags & (DB_DUP|DB_DUPSORT))
2814 /* dictionaries shouldn't have duplicate keys */
2815 flags = DB_NOOVERWRITE;
2816 retval = _DB_put(self, NULL, &key, &data, flags);
2817
2818 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2819 /* try deleting any old record that matches and then PUT it
2820 * again... */
2821 _DB_delete(self, NULL, &key, 0);
2822 PyErr_Clear();
2823 retval = _DB_put(self, NULL, &key, &data, flags);
2824 }
2825 }
2826 }
2827 else {
2828 /* dataobj == NULL, so delete the key */
2829 retval = _DB_delete(self, NULL, &key, 0);
2830 }
2831 FREE_DBT(key);
2832 return retval;
2833}
2834
2835
2836static PyObject*
2837DB_has_key(DBObject* self, PyObject* args)
2838{
2839 int err;
2840 PyObject* keyobj;
2841 DBT key, data;
2842 PyObject* txnobj = NULL;
2843 DB_TXN *txn = NULL;
2844
2845 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2846 return NULL;
2847 CHECK_DB_NOT_CLOSED(self);
2848 if (!make_key_dbt(self, keyobj, &key, NULL))
2849 return NULL;
2850 if (!checkTxnObj(txnobj, &txn)) {
2851 FREE_DBT(key);
2852 return NULL;
2853 }
2854
2855 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
2856 it has a record but can't allocate a buffer for the data. This saves
2857 having to deal with data we won't be using.
2858 */
2859 CLEAR_DBT(data);
2860 data.flags = DB_DBT_USERMEM;
2861
2862 MYDB_BEGIN_ALLOW_THREADS;
2863 err = self->db->get(self->db, txn, &key, &data, 0);
2864 MYDB_END_ALLOW_THREADS;
2865 FREE_DBT(key);
2866
2867 if (err == DB_BUFFER_SMALL || err == 0) {
2868 return PyInt_FromLong(1);
2869 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2870 return PyInt_FromLong(0);
2871 }
2872
2873 makeDBError(err);
2874 return NULL;
2875}
2876
2877
2878#define _KEYS_LIST 1
2879#define _VALUES_LIST 2
2880#define _ITEMS_LIST 3
2881
2882static PyObject*
2883_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2884{
2885 int err, dbtype;
2886 DBT key;
2887 DBT data;
2888 DBC *cursor;
2889 PyObject* list;
2890 PyObject* item = NULL;
2891
2892 CHECK_DB_NOT_CLOSED(self);
2893 CLEAR_DBT(key);
2894 CLEAR_DBT(data);
2895
2896 dbtype = _DB_get_type(self);
2897 if (dbtype == -1)
2898 return NULL;
2899
2900 list = PyList_New(0);
2901 if (list == NULL)
2902 return NULL;
2903
2904 /* get a cursor */
2905 MYDB_BEGIN_ALLOW_THREADS;
2906 err = self->db->cursor(self->db, txn, &cursor, 0);
2907 MYDB_END_ALLOW_THREADS;
2908 if (makeDBError(err)) {
2909 Py_DECREF(list);
2910 return NULL;
2911 }
2912
2913 if (CHECK_DBFLAG(self, DB_THREAD)) {
2914 key.flags = DB_DBT_REALLOC;
2915 data.flags = DB_DBT_REALLOC;
2916 }
2917
2918 while (1) { /* use the cursor to traverse the DB, collecting items */
2919 MYDB_BEGIN_ALLOW_THREADS;
2920 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2921 MYDB_END_ALLOW_THREADS;
2922
2923 if (err) {
2924 /* for any error, break out of the loop */
2925 break;
2926 }
2927
2928 switch (type) {
2929 case _KEYS_LIST:
2930 switch(dbtype) {
2931 case DB_BTREE:
2932 case DB_HASH:
2933 default:
2934 item = PyString_FromStringAndSize((char*)key.data, key.size);
2935 break;
2936 case DB_RECNO:
2937 case DB_QUEUE:
2938 item = PyInt_FromLong(*((db_recno_t*)key.data));
2939 break;
2940 }
2941 break;
2942
2943 case _VALUES_LIST:
2944 item = PyString_FromStringAndSize((char*)data.data, data.size);
2945 break;
2946
2947 case _ITEMS_LIST:
2948 switch(dbtype) {
2949 case DB_BTREE:
2950 case DB_HASH:
2951 default:
2952 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2953 data.size);
2954 break;
2955 case DB_RECNO:
2956 case DB_QUEUE:
2957 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2958 data.data, data.size);
2959 break;
2960 }
2961 break;
2962 default:
2963 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2964 item = NULL;
2965 break;
2966 }
2967 if (item == NULL) {
2968 Py_DECREF(list);
2969 list = NULL;
2970 goto done;
2971 }
2972 PyList_Append(list, item);
2973 Py_DECREF(item);
2974 }
2975
2976 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2977 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
2978 Py_DECREF(list);
2979 list = NULL;
2980 }
2981
2982 done:
2983 FREE_DBT(key);
2984 FREE_DBT(data);
2985 MYDB_BEGIN_ALLOW_THREADS;
2986 cursor->c_close(cursor);
2987 MYDB_END_ALLOW_THREADS;
2988 return list;
2989}
2990
2991
2992static PyObject*
2993DB_keys(DBObject* self, PyObject* args)
2994{
2995 PyObject* txnobj = NULL;
2996 DB_TXN *txn = NULL;
2997
2998 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
2999 return NULL;
3000 if (!checkTxnObj(txnobj, &txn))
3001 return NULL;
3002 return _DB_make_list(self, txn, _KEYS_LIST);
3003}
3004
3005
3006static PyObject*
3007DB_items(DBObject* self, PyObject* args)
3008{
3009 PyObject* txnobj = NULL;
3010 DB_TXN *txn = NULL;
3011
3012 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
3013 return NULL;
3014 if (!checkTxnObj(txnobj, &txn))
3015 return NULL;
3016 return _DB_make_list(self, txn, _ITEMS_LIST);
3017}
3018
3019
3020static PyObject*
3021DB_values(DBObject* self, PyObject* args)
3022{
3023 PyObject* txnobj = NULL;
3024 DB_TXN *txn = NULL;
3025
3026 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
3027 return NULL;
3028 if (!checkTxnObj(txnobj, &txn))
3029 return NULL;
3030 return _DB_make_list(self, txn, _VALUES_LIST);
3031}
3032
3033/* --------------------------------------------------------------------- */
3034/* DBCursor methods */
3035
3036
3037static PyObject*
3038DBC_close(DBCursorObject* self, PyObject* args)
3039{
3040 int err = 0;
3041
3042 if (!PyArg_ParseTuple(args, ":close"))
3043 return NULL;
3044
3045 if (self->dbc != NULL) {
3046 MYDB_BEGIN_ALLOW_THREADS;
3047 err = self->dbc->c_close(self->dbc);
3048 self->dbc = NULL;
3049 MYDB_END_ALLOW_THREADS;
3050 }
3051 RETURN_IF_ERR();
3052 RETURN_NONE();
3053}
3054
3055
3056static PyObject*
3057DBC_count(DBCursorObject* self, PyObject* args)
3058{
3059 int err = 0;
3060 db_recno_t count;
3061 int flags = 0;
3062
3063 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3064 return NULL;
3065
3066 CHECK_CURSOR_NOT_CLOSED(self);
3067
3068 MYDB_BEGIN_ALLOW_THREADS;
3069 err = self->dbc->c_count(self->dbc, &count, flags);
3070 MYDB_END_ALLOW_THREADS;
3071 RETURN_IF_ERR();
3072
3073 return PyInt_FromLong(count);
3074}
3075
3076
3077static PyObject*
3078DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3079{
3080 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3081}
3082
3083
3084static PyObject*
3085DBC_delete(DBCursorObject* self, PyObject* args)
3086{
3087 int err, flags=0;
3088
3089 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3090 return NULL;
3091
3092 CHECK_CURSOR_NOT_CLOSED(self);
3093
3094 MYDB_BEGIN_ALLOW_THREADS;
3095 err = self->dbc->c_del(self->dbc, flags);
3096 MYDB_END_ALLOW_THREADS;
3097 RETURN_IF_ERR();
3098
3099 self->mydb->haveStat = 0;
3100 RETURN_NONE();
3101}
3102
3103
3104static PyObject*
3105DBC_dup(DBCursorObject* self, PyObject* args)
3106{
3107 int err, flags =0;
3108 DBC* dbc = NULL;
3109
3110 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3111 return NULL;
3112
3113 CHECK_CURSOR_NOT_CLOSED(self);
3114
3115 MYDB_BEGIN_ALLOW_THREADS;
3116 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3117 MYDB_END_ALLOW_THREADS;
3118 RETURN_IF_ERR();
3119
3120 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3121}
3122
3123static PyObject*
3124DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3125{
3126 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3127}
3128
3129
3130static PyObject*
3131DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3132{
3133 int err, flags=0;
3134 PyObject* keyobj = NULL;
3135 PyObject* dataobj = NULL;
3136 PyObject* retval = NULL;
3137 int dlen = -1;
3138 int doff = -1;
3139 DBT key, data;
3140 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3141 NULL };
3142
3143 CLEAR_DBT(key);
3144 CLEAR_DBT(data);
3145 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3146 &flags, &dlen, &doff))
3147 {
3148 PyErr_Clear();
3149 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3150 &kwnames[1],
3151 &keyobj, &flags, &dlen, &doff))
3152 {
3153 PyErr_Clear();
3154 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3155 kwnames, &keyobj, &dataobj,
3156 &flags, &dlen, &doff))
3157 {
3158 return NULL;
3159 }
3160 }
3161 }
3162
3163 CHECK_CURSOR_NOT_CLOSED(self);
3164
3165 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3166 return NULL;
3167 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3168 (!add_partial_dbt(&data, dlen, doff)) )
3169 {
3170 FREE_DBT(key);
3171 return NULL;
3172 }
3173
3174 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3175 data.flags = DB_DBT_MALLOC;
3176 if (!(key.flags & DB_DBT_REALLOC)) {
3177 key.flags |= DB_DBT_MALLOC;
3178 }
3179 }
3180
3181 MYDB_BEGIN_ALLOW_THREADS;
3182 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3183 MYDB_END_ALLOW_THREADS;
3184
3185 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3186 && self->mydb->moduleFlags.getReturnsNone) {
3187 Py_INCREF(Py_None);
3188 retval = Py_None;
3189 }
3190 else if (makeDBError(err)) {
3191 retval = NULL;
3192 }
3193 else {
3194 switch (_DB_get_type(self->mydb)) {
3195 case -1:
3196 retval = NULL;
3197 break;
3198 case DB_BTREE:
3199 case DB_HASH:
3200 default:
3201 retval = Py_BuildValue("s#s#", key.data, key.size,
3202 data.data, data.size);
3203 break;
3204 case DB_RECNO:
3205 case DB_QUEUE:
3206 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3207 data.data, data.size);
3208 break;
3209 }
3210 FREE_DBT(data);
3211 }
3212 FREE_DBT(key);
3213 return retval;
3214}
3215
3216#if (DBVER >= 33)
3217static PyObject*
3218DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3219{
3220 int err, flags=0;
3221 PyObject* keyobj = NULL;
3222 PyObject* dataobj = NULL;
3223 PyObject* retval = NULL;
3224 int dlen = -1;
3225 int doff = -1;
3226 DBT key, pkey, data;
3227 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3228 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3229
3230 CLEAR_DBT(key);
3231 CLEAR_DBT(data);
3232 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3233 &flags, &dlen, &doff))
3234 {
3235 PyErr_Clear();
3236 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3237 kwnames_keyOnly,
3238 &keyobj, &flags, &dlen, &doff))
3239 {
3240 PyErr_Clear();
3241 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3242 kwnames, &keyobj, &dataobj,
3243 &flags, &dlen, &doff))
3244 {
3245 return NULL;
3246 }
3247 }
3248 }
3249
3250 CHECK_CURSOR_NOT_CLOSED(self);
3251
3252 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3253 return NULL;
3254 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3255 (!add_partial_dbt(&data, dlen, doff)) ) {
3256 FREE_DBT(key);
3257 return NULL;
3258 }
3259
3260 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3261 data.flags = DB_DBT_MALLOC;
3262 if (!(key.flags & DB_DBT_REALLOC)) {
3263 key.flags |= DB_DBT_MALLOC;
3264 }
3265 }
3266
3267 CLEAR_DBT(pkey);
3268 pkey.flags = DB_DBT_MALLOC;
3269
3270 MYDB_BEGIN_ALLOW_THREADS;
3271 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3272 MYDB_END_ALLOW_THREADS;
3273
3274 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3275 && self->mydb->moduleFlags.getReturnsNone) {
3276 Py_INCREF(Py_None);
3277 retval = Py_None;
3278 }
3279 else if (makeDBError(err)) {
3280 retval = NULL;
3281 }
3282 else {
3283 PyObject *pkeyObj;
3284 PyObject *dataObj;
3285 dataObj = PyString_FromStringAndSize(data.data, data.size);
3286
3287 if (self->mydb->primaryDBType == DB_RECNO ||
3288 self->mydb->primaryDBType == DB_QUEUE)
3289 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
3290 else
3291 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3292
3293 if (key.data && key.size) /* return key, pkey and data */
3294 {
3295 PyObject *keyObj;
3296 int type = _DB_get_type(self->mydb);
3297 if (type == DB_RECNO || type == DB_QUEUE)
3298 keyObj = PyInt_FromLong(*(int *)key.data);
3299 else
3300 keyObj = PyString_FromStringAndSize(key.data, key.size);
3301#if (PY_VERSION_HEX >= 0x02040000)
3302 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
3303#else
3304 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3305#endif
3306 Py_DECREF(keyObj);
3307 FREE_DBT(key);
3308 }
3309 else /* return just the pkey and data */
3310 {
3311#if (PY_VERSION_HEX >= 0x02040000)
3312 retval = PyTuple_Pack(2, pkeyObj, dataObj);
3313#else
3314 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3315#endif
3316 }
3317 Py_DECREF(dataObj);
3318 Py_DECREF(pkeyObj);
3319 FREE_DBT(pkey);
3320 FREE_DBT(data);
3321 }
3322 /* the only time REALLOC should be set is if we used an integer
3323 * key that make_key_dbt malloc'd for us. always free these. */
3324 if (key.flags & DB_DBT_REALLOC) {
3325 FREE_DBT(key);
3326 }
3327 return retval;
3328}
3329#endif
3330
3331
3332static PyObject*
3333DBC_get_recno(DBCursorObject* self, PyObject* args)
3334{
3335 int err;
3336 db_recno_t recno;
3337 DBT key;
3338 DBT data;
3339
3340 if (!PyArg_ParseTuple(args, ":get_recno"))
3341 return NULL;
3342
3343 CHECK_CURSOR_NOT_CLOSED(self);
3344
3345 CLEAR_DBT(key);
3346 CLEAR_DBT(data);
3347 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3348 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3349 data.flags = DB_DBT_MALLOC;
3350 key.flags = DB_DBT_MALLOC;
3351 }
3352
3353 MYDB_BEGIN_ALLOW_THREADS;
3354 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3355 MYDB_END_ALLOW_THREADS;
3356 RETURN_IF_ERR();
3357
3358 recno = *((db_recno_t*)data.data);
3359 FREE_DBT(key);
3360 FREE_DBT(data);
3361 return PyInt_FromLong(recno);
3362}
3363
3364
3365static PyObject*
3366DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3367{
3368 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3369}
3370
3371
3372static PyObject*
3373DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3374{
3375 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3376}
3377
3378
3379static PyObject*
3380DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3381{
3382 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3383}
3384
3385
3386static PyObject*
3387DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3388{
3389 int err, flags = 0;
3390 PyObject* keyobj, *dataobj;
3391 DBT key, data;
3392 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3393 NULL };
3394 int dlen = -1;
3395 int doff = -1;
3396
3397 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3398 &keyobj, &dataobj, &flags, &dlen, &doff))
3399 return NULL;
3400
3401 CHECK_CURSOR_NOT_CLOSED(self);
3402
3403 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3404 return NULL;
3405 if (!make_dbt(dataobj, &data) ||
3406 !add_partial_dbt(&data, dlen, doff) )
3407 {
3408 FREE_DBT(key);
3409 return NULL;
3410 }
3411
3412 MYDB_BEGIN_ALLOW_THREADS;
3413 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3414 MYDB_END_ALLOW_THREADS;
3415 FREE_DBT(key);
3416 RETURN_IF_ERR();
3417 self->mydb->haveStat = 0;
3418 RETURN_NONE();
3419}
3420
3421
3422static PyObject*
3423DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3424{
3425 int err, flags = 0;
3426 DBT key, data;
3427 PyObject* retval, *keyobj;
3428 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3429 int dlen = -1;
3430 int doff = -1;
3431
3432 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3433 &keyobj, &flags, &dlen, &doff))
3434 return NULL;
3435
3436 CHECK_CURSOR_NOT_CLOSED(self);
3437
3438 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3439 return NULL;
3440
3441 CLEAR_DBT(data);
3442 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3443 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3444 data.flags = DB_DBT_MALLOC;
3445 }
3446 if (!add_partial_dbt(&data, dlen, doff)) {
3447 FREE_DBT(key);
3448 return NULL;
3449 }
3450
3451 MYDB_BEGIN_ALLOW_THREADS;
3452 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3453 MYDB_END_ALLOW_THREADS;
3454 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3455 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3456 Py_INCREF(Py_None);
3457 retval = Py_None;
3458 }
3459 else if (makeDBError(err)) {
3460 retval = NULL;
3461 }
3462 else {
3463 switch (_DB_get_type(self->mydb)) {
3464 case -1:
3465 retval = NULL;
3466 break;
3467 case DB_BTREE:
3468 case DB_HASH:
3469 default:
3470 retval = Py_BuildValue("s#s#", key.data, key.size,
3471 data.data, data.size);
3472 break;
3473 case DB_RECNO:
3474 case DB_QUEUE:
3475 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3476 data.data, data.size);
3477 break;
3478 }
3479 FREE_DBT(data);
3480 FREE_DBT(key);
3481 }
3482 /* the only time REALLOC should be set is if we used an integer
3483 * key that make_key_dbt malloc'd for us. always free these. */
3484 if (key.flags & DB_DBT_REALLOC) {
3485 FREE_DBT(key);
3486 }
3487
3488 return retval;
3489}
3490
3491
3492static PyObject*
3493DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3494{
3495 int err, flags = 0;
3496 DBT key, data;
3497 PyObject* retval, *keyobj;
3498 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3499 int dlen = -1;
3500 int doff = -1;
3501
3502 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3503 &keyobj, &flags, &dlen, &doff))
3504 return NULL;
3505
3506 CHECK_CURSOR_NOT_CLOSED(self);
3507
3508 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3509 return NULL;
3510
3511 CLEAR_DBT(data);
3512 if (!add_partial_dbt(&data, dlen, doff)) {
3513 FREE_DBT(key);
3514 return NULL;
3515 }
3516 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3517 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3518 data.flags |= DB_DBT_MALLOC;
3519 /* only BTREE databases will return anything in the key */
3520 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3521 key.flags |= DB_DBT_MALLOC;
3522 }
3523 }
3524 MYDB_BEGIN_ALLOW_THREADS;
3525 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3526 MYDB_END_ALLOW_THREADS;
3527 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3528 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3529 Py_INCREF(Py_None);
3530 retval = Py_None;
3531 }
3532 else if (makeDBError(err)) {
3533 retval = NULL;
3534 }
3535 else {
3536 switch (_DB_get_type(self->mydb)) {
3537 case -1:
3538 retval = NULL;
3539 break;
3540 case DB_BTREE:
3541 case DB_HASH:
3542 default:
3543 retval = Py_BuildValue("s#s#", key.data, key.size,
3544 data.data, data.size);
3545 break;
3546 case DB_RECNO:
3547 case DB_QUEUE:
3548 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3549 data.data, data.size);
3550 break;
3551 }
3552 FREE_DBT(key);
3553 FREE_DBT(data);
3554 }
3555 /* the only time REALLOC should be set is if we used an integer
3556 * key that make_key_dbt malloc'd for us. always free these. */
3557 if (key.flags & DB_DBT_REALLOC) {
3558 FREE_DBT(key);
3559 }
3560
3561 return retval;
3562}
3563
3564static PyObject*
3565_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3566 int flags, unsigned int returnsNone)
3567{
3568 int err;
3569 DBT key, data;
3570 PyObject* retval;
3571
3572 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3573 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3574 return NULL;
3575 if (!make_dbt(dataobj, &data)) {
3576 FREE_DBT(key);
3577 return NULL;
3578 }
3579
3580 MYDB_BEGIN_ALLOW_THREADS;
3581 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3582 MYDB_END_ALLOW_THREADS;
3583 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3584 Py_INCREF(Py_None);
3585 retval = Py_None;
3586 }
3587 else if (makeDBError(err)) {
3588 retval = NULL;
3589 }
3590 else {
3591 switch (_DB_get_type(self->mydb)) {
3592 case -1:
3593 retval = NULL;
3594 break;
3595 case DB_BTREE:
3596 case DB_HASH:
3597 default:
3598 retval = Py_BuildValue("s#s#", key.data, key.size,
3599 data.data, data.size);
3600 break;
3601 case DB_RECNO:
3602 case DB_QUEUE:
3603 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3604 data.data, data.size);
3605 break;
3606 }
3607 }
3608
3609 FREE_DBT(key);
3610 return retval;
3611}
3612
3613static PyObject*
3614DBC_get_both(DBCursorObject* self, PyObject* args)
3615{
3616 int flags=0;
3617 PyObject *keyobj, *dataobj;
3618
3619 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3620 return NULL;
3621
3622 /* if the cursor is closed, self->mydb may be invalid */
3623 CHECK_CURSOR_NOT_CLOSED(self);
3624
3625 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3626 self->mydb->moduleFlags.getReturnsNone);
3627}
3628
3629/* Return size of entry */
3630static PyObject*
3631DBC_get_current_size(DBCursorObject* self, PyObject* args)
3632{
3633 int err, flags=DB_CURRENT;
3634 PyObject* retval = NULL;
3635 DBT key, data;
3636
3637 if (!PyArg_ParseTuple(args, ":get_current_size"))
3638 return NULL;
3639 CHECK_CURSOR_NOT_CLOSED(self);
3640 CLEAR_DBT(key);
3641 CLEAR_DBT(data);
3642
3643 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3644 getting the record size. */
3645 data.flags = DB_DBT_USERMEM;
3646 data.ulen = 0;
3647 MYDB_BEGIN_ALLOW_THREADS;
3648 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3649 MYDB_END_ALLOW_THREADS;
3650 if (err == DB_BUFFER_SMALL || !err) {
3651 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3652 retval = PyInt_FromLong((long)data.size);
3653 err = 0;
3654 }
3655
3656 FREE_DBT(key);
3657 FREE_DBT(data);
3658 RETURN_IF_ERR();
3659 return retval;
3660}
3661
3662static PyObject*
3663DBC_set_both(DBCursorObject* self, PyObject* args)
3664{
3665 int flags=0;
3666 PyObject *keyobj, *dataobj;
3667
3668 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3669 return NULL;
3670
3671 /* if the cursor is closed, self->mydb may be invalid */
3672 CHECK_CURSOR_NOT_CLOSED(self);
3673
3674 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3675 self->mydb->moduleFlags.cursorSetReturnsNone);
3676}
3677
3678
3679static PyObject*
3680DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3681{
3682 int err, irecno, flags=0;
3683 db_recno_t recno;
3684 DBT key, data;
3685 PyObject* retval;
3686 int dlen = -1;
3687 int doff = -1;
3688 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3689
3690 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3691 &irecno, &flags, &dlen, &doff))
3692 return NULL;
3693
3694 CHECK_CURSOR_NOT_CLOSED(self);
3695
3696 CLEAR_DBT(key);
3697 recno = (db_recno_t) irecno;
3698 /* use allocated space so DB will be able to realloc room for the real
3699 * key */
3700 key.data = malloc(sizeof(db_recno_t));
3701 if (key.data == NULL) {
3702 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3703 return NULL;
3704 }
3705 key.size = sizeof(db_recno_t);
3706 key.ulen = key.size;
3707 memcpy(key.data, &recno, sizeof(db_recno_t));
3708 key.flags = DB_DBT_REALLOC;
3709
3710 CLEAR_DBT(data);
3711 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3712 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3713 data.flags = DB_DBT_MALLOC;
3714 }
3715 if (!add_partial_dbt(&data, dlen, doff)) {
3716 FREE_DBT(key);
3717 return NULL;
3718 }
3719
3720 MYDB_BEGIN_ALLOW_THREADS;
3721 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3722 MYDB_END_ALLOW_THREADS;
3723 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3724 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3725 Py_INCREF(Py_None);
3726 retval = Py_None;
3727 }
3728 else if (makeDBError(err)) {
3729 retval = NULL;
3730 }
3731 else { /* Can only be used for BTrees, so no need to return int key */
3732 retval = Py_BuildValue("s#s#", key.data, key.size,
3733 data.data, data.size);
3734 FREE_DBT(data);
3735 }
3736 FREE_DBT(key);
3737
3738 return retval;
3739}
3740
3741
3742static PyObject*
3743DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3744{
3745 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3746}
3747
3748
3749static PyObject*
3750DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3751{
3752 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3753}
3754
3755
3756static PyObject*
3757DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3758{
3759 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3760}
3761
3762
3763static PyObject*
3764DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3765{
3766 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3767}
3768
3769
3770static PyObject*
3771DBC_join_item(DBCursorObject* self, PyObject* args)
3772{
3773 int err, flags=0;
3774 DBT key, data;
3775 PyObject* retval;
3776
3777 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3778 return NULL;
3779
3780 CHECK_CURSOR_NOT_CLOSED(self);
3781
3782 CLEAR_DBT(key);
3783 CLEAR_DBT(data);
3784 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3785 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3786 key.flags = DB_DBT_MALLOC;
3787 }
3788
3789 MYDB_BEGIN_ALLOW_THREADS;
3790 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3791 MYDB_END_ALLOW_THREADS;
3792 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3793 && self->mydb->moduleFlags.getReturnsNone) {
3794 Py_INCREF(Py_None);
3795 retval = Py_None;
3796 }
3797 else if (makeDBError(err)) {
3798 retval = NULL;
3799 }
3800 else {
3801 retval = Py_BuildValue("s#", key.data, key.size);
3802 FREE_DBT(key);
3803 }
3804
3805 return retval;
3806}
3807
3808
3809
3810/* --------------------------------------------------------------------- */
3811/* DBEnv methods */
3812
3813
3814static PyObject*
3815DBEnv_close(DBEnvObject* self, PyObject* args)
3816{
3817 int err, flags = 0;
3818
3819 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3820 return NULL;
3821 if (!self->closed) { /* Don't close more than once */
3822 MYDB_BEGIN_ALLOW_THREADS;
3823 err = self->db_env->close(self->db_env, flags);
3824 MYDB_END_ALLOW_THREADS;
3825 /* after calling DBEnv->close, regardless of error, this DBEnv
3826 * may not be accessed again (BerkeleyDB docs). */
3827 self->closed = 1;
3828 self->db_env = NULL;
3829 RETURN_IF_ERR();
3830 }
3831 RETURN_NONE();
3832}
3833
3834
3835static PyObject*
3836DBEnv_open(DBEnvObject* self, PyObject* args)
3837{
3838 int err, flags=0, mode=0660;
3839 char *db_home;
3840
3841 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3842 return NULL;
3843
3844 CHECK_ENV_NOT_CLOSED(self);
3845
3846 MYDB_BEGIN_ALLOW_THREADS;
3847 err = self->db_env->open(self->db_env, db_home, flags, mode);
3848 MYDB_END_ALLOW_THREADS;
3849 RETURN_IF_ERR();
3850 self->closed = 0;
3851 self->flags = flags;
3852 RETURN_NONE();
3853}
3854
3855
3856static PyObject*
3857DBEnv_remove(DBEnvObject* self, PyObject* args)
3858{
3859 int err, flags=0;
3860 char *db_home;
3861
3862 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3863 return NULL;
3864 CHECK_ENV_NOT_CLOSED(self);
3865 MYDB_BEGIN_ALLOW_THREADS;
3866 err = self->db_env->remove(self->db_env, db_home, flags);
3867 MYDB_END_ALLOW_THREADS;
3868 RETURN_IF_ERR();
3869 RETURN_NONE();
3870}
3871
3872#if (DBVER >= 41)
3873static PyObject*
3874DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3875{
3876 int err;
3877 u_int32_t flags=0;
3878 char *file = NULL;
3879 char *database = NULL;
3880 PyObject *txnobj = NULL;
3881 DB_TXN *txn = NULL;
3882 static char* kwnames[] = { "file", "database", "txn", "flags",
3883 NULL };
3884
3885 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
3886 &file, &database, &txnobj, &flags)) {
3887 return NULL;
3888 }
3889 if (!checkTxnObj(txnobj, &txn)) {
3890 return NULL;
3891 }
3892 CHECK_ENV_NOT_CLOSED(self);
3893 MYDB_BEGIN_ALLOW_THREADS;
3894 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3895 MYDB_END_ALLOW_THREADS;
3896 RETURN_IF_ERR();
3897 RETURN_NONE();
3898}
3899
3900static PyObject*
3901DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3902{
3903 int err;
3904 u_int32_t flags=0;
3905 char *file = NULL;
3906 char *database = NULL;
3907 char *newname = NULL;
3908 PyObject *txnobj = NULL;
3909 DB_TXN *txn = NULL;
3910 static char* kwnames[] = { "file", "database", "newname", "txn",
3911 "flags", NULL };
3912
3913 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
3914 &file, &database, &newname, &txnobj, &flags)) {
3915 return NULL;
3916 }
3917 if (!checkTxnObj(txnobj, &txn)) {
3918 return NULL;
3919 }
3920 CHECK_ENV_NOT_CLOSED(self);
3921 MYDB_BEGIN_ALLOW_THREADS;
3922 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3923 flags);
3924 MYDB_END_ALLOW_THREADS;
3925 RETURN_IF_ERR();
3926 RETURN_NONE();
3927}
3928
3929static PyObject*
3930DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3931{
3932 int err;
3933 u_int32_t flags=0;
3934 char *passwd = NULL;
3935 static char* kwnames[] = { "passwd", "flags", NULL };
3936
3937 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3938 &passwd, &flags)) {
3939 return NULL;
3940 }
3941
3942 MYDB_BEGIN_ALLOW_THREADS;
3943 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3944 MYDB_END_ALLOW_THREADS;
3945
3946 RETURN_IF_ERR();
3947 RETURN_NONE();
3948}
3949#endif /* DBVER >= 41 */
3950
3951#if (DBVER >= 40)
3952static PyObject*
3953DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3954{
3955 int err;
3956 u_int32_t flags=0;
3957 u_int32_t timeout = 0;
3958 static char* kwnames[] = { "timeout", "flags", NULL };
3959
3960 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3961 &timeout, &flags)) {
3962 return NULL;
3963 }
3964
3965 MYDB_BEGIN_ALLOW_THREADS;
3966 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3967 MYDB_END_ALLOW_THREADS;
3968
3969 RETURN_IF_ERR();
3970 RETURN_NONE();
3971}
3972#endif /* DBVER >= 40 */
3973
3974static PyObject*
3975DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3976{
3977 int err;
3978 long shm_key = 0;
3979
3980 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3981 return NULL;
3982 CHECK_ENV_NOT_CLOSED(self);
3983
3984 err = self->db_env->set_shm_key(self->db_env, shm_key);
3985 RETURN_IF_ERR();
3986 RETURN_NONE();
3987}
3988
3989static PyObject*
3990DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3991{
3992 int err, gbytes=0, bytes=0, ncache=0;
3993
3994 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3995 &gbytes, &bytes, &ncache))
3996 return NULL;
3997 CHECK_ENV_NOT_CLOSED(self);
3998
3999 MYDB_BEGIN_ALLOW_THREADS;
4000 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4001 MYDB_END_ALLOW_THREADS;
4002 RETURN_IF_ERR();
4003 RETURN_NONE();
4004}
4005
4006
4007#if (DBVER >= 32)
4008static PyObject*
4009DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4010{
4011 int err, flags=0, onoff=0;
4012
4013 if (!PyArg_ParseTuple(args, "ii:set_flags",
4014 &flags, &onoff))
4015 return NULL;
4016 CHECK_ENV_NOT_CLOSED(self);
4017
4018 MYDB_BEGIN_ALLOW_THREADS;
4019 err = self->db_env->set_flags(self->db_env, flags, onoff);
4020 MYDB_END_ALLOW_THREADS;
4021 RETURN_IF_ERR();
4022 RETURN_NONE();
4023}
4024#endif
4025
4026
4027static PyObject*
4028DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4029{
4030 int err;
4031 char *dir;
4032
4033 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4034 return NULL;
4035 CHECK_ENV_NOT_CLOSED(self);
4036
4037 MYDB_BEGIN_ALLOW_THREADS;
4038 err = self->db_env->set_data_dir(self->db_env, dir);
4039 MYDB_END_ALLOW_THREADS;
4040 RETURN_IF_ERR();
4041 RETURN_NONE();
4042}
4043
4044
4045static PyObject*
4046DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4047{
4048 int err, lg_bsize;
4049
4050 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4051 return NULL;
4052 CHECK_ENV_NOT_CLOSED(self);
4053
4054 MYDB_BEGIN_ALLOW_THREADS;
4055 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4056 MYDB_END_ALLOW_THREADS;
4057 RETURN_IF_ERR();
4058 RETURN_NONE();
4059}
4060
4061
4062static PyObject*
4063DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4064{
4065 int err;
4066 char *dir;
4067
4068 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4069 return NULL;
4070 CHECK_ENV_NOT_CLOSED(self);
4071
4072 MYDB_BEGIN_ALLOW_THREADS;
4073 err = self->db_env->set_lg_dir(self->db_env, dir);
4074 MYDB_END_ALLOW_THREADS;
4075 RETURN_IF_ERR();
4076 RETURN_NONE();
4077}
4078
4079static PyObject*
4080DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4081{
4082 int err, lg_max;
4083
4084 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4085 return NULL;
4086 CHECK_ENV_NOT_CLOSED(self);
4087
4088 MYDB_BEGIN_ALLOW_THREADS;
4089 err = self->db_env->set_lg_max(self->db_env, lg_max);
4090 MYDB_END_ALLOW_THREADS;
4091 RETURN_IF_ERR();
4092 RETURN_NONE();
4093}
4094
4095
4096#if (DBVER >= 33)
4097static PyObject*
4098DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4099{
4100 int err, lg_max;
4101
4102 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4103 return NULL;
4104 CHECK_ENV_NOT_CLOSED(self);
4105
4106 MYDB_BEGIN_ALLOW_THREADS;
4107 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4108 MYDB_END_ALLOW_THREADS;
4109 RETURN_IF_ERR();
4110 RETURN_NONE();
4111}
4112#endif
4113
4114
4115static PyObject*
4116DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4117{
4118 int err, lk_detect;
4119
4120 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4121 return NULL;
4122 CHECK_ENV_NOT_CLOSED(self);
4123
4124 MYDB_BEGIN_ALLOW_THREADS;
4125 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4126 MYDB_END_ALLOW_THREADS;
4127 RETURN_IF_ERR();
4128 RETURN_NONE();
4129}
4130
4131
4132static PyObject*
4133DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4134{
4135 int err, max;
4136
4137 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4138 return NULL;
4139 CHECK_ENV_NOT_CLOSED(self);
4140
4141 MYDB_BEGIN_ALLOW_THREADS;
4142 err = self->db_env->set_lk_max(self->db_env, max);
4143 MYDB_END_ALLOW_THREADS;
4144 RETURN_IF_ERR();
4145 RETURN_NONE();
4146}
4147
4148
4149#if (DBVER >= 32)
4150
4151static PyObject*
4152DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4153{
4154 int err, max;
4155
4156 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4157 return NULL;
4158 CHECK_ENV_NOT_CLOSED(self);
4159
4160 MYDB_BEGIN_ALLOW_THREADS;
4161 err = self->db_env->set_lk_max_locks(self->db_env, max);
4162 MYDB_END_ALLOW_THREADS;
4163 RETURN_IF_ERR();
4164 RETURN_NONE();
4165}
4166
4167
4168static PyObject*
4169DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4170{
4171 int err, max;
4172
4173 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4174 return NULL;
4175 CHECK_ENV_NOT_CLOSED(self);
4176
4177 MYDB_BEGIN_ALLOW_THREADS;
4178 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4179 MYDB_END_ALLOW_THREADS;
4180 RETURN_IF_ERR();
4181 RETURN_NONE();
4182}
4183
4184
4185static PyObject*
4186DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4187{
4188 int err, max;
4189
4190 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4191 return NULL;
4192 CHECK_ENV_NOT_CLOSED(self);
4193
4194 MYDB_BEGIN_ALLOW_THREADS;
4195 err = self->db_env->set_lk_max_objects(self->db_env, max);
4196 MYDB_END_ALLOW_THREADS;
4197 RETURN_IF_ERR();
4198 RETURN_NONE();
4199}
4200
4201#endif
4202
4203
4204static PyObject*
4205DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4206{
4207 int err, mp_mmapsize;
4208
4209 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4210 return NULL;
4211 CHECK_ENV_NOT_CLOSED(self);
4212
4213 MYDB_BEGIN_ALLOW_THREADS;
4214 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4215 MYDB_END_ALLOW_THREADS;
4216 RETURN_IF_ERR();
4217 RETURN_NONE();
4218}
4219
4220
4221static PyObject*
4222DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4223{
4224 int err;
4225 char *dir;
4226
4227 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4228 return NULL;
4229 CHECK_ENV_NOT_CLOSED(self);
4230
4231 MYDB_BEGIN_ALLOW_THREADS;
4232 err = self->db_env->set_tmp_dir(self->db_env, dir);
4233 MYDB_END_ALLOW_THREADS;
4234 RETURN_IF_ERR();
4235 RETURN_NONE();
4236}
4237
4238
4239static PyObject*
4240DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4241{
4242 int flags = 0;
4243 PyObject* txnobj = NULL;
4244 DB_TXN *txn = NULL;
4245 static char* kwnames[] = { "parent", "flags", NULL };
4246
4247 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4248 &txnobj, &flags))
4249 return NULL;
4250
4251 if (!checkTxnObj(txnobj, &txn))
4252 return NULL;
4253 CHECK_ENV_NOT_CLOSED(self);
4254
4255 return (PyObject*)newDBTxnObject(self, txn, flags);
4256}
4257
4258
4259static PyObject*
4260DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4261{
4262 int err, kbyte=0, min=0, flags=0;
4263
4264 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4265 return NULL;
4266 CHECK_ENV_NOT_CLOSED(self);
4267
4268 MYDB_BEGIN_ALLOW_THREADS;
4269#if (DBVER >= 40)
4270 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4271#else
4272 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4273#endif
4274 MYDB_END_ALLOW_THREADS;
4275 RETURN_IF_ERR();
4276 RETURN_NONE();
4277}
4278
4279
4280static PyObject*
4281DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4282{
4283 int err, max;
4284
4285 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4286 return NULL;
4287 CHECK_ENV_NOT_CLOSED(self);
4288
4289 err = self->db_env->set_tx_max(self->db_env, max);
4290 RETURN_IF_ERR();
4291 RETURN_NONE();
4292}
4293
4294
4295static PyObject*
4296DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4297{
4298 int err;
4299 long stamp;
4300 time_t timestamp;
4301
4302 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
4303 return NULL;
4304 CHECK_ENV_NOT_CLOSED(self);
4305 timestamp = (time_t)stamp;
4306 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
4307 RETURN_IF_ERR();
4308 RETURN_NONE();
4309}
4310
4311
4312static PyObject*
4313DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4314{
4315 int err, atype, flags=0;
4316 int aborted = 0;
4317
4318 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4319 return NULL;
4320 CHECK_ENV_NOT_CLOSED(self);
4321
4322 MYDB_BEGIN_ALLOW_THREADS;
4323#if (DBVER >= 40)
4324 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4325#else
4326 err = lock_detect(self->db_env, flags, atype, &aborted);
4327#endif
4328 MYDB_END_ALLOW_THREADS;
4329 RETURN_IF_ERR();
4330 return PyInt_FromLong(aborted);
4331}
4332
4333
4334static PyObject*
4335DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4336{
4337 int flags=0;
4338 int locker, lock_mode;
4339 DBT obj;
4340 PyObject* objobj;
4341
4342 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4343 return NULL;
4344
4345
4346 if (!make_dbt(objobj, &obj))
4347 return NULL;
4348
4349 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4350}
4351
4352
4353static PyObject*
4354DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4355{
4356 int err;
4357 u_int32_t theID;
4358
4359 if (!PyArg_ParseTuple(args, ":lock_id"))
4360 return NULL;
4361
4362 CHECK_ENV_NOT_CLOSED(self);
4363 MYDB_BEGIN_ALLOW_THREADS;
4364#if (DBVER >= 40)
4365 err = self->db_env->lock_id(self->db_env, &theID);
4366#else
4367 err = lock_id(self->db_env, &theID);
4368#endif
4369 MYDB_END_ALLOW_THREADS;
4370 RETURN_IF_ERR();
4371
4372 return PyInt_FromLong((long)theID);
4373}
4374
4375
4376static PyObject*
4377DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4378{
4379 int err;
4380 DBLockObject* dblockobj;
4381
4382 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4383 return NULL;
4384
4385 CHECK_ENV_NOT_CLOSED(self);
4386 MYDB_BEGIN_ALLOW_THREADS;
4387#if (DBVER >= 40)
4388 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4389#else
4390 err = lock_put(self->db_env, &dblockobj->lock);
4391#endif
4392 MYDB_END_ALLOW_THREADS;
4393 RETURN_IF_ERR();
4394 RETURN_NONE();
4395}
4396
4397#if (DBVER >= 44)
4398static PyObject*
4399DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4400{
4401 int err;
4402 char *file;
4403 u_int32_t flags = 0;
4404 static char* kwnames[] = { "file", "flags", NULL};
4405
4406 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4407 &file, &flags))
4408 return NULL;
4409 CHECK_ENV_NOT_CLOSED(self);
4410
4411 MYDB_BEGIN_ALLOW_THREADS;
4412 err = self->db_env->lsn_reset(self->db_env, file, flags);
4413 MYDB_END_ALLOW_THREADS;
4414 RETURN_IF_ERR();
4415 RETURN_NONE();
4416}
4417#endif /* DBVER >= 4.4 */
4418
4419#if (DBVER >= 40)
4420static PyObject*
4421DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4422{
4423 int err;
4424 DB_LOG_STAT* statp = NULL;
4425 PyObject* d = NULL;
4426 u_int32_t flags = 0;
4427
4428 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4429 return NULL;
4430 CHECK_ENV_NOT_CLOSED(self);
4431
4432 MYDB_BEGIN_ALLOW_THREADS;
4433 err = self->db_env->log_stat(self->db_env, &statp, flags);
4434 MYDB_END_ALLOW_THREADS;
4435 RETURN_IF_ERR();
4436
4437 /* Turn the stat structure into a dictionary */
4438 d = PyDict_New();
4439 if (d == NULL) {
4440 if (statp)
4441 free(statp);
4442 return NULL;
4443 }
4444
4445#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4446
4447 MAKE_ENTRY(magic);
4448 MAKE_ENTRY(version);
4449 MAKE_ENTRY(mode);
4450 MAKE_ENTRY(lg_bsize);
4451#if (DBVER >= 44)
4452 MAKE_ENTRY(lg_size);
4453 MAKE_ENTRY(record);
4454#endif
4455#if (DBVER <= 40)
4456 MAKE_ENTRY(lg_max);
4457#endif
4458 MAKE_ENTRY(w_mbytes);
4459 MAKE_ENTRY(w_bytes);
4460 MAKE_ENTRY(wc_mbytes);
4461 MAKE_ENTRY(wc_bytes);
4462 MAKE_ENTRY(wcount);
4463 MAKE_ENTRY(wcount_fill);
4464#if (DBVER >= 44)
4465 MAKE_ENTRY(rcount);
4466#endif
4467 MAKE_ENTRY(scount);
4468 MAKE_ENTRY(cur_file);
4469 MAKE_ENTRY(cur_offset);
4470 MAKE_ENTRY(disk_file);
4471 MAKE_ENTRY(disk_offset);
4472 MAKE_ENTRY(maxcommitperflush);
4473 MAKE_ENTRY(mincommitperflush);
4474 MAKE_ENTRY(regsize);
4475 MAKE_ENTRY(region_wait);
4476 MAKE_ENTRY(region_nowait);
4477
4478#undef MAKE_ENTRY
4479 free(statp);
4480 return d;
4481} /* DBEnv_log_stat */
4482#endif /* DBVER >= 4.0 for log_stat method */
4483
4484
4485static PyObject*
4486DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4487{
4488 int err;
4489 DB_LOCK_STAT* sp;
4490 PyObject* d = NULL;
4491 u_int32_t flags = 0;
4492
4493 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4494 return NULL;
4495 CHECK_ENV_NOT_CLOSED(self);
4496
4497 MYDB_BEGIN_ALLOW_THREADS;
4498#if (DBVER >= 40)
4499 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4500#else
4501#if (DBVER >= 33)
4502 err = lock_stat(self->db_env, &sp);
4503#else
4504 err = lock_stat(self->db_env, &sp, NULL);
4505#endif
4506#endif
4507 MYDB_END_ALLOW_THREADS;
4508 RETURN_IF_ERR();
4509
4510 /* Turn the stat structure into a dictionary */
4511 d = PyDict_New();
4512 if (d == NULL) {
4513 free(sp);
4514 return NULL;
4515 }
4516
4517#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4518
4519#if (DBVER < 41)
4520 MAKE_ENTRY(lastid);
4521#endif
4522 MAKE_ENTRY(nmodes);
4523#if (DBVER >= 32)
4524 MAKE_ENTRY(maxlocks);
4525 MAKE_ENTRY(maxlockers);
4526 MAKE_ENTRY(maxobjects);
4527 MAKE_ENTRY(nlocks);
4528 MAKE_ENTRY(maxnlocks);
4529#endif
4530 MAKE_ENTRY(nlockers);
4531 MAKE_ENTRY(maxnlockers);
4532#if (DBVER >= 32)
4533 MAKE_ENTRY(nobjects);
4534 MAKE_ENTRY(maxnobjects);
4535#endif
4536 MAKE_ENTRY(nrequests);
4537 MAKE_ENTRY(nreleases);
4538#if (DBVER < 44)
4539 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
4540 MAKE_ENTRY(nconflicts);
4541#else
4542 MAKE_ENTRY(lock_nowait);
4543 MAKE_ENTRY(lock_wait);
4544#endif
4545 MAKE_ENTRY(ndeadlocks);
4546 MAKE_ENTRY(regsize);
4547 MAKE_ENTRY(region_wait);
4548 MAKE_ENTRY(region_nowait);
4549
4550#undef MAKE_ENTRY
4551 free(sp);
4552 return d;
4553}
4554
4555
4556static PyObject*
4557DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4558{
4559 int flags=0;
4560 int err;
4561 char **log_list = NULL;
4562 PyObject* list;
4563 PyObject* item = NULL;
4564
4565 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4566 return NULL;
4567
4568 CHECK_ENV_NOT_CLOSED(self);
4569 MYDB_BEGIN_ALLOW_THREADS;
4570#if (DBVER >= 40)
4571 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4572#elif (DBVER == 33)
4573 err = log_archive(self->db_env, &log_list, flags);
4574#else
4575 err = log_archive(self->db_env, &log_list, flags, NULL);
4576#endif
4577 MYDB_END_ALLOW_THREADS;
4578 RETURN_IF_ERR();
4579
4580 list = PyList_New(0);
4581 if (list == NULL) {
4582 if (log_list)
4583 free(log_list);
4584 return NULL;
4585 }
4586
4587 if (log_list) {
4588 char **log_list_start;
4589 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4590 item = PyString_FromString (*log_list);
4591 if (item == NULL) {
4592 Py_DECREF(list);
4593 list = NULL;
4594 break;
4595 }
4596 PyList_Append(list, item);
4597 Py_DECREF(item);
4598 }
4599 free(log_list_start);
4600 }
4601 return list;
4602}
4603
4604
4605static PyObject*
4606DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4607{
4608 int err;
4609 DB_TXN_STAT* sp;
4610 PyObject* d = NULL;
4611 u_int32_t flags=0;
4612
4613 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4614 return NULL;
4615 CHECK_ENV_NOT_CLOSED(self);
4616
4617 MYDB_BEGIN_ALLOW_THREADS;
4618#if (DBVER >= 40)
4619 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4620#elif (DBVER == 33)
4621 err = txn_stat(self->db_env, &sp);
4622#else
4623 err = txn_stat(self->db_env, &sp, NULL);
4624#endif
4625 MYDB_END_ALLOW_THREADS;
4626 RETURN_IF_ERR();
4627
4628 /* Turn the stat structure into a dictionary */
4629 d = PyDict_New();
4630 if (d == NULL) {
4631 free(sp);
4632 return NULL;
4633 }
4634
4635#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4636
4637 MAKE_ENTRY(time_ckp);
4638 MAKE_ENTRY(last_txnid);
4639 MAKE_ENTRY(maxtxns);
4640 MAKE_ENTRY(nactive);
4641 MAKE_ENTRY(maxnactive);
4642 MAKE_ENTRY(nbegins);
4643 MAKE_ENTRY(naborts);
4644 MAKE_ENTRY(ncommits);
4645 MAKE_ENTRY(regsize);
4646 MAKE_ENTRY(region_wait);
4647 MAKE_ENTRY(region_nowait);
4648
4649#undef MAKE_ENTRY
4650 free(sp);
4651 return d;
4652}
4653
4654
4655static PyObject*
4656DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4657{
4658 int flags=0;
4659 int oldValue=0;
4660
4661 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4662 return NULL;
4663 CHECK_ENV_NOT_CLOSED(self);
4664
4665 if (self->moduleFlags.getReturnsNone)
4666 ++oldValue;
4667 if (self->moduleFlags.cursorSetReturnsNone)
4668 ++oldValue;
4669 self->moduleFlags.getReturnsNone = (flags >= 1);
4670 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
4671 return PyInt_FromLong(oldValue);
4672}
4673
4674
4675/* --------------------------------------------------------------------- */
4676/* DBTxn methods */
4677
4678
4679static PyObject*
4680DBTxn_commit(DBTxnObject* self, PyObject* args)
4681{
4682 int flags=0, err;
4683 DB_TXN *txn;
4684
4685 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4686 return NULL;
4687
4688 if (!self->txn) {
4689 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4690 "after txn_commit or txn_abort");
4691 PyErr_SetObject(DBError, t);
4692 Py_DECREF(t);
4693 return NULL;
4694 }
4695 txn = self->txn;
4696 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4697 MYDB_BEGIN_ALLOW_THREADS;
4698#if (DBVER >= 40)
4699 err = txn->commit(txn, flags);
4700#else
4701 err = txn_commit(txn, flags);
4702#endif
4703 MYDB_END_ALLOW_THREADS;
4704 RETURN_IF_ERR();
4705 RETURN_NONE();
4706}
4707
4708static PyObject*
4709DBTxn_prepare(DBTxnObject* self, PyObject* args)
4710{
4711#if (DBVER >= 33)
4712 int err;
4713 char* gid=NULL;
4714 int gid_size=0;
4715
4716 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4717 return NULL;
4718
4719 if (gid_size != DB_XIDDATASIZE) {
4720 PyErr_SetString(PyExc_TypeError,
4721 "gid must be DB_XIDDATASIZE bytes long");
4722 return NULL;
4723 }
4724
4725 if (!self->txn) {
4726 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4727 "after txn_commit or txn_abort");
4728 PyErr_SetObject(DBError, t);
4729 Py_DECREF(t);
4730 return NULL;
4731 }
4732 MYDB_BEGIN_ALLOW_THREADS;
4733#if (DBVER >= 40)
4734 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4735#else
4736 err = txn_prepare(self->txn, (u_int8_t*)gid);
4737#endif
4738 MYDB_END_ALLOW_THREADS;
4739 RETURN_IF_ERR();
4740 RETURN_NONE();
4741#else
4742 int err;
4743
4744 if (!PyArg_ParseTuple(args, ":prepare"))
4745 return NULL;
4746
4747 if (!self->txn) {
4748 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4749 "after txn_commit or txn_abort");
4750 PyErr_SetObject(DBError, t);
4751 Py_DECREF(t);
4752 return NULL;
4753 }
4754 MYDB_BEGIN_ALLOW_THREADS;
4755 err = txn_prepare(self->txn);
4756 MYDB_END_ALLOW_THREADS;
4757 RETURN_IF_ERR();
4758 RETURN_NONE();
4759#endif
4760}
4761
4762
4763static PyObject*
4764DBTxn_abort(DBTxnObject* self, PyObject* args)
4765{
4766 int err;
4767 DB_TXN *txn;
4768
4769 if (!PyArg_ParseTuple(args, ":abort"))
4770 return NULL;
4771
4772 if (!self->txn) {
4773 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4774 "after txn_commit or txn_abort");
4775 PyErr_SetObject(DBError, t);
4776 Py_DECREF(t);
4777 return NULL;
4778 }
4779 txn = self->txn;
4780 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4781 MYDB_BEGIN_ALLOW_THREADS;
4782#if (DBVER >= 40)
4783 err = txn->abort(txn);
4784#else
4785 err = txn_abort(txn);
4786#endif
4787 MYDB_END_ALLOW_THREADS;
4788 RETURN_IF_ERR();
4789 RETURN_NONE();
4790}
4791
4792
4793static PyObject*
4794DBTxn_id(DBTxnObject* self, PyObject* args)
4795{
4796 int id;
4797
4798 if (!PyArg_ParseTuple(args, ":id"))
4799 return NULL;
4800
4801 if (!self->txn) {
4802 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4803 "after txn_commit or txn_abort");
4804 PyErr_SetObject(DBError, t);
4805 Py_DECREF(t);
4806 return NULL;
4807 }
4808 MYDB_BEGIN_ALLOW_THREADS;
4809#if (DBVER >= 40)
4810 id = self->txn->id(self->txn);
4811#else
4812 id = txn_id(self->txn);
4813#endif
4814 MYDB_END_ALLOW_THREADS;
4815 return PyInt_FromLong(id);
4816}
4817
4818#if (DBVER >= 43)
4819/* --------------------------------------------------------------------- */
4820/* DBSequence methods */
4821
4822
4823static PyObject*
4824DBSequence_close(DBSequenceObject* self, PyObject* args)
4825{
4826 int err, flags=0;
4827 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4828 return NULL;
4829 CHECK_SEQUENCE_NOT_CLOSED(self)
4830
4831 MYDB_BEGIN_ALLOW_THREADS
4832 err = self->sequence->close(self->sequence, flags);
4833 self->sequence = NULL;
4834 MYDB_END_ALLOW_THREADS
4835
4836 RETURN_IF_ERR();
4837
4838 RETURN_NONE();
4839}
4840
4841static PyObject*
4842DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4843{
4844 int err, flags = 0;
4845 int delta = 1;
4846 db_seq_t value;
4847 PyObject *txnobj = NULL;
4848 DB_TXN *txn = NULL;
4849 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4850 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4851 return NULL;
4852 CHECK_SEQUENCE_NOT_CLOSED(self)
4853
4854 if (!checkTxnObj(txnobj, &txn))
4855 return NULL;
4856
4857 MYDB_BEGIN_ALLOW_THREADS
4858 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4859 MYDB_END_ALLOW_THREADS
4860
4861 RETURN_IF_ERR();
4862 return PyLong_FromLongLong(value);
4863
4864}
4865
4866static PyObject*
4867DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4868{
4869 if (!PyArg_ParseTuple(args,":get_dbp"))
4870 return NULL;
4871 CHECK_SEQUENCE_NOT_CLOSED(self)
4872 Py_INCREF(self->mydb);
4873 return (PyObject* )self->mydb;
4874}
4875
4876static PyObject*
4877DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4878{
4879 int err;
4880 DBT key;
4881 CHECK_SEQUENCE_NOT_CLOSED(self)
4882 MYDB_BEGIN_ALLOW_THREADS
4883 err = self->sequence->get_key(self->sequence, &key);
4884 MYDB_END_ALLOW_THREADS
4885
4886 RETURN_IF_ERR();
4887
4888 return PyString_FromStringAndSize(key.data, key.size);
4889}
4890
4891static PyObject*
4892DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4893{
4894 int err;
4895 db_seq_t value;
4896 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4897 return NULL;
4898 CHECK_SEQUENCE_NOT_CLOSED(self)
4899
4900 MYDB_BEGIN_ALLOW_THREADS
4901 err = self->sequence->initial_value(self->sequence, value);
4902 MYDB_END_ALLOW_THREADS
4903
4904 RETURN_IF_ERR();
4905
4906 RETURN_NONE();
4907}
4908
4909static PyObject*
4910DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4911{
4912 int err, flags = 0;
4913 PyObject* keyobj;
4914 PyObject *txnobj = NULL;
4915 DB_TXN *txn = NULL;
4916 DBT key;
4917
4918 static char* kwnames[] = {"key", "txn", "flags", NULL };
4919 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4920 return NULL;
4921
4922 if (!checkTxnObj(txnobj, &txn))
4923 return NULL;
4924
4925 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4926 return NULL;
4927
4928 MYDB_BEGIN_ALLOW_THREADS
4929 err = self->sequence->open(self->sequence, txn, &key, flags);
4930 MYDB_END_ALLOW_THREADS
4931
4932 CLEAR_DBT(key);
4933 RETURN_IF_ERR();
4934
4935 RETURN_NONE();
4936}
4937
4938static PyObject*
4939DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4940{
4941 int err, flags = 0;
4942 PyObject *txnobj = NULL;
4943 DB_TXN *txn = NULL;
4944
4945 static char* kwnames[] = {"txn", "flags", NULL };
4946 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4947 return NULL;
4948
4949 if (!checkTxnObj(txnobj, &txn))
4950 return NULL;
4951
4952 CHECK_SEQUENCE_NOT_CLOSED(self)
4953
4954 MYDB_BEGIN_ALLOW_THREADS
4955 err = self->sequence->remove(self->sequence, txn, flags);
4956 MYDB_END_ALLOW_THREADS
4957
4958 RETURN_IF_ERR();
4959 RETURN_NONE();
4960}
4961
4962static PyObject*
4963DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4964{
4965 int err, size;
4966 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4967 return NULL;
4968 CHECK_SEQUENCE_NOT_CLOSED(self)
4969
4970 MYDB_BEGIN_ALLOW_THREADS
4971 err = self->sequence->set_cachesize(self->sequence, size);
4972 MYDB_END_ALLOW_THREADS
4973
4974 RETURN_IF_ERR();
4975 RETURN_NONE();
4976}
4977
4978static PyObject*
4979DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4980{
4981 int err, size;
4982 if (!PyArg_ParseTuple(args,":get_cachesize"))
4983 return NULL;
4984 CHECK_SEQUENCE_NOT_CLOSED(self)
4985
4986 MYDB_BEGIN_ALLOW_THREADS
4987 err = self->sequence->get_cachesize(self->sequence, &size);
4988 MYDB_END_ALLOW_THREADS
4989
4990 RETURN_IF_ERR();
4991 return PyInt_FromLong(size);
4992}
4993
4994static PyObject*
4995DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4996{
4997 int err, flags = 0;
4998 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
4999 return NULL;
5000 CHECK_SEQUENCE_NOT_CLOSED(self)
5001
5002 MYDB_BEGIN_ALLOW_THREADS
5003 err = self->sequence->set_flags(self->sequence, flags);
5004 MYDB_END_ALLOW_THREADS
5005
5006 RETURN_IF_ERR();
5007 RETURN_NONE();
5008
5009}
5010
5011static PyObject*
5012DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5013{
5014 unsigned int flags;
5015 int err;
5016 if (!PyArg_ParseTuple(args,":get_flags"))
5017 return NULL;
5018 CHECK_SEQUENCE_NOT_CLOSED(self)
5019
5020 MYDB_BEGIN_ALLOW_THREADS
5021 err = self->sequence->get_flags(self->sequence, &flags);
5022 MYDB_END_ALLOW_THREADS
5023
5024 RETURN_IF_ERR();
5025 return PyInt_FromLong((int)flags);
5026}
5027
5028static PyObject*
5029DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5030{
5031 int err;
5032 db_seq_t min, max;
5033 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5034 return NULL;
5035 CHECK_SEQUENCE_NOT_CLOSED(self)
5036
5037 MYDB_BEGIN_ALLOW_THREADS
5038 err = self->sequence->set_range(self->sequence, min, max);
5039 MYDB_END_ALLOW_THREADS
5040
5041 RETURN_IF_ERR();
5042 RETURN_NONE();
5043}
5044
5045static PyObject*
5046DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5047{
5048 int err;
5049 db_seq_t min, max;
5050 if (!PyArg_ParseTuple(args,":get_range"))
5051 return NULL;
5052 CHECK_SEQUENCE_NOT_CLOSED(self)
5053
5054 MYDB_BEGIN_ALLOW_THREADS
5055 err = self->sequence->get_range(self->sequence, &min, &max);
5056 MYDB_END_ALLOW_THREADS
5057
5058 RETURN_IF_ERR();
5059 return Py_BuildValue("(LL)", min, max);
5060}
5061
5062static PyObject*
5063DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5064{
5065 int err, flags = 0;
5066 DB_SEQUENCE_STAT* sp = NULL;
5067 PyObject* dict_stat;
5068 static char* kwnames[] = {"flags", NULL };
5069 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5070 return NULL;
5071 CHECK_SEQUENCE_NOT_CLOSED(self);
5072
5073 MYDB_BEGIN_ALLOW_THREADS;
5074 err = self->sequence->stat(self->sequence, &sp, flags);
5075 MYDB_END_ALLOW_THREADS;
5076 RETURN_IF_ERR();
5077
5078 if ((dict_stat = PyDict_New()) == NULL) {
5079 free(sp);
5080 return NULL;
5081 }
5082
5083
5084#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5085#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5086
5087 MAKE_INT_ENTRY(wait);
5088 MAKE_INT_ENTRY(nowait);
5089 MAKE_LONG_LONG_ENTRY(current);
5090 MAKE_LONG_LONG_ENTRY(value);
5091 MAKE_LONG_LONG_ENTRY(last_value);
5092 MAKE_LONG_LONG_ENTRY(min);
5093 MAKE_LONG_LONG_ENTRY(max);
5094 MAKE_INT_ENTRY(cache_size);
5095 MAKE_INT_ENTRY(flags);
5096
5097#undef MAKE_INT_ENTRY
5098#undef MAKE_LONG_LONG_ENTRY
5099
5100 free(sp);
5101 return dict_stat;
5102}
5103#endif
5104
5105
5106/* --------------------------------------------------------------------- */
5107/* Method definition tables and type objects */
5108
5109static PyMethodDef DB_methods[] = {
5110 {"append", (PyCFunction)DB_append, METH_VARARGS},
5111#if (DBVER >= 33)
5112 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5113#endif
5114 {"close", (PyCFunction)DB_close, METH_VARARGS},
5115#if (DBVER >= 32)
5116 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5117 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5118#endif
5119 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5120 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5121 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5122 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
5123#if (DBVER >= 33)
5124 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
5125#endif
5126 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5127 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5128 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5129 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5130 {"join", (PyCFunction)DB_join, METH_VARARGS},
5131 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5132 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5133 {"items", (PyCFunction)DB_items, METH_VARARGS},
5134 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5135 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5136 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5137 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5138 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5139 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
5140#if (DBVER >= 33)
5141 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
5142#endif
5143 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
5144#if (DBVER >= 41)
5145 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5146#endif
5147 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5148 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5149 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5150 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5151 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5152 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5153 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5154 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5155 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5156#if (DBVER >= 32)
5157 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5158#endif
5159 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
5160 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5161#if (DBVER >= 33)
5162 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5163#endif
5164 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5165 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5166 {"values", (PyCFunction)DB_values, METH_VARARGS},
5167 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5168 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5169 {NULL, NULL} /* sentinel */
5170};
5171
5172
5173static PyMappingMethods DB_mapping = {
5174 DB_length, /*mp_length*/
5175 (binaryfunc)DB_subscript, /*mp_subscript*/
5176 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5177};
5178
5179
5180static PyMethodDef DBCursor_methods[] = {
5181 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5182 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5183 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5184 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5185 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5186 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5187 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
5188#if (DBVER >= 33)
5189 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
5190#endif
5191 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5192 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5193 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5194 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5195 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5196 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5197 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5198 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
5199 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
5200 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
5201 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5202 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5203 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5204 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5205 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5206 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5207 {NULL, NULL} /* sentinel */
5208};
5209
5210
5211static PyMethodDef DBEnv_methods[] = {
5212 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5213 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5214 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
5215#if (DBVER >= 41)
5216 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5217 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5218 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5219#endif
5220#if (DBVER >= 40)
5221 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5222#endif
5223 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
5224 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5225 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5226#if (DBVER >= 32)
5227 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5228#endif
5229 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5230 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5231 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
5232#if (DBVER >= 33)
5233 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
5234#endif
5235 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5236 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5237#if (DBVER >= 32)
5238 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5239 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5240 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5241#endif
5242 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5243 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5244 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5245 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5246 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5247 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
5248 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
5249 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5250 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5251 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5252 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5253 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5254 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
5255#if (DBVER >= 40)
5256 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5257#endif
5258#if (DBVER >= 44)
5259 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5260#endif
5261 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5262 {NULL, NULL} /* sentinel */
5263};
5264
5265
5266static PyMethodDef DBTxn_methods[] = {
5267 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5268 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5269 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5270 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5271 {NULL, NULL} /* sentinel */
5272};
5273
5274
5275#if (DBVER >= 43)
5276static PyMethodDef DBSequence_methods[] = {
5277 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5278 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5279 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5280 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5281 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5282 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5283 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5284 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5285 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5286 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5287 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5288 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5289 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5290 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5291 {NULL, NULL} /* sentinel */
5292};
5293#endif
5294
5295
5296static PyObject*
5297DB_getattr(DBObject* self, char *name)
5298{
5299 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5300}
5301
5302
5303static PyObject*
5304DBEnv_getattr(DBEnvObject* self, char *name)
5305{
5306 if (!strcmp(name, "db_home")) {
5307 CHECK_ENV_NOT_CLOSED(self);
5308 if (self->db_env->db_home == NULL) {
5309 RETURN_NONE();
5310 }
5311 return PyString_FromString(self->db_env->db_home);
5312 }
5313
5314 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5315}
5316
5317
5318static PyObject*
5319DBCursor_getattr(DBCursorObject* self, char *name)
5320{
5321 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5322}
5323
5324static PyObject*
5325DBTxn_getattr(DBTxnObject* self, char *name)
5326{
5327 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5328}
5329
5330static PyObject*
5331DBLock_getattr(DBLockObject* self, char *name)
5332{
5333 return NULL;
5334}
5335
5336#if (DBVER >= 43)
5337static PyObject*
5338DBSequence_getattr(DBSequenceObject* self, char *name)
5339{
5340 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5341}
5342#endif
5343
5344statichere PyTypeObject DB_Type = {
5345 PyObject_HEAD_INIT(NULL)
5346 0, /*ob_size*/
5347 "DB", /*tp_name*/
5348 sizeof(DBObject), /*tp_basicsize*/
5349 0, /*tp_itemsize*/
5350 /* methods */
5351 (destructor)DB_dealloc, /*tp_dealloc*/
5352 0, /*tp_print*/
5353 (getattrfunc)DB_getattr, /*tp_getattr*/
5354 0, /*tp_setattr*/
5355 0, /*tp_compare*/
5356 0, /*tp_repr*/
5357 0, /*tp_as_number*/
5358 0, /*tp_as_sequence*/
5359 &DB_mapping,/*tp_as_mapping*/
5360 0, /*tp_hash*/
5361#ifdef HAVE_WEAKREF
5362 0, /* tp_call */
5363 0, /* tp_str */
5364 0, /* tp_getattro */
5365 0, /* tp_setattro */
5366 0, /* tp_as_buffer */
5367 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5368 0, /* tp_doc */
5369 0, /* tp_traverse */
5370 0, /* tp_clear */
5371 0, /* tp_richcompare */
5372 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5373#endif
5374};
5375
5376
5377statichere PyTypeObject DBCursor_Type = {
5378 PyObject_HEAD_INIT(NULL)
5379 0, /*ob_size*/
5380 "DBCursor", /*tp_name*/
5381 sizeof(DBCursorObject), /*tp_basicsize*/
5382 0, /*tp_itemsize*/
5383 /* methods */
5384 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5385 0, /*tp_print*/
5386 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5387 0, /*tp_setattr*/
5388 0, /*tp_compare*/
5389 0, /*tp_repr*/
5390 0, /*tp_as_number*/
5391 0, /*tp_as_sequence*/
5392 0, /*tp_as_mapping*/
5393 0, /*tp_hash*/
5394#ifdef HAVE_WEAKREF
5395 0, /* tp_call */
5396 0, /* tp_str */
5397 0, /* tp_getattro */
5398 0, /* tp_setattro */
5399 0, /* tp_as_buffer */
5400 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5401 0, /* tp_doc */
5402 0, /* tp_traverse */
5403 0, /* tp_clear */
5404 0, /* tp_richcompare */
5405 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5406#endif
5407};
5408
5409
5410statichere PyTypeObject DBEnv_Type = {
5411 PyObject_HEAD_INIT(NULL)
5412 0, /*ob_size*/
5413 "DBEnv", /*tp_name*/
5414 sizeof(DBEnvObject), /*tp_basicsize*/
5415 0, /*tp_itemsize*/
5416 /* methods */
5417 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5418 0, /*tp_print*/
5419 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5420 0, /*tp_setattr*/
5421 0, /*tp_compare*/
5422 0, /*tp_repr*/
5423 0, /*tp_as_number*/
5424 0, /*tp_as_sequence*/
5425 0, /*tp_as_mapping*/
5426 0, /*tp_hash*/
5427#ifdef HAVE_WEAKREF
5428 0, /* tp_call */
5429 0, /* tp_str */
5430 0, /* tp_getattro */
5431 0, /* tp_setattro */
5432 0, /* tp_as_buffer */
5433 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5434 0, /* tp_doc */
5435 0, /* tp_traverse */
5436 0, /* tp_clear */
5437 0, /* tp_richcompare */
5438 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5439#endif
5440};
5441
5442statichere PyTypeObject DBTxn_Type = {
5443 PyObject_HEAD_INIT(NULL)
5444 0, /*ob_size*/
5445 "DBTxn", /*tp_name*/
5446 sizeof(DBTxnObject), /*tp_basicsize*/
5447 0, /*tp_itemsize*/
5448 /* methods */
5449 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5450 0, /*tp_print*/
5451 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5452 0, /*tp_setattr*/
5453 0, /*tp_compare*/
5454 0, /*tp_repr*/
5455 0, /*tp_as_number*/
5456 0, /*tp_as_sequence*/
5457 0, /*tp_as_mapping*/
5458 0, /*tp_hash*/
5459#ifdef HAVE_WEAKREF
5460 0, /* tp_call */
5461 0, /* tp_str */
5462 0, /* tp_getattro */
5463 0, /* tp_setattro */
5464 0, /* tp_as_buffer */
5465 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5466 0, /* tp_doc */
5467 0, /* tp_traverse */
5468 0, /* tp_clear */
5469 0, /* tp_richcompare */
5470 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5471#endif
5472};
5473
5474
5475statichere PyTypeObject DBLock_Type = {
5476 PyObject_HEAD_INIT(NULL)
5477 0, /*ob_size*/
5478 "DBLock", /*tp_name*/
5479 sizeof(DBLockObject), /*tp_basicsize*/
5480 0, /*tp_itemsize*/
5481 /* methods */
5482 (destructor)DBLock_dealloc, /*tp_dealloc*/
5483 0, /*tp_print*/
5484 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5485 0, /*tp_setattr*/
5486 0, /*tp_compare*/
5487 0, /*tp_repr*/
5488 0, /*tp_as_number*/
5489 0, /*tp_as_sequence*/
5490 0, /*tp_as_mapping*/
5491 0, /*tp_hash*/
5492#ifdef HAVE_WEAKREF
5493 0, /* tp_call */
5494 0, /* tp_str */
5495 0, /* tp_getattro */
5496 0, /* tp_setattro */
5497 0, /* tp_as_buffer */
5498 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5499 0, /* tp_doc */
5500 0, /* tp_traverse */
5501 0, /* tp_clear */
5502 0, /* tp_richcompare */
5503 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5504#endif
5505};
5506
5507#if (DBVER >= 43)
5508statichere PyTypeObject DBSequence_Type = {
5509 PyObject_HEAD_INIT(NULL)
5510 0, /*ob_size*/
5511 "DBSequence", /*tp_name*/
5512 sizeof(DBSequenceObject), /*tp_basicsize*/
5513 0, /*tp_itemsize*/
5514 /* methods */
5515 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5516 0, /*tp_print*/
5517 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5518 0, /*tp_setattr*/
5519 0, /*tp_compare*/
5520 0, /*tp_repr*/
5521 0, /*tp_as_number*/
5522 0, /*tp_as_sequence*/
5523 0, /*tp_as_mapping*/
5524 0, /*tp_hash*/
5525#ifdef HAVE_WEAKREF
5526 0, /* tp_call */
5527 0, /* tp_str */
5528 0, /* tp_getattro */
5529 0, /* tp_setattro */
5530 0, /* tp_as_buffer */
5531 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5532 0, /* tp_doc */
5533 0, /* tp_traverse */
5534 0, /* tp_clear */
5535 0, /* tp_richcompare */
5536 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5537#endif
5538};
5539#endif
5540
5541/* --------------------------------------------------------------------- */
5542/* Module-level functions */
5543
5544static PyObject*
5545DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5546{
5547 PyObject* dbenvobj = NULL;
5548 int flags = 0;
5549 static char* kwnames[] = { "dbEnv", "flags", NULL};
5550
5551 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5552 &dbenvobj, &flags))
5553 return NULL;
5554 if (dbenvobj == Py_None)
5555 dbenvobj = NULL;
5556 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5557 makeTypeError("DBEnv", dbenvobj);
5558 return NULL;
5559 }
5560
5561 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5562}
5563
5564
5565static PyObject*
5566DBEnv_construct(PyObject* self, PyObject* args)
5567{
5568 int flags = 0;
5569 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5570 return (PyObject* )newDBEnvObject(flags);
5571}
5572
5573#if (DBVER >= 43)
5574static PyObject*
5575DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5576{
5577 PyObject* dbobj;
5578 int flags = 0;
5579 static char* kwnames[] = { "db", "flags", NULL};
5580
5581 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5582 return NULL;
5583 if (!DBObject_Check(dbobj)) {
5584 makeTypeError("DB", dbobj);
5585 return NULL;
5586 }
5587 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5588}
5589#endif
5590
5591static char bsddb_version_doc[] =
5592"Returns a tuple of major, minor, and patch release numbers of the\n\
5593underlying DB library.";
5594
5595static PyObject*
5596bsddb_version(PyObject* self, PyObject* args)
5597{
5598 int major, minor, patch;
5599
5600 if (!PyArg_ParseTuple(args, ":version"))
5601 return NULL;
5602 db_version(&major, &minor, &patch);
5603 return Py_BuildValue("(iii)", major, minor, patch);
5604}
5605
5606
5607/* List of functions defined in the module */
5608
5609static PyMethodDef bsddb_methods[] = {
5610 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5611 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5612#if (DBVER >= 43)
5613 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5614#endif
5615 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
5616 {NULL, NULL} /* sentinel */
5617};
5618
5619
5620/* --------------------------------------------------------------------- */
5621/* Module initialization */
5622
5623
5624/* Convenience routine to export an integer value.
5625 * Errors are silently ignored, for better or for worse...
5626 */
5627#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5628
5629#define MODULE_NAME_MAX_LEN 11
5630static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
5631
5632DL_EXPORT(void) init_bsddb(void)
5633{
5634 PyObject* m;
5635 PyObject* d;
5636 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5637 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5638 PyObject* cvsid_s = PyString_FromString( rcs_id );
5639
5640 /* Initialize the type of the new type objects here; doing it here
5641 is required for portability to Windows without requiring C++. */
5642 DB_Type.ob_type = &PyType_Type;
5643 DBCursor_Type.ob_type = &PyType_Type;
5644 DBEnv_Type.ob_type = &PyType_Type;
5645 DBTxn_Type.ob_type = &PyType_Type;
5646 DBLock_Type.ob_type = &PyType_Type;
5647#if (DBVER >= 43)
5648 DBSequence_Type.ob_type = &PyType_Type;
5649#endif
5650
5651
5652#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
5653 /* Save the current interpreter, so callbacks can do the right thing. */
5654 _db_interpreterState = PyThreadState_GET()->interp;
5655#endif
5656
5657 /* Create the module and add the functions */
5658 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
5659 if (m == NULL)
5660 return;
5661
5662 /* Add some symbolic constants to the module */
5663 d = PyModule_GetDict(m);
5664 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5665 PyDict_SetItemString(d, "cvsid", cvsid_s);
5666 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5667 Py_DECREF(pybsddb_version_s);
5668 pybsddb_version_s = NULL;
5669 Py_DECREF(cvsid_s);
5670 cvsid_s = NULL;
5671 Py_DECREF(db_version_s);
5672 db_version_s = NULL;
5673
5674 ADD_INT(d, DB_VERSION_MAJOR);
5675 ADD_INT(d, DB_VERSION_MINOR);
5676 ADD_INT(d, DB_VERSION_PATCH);
5677
5678 ADD_INT(d, DB_MAX_PAGES);
5679 ADD_INT(d, DB_MAX_RECORDS);
5680
5681#if (DBVER >= 42)
5682 ADD_INT(d, DB_RPCCLIENT);
5683#else
5684 ADD_INT(d, DB_CLIENT);
5685 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5686 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5687#endif
5688 ADD_INT(d, DB_XA_CREATE);
5689
5690 ADD_INT(d, DB_CREATE);
5691 ADD_INT(d, DB_NOMMAP);
5692 ADD_INT(d, DB_THREAD);
5693
5694 ADD_INT(d, DB_FORCE);
5695 ADD_INT(d, DB_INIT_CDB);
5696 ADD_INT(d, DB_INIT_LOCK);
5697 ADD_INT(d, DB_INIT_LOG);
5698 ADD_INT(d, DB_INIT_MPOOL);
5699 ADD_INT(d, DB_INIT_TXN);
5700#if (DBVER >= 32)
5701 ADD_INT(d, DB_JOINENV);
5702#endif
5703
5704 ADD_INT(d, DB_RECOVER);
5705 ADD_INT(d, DB_RECOVER_FATAL);
5706 ADD_INT(d, DB_TXN_NOSYNC);
5707 ADD_INT(d, DB_USE_ENVIRON);
5708 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5709
5710 ADD_INT(d, DB_LOCKDOWN);
5711 ADD_INT(d, DB_PRIVATE);
5712 ADD_INT(d, DB_SYSTEM_MEM);
5713
5714 ADD_INT(d, DB_TXN_SYNC);
5715 ADD_INT(d, DB_TXN_NOWAIT);
5716
5717 ADD_INT(d, DB_EXCL);
5718 ADD_INT(d, DB_FCNTL_LOCKING);
5719 ADD_INT(d, DB_ODDFILESIZE);
5720 ADD_INT(d, DB_RDWRMASTER);
5721 ADD_INT(d, DB_RDONLY);
5722 ADD_INT(d, DB_TRUNCATE);
5723#if (DBVER >= 32)
5724 ADD_INT(d, DB_EXTENT);
5725 ADD_INT(d, DB_CDB_ALLDB);
5726 ADD_INT(d, DB_VERIFY);
5727#endif
5728 ADD_INT(d, DB_UPGRADE);
5729
5730 ADD_INT(d, DB_AGGRESSIVE);
5731 ADD_INT(d, DB_NOORDERCHK);
5732 ADD_INT(d, DB_ORDERCHKONLY);
5733 ADD_INT(d, DB_PR_PAGE);
5734#if ! (DBVER >= 33)
5735 ADD_INT(d, DB_VRFY_FLAGMASK);
5736 ADD_INT(d, DB_PR_HEADERS);
5737#endif
5738 ADD_INT(d, DB_PR_RECOVERYTEST);
5739 ADD_INT(d, DB_SALVAGE);
5740
5741 ADD_INT(d, DB_LOCK_NORUN);
5742 ADD_INT(d, DB_LOCK_DEFAULT);
5743 ADD_INT(d, DB_LOCK_OLDEST);
5744 ADD_INT(d, DB_LOCK_RANDOM);
5745 ADD_INT(d, DB_LOCK_YOUNGEST);
5746#if (DBVER >= 33)
5747 ADD_INT(d, DB_LOCK_MAXLOCKS);
5748 ADD_INT(d, DB_LOCK_MINLOCKS);
5749 ADD_INT(d, DB_LOCK_MINWRITE);
5750#endif
5751
5752
5753#if (DBVER >= 33)
5754 /* docs say to use zero instead */
5755 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
5756#else
5757 ADD_INT(d, DB_LOCK_CONFLICT);
5758#endif
5759
5760 ADD_INT(d, DB_LOCK_DUMP);
5761 ADD_INT(d, DB_LOCK_GET);
5762 ADD_INT(d, DB_LOCK_INHERIT);
5763 ADD_INT(d, DB_LOCK_PUT);
5764 ADD_INT(d, DB_LOCK_PUT_ALL);
5765 ADD_INT(d, DB_LOCK_PUT_OBJ);
5766
5767 ADD_INT(d, DB_LOCK_NG);
5768 ADD_INT(d, DB_LOCK_READ);
5769 ADD_INT(d, DB_LOCK_WRITE);
5770 ADD_INT(d, DB_LOCK_NOWAIT);
5771#if (DBVER >= 32)
5772 ADD_INT(d, DB_LOCK_WAIT);
5773#endif
5774 ADD_INT(d, DB_LOCK_IWRITE);
5775 ADD_INT(d, DB_LOCK_IREAD);
5776 ADD_INT(d, DB_LOCK_IWR);
5777#if (DBVER >= 33)
5778#if (DBVER < 44)
5779 ADD_INT(d, DB_LOCK_DIRTY);
5780#else
5781 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5782#endif
5783 ADD_INT(d, DB_LOCK_WWRITE);
5784#endif
5785
5786 ADD_INT(d, DB_LOCK_RECORD);
5787 ADD_INT(d, DB_LOCK_UPGRADE);
5788#if (DBVER >= 32)
5789 ADD_INT(d, DB_LOCK_SWITCH);
5790#endif
5791#if (DBVER >= 33)
5792 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5793#endif
5794
5795 ADD_INT(d, DB_LOCK_NOWAIT);
5796 ADD_INT(d, DB_LOCK_RECORD);
5797 ADD_INT(d, DB_LOCK_UPGRADE);
5798
5799#if (DBVER >= 33)
5800 ADD_INT(d, DB_LSTAT_ABORTED);
5801#if (DBVER < 43)
5802 ADD_INT(d, DB_LSTAT_ERR);
5803#endif
5804 ADD_INT(d, DB_LSTAT_FREE);
5805 ADD_INT(d, DB_LSTAT_HELD);
5806#if (DBVER == 33)
5807 ADD_INT(d, DB_LSTAT_NOGRANT);
5808#endif
5809 ADD_INT(d, DB_LSTAT_PENDING);
5810 ADD_INT(d, DB_LSTAT_WAITING);
5811#endif
5812
5813 ADD_INT(d, DB_ARCH_ABS);
5814 ADD_INT(d, DB_ARCH_DATA);
5815 ADD_INT(d, DB_ARCH_LOG);
5816#if (DBVER >= 42)
5817 ADD_INT(d, DB_ARCH_REMOVE);
5818#endif
5819
5820 ADD_INT(d, DB_BTREE);
5821 ADD_INT(d, DB_HASH);
5822 ADD_INT(d, DB_RECNO);
5823 ADD_INT(d, DB_QUEUE);
5824 ADD_INT(d, DB_UNKNOWN);
5825
5826 ADD_INT(d, DB_DUP);
5827 ADD_INT(d, DB_DUPSORT);
5828 ADD_INT(d, DB_RECNUM);
5829 ADD_INT(d, DB_RENUMBER);
5830 ADD_INT(d, DB_REVSPLITOFF);
5831 ADD_INT(d, DB_SNAPSHOT);
5832
5833 ADD_INT(d, DB_JOIN_NOSORT);
5834
5835 ADD_INT(d, DB_AFTER);
5836 ADD_INT(d, DB_APPEND);
5837 ADD_INT(d, DB_BEFORE);
5838 ADD_INT(d, DB_CACHED_COUNTS);
5839#if (DBVER >= 41)
5840 _addIntToDict(d, "DB_CHECKPOINT", 0);
5841#else
5842 ADD_INT(d, DB_CHECKPOINT);
5843 ADD_INT(d, DB_CURLSN);
5844#endif
5845#if ((DBVER >= 33) && (DBVER <= 41))
5846 ADD_INT(d, DB_COMMIT);
5847#endif
5848 ADD_INT(d, DB_CONSUME);
5849#if (DBVER >= 32)
5850 ADD_INT(d, DB_CONSUME_WAIT);
5851#endif
5852 ADD_INT(d, DB_CURRENT);
5853#if (DBVER >= 33)
5854 ADD_INT(d, DB_FAST_STAT);
5855#endif
5856 ADD_INT(d, DB_FIRST);
5857 ADD_INT(d, DB_FLUSH);
5858 ADD_INT(d, DB_GET_BOTH);
5859 ADD_INT(d, DB_GET_RECNO);
5860 ADD_INT(d, DB_JOIN_ITEM);
5861 ADD_INT(d, DB_KEYFIRST);
5862 ADD_INT(d, DB_KEYLAST);
5863 ADD_INT(d, DB_LAST);
5864 ADD_INT(d, DB_NEXT);
5865 ADD_INT(d, DB_NEXT_DUP);
5866 ADD_INT(d, DB_NEXT_NODUP);
5867 ADD_INT(d, DB_NODUPDATA);
5868 ADD_INT(d, DB_NOOVERWRITE);
5869 ADD_INT(d, DB_NOSYNC);
5870 ADD_INT(d, DB_POSITION);
5871 ADD_INT(d, DB_PREV);
5872 ADD_INT(d, DB_PREV_NODUP);
5873 ADD_INT(d, DB_RECORDCOUNT);
5874 ADD_INT(d, DB_SET);
5875 ADD_INT(d, DB_SET_RANGE);
5876 ADD_INT(d, DB_SET_RECNO);
5877 ADD_INT(d, DB_WRITECURSOR);
5878
5879 ADD_INT(d, DB_OPFLAGS_MASK);
5880 ADD_INT(d, DB_RMW);
5881#if (DBVER >= 33)
5882 ADD_INT(d, DB_DIRTY_READ);
5883 ADD_INT(d, DB_MULTIPLE);
5884 ADD_INT(d, DB_MULTIPLE_KEY);
5885#endif
5886
5887#if (DBVER >= 44)
5888 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5889 ADD_INT(d, DB_READ_COMMITTED);
5890#endif
5891
5892#if (DBVER >= 33)
5893 ADD_INT(d, DB_DONOTINDEX);
5894#endif
5895
5896#if (DBVER >= 41)
5897 _addIntToDict(d, "DB_INCOMPLETE", 0);
5898#else
5899 ADD_INT(d, DB_INCOMPLETE);
5900#endif
5901 ADD_INT(d, DB_KEYEMPTY);
5902 ADD_INT(d, DB_KEYEXIST);
5903 ADD_INT(d, DB_LOCK_DEADLOCK);
5904 ADD_INT(d, DB_LOCK_NOTGRANTED);
5905 ADD_INT(d, DB_NOSERVER);
5906 ADD_INT(d, DB_NOSERVER_HOME);
5907 ADD_INT(d, DB_NOSERVER_ID);
5908 ADD_INT(d, DB_NOTFOUND);
5909 ADD_INT(d, DB_OLD_VERSION);
5910 ADD_INT(d, DB_RUNRECOVERY);
5911 ADD_INT(d, DB_VERIFY_BAD);
5912#if (DBVER >= 33)
5913 ADD_INT(d, DB_PAGE_NOTFOUND);
5914 ADD_INT(d, DB_SECONDARY_BAD);
5915#endif
5916#if (DBVER >= 40)
5917 ADD_INT(d, DB_STAT_CLEAR);
5918 ADD_INT(d, DB_REGION_INIT);
5919 ADD_INT(d, DB_NOLOCKING);
5920 ADD_INT(d, DB_YIELDCPU);
5921 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5922 ADD_INT(d, DB_NOPANIC);
5923#endif
5924
5925#if (DBVER >= 42)
5926 ADD_INT(d, DB_TIME_NOTGRANTED);
5927 ADD_INT(d, DB_TXN_NOT_DURABLE);
5928 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5929 ADD_INT(d, DB_LOG_AUTOREMOVE);
5930 ADD_INT(d, DB_DIRECT_LOG);
5931 ADD_INT(d, DB_DIRECT_DB);
5932 ADD_INT(d, DB_INIT_REP);
5933 ADD_INT(d, DB_ENCRYPT);
5934 ADD_INT(d, DB_CHKSUM);
5935#endif
5936
5937#if (DBVER >= 43)
5938 ADD_INT(d, DB_LOG_INMEMORY);
5939 ADD_INT(d, DB_BUFFER_SMALL);
5940 ADD_INT(d, DB_SEQ_DEC);
5941 ADD_INT(d, DB_SEQ_INC);
5942 ADD_INT(d, DB_SEQ_WRAP);
5943#endif
5944
5945#if (DBVER >= 41)
5946 ADD_INT(d, DB_ENCRYPT_AES);
5947 ADD_INT(d, DB_AUTO_COMMIT);
5948#else
5949 /* allow berkeleydb 4.1 aware apps to run on older versions */
5950 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5951#endif
5952
5953 ADD_INT(d, EINVAL);
5954 ADD_INT(d, EACCES);
5955 ADD_INT(d, ENOSPC);
5956 ADD_INT(d, ENOMEM);
5957 ADD_INT(d, EAGAIN);
5958 ADD_INT(d, EBUSY);
5959 ADD_INT(d, EEXIST);
5960 ADD_INT(d, ENOENT);
5961 ADD_INT(d, EPERM);
5962
5963#if (DBVER >= 40)
5964 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5965 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5966#endif
5967
5968 /* The exception name must be correct for pickled exception *
5969 * objects to unpickle properly. */
5970#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5971#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5972#else
5973#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5974#endif
5975
5976 /* All the rest of the exceptions derive only from DBError */
5977#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5978 PyDict_SetItemString(d, #name, name)
5979
5980 /* The base exception class is DBError */
5981 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5982 MAKE_EX(DBError);
5983
5984 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5985 * from both DBError and KeyError, since the API only supports
5986 * using one base class. */
5987 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5988 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5989 "class DBKeyEmptyError(DBError, KeyError): pass",
5990 Py_file_input, d, d);
5991 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5992 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
5993 PyDict_DelItemString(d, "KeyError");
5994
5995
5996#if !INCOMPLETE_IS_WARNING
5997 MAKE_EX(DBIncompleteError);
5998#endif
5999 MAKE_EX(DBCursorClosedError);
6000 MAKE_EX(DBKeyEmptyError);
6001 MAKE_EX(DBKeyExistError);
6002 MAKE_EX(DBLockDeadlockError);
6003 MAKE_EX(DBLockNotGrantedError);
6004 MAKE_EX(DBOldVersionError);
6005 MAKE_EX(DBRunRecoveryError);
6006 MAKE_EX(DBVerifyBadError);
6007 MAKE_EX(DBNoServerError);
6008 MAKE_EX(DBNoServerHomeError);
6009 MAKE_EX(DBNoServerIDError);
6010#if (DBVER >= 33)
6011 MAKE_EX(DBPageNotFoundError);
6012 MAKE_EX(DBSecondaryBadError);
6013#endif
6014
6015 MAKE_EX(DBInvalidArgError);
6016 MAKE_EX(DBAccessError);
6017 MAKE_EX(DBNoSpaceError);
6018 MAKE_EX(DBNoMemoryError);
6019 MAKE_EX(DBAgainError);
6020 MAKE_EX(DBBusyError);
6021 MAKE_EX(DBFileExistsError);
6022 MAKE_EX(DBNoSuchFileError);
6023 MAKE_EX(DBPermissionsError);
6024
6025#undef MAKE_EX
6026
6027 /* Check for errors */
6028 if (PyErr_Occurred()) {
6029 PyErr_Print();
6030 Py_FatalError("can't initialize module _bsddb");
6031 }
6032}
6033
6034/* allow this module to be named _pybsddb so that it can be installed
6035 * and imported on top of python >= 2.3 that includes its own older
6036 * copy of the library named _bsddb without importing the old version. */
6037DL_EXPORT(void) init_pybsddb(void)
6038{
6039 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6040 init_bsddb();
6041}
Note: See TracBrowser for help on using the repository browser.