blob: 990c89f215bd170e3a369e71a07012482a606afc [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*
3280DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3281{
3282 int err, gbytes=0, bytes=0, ncache=0;
3283
3284 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3285 &gbytes, &bytes, &ncache))
3286 return NULL;
3287 CHECK_ENV_NOT_CLOSED(self);
3288
3289 MYDB_BEGIN_ALLOW_THREADS;
3290 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3291 MYDB_END_ALLOW_THREADS;
3292 RETURN_IF_ERR();
3293 RETURN_NONE();
3294}
3295
3296
3297#if (DBVER >= 32)
3298static PyObject*
3299DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3300{
3301 int err, flags=0, onoff=0;
3302
3303 if (!PyArg_ParseTuple(args, "ii:set_flags",
3304 &flags, &onoff))
3305 return NULL;
3306 CHECK_ENV_NOT_CLOSED(self);
3307
3308 MYDB_BEGIN_ALLOW_THREADS;
3309 err = self->db_env->set_flags(self->db_env, flags, onoff);
3310 MYDB_END_ALLOW_THREADS;
3311 RETURN_IF_ERR();
3312 RETURN_NONE();
3313}
3314#endif
3315
3316
3317static PyObject*
3318DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3319{
3320 int err;
3321 char *dir;
3322
3323 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3324 return NULL;
3325 CHECK_ENV_NOT_CLOSED(self);
3326
3327 MYDB_BEGIN_ALLOW_THREADS;
3328 err = self->db_env->set_data_dir(self->db_env, dir);
3329 MYDB_END_ALLOW_THREADS;
3330 RETURN_IF_ERR();
3331 RETURN_NONE();
3332}
3333
3334
3335static PyObject*
3336DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3337{
3338 int err, lg_bsize;
3339
3340 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3341 return NULL;
3342 CHECK_ENV_NOT_CLOSED(self);
3343
3344 MYDB_BEGIN_ALLOW_THREADS;
3345 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3346 MYDB_END_ALLOW_THREADS;
3347 RETURN_IF_ERR();
3348 RETURN_NONE();
3349}
3350
3351
3352static PyObject*
3353DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3354{
3355 int err;
3356 char *dir;
3357
3358 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3359 return NULL;
3360 CHECK_ENV_NOT_CLOSED(self);
3361
3362 MYDB_BEGIN_ALLOW_THREADS;
3363 err = self->db_env->set_lg_dir(self->db_env, dir);
3364 MYDB_END_ALLOW_THREADS;
3365 RETURN_IF_ERR();
3366 RETURN_NONE();
3367}
3368
3369static PyObject*
3370DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3371{
3372 int err, lg_max;
3373
3374 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3375 return NULL;
3376 CHECK_ENV_NOT_CLOSED(self);
3377
3378 MYDB_BEGIN_ALLOW_THREADS;
3379 err = self->db_env->set_lg_max(self->db_env, lg_max);
3380 MYDB_END_ALLOW_THREADS;
3381 RETURN_IF_ERR();
3382 RETURN_NONE();
3383}
3384
3385
3386static PyObject*
3387DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3388{
3389 int err, lk_detect;
3390
3391 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3392 return NULL;
3393 CHECK_ENV_NOT_CLOSED(self);
3394
3395 MYDB_BEGIN_ALLOW_THREADS;
3396 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3397 MYDB_END_ALLOW_THREADS;
3398 RETURN_IF_ERR();
3399 RETURN_NONE();
3400}
3401
3402
3403static PyObject*
3404DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3405{
3406 int err, max;
3407
3408 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3409 return NULL;
3410 CHECK_ENV_NOT_CLOSED(self);
3411
3412 MYDB_BEGIN_ALLOW_THREADS;
3413 err = self->db_env->set_lk_max(self->db_env, max);
3414 MYDB_END_ALLOW_THREADS;
3415 RETURN_IF_ERR();
3416 RETURN_NONE();
3417}
3418
3419
3420#if (DBVER >= 32)
3421
3422static PyObject*
3423DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3424{
3425 int err, max;
3426
3427 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3428 return NULL;
3429 CHECK_ENV_NOT_CLOSED(self);
3430
3431 MYDB_BEGIN_ALLOW_THREADS;
3432 err = self->db_env->set_lk_max_locks(self->db_env, max);
3433 MYDB_END_ALLOW_THREADS;
3434 RETURN_IF_ERR();
3435 RETURN_NONE();
3436}
3437
3438
3439static PyObject*
3440DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3441{
3442 int err, max;
3443
3444 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3445 return NULL;
3446 CHECK_ENV_NOT_CLOSED(self);
3447
3448 MYDB_BEGIN_ALLOW_THREADS;
3449 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3450 MYDB_END_ALLOW_THREADS;
3451 RETURN_IF_ERR();
3452 RETURN_NONE();
3453}
3454
3455
3456static PyObject*
3457DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3458{
3459 int err, max;
3460
3461 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3462 return NULL;
3463 CHECK_ENV_NOT_CLOSED(self);
3464
3465 MYDB_BEGIN_ALLOW_THREADS;
3466 err = self->db_env->set_lk_max_objects(self->db_env, max);
3467 MYDB_END_ALLOW_THREADS;
3468 RETURN_IF_ERR();
3469 RETURN_NONE();
3470}
3471
3472#endif
3473
3474
3475static PyObject*
3476DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3477{
3478 int err, mp_mmapsize;
3479
3480 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3481 return NULL;
3482 CHECK_ENV_NOT_CLOSED(self);
3483
3484 MYDB_BEGIN_ALLOW_THREADS;
3485 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3486 MYDB_END_ALLOW_THREADS;
3487 RETURN_IF_ERR();
3488 RETURN_NONE();
3489}
3490
3491
3492static PyObject*
3493DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3494{
3495 int err;
3496 char *dir;
3497
3498 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3499 return NULL;
3500 CHECK_ENV_NOT_CLOSED(self);
3501
3502 MYDB_BEGIN_ALLOW_THREADS;
3503 err = self->db_env->set_tmp_dir(self->db_env, dir);
3504 MYDB_END_ALLOW_THREADS;
3505 RETURN_IF_ERR();
3506 RETURN_NONE();
3507}
3508
3509
3510static PyObject*
3511DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3512{
3513 int flags = 0;
3514 PyObject* txnobj = NULL;
3515 DB_TXN *txn = NULL;
3516 char* kwnames[] = { "parent", "flags", NULL };
3517
3518 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3519 &txnobj, &flags))
3520 return NULL;
3521
3522 if (!checkTxnObj(txnobj, &txn))
3523 return NULL;
3524 CHECK_ENV_NOT_CLOSED(self);
3525
3526 return (PyObject*)newDBTxnObject(self, txn, flags);
3527}
3528
3529
3530static PyObject*
3531DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3532{
3533 int err, kbyte=0, min=0, flags=0;
3534
3535 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3536 return NULL;
3537 CHECK_ENV_NOT_CLOSED(self);
3538
3539 MYDB_BEGIN_ALLOW_THREADS;
3540#if (DBVER >= 40)
3541 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3542#else
3543 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3544#endif
3545 MYDB_END_ALLOW_THREADS;
3546 RETURN_IF_ERR();
3547 RETURN_NONE();
3548}
3549
3550
3551static PyObject*
3552DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3553{
3554 int err, max;
3555
3556 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3557 return NULL;
3558 CHECK_ENV_NOT_CLOSED(self);
3559
3560 MYDB_BEGIN_ALLOW_THREADS;
3561 err = self->db_env->set_tx_max(self->db_env, max);
3562 MYDB_END_ALLOW_THREADS;
3563 RETURN_IF_ERR();
3564 RETURN_NONE();
3565}
3566
3567
3568static PyObject*
3569DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3570{
3571 int err, atype, flags=0;
3572 int aborted = 0;
3573
3574 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3575 return NULL;
3576 CHECK_ENV_NOT_CLOSED(self);
3577
3578 MYDB_BEGIN_ALLOW_THREADS;
3579#if (DBVER >= 40)
3580 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3581#else
3582 err = lock_detect(self->db_env, flags, atype, &aborted);
3583#endif
3584 MYDB_END_ALLOW_THREADS;
3585 RETURN_IF_ERR();
3586 return PyInt_FromLong(aborted);
3587}
3588
3589
3590static PyObject*
3591DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3592{
3593 int flags=0;
3594 int locker, lock_mode;
3595 DBT obj;
3596 PyObject* objobj;
3597
3598 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3599 return NULL;
3600
3601
3602 if (!make_dbt(objobj, &obj))
3603 return NULL;
3604
3605 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3606}
3607
3608
3609static PyObject*
3610DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3611{
3612 int err;
3613 u_int32_t theID;
3614
3615 if (!PyArg_ParseTuple(args, ":lock_id"))
3616 return NULL;
3617
3618 CHECK_ENV_NOT_CLOSED(self);
3619 MYDB_BEGIN_ALLOW_THREADS;
3620#if (DBVER >= 40)
3621 err = self->db_env->lock_id(self->db_env, &theID);
3622#else
3623 err = lock_id(self->db_env, &theID);
3624#endif
3625 MYDB_END_ALLOW_THREADS;
3626 RETURN_IF_ERR();
3627
3628 return PyInt_FromLong((long)theID);
3629}
3630
3631
3632static PyObject*
3633DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3634{
3635 int err;
3636 DBLockObject* dblockobj;
3637
3638 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3639 return NULL;
3640
3641 CHECK_ENV_NOT_CLOSED(self);
3642 MYDB_BEGIN_ALLOW_THREADS;
3643#if (DBVER >= 40)
3644 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3645#else
3646 err = lock_put(self->db_env, &dblockobj->lock);
3647#endif
3648 MYDB_END_ALLOW_THREADS;
3649 RETURN_IF_ERR();
3650 RETURN_NONE();
3651}
3652
3653
3654static PyObject*
3655DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
3656{
3657 int err;
3658 DB_LOCK_STAT* sp;
3659 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003660 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003661
3662 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
3663 return NULL;
3664 CHECK_ENV_NOT_CLOSED(self);
3665
3666 MYDB_BEGIN_ALLOW_THREADS;
3667#if (DBVER >= 40)
3668 err = self->db_env->lock_stat(self->db_env, &sp, flags);
3669#else
3670#if (DBVER >= 33)
3671 err = lock_stat(self->db_env, &sp);
3672#else
3673 err = lock_stat(self->db_env, &sp, NULL);
3674#endif
3675#endif
3676 MYDB_END_ALLOW_THREADS;
3677 RETURN_IF_ERR();
3678
3679 /* Turn the stat structure into a dictionary */
3680 d = PyDict_New();
3681 if (d == NULL) {
3682 free(sp);
3683 return NULL;
3684 }
3685
3686#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3687
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003688#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003689 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003690#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003691 MAKE_ENTRY(nmodes);
3692#if (DBVER >= 32)
3693 MAKE_ENTRY(maxlocks);
3694 MAKE_ENTRY(maxlockers);
3695 MAKE_ENTRY(maxobjects);
3696 MAKE_ENTRY(nlocks);
3697 MAKE_ENTRY(maxnlocks);
3698#endif
3699 MAKE_ENTRY(nlockers);
3700 MAKE_ENTRY(maxnlockers);
3701#if (DBVER >= 32)
3702 MAKE_ENTRY(nobjects);
3703 MAKE_ENTRY(maxnobjects);
3704#endif
3705 MAKE_ENTRY(nrequests);
3706 MAKE_ENTRY(nreleases);
3707 MAKE_ENTRY(nnowaits);
3708 MAKE_ENTRY(nconflicts);
3709 MAKE_ENTRY(ndeadlocks);
3710 MAKE_ENTRY(regsize);
3711 MAKE_ENTRY(region_wait);
3712 MAKE_ENTRY(region_nowait);
3713
3714#undef MAKE_ENTRY
3715 free(sp);
3716 return d;
3717}
3718
3719
3720static PyObject*
3721DBEnv_log_archive(DBEnvObject* self, PyObject* args)
3722{
3723 int flags=0;
3724 int err;
3725 char **log_list_start, **log_list;
3726 PyObject* list;
3727 PyObject* item = NULL;
3728
3729 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
3730 return NULL;
3731
3732 CHECK_ENV_NOT_CLOSED(self);
3733 MYDB_BEGIN_ALLOW_THREADS;
3734#if (DBVER >= 40)
3735 err = self->db_env->log_archive(self->db_env, &log_list, flags);
3736#elif (DBVER == 33)
3737 err = log_archive(self->db_env, &log_list, flags);
3738#else
3739 err = log_archive(self->db_env, &log_list, flags, NULL);
3740#endif
3741 MYDB_END_ALLOW_THREADS;
3742 RETURN_IF_ERR();
3743
3744 list = PyList_New(0);
3745 if (list == NULL) {
3746 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
3747 return NULL;
3748 }
3749
3750 if (log_list) {
3751 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
3752 item = PyString_FromString (*log_list);
3753 if (item == NULL) {
3754 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003755 PyErr_SetString(PyExc_MemoryError,
3756 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003757 list = NULL;
3758 break;
3759 }
3760 PyList_Append(list, item);
3761 Py_DECREF(item);
3762 }
3763 free(log_list_start);
3764 }
3765 return list;
3766}
3767
3768
3769static PyObject*
3770DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
3771{
3772 int err;
3773 DB_TXN_STAT* sp;
3774 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003775 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003776
3777 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
3778 return NULL;
3779 CHECK_ENV_NOT_CLOSED(self);
3780
3781 MYDB_BEGIN_ALLOW_THREADS;
3782#if (DBVER >= 40)
3783 err = self->db_env->txn_stat(self->db_env, &sp, flags);
3784#elif (DBVER == 33)
3785 err = txn_stat(self->db_env, &sp);
3786#else
3787 err = txn_stat(self->db_env, &sp, NULL);
3788#endif
3789 MYDB_END_ALLOW_THREADS;
3790 RETURN_IF_ERR();
3791
3792 /* Turn the stat structure into a dictionary */
3793 d = PyDict_New();
3794 if (d == NULL) {
3795 free(sp);
3796 return NULL;
3797 }
3798
3799#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3800
3801 MAKE_ENTRY(time_ckp);
3802 MAKE_ENTRY(last_txnid);
3803 MAKE_ENTRY(maxtxns);
3804 MAKE_ENTRY(nactive);
3805 MAKE_ENTRY(maxnactive);
3806 MAKE_ENTRY(nbegins);
3807 MAKE_ENTRY(naborts);
3808 MAKE_ENTRY(ncommits);
3809 MAKE_ENTRY(regsize);
3810 MAKE_ENTRY(region_wait);
3811 MAKE_ENTRY(region_nowait);
3812
3813#undef MAKE_ENTRY
3814 free(sp);
3815 return d;
3816}
3817
3818
3819static PyObject*
3820DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
3821{
3822 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003823 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003824
3825 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
3826 return NULL;
3827 CHECK_ENV_NOT_CLOSED(self);
3828
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003829 if (self->moduleFlags.getReturnsNone)
3830 ++oldValue;
3831 if (self->moduleFlags.cursorSetReturnsNone)
3832 ++oldValue;
3833 self->moduleFlags.getReturnsNone = (flags >= 1);
3834 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003835 return PyInt_FromLong(oldValue);
3836}
3837
3838
3839/* --------------------------------------------------------------------- */
3840/* DBTxn methods */
3841
3842
3843static PyObject*
3844DBTxn_commit(DBTxnObject* self, PyObject* args)
3845{
3846 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003847 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003848
3849 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
3850 return NULL;
3851
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003852 if (!self->txn) {
3853 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3854 "DBTxn must not be used after txn_commit or txn_abort"));
3855 return NULL;
3856 }
3857 txn = self->txn;
3858 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003859 MYDB_BEGIN_ALLOW_THREADS;
3860#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003861 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003862#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003863 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003864#endif
3865 MYDB_END_ALLOW_THREADS;
3866 RETURN_IF_ERR();
3867 RETURN_NONE();
3868}
3869
3870static PyObject*
3871DBTxn_prepare(DBTxnObject* self, PyObject* args)
3872{
3873#if (DBVER >= 33)
3874 int err;
3875 char* gid=NULL;
3876 int gid_size=0;
3877
3878 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
3879 return NULL;
3880
3881 if (gid_size != DB_XIDDATASIZE) {
3882 PyErr_SetString(PyExc_TypeError,
3883 "gid must be DB_XIDDATASIZE bytes long");
3884 return NULL;
3885 }
3886
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003887 if (!self->txn) {
3888 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3889 "DBTxn must not be used after txn_commit or txn_abort"));
3890 return NULL;
3891 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003892 MYDB_BEGIN_ALLOW_THREADS;
3893#if (DBVER >= 40)
3894 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
3895#else
3896 err = txn_prepare(self->txn, (u_int8_t*)gid);
3897#endif
3898 MYDB_END_ALLOW_THREADS;
3899 RETURN_IF_ERR();
3900 RETURN_NONE();
3901#else
3902 int err;
3903
3904 if (!PyArg_ParseTuple(args, ":prepare"))
3905 return NULL;
3906
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003907 if (!self->txn) {
3908 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3909 "DBTxn must not be used after txn_commit or txn_abort"));
3910 return NULL;
3911 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003912 MYDB_BEGIN_ALLOW_THREADS;
3913 err = txn_prepare(self->txn);
3914 MYDB_END_ALLOW_THREADS;
3915 RETURN_IF_ERR();
3916 RETURN_NONE();
3917#endif
3918}
3919
3920
3921static PyObject*
3922DBTxn_abort(DBTxnObject* self, PyObject* args)
3923{
3924 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003925 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003926
3927 if (!PyArg_ParseTuple(args, ":abort"))
3928 return NULL;
3929
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003930 if (!self->txn) {
3931 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3932 "DBTxn must not be used after txn_commit or txn_abort"));
3933 return NULL;
3934 }
3935 txn = self->txn;
3936 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003937 MYDB_BEGIN_ALLOW_THREADS;
3938#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003939 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003940#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003941 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003942#endif
3943 MYDB_END_ALLOW_THREADS;
3944 RETURN_IF_ERR();
3945 RETURN_NONE();
3946}
3947
3948
3949static PyObject*
3950DBTxn_id(DBTxnObject* self, PyObject* args)
3951{
3952 int id;
3953
3954 if (!PyArg_ParseTuple(args, ":id"))
3955 return NULL;
3956
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003957 if (!self->txn) {
3958 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3959 "DBTxn must not be used after txn_commit or txn_abort"));
3960 return NULL;
3961 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003962 MYDB_BEGIN_ALLOW_THREADS;
3963#if (DBVER >= 40)
3964 id = self->txn->id(self->txn);
3965#else
3966 id = txn_id(self->txn);
3967#endif
3968 MYDB_END_ALLOW_THREADS;
3969 return PyInt_FromLong(id);
3970}
3971
3972/* --------------------------------------------------------------------- */
3973/* Method definition tables and type objects */
3974
3975static PyMethodDef DB_methods[] = {
3976 {"append", (PyCFunction)DB_append, METH_VARARGS},
3977#if (DBVER >= 33)
3978 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
3979#endif
3980 {"close", (PyCFunction)DB_close, METH_VARARGS},
3981#if (DBVER >= 32)
3982 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
3983 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
3984#endif
3985 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
3986 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
3987 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
3988 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
3989 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
3990 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
3991 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
3992 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
3993 {"join", (PyCFunction)DB_join, METH_VARARGS},
3994 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
3995 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
3996 {"items", (PyCFunction)DB_items, METH_VARARGS},
3997 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
3998 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
3999 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4000 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4001 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4002 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4003 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004004#if (DBVER >= 41)
4005 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4006#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004007 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4008 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4009 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4010 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4011 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4012 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4013 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4014 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4015 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4016#if (DBVER >= 32)
4017 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4018#endif
4019 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4020 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4021#if (DBVER >= 33)
4022 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4023#endif
4024 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4025 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4026 {"values", (PyCFunction)DB_values, METH_VARARGS},
4027 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4028 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4029 {NULL, NULL} /* sentinel */
4030};
4031
4032
4033static PyMappingMethods DB_mapping = {
4034 (inquiry)DB_length, /*mp_length*/
4035 (binaryfunc)DB_subscript, /*mp_subscript*/
4036 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4037};
4038
4039
4040static PyMethodDef DBCursor_methods[] = {
4041 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4042 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4043 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4044 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4045 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4046 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4047 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4048 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4049 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4050 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4051 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4052 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4053 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4054 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4055 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004056 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004057 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4058 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4059 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4060 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4061 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4062 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4063 {NULL, NULL} /* sentinel */
4064};
4065
4066
4067static PyMethodDef DBEnv_methods[] = {
4068 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4069 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4070 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004071#if (DBVER >= 41)
4072 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4073 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4074 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4075#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004076#if (DBVER >= 40)
4077 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4078#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004079 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4080 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4081#if (DBVER >= 32)
4082 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4083#endif
4084 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4085 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4086 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4087 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4088 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4089#if (DBVER >= 32)
4090 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4091 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4092 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4093#endif
4094 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4095 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4096 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4097 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4098 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4099 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4100 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4101 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4102 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4103 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4104 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4105 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4106 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4107 {NULL, NULL} /* sentinel */
4108};
4109
4110
4111static PyMethodDef DBTxn_methods[] = {
4112 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4113 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4114 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4115 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4116 {NULL, NULL} /* sentinel */
4117};
4118
4119
4120static PyObject*
4121DB_getattr(DBObject* self, char *name)
4122{
4123 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4124}
4125
4126
4127static PyObject*
4128DBEnv_getattr(DBEnvObject* self, char *name)
4129{
4130 if (!strcmp(name, "db_home")) {
4131 CHECK_ENV_NOT_CLOSED(self);
4132 if (self->db_env->db_home == NULL) {
4133 RETURN_NONE();
4134 }
4135 return PyString_FromString(self->db_env->db_home);
4136 }
4137
4138 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4139}
4140
4141
4142static PyObject*
4143DBCursor_getattr(DBCursorObject* self, char *name)
4144{
4145 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4146}
4147
4148static PyObject*
4149DBTxn_getattr(DBTxnObject* self, char *name)
4150{
4151 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4152}
4153
4154static PyObject*
4155DBLock_getattr(DBLockObject* self, char *name)
4156{
4157 return NULL;
4158}
4159
4160statichere PyTypeObject DB_Type = {
4161 PyObject_HEAD_INIT(NULL)
4162 0, /*ob_size*/
4163 "DB", /*tp_name*/
4164 sizeof(DBObject), /*tp_basicsize*/
4165 0, /*tp_itemsize*/
4166 /* methods */
4167 (destructor)DB_dealloc, /*tp_dealloc*/
4168 0, /*tp_print*/
4169 (getattrfunc)DB_getattr, /*tp_getattr*/
4170 0, /*tp_setattr*/
4171 0, /*tp_compare*/
4172 0, /*tp_repr*/
4173 0, /*tp_as_number*/
4174 0, /*tp_as_sequence*/
4175 &DB_mapping,/*tp_as_mapping*/
4176 0, /*tp_hash*/
4177};
4178
4179
4180statichere PyTypeObject DBCursor_Type = {
4181 PyObject_HEAD_INIT(NULL)
4182 0, /*ob_size*/
4183 "DBCursor", /*tp_name*/
4184 sizeof(DBCursorObject), /*tp_basicsize*/
4185 0, /*tp_itemsize*/
4186 /* methods */
4187 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4188 0, /*tp_print*/
4189 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4190 0, /*tp_setattr*/
4191 0, /*tp_compare*/
4192 0, /*tp_repr*/
4193 0, /*tp_as_number*/
4194 0, /*tp_as_sequence*/
4195 0, /*tp_as_mapping*/
4196 0, /*tp_hash*/
4197};
4198
4199
4200statichere PyTypeObject DBEnv_Type = {
4201 PyObject_HEAD_INIT(NULL)
4202 0, /*ob_size*/
4203 "DBEnv", /*tp_name*/
4204 sizeof(DBEnvObject), /*tp_basicsize*/
4205 0, /*tp_itemsize*/
4206 /* methods */
4207 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4208 0, /*tp_print*/
4209 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4210 0, /*tp_setattr*/
4211 0, /*tp_compare*/
4212 0, /*tp_repr*/
4213 0, /*tp_as_number*/
4214 0, /*tp_as_sequence*/
4215 0, /*tp_as_mapping*/
4216 0, /*tp_hash*/
4217};
4218
4219statichere PyTypeObject DBTxn_Type = {
4220 PyObject_HEAD_INIT(NULL)
4221 0, /*ob_size*/
4222 "DBTxn", /*tp_name*/
4223 sizeof(DBTxnObject), /*tp_basicsize*/
4224 0, /*tp_itemsize*/
4225 /* methods */
4226 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4227 0, /*tp_print*/
4228 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4229 0, /*tp_setattr*/
4230 0, /*tp_compare*/
4231 0, /*tp_repr*/
4232 0, /*tp_as_number*/
4233 0, /*tp_as_sequence*/
4234 0, /*tp_as_mapping*/
4235 0, /*tp_hash*/
4236};
4237
4238
4239statichere PyTypeObject DBLock_Type = {
4240 PyObject_HEAD_INIT(NULL)
4241 0, /*ob_size*/
4242 "DBLock", /*tp_name*/
4243 sizeof(DBLockObject), /*tp_basicsize*/
4244 0, /*tp_itemsize*/
4245 /* methods */
4246 (destructor)DBLock_dealloc, /*tp_dealloc*/
4247 0, /*tp_print*/
4248 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4249 0, /*tp_setattr*/
4250 0, /*tp_compare*/
4251 0, /*tp_repr*/
4252 0, /*tp_as_number*/
4253 0, /*tp_as_sequence*/
4254 0, /*tp_as_mapping*/
4255 0, /*tp_hash*/
4256};
4257
4258
4259/* --------------------------------------------------------------------- */
4260/* Module-level functions */
4261
4262static PyObject*
4263DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4264{
4265 PyObject* dbenvobj = NULL;
4266 int flags = 0;
4267 char* kwnames[] = { "dbEnv", "flags", NULL};
4268
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004269 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4270 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004271 return NULL;
4272 if (dbenvobj == Py_None)
4273 dbenvobj = NULL;
4274 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4275 makeTypeError("DBEnv", dbenvobj);
4276 return NULL;
4277 }
4278
4279 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4280}
4281
4282
4283static PyObject*
4284DBEnv_construct(PyObject* self, PyObject* args)
4285{
4286 int flags = 0;
4287 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4288 return (PyObject* )newDBEnvObject(flags);
4289}
4290
4291
4292static char bsddb_version_doc[] =
4293"Returns a tuple of major, minor, and patch release numbers of the\n\
4294underlying DB library.";
4295
4296static PyObject*
4297bsddb_version(PyObject* self, PyObject* args)
4298{
4299 int major, minor, patch;
4300
4301 if (!PyArg_ParseTuple(args, ":version"))
4302 return NULL;
4303 db_version(&major, &minor, &patch);
4304 return Py_BuildValue("(iii)", major, minor, patch);
4305}
4306
4307
4308/* List of functions defined in the module */
4309
4310static PyMethodDef bsddb_methods[] = {
4311 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4312 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4313 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4314 {NULL, NULL} /* sentinel */
4315};
4316
4317
4318/* --------------------------------------------------------------------- */
4319/* Module initialization */
4320
4321
4322/* Convenience routine to export an integer value.
4323 * Errors are silently ignored, for better or for worse...
4324 */
4325#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4326
4327
4328
4329DL_EXPORT(void) init_bsddb(void)
4330{
4331 PyObject* m;
4332 PyObject* d;
4333 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4334 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4335 PyObject* cvsid_s = PyString_FromString( rcs_id );
4336
4337 /* Initialize the type of the new type objects here; doing it here
4338 is required for portability to Windows without requiring C++. */
4339 DB_Type.ob_type = &PyType_Type;
4340 DBCursor_Type.ob_type = &PyType_Type;
4341 DBEnv_Type.ob_type = &PyType_Type;
4342 DBTxn_Type.ob_type = &PyType_Type;
4343 DBLock_Type.ob_type = &PyType_Type;
4344
4345
Mark Hammonda69d4092003-04-22 23:13:27 +00004346#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004347 /* Save the current interpreter, so callbacks can do the right thing. */
4348 _db_interpreterState = PyThreadState_Get()->interp;
4349#endif
4350
4351 /* Create the module and add the functions */
4352 m = Py_InitModule("_bsddb", bsddb_methods);
4353
4354 /* Add some symbolic constants to the module */
4355 d = PyModule_GetDict(m);
4356 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4357 PyDict_SetItemString(d, "cvsid", cvsid_s);
4358 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4359 Py_DECREF(pybsddb_version_s);
4360 pybsddb_version_s = NULL;
4361 Py_DECREF(cvsid_s);
4362 cvsid_s = NULL;
4363 Py_DECREF(db_version_s);
4364 db_version_s = NULL;
4365
4366 ADD_INT(d, DB_VERSION_MAJOR);
4367 ADD_INT(d, DB_VERSION_MINOR);
4368 ADD_INT(d, DB_VERSION_PATCH);
4369
4370 ADD_INT(d, DB_MAX_PAGES);
4371 ADD_INT(d, DB_MAX_RECORDS);
4372
4373 ADD_INT(d, DB_CLIENT);
4374 ADD_INT(d, DB_XA_CREATE);
4375
4376 ADD_INT(d, DB_CREATE);
4377 ADD_INT(d, DB_NOMMAP);
4378 ADD_INT(d, DB_THREAD);
4379
4380 ADD_INT(d, DB_FORCE);
4381 ADD_INT(d, DB_INIT_CDB);
4382 ADD_INT(d, DB_INIT_LOCK);
4383 ADD_INT(d, DB_INIT_LOG);
4384 ADD_INT(d, DB_INIT_MPOOL);
4385 ADD_INT(d, DB_INIT_TXN);
4386#if (DBVER >= 32)
4387 ADD_INT(d, DB_JOINENV);
4388#endif
4389
4390 ADD_INT(d, DB_RECOVER);
4391 ADD_INT(d, DB_RECOVER_FATAL);
4392 ADD_INT(d, DB_TXN_NOSYNC);
4393 ADD_INT(d, DB_USE_ENVIRON);
4394 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4395
4396 ADD_INT(d, DB_LOCKDOWN);
4397 ADD_INT(d, DB_PRIVATE);
4398 ADD_INT(d, DB_SYSTEM_MEM);
4399
4400 ADD_INT(d, DB_TXN_SYNC);
4401 ADD_INT(d, DB_TXN_NOWAIT);
4402
4403 ADD_INT(d, DB_EXCL);
4404 ADD_INT(d, DB_FCNTL_LOCKING);
4405 ADD_INT(d, DB_ODDFILESIZE);
4406 ADD_INT(d, DB_RDWRMASTER);
4407 ADD_INT(d, DB_RDONLY);
4408 ADD_INT(d, DB_TRUNCATE);
4409#if (DBVER >= 32)
4410 ADD_INT(d, DB_EXTENT);
4411 ADD_INT(d, DB_CDB_ALLDB);
4412 ADD_INT(d, DB_VERIFY);
4413#endif
4414 ADD_INT(d, DB_UPGRADE);
4415
4416 ADD_INT(d, DB_AGGRESSIVE);
4417 ADD_INT(d, DB_NOORDERCHK);
4418 ADD_INT(d, DB_ORDERCHKONLY);
4419 ADD_INT(d, DB_PR_PAGE);
4420#if ! (DBVER >= 33)
4421 ADD_INT(d, DB_VRFY_FLAGMASK);
4422 ADD_INT(d, DB_PR_HEADERS);
4423#endif
4424 ADD_INT(d, DB_PR_RECOVERYTEST);
4425 ADD_INT(d, DB_SALVAGE);
4426
4427 ADD_INT(d, DB_LOCK_NORUN);
4428 ADD_INT(d, DB_LOCK_DEFAULT);
4429 ADD_INT(d, DB_LOCK_OLDEST);
4430 ADD_INT(d, DB_LOCK_RANDOM);
4431 ADD_INT(d, DB_LOCK_YOUNGEST);
4432#if (DBVER >= 33)
4433 ADD_INT(d, DB_LOCK_MAXLOCKS);
4434 ADD_INT(d, DB_LOCK_MINLOCKS);
4435 ADD_INT(d, DB_LOCK_MINWRITE);
4436#endif
4437
4438
4439#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004440 /* docs say to use zero instead */
4441 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004442#else
4443 ADD_INT(d, DB_LOCK_CONFLICT);
4444#endif
4445
4446 ADD_INT(d, DB_LOCK_DUMP);
4447 ADD_INT(d, DB_LOCK_GET);
4448 ADD_INT(d, DB_LOCK_INHERIT);
4449 ADD_INT(d, DB_LOCK_PUT);
4450 ADD_INT(d, DB_LOCK_PUT_ALL);
4451 ADD_INT(d, DB_LOCK_PUT_OBJ);
4452
4453 ADD_INT(d, DB_LOCK_NG);
4454 ADD_INT(d, DB_LOCK_READ);
4455 ADD_INT(d, DB_LOCK_WRITE);
4456 ADD_INT(d, DB_LOCK_NOWAIT);
4457#if (DBVER >= 32)
4458 ADD_INT(d, DB_LOCK_WAIT);
4459#endif
4460 ADD_INT(d, DB_LOCK_IWRITE);
4461 ADD_INT(d, DB_LOCK_IREAD);
4462 ADD_INT(d, DB_LOCK_IWR);
4463#if (DBVER >= 33)
4464 ADD_INT(d, DB_LOCK_DIRTY);
4465 ADD_INT(d, DB_LOCK_WWRITE);
4466#endif
4467
4468 ADD_INT(d, DB_LOCK_RECORD);
4469 ADD_INT(d, DB_LOCK_UPGRADE);
4470#if (DBVER >= 32)
4471 ADD_INT(d, DB_LOCK_SWITCH);
4472#endif
4473#if (DBVER >= 33)
4474 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4475#endif
4476
4477 ADD_INT(d, DB_LOCK_NOWAIT);
4478 ADD_INT(d, DB_LOCK_RECORD);
4479 ADD_INT(d, DB_LOCK_UPGRADE);
4480
4481#if (DBVER >= 33)
4482 ADD_INT(d, DB_LSTAT_ABORTED);
4483 ADD_INT(d, DB_LSTAT_ERR);
4484 ADD_INT(d, DB_LSTAT_FREE);
4485 ADD_INT(d, DB_LSTAT_HELD);
4486#if (DBVER == 33)
4487 ADD_INT(d, DB_LSTAT_NOGRANT);
4488#endif
4489 ADD_INT(d, DB_LSTAT_PENDING);
4490 ADD_INT(d, DB_LSTAT_WAITING);
4491#endif
4492
4493 ADD_INT(d, DB_ARCH_ABS);
4494 ADD_INT(d, DB_ARCH_DATA);
4495 ADD_INT(d, DB_ARCH_LOG);
4496
4497 ADD_INT(d, DB_BTREE);
4498 ADD_INT(d, DB_HASH);
4499 ADD_INT(d, DB_RECNO);
4500 ADD_INT(d, DB_QUEUE);
4501 ADD_INT(d, DB_UNKNOWN);
4502
4503 ADD_INT(d, DB_DUP);
4504 ADD_INT(d, DB_DUPSORT);
4505 ADD_INT(d, DB_RECNUM);
4506 ADD_INT(d, DB_RENUMBER);
4507 ADD_INT(d, DB_REVSPLITOFF);
4508 ADD_INT(d, DB_SNAPSHOT);
4509
4510 ADD_INT(d, DB_JOIN_NOSORT);
4511
4512 ADD_INT(d, DB_AFTER);
4513 ADD_INT(d, DB_APPEND);
4514 ADD_INT(d, DB_BEFORE);
4515 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004516#if (DBVER >= 41)
4517 _addIntToDict(d, "DB_CHECKPOINT", 0);
4518#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004519 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004520 ADD_INT(d, DB_CURLSN);
4521#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004522#if (DBVER >= 33)
4523 ADD_INT(d, DB_COMMIT);
4524#endif
4525 ADD_INT(d, DB_CONSUME);
4526#if (DBVER >= 32)
4527 ADD_INT(d, DB_CONSUME_WAIT);
4528#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004529 ADD_INT(d, DB_CURRENT);
4530#if (DBVER >= 33)
4531 ADD_INT(d, DB_FAST_STAT);
4532#endif
4533 ADD_INT(d, DB_FIRST);
4534 ADD_INT(d, DB_FLUSH);
4535 ADD_INT(d, DB_GET_BOTH);
4536 ADD_INT(d, DB_GET_RECNO);
4537 ADD_INT(d, DB_JOIN_ITEM);
4538 ADD_INT(d, DB_KEYFIRST);
4539 ADD_INT(d, DB_KEYLAST);
4540 ADD_INT(d, DB_LAST);
4541 ADD_INT(d, DB_NEXT);
4542 ADD_INT(d, DB_NEXT_DUP);
4543 ADD_INT(d, DB_NEXT_NODUP);
4544 ADD_INT(d, DB_NODUPDATA);
4545 ADD_INT(d, DB_NOOVERWRITE);
4546 ADD_INT(d, DB_NOSYNC);
4547 ADD_INT(d, DB_POSITION);
4548 ADD_INT(d, DB_PREV);
4549 ADD_INT(d, DB_PREV_NODUP);
4550 ADD_INT(d, DB_RECORDCOUNT);
4551 ADD_INT(d, DB_SET);
4552 ADD_INT(d, DB_SET_RANGE);
4553 ADD_INT(d, DB_SET_RECNO);
4554 ADD_INT(d, DB_WRITECURSOR);
4555
4556 ADD_INT(d, DB_OPFLAGS_MASK);
4557 ADD_INT(d, DB_RMW);
4558#if (DBVER >= 33)
4559 ADD_INT(d, DB_DIRTY_READ);
4560 ADD_INT(d, DB_MULTIPLE);
4561 ADD_INT(d, DB_MULTIPLE_KEY);
4562#endif
4563
4564#if (DBVER >= 33)
4565 ADD_INT(d, DB_DONOTINDEX);
4566#endif
4567
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004568#if (DBVER >= 41)
4569 _addIntToDict(d, "DB_INCOMPLETE", 0);
4570#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004571 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004572#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004573 ADD_INT(d, DB_KEYEMPTY);
4574 ADD_INT(d, DB_KEYEXIST);
4575 ADD_INT(d, DB_LOCK_DEADLOCK);
4576 ADD_INT(d, DB_LOCK_NOTGRANTED);
4577 ADD_INT(d, DB_NOSERVER);
4578 ADD_INT(d, DB_NOSERVER_HOME);
4579 ADD_INT(d, DB_NOSERVER_ID);
4580 ADD_INT(d, DB_NOTFOUND);
4581 ADD_INT(d, DB_OLD_VERSION);
4582 ADD_INT(d, DB_RUNRECOVERY);
4583 ADD_INT(d, DB_VERIFY_BAD);
4584#if (DBVER >= 33)
4585 ADD_INT(d, DB_PAGE_NOTFOUND);
4586 ADD_INT(d, DB_SECONDARY_BAD);
4587#endif
4588#if (DBVER >= 40)
4589 ADD_INT(d, DB_STAT_CLEAR);
4590 ADD_INT(d, DB_REGION_INIT);
4591 ADD_INT(d, DB_NOLOCKING);
4592 ADD_INT(d, DB_YIELDCPU);
4593 ADD_INT(d, DB_PANIC_ENVIRONMENT);
4594 ADD_INT(d, DB_NOPANIC);
4595#endif
4596
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004597#if (DBVER >= 41)
4598 ADD_INT(d, DB_ENCRYPT_AES);
4599 ADD_INT(d, DB_AUTO_COMMIT);
4600#else
4601 /* allow berkeleydb 4.1 aware apps to run on older versions */
4602 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
4603#endif
4604
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004605 ADD_INT(d, EINVAL);
4606 ADD_INT(d, EACCES);
4607 ADD_INT(d, ENOSPC);
4608 ADD_INT(d, ENOMEM);
4609 ADD_INT(d, EAGAIN);
4610 ADD_INT(d, EBUSY);
4611 ADD_INT(d, EEXIST);
4612 ADD_INT(d, ENOENT);
4613 ADD_INT(d, EPERM);
4614
Barry Warsaw1baa9822003-03-31 19:51:29 +00004615#if (DBVER >= 40)
4616 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
4617 ADD_INT(d, DB_SET_TXN_TIMEOUT);
4618#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004619
4620 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004621 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004622 PyDict_SetItemString(d, "DBError", DBError);
4623
4624 /* Some magic to make DBNotFoundError derive from both DBError and
4625 KeyError, since the API only supports using one base class. */
4626 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
4627 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
4628 Py_file_input, d, d);
4629 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
4630 PyDict_DelItemString(d, "KeyError");
4631
4632
4633 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004634#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004635 PyDict_SetItemString(d, #name, name)
4636
4637#if !INCOMPLETE_IS_WARNING
4638 MAKE_EX(DBIncompleteError);
4639#endif
4640 MAKE_EX(DBKeyEmptyError);
4641 MAKE_EX(DBKeyExistError);
4642 MAKE_EX(DBLockDeadlockError);
4643 MAKE_EX(DBLockNotGrantedError);
4644 MAKE_EX(DBOldVersionError);
4645 MAKE_EX(DBRunRecoveryError);
4646 MAKE_EX(DBVerifyBadError);
4647 MAKE_EX(DBNoServerError);
4648 MAKE_EX(DBNoServerHomeError);
4649 MAKE_EX(DBNoServerIDError);
4650#if (DBVER >= 33)
4651 MAKE_EX(DBPageNotFoundError);
4652 MAKE_EX(DBSecondaryBadError);
4653#endif
4654
4655 MAKE_EX(DBInvalidArgError);
4656 MAKE_EX(DBAccessError);
4657 MAKE_EX(DBNoSpaceError);
4658 MAKE_EX(DBNoMemoryError);
4659 MAKE_EX(DBAgainError);
4660 MAKE_EX(DBBusyError);
4661 MAKE_EX(DBFileExistsError);
4662 MAKE_EX(DBNoSuchFileError);
4663 MAKE_EX(DBPermissionsError);
4664
4665#undef MAKE_EX
4666
4667 /* Check for errors */
4668 if (PyErr_Occurred()) {
4669 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004670 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004671 }
4672}