blob: dcbcdb37cee9dbe5b3a9c76d0a61f8d7f817273a [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
39 * to compile with BerkeleyDB versions 3.2 through 4.1.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
45 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
50 *
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
52 *
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000054 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
56 *
57 * http://pybsddb.sf.net
58 *
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
61 *
62 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000063 *
64 * This module contains 5 types:
65 *
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
71 *
72 */
73
74/* --------------------------------------------------------------------- */
75
76/*
77 * Portions of this module, associated unit tests and build scripts are the
78 * result of a contract with The Written Word (http://thewrittenword.com/)
79 * Many thanks go out to them for causing me to raise the bar on quality and
80 * functionality, resulting in a better bsddb3 package for all of us to use.
81 *
82 * --Robin
83 */
84
85/* --------------------------------------------------------------------- */
86
87#include <Python.h>
88#include <db.h>
89
90/* --------------------------------------------------------------------- */
91/* Various macro definitions */
92
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000093/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
94#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
95
Gregory P. Smith455d46f2003-07-09 04:45:59 +000096#define PY_BSDDB_VERSION "4.1.6"
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);
2170 RETURN_IF_ERR();
2171 RETURN_NONE();
2172}
2173
2174
2175static PyObject*
2176DB_set_get_returns_none(DBObject* self, PyObject* args)
2177{
2178 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002179 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002180
2181 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2182 return NULL;
2183 CHECK_DB_NOT_CLOSED(self);
2184
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002185 if (self->moduleFlags.getReturnsNone)
2186 ++oldValue;
2187 if (self->moduleFlags.cursorSetReturnsNone)
2188 ++oldValue;
2189 self->moduleFlags.getReturnsNone = (flags >= 1);
2190 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002191 return PyInt_FromLong(oldValue);
2192}
2193
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002194#if (DBVER >= 41)
2195static PyObject*
2196DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2197{
2198 int err;
2199 u_int32_t flags=0;
2200 char *passwd = NULL;
2201 char* kwnames[] = { "passwd", "flags", NULL };
2202
2203 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2204 &passwd, &flags)) {
2205 return NULL;
2206 }
2207
2208 MYDB_BEGIN_ALLOW_THREADS;
2209 err = self->db->set_encrypt(self->db, passwd, flags);
2210 MYDB_END_ALLOW_THREADS;
2211
2212 RETURN_IF_ERR();
2213 RETURN_NONE();
2214}
2215#endif /* DBVER >= 41 */
2216
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002217
2218/*-------------------------------------------------------------- */
2219/* Mapping and Dictionary-like access routines */
2220
2221int DB_length(DBObject* self)
2222{
2223 int err;
2224 long size = 0;
2225 int flags = 0;
2226 void* sp;
2227
2228 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002229 PyErr_SetObject(DBError,
2230 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002231 return -1;
2232 }
2233
2234 if (self->haveStat) { /* Has the stat function been called recently? If
2235 so, we can use the cached value. */
2236 flags = DB_CACHED_COUNTS;
2237 }
2238
2239 MYDB_BEGIN_ALLOW_THREADS;
2240#if (DBVER >= 33)
2241 err = self->db->stat(self->db, &sp, flags);
2242#else
2243 err = self->db->stat(self->db, &sp, NULL, flags);
2244#endif
2245 MYDB_END_ALLOW_THREADS;
2246
2247 if (err)
2248 return -1;
2249
2250 self->haveStat = 1;
2251
2252 /* All the stat structures have matching fields upto the ndata field,
2253 so we can use any of them for the type cast */
2254 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2255 free(sp);
2256 return size;
2257}
2258
2259
2260PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2261{
2262 int err;
2263 PyObject* retval;
2264 DBT key;
2265 DBT data;
2266
2267 CHECK_DB_NOT_CLOSED(self);
2268 if (!make_key_dbt(self, keyobj, &key, NULL))
2269 return NULL;
2270
2271 CLEAR_DBT(data);
2272 if (CHECK_DBFLAG(self, DB_THREAD)) {
2273 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2274 data.flags = DB_DBT_MALLOC;
2275 }
2276 MYDB_BEGIN_ALLOW_THREADS;
2277 err = self->db->get(self->db, NULL, &key, &data, 0);
2278 MYDB_END_ALLOW_THREADS;
2279 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2280 PyErr_SetObject(PyExc_KeyError, keyobj);
2281 retval = NULL;
2282 }
2283 else if (makeDBError(err)) {
2284 retval = NULL;
2285 }
2286 else {
2287 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2288 FREE_DBT(data);
2289 }
2290
2291 FREE_DBT(key);
2292 return retval;
2293}
2294
2295
2296static int
2297DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2298{
2299 DBT key, data;
2300 int retval;
2301 int flags = 0;
2302
2303 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002304 PyErr_SetObject(DBError,
2305 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002306 return -1;
2307 }
2308
2309 if (!make_key_dbt(self, keyobj, &key, NULL))
2310 return -1;
2311
2312 if (dataobj != NULL) {
2313 if (!make_dbt(dataobj, &data))
2314 retval = -1;
2315 else {
2316 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002317 /* dictionaries shouldn't have duplicate keys */
2318 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002319 retval = _DB_put(self, NULL, &key, &data, flags);
2320
2321 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002322 /* try deleting any old record that matches and then PUT it
2323 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002324 _DB_delete(self, NULL, &key, 0);
2325 PyErr_Clear();
2326 retval = _DB_put(self, NULL, &key, &data, flags);
2327 }
2328 }
2329 }
2330 else {
2331 /* dataobj == NULL, so delete the key */
2332 retval = _DB_delete(self, NULL, &key, 0);
2333 }
2334 FREE_DBT(key);
2335 return retval;
2336}
2337
2338
2339static PyObject*
2340DB_has_key(DBObject* self, PyObject* args)
2341{
2342 int err;
2343 PyObject* keyobj;
2344 DBT key, data;
2345 PyObject* txnobj = NULL;
2346 DB_TXN *txn = NULL;
2347
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002348 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002349 return NULL;
2350 CHECK_DB_NOT_CLOSED(self);
2351 if (!make_key_dbt(self, keyobj, &key, NULL))
2352 return NULL;
2353 if (!checkTxnObj(txnobj, &txn))
2354 return NULL;
2355
2356 /* This causes ENOMEM to be returned when the db has the key because
2357 it has a record but can't allocate a buffer for the data. This saves
2358 having to deal with data we won't be using.
2359 */
2360 CLEAR_DBT(data);
2361 data.flags = DB_DBT_USERMEM;
2362
2363 MYDB_BEGIN_ALLOW_THREADS;
2364 err = self->db->get(self->db, NULL, &key, &data, 0);
2365 MYDB_END_ALLOW_THREADS;
2366 FREE_DBT(key);
2367 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2368}
2369
2370
2371#define _KEYS_LIST 1
2372#define _VALUES_LIST 2
2373#define _ITEMS_LIST 3
2374
2375static PyObject*
2376_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2377{
2378 int err, dbtype;
2379 DBT key;
2380 DBT data;
2381 DBC *cursor;
2382 PyObject* list;
2383 PyObject* item = NULL;
2384
2385 CHECK_DB_NOT_CLOSED(self);
2386 CLEAR_DBT(key);
2387 CLEAR_DBT(data);
2388
2389 dbtype = _DB_get_type(self);
2390 if (dbtype == -1)
2391 return NULL;
2392
2393 list = PyList_New(0);
2394 if (list == NULL) {
2395 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2396 return NULL;
2397 }
2398
2399 /* get a cursor */
2400 MYDB_BEGIN_ALLOW_THREADS;
2401 err = self->db->cursor(self->db, NULL, &cursor, 0);
2402 MYDB_END_ALLOW_THREADS;
2403 RETURN_IF_ERR();
2404
2405 if (CHECK_DBFLAG(self, DB_THREAD)) {
2406 key.flags = DB_DBT_REALLOC;
2407 data.flags = DB_DBT_REALLOC;
2408 }
2409
2410 while (1) { /* use the cursor to traverse the DB, collecting items */
2411 MYDB_BEGIN_ALLOW_THREADS;
2412 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2413 MYDB_END_ALLOW_THREADS;
2414
2415 if (err) {
2416 /* for any error, break out of the loop */
2417 break;
2418 }
2419
2420 switch (type) {
2421 case _KEYS_LIST:
2422 switch(dbtype) {
2423 case DB_BTREE:
2424 case DB_HASH:
2425 default:
2426 item = PyString_FromStringAndSize((char*)key.data, key.size);
2427 break;
2428 case DB_RECNO:
2429 case DB_QUEUE:
2430 item = PyInt_FromLong(*((db_recno_t*)key.data));
2431 break;
2432 }
2433 break;
2434
2435 case _VALUES_LIST:
2436 item = PyString_FromStringAndSize((char*)data.data, data.size);
2437 break;
2438
2439 case _ITEMS_LIST:
2440 switch(dbtype) {
2441 case DB_BTREE:
2442 case DB_HASH:
2443 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002444 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2445 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002446 break;
2447 case DB_RECNO:
2448 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002449 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2450 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002451 break;
2452 }
2453 break;
2454 }
2455 if (item == NULL) {
2456 Py_DECREF(list);
2457 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2458 list = NULL;
2459 goto done;
2460 }
2461 PyList_Append(list, item);
2462 Py_DECREF(item);
2463 }
2464
2465 /* DB_NOTFOUND is okay, it just means we got to the end */
2466 if (err != DB_NOTFOUND && makeDBError(err)) {
2467 Py_DECREF(list);
2468 list = NULL;
2469 }
2470
2471 done:
2472 FREE_DBT(key);
2473 FREE_DBT(data);
2474 MYDB_BEGIN_ALLOW_THREADS;
2475 cursor->c_close(cursor);
2476 MYDB_END_ALLOW_THREADS;
2477 return list;
2478}
2479
2480
2481static PyObject*
2482DB_keys(DBObject* self, PyObject* args)
2483{
2484 PyObject* txnobj = NULL;
2485 DB_TXN *txn = NULL;
2486
2487 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2488 return NULL;
2489 if (!checkTxnObj(txnobj, &txn))
2490 return NULL;
2491 return _DB_make_list(self, txn, _KEYS_LIST);
2492}
2493
2494
2495static PyObject*
2496DB_items(DBObject* self, PyObject* args)
2497{
2498 PyObject* txnobj = NULL;
2499 DB_TXN *txn = NULL;
2500
2501 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2502 return NULL;
2503 if (!checkTxnObj(txnobj, &txn))
2504 return NULL;
2505 return _DB_make_list(self, txn, _ITEMS_LIST);
2506}
2507
2508
2509static PyObject*
2510DB_values(DBObject* self, PyObject* args)
2511{
2512 PyObject* txnobj = NULL;
2513 DB_TXN *txn = NULL;
2514
2515 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2516 return NULL;
2517 if (!checkTxnObj(txnobj, &txn))
2518 return NULL;
2519 return _DB_make_list(self, txn, _VALUES_LIST);
2520}
2521
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002522/* --------------------------------------------------------------------- */
2523/* DBCursor methods */
2524
2525
2526static PyObject*
2527DBC_close(DBCursorObject* self, PyObject* args)
2528{
2529 int err = 0;
2530
2531 if (!PyArg_ParseTuple(args, ":close"))
2532 return NULL;
2533
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002534 if (self->dbc != NULL) {
2535 MYDB_BEGIN_ALLOW_THREADS;
2536 err = self->dbc->c_close(self->dbc);
2537 self->dbc = NULL;
2538 MYDB_END_ALLOW_THREADS;
2539 }
2540 RETURN_IF_ERR();
2541 RETURN_NONE();
2542}
2543
2544
2545static PyObject*
2546DBC_count(DBCursorObject* self, PyObject* args)
2547{
2548 int err = 0;
2549 db_recno_t count;
2550 int flags = 0;
2551
2552 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2553 return NULL;
2554
2555 CHECK_CURSOR_NOT_CLOSED(self);
2556
2557 MYDB_BEGIN_ALLOW_THREADS;
2558 err = self->dbc->c_count(self->dbc, &count, flags);
2559 MYDB_END_ALLOW_THREADS;
2560 RETURN_IF_ERR();
2561
2562 return PyInt_FromLong(count);
2563}
2564
2565
2566static PyObject*
2567DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2568{
2569 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2570}
2571
2572
2573static PyObject*
2574DBC_delete(DBCursorObject* self, PyObject* args)
2575{
2576 int err, flags=0;
2577
2578 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2579 return NULL;
2580
2581 CHECK_CURSOR_NOT_CLOSED(self);
2582
2583 MYDB_BEGIN_ALLOW_THREADS;
2584 err = self->dbc->c_del(self->dbc, flags);
2585 MYDB_END_ALLOW_THREADS;
2586 RETURN_IF_ERR();
2587
2588 self->mydb->haveStat = 0;
2589 RETURN_NONE();
2590}
2591
2592
2593static PyObject*
2594DBC_dup(DBCursorObject* self, PyObject* args)
2595{
2596 int err, flags =0;
2597 DBC* dbc = NULL;
2598
2599 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2600 return NULL;
2601
2602 CHECK_CURSOR_NOT_CLOSED(self);
2603
2604 MYDB_BEGIN_ALLOW_THREADS;
2605 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2606 MYDB_END_ALLOW_THREADS;
2607 RETURN_IF_ERR();
2608
2609 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2610}
2611
2612static PyObject*
2613DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2614{
2615 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2616}
2617
2618
2619static PyObject*
2620DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2621{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00002622 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002623 PyObject* keyobj = NULL;
2624 PyObject* dataobj = NULL;
2625 PyObject* retval = NULL;
2626 int dlen = -1;
2627 int doff = -1;
2628 DBT key, data;
2629 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2630
2631 CLEAR_DBT(key);
2632 CLEAR_DBT(data);
2633 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002634 &flags, &dlen, &doff))
2635 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002636 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002637 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2638 &kwnames[1],
2639 &keyobj, &flags, &dlen, &doff))
2640 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002641 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002642 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2643 kwnames, &keyobj, &dataobj,
2644 &flags, &dlen, &doff))
2645 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002646 return NULL;
2647 }
2648 }
2649 }
2650
2651 CHECK_CURSOR_NOT_CLOSED(self);
2652
2653 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2654 return NULL;
2655 if (dataobj && !make_dbt(dataobj, &data))
2656 return NULL;
2657 if (!add_partial_dbt(&data, dlen, doff))
2658 return NULL;
2659
2660 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2661 data.flags = DB_DBT_MALLOC;
2662 key.flags = DB_DBT_MALLOC;
2663 }
2664
2665 MYDB_BEGIN_ALLOW_THREADS;
2666 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2667 MYDB_END_ALLOW_THREADS;
2668
2669
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002670 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002671 Py_INCREF(Py_None);
2672 retval = Py_None;
2673 }
2674 else if (makeDBError(err)) {
2675 retval = NULL;
2676 }
2677 else {
2678 switch (_DB_get_type(self->mydb)) {
2679 case -1:
2680 retval = NULL;
2681 break;
2682 case DB_BTREE:
2683 case DB_HASH:
2684 default:
2685 retval = Py_BuildValue("s#s#", key.data, key.size,
2686 data.data, data.size);
2687 break;
2688 case DB_RECNO:
2689 case DB_QUEUE:
2690 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2691 data.data, data.size);
2692 break;
2693 }
2694 FREE_DBT(key);
2695 FREE_DBT(data);
2696 }
2697 return retval;
2698}
2699
2700
2701static PyObject*
2702DBC_get_recno(DBCursorObject* self, PyObject* args)
2703{
2704 int err;
2705 db_recno_t recno;
2706 DBT key;
2707 DBT data;
2708
2709 if (!PyArg_ParseTuple(args, ":get_recno"))
2710 return NULL;
2711
2712 CHECK_CURSOR_NOT_CLOSED(self);
2713
2714 CLEAR_DBT(key);
2715 CLEAR_DBT(data);
2716 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2717 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2718 data.flags = DB_DBT_MALLOC;
2719 key.flags = DB_DBT_MALLOC;
2720 }
2721
2722 MYDB_BEGIN_ALLOW_THREADS;
2723 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
2724 MYDB_END_ALLOW_THREADS;
2725 RETURN_IF_ERR();
2726
2727 recno = *((db_recno_t*)data.data);
2728 FREE_DBT(key);
2729 FREE_DBT(data);
2730 return PyInt_FromLong(recno);
2731}
2732
2733
2734static PyObject*
2735DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2736{
2737 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
2738}
2739
2740
2741static PyObject*
2742DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2743{
2744 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
2745}
2746
2747
2748static PyObject*
2749DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2750{
2751 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
2752}
2753
2754
2755static PyObject*
2756DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2757{
2758 int err, flags = 0;
2759 PyObject* keyobj, *dataobj;
2760 DBT key, data;
2761 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
2762 int dlen = -1;
2763 int doff = -1;
2764
2765 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
2766 &keyobj, &dataobj, &flags, &dlen, &doff))
2767 return NULL;
2768
2769 CHECK_CURSOR_NOT_CLOSED(self);
2770
2771 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2772 return NULL;
2773 if (!make_dbt(dataobj, &data))
2774 return NULL;
2775 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
2776
2777 MYDB_BEGIN_ALLOW_THREADS;
2778 err = self->dbc->c_put(self->dbc, &key, &data, flags);
2779 MYDB_END_ALLOW_THREADS;
2780 FREE_DBT(key);
2781 RETURN_IF_ERR();
2782 self->mydb->haveStat = 0;
2783 RETURN_NONE();
2784}
2785
2786
2787static PyObject*
2788DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2789{
2790 int err, flags = 0;
2791 DBT key, data;
2792 PyObject* retval, *keyobj;
2793 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2794 int dlen = -1;
2795 int doff = -1;
2796
2797 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
2798 &keyobj, &flags, &dlen, &doff))
2799 return NULL;
2800
2801 CHECK_CURSOR_NOT_CLOSED(self);
2802
2803 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2804 return NULL;
2805
2806 CLEAR_DBT(data);
2807 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2808 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2809 data.flags = DB_DBT_MALLOC;
2810 }
2811 if (!add_partial_dbt(&data, dlen, doff))
2812 return NULL;
2813
2814 MYDB_BEGIN_ALLOW_THREADS;
2815 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
2816 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002817 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2818 Py_INCREF(Py_None);
2819 retval = Py_None;
2820 }
2821 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002822 retval = NULL;
2823 }
2824 else {
2825 switch (_DB_get_type(self->mydb)) {
2826 case -1:
2827 retval = NULL;
2828 break;
2829 case DB_BTREE:
2830 case DB_HASH:
2831 default:
2832 retval = Py_BuildValue("s#s#", key.data, key.size,
2833 data.data, data.size);
2834 break;
2835 case DB_RECNO:
2836 case DB_QUEUE:
2837 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2838 data.data, data.size);
2839 break;
2840 }
2841 FREE_DBT(key);
2842 FREE_DBT(data);
2843 }
2844
2845 return retval;
2846}
2847
2848
2849static PyObject*
2850DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2851{
2852 int err, flags = 0;
2853 DBT key, data;
2854 PyObject* retval, *keyobj;
2855 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2856 int dlen = -1;
2857 int doff = -1;
2858
2859 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
2860 &keyobj, &flags, &dlen, &doff))
2861 return NULL;
2862
2863 CHECK_CURSOR_NOT_CLOSED(self);
2864
2865 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2866 return NULL;
2867
2868 CLEAR_DBT(data);
2869 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2870 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2871 data.flags = DB_DBT_MALLOC;
2872 key.flags = DB_DBT_MALLOC;
2873 }
2874 if (!add_partial_dbt(&data, dlen, doff))
2875 return NULL;
2876 MYDB_BEGIN_ALLOW_THREADS;
2877 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
2878 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002879 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2880 Py_INCREF(Py_None);
2881 retval = Py_None;
2882 }
2883 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002884 retval = NULL;
2885 }
2886 else {
2887 switch (_DB_get_type(self->mydb)) {
2888 case -1:
2889 retval = NULL;
2890 break;
2891 case DB_BTREE:
2892 case DB_HASH:
2893 default:
2894 retval = Py_BuildValue("s#s#", key.data, key.size,
2895 data.data, data.size);
2896 break;
2897 case DB_RECNO:
2898 case DB_QUEUE:
2899 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2900 data.data, data.size);
2901 break;
2902 }
2903 FREE_DBT(key);
2904 FREE_DBT(data);
2905 }
2906
2907 return retval;
2908}
2909
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002910static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002911_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
2912 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002913{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002914 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002915 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002916 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002917
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002918 // the caller did this: CHECK_CURSOR_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002919 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2920 return NULL;
2921 if (!make_dbt(dataobj, &data))
2922 return NULL;
2923
2924 MYDB_BEGIN_ALLOW_THREADS;
2925 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
2926 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002927 if ((err == DB_NOTFOUND) && returnsNone) {
2928 Py_INCREF(Py_None);
2929 retval = Py_None;
2930 }
2931 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002932 retval = NULL;
2933 }
2934 else {
2935 switch (_DB_get_type(self->mydb)) {
2936 case -1:
2937 retval = NULL;
2938 break;
2939 case DB_BTREE:
2940 case DB_HASH:
2941 default:
2942 retval = Py_BuildValue("s#s#", key.data, key.size,
2943 data.data, data.size);
2944 break;
2945 case DB_RECNO:
2946 case DB_QUEUE:
2947 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2948 data.data, data.size);
2949 break;
2950 }
2951 }
2952
2953 FREE_DBT(key);
2954 return retval;
2955}
2956
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002957static PyObject*
2958DBC_get_both(DBCursorObject* self, PyObject* args)
2959{
2960 int flags=0;
2961 PyObject *keyobj, *dataobj;
2962
2963 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
2964 return NULL;
2965
2966 // if the cursor is closed, self->mydb may be invalid
2967 CHECK_CURSOR_NOT_CLOSED(self);
2968
2969 return _DBC_get_set_both(self, keyobj, dataobj, flags,
2970 self->mydb->moduleFlags.getReturnsNone);
2971}
2972
2973static PyObject*
2974DBC_set_both(DBCursorObject* self, PyObject* args)
2975{
2976 int flags=0;
2977 PyObject *keyobj, *dataobj;
2978
2979 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
2980 return NULL;
2981
2982 // if the cursor is closed, self->mydb may be invalid
2983 CHECK_CURSOR_NOT_CLOSED(self);
2984
2985 return _DBC_get_set_both(self, keyobj, dataobj, flags,
2986 self->mydb->moduleFlags.cursorSetReturnsNone);
2987}
2988
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002989
2990static PyObject*
2991DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2992{
2993 int err, irecno, flags=0;
2994 db_recno_t recno;
2995 DBT key, data;
2996 PyObject* retval;
2997 int dlen = -1;
2998 int doff = -1;
2999 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3000
3001 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3002 &irecno, &flags, &dlen, &doff))
3003 return NULL;
3004
3005 CHECK_CURSOR_NOT_CLOSED(self);
3006
3007 CLEAR_DBT(key);
3008 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003009 /* use allocated space so DB will be able to realloc room for the real
3010 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003011 key.data = malloc(sizeof(db_recno_t));
3012 if (key.data == NULL) {
3013 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3014 return NULL;
3015 }
3016 key.size = sizeof(db_recno_t);
3017 key.ulen = key.size;
3018 memcpy(key.data, &recno, sizeof(db_recno_t));
3019 key.flags = DB_DBT_REALLOC;
3020
3021 CLEAR_DBT(data);
3022 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3023 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3024 data.flags = DB_DBT_MALLOC;
3025 }
3026 if (!add_partial_dbt(&data, dlen, doff))
3027 return NULL;
3028
3029 MYDB_BEGIN_ALLOW_THREADS;
3030 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3031 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003032 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3033 Py_INCREF(Py_None);
3034 retval = Py_None;
3035 }
3036 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003037 retval = NULL;
3038 }
3039 else { /* Can only be used for BTrees, so no need to return int key */
3040 retval = Py_BuildValue("s#s#", key.data, key.size,
3041 data.data, data.size);
3042 FREE_DBT(key);
3043 FREE_DBT(data);
3044 }
3045
3046 return retval;
3047}
3048
3049
3050static PyObject*
3051DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3052{
3053 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3054}
3055
3056
3057static PyObject*
3058DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3059{
3060 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3061}
3062
3063
3064static PyObject*
3065DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3066{
3067 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3068}
3069
3070
3071static PyObject*
3072DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3073{
3074 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3075}
3076
3077
3078static PyObject*
3079DBC_join_item(DBCursorObject* self, PyObject* args)
3080{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003081 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003082 DBT key, data;
3083 PyObject* retval;
3084
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003085 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003086 return NULL;
3087
3088 CHECK_CURSOR_NOT_CLOSED(self);
3089
3090 CLEAR_DBT(key);
3091 CLEAR_DBT(data);
3092 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3093 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3094 key.flags = DB_DBT_MALLOC;
3095 }
3096
3097 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003098 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003099 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003100 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3101 Py_INCREF(Py_None);
3102 retval = Py_None;
3103 }
3104 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003105 retval = NULL;
3106 }
3107 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003108 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003109 FREE_DBT(key);
3110 }
3111
3112 return retval;
3113}
3114
3115
3116
3117/* --------------------------------------------------------------------- */
3118/* DBEnv methods */
3119
3120
3121static PyObject*
3122DBEnv_close(DBEnvObject* self, PyObject* args)
3123{
3124 int err, flags = 0;
3125
3126 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3127 return NULL;
3128 if (!self->closed) { /* Don't close more than once */
3129 MYDB_BEGIN_ALLOW_THREADS;
3130 err = self->db_env->close(self->db_env, flags);
3131 MYDB_END_ALLOW_THREADS;
3132 /* after calling DBEnv->close, regardless of error, this DBEnv
3133 * may not be accessed again (BerkeleyDB docs). */
3134 self->closed = 1;
3135 self->db_env = NULL;
3136 RETURN_IF_ERR();
3137 }
3138 RETURN_NONE();
3139}
3140
3141
3142static PyObject*
3143DBEnv_open(DBEnvObject* self, PyObject* args)
3144{
3145 int err, flags=0, mode=0660;
3146 char *db_home;
3147
3148 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3149 return NULL;
3150
3151 CHECK_ENV_NOT_CLOSED(self);
3152
3153 MYDB_BEGIN_ALLOW_THREADS;
3154 err = self->db_env->open(self->db_env, db_home, flags, mode);
3155 MYDB_END_ALLOW_THREADS;
3156 RETURN_IF_ERR();
3157 self->closed = 0;
3158 self->flags = flags;
3159 RETURN_NONE();
3160}
3161
3162
3163static PyObject*
3164DBEnv_remove(DBEnvObject* self, PyObject* args)
3165{
3166 int err, flags=0;
3167 char *db_home;
3168
3169 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3170 return NULL;
3171 CHECK_ENV_NOT_CLOSED(self);
3172 MYDB_BEGIN_ALLOW_THREADS;
3173 err = self->db_env->remove(self->db_env, db_home, flags);
3174 MYDB_END_ALLOW_THREADS;
3175 RETURN_IF_ERR();
3176 RETURN_NONE();
3177}
3178
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003179#if (DBVER >= 41)
3180static PyObject*
3181DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3182{
3183 int err;
3184 u_int32_t flags=0;
3185 char *file = NULL;
3186 char *database = NULL;
3187 PyObject *txnobj = NULL;
3188 DB_TXN *txn = NULL;
3189 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3190
3191 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3192 &file, &database, &txnobj, &flags)) {
3193 return NULL;
3194 }
3195 if (!checkTxnObj(txnobj, &txn)) {
3196 return NULL;
3197 }
3198 CHECK_ENV_NOT_CLOSED(self);
3199 MYDB_BEGIN_ALLOW_THREADS;
3200 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3201 MYDB_END_ALLOW_THREADS;
3202 RETURN_IF_ERR();
3203 RETURN_NONE();
3204}
3205
3206static PyObject*
3207DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3208{
3209 int err;
3210 u_int32_t flags=0;
3211 char *file = NULL;
3212 char *database = NULL;
3213 char *newname = NULL;
3214 PyObject *txnobj = NULL;
3215 DB_TXN *txn = NULL;
3216 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3217
3218 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3219 &file, &database, &newname, &txnobj, &flags)) {
3220 return NULL;
3221 }
3222 if (!checkTxnObj(txnobj, &txn)) {
3223 return NULL;
3224 }
3225 CHECK_ENV_NOT_CLOSED(self);
3226 MYDB_BEGIN_ALLOW_THREADS;
3227 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3228 flags);
3229 MYDB_END_ALLOW_THREADS;
3230 RETURN_IF_ERR();
3231 RETURN_NONE();
3232}
3233
3234static PyObject*
3235DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3236{
3237 int err;
3238 u_int32_t flags=0;
3239 char *passwd = NULL;
3240 char* kwnames[] = { "passwd", "flags", NULL };
3241
3242 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3243 &passwd, &flags)) {
3244 return NULL;
3245 }
3246
3247 MYDB_BEGIN_ALLOW_THREADS;
3248 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3249 MYDB_END_ALLOW_THREADS;
3250
3251 RETURN_IF_ERR();
3252 RETURN_NONE();
3253}
3254#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003255
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003256#if (DBVER >= 40)
3257static PyObject*
3258DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3259{
3260 int err;
3261 u_int32_t flags=0;
3262 u_int32_t timeout = 0;
3263 char* kwnames[] = { "timeout", "flags", NULL };
3264
3265 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3266 &timeout, &flags)) {
3267 return NULL;
3268 }
3269
3270 MYDB_BEGIN_ALLOW_THREADS;
3271 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3272 MYDB_END_ALLOW_THREADS;
3273
3274 RETURN_IF_ERR();
3275 RETURN_NONE();
3276}
3277#endif /* DBVER >= 40 */
3278
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003279static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00003280DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3281{
3282 int err;
3283 long shm_key = 0;
3284
3285 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3286 return NULL;
3287 CHECK_ENV_NOT_CLOSED(self);
3288
3289 err = self->db_env->set_shm_key(self->db_env, shm_key);
3290 RETURN_IF_ERR();
3291 RETURN_NONE();
3292}
3293
3294static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003295DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3296{
3297 int err, gbytes=0, bytes=0, ncache=0;
3298
3299 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3300 &gbytes, &bytes, &ncache))
3301 return NULL;
3302 CHECK_ENV_NOT_CLOSED(self);
3303
3304 MYDB_BEGIN_ALLOW_THREADS;
3305 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3306 MYDB_END_ALLOW_THREADS;
3307 RETURN_IF_ERR();
3308 RETURN_NONE();
3309}
3310
3311
3312#if (DBVER >= 32)
3313static PyObject*
3314DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3315{
3316 int err, flags=0, onoff=0;
3317
3318 if (!PyArg_ParseTuple(args, "ii:set_flags",
3319 &flags, &onoff))
3320 return NULL;
3321 CHECK_ENV_NOT_CLOSED(self);
3322
3323 MYDB_BEGIN_ALLOW_THREADS;
3324 err = self->db_env->set_flags(self->db_env, flags, onoff);
3325 MYDB_END_ALLOW_THREADS;
3326 RETURN_IF_ERR();
3327 RETURN_NONE();
3328}
3329#endif
3330
3331
3332static PyObject*
3333DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3334{
3335 int err;
3336 char *dir;
3337
3338 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3339 return NULL;
3340 CHECK_ENV_NOT_CLOSED(self);
3341
3342 MYDB_BEGIN_ALLOW_THREADS;
3343 err = self->db_env->set_data_dir(self->db_env, dir);
3344 MYDB_END_ALLOW_THREADS;
3345 RETURN_IF_ERR();
3346 RETURN_NONE();
3347}
3348
3349
3350static PyObject*
3351DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3352{
3353 int err, lg_bsize;
3354
3355 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3356 return NULL;
3357 CHECK_ENV_NOT_CLOSED(self);
3358
3359 MYDB_BEGIN_ALLOW_THREADS;
3360 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3361 MYDB_END_ALLOW_THREADS;
3362 RETURN_IF_ERR();
3363 RETURN_NONE();
3364}
3365
3366
3367static PyObject*
3368DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3369{
3370 int err;
3371 char *dir;
3372
3373 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3374 return NULL;
3375 CHECK_ENV_NOT_CLOSED(self);
3376
3377 MYDB_BEGIN_ALLOW_THREADS;
3378 err = self->db_env->set_lg_dir(self->db_env, dir);
3379 MYDB_END_ALLOW_THREADS;
3380 RETURN_IF_ERR();
3381 RETURN_NONE();
3382}
3383
3384static PyObject*
3385DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3386{
3387 int err, lg_max;
3388
3389 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3390 return NULL;
3391 CHECK_ENV_NOT_CLOSED(self);
3392
3393 MYDB_BEGIN_ALLOW_THREADS;
3394 err = self->db_env->set_lg_max(self->db_env, lg_max);
3395 MYDB_END_ALLOW_THREADS;
3396 RETURN_IF_ERR();
3397 RETURN_NONE();
3398}
3399
3400
3401static PyObject*
3402DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3403{
3404 int err, lk_detect;
3405
3406 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3407 return NULL;
3408 CHECK_ENV_NOT_CLOSED(self);
3409
3410 MYDB_BEGIN_ALLOW_THREADS;
3411 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3412 MYDB_END_ALLOW_THREADS;
3413 RETURN_IF_ERR();
3414 RETURN_NONE();
3415}
3416
3417
3418static PyObject*
3419DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3420{
3421 int err, max;
3422
3423 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3424 return NULL;
3425 CHECK_ENV_NOT_CLOSED(self);
3426
3427 MYDB_BEGIN_ALLOW_THREADS;
3428 err = self->db_env->set_lk_max(self->db_env, max);
3429 MYDB_END_ALLOW_THREADS;
3430 RETURN_IF_ERR();
3431 RETURN_NONE();
3432}
3433
3434
3435#if (DBVER >= 32)
3436
3437static PyObject*
3438DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3439{
3440 int err, max;
3441
3442 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3443 return NULL;
3444 CHECK_ENV_NOT_CLOSED(self);
3445
3446 MYDB_BEGIN_ALLOW_THREADS;
3447 err = self->db_env->set_lk_max_locks(self->db_env, max);
3448 MYDB_END_ALLOW_THREADS;
3449 RETURN_IF_ERR();
3450 RETURN_NONE();
3451}
3452
3453
3454static PyObject*
3455DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3456{
3457 int err, max;
3458
3459 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3460 return NULL;
3461 CHECK_ENV_NOT_CLOSED(self);
3462
3463 MYDB_BEGIN_ALLOW_THREADS;
3464 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3465 MYDB_END_ALLOW_THREADS;
3466 RETURN_IF_ERR();
3467 RETURN_NONE();
3468}
3469
3470
3471static PyObject*
3472DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3473{
3474 int err, max;
3475
3476 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3477 return NULL;
3478 CHECK_ENV_NOT_CLOSED(self);
3479
3480 MYDB_BEGIN_ALLOW_THREADS;
3481 err = self->db_env->set_lk_max_objects(self->db_env, max);
3482 MYDB_END_ALLOW_THREADS;
3483 RETURN_IF_ERR();
3484 RETURN_NONE();
3485}
3486
3487#endif
3488
3489
3490static PyObject*
3491DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3492{
3493 int err, mp_mmapsize;
3494
3495 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3496 return NULL;
3497 CHECK_ENV_NOT_CLOSED(self);
3498
3499 MYDB_BEGIN_ALLOW_THREADS;
3500 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3501 MYDB_END_ALLOW_THREADS;
3502 RETURN_IF_ERR();
3503 RETURN_NONE();
3504}
3505
3506
3507static PyObject*
3508DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3509{
3510 int err;
3511 char *dir;
3512
3513 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3514 return NULL;
3515 CHECK_ENV_NOT_CLOSED(self);
3516
3517 MYDB_BEGIN_ALLOW_THREADS;
3518 err = self->db_env->set_tmp_dir(self->db_env, dir);
3519 MYDB_END_ALLOW_THREADS;
3520 RETURN_IF_ERR();
3521 RETURN_NONE();
3522}
3523
3524
3525static PyObject*
3526DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3527{
3528 int flags = 0;
3529 PyObject* txnobj = NULL;
3530 DB_TXN *txn = NULL;
3531 char* kwnames[] = { "parent", "flags", NULL };
3532
3533 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3534 &txnobj, &flags))
3535 return NULL;
3536
3537 if (!checkTxnObj(txnobj, &txn))
3538 return NULL;
3539 CHECK_ENV_NOT_CLOSED(self);
3540
3541 return (PyObject*)newDBTxnObject(self, txn, flags);
3542}
3543
3544
3545static PyObject*
3546DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3547{
3548 int err, kbyte=0, min=0, flags=0;
3549
3550 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3551 return NULL;
3552 CHECK_ENV_NOT_CLOSED(self);
3553
3554 MYDB_BEGIN_ALLOW_THREADS;
3555#if (DBVER >= 40)
3556 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3557#else
3558 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3559#endif
3560 MYDB_END_ALLOW_THREADS;
3561 RETURN_IF_ERR();
3562 RETURN_NONE();
3563}
3564
3565
3566static PyObject*
3567DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3568{
3569 int err, max;
3570
3571 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3572 return NULL;
3573 CHECK_ENV_NOT_CLOSED(self);
3574
3575 MYDB_BEGIN_ALLOW_THREADS;
3576 err = self->db_env->set_tx_max(self->db_env, max);
3577 MYDB_END_ALLOW_THREADS;
3578 RETURN_IF_ERR();
3579 RETURN_NONE();
3580}
3581
3582
3583static PyObject*
3584DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3585{
3586 int err, atype, flags=0;
3587 int aborted = 0;
3588
3589 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3590 return NULL;
3591 CHECK_ENV_NOT_CLOSED(self);
3592
3593 MYDB_BEGIN_ALLOW_THREADS;
3594#if (DBVER >= 40)
3595 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3596#else
3597 err = lock_detect(self->db_env, flags, atype, &aborted);
3598#endif
3599 MYDB_END_ALLOW_THREADS;
3600 RETURN_IF_ERR();
3601 return PyInt_FromLong(aborted);
3602}
3603
3604
3605static PyObject*
3606DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3607{
3608 int flags=0;
3609 int locker, lock_mode;
3610 DBT obj;
3611 PyObject* objobj;
3612
3613 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3614 return NULL;
3615
3616
3617 if (!make_dbt(objobj, &obj))
3618 return NULL;
3619
3620 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3621}
3622
3623
3624static PyObject*
3625DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3626{
3627 int err;
3628 u_int32_t theID;
3629
3630 if (!PyArg_ParseTuple(args, ":lock_id"))
3631 return NULL;
3632
3633 CHECK_ENV_NOT_CLOSED(self);
3634 MYDB_BEGIN_ALLOW_THREADS;
3635#if (DBVER >= 40)
3636 err = self->db_env->lock_id(self->db_env, &theID);
3637#else
3638 err = lock_id(self->db_env, &theID);
3639#endif
3640 MYDB_END_ALLOW_THREADS;
3641 RETURN_IF_ERR();
3642
3643 return PyInt_FromLong((long)theID);
3644}
3645
3646
3647static PyObject*
3648DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3649{
3650 int err;
3651 DBLockObject* dblockobj;
3652
3653 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3654 return NULL;
3655
3656 CHECK_ENV_NOT_CLOSED(self);
3657 MYDB_BEGIN_ALLOW_THREADS;
3658#if (DBVER >= 40)
3659 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3660#else
3661 err = lock_put(self->db_env, &dblockobj->lock);
3662#endif
3663 MYDB_END_ALLOW_THREADS;
3664 RETURN_IF_ERR();
3665 RETURN_NONE();
3666}
3667
3668
3669static PyObject*
3670DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
3671{
3672 int err;
3673 DB_LOCK_STAT* sp;
3674 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003675 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003676
3677 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
3678 return NULL;
3679 CHECK_ENV_NOT_CLOSED(self);
3680
3681 MYDB_BEGIN_ALLOW_THREADS;
3682#if (DBVER >= 40)
3683 err = self->db_env->lock_stat(self->db_env, &sp, flags);
3684#else
3685#if (DBVER >= 33)
3686 err = lock_stat(self->db_env, &sp);
3687#else
3688 err = lock_stat(self->db_env, &sp, NULL);
3689#endif
3690#endif
3691 MYDB_END_ALLOW_THREADS;
3692 RETURN_IF_ERR();
3693
3694 /* Turn the stat structure into a dictionary */
3695 d = PyDict_New();
3696 if (d == NULL) {
3697 free(sp);
3698 return NULL;
3699 }
3700
3701#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3702
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003703#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003704 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003705#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003706 MAKE_ENTRY(nmodes);
3707#if (DBVER >= 32)
3708 MAKE_ENTRY(maxlocks);
3709 MAKE_ENTRY(maxlockers);
3710 MAKE_ENTRY(maxobjects);
3711 MAKE_ENTRY(nlocks);
3712 MAKE_ENTRY(maxnlocks);
3713#endif
3714 MAKE_ENTRY(nlockers);
3715 MAKE_ENTRY(maxnlockers);
3716#if (DBVER >= 32)
3717 MAKE_ENTRY(nobjects);
3718 MAKE_ENTRY(maxnobjects);
3719#endif
3720 MAKE_ENTRY(nrequests);
3721 MAKE_ENTRY(nreleases);
3722 MAKE_ENTRY(nnowaits);
3723 MAKE_ENTRY(nconflicts);
3724 MAKE_ENTRY(ndeadlocks);
3725 MAKE_ENTRY(regsize);
3726 MAKE_ENTRY(region_wait);
3727 MAKE_ENTRY(region_nowait);
3728
3729#undef MAKE_ENTRY
3730 free(sp);
3731 return d;
3732}
3733
3734
3735static PyObject*
3736DBEnv_log_archive(DBEnvObject* self, PyObject* args)
3737{
3738 int flags=0;
3739 int err;
3740 char **log_list_start, **log_list;
3741 PyObject* list;
3742 PyObject* item = NULL;
3743
3744 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
3745 return NULL;
3746
3747 CHECK_ENV_NOT_CLOSED(self);
3748 MYDB_BEGIN_ALLOW_THREADS;
3749#if (DBVER >= 40)
3750 err = self->db_env->log_archive(self->db_env, &log_list, flags);
3751#elif (DBVER == 33)
3752 err = log_archive(self->db_env, &log_list, flags);
3753#else
3754 err = log_archive(self->db_env, &log_list, flags, NULL);
3755#endif
3756 MYDB_END_ALLOW_THREADS;
3757 RETURN_IF_ERR();
3758
3759 list = PyList_New(0);
3760 if (list == NULL) {
3761 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
3762 return NULL;
3763 }
3764
3765 if (log_list) {
3766 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
3767 item = PyString_FromString (*log_list);
3768 if (item == NULL) {
3769 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003770 PyErr_SetString(PyExc_MemoryError,
3771 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003772 list = NULL;
3773 break;
3774 }
3775 PyList_Append(list, item);
3776 Py_DECREF(item);
3777 }
3778 free(log_list_start);
3779 }
3780 return list;
3781}
3782
3783
3784static PyObject*
3785DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
3786{
3787 int err;
3788 DB_TXN_STAT* sp;
3789 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003790 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003791
3792 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
3793 return NULL;
3794 CHECK_ENV_NOT_CLOSED(self);
3795
3796 MYDB_BEGIN_ALLOW_THREADS;
3797#if (DBVER >= 40)
3798 err = self->db_env->txn_stat(self->db_env, &sp, flags);
3799#elif (DBVER == 33)
3800 err = txn_stat(self->db_env, &sp);
3801#else
3802 err = txn_stat(self->db_env, &sp, NULL);
3803#endif
3804 MYDB_END_ALLOW_THREADS;
3805 RETURN_IF_ERR();
3806
3807 /* Turn the stat structure into a dictionary */
3808 d = PyDict_New();
3809 if (d == NULL) {
3810 free(sp);
3811 return NULL;
3812 }
3813
3814#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3815
3816 MAKE_ENTRY(time_ckp);
3817 MAKE_ENTRY(last_txnid);
3818 MAKE_ENTRY(maxtxns);
3819 MAKE_ENTRY(nactive);
3820 MAKE_ENTRY(maxnactive);
3821 MAKE_ENTRY(nbegins);
3822 MAKE_ENTRY(naborts);
3823 MAKE_ENTRY(ncommits);
3824 MAKE_ENTRY(regsize);
3825 MAKE_ENTRY(region_wait);
3826 MAKE_ENTRY(region_nowait);
3827
3828#undef MAKE_ENTRY
3829 free(sp);
3830 return d;
3831}
3832
3833
3834static PyObject*
3835DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
3836{
3837 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003838 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003839
3840 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
3841 return NULL;
3842 CHECK_ENV_NOT_CLOSED(self);
3843
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003844 if (self->moduleFlags.getReturnsNone)
3845 ++oldValue;
3846 if (self->moduleFlags.cursorSetReturnsNone)
3847 ++oldValue;
3848 self->moduleFlags.getReturnsNone = (flags >= 1);
3849 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003850 return PyInt_FromLong(oldValue);
3851}
3852
3853
3854/* --------------------------------------------------------------------- */
3855/* DBTxn methods */
3856
3857
3858static PyObject*
3859DBTxn_commit(DBTxnObject* self, PyObject* args)
3860{
3861 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003862 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003863
3864 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
3865 return NULL;
3866
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003867 if (!self->txn) {
3868 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3869 "DBTxn must not be used after txn_commit or txn_abort"));
3870 return NULL;
3871 }
3872 txn = self->txn;
3873 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003874 MYDB_BEGIN_ALLOW_THREADS;
3875#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003876 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003877#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003878 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003879#endif
3880 MYDB_END_ALLOW_THREADS;
3881 RETURN_IF_ERR();
3882 RETURN_NONE();
3883}
3884
3885static PyObject*
3886DBTxn_prepare(DBTxnObject* self, PyObject* args)
3887{
3888#if (DBVER >= 33)
3889 int err;
3890 char* gid=NULL;
3891 int gid_size=0;
3892
3893 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
3894 return NULL;
3895
3896 if (gid_size != DB_XIDDATASIZE) {
3897 PyErr_SetString(PyExc_TypeError,
3898 "gid must be DB_XIDDATASIZE bytes long");
3899 return NULL;
3900 }
3901
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003902 if (!self->txn) {
3903 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3904 "DBTxn must not be used after txn_commit or txn_abort"));
3905 return NULL;
3906 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003907 MYDB_BEGIN_ALLOW_THREADS;
3908#if (DBVER >= 40)
3909 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
3910#else
3911 err = txn_prepare(self->txn, (u_int8_t*)gid);
3912#endif
3913 MYDB_END_ALLOW_THREADS;
3914 RETURN_IF_ERR();
3915 RETURN_NONE();
3916#else
3917 int err;
3918
3919 if (!PyArg_ParseTuple(args, ":prepare"))
3920 return NULL;
3921
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003922 if (!self->txn) {
3923 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3924 "DBTxn must not be used after txn_commit or txn_abort"));
3925 return NULL;
3926 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003927 MYDB_BEGIN_ALLOW_THREADS;
3928 err = txn_prepare(self->txn);
3929 MYDB_END_ALLOW_THREADS;
3930 RETURN_IF_ERR();
3931 RETURN_NONE();
3932#endif
3933}
3934
3935
3936static PyObject*
3937DBTxn_abort(DBTxnObject* self, PyObject* args)
3938{
3939 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003940 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003941
3942 if (!PyArg_ParseTuple(args, ":abort"))
3943 return NULL;
3944
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003945 if (!self->txn) {
3946 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3947 "DBTxn must not be used after txn_commit or txn_abort"));
3948 return NULL;
3949 }
3950 txn = self->txn;
3951 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003952 MYDB_BEGIN_ALLOW_THREADS;
3953#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003954 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003955#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003956 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003957#endif
3958 MYDB_END_ALLOW_THREADS;
3959 RETURN_IF_ERR();
3960 RETURN_NONE();
3961}
3962
3963
3964static PyObject*
3965DBTxn_id(DBTxnObject* self, PyObject* args)
3966{
3967 int id;
3968
3969 if (!PyArg_ParseTuple(args, ":id"))
3970 return NULL;
3971
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003972 if (!self->txn) {
3973 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3974 "DBTxn must not be used after txn_commit or txn_abort"));
3975 return NULL;
3976 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003977 MYDB_BEGIN_ALLOW_THREADS;
3978#if (DBVER >= 40)
3979 id = self->txn->id(self->txn);
3980#else
3981 id = txn_id(self->txn);
3982#endif
3983 MYDB_END_ALLOW_THREADS;
3984 return PyInt_FromLong(id);
3985}
3986
3987/* --------------------------------------------------------------------- */
3988/* Method definition tables and type objects */
3989
3990static PyMethodDef DB_methods[] = {
3991 {"append", (PyCFunction)DB_append, METH_VARARGS},
3992#if (DBVER >= 33)
3993 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
3994#endif
3995 {"close", (PyCFunction)DB_close, METH_VARARGS},
3996#if (DBVER >= 32)
3997 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
3998 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
3999#endif
4000 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4001 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4002 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4003 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
4004 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4005 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4006 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4007 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4008 {"join", (PyCFunction)DB_join, METH_VARARGS},
4009 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4010 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4011 {"items", (PyCFunction)DB_items, METH_VARARGS},
4012 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4013 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4014 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4015 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4016 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4017 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4018 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004019#if (DBVER >= 41)
4020 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4021#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004022 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4023 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4024 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4025 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4026 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4027 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4028 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4029 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4030 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4031#if (DBVER >= 32)
4032 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4033#endif
4034 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4035 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4036#if (DBVER >= 33)
4037 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4038#endif
4039 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4040 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4041 {"values", (PyCFunction)DB_values, METH_VARARGS},
4042 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4043 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4044 {NULL, NULL} /* sentinel */
4045};
4046
4047
4048static PyMappingMethods DB_mapping = {
4049 (inquiry)DB_length, /*mp_length*/
4050 (binaryfunc)DB_subscript, /*mp_subscript*/
4051 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4052};
4053
4054
4055static PyMethodDef DBCursor_methods[] = {
4056 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4057 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4058 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4059 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4060 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4061 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4062 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4063 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4064 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4065 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4066 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4067 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4068 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4069 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4070 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004071 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004072 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4073 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4074 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4075 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4076 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4077 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4078 {NULL, NULL} /* sentinel */
4079};
4080
4081
4082static PyMethodDef DBEnv_methods[] = {
4083 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4084 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4085 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004086#if (DBVER >= 41)
4087 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4088 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4089 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4090#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004091#if (DBVER >= 40)
4092 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4093#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004094 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004095 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4096 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4097#if (DBVER >= 32)
4098 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4099#endif
4100 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4101 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4102 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4103 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4104 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4105#if (DBVER >= 32)
4106 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4107 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4108 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4109#endif
4110 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4111 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4112 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4113 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4114 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4115 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4116 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4117 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4118 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4119 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4120 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4121 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4122 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4123 {NULL, NULL} /* sentinel */
4124};
4125
4126
4127static PyMethodDef DBTxn_methods[] = {
4128 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4129 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4130 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4131 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4132 {NULL, NULL} /* sentinel */
4133};
4134
4135
4136static PyObject*
4137DB_getattr(DBObject* self, char *name)
4138{
4139 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4140}
4141
4142
4143static PyObject*
4144DBEnv_getattr(DBEnvObject* self, char *name)
4145{
4146 if (!strcmp(name, "db_home")) {
4147 CHECK_ENV_NOT_CLOSED(self);
4148 if (self->db_env->db_home == NULL) {
4149 RETURN_NONE();
4150 }
4151 return PyString_FromString(self->db_env->db_home);
4152 }
4153
4154 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4155}
4156
4157
4158static PyObject*
4159DBCursor_getattr(DBCursorObject* self, char *name)
4160{
4161 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4162}
4163
4164static PyObject*
4165DBTxn_getattr(DBTxnObject* self, char *name)
4166{
4167 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4168}
4169
4170static PyObject*
4171DBLock_getattr(DBLockObject* self, char *name)
4172{
4173 return NULL;
4174}
4175
4176statichere PyTypeObject DB_Type = {
4177 PyObject_HEAD_INIT(NULL)
4178 0, /*ob_size*/
4179 "DB", /*tp_name*/
4180 sizeof(DBObject), /*tp_basicsize*/
4181 0, /*tp_itemsize*/
4182 /* methods */
4183 (destructor)DB_dealloc, /*tp_dealloc*/
4184 0, /*tp_print*/
4185 (getattrfunc)DB_getattr, /*tp_getattr*/
4186 0, /*tp_setattr*/
4187 0, /*tp_compare*/
4188 0, /*tp_repr*/
4189 0, /*tp_as_number*/
4190 0, /*tp_as_sequence*/
4191 &DB_mapping,/*tp_as_mapping*/
4192 0, /*tp_hash*/
4193};
4194
4195
4196statichere PyTypeObject DBCursor_Type = {
4197 PyObject_HEAD_INIT(NULL)
4198 0, /*ob_size*/
4199 "DBCursor", /*tp_name*/
4200 sizeof(DBCursorObject), /*tp_basicsize*/
4201 0, /*tp_itemsize*/
4202 /* methods */
4203 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4204 0, /*tp_print*/
4205 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4206 0, /*tp_setattr*/
4207 0, /*tp_compare*/
4208 0, /*tp_repr*/
4209 0, /*tp_as_number*/
4210 0, /*tp_as_sequence*/
4211 0, /*tp_as_mapping*/
4212 0, /*tp_hash*/
4213};
4214
4215
4216statichere PyTypeObject DBEnv_Type = {
4217 PyObject_HEAD_INIT(NULL)
4218 0, /*ob_size*/
4219 "DBEnv", /*tp_name*/
4220 sizeof(DBEnvObject), /*tp_basicsize*/
4221 0, /*tp_itemsize*/
4222 /* methods */
4223 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4224 0, /*tp_print*/
4225 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4226 0, /*tp_setattr*/
4227 0, /*tp_compare*/
4228 0, /*tp_repr*/
4229 0, /*tp_as_number*/
4230 0, /*tp_as_sequence*/
4231 0, /*tp_as_mapping*/
4232 0, /*tp_hash*/
4233};
4234
4235statichere PyTypeObject DBTxn_Type = {
4236 PyObject_HEAD_INIT(NULL)
4237 0, /*ob_size*/
4238 "DBTxn", /*tp_name*/
4239 sizeof(DBTxnObject), /*tp_basicsize*/
4240 0, /*tp_itemsize*/
4241 /* methods */
4242 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4243 0, /*tp_print*/
4244 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4245 0, /*tp_setattr*/
4246 0, /*tp_compare*/
4247 0, /*tp_repr*/
4248 0, /*tp_as_number*/
4249 0, /*tp_as_sequence*/
4250 0, /*tp_as_mapping*/
4251 0, /*tp_hash*/
4252};
4253
4254
4255statichere PyTypeObject DBLock_Type = {
4256 PyObject_HEAD_INIT(NULL)
4257 0, /*ob_size*/
4258 "DBLock", /*tp_name*/
4259 sizeof(DBLockObject), /*tp_basicsize*/
4260 0, /*tp_itemsize*/
4261 /* methods */
4262 (destructor)DBLock_dealloc, /*tp_dealloc*/
4263 0, /*tp_print*/
4264 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4265 0, /*tp_setattr*/
4266 0, /*tp_compare*/
4267 0, /*tp_repr*/
4268 0, /*tp_as_number*/
4269 0, /*tp_as_sequence*/
4270 0, /*tp_as_mapping*/
4271 0, /*tp_hash*/
4272};
4273
4274
4275/* --------------------------------------------------------------------- */
4276/* Module-level functions */
4277
4278static PyObject*
4279DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4280{
4281 PyObject* dbenvobj = NULL;
4282 int flags = 0;
4283 char* kwnames[] = { "dbEnv", "flags", NULL};
4284
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004285 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4286 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004287 return NULL;
4288 if (dbenvobj == Py_None)
4289 dbenvobj = NULL;
4290 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4291 makeTypeError("DBEnv", dbenvobj);
4292 return NULL;
4293 }
4294
4295 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4296}
4297
4298
4299static PyObject*
4300DBEnv_construct(PyObject* self, PyObject* args)
4301{
4302 int flags = 0;
4303 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4304 return (PyObject* )newDBEnvObject(flags);
4305}
4306
4307
4308static char bsddb_version_doc[] =
4309"Returns a tuple of major, minor, and patch release numbers of the\n\
4310underlying DB library.";
4311
4312static PyObject*
4313bsddb_version(PyObject* self, PyObject* args)
4314{
4315 int major, minor, patch;
4316
4317 if (!PyArg_ParseTuple(args, ":version"))
4318 return NULL;
4319 db_version(&major, &minor, &patch);
4320 return Py_BuildValue("(iii)", major, minor, patch);
4321}
4322
4323
4324/* List of functions defined in the module */
4325
4326static PyMethodDef bsddb_methods[] = {
4327 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4328 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4329 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4330 {NULL, NULL} /* sentinel */
4331};
4332
4333
4334/* --------------------------------------------------------------------- */
4335/* Module initialization */
4336
4337
4338/* Convenience routine to export an integer value.
4339 * Errors are silently ignored, for better or for worse...
4340 */
4341#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4342
4343
4344
4345DL_EXPORT(void) init_bsddb(void)
4346{
4347 PyObject* m;
4348 PyObject* d;
4349 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4350 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4351 PyObject* cvsid_s = PyString_FromString( rcs_id );
4352
4353 /* Initialize the type of the new type objects here; doing it here
4354 is required for portability to Windows without requiring C++. */
4355 DB_Type.ob_type = &PyType_Type;
4356 DBCursor_Type.ob_type = &PyType_Type;
4357 DBEnv_Type.ob_type = &PyType_Type;
4358 DBTxn_Type.ob_type = &PyType_Type;
4359 DBLock_Type.ob_type = &PyType_Type;
4360
4361
Mark Hammonda69d4092003-04-22 23:13:27 +00004362#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004363 /* Save the current interpreter, so callbacks can do the right thing. */
4364 _db_interpreterState = PyThreadState_Get()->interp;
4365#endif
4366
4367 /* Create the module and add the functions */
4368 m = Py_InitModule("_bsddb", bsddb_methods);
4369
4370 /* Add some symbolic constants to the module */
4371 d = PyModule_GetDict(m);
4372 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4373 PyDict_SetItemString(d, "cvsid", cvsid_s);
4374 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4375 Py_DECREF(pybsddb_version_s);
4376 pybsddb_version_s = NULL;
4377 Py_DECREF(cvsid_s);
4378 cvsid_s = NULL;
4379 Py_DECREF(db_version_s);
4380 db_version_s = NULL;
4381
4382 ADD_INT(d, DB_VERSION_MAJOR);
4383 ADD_INT(d, DB_VERSION_MINOR);
4384 ADD_INT(d, DB_VERSION_PATCH);
4385
4386 ADD_INT(d, DB_MAX_PAGES);
4387 ADD_INT(d, DB_MAX_RECORDS);
4388
4389 ADD_INT(d, DB_CLIENT);
4390 ADD_INT(d, DB_XA_CREATE);
4391
4392 ADD_INT(d, DB_CREATE);
4393 ADD_INT(d, DB_NOMMAP);
4394 ADD_INT(d, DB_THREAD);
4395
4396 ADD_INT(d, DB_FORCE);
4397 ADD_INT(d, DB_INIT_CDB);
4398 ADD_INT(d, DB_INIT_LOCK);
4399 ADD_INT(d, DB_INIT_LOG);
4400 ADD_INT(d, DB_INIT_MPOOL);
4401 ADD_INT(d, DB_INIT_TXN);
4402#if (DBVER >= 32)
4403 ADD_INT(d, DB_JOINENV);
4404#endif
4405
4406 ADD_INT(d, DB_RECOVER);
4407 ADD_INT(d, DB_RECOVER_FATAL);
4408 ADD_INT(d, DB_TXN_NOSYNC);
4409 ADD_INT(d, DB_USE_ENVIRON);
4410 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4411
4412 ADD_INT(d, DB_LOCKDOWN);
4413 ADD_INT(d, DB_PRIVATE);
4414 ADD_INT(d, DB_SYSTEM_MEM);
4415
4416 ADD_INT(d, DB_TXN_SYNC);
4417 ADD_INT(d, DB_TXN_NOWAIT);
4418
4419 ADD_INT(d, DB_EXCL);
4420 ADD_INT(d, DB_FCNTL_LOCKING);
4421 ADD_INT(d, DB_ODDFILESIZE);
4422 ADD_INT(d, DB_RDWRMASTER);
4423 ADD_INT(d, DB_RDONLY);
4424 ADD_INT(d, DB_TRUNCATE);
4425#if (DBVER >= 32)
4426 ADD_INT(d, DB_EXTENT);
4427 ADD_INT(d, DB_CDB_ALLDB);
4428 ADD_INT(d, DB_VERIFY);
4429#endif
4430 ADD_INT(d, DB_UPGRADE);
4431
4432 ADD_INT(d, DB_AGGRESSIVE);
4433 ADD_INT(d, DB_NOORDERCHK);
4434 ADD_INT(d, DB_ORDERCHKONLY);
4435 ADD_INT(d, DB_PR_PAGE);
4436#if ! (DBVER >= 33)
4437 ADD_INT(d, DB_VRFY_FLAGMASK);
4438 ADD_INT(d, DB_PR_HEADERS);
4439#endif
4440 ADD_INT(d, DB_PR_RECOVERYTEST);
4441 ADD_INT(d, DB_SALVAGE);
4442
4443 ADD_INT(d, DB_LOCK_NORUN);
4444 ADD_INT(d, DB_LOCK_DEFAULT);
4445 ADD_INT(d, DB_LOCK_OLDEST);
4446 ADD_INT(d, DB_LOCK_RANDOM);
4447 ADD_INT(d, DB_LOCK_YOUNGEST);
4448#if (DBVER >= 33)
4449 ADD_INT(d, DB_LOCK_MAXLOCKS);
4450 ADD_INT(d, DB_LOCK_MINLOCKS);
4451 ADD_INT(d, DB_LOCK_MINWRITE);
4452#endif
4453
4454
4455#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004456 /* docs say to use zero instead */
4457 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004458#else
4459 ADD_INT(d, DB_LOCK_CONFLICT);
4460#endif
4461
4462 ADD_INT(d, DB_LOCK_DUMP);
4463 ADD_INT(d, DB_LOCK_GET);
4464 ADD_INT(d, DB_LOCK_INHERIT);
4465 ADD_INT(d, DB_LOCK_PUT);
4466 ADD_INT(d, DB_LOCK_PUT_ALL);
4467 ADD_INT(d, DB_LOCK_PUT_OBJ);
4468
4469 ADD_INT(d, DB_LOCK_NG);
4470 ADD_INT(d, DB_LOCK_READ);
4471 ADD_INT(d, DB_LOCK_WRITE);
4472 ADD_INT(d, DB_LOCK_NOWAIT);
4473#if (DBVER >= 32)
4474 ADD_INT(d, DB_LOCK_WAIT);
4475#endif
4476 ADD_INT(d, DB_LOCK_IWRITE);
4477 ADD_INT(d, DB_LOCK_IREAD);
4478 ADD_INT(d, DB_LOCK_IWR);
4479#if (DBVER >= 33)
4480 ADD_INT(d, DB_LOCK_DIRTY);
4481 ADD_INT(d, DB_LOCK_WWRITE);
4482#endif
4483
4484 ADD_INT(d, DB_LOCK_RECORD);
4485 ADD_INT(d, DB_LOCK_UPGRADE);
4486#if (DBVER >= 32)
4487 ADD_INT(d, DB_LOCK_SWITCH);
4488#endif
4489#if (DBVER >= 33)
4490 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4491#endif
4492
4493 ADD_INT(d, DB_LOCK_NOWAIT);
4494 ADD_INT(d, DB_LOCK_RECORD);
4495 ADD_INT(d, DB_LOCK_UPGRADE);
4496
4497#if (DBVER >= 33)
4498 ADD_INT(d, DB_LSTAT_ABORTED);
4499 ADD_INT(d, DB_LSTAT_ERR);
4500 ADD_INT(d, DB_LSTAT_FREE);
4501 ADD_INT(d, DB_LSTAT_HELD);
4502#if (DBVER == 33)
4503 ADD_INT(d, DB_LSTAT_NOGRANT);
4504#endif
4505 ADD_INT(d, DB_LSTAT_PENDING);
4506 ADD_INT(d, DB_LSTAT_WAITING);
4507#endif
4508
4509 ADD_INT(d, DB_ARCH_ABS);
4510 ADD_INT(d, DB_ARCH_DATA);
4511 ADD_INT(d, DB_ARCH_LOG);
4512
4513 ADD_INT(d, DB_BTREE);
4514 ADD_INT(d, DB_HASH);
4515 ADD_INT(d, DB_RECNO);
4516 ADD_INT(d, DB_QUEUE);
4517 ADD_INT(d, DB_UNKNOWN);
4518
4519 ADD_INT(d, DB_DUP);
4520 ADD_INT(d, DB_DUPSORT);
4521 ADD_INT(d, DB_RECNUM);
4522 ADD_INT(d, DB_RENUMBER);
4523 ADD_INT(d, DB_REVSPLITOFF);
4524 ADD_INT(d, DB_SNAPSHOT);
4525
4526 ADD_INT(d, DB_JOIN_NOSORT);
4527
4528 ADD_INT(d, DB_AFTER);
4529 ADD_INT(d, DB_APPEND);
4530 ADD_INT(d, DB_BEFORE);
4531 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004532#if (DBVER >= 41)
4533 _addIntToDict(d, "DB_CHECKPOINT", 0);
4534#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004535 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004536 ADD_INT(d, DB_CURLSN);
4537#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004538#if (DBVER >= 33)
4539 ADD_INT(d, DB_COMMIT);
4540#endif
4541 ADD_INT(d, DB_CONSUME);
4542#if (DBVER >= 32)
4543 ADD_INT(d, DB_CONSUME_WAIT);
4544#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004545 ADD_INT(d, DB_CURRENT);
4546#if (DBVER >= 33)
4547 ADD_INT(d, DB_FAST_STAT);
4548#endif
4549 ADD_INT(d, DB_FIRST);
4550 ADD_INT(d, DB_FLUSH);
4551 ADD_INT(d, DB_GET_BOTH);
4552 ADD_INT(d, DB_GET_RECNO);
4553 ADD_INT(d, DB_JOIN_ITEM);
4554 ADD_INT(d, DB_KEYFIRST);
4555 ADD_INT(d, DB_KEYLAST);
4556 ADD_INT(d, DB_LAST);
4557 ADD_INT(d, DB_NEXT);
4558 ADD_INT(d, DB_NEXT_DUP);
4559 ADD_INT(d, DB_NEXT_NODUP);
4560 ADD_INT(d, DB_NODUPDATA);
4561 ADD_INT(d, DB_NOOVERWRITE);
4562 ADD_INT(d, DB_NOSYNC);
4563 ADD_INT(d, DB_POSITION);
4564 ADD_INT(d, DB_PREV);
4565 ADD_INT(d, DB_PREV_NODUP);
4566 ADD_INT(d, DB_RECORDCOUNT);
4567 ADD_INT(d, DB_SET);
4568 ADD_INT(d, DB_SET_RANGE);
4569 ADD_INT(d, DB_SET_RECNO);
4570 ADD_INT(d, DB_WRITECURSOR);
4571
4572 ADD_INT(d, DB_OPFLAGS_MASK);
4573 ADD_INT(d, DB_RMW);
4574#if (DBVER >= 33)
4575 ADD_INT(d, DB_DIRTY_READ);
4576 ADD_INT(d, DB_MULTIPLE);
4577 ADD_INT(d, DB_MULTIPLE_KEY);
4578#endif
4579
4580#if (DBVER >= 33)
4581 ADD_INT(d, DB_DONOTINDEX);
4582#endif
4583
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004584#if (DBVER >= 41)
4585 _addIntToDict(d, "DB_INCOMPLETE", 0);
4586#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004587 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004588#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004589 ADD_INT(d, DB_KEYEMPTY);
4590 ADD_INT(d, DB_KEYEXIST);
4591 ADD_INT(d, DB_LOCK_DEADLOCK);
4592 ADD_INT(d, DB_LOCK_NOTGRANTED);
4593 ADD_INT(d, DB_NOSERVER);
4594 ADD_INT(d, DB_NOSERVER_HOME);
4595 ADD_INT(d, DB_NOSERVER_ID);
4596 ADD_INT(d, DB_NOTFOUND);
4597 ADD_INT(d, DB_OLD_VERSION);
4598 ADD_INT(d, DB_RUNRECOVERY);
4599 ADD_INT(d, DB_VERIFY_BAD);
4600#if (DBVER >= 33)
4601 ADD_INT(d, DB_PAGE_NOTFOUND);
4602 ADD_INT(d, DB_SECONDARY_BAD);
4603#endif
4604#if (DBVER >= 40)
4605 ADD_INT(d, DB_STAT_CLEAR);
4606 ADD_INT(d, DB_REGION_INIT);
4607 ADD_INT(d, DB_NOLOCKING);
4608 ADD_INT(d, DB_YIELDCPU);
4609 ADD_INT(d, DB_PANIC_ENVIRONMENT);
4610 ADD_INT(d, DB_NOPANIC);
4611#endif
4612
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004613#if (DBVER >= 41)
4614 ADD_INT(d, DB_ENCRYPT_AES);
4615 ADD_INT(d, DB_AUTO_COMMIT);
4616#else
4617 /* allow berkeleydb 4.1 aware apps to run on older versions */
4618 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
4619#endif
4620
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004621 ADD_INT(d, EINVAL);
4622 ADD_INT(d, EACCES);
4623 ADD_INT(d, ENOSPC);
4624 ADD_INT(d, ENOMEM);
4625 ADD_INT(d, EAGAIN);
4626 ADD_INT(d, EBUSY);
4627 ADD_INT(d, EEXIST);
4628 ADD_INT(d, ENOENT);
4629 ADD_INT(d, EPERM);
4630
Barry Warsaw1baa9822003-03-31 19:51:29 +00004631#if (DBVER >= 40)
4632 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
4633 ADD_INT(d, DB_SET_TXN_TIMEOUT);
4634#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004635
4636 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004637 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004638 PyDict_SetItemString(d, "DBError", DBError);
4639
4640 /* Some magic to make DBNotFoundError derive from both DBError and
4641 KeyError, since the API only supports using one base class. */
4642 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
4643 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
4644 Py_file_input, d, d);
4645 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
4646 PyDict_DelItemString(d, "KeyError");
4647
4648
4649 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004650#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004651 PyDict_SetItemString(d, #name, name)
4652
4653#if !INCOMPLETE_IS_WARNING
4654 MAKE_EX(DBIncompleteError);
4655#endif
4656 MAKE_EX(DBKeyEmptyError);
4657 MAKE_EX(DBKeyExistError);
4658 MAKE_EX(DBLockDeadlockError);
4659 MAKE_EX(DBLockNotGrantedError);
4660 MAKE_EX(DBOldVersionError);
4661 MAKE_EX(DBRunRecoveryError);
4662 MAKE_EX(DBVerifyBadError);
4663 MAKE_EX(DBNoServerError);
4664 MAKE_EX(DBNoServerHomeError);
4665 MAKE_EX(DBNoServerIDError);
4666#if (DBVER >= 33)
4667 MAKE_EX(DBPageNotFoundError);
4668 MAKE_EX(DBSecondaryBadError);
4669#endif
4670
4671 MAKE_EX(DBInvalidArgError);
4672 MAKE_EX(DBAccessError);
4673 MAKE_EX(DBNoSpaceError);
4674 MAKE_EX(DBNoMemoryError);
4675 MAKE_EX(DBAgainError);
4676 MAKE_EX(DBBusyError);
4677 MAKE_EX(DBFileExistsError);
4678 MAKE_EX(DBNoSuchFileError);
4679 MAKE_EX(DBPermissionsError);
4680
4681#undef MAKE_EX
4682
4683 /* Check for errors */
4684 if (PyErr_Occurred()) {
4685 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004686 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004687 }
4688}