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