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