blob: 227fe7bdf58672d4a77a802907d467548137e6d1 [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;
Gregory P. Smithb6c9f782003-01-17 08:42:50 +0000777 if (self->mydb->db != NULL)
778 err = self->dbc->c_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000779 self->dbc = NULL;
780 MYDB_END_ALLOW_THREADS;
781 }
782 Py_XDECREF( self->mydb );
783#if PYTHON_API_VERSION <= 1007
784 PyMem_DEL(self);
785#else
786 PyObject_Del(self);
787#endif
788}
789
790
791static DBEnvObject*
792newDBEnvObject(int flags)
793{
794 int err;
795 DBEnvObject* self;
796#if PYTHON_API_VERSION <= 1007
797 self = PyObject_NEW(DBEnvObject, &DBEnv_Type);
798#else
799 self = PyObject_New(DBEnvObject, &DBEnv_Type);
800#endif
801
802 if (self == NULL)
803 return NULL;
804
805 self->closed = 1;
806 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000807 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
808 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000809
810 MYDB_BEGIN_ALLOW_THREADS;
811 err = db_env_create(&self->db_env, flags);
812 MYDB_END_ALLOW_THREADS;
813 if (makeDBError(err)) {
814 self = NULL;
815 }
816 else {
817 self->db_env->set_errcall(self->db_env, _db_errorCallback);
818 }
819 return self;
820}
821
822
823static void
824DBEnv_dealloc(DBEnvObject* self)
825{
826 if (!self->closed) {
827 MYDB_BEGIN_ALLOW_THREADS;
828 self->db_env->close(self->db_env, 0);
829 MYDB_END_ALLOW_THREADS;
830 }
831#if PYTHON_API_VERSION <= 1007
832 PyMem_DEL(self);
833#else
834 PyObject_Del(self);
835#endif
836}
837
838
839static DBTxnObject*
840newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
841{
842 int err;
843 DBTxnObject* self;
844
845#if PYTHON_API_VERSION <= 1007
846 self = PyObject_NEW(DBTxnObject, &DBTxn_Type);
847#else
848 self = PyObject_New(DBTxnObject, &DBTxn_Type);
849#endif
850 if (self == NULL)
851 return NULL;
852
853 MYDB_BEGIN_ALLOW_THREADS;
854#if (DBVER >= 40)
855 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
856#else
857 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
858#endif
859 MYDB_END_ALLOW_THREADS;
860 if (makeDBError(err)) {
861 self = NULL;
862 }
863 return self;
864}
865
866
867static void
868DBTxn_dealloc(DBTxnObject* self)
869{
870 /* XXX nothing to do for transaction objects?!? */
871
872 /* TODO: if it hasn't been commited, should we abort it? */
873
874#if PYTHON_API_VERSION <= 1007
875 PyMem_DEL(self);
876#else
877 PyObject_Del(self);
878#endif
879}
880
881
882static DBLockObject*
883newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
884 db_lockmode_t lock_mode, int flags)
885{
886 int err;
887 DBLockObject* self;
888
889#if PYTHON_API_VERSION <= 1007
890 self = PyObject_NEW(DBLockObject, &DBLock_Type);
891#else
892 self = PyObject_New(DBLockObject, &DBLock_Type);
893#endif
894 if (self == NULL)
895 return NULL;
896
897 MYDB_BEGIN_ALLOW_THREADS;
898#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000899 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
900 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000901#else
902 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
903#endif
904 MYDB_END_ALLOW_THREADS;
905 if (makeDBError(err)) {
906 self = NULL;
907 }
908
909 return self;
910}
911
912
913static void
914DBLock_dealloc(DBLockObject* self)
915{
916 /* TODO: if it hasn't been released, should we do it? */
917
918#if PYTHON_API_VERSION <= 1007
919 PyMem_DEL(self);
920#else
921 PyObject_Del(self);
922#endif
923}
924
925
926/* --------------------------------------------------------------------- */
927/* DB methods */
928
929static PyObject*
930DB_append(DBObject* self, PyObject* args)
931{
932 PyObject* txnobj = NULL;
933 PyObject* dataobj;
934 db_recno_t recno;
935 DBT key, data;
936 DB_TXN *txn = NULL;
937
938 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
939 return NULL;
940
941 CHECK_DB_NOT_CLOSED(self);
942
943 /* make a dummy key out of a recno */
944 recno = 0;
945 CLEAR_DBT(key);
946 key.data = &recno;
947 key.size = sizeof(recno);
948 key.ulen = key.size;
949 key.flags = DB_DBT_USERMEM;
950
951 if (!make_dbt(dataobj, &data)) return NULL;
952 if (!checkTxnObj(txnobj, &txn)) return NULL;
953
954 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
955 return NULL;
956
957 return PyInt_FromLong(recno);
958}
959
960
961#if (DBVER >= 33)
962
963static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000964_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
965 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000966{
967 int retval = DB_DONOTINDEX;
968 DBObject* secondaryDB = (DBObject*)db->app_private;
969 PyObject* callback = secondaryDB->associateCallback;
970 int type = secondaryDB->primaryDBType;
971 PyObject* key;
972 PyObject* data;
973 PyObject* args;
974 PyObject* result;
975
976
977 if (callback != NULL) {
978 MYDB_BEGIN_BLOCK_THREADS;
979
980 if (type == DB_RECNO || type == DB_QUEUE) {
981 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
982 }
983 else {
984 key = PyString_FromStringAndSize(priKey->data, priKey->size);
985 }
986 data = PyString_FromStringAndSize(priData->data, priData->size);
987 args = PyTuple_New(2);
988 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
989 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
990
991 result = PyEval_CallObject(callback, args);
992
993 if (result == NULL) {
994 PyErr_Print();
995 }
996 else if (result == Py_None) {
997 retval = DB_DONOTINDEX;
998 }
999 else if (PyInt_Check(result)) {
1000 retval = PyInt_AsLong(result);
1001 }
1002 else if (PyString_Check(result)) {
1003 char* data;
1004 int size;
1005
1006 CLEAR_DBT(*secKey);
1007#if PYTHON_API_VERSION <= 1007
1008 /* 1.5 compatibility */
1009 size = PyString_Size(result);
1010 data = PyString_AsString(result);
1011#else
1012 PyString_AsStringAndSize(result, &data, &size);
1013#endif
1014 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1015 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001016 if (secKey->data) {
1017 memcpy(secKey->data, data, size);
1018 secKey->size = size;
1019 retval = 0;
1020 }
1021 else {
1022 PyErr_SetString(PyExc_MemoryError,
1023 "malloc failed in _db_associateCallback");
1024 PyErr_Print();
1025 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001026 }
1027 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001028 PyErr_SetString(
1029 PyExc_TypeError,
1030 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001031 PyErr_Print();
1032 }
1033
1034 Py_DECREF(args);
1035 if (result) {
1036 Py_DECREF(result);
1037 }
1038
1039 MYDB_END_BLOCK_THREADS;
1040 }
1041 return retval;
1042}
1043
1044
1045static PyObject*
1046DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1047{
1048 int err, flags=0;
1049 DBObject* secondaryDB;
1050 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001051#if (DBVER >= 41)
1052 PyObject *txnobj = NULL;
1053 DB_TXN *txn = NULL;
1054 char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL};
1055#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056 char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001057#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001058
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001059#if (DBVER >= 41)
1060 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1061 &secondaryDB, &callback, &flags,
1062 &txnobj)) {
1063#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001064 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001065 &secondaryDB, &callback, &flags)) {
1066#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001067 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001068 }
1069
1070#if (DBVER >= 41)
1071 if (!checkTxnObj(txnobj, &txn)) return NULL;
1072#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001073
1074 CHECK_DB_NOT_CLOSED(self);
1075 if (!DBObject_Check(secondaryDB)) {
1076 makeTypeError("DB", (PyObject*)secondaryDB);
1077 return NULL;
1078 }
1079 if (callback == Py_None) {
1080 callback = NULL;
1081 }
1082 else if (!PyCallable_Check(callback)) {
1083 makeTypeError("Callable", callback);
1084 return NULL;
1085 }
1086
1087 /* Save a reference to the callback in the secondary DB. */
1088 if (self->associateCallback != NULL) {
1089 Py_DECREF(self->associateCallback);
1090 }
1091 Py_INCREF(callback);
1092 secondaryDB->associateCallback = callback;
1093 secondaryDB->primaryDBType = _DB_get_type(self);
1094
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001095 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1096 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1097 * The global interepreter lock is not initialized until the first
1098 * thread is created using thread.start_new_thread() or fork() is
1099 * called. that would cause the ALLOW_THREADS here to segfault due
1100 * to a null pointer reference if no threads or child processes
1101 * have been created. This works around that and is a no-op if
1102 * threads have already been initialized.
1103 * (see pybsddb-users mailing list post on 2002-08-07)
1104 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001105#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001106 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001107#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001108 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001109#if (DBVER >= 41)
1110 err = self->db->associate(self->db,
1111 txn,
1112 secondaryDB->db,
1113 _db_associateCallback,
1114 flags);
1115#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001116 err = self->db->associate(self->db,
1117 secondaryDB->db,
1118 _db_associateCallback,
1119 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001120#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001121 MYDB_END_ALLOW_THREADS;
1122
1123 if (err) {
1124 Py_DECREF(self->associateCallback);
1125 self->associateCallback = NULL;
1126 secondaryDB->primaryDBType = 0;
1127 }
1128
1129 RETURN_IF_ERR();
1130 RETURN_NONE();
1131}
1132
1133
1134#endif
1135
1136
1137static PyObject*
1138DB_close(DBObject* self, PyObject* args)
1139{
1140 int err, flags=0;
1141 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1142 return NULL;
1143 if (self->db != NULL) {
1144 if (self->myenvobj)
1145 CHECK_ENV_NOT_CLOSED(self->myenvobj);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001146 err = self->db->close(self->db, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001147 self->db = NULL;
1148 RETURN_IF_ERR();
1149 }
1150 RETURN_NONE();
1151}
1152
1153
1154#if (DBVER >= 32)
1155static PyObject*
1156_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1157{
1158 int err, flags=0, type;
1159 PyObject* txnobj = NULL;
1160 PyObject* retval = NULL;
1161 DBT key, data;
1162 DB_TXN *txn = NULL;
1163 char* kwnames[] = { "txn", "flags", NULL };
1164
1165 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1166 &txnobj, &flags))
1167 return NULL;
1168
1169 CHECK_DB_NOT_CLOSED(self);
1170 type = _DB_get_type(self);
1171 if (type == -1)
1172 return NULL;
1173 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001174 PyErr_SetString(PyExc_TypeError,
1175 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001176 return NULL;
1177 }
1178 if (!checkTxnObj(txnobj, &txn))
1179 return NULL;
1180
1181 CLEAR_DBT(key);
1182 CLEAR_DBT(data);
1183 if (CHECK_DBFLAG(self, DB_THREAD)) {
1184 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1185 data.flags = DB_DBT_MALLOC;
1186 key.flags = DB_DBT_MALLOC;
1187 }
1188
1189 MYDB_BEGIN_ALLOW_THREADS;
1190 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1191 MYDB_END_ALLOW_THREADS;
1192
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001193 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001194 err = 0;
1195 Py_INCREF(Py_None);
1196 retval = Py_None;
1197 }
1198 else if (!err) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001199 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1200 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001201 FREE_DBT(key);
1202 FREE_DBT(data);
1203 }
1204
1205 RETURN_IF_ERR();
1206 return retval;
1207}
1208
1209static PyObject*
1210DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1211{
1212 return _DB_consume(self, args, kwargs, DB_CONSUME);
1213}
1214
1215static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001216DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1217 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001218{
1219 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1220}
1221#endif
1222
1223
1224
1225static PyObject*
1226DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1227{
1228 int err, flags=0;
1229 DBC* dbc;
1230 PyObject* txnobj = NULL;
1231 DB_TXN *txn = NULL;
1232 char* kwnames[] = { "txn", "flags", NULL };
1233
1234 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1235 &txnobj, &flags))
1236 return NULL;
1237 CHECK_DB_NOT_CLOSED(self);
1238 if (!checkTxnObj(txnobj, &txn))
1239 return NULL;
1240
1241 MYDB_BEGIN_ALLOW_THREADS;
1242 err = self->db->cursor(self->db, txn, &dbc, flags);
1243 MYDB_END_ALLOW_THREADS;
1244 RETURN_IF_ERR();
1245 return (PyObject*) newDBCursorObject(dbc, self);
1246}
1247
1248
1249static PyObject*
1250DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1251{
1252 PyObject* txnobj = NULL;
1253 int flags = 0;
1254 PyObject* keyobj;
1255 DBT key;
1256 DB_TXN *txn = NULL;
1257 char* kwnames[] = { "key", "txn", "flags", NULL };
1258
1259 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1260 &keyobj, &txnobj, &flags))
1261 return NULL;
1262 CHECK_DB_NOT_CLOSED(self);
1263 if (!make_key_dbt(self, keyobj, &key, NULL))
1264 return NULL;
1265 if (!checkTxnObj(txnobj, &txn))
1266 return NULL;
1267
1268 if (-1 == _DB_delete(self, txn, &key, 0))
1269 return NULL;
1270
1271 FREE_DBT(key);
1272 RETURN_NONE();
1273}
1274
1275
1276static PyObject*
1277DB_fd(DBObject* self, PyObject* args)
1278{
1279 int err, the_fd;
1280
1281 if (!PyArg_ParseTuple(args,":fd"))
1282 return NULL;
1283 CHECK_DB_NOT_CLOSED(self);
1284
1285 MYDB_BEGIN_ALLOW_THREADS;
1286 err = self->db->fd(self->db, &the_fd);
1287 MYDB_END_ALLOW_THREADS;
1288 RETURN_IF_ERR();
1289 return PyInt_FromLong(the_fd);
1290}
1291
1292
1293static PyObject*
1294DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1295{
1296 int err, flags=0;
1297 PyObject* txnobj = NULL;
1298 PyObject* keyobj;
1299 PyObject* dfltobj = NULL;
1300 PyObject* retval = NULL;
1301 int dlen = -1;
1302 int doff = -1;
1303 DBT key, data;
1304 DB_TXN *txn = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001305 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001306
1307 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001308 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1309 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001310 return NULL;
1311
1312 CHECK_DB_NOT_CLOSED(self);
1313 if (!make_key_dbt(self, keyobj, &key, &flags))
1314 return NULL;
1315 if (!checkTxnObj(txnobj, &txn))
1316 return NULL;
1317
1318 CLEAR_DBT(data);
1319 if (CHECK_DBFLAG(self, DB_THREAD)) {
1320 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1321 data.flags = DB_DBT_MALLOC;
1322 }
1323 if (!add_partial_dbt(&data, dlen, doff))
1324 return NULL;
1325
1326 MYDB_BEGIN_ALLOW_THREADS;
1327 err = self->db->get(self->db, txn, &key, &data, flags);
1328 MYDB_END_ALLOW_THREADS;
1329
1330 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1331 err = 0;
1332 Py_INCREF(dfltobj);
1333 retval = dfltobj;
1334 }
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001335 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001336 err = 0;
1337 Py_INCREF(Py_None);
1338 retval = Py_None;
1339 }
1340 else if (!err) {
1341 if (flags & DB_SET_RECNO) /* return both key and data */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001342 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1343 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001344 else /* return just the data */
1345 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1346 FREE_DBT(key);
1347 FREE_DBT(data);
1348 }
1349
1350 RETURN_IF_ERR();
1351 return retval;
1352}
1353
1354
1355/* Return size of entry */
1356static PyObject*
1357DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1358{
1359 int err, flags=0;
1360 PyObject* txnobj = NULL;
1361 PyObject* keyobj;
1362 PyObject* retval = NULL;
1363 DBT key, data;
1364 DB_TXN *txn = NULL;
1365 char* kwnames[] = { "key", "txn", NULL };
1366
1367 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1368 &keyobj, &txnobj))
1369 return NULL;
1370 CHECK_DB_NOT_CLOSED(self);
1371 if (!make_key_dbt(self, keyobj, &key, &flags))
1372 return NULL;
1373 if (!checkTxnObj(txnobj, &txn))
1374 return NULL;
1375 CLEAR_DBT(data);
1376
1377 /* We don't allocate any memory, forcing a ENOMEM error and thus
1378 getting the record size. */
1379 data.flags = DB_DBT_USERMEM;
1380 data.ulen = 0;
1381 MYDB_BEGIN_ALLOW_THREADS;
1382 err = self->db->get(self->db, txn, &key, &data, flags);
1383 MYDB_END_ALLOW_THREADS;
1384 if (err == ENOMEM) {
1385 retval = PyInt_FromLong((long)data.size);
1386 err = 0;
1387 }
1388
1389 FREE_DBT(key);
1390 FREE_DBT(data);
1391 RETURN_IF_ERR();
1392 return retval;
1393}
1394
1395
1396static PyObject*
1397DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1398{
1399 int err, flags=0;
1400 PyObject* txnobj = NULL;
1401 PyObject* keyobj;
1402 PyObject* dataobj;
1403 PyObject* retval = NULL;
1404 DBT key, data;
1405 DB_TXN *txn = NULL;
1406 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1407
1408
1409 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1410 &keyobj, &dataobj, &txnobj, &flags))
1411 return NULL;
1412
1413 CHECK_DB_NOT_CLOSED(self);
1414 if (!make_key_dbt(self, keyobj, &key, NULL))
1415 return NULL;
1416 if (!make_dbt(dataobj, &data))
1417 return NULL;
1418 if (!checkTxnObj(txnobj, &txn))
1419 return NULL;
1420
1421 flags |= DB_GET_BOTH;
1422
1423 if (CHECK_DBFLAG(self, DB_THREAD)) {
1424 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1425 data.flags = DB_DBT_MALLOC;
1426 /* TODO: Is this flag needed? We're passing a data object that should
1427 match what's in the DB, so there should be no need to malloc.
1428 We run the risk of freeing something twice! Check this. */
1429 }
1430
1431 MYDB_BEGIN_ALLOW_THREADS;
1432 err = self->db->get(self->db, txn, &key, &data, flags);
1433 MYDB_END_ALLOW_THREADS;
1434
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001435 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001436 err = 0;
1437 Py_INCREF(Py_None);
1438 retval = Py_None;
1439 }
1440 else if (!err) {
1441 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1442 FREE_DBT(data); /* Only if retrieval was successful */
1443 }
1444
1445 FREE_DBT(key);
1446 RETURN_IF_ERR();
1447 return retval;
1448}
1449
1450
1451static PyObject*
1452DB_get_byteswapped(DBObject* self, PyObject* args)
1453{
1454#if (DBVER >= 33)
1455 int err = 0;
1456#endif
1457 int retval = -1;
1458
1459 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1460 return NULL;
1461 CHECK_DB_NOT_CLOSED(self);
1462
1463#if (DBVER >= 33)
1464 MYDB_BEGIN_ALLOW_THREADS;
1465 err = self->db->get_byteswapped(self->db, &retval);
1466 MYDB_END_ALLOW_THREADS;
1467 RETURN_IF_ERR();
1468#else
1469 MYDB_BEGIN_ALLOW_THREADS;
1470 retval = self->db->get_byteswapped(self->db);
1471 MYDB_END_ALLOW_THREADS;
1472#endif
1473 return PyInt_FromLong(retval);
1474}
1475
1476
1477static PyObject*
1478DB_get_type(DBObject* self, PyObject* args)
1479{
1480 int type;
1481
1482 if (!PyArg_ParseTuple(args,":get_type"))
1483 return NULL;
1484 CHECK_DB_NOT_CLOSED(self);
1485
1486 MYDB_BEGIN_ALLOW_THREADS;
1487 type = _DB_get_type(self);
1488 MYDB_END_ALLOW_THREADS;
1489 if (type == -1)
1490 return NULL;
1491 return PyInt_FromLong(type);
1492}
1493
1494
1495static PyObject*
1496DB_join(DBObject* self, PyObject* args)
1497{
1498 int err, flags=0;
1499 int length, x;
1500 PyObject* cursorsObj;
1501 DBC** cursors;
1502 DBC* dbc;
1503
1504
1505 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1506 return NULL;
1507
1508 CHECK_DB_NOT_CLOSED(self);
1509
1510 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001511 PyErr_SetString(PyExc_TypeError,
1512 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001513 return NULL;
1514 }
1515
1516 length = PyObject_Length(cursorsObj);
1517 cursors = malloc((length+1) * sizeof(DBC*));
1518 cursors[length] = NULL;
1519 for (x=0; x<length; x++) {
1520 PyObject* item = PySequence_GetItem(cursorsObj, x);
1521 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001522 PyErr_SetString(PyExc_TypeError,
1523 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001524 free(cursors);
1525 return NULL;
1526 }
1527 cursors[x] = ((DBCursorObject*)item)->dbc;
1528 }
1529
1530 MYDB_BEGIN_ALLOW_THREADS;
1531 err = self->db->join(self->db, cursors, &dbc, flags);
1532 MYDB_END_ALLOW_THREADS;
1533 free(cursors);
1534 RETURN_IF_ERR();
1535
Gregory P. Smith455d46f2003-07-09 04:45:59 +00001536 // FIXME: this is a buggy interface. The returned cursor
1537 // contains internal references to the passed in cursors
1538 // but does not hold python references to them or prevent
1539 // them from being closed prematurely. This can cause
1540 // python to crash when things are done in the wrong order.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001541 return (PyObject*) newDBCursorObject(dbc, self);
1542}
1543
1544
1545static PyObject*
1546DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1547{
1548 int err, flags=0;
1549 PyObject* txnobj = NULL;
1550 PyObject* keyobj;
1551 DBT key;
1552 DB_TXN *txn = NULL;
1553 DB_KEY_RANGE range;
1554 char* kwnames[] = { "key", "txn", "flags", NULL };
1555
1556 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1557 &keyobj, &txnobj, &flags))
1558 return NULL;
1559 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001560 if (!make_dbt(keyobj, &key))
1561 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001562 return NULL;
1563 if (!checkTxnObj(txnobj, &txn))
1564 return NULL;
1565
1566 MYDB_BEGIN_ALLOW_THREADS;
1567 err = self->db->key_range(self->db, txn, &key, &range, flags);
1568 MYDB_END_ALLOW_THREADS;
1569
1570 RETURN_IF_ERR();
1571 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1572}
1573
1574
1575static PyObject*
1576DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1577{
1578 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1579 char* filename = NULL;
1580 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001581#if (DBVER >= 41)
1582 PyObject *txnobj = NULL;
1583 DB_TXN *txn = NULL;
1584 /* with dbname */
1585 char* kwnames[] = {
1586 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1587 /* without dbname */
1588 char* kwnames_basic[] = {
1589 "filename", "dbtype", "flags", "mode", "txn", NULL};
1590#else
1591 /* with dbname */
1592 char* kwnames[] = {
1593 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1594 /* without dbname */
1595 char* kwnames_basic[] = {
1596 "filename", "dbtype", "flags", "mode", NULL};
1597#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001598
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001599#if (DBVER >= 41)
1600 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1601 &filename, &dbname, &type, &flags, &mode,
1602 &txnobj))
1603#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001604 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001605 &filename, &dbname, &type, &flags,
1606 &mode))
1607#endif
1608 {
1609 PyErr_Clear();
1610 type = DB_UNKNOWN; flags = 0; mode = 0660;
1611 filename = NULL; dbname = NULL;
1612#if (DBVER >= 41)
1613 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1614 kwnames_basic,
1615 &filename, &type, &flags, &mode,
1616 &txnobj))
1617 return NULL;
1618#else
1619 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1620 kwnames_basic,
1621 &filename, &type, &flags, &mode))
1622 return NULL;
1623#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001624 }
1625
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001626#if (DBVER >= 41)
1627 if (!checkTxnObj(txnobj, &txn)) return NULL;
1628#endif
1629
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001630 if (NULL == self->db) {
1631 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1632 "Cannot call open() twice for DB object"));
1633 return NULL;
1634 }
1635
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001636#if 0 && (DBVER >= 41)
1637 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1638 && (self->myenvobj->flags & DB_INIT_TXN))
1639 {
1640 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1641 * explicitly passed) but we are in a transaction ready environment:
1642 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1643 * to work on BerkeleyDB 4.1 without needing to modify their
1644 * DBEnv or DB open calls.
1645 * TODO make this behaviour of the library configurable.
1646 */
1647 flags |= DB_AUTO_COMMIT;
1648 }
1649#endif
1650
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001651 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001652#if (DBVER >= 41)
1653 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1654#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001655 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001656#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001657 MYDB_END_ALLOW_THREADS;
1658 if (makeDBError(err)) {
Gregory P. Smithb6c9f782003-01-17 08:42:50 +00001659 self->db->close(self->db, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001660 self->db = NULL;
1661 return NULL;
1662 }
1663
1664 self->flags = flags;
1665 RETURN_NONE();
1666}
1667
1668
1669static PyObject*
1670DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1671{
1672 int flags=0;
1673 PyObject* txnobj = NULL;
1674 int dlen = -1;
1675 int doff = -1;
1676 PyObject* keyobj, *dataobj, *retval;
1677 DBT key, data;
1678 DB_TXN *txn = NULL;
1679 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1680
1681 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1682 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1683 return NULL;
1684
1685 CHECK_DB_NOT_CLOSED(self);
1686 if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL;
1687 if (!make_dbt(dataobj, &data)) return NULL;
1688 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
1689 if (!checkTxnObj(txnobj, &txn)) return NULL;
1690
1691 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1692 FREE_DBT(key);
1693 return NULL;
1694 }
1695
1696 if (flags & DB_APPEND)
1697 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1698 else {
1699 retval = Py_None;
1700 Py_INCREF(retval);
1701 }
1702 FREE_DBT(key);
1703 return retval;
1704}
1705
1706
1707
1708static PyObject*
1709DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1710{
1711 char* filename;
1712 char* database = NULL;
1713 int err, flags=0;
1714 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1715
1716 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1717 &filename, &database, &flags))
1718 return NULL;
1719 CHECK_DB_NOT_CLOSED(self);
1720
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001721 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00001722 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001723 RETURN_IF_ERR();
1724 RETURN_NONE();
1725}
1726
1727
1728
1729static PyObject*
1730DB_rename(DBObject* self, PyObject* args)
1731{
1732 char* filename;
1733 char* database;
1734 char* newname;
1735 int err, flags=0;
1736
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001737 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1738 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001739 return NULL;
1740 CHECK_DB_NOT_CLOSED(self);
1741
1742 MYDB_BEGIN_ALLOW_THREADS;
1743 err = self->db->rename(self->db, filename, database, newname, flags);
1744 MYDB_END_ALLOW_THREADS;
1745 RETURN_IF_ERR();
1746 RETURN_NONE();
1747}
1748
1749
1750static PyObject*
1751DB_set_bt_minkey(DBObject* self, PyObject* args)
1752{
1753 int err, minkey;
1754
1755 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1756 return NULL;
1757 CHECK_DB_NOT_CLOSED(self);
1758
1759 MYDB_BEGIN_ALLOW_THREADS;
1760 err = self->db->set_bt_minkey(self->db, minkey);
1761 MYDB_END_ALLOW_THREADS;
1762 RETURN_IF_ERR();
1763 RETURN_NONE();
1764}
1765
1766
1767static PyObject*
1768DB_set_cachesize(DBObject* self, PyObject* args)
1769{
1770 int err;
1771 int gbytes = 0, bytes = 0, ncache = 0;
1772
1773 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1774 &gbytes,&bytes,&ncache))
1775 return NULL;
1776 CHECK_DB_NOT_CLOSED(self);
1777
1778 MYDB_BEGIN_ALLOW_THREADS;
1779 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1780 MYDB_END_ALLOW_THREADS;
1781 RETURN_IF_ERR();
1782 RETURN_NONE();
1783}
1784
1785
1786static PyObject*
1787DB_set_flags(DBObject* self, PyObject* args)
1788{
1789 int err, flags;
1790
1791 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
1792 return NULL;
1793 CHECK_DB_NOT_CLOSED(self);
1794
1795 MYDB_BEGIN_ALLOW_THREADS;
1796 err = self->db->set_flags(self->db, flags);
1797 MYDB_END_ALLOW_THREADS;
1798 RETURN_IF_ERR();
1799
1800 self->setflags |= flags;
1801 RETURN_NONE();
1802}
1803
1804
1805static PyObject*
1806DB_set_h_ffactor(DBObject* self, PyObject* args)
1807{
1808 int err, ffactor;
1809
1810 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
1811 return NULL;
1812 CHECK_DB_NOT_CLOSED(self);
1813
1814 MYDB_BEGIN_ALLOW_THREADS;
1815 err = self->db->set_h_ffactor(self->db, ffactor);
1816 MYDB_END_ALLOW_THREADS;
1817 RETURN_IF_ERR();
1818 RETURN_NONE();
1819}
1820
1821
1822static PyObject*
1823DB_set_h_nelem(DBObject* self, PyObject* args)
1824{
1825 int err, nelem;
1826
1827 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
1828 return NULL;
1829 CHECK_DB_NOT_CLOSED(self);
1830
1831 MYDB_BEGIN_ALLOW_THREADS;
1832 err = self->db->set_h_nelem(self->db, nelem);
1833 MYDB_END_ALLOW_THREADS;
1834 RETURN_IF_ERR();
1835 RETURN_NONE();
1836}
1837
1838
1839static PyObject*
1840DB_set_lorder(DBObject* self, PyObject* args)
1841{
1842 int err, lorder;
1843
1844 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
1845 return NULL;
1846 CHECK_DB_NOT_CLOSED(self);
1847
1848 MYDB_BEGIN_ALLOW_THREADS;
1849 err = self->db->set_lorder(self->db, lorder);
1850 MYDB_END_ALLOW_THREADS;
1851 RETURN_IF_ERR();
1852 RETURN_NONE();
1853}
1854
1855
1856static PyObject*
1857DB_set_pagesize(DBObject* self, PyObject* args)
1858{
1859 int err, pagesize;
1860
1861 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
1862 return NULL;
1863 CHECK_DB_NOT_CLOSED(self);
1864
1865 MYDB_BEGIN_ALLOW_THREADS;
1866 err = self->db->set_pagesize(self->db, pagesize);
1867 MYDB_END_ALLOW_THREADS;
1868 RETURN_IF_ERR();
1869 RETURN_NONE();
1870}
1871
1872
1873static PyObject*
1874DB_set_re_delim(DBObject* self, PyObject* args)
1875{
1876 int err;
1877 char delim;
1878
1879 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
1880 PyErr_Clear();
1881 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
1882 return NULL;
1883 }
1884
1885 CHECK_DB_NOT_CLOSED(self);
1886
1887 MYDB_BEGIN_ALLOW_THREADS;
1888 err = self->db->set_re_delim(self->db, delim);
1889 MYDB_END_ALLOW_THREADS;
1890 RETURN_IF_ERR();
1891 RETURN_NONE();
1892}
1893
1894static PyObject*
1895DB_set_re_len(DBObject* self, PyObject* args)
1896{
1897 int err, len;
1898
1899 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
1900 return NULL;
1901 CHECK_DB_NOT_CLOSED(self);
1902
1903 MYDB_BEGIN_ALLOW_THREADS;
1904 err = self->db->set_re_len(self->db, len);
1905 MYDB_END_ALLOW_THREADS;
1906 RETURN_IF_ERR();
1907 RETURN_NONE();
1908}
1909
1910
1911static PyObject*
1912DB_set_re_pad(DBObject* self, PyObject* args)
1913{
1914 int err;
1915 char pad;
1916
1917 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
1918 PyErr_Clear();
1919 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
1920 return NULL;
1921 }
1922 CHECK_DB_NOT_CLOSED(self);
1923
1924 MYDB_BEGIN_ALLOW_THREADS;
1925 err = self->db->set_re_pad(self->db, pad);
1926 MYDB_END_ALLOW_THREADS;
1927 RETURN_IF_ERR();
1928 RETURN_NONE();
1929}
1930
1931
1932static PyObject*
1933DB_set_re_source(DBObject* self, PyObject* args)
1934{
1935 int err;
1936 char *re_source;
1937
1938 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
1939 return NULL;
1940 CHECK_DB_NOT_CLOSED(self);
1941
1942 MYDB_BEGIN_ALLOW_THREADS;
1943 err = self->db->set_re_source(self->db, re_source);
1944 MYDB_END_ALLOW_THREADS;
1945 RETURN_IF_ERR();
1946 RETURN_NONE();
1947}
1948
1949
1950#if (DBVER >= 32)
1951static PyObject*
1952DB_set_q_extentsize(DBObject* self, PyObject* args)
1953{
1954 int err;
1955 int extentsize;
1956
1957 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
1958 return NULL;
1959 CHECK_DB_NOT_CLOSED(self);
1960
1961 MYDB_BEGIN_ALLOW_THREADS;
1962 err = self->db->set_q_extentsize(self->db, extentsize);
1963 MYDB_END_ALLOW_THREADS;
1964 RETURN_IF_ERR();
1965 RETURN_NONE();
1966}
1967#endif
1968
1969static PyObject*
1970DB_stat(DBObject* self, PyObject* args)
1971{
1972 int err, flags = 0, type;
1973 void* sp;
1974 PyObject* d;
1975
1976
1977 if (!PyArg_ParseTuple(args, "|i:stat", &flags))
1978 return NULL;
1979 CHECK_DB_NOT_CLOSED(self);
1980
1981 MYDB_BEGIN_ALLOW_THREADS;
1982#if (DBVER >= 33)
1983 err = self->db->stat(self->db, &sp, flags);
1984#else
1985 err = self->db->stat(self->db, &sp, NULL, flags);
1986#endif
1987 MYDB_END_ALLOW_THREADS;
1988 RETURN_IF_ERR();
1989
1990 self->haveStat = 1;
1991
1992 /* Turn the stat structure into a dictionary */
1993 type = _DB_get_type(self);
1994 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
1995 free(sp);
1996 return NULL;
1997 }
1998
1999#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2000#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2001#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2002
2003 switch (type) {
2004 case DB_HASH:
2005 MAKE_HASH_ENTRY(magic);
2006 MAKE_HASH_ENTRY(version);
2007 MAKE_HASH_ENTRY(nkeys);
2008 MAKE_HASH_ENTRY(ndata);
2009 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002010#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002011 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002012#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002013 MAKE_HASH_ENTRY(ffactor);
2014 MAKE_HASH_ENTRY(buckets);
2015 MAKE_HASH_ENTRY(free);
2016 MAKE_HASH_ENTRY(bfree);
2017 MAKE_HASH_ENTRY(bigpages);
2018 MAKE_HASH_ENTRY(big_bfree);
2019 MAKE_HASH_ENTRY(overflows);
2020 MAKE_HASH_ENTRY(ovfl_free);
2021 MAKE_HASH_ENTRY(dup);
2022 MAKE_HASH_ENTRY(dup_free);
2023 break;
2024
2025 case DB_BTREE:
2026 case DB_RECNO:
2027 MAKE_BT_ENTRY(magic);
2028 MAKE_BT_ENTRY(version);
2029 MAKE_BT_ENTRY(nkeys);
2030 MAKE_BT_ENTRY(ndata);
2031 MAKE_BT_ENTRY(pagesize);
2032 MAKE_BT_ENTRY(minkey);
2033 MAKE_BT_ENTRY(re_len);
2034 MAKE_BT_ENTRY(re_pad);
2035 MAKE_BT_ENTRY(levels);
2036 MAKE_BT_ENTRY(int_pg);
2037 MAKE_BT_ENTRY(leaf_pg);
2038 MAKE_BT_ENTRY(dup_pg);
2039 MAKE_BT_ENTRY(over_pg);
2040 MAKE_BT_ENTRY(free);
2041 MAKE_BT_ENTRY(int_pgfree);
2042 MAKE_BT_ENTRY(leaf_pgfree);
2043 MAKE_BT_ENTRY(dup_pgfree);
2044 MAKE_BT_ENTRY(over_pgfree);
2045 break;
2046
2047 case DB_QUEUE:
2048 MAKE_QUEUE_ENTRY(magic);
2049 MAKE_QUEUE_ENTRY(version);
2050 MAKE_QUEUE_ENTRY(nkeys);
2051 MAKE_QUEUE_ENTRY(ndata);
2052 MAKE_QUEUE_ENTRY(pagesize);
2053 MAKE_QUEUE_ENTRY(pages);
2054 MAKE_QUEUE_ENTRY(re_len);
2055 MAKE_QUEUE_ENTRY(re_pad);
2056 MAKE_QUEUE_ENTRY(pgfree);
2057#if (DBVER == 31)
2058 MAKE_QUEUE_ENTRY(start);
2059#endif
2060 MAKE_QUEUE_ENTRY(first_recno);
2061 MAKE_QUEUE_ENTRY(cur_recno);
2062 break;
2063
2064 default:
2065 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2066 Py_DECREF(d);
2067 d = NULL;
2068 }
2069
2070#undef MAKE_HASH_ENTRY
2071#undef MAKE_BT_ENTRY
2072#undef MAKE_QUEUE_ENTRY
2073
2074 free(sp);
2075 return d;
2076}
2077
2078static PyObject*
2079DB_sync(DBObject* self, PyObject* args)
2080{
2081 int err;
2082 int flags = 0;
2083
2084 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2085 return NULL;
2086 CHECK_DB_NOT_CLOSED(self);
2087
2088 MYDB_BEGIN_ALLOW_THREADS;
2089 err = self->db->sync(self->db, flags);
2090 MYDB_END_ALLOW_THREADS;
2091 RETURN_IF_ERR();
2092 RETURN_NONE();
2093}
2094
2095
2096#if (DBVER >= 33)
2097static PyObject*
2098DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2099{
2100 int err, flags=0;
2101 u_int32_t count=0;
2102 PyObject* txnobj = NULL;
2103 DB_TXN *txn = NULL;
2104 char* kwnames[] = { "txn", "flags", NULL };
2105
2106 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2107 &txnobj, &flags))
2108 return NULL;
2109 CHECK_DB_NOT_CLOSED(self);
2110 if (!checkTxnObj(txnobj, &txn))
2111 return NULL;
2112
2113 MYDB_BEGIN_ALLOW_THREADS;
2114 err = self->db->truncate(self->db, txn, &count, flags);
2115 MYDB_END_ALLOW_THREADS;
2116 RETURN_IF_ERR();
2117 return PyInt_FromLong(count);
2118}
2119#endif
2120
2121
2122static PyObject*
2123DB_upgrade(DBObject* self, PyObject* args)
2124{
2125 int err, flags=0;
2126 char *filename;
2127
2128 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2129 return NULL;
2130 CHECK_DB_NOT_CLOSED(self);
2131
2132 MYDB_BEGIN_ALLOW_THREADS;
2133 err = self->db->upgrade(self->db, filename, flags);
2134 MYDB_END_ALLOW_THREADS;
2135 RETURN_IF_ERR();
2136 RETURN_NONE();
2137}
2138
2139
2140static PyObject*
2141DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2142{
2143 int err, flags=0;
2144 char* fileName;
2145 char* dbName=NULL;
2146 char* outFileName=NULL;
2147 FILE* outFile=NULL;
2148 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2149
2150 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2151 &fileName, &dbName, &outFileName, &flags))
2152 return NULL;
2153
2154 CHECK_DB_NOT_CLOSED(self);
2155 if (outFileName)
2156 outFile = fopen(outFileName, "w");
2157
2158 MYDB_BEGIN_ALLOW_THREADS;
2159 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2160 MYDB_END_ALLOW_THREADS;
2161 if (outFileName)
2162 fclose(outFile);
2163 RETURN_IF_ERR();
2164 RETURN_NONE();
2165}
2166
2167
2168static PyObject*
2169DB_set_get_returns_none(DBObject* self, PyObject* args)
2170{
2171 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002172 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002173
2174 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2175 return NULL;
2176 CHECK_DB_NOT_CLOSED(self);
2177
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002178 if (self->moduleFlags.getReturnsNone)
2179 ++oldValue;
2180 if (self->moduleFlags.cursorSetReturnsNone)
2181 ++oldValue;
2182 self->moduleFlags.getReturnsNone = (flags >= 1);
2183 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002184 return PyInt_FromLong(oldValue);
2185}
2186
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002187#if (DBVER >= 41)
2188static PyObject*
2189DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2190{
2191 int err;
2192 u_int32_t flags=0;
2193 char *passwd = NULL;
2194 char* kwnames[] = { "passwd", "flags", NULL };
2195
2196 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2197 &passwd, &flags)) {
2198 return NULL;
2199 }
2200
2201 MYDB_BEGIN_ALLOW_THREADS;
2202 err = self->db->set_encrypt(self->db, passwd, flags);
2203 MYDB_END_ALLOW_THREADS;
2204
2205 RETURN_IF_ERR();
2206 RETURN_NONE();
2207}
2208#endif /* DBVER >= 41 */
2209
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002210
2211/*-------------------------------------------------------------- */
2212/* Mapping and Dictionary-like access routines */
2213
2214int DB_length(DBObject* self)
2215{
2216 int err;
2217 long size = 0;
2218 int flags = 0;
2219 void* sp;
2220
2221 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002222 PyErr_SetObject(DBError,
2223 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002224 return -1;
2225 }
2226
2227 if (self->haveStat) { /* Has the stat function been called recently? If
2228 so, we can use the cached value. */
2229 flags = DB_CACHED_COUNTS;
2230 }
2231
2232 MYDB_BEGIN_ALLOW_THREADS;
2233#if (DBVER >= 33)
2234 err = self->db->stat(self->db, &sp, flags);
2235#else
2236 err = self->db->stat(self->db, &sp, NULL, flags);
2237#endif
2238 MYDB_END_ALLOW_THREADS;
2239
2240 if (err)
2241 return -1;
2242
2243 self->haveStat = 1;
2244
2245 /* All the stat structures have matching fields upto the ndata field,
2246 so we can use any of them for the type cast */
2247 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2248 free(sp);
2249 return size;
2250}
2251
2252
2253PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2254{
2255 int err;
2256 PyObject* retval;
2257 DBT key;
2258 DBT data;
2259
2260 CHECK_DB_NOT_CLOSED(self);
2261 if (!make_key_dbt(self, keyobj, &key, NULL))
2262 return NULL;
2263
2264 CLEAR_DBT(data);
2265 if (CHECK_DBFLAG(self, DB_THREAD)) {
2266 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2267 data.flags = DB_DBT_MALLOC;
2268 }
2269 MYDB_BEGIN_ALLOW_THREADS;
2270 err = self->db->get(self->db, NULL, &key, &data, 0);
2271 MYDB_END_ALLOW_THREADS;
2272 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2273 PyErr_SetObject(PyExc_KeyError, keyobj);
2274 retval = NULL;
2275 }
2276 else if (makeDBError(err)) {
2277 retval = NULL;
2278 }
2279 else {
2280 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2281 FREE_DBT(data);
2282 }
2283
2284 FREE_DBT(key);
2285 return retval;
2286}
2287
2288
2289static int
2290DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2291{
2292 DBT key, data;
2293 int retval;
2294 int flags = 0;
2295
2296 if (self->db == NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002297 PyErr_SetObject(DBError,
2298 Py_BuildValue("(is)", 0, "DB object has been closed"));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002299 return -1;
2300 }
2301
2302 if (!make_key_dbt(self, keyobj, &key, NULL))
2303 return -1;
2304
2305 if (dataobj != NULL) {
2306 if (!make_dbt(dataobj, &data))
2307 retval = -1;
2308 else {
2309 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002310 /* dictionaries shouldn't have duplicate keys */
2311 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002312 retval = _DB_put(self, NULL, &key, &data, flags);
2313
2314 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002315 /* try deleting any old record that matches and then PUT it
2316 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002317 _DB_delete(self, NULL, &key, 0);
2318 PyErr_Clear();
2319 retval = _DB_put(self, NULL, &key, &data, flags);
2320 }
2321 }
2322 }
2323 else {
2324 /* dataobj == NULL, so delete the key */
2325 retval = _DB_delete(self, NULL, &key, 0);
2326 }
2327 FREE_DBT(key);
2328 return retval;
2329}
2330
2331
2332static PyObject*
2333DB_has_key(DBObject* self, PyObject* args)
2334{
2335 int err;
2336 PyObject* keyobj;
2337 DBT key, data;
2338 PyObject* txnobj = NULL;
2339 DB_TXN *txn = NULL;
2340
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002341 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002342 return NULL;
2343 CHECK_DB_NOT_CLOSED(self);
2344 if (!make_key_dbt(self, keyobj, &key, NULL))
2345 return NULL;
2346 if (!checkTxnObj(txnobj, &txn))
2347 return NULL;
2348
2349 /* This causes ENOMEM to be returned when the db has the key because
2350 it has a record but can't allocate a buffer for the data. This saves
2351 having to deal with data we won't be using.
2352 */
2353 CLEAR_DBT(data);
2354 data.flags = DB_DBT_USERMEM;
2355
2356 MYDB_BEGIN_ALLOW_THREADS;
2357 err = self->db->get(self->db, NULL, &key, &data, 0);
2358 MYDB_END_ALLOW_THREADS;
2359 FREE_DBT(key);
2360 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2361}
2362
2363
2364#define _KEYS_LIST 1
2365#define _VALUES_LIST 2
2366#define _ITEMS_LIST 3
2367
2368static PyObject*
2369_DB_make_list(DBObject* self, DB_TXN* txn, int type)
2370{
2371 int err, dbtype;
2372 DBT key;
2373 DBT data;
2374 DBC *cursor;
2375 PyObject* list;
2376 PyObject* item = NULL;
2377
2378 CHECK_DB_NOT_CLOSED(self);
2379 CLEAR_DBT(key);
2380 CLEAR_DBT(data);
2381
2382 dbtype = _DB_get_type(self);
2383 if (dbtype == -1)
2384 return NULL;
2385
2386 list = PyList_New(0);
2387 if (list == NULL) {
2388 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2389 return NULL;
2390 }
2391
2392 /* get a cursor */
2393 MYDB_BEGIN_ALLOW_THREADS;
2394 err = self->db->cursor(self->db, NULL, &cursor, 0);
2395 MYDB_END_ALLOW_THREADS;
2396 RETURN_IF_ERR();
2397
2398 if (CHECK_DBFLAG(self, DB_THREAD)) {
2399 key.flags = DB_DBT_REALLOC;
2400 data.flags = DB_DBT_REALLOC;
2401 }
2402
2403 while (1) { /* use the cursor to traverse the DB, collecting items */
2404 MYDB_BEGIN_ALLOW_THREADS;
2405 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2406 MYDB_END_ALLOW_THREADS;
2407
2408 if (err) {
2409 /* for any error, break out of the loop */
2410 break;
2411 }
2412
2413 switch (type) {
2414 case _KEYS_LIST:
2415 switch(dbtype) {
2416 case DB_BTREE:
2417 case DB_HASH:
2418 default:
2419 item = PyString_FromStringAndSize((char*)key.data, key.size);
2420 break;
2421 case DB_RECNO:
2422 case DB_QUEUE:
2423 item = PyInt_FromLong(*((db_recno_t*)key.data));
2424 break;
2425 }
2426 break;
2427
2428 case _VALUES_LIST:
2429 item = PyString_FromStringAndSize((char*)data.data, data.size);
2430 break;
2431
2432 case _ITEMS_LIST:
2433 switch(dbtype) {
2434 case DB_BTREE:
2435 case DB_HASH:
2436 default:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002437 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2438 data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002439 break;
2440 case DB_RECNO:
2441 case DB_QUEUE:
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002442 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2443 data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002444 break;
2445 }
2446 break;
2447 }
2448 if (item == NULL) {
2449 Py_DECREF(list);
2450 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2451 list = NULL;
2452 goto done;
2453 }
2454 PyList_Append(list, item);
2455 Py_DECREF(item);
2456 }
2457
2458 /* DB_NOTFOUND is okay, it just means we got to the end */
2459 if (err != DB_NOTFOUND && makeDBError(err)) {
2460 Py_DECREF(list);
2461 list = NULL;
2462 }
2463
2464 done:
2465 FREE_DBT(key);
2466 FREE_DBT(data);
2467 MYDB_BEGIN_ALLOW_THREADS;
2468 cursor->c_close(cursor);
2469 MYDB_END_ALLOW_THREADS;
2470 return list;
2471}
2472
2473
2474static PyObject*
2475DB_keys(DBObject* self, PyObject* args)
2476{
2477 PyObject* txnobj = NULL;
2478 DB_TXN *txn = NULL;
2479
2480 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2481 return NULL;
2482 if (!checkTxnObj(txnobj, &txn))
2483 return NULL;
2484 return _DB_make_list(self, txn, _KEYS_LIST);
2485}
2486
2487
2488static PyObject*
2489DB_items(DBObject* self, PyObject* args)
2490{
2491 PyObject* txnobj = NULL;
2492 DB_TXN *txn = NULL;
2493
2494 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2495 return NULL;
2496 if (!checkTxnObj(txnobj, &txn))
2497 return NULL;
2498 return _DB_make_list(self, txn, _ITEMS_LIST);
2499}
2500
2501
2502static PyObject*
2503DB_values(DBObject* self, PyObject* args)
2504{
2505 PyObject* txnobj = NULL;
2506 DB_TXN *txn = NULL;
2507
2508 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2509 return NULL;
2510 if (!checkTxnObj(txnobj, &txn))
2511 return NULL;
2512 return _DB_make_list(self, txn, _VALUES_LIST);
2513}
2514
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002515/* --------------------------------------------------------------------- */
2516/* DBCursor methods */
2517
2518
2519static PyObject*
2520DBC_close(DBCursorObject* self, PyObject* args)
2521{
2522 int err = 0;
2523
2524 if (!PyArg_ParseTuple(args, ":close"))
2525 return NULL;
2526
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002527 if (self->dbc != NULL) {
2528 MYDB_BEGIN_ALLOW_THREADS;
2529 err = self->dbc->c_close(self->dbc);
2530 self->dbc = NULL;
2531 MYDB_END_ALLOW_THREADS;
2532 }
2533 RETURN_IF_ERR();
2534 RETURN_NONE();
2535}
2536
2537
2538static PyObject*
2539DBC_count(DBCursorObject* self, PyObject* args)
2540{
2541 int err = 0;
2542 db_recno_t count;
2543 int flags = 0;
2544
2545 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2546 return NULL;
2547
2548 CHECK_CURSOR_NOT_CLOSED(self);
2549
2550 MYDB_BEGIN_ALLOW_THREADS;
2551 err = self->dbc->c_count(self->dbc, &count, flags);
2552 MYDB_END_ALLOW_THREADS;
2553 RETURN_IF_ERR();
2554
2555 return PyInt_FromLong(count);
2556}
2557
2558
2559static PyObject*
2560DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2561{
2562 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2563}
2564
2565
2566static PyObject*
2567DBC_delete(DBCursorObject* self, PyObject* args)
2568{
2569 int err, flags=0;
2570
2571 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2572 return NULL;
2573
2574 CHECK_CURSOR_NOT_CLOSED(self);
2575
2576 MYDB_BEGIN_ALLOW_THREADS;
2577 err = self->dbc->c_del(self->dbc, flags);
2578 MYDB_END_ALLOW_THREADS;
2579 RETURN_IF_ERR();
2580
2581 self->mydb->haveStat = 0;
2582 RETURN_NONE();
2583}
2584
2585
2586static PyObject*
2587DBC_dup(DBCursorObject* self, PyObject* args)
2588{
2589 int err, flags =0;
2590 DBC* dbc = NULL;
2591
2592 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2593 return NULL;
2594
2595 CHECK_CURSOR_NOT_CLOSED(self);
2596
2597 MYDB_BEGIN_ALLOW_THREADS;
2598 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2599 MYDB_END_ALLOW_THREADS;
2600 RETURN_IF_ERR();
2601
2602 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2603}
2604
2605static PyObject*
2606DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2607{
2608 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2609}
2610
2611
2612static PyObject*
2613DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2614{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00002615 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002616 PyObject* keyobj = NULL;
2617 PyObject* dataobj = NULL;
2618 PyObject* retval = NULL;
2619 int dlen = -1;
2620 int doff = -1;
2621 DBT key, data;
2622 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2623
2624 CLEAR_DBT(key);
2625 CLEAR_DBT(data);
2626 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002627 &flags, &dlen, &doff))
2628 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002629 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002630 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2631 &kwnames[1],
2632 &keyobj, &flags, &dlen, &doff))
2633 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002634 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002635 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2636 kwnames, &keyobj, &dataobj,
2637 &flags, &dlen, &doff))
2638 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002639 return NULL;
2640 }
2641 }
2642 }
2643
2644 CHECK_CURSOR_NOT_CLOSED(self);
2645
2646 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2647 return NULL;
2648 if (dataobj && !make_dbt(dataobj, &data))
2649 return NULL;
2650 if (!add_partial_dbt(&data, dlen, doff))
2651 return NULL;
2652
2653 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2654 data.flags = DB_DBT_MALLOC;
2655 key.flags = DB_DBT_MALLOC;
2656 }
2657
2658 MYDB_BEGIN_ALLOW_THREADS;
2659 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2660 MYDB_END_ALLOW_THREADS;
2661
2662
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002663 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002664 Py_INCREF(Py_None);
2665 retval = Py_None;
2666 }
2667 else if (makeDBError(err)) {
2668 retval = NULL;
2669 }
2670 else {
2671 switch (_DB_get_type(self->mydb)) {
2672 case -1:
2673 retval = NULL;
2674 break;
2675 case DB_BTREE:
2676 case DB_HASH:
2677 default:
2678 retval = Py_BuildValue("s#s#", key.data, key.size,
2679 data.data, data.size);
2680 break;
2681 case DB_RECNO:
2682 case DB_QUEUE:
2683 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2684 data.data, data.size);
2685 break;
2686 }
2687 FREE_DBT(key);
2688 FREE_DBT(data);
2689 }
2690 return retval;
2691}
2692
2693
2694static PyObject*
2695DBC_get_recno(DBCursorObject* self, PyObject* args)
2696{
2697 int err;
2698 db_recno_t recno;
2699 DBT key;
2700 DBT data;
2701
2702 if (!PyArg_ParseTuple(args, ":get_recno"))
2703 return NULL;
2704
2705 CHECK_CURSOR_NOT_CLOSED(self);
2706
2707 CLEAR_DBT(key);
2708 CLEAR_DBT(data);
2709 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2710 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2711 data.flags = DB_DBT_MALLOC;
2712 key.flags = DB_DBT_MALLOC;
2713 }
2714
2715 MYDB_BEGIN_ALLOW_THREADS;
2716 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
2717 MYDB_END_ALLOW_THREADS;
2718 RETURN_IF_ERR();
2719
2720 recno = *((db_recno_t*)data.data);
2721 FREE_DBT(key);
2722 FREE_DBT(data);
2723 return PyInt_FromLong(recno);
2724}
2725
2726
2727static PyObject*
2728DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2729{
2730 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
2731}
2732
2733
2734static PyObject*
2735DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2736{
2737 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
2738}
2739
2740
2741static PyObject*
2742DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2743{
2744 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
2745}
2746
2747
2748static PyObject*
2749DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2750{
2751 int err, flags = 0;
2752 PyObject* keyobj, *dataobj;
2753 DBT key, data;
2754 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
2755 int dlen = -1;
2756 int doff = -1;
2757
2758 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
2759 &keyobj, &dataobj, &flags, &dlen, &doff))
2760 return NULL;
2761
2762 CHECK_CURSOR_NOT_CLOSED(self);
2763
2764 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2765 return NULL;
2766 if (!make_dbt(dataobj, &data))
2767 return NULL;
2768 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
2769
2770 MYDB_BEGIN_ALLOW_THREADS;
2771 err = self->dbc->c_put(self->dbc, &key, &data, flags);
2772 MYDB_END_ALLOW_THREADS;
2773 FREE_DBT(key);
2774 RETURN_IF_ERR();
2775 self->mydb->haveStat = 0;
2776 RETURN_NONE();
2777}
2778
2779
2780static PyObject*
2781DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2782{
2783 int err, flags = 0;
2784 DBT key, data;
2785 PyObject* retval, *keyobj;
2786 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2787 int dlen = -1;
2788 int doff = -1;
2789
2790 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
2791 &keyobj, &flags, &dlen, &doff))
2792 return NULL;
2793
2794 CHECK_CURSOR_NOT_CLOSED(self);
2795
2796 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2797 return NULL;
2798
2799 CLEAR_DBT(data);
2800 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2801 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2802 data.flags = DB_DBT_MALLOC;
2803 }
2804 if (!add_partial_dbt(&data, dlen, doff))
2805 return NULL;
2806
2807 MYDB_BEGIN_ALLOW_THREADS;
2808 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
2809 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002810 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2811 Py_INCREF(Py_None);
2812 retval = Py_None;
2813 }
2814 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002815 retval = NULL;
2816 }
2817 else {
2818 switch (_DB_get_type(self->mydb)) {
2819 case -1:
2820 retval = NULL;
2821 break;
2822 case DB_BTREE:
2823 case DB_HASH:
2824 default:
2825 retval = Py_BuildValue("s#s#", key.data, key.size,
2826 data.data, data.size);
2827 break;
2828 case DB_RECNO:
2829 case DB_QUEUE:
2830 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2831 data.data, data.size);
2832 break;
2833 }
2834 FREE_DBT(key);
2835 FREE_DBT(data);
2836 }
2837
2838 return retval;
2839}
2840
2841
2842static PyObject*
2843DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2844{
2845 int err, flags = 0;
2846 DBT key, data;
2847 PyObject* retval, *keyobj;
2848 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2849 int dlen = -1;
2850 int doff = -1;
2851
2852 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
2853 &keyobj, &flags, &dlen, &doff))
2854 return NULL;
2855
2856 CHECK_CURSOR_NOT_CLOSED(self);
2857
2858 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2859 return NULL;
2860
2861 CLEAR_DBT(data);
2862 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2863 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2864 data.flags = DB_DBT_MALLOC;
2865 key.flags = DB_DBT_MALLOC;
2866 }
2867 if (!add_partial_dbt(&data, dlen, doff))
2868 return NULL;
2869 MYDB_BEGIN_ALLOW_THREADS;
2870 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
2871 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002872 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2873 Py_INCREF(Py_None);
2874 retval = Py_None;
2875 }
2876 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002877 retval = NULL;
2878 }
2879 else {
2880 switch (_DB_get_type(self->mydb)) {
2881 case -1:
2882 retval = NULL;
2883 break;
2884 case DB_BTREE:
2885 case DB_HASH:
2886 default:
2887 retval = Py_BuildValue("s#s#", key.data, key.size,
2888 data.data, data.size);
2889 break;
2890 case DB_RECNO:
2891 case DB_QUEUE:
2892 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2893 data.data, data.size);
2894 break;
2895 }
2896 FREE_DBT(key);
2897 FREE_DBT(data);
2898 }
2899
2900 return retval;
2901}
2902
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002903static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002904_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
2905 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002906{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002907 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002908 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002909 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002910
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002911 // the caller did this: CHECK_CURSOR_NOT_CLOSED(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002912 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2913 return NULL;
2914 if (!make_dbt(dataobj, &data))
2915 return NULL;
2916
2917 MYDB_BEGIN_ALLOW_THREADS;
2918 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
2919 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002920 if ((err == DB_NOTFOUND) && returnsNone) {
2921 Py_INCREF(Py_None);
2922 retval = Py_None;
2923 }
2924 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002925 retval = NULL;
2926 }
2927 else {
2928 switch (_DB_get_type(self->mydb)) {
2929 case -1:
2930 retval = NULL;
2931 break;
2932 case DB_BTREE:
2933 case DB_HASH:
2934 default:
2935 retval = Py_BuildValue("s#s#", key.data, key.size,
2936 data.data, data.size);
2937 break;
2938 case DB_RECNO:
2939 case DB_QUEUE:
2940 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2941 data.data, data.size);
2942 break;
2943 }
2944 }
2945
2946 FREE_DBT(key);
2947 return retval;
2948}
2949
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002950static PyObject*
2951DBC_get_both(DBCursorObject* self, PyObject* args)
2952{
2953 int flags=0;
2954 PyObject *keyobj, *dataobj;
2955
2956 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
2957 return NULL;
2958
2959 // if the cursor is closed, self->mydb may be invalid
2960 CHECK_CURSOR_NOT_CLOSED(self);
2961
2962 return _DBC_get_set_both(self, keyobj, dataobj, flags,
2963 self->mydb->moduleFlags.getReturnsNone);
2964}
2965
2966static PyObject*
2967DBC_set_both(DBCursorObject* self, PyObject* args)
2968{
2969 int flags=0;
2970 PyObject *keyobj, *dataobj;
2971
2972 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
2973 return NULL;
2974
2975 // if the cursor is closed, self->mydb may be invalid
2976 CHECK_CURSOR_NOT_CLOSED(self);
2977
2978 return _DBC_get_set_both(self, keyobj, dataobj, flags,
2979 self->mydb->moduleFlags.cursorSetReturnsNone);
2980}
2981
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002982
2983static PyObject*
2984DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2985{
2986 int err, irecno, flags=0;
2987 db_recno_t recno;
2988 DBT key, data;
2989 PyObject* retval;
2990 int dlen = -1;
2991 int doff = -1;
2992 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
2993
2994 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
2995 &irecno, &flags, &dlen, &doff))
2996 return NULL;
2997
2998 CHECK_CURSOR_NOT_CLOSED(self);
2999
3000 CLEAR_DBT(key);
3001 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003002 /* use allocated space so DB will be able to realloc room for the real
3003 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003004 key.data = malloc(sizeof(db_recno_t));
3005 if (key.data == NULL) {
3006 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3007 return NULL;
3008 }
3009 key.size = sizeof(db_recno_t);
3010 key.ulen = key.size;
3011 memcpy(key.data, &recno, sizeof(db_recno_t));
3012 key.flags = DB_DBT_REALLOC;
3013
3014 CLEAR_DBT(data);
3015 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3016 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3017 data.flags = DB_DBT_MALLOC;
3018 }
3019 if (!add_partial_dbt(&data, dlen, doff))
3020 return NULL;
3021
3022 MYDB_BEGIN_ALLOW_THREADS;
3023 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3024 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003025 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3026 Py_INCREF(Py_None);
3027 retval = Py_None;
3028 }
3029 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003030 retval = NULL;
3031 }
3032 else { /* Can only be used for BTrees, so no need to return int key */
3033 retval = Py_BuildValue("s#s#", key.data, key.size,
3034 data.data, data.size);
3035 FREE_DBT(key);
3036 FREE_DBT(data);
3037 }
3038
3039 return retval;
3040}
3041
3042
3043static PyObject*
3044DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3045{
3046 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3047}
3048
3049
3050static PyObject*
3051DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3052{
3053 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3054}
3055
3056
3057static PyObject*
3058DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3059{
3060 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3061}
3062
3063
3064static PyObject*
3065DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3066{
3067 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3068}
3069
3070
3071static PyObject*
3072DBC_join_item(DBCursorObject* self, PyObject* args)
3073{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003074 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003075 DBT key, data;
3076 PyObject* retval;
3077
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003078 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003079 return NULL;
3080
3081 CHECK_CURSOR_NOT_CLOSED(self);
3082
3083 CLEAR_DBT(key);
3084 CLEAR_DBT(data);
3085 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3086 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3087 key.flags = DB_DBT_MALLOC;
3088 }
3089
3090 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003091 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003092 MYDB_END_ALLOW_THREADS;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003093 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3094 Py_INCREF(Py_None);
3095 retval = Py_None;
3096 }
3097 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003098 retval = NULL;
3099 }
3100 else {
Gregory P. Smith84261d22003-07-07 19:06:45 +00003101 retval = Py_BuildValue("s#", key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003102 FREE_DBT(key);
3103 }
3104
3105 return retval;
3106}
3107
3108
3109
3110/* --------------------------------------------------------------------- */
3111/* DBEnv methods */
3112
3113
3114static PyObject*
3115DBEnv_close(DBEnvObject* self, PyObject* args)
3116{
3117 int err, flags = 0;
3118
3119 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3120 return NULL;
3121 if (!self->closed) { /* Don't close more than once */
3122 MYDB_BEGIN_ALLOW_THREADS;
3123 err = self->db_env->close(self->db_env, flags);
3124 MYDB_END_ALLOW_THREADS;
3125 /* after calling DBEnv->close, regardless of error, this DBEnv
3126 * may not be accessed again (BerkeleyDB docs). */
3127 self->closed = 1;
3128 self->db_env = NULL;
3129 RETURN_IF_ERR();
3130 }
3131 RETURN_NONE();
3132}
3133
3134
3135static PyObject*
3136DBEnv_open(DBEnvObject* self, PyObject* args)
3137{
3138 int err, flags=0, mode=0660;
3139 char *db_home;
3140
3141 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3142 return NULL;
3143
3144 CHECK_ENV_NOT_CLOSED(self);
3145
3146 MYDB_BEGIN_ALLOW_THREADS;
3147 err = self->db_env->open(self->db_env, db_home, flags, mode);
3148 MYDB_END_ALLOW_THREADS;
3149 RETURN_IF_ERR();
3150 self->closed = 0;
3151 self->flags = flags;
3152 RETURN_NONE();
3153}
3154
3155
3156static PyObject*
3157DBEnv_remove(DBEnvObject* self, PyObject* args)
3158{
3159 int err, flags=0;
3160 char *db_home;
3161
3162 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3163 return NULL;
3164 CHECK_ENV_NOT_CLOSED(self);
3165 MYDB_BEGIN_ALLOW_THREADS;
3166 err = self->db_env->remove(self->db_env, db_home, flags);
3167 MYDB_END_ALLOW_THREADS;
3168 RETURN_IF_ERR();
3169 RETURN_NONE();
3170}
3171
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003172#if (DBVER >= 41)
3173static PyObject*
3174DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3175{
3176 int err;
3177 u_int32_t flags=0;
3178 char *file = NULL;
3179 char *database = NULL;
3180 PyObject *txnobj = NULL;
3181 DB_TXN *txn = NULL;
3182 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3183
3184 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3185 &file, &database, &txnobj, &flags)) {
3186 return NULL;
3187 }
3188 if (!checkTxnObj(txnobj, &txn)) {
3189 return NULL;
3190 }
3191 CHECK_ENV_NOT_CLOSED(self);
3192 MYDB_BEGIN_ALLOW_THREADS;
3193 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3194 MYDB_END_ALLOW_THREADS;
3195 RETURN_IF_ERR();
3196 RETURN_NONE();
3197}
3198
3199static PyObject*
3200DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3201{
3202 int err;
3203 u_int32_t flags=0;
3204 char *file = NULL;
3205 char *database = NULL;
3206 char *newname = NULL;
3207 PyObject *txnobj = NULL;
3208 DB_TXN *txn = NULL;
3209 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3210
3211 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3212 &file, &database, &newname, &txnobj, &flags)) {
3213 return NULL;
3214 }
3215 if (!checkTxnObj(txnobj, &txn)) {
3216 return NULL;
3217 }
3218 CHECK_ENV_NOT_CLOSED(self);
3219 MYDB_BEGIN_ALLOW_THREADS;
3220 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3221 flags);
3222 MYDB_END_ALLOW_THREADS;
3223 RETURN_IF_ERR();
3224 RETURN_NONE();
3225}
3226
3227static PyObject*
3228DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3229{
3230 int err;
3231 u_int32_t flags=0;
3232 char *passwd = NULL;
3233 char* kwnames[] = { "passwd", "flags", NULL };
3234
3235 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3236 &passwd, &flags)) {
3237 return NULL;
3238 }
3239
3240 MYDB_BEGIN_ALLOW_THREADS;
3241 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3242 MYDB_END_ALLOW_THREADS;
3243
3244 RETURN_IF_ERR();
3245 RETURN_NONE();
3246}
3247#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003248
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00003249#if (DBVER >= 40)
3250static PyObject*
3251DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3252{
3253 int err;
3254 u_int32_t flags=0;
3255 u_int32_t timeout = 0;
3256 char* kwnames[] = { "timeout", "flags", NULL };
3257
3258 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3259 &timeout, &flags)) {
3260 return NULL;
3261 }
3262
3263 MYDB_BEGIN_ALLOW_THREADS;
3264 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3265 MYDB_END_ALLOW_THREADS;
3266
3267 RETURN_IF_ERR();
3268 RETURN_NONE();
3269}
3270#endif /* DBVER >= 40 */
3271
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003272static PyObject*
3273DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3274{
3275 int err, gbytes=0, bytes=0, ncache=0;
3276
3277 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3278 &gbytes, &bytes, &ncache))
3279 return NULL;
3280 CHECK_ENV_NOT_CLOSED(self);
3281
3282 MYDB_BEGIN_ALLOW_THREADS;
3283 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3284 MYDB_END_ALLOW_THREADS;
3285 RETURN_IF_ERR();
3286 RETURN_NONE();
3287}
3288
3289
3290#if (DBVER >= 32)
3291static PyObject*
3292DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3293{
3294 int err, flags=0, onoff=0;
3295
3296 if (!PyArg_ParseTuple(args, "ii:set_flags",
3297 &flags, &onoff))
3298 return NULL;
3299 CHECK_ENV_NOT_CLOSED(self);
3300
3301 MYDB_BEGIN_ALLOW_THREADS;
3302 err = self->db_env->set_flags(self->db_env, flags, onoff);
3303 MYDB_END_ALLOW_THREADS;
3304 RETURN_IF_ERR();
3305 RETURN_NONE();
3306}
3307#endif
3308
3309
3310static PyObject*
3311DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3312{
3313 int err;
3314 char *dir;
3315
3316 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3317 return NULL;
3318 CHECK_ENV_NOT_CLOSED(self);
3319
3320 MYDB_BEGIN_ALLOW_THREADS;
3321 err = self->db_env->set_data_dir(self->db_env, dir);
3322 MYDB_END_ALLOW_THREADS;
3323 RETURN_IF_ERR();
3324 RETURN_NONE();
3325}
3326
3327
3328static PyObject*
3329DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3330{
3331 int err, lg_bsize;
3332
3333 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3334 return NULL;
3335 CHECK_ENV_NOT_CLOSED(self);
3336
3337 MYDB_BEGIN_ALLOW_THREADS;
3338 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3339 MYDB_END_ALLOW_THREADS;
3340 RETURN_IF_ERR();
3341 RETURN_NONE();
3342}
3343
3344
3345static PyObject*
3346DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3347{
3348 int err;
3349 char *dir;
3350
3351 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3352 return NULL;
3353 CHECK_ENV_NOT_CLOSED(self);
3354
3355 MYDB_BEGIN_ALLOW_THREADS;
3356 err = self->db_env->set_lg_dir(self->db_env, dir);
3357 MYDB_END_ALLOW_THREADS;
3358 RETURN_IF_ERR();
3359 RETURN_NONE();
3360}
3361
3362static PyObject*
3363DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3364{
3365 int err, lg_max;
3366
3367 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3368 return NULL;
3369 CHECK_ENV_NOT_CLOSED(self);
3370
3371 MYDB_BEGIN_ALLOW_THREADS;
3372 err = self->db_env->set_lg_max(self->db_env, lg_max);
3373 MYDB_END_ALLOW_THREADS;
3374 RETURN_IF_ERR();
3375 RETURN_NONE();
3376}
3377
3378
3379static PyObject*
3380DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3381{
3382 int err, lk_detect;
3383
3384 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3385 return NULL;
3386 CHECK_ENV_NOT_CLOSED(self);
3387
3388 MYDB_BEGIN_ALLOW_THREADS;
3389 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3390 MYDB_END_ALLOW_THREADS;
3391 RETURN_IF_ERR();
3392 RETURN_NONE();
3393}
3394
3395
3396static PyObject*
3397DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3398{
3399 int err, max;
3400
3401 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3402 return NULL;
3403 CHECK_ENV_NOT_CLOSED(self);
3404
3405 MYDB_BEGIN_ALLOW_THREADS;
3406 err = self->db_env->set_lk_max(self->db_env, max);
3407 MYDB_END_ALLOW_THREADS;
3408 RETURN_IF_ERR();
3409 RETURN_NONE();
3410}
3411
3412
3413#if (DBVER >= 32)
3414
3415static PyObject*
3416DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3417{
3418 int err, max;
3419
3420 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3421 return NULL;
3422 CHECK_ENV_NOT_CLOSED(self);
3423
3424 MYDB_BEGIN_ALLOW_THREADS;
3425 err = self->db_env->set_lk_max_locks(self->db_env, max);
3426 MYDB_END_ALLOW_THREADS;
3427 RETURN_IF_ERR();
3428 RETURN_NONE();
3429}
3430
3431
3432static PyObject*
3433DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3434{
3435 int err, max;
3436
3437 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3438 return NULL;
3439 CHECK_ENV_NOT_CLOSED(self);
3440
3441 MYDB_BEGIN_ALLOW_THREADS;
3442 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3443 MYDB_END_ALLOW_THREADS;
3444 RETURN_IF_ERR();
3445 RETURN_NONE();
3446}
3447
3448
3449static PyObject*
3450DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3451{
3452 int err, max;
3453
3454 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3455 return NULL;
3456 CHECK_ENV_NOT_CLOSED(self);
3457
3458 MYDB_BEGIN_ALLOW_THREADS;
3459 err = self->db_env->set_lk_max_objects(self->db_env, max);
3460 MYDB_END_ALLOW_THREADS;
3461 RETURN_IF_ERR();
3462 RETURN_NONE();
3463}
3464
3465#endif
3466
3467
3468static PyObject*
3469DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3470{
3471 int err, mp_mmapsize;
3472
3473 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3474 return NULL;
3475 CHECK_ENV_NOT_CLOSED(self);
3476
3477 MYDB_BEGIN_ALLOW_THREADS;
3478 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3479 MYDB_END_ALLOW_THREADS;
3480 RETURN_IF_ERR();
3481 RETURN_NONE();
3482}
3483
3484
3485static PyObject*
3486DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3487{
3488 int err;
3489 char *dir;
3490
3491 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3492 return NULL;
3493 CHECK_ENV_NOT_CLOSED(self);
3494
3495 MYDB_BEGIN_ALLOW_THREADS;
3496 err = self->db_env->set_tmp_dir(self->db_env, dir);
3497 MYDB_END_ALLOW_THREADS;
3498 RETURN_IF_ERR();
3499 RETURN_NONE();
3500}
3501
3502
3503static PyObject*
3504DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3505{
3506 int flags = 0;
3507 PyObject* txnobj = NULL;
3508 DB_TXN *txn = NULL;
3509 char* kwnames[] = { "parent", "flags", NULL };
3510
3511 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3512 &txnobj, &flags))
3513 return NULL;
3514
3515 if (!checkTxnObj(txnobj, &txn))
3516 return NULL;
3517 CHECK_ENV_NOT_CLOSED(self);
3518
3519 return (PyObject*)newDBTxnObject(self, txn, flags);
3520}
3521
3522
3523static PyObject*
3524DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3525{
3526 int err, kbyte=0, min=0, flags=0;
3527
3528 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3529 return NULL;
3530 CHECK_ENV_NOT_CLOSED(self);
3531
3532 MYDB_BEGIN_ALLOW_THREADS;
3533#if (DBVER >= 40)
3534 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3535#else
3536 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3537#endif
3538 MYDB_END_ALLOW_THREADS;
3539 RETURN_IF_ERR();
3540 RETURN_NONE();
3541}
3542
3543
3544static PyObject*
3545DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3546{
3547 int err, max;
3548
3549 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3550 return NULL;
3551 CHECK_ENV_NOT_CLOSED(self);
3552
3553 MYDB_BEGIN_ALLOW_THREADS;
3554 err = self->db_env->set_tx_max(self->db_env, max);
3555 MYDB_END_ALLOW_THREADS;
3556 RETURN_IF_ERR();
3557 RETURN_NONE();
3558}
3559
3560
3561static PyObject*
3562DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3563{
3564 int err, atype, flags=0;
3565 int aborted = 0;
3566
3567 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3568 return NULL;
3569 CHECK_ENV_NOT_CLOSED(self);
3570
3571 MYDB_BEGIN_ALLOW_THREADS;
3572#if (DBVER >= 40)
3573 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3574#else
3575 err = lock_detect(self->db_env, flags, atype, &aborted);
3576#endif
3577 MYDB_END_ALLOW_THREADS;
3578 RETURN_IF_ERR();
3579 return PyInt_FromLong(aborted);
3580}
3581
3582
3583static PyObject*
3584DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3585{
3586 int flags=0;
3587 int locker, lock_mode;
3588 DBT obj;
3589 PyObject* objobj;
3590
3591 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3592 return NULL;
3593
3594
3595 if (!make_dbt(objobj, &obj))
3596 return NULL;
3597
3598 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3599}
3600
3601
3602static PyObject*
3603DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3604{
3605 int err;
3606 u_int32_t theID;
3607
3608 if (!PyArg_ParseTuple(args, ":lock_id"))
3609 return NULL;
3610
3611 CHECK_ENV_NOT_CLOSED(self);
3612 MYDB_BEGIN_ALLOW_THREADS;
3613#if (DBVER >= 40)
3614 err = self->db_env->lock_id(self->db_env, &theID);
3615#else
3616 err = lock_id(self->db_env, &theID);
3617#endif
3618 MYDB_END_ALLOW_THREADS;
3619 RETURN_IF_ERR();
3620
3621 return PyInt_FromLong((long)theID);
3622}
3623
3624
3625static PyObject*
3626DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3627{
3628 int err;
3629 DBLockObject* dblockobj;
3630
3631 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3632 return NULL;
3633
3634 CHECK_ENV_NOT_CLOSED(self);
3635 MYDB_BEGIN_ALLOW_THREADS;
3636#if (DBVER >= 40)
3637 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3638#else
3639 err = lock_put(self->db_env, &dblockobj->lock);
3640#endif
3641 MYDB_END_ALLOW_THREADS;
3642 RETURN_IF_ERR();
3643 RETURN_NONE();
3644}
3645
3646
3647static PyObject*
3648DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
3649{
3650 int err;
3651 DB_LOCK_STAT* sp;
3652 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003653 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003654
3655 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
3656 return NULL;
3657 CHECK_ENV_NOT_CLOSED(self);
3658
3659 MYDB_BEGIN_ALLOW_THREADS;
3660#if (DBVER >= 40)
3661 err = self->db_env->lock_stat(self->db_env, &sp, flags);
3662#else
3663#if (DBVER >= 33)
3664 err = lock_stat(self->db_env, &sp);
3665#else
3666 err = lock_stat(self->db_env, &sp, NULL);
3667#endif
3668#endif
3669 MYDB_END_ALLOW_THREADS;
3670 RETURN_IF_ERR();
3671
3672 /* Turn the stat structure into a dictionary */
3673 d = PyDict_New();
3674 if (d == NULL) {
3675 free(sp);
3676 return NULL;
3677 }
3678
3679#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3680
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003681#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003682 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003683#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003684 MAKE_ENTRY(nmodes);
3685#if (DBVER >= 32)
3686 MAKE_ENTRY(maxlocks);
3687 MAKE_ENTRY(maxlockers);
3688 MAKE_ENTRY(maxobjects);
3689 MAKE_ENTRY(nlocks);
3690 MAKE_ENTRY(maxnlocks);
3691#endif
3692 MAKE_ENTRY(nlockers);
3693 MAKE_ENTRY(maxnlockers);
3694#if (DBVER >= 32)
3695 MAKE_ENTRY(nobjects);
3696 MAKE_ENTRY(maxnobjects);
3697#endif
3698 MAKE_ENTRY(nrequests);
3699 MAKE_ENTRY(nreleases);
3700 MAKE_ENTRY(nnowaits);
3701 MAKE_ENTRY(nconflicts);
3702 MAKE_ENTRY(ndeadlocks);
3703 MAKE_ENTRY(regsize);
3704 MAKE_ENTRY(region_wait);
3705 MAKE_ENTRY(region_nowait);
3706
3707#undef MAKE_ENTRY
3708 free(sp);
3709 return d;
3710}
3711
3712
3713static PyObject*
3714DBEnv_log_archive(DBEnvObject* self, PyObject* args)
3715{
3716 int flags=0;
3717 int err;
3718 char **log_list_start, **log_list;
3719 PyObject* list;
3720 PyObject* item = NULL;
3721
3722 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
3723 return NULL;
3724
3725 CHECK_ENV_NOT_CLOSED(self);
3726 MYDB_BEGIN_ALLOW_THREADS;
3727#if (DBVER >= 40)
3728 err = self->db_env->log_archive(self->db_env, &log_list, flags);
3729#elif (DBVER == 33)
3730 err = log_archive(self->db_env, &log_list, flags);
3731#else
3732 err = log_archive(self->db_env, &log_list, flags, NULL);
3733#endif
3734 MYDB_END_ALLOW_THREADS;
3735 RETURN_IF_ERR();
3736
3737 list = PyList_New(0);
3738 if (list == NULL) {
3739 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
3740 return NULL;
3741 }
3742
3743 if (log_list) {
3744 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
3745 item = PyString_FromString (*log_list);
3746 if (item == NULL) {
3747 Py_DECREF(list);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003748 PyErr_SetString(PyExc_MemoryError,
3749 "List item creation failed");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003750 list = NULL;
3751 break;
3752 }
3753 PyList_Append(list, item);
3754 Py_DECREF(item);
3755 }
3756 free(log_list_start);
3757 }
3758 return list;
3759}
3760
3761
3762static PyObject*
3763DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
3764{
3765 int err;
3766 DB_TXN_STAT* sp;
3767 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003768 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003769
3770 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
3771 return NULL;
3772 CHECK_ENV_NOT_CLOSED(self);
3773
3774 MYDB_BEGIN_ALLOW_THREADS;
3775#if (DBVER >= 40)
3776 err = self->db_env->txn_stat(self->db_env, &sp, flags);
3777#elif (DBVER == 33)
3778 err = txn_stat(self->db_env, &sp);
3779#else
3780 err = txn_stat(self->db_env, &sp, NULL);
3781#endif
3782 MYDB_END_ALLOW_THREADS;
3783 RETURN_IF_ERR();
3784
3785 /* Turn the stat structure into a dictionary */
3786 d = PyDict_New();
3787 if (d == NULL) {
3788 free(sp);
3789 return NULL;
3790 }
3791
3792#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3793
3794 MAKE_ENTRY(time_ckp);
3795 MAKE_ENTRY(last_txnid);
3796 MAKE_ENTRY(maxtxns);
3797 MAKE_ENTRY(nactive);
3798 MAKE_ENTRY(maxnactive);
3799 MAKE_ENTRY(nbegins);
3800 MAKE_ENTRY(naborts);
3801 MAKE_ENTRY(ncommits);
3802 MAKE_ENTRY(regsize);
3803 MAKE_ENTRY(region_wait);
3804 MAKE_ENTRY(region_nowait);
3805
3806#undef MAKE_ENTRY
3807 free(sp);
3808 return d;
3809}
3810
3811
3812static PyObject*
3813DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
3814{
3815 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003816 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003817
3818 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
3819 return NULL;
3820 CHECK_ENV_NOT_CLOSED(self);
3821
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003822 if (self->moduleFlags.getReturnsNone)
3823 ++oldValue;
3824 if (self->moduleFlags.cursorSetReturnsNone)
3825 ++oldValue;
3826 self->moduleFlags.getReturnsNone = (flags >= 1);
3827 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003828 return PyInt_FromLong(oldValue);
3829}
3830
3831
3832/* --------------------------------------------------------------------- */
3833/* DBTxn methods */
3834
3835
3836static PyObject*
3837DBTxn_commit(DBTxnObject* self, PyObject* args)
3838{
3839 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003840 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003841
3842 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
3843 return NULL;
3844
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003845 if (!self->txn) {
3846 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3847 "DBTxn must not be used after txn_commit or txn_abort"));
3848 return NULL;
3849 }
3850 txn = self->txn;
3851 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003852 MYDB_BEGIN_ALLOW_THREADS;
3853#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003854 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003855#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003856 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003857#endif
3858 MYDB_END_ALLOW_THREADS;
3859 RETURN_IF_ERR();
3860 RETURN_NONE();
3861}
3862
3863static PyObject*
3864DBTxn_prepare(DBTxnObject* self, PyObject* args)
3865{
3866#if (DBVER >= 33)
3867 int err;
3868 char* gid=NULL;
3869 int gid_size=0;
3870
3871 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
3872 return NULL;
3873
3874 if (gid_size != DB_XIDDATASIZE) {
3875 PyErr_SetString(PyExc_TypeError,
3876 "gid must be DB_XIDDATASIZE bytes long");
3877 return NULL;
3878 }
3879
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003880 if (!self->txn) {
3881 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3882 "DBTxn must not be used after txn_commit or txn_abort"));
3883 return NULL;
3884 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003885 MYDB_BEGIN_ALLOW_THREADS;
3886#if (DBVER >= 40)
3887 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
3888#else
3889 err = txn_prepare(self->txn, (u_int8_t*)gid);
3890#endif
3891 MYDB_END_ALLOW_THREADS;
3892 RETURN_IF_ERR();
3893 RETURN_NONE();
3894#else
3895 int err;
3896
3897 if (!PyArg_ParseTuple(args, ":prepare"))
3898 return NULL;
3899
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003900 if (!self->txn) {
3901 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3902 "DBTxn must not be used after txn_commit or txn_abort"));
3903 return NULL;
3904 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003905 MYDB_BEGIN_ALLOW_THREADS;
3906 err = txn_prepare(self->txn);
3907 MYDB_END_ALLOW_THREADS;
3908 RETURN_IF_ERR();
3909 RETURN_NONE();
3910#endif
3911}
3912
3913
3914static PyObject*
3915DBTxn_abort(DBTxnObject* self, PyObject* args)
3916{
3917 int err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003918 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003919
3920 if (!PyArg_ParseTuple(args, ":abort"))
3921 return NULL;
3922
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003923 if (!self->txn) {
3924 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3925 "DBTxn must not be used after txn_commit or txn_abort"));
3926 return NULL;
3927 }
3928 txn = self->txn;
3929 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003930 MYDB_BEGIN_ALLOW_THREADS;
3931#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003932 err = txn->abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003933#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003934 err = txn_abort(txn);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003935#endif
3936 MYDB_END_ALLOW_THREADS;
3937 RETURN_IF_ERR();
3938 RETURN_NONE();
3939}
3940
3941
3942static PyObject*
3943DBTxn_id(DBTxnObject* self, PyObject* args)
3944{
3945 int id;
3946
3947 if (!PyArg_ParseTuple(args, ":id"))
3948 return NULL;
3949
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00003950 if (!self->txn) {
3951 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3952 "DBTxn must not be used after txn_commit or txn_abort"));
3953 return NULL;
3954 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003955 MYDB_BEGIN_ALLOW_THREADS;
3956#if (DBVER >= 40)
3957 id = self->txn->id(self->txn);
3958#else
3959 id = txn_id(self->txn);
3960#endif
3961 MYDB_END_ALLOW_THREADS;
3962 return PyInt_FromLong(id);
3963}
3964
3965/* --------------------------------------------------------------------- */
3966/* Method definition tables and type objects */
3967
3968static PyMethodDef DB_methods[] = {
3969 {"append", (PyCFunction)DB_append, METH_VARARGS},
3970#if (DBVER >= 33)
3971 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
3972#endif
3973 {"close", (PyCFunction)DB_close, METH_VARARGS},
3974#if (DBVER >= 32)
3975 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
3976 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
3977#endif
3978 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
3979 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
3980 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
3981 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
3982 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
3983 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
3984 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
3985 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
3986 {"join", (PyCFunction)DB_join, METH_VARARGS},
3987 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
3988 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
3989 {"items", (PyCFunction)DB_items, METH_VARARGS},
3990 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
3991 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
3992 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
3993 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
3994 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
3995 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
3996 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003997#if (DBVER >= 41)
3998 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
3999#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004000 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4001 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4002 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4003 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4004 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4005 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4006 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4007 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4008 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4009#if (DBVER >= 32)
4010 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4011#endif
4012 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4013 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4014#if (DBVER >= 33)
4015 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4016#endif
4017 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4018 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4019 {"values", (PyCFunction)DB_values, METH_VARARGS},
4020 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4021 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4022 {NULL, NULL} /* sentinel */
4023};
4024
4025
4026static PyMappingMethods DB_mapping = {
4027 (inquiry)DB_length, /*mp_length*/
4028 (binaryfunc)DB_subscript, /*mp_subscript*/
4029 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4030};
4031
4032
4033static PyMethodDef DBCursor_methods[] = {
4034 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4035 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4036 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4037 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4038 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4039 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4040 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4041 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4042 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4043 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4044 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4045 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4046 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4047 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4048 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004049 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004050 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4051 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4052 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4053 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4054 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4055 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4056 {NULL, NULL} /* sentinel */
4057};
4058
4059
4060static PyMethodDef DBEnv_methods[] = {
4061 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4062 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4063 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004064#if (DBVER >= 41)
4065 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4066 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4067 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4068#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004069#if (DBVER >= 40)
4070 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4071#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004072 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4073 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4074#if (DBVER >= 32)
4075 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4076#endif
4077 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4078 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4079 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4080 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4081 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4082#if (DBVER >= 32)
4083 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4084 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4085 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4086#endif
4087 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4088 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4089 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4090 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4091 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4092 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4093 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4094 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4095 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4096 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4097 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4098 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4099 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4100 {NULL, NULL} /* sentinel */
4101};
4102
4103
4104static PyMethodDef DBTxn_methods[] = {
4105 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4106 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4107 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4108 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4109 {NULL, NULL} /* sentinel */
4110};
4111
4112
4113static PyObject*
4114DB_getattr(DBObject* self, char *name)
4115{
4116 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4117}
4118
4119
4120static PyObject*
4121DBEnv_getattr(DBEnvObject* self, char *name)
4122{
4123 if (!strcmp(name, "db_home")) {
4124 CHECK_ENV_NOT_CLOSED(self);
4125 if (self->db_env->db_home == NULL) {
4126 RETURN_NONE();
4127 }
4128 return PyString_FromString(self->db_env->db_home);
4129 }
4130
4131 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4132}
4133
4134
4135static PyObject*
4136DBCursor_getattr(DBCursorObject* self, char *name)
4137{
4138 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4139}
4140
4141static PyObject*
4142DBTxn_getattr(DBTxnObject* self, char *name)
4143{
4144 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4145}
4146
4147static PyObject*
4148DBLock_getattr(DBLockObject* self, char *name)
4149{
4150 return NULL;
4151}
4152
4153statichere PyTypeObject DB_Type = {
4154 PyObject_HEAD_INIT(NULL)
4155 0, /*ob_size*/
4156 "DB", /*tp_name*/
4157 sizeof(DBObject), /*tp_basicsize*/
4158 0, /*tp_itemsize*/
4159 /* methods */
4160 (destructor)DB_dealloc, /*tp_dealloc*/
4161 0, /*tp_print*/
4162 (getattrfunc)DB_getattr, /*tp_getattr*/
4163 0, /*tp_setattr*/
4164 0, /*tp_compare*/
4165 0, /*tp_repr*/
4166 0, /*tp_as_number*/
4167 0, /*tp_as_sequence*/
4168 &DB_mapping,/*tp_as_mapping*/
4169 0, /*tp_hash*/
4170};
4171
4172
4173statichere PyTypeObject DBCursor_Type = {
4174 PyObject_HEAD_INIT(NULL)
4175 0, /*ob_size*/
4176 "DBCursor", /*tp_name*/
4177 sizeof(DBCursorObject), /*tp_basicsize*/
4178 0, /*tp_itemsize*/
4179 /* methods */
4180 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4181 0, /*tp_print*/
4182 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4183 0, /*tp_setattr*/
4184 0, /*tp_compare*/
4185 0, /*tp_repr*/
4186 0, /*tp_as_number*/
4187 0, /*tp_as_sequence*/
4188 0, /*tp_as_mapping*/
4189 0, /*tp_hash*/
4190};
4191
4192
4193statichere PyTypeObject DBEnv_Type = {
4194 PyObject_HEAD_INIT(NULL)
4195 0, /*ob_size*/
4196 "DBEnv", /*tp_name*/
4197 sizeof(DBEnvObject), /*tp_basicsize*/
4198 0, /*tp_itemsize*/
4199 /* methods */
4200 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4201 0, /*tp_print*/
4202 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4203 0, /*tp_setattr*/
4204 0, /*tp_compare*/
4205 0, /*tp_repr*/
4206 0, /*tp_as_number*/
4207 0, /*tp_as_sequence*/
4208 0, /*tp_as_mapping*/
4209 0, /*tp_hash*/
4210};
4211
4212statichere PyTypeObject DBTxn_Type = {
4213 PyObject_HEAD_INIT(NULL)
4214 0, /*ob_size*/
4215 "DBTxn", /*tp_name*/
4216 sizeof(DBTxnObject), /*tp_basicsize*/
4217 0, /*tp_itemsize*/
4218 /* methods */
4219 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4220 0, /*tp_print*/
4221 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4222 0, /*tp_setattr*/
4223 0, /*tp_compare*/
4224 0, /*tp_repr*/
4225 0, /*tp_as_number*/
4226 0, /*tp_as_sequence*/
4227 0, /*tp_as_mapping*/
4228 0, /*tp_hash*/
4229};
4230
4231
4232statichere PyTypeObject DBLock_Type = {
4233 PyObject_HEAD_INIT(NULL)
4234 0, /*ob_size*/
4235 "DBLock", /*tp_name*/
4236 sizeof(DBLockObject), /*tp_basicsize*/
4237 0, /*tp_itemsize*/
4238 /* methods */
4239 (destructor)DBLock_dealloc, /*tp_dealloc*/
4240 0, /*tp_print*/
4241 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4242 0, /*tp_setattr*/
4243 0, /*tp_compare*/
4244 0, /*tp_repr*/
4245 0, /*tp_as_number*/
4246 0, /*tp_as_sequence*/
4247 0, /*tp_as_mapping*/
4248 0, /*tp_hash*/
4249};
4250
4251
4252/* --------------------------------------------------------------------- */
4253/* Module-level functions */
4254
4255static PyObject*
4256DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4257{
4258 PyObject* dbenvobj = NULL;
4259 int flags = 0;
4260 char* kwnames[] = { "dbEnv", "flags", NULL};
4261
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004262 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4263 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004264 return NULL;
4265 if (dbenvobj == Py_None)
4266 dbenvobj = NULL;
4267 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4268 makeTypeError("DBEnv", dbenvobj);
4269 return NULL;
4270 }
4271
4272 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4273}
4274
4275
4276static PyObject*
4277DBEnv_construct(PyObject* self, PyObject* args)
4278{
4279 int flags = 0;
4280 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4281 return (PyObject* )newDBEnvObject(flags);
4282}
4283
4284
4285static char bsddb_version_doc[] =
4286"Returns a tuple of major, minor, and patch release numbers of the\n\
4287underlying DB library.";
4288
4289static PyObject*
4290bsddb_version(PyObject* self, PyObject* args)
4291{
4292 int major, minor, patch;
4293
4294 if (!PyArg_ParseTuple(args, ":version"))
4295 return NULL;
4296 db_version(&major, &minor, &patch);
4297 return Py_BuildValue("(iii)", major, minor, patch);
4298}
4299
4300
4301/* List of functions defined in the module */
4302
4303static PyMethodDef bsddb_methods[] = {
4304 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4305 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4306 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4307 {NULL, NULL} /* sentinel */
4308};
4309
4310
4311/* --------------------------------------------------------------------- */
4312/* Module initialization */
4313
4314
4315/* Convenience routine to export an integer value.
4316 * Errors are silently ignored, for better or for worse...
4317 */
4318#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4319
4320
4321
4322DL_EXPORT(void) init_bsddb(void)
4323{
4324 PyObject* m;
4325 PyObject* d;
4326 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4327 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4328 PyObject* cvsid_s = PyString_FromString( rcs_id );
4329
4330 /* Initialize the type of the new type objects here; doing it here
4331 is required for portability to Windows without requiring C++. */
4332 DB_Type.ob_type = &PyType_Type;
4333 DBCursor_Type.ob_type = &PyType_Type;
4334 DBEnv_Type.ob_type = &PyType_Type;
4335 DBTxn_Type.ob_type = &PyType_Type;
4336 DBLock_Type.ob_type = &PyType_Type;
4337
4338
Mark Hammonda69d4092003-04-22 23:13:27 +00004339#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004340 /* Save the current interpreter, so callbacks can do the right thing. */
4341 _db_interpreterState = PyThreadState_Get()->interp;
4342#endif
4343
4344 /* Create the module and add the functions */
4345 m = Py_InitModule("_bsddb", bsddb_methods);
4346
4347 /* Add some symbolic constants to the module */
4348 d = PyModule_GetDict(m);
4349 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4350 PyDict_SetItemString(d, "cvsid", cvsid_s);
4351 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4352 Py_DECREF(pybsddb_version_s);
4353 pybsddb_version_s = NULL;
4354 Py_DECREF(cvsid_s);
4355 cvsid_s = NULL;
4356 Py_DECREF(db_version_s);
4357 db_version_s = NULL;
4358
4359 ADD_INT(d, DB_VERSION_MAJOR);
4360 ADD_INT(d, DB_VERSION_MINOR);
4361 ADD_INT(d, DB_VERSION_PATCH);
4362
4363 ADD_INT(d, DB_MAX_PAGES);
4364 ADD_INT(d, DB_MAX_RECORDS);
4365
4366 ADD_INT(d, DB_CLIENT);
4367 ADD_INT(d, DB_XA_CREATE);
4368
4369 ADD_INT(d, DB_CREATE);
4370 ADD_INT(d, DB_NOMMAP);
4371 ADD_INT(d, DB_THREAD);
4372
4373 ADD_INT(d, DB_FORCE);
4374 ADD_INT(d, DB_INIT_CDB);
4375 ADD_INT(d, DB_INIT_LOCK);
4376 ADD_INT(d, DB_INIT_LOG);
4377 ADD_INT(d, DB_INIT_MPOOL);
4378 ADD_INT(d, DB_INIT_TXN);
4379#if (DBVER >= 32)
4380 ADD_INT(d, DB_JOINENV);
4381#endif
4382
4383 ADD_INT(d, DB_RECOVER);
4384 ADD_INT(d, DB_RECOVER_FATAL);
4385 ADD_INT(d, DB_TXN_NOSYNC);
4386 ADD_INT(d, DB_USE_ENVIRON);
4387 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4388
4389 ADD_INT(d, DB_LOCKDOWN);
4390 ADD_INT(d, DB_PRIVATE);
4391 ADD_INT(d, DB_SYSTEM_MEM);
4392
4393 ADD_INT(d, DB_TXN_SYNC);
4394 ADD_INT(d, DB_TXN_NOWAIT);
4395
4396 ADD_INT(d, DB_EXCL);
4397 ADD_INT(d, DB_FCNTL_LOCKING);
4398 ADD_INT(d, DB_ODDFILESIZE);
4399 ADD_INT(d, DB_RDWRMASTER);
4400 ADD_INT(d, DB_RDONLY);
4401 ADD_INT(d, DB_TRUNCATE);
4402#if (DBVER >= 32)
4403 ADD_INT(d, DB_EXTENT);
4404 ADD_INT(d, DB_CDB_ALLDB);
4405 ADD_INT(d, DB_VERIFY);
4406#endif
4407 ADD_INT(d, DB_UPGRADE);
4408
4409 ADD_INT(d, DB_AGGRESSIVE);
4410 ADD_INT(d, DB_NOORDERCHK);
4411 ADD_INT(d, DB_ORDERCHKONLY);
4412 ADD_INT(d, DB_PR_PAGE);
4413#if ! (DBVER >= 33)
4414 ADD_INT(d, DB_VRFY_FLAGMASK);
4415 ADD_INT(d, DB_PR_HEADERS);
4416#endif
4417 ADD_INT(d, DB_PR_RECOVERYTEST);
4418 ADD_INT(d, DB_SALVAGE);
4419
4420 ADD_INT(d, DB_LOCK_NORUN);
4421 ADD_INT(d, DB_LOCK_DEFAULT);
4422 ADD_INT(d, DB_LOCK_OLDEST);
4423 ADD_INT(d, DB_LOCK_RANDOM);
4424 ADD_INT(d, DB_LOCK_YOUNGEST);
4425#if (DBVER >= 33)
4426 ADD_INT(d, DB_LOCK_MAXLOCKS);
4427 ADD_INT(d, DB_LOCK_MINLOCKS);
4428 ADD_INT(d, DB_LOCK_MINWRITE);
4429#endif
4430
4431
4432#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004433 /* docs say to use zero instead */
4434 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004435#else
4436 ADD_INT(d, DB_LOCK_CONFLICT);
4437#endif
4438
4439 ADD_INT(d, DB_LOCK_DUMP);
4440 ADD_INT(d, DB_LOCK_GET);
4441 ADD_INT(d, DB_LOCK_INHERIT);
4442 ADD_INT(d, DB_LOCK_PUT);
4443 ADD_INT(d, DB_LOCK_PUT_ALL);
4444 ADD_INT(d, DB_LOCK_PUT_OBJ);
4445
4446 ADD_INT(d, DB_LOCK_NG);
4447 ADD_INT(d, DB_LOCK_READ);
4448 ADD_INT(d, DB_LOCK_WRITE);
4449 ADD_INT(d, DB_LOCK_NOWAIT);
4450#if (DBVER >= 32)
4451 ADD_INT(d, DB_LOCK_WAIT);
4452#endif
4453 ADD_INT(d, DB_LOCK_IWRITE);
4454 ADD_INT(d, DB_LOCK_IREAD);
4455 ADD_INT(d, DB_LOCK_IWR);
4456#if (DBVER >= 33)
4457 ADD_INT(d, DB_LOCK_DIRTY);
4458 ADD_INT(d, DB_LOCK_WWRITE);
4459#endif
4460
4461 ADD_INT(d, DB_LOCK_RECORD);
4462 ADD_INT(d, DB_LOCK_UPGRADE);
4463#if (DBVER >= 32)
4464 ADD_INT(d, DB_LOCK_SWITCH);
4465#endif
4466#if (DBVER >= 33)
4467 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4468#endif
4469
4470 ADD_INT(d, DB_LOCK_NOWAIT);
4471 ADD_INT(d, DB_LOCK_RECORD);
4472 ADD_INT(d, DB_LOCK_UPGRADE);
4473
4474#if (DBVER >= 33)
4475 ADD_INT(d, DB_LSTAT_ABORTED);
4476 ADD_INT(d, DB_LSTAT_ERR);
4477 ADD_INT(d, DB_LSTAT_FREE);
4478 ADD_INT(d, DB_LSTAT_HELD);
4479#if (DBVER == 33)
4480 ADD_INT(d, DB_LSTAT_NOGRANT);
4481#endif
4482 ADD_INT(d, DB_LSTAT_PENDING);
4483 ADD_INT(d, DB_LSTAT_WAITING);
4484#endif
4485
4486 ADD_INT(d, DB_ARCH_ABS);
4487 ADD_INT(d, DB_ARCH_DATA);
4488 ADD_INT(d, DB_ARCH_LOG);
4489
4490 ADD_INT(d, DB_BTREE);
4491 ADD_INT(d, DB_HASH);
4492 ADD_INT(d, DB_RECNO);
4493 ADD_INT(d, DB_QUEUE);
4494 ADD_INT(d, DB_UNKNOWN);
4495
4496 ADD_INT(d, DB_DUP);
4497 ADD_INT(d, DB_DUPSORT);
4498 ADD_INT(d, DB_RECNUM);
4499 ADD_INT(d, DB_RENUMBER);
4500 ADD_INT(d, DB_REVSPLITOFF);
4501 ADD_INT(d, DB_SNAPSHOT);
4502
4503 ADD_INT(d, DB_JOIN_NOSORT);
4504
4505 ADD_INT(d, DB_AFTER);
4506 ADD_INT(d, DB_APPEND);
4507 ADD_INT(d, DB_BEFORE);
4508 ADD_INT(d, DB_CACHED_COUNTS);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004509#if (DBVER >= 41)
4510 _addIntToDict(d, "DB_CHECKPOINT", 0);
4511#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004512 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004513 ADD_INT(d, DB_CURLSN);
4514#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004515#if (DBVER >= 33)
4516 ADD_INT(d, DB_COMMIT);
4517#endif
4518 ADD_INT(d, DB_CONSUME);
4519#if (DBVER >= 32)
4520 ADD_INT(d, DB_CONSUME_WAIT);
4521#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004522 ADD_INT(d, DB_CURRENT);
4523#if (DBVER >= 33)
4524 ADD_INT(d, DB_FAST_STAT);
4525#endif
4526 ADD_INT(d, DB_FIRST);
4527 ADD_INT(d, DB_FLUSH);
4528 ADD_INT(d, DB_GET_BOTH);
4529 ADD_INT(d, DB_GET_RECNO);
4530 ADD_INT(d, DB_JOIN_ITEM);
4531 ADD_INT(d, DB_KEYFIRST);
4532 ADD_INT(d, DB_KEYLAST);
4533 ADD_INT(d, DB_LAST);
4534 ADD_INT(d, DB_NEXT);
4535 ADD_INT(d, DB_NEXT_DUP);
4536 ADD_INT(d, DB_NEXT_NODUP);
4537 ADD_INT(d, DB_NODUPDATA);
4538 ADD_INT(d, DB_NOOVERWRITE);
4539 ADD_INT(d, DB_NOSYNC);
4540 ADD_INT(d, DB_POSITION);
4541 ADD_INT(d, DB_PREV);
4542 ADD_INT(d, DB_PREV_NODUP);
4543 ADD_INT(d, DB_RECORDCOUNT);
4544 ADD_INT(d, DB_SET);
4545 ADD_INT(d, DB_SET_RANGE);
4546 ADD_INT(d, DB_SET_RECNO);
4547 ADD_INT(d, DB_WRITECURSOR);
4548
4549 ADD_INT(d, DB_OPFLAGS_MASK);
4550 ADD_INT(d, DB_RMW);
4551#if (DBVER >= 33)
4552 ADD_INT(d, DB_DIRTY_READ);
4553 ADD_INT(d, DB_MULTIPLE);
4554 ADD_INT(d, DB_MULTIPLE_KEY);
4555#endif
4556
4557#if (DBVER >= 33)
4558 ADD_INT(d, DB_DONOTINDEX);
4559#endif
4560
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004561#if (DBVER >= 41)
4562 _addIntToDict(d, "DB_INCOMPLETE", 0);
4563#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004564 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004565#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004566 ADD_INT(d, DB_KEYEMPTY);
4567 ADD_INT(d, DB_KEYEXIST);
4568 ADD_INT(d, DB_LOCK_DEADLOCK);
4569 ADD_INT(d, DB_LOCK_NOTGRANTED);
4570 ADD_INT(d, DB_NOSERVER);
4571 ADD_INT(d, DB_NOSERVER_HOME);
4572 ADD_INT(d, DB_NOSERVER_ID);
4573 ADD_INT(d, DB_NOTFOUND);
4574 ADD_INT(d, DB_OLD_VERSION);
4575 ADD_INT(d, DB_RUNRECOVERY);
4576 ADD_INT(d, DB_VERIFY_BAD);
4577#if (DBVER >= 33)
4578 ADD_INT(d, DB_PAGE_NOTFOUND);
4579 ADD_INT(d, DB_SECONDARY_BAD);
4580#endif
4581#if (DBVER >= 40)
4582 ADD_INT(d, DB_STAT_CLEAR);
4583 ADD_INT(d, DB_REGION_INIT);
4584 ADD_INT(d, DB_NOLOCKING);
4585 ADD_INT(d, DB_YIELDCPU);
4586 ADD_INT(d, DB_PANIC_ENVIRONMENT);
4587 ADD_INT(d, DB_NOPANIC);
4588#endif
4589
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004590#if (DBVER >= 41)
4591 ADD_INT(d, DB_ENCRYPT_AES);
4592 ADD_INT(d, DB_AUTO_COMMIT);
4593#else
4594 /* allow berkeleydb 4.1 aware apps to run on older versions */
4595 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
4596#endif
4597
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004598 ADD_INT(d, EINVAL);
4599 ADD_INT(d, EACCES);
4600 ADD_INT(d, ENOSPC);
4601 ADD_INT(d, ENOMEM);
4602 ADD_INT(d, EAGAIN);
4603 ADD_INT(d, EBUSY);
4604 ADD_INT(d, EEXIST);
4605 ADD_INT(d, ENOENT);
4606 ADD_INT(d, EPERM);
4607
Barry Warsaw1baa9822003-03-31 19:51:29 +00004608#if (DBVER >= 40)
4609 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
4610 ADD_INT(d, DB_SET_TXN_TIMEOUT);
4611#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004612
4613 /* The base exception class is DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004614 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004615 PyDict_SetItemString(d, "DBError", DBError);
4616
4617 /* Some magic to make DBNotFoundError derive from both DBError and
4618 KeyError, since the API only supports using one base class. */
4619 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
4620 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
4621 Py_file_input, d, d);
4622 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
4623 PyDict_DelItemString(d, "KeyError");
4624
4625
4626 /* All the rest of the exceptions derive only from DBError */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004627#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004628 PyDict_SetItemString(d, #name, name)
4629
4630#if !INCOMPLETE_IS_WARNING
4631 MAKE_EX(DBIncompleteError);
4632#endif
4633 MAKE_EX(DBKeyEmptyError);
4634 MAKE_EX(DBKeyExistError);
4635 MAKE_EX(DBLockDeadlockError);
4636 MAKE_EX(DBLockNotGrantedError);
4637 MAKE_EX(DBOldVersionError);
4638 MAKE_EX(DBRunRecoveryError);
4639 MAKE_EX(DBVerifyBadError);
4640 MAKE_EX(DBNoServerError);
4641 MAKE_EX(DBNoServerHomeError);
4642 MAKE_EX(DBNoServerIDError);
4643#if (DBVER >= 33)
4644 MAKE_EX(DBPageNotFoundError);
4645 MAKE_EX(DBSecondaryBadError);
4646#endif
4647
4648 MAKE_EX(DBInvalidArgError);
4649 MAKE_EX(DBAccessError);
4650 MAKE_EX(DBNoSpaceError);
4651 MAKE_EX(DBNoMemoryError);
4652 MAKE_EX(DBAgainError);
4653 MAKE_EX(DBBusyError);
4654 MAKE_EX(DBFileExistsError);
4655 MAKE_EX(DBNoSuchFileError);
4656 MAKE_EX(DBPermissionsError);
4657
4658#undef MAKE_EX
4659
4660 /* Check for errors */
4661 if (PyErr_Occurred()) {
4662 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004663 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004664 }
4665}