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