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