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