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