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