source: python/vendor/Python-2.6.5/Modules/_bsddb.c

Last change on this file was 2, checked in by Yuri Dario, 15 years ago

Initial import for vendor code.

  • Property svn:eol-style set to native
File size: 202.9 KB
Line 
1/*----------------------------------------------------------------------
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,
38 * written to replace a SWIG-generated file. It has since been updated
39 * to compile with Berkeley DB versions 3.2 through 4.2.
40 *
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * Berkeley DB 2.7.x.
45 *
46 * 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@krypto.org> was once again the maintainer.
52 *
53 * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>.
54 * Jesus Cea licenses this code to PSF under a Contributor Agreement.
55 *
56 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
57 * Things can change faster than the header of this file is updated. This
58 * file is shared with the PyBSDDB project at SourceForge:
59 *
60 * http://pybsddb.sf.net
61 *
62 * This file should remain backward compatible with Python 2.1, but see PEP
63 * 291 for the most current backward compatibility requirements:
64 *
65 * http://www.python.org/peps/pep-0291.html
66 *
67 * This module contains 6 types:
68 *
69 * DB (Database)
70 * DBCursor (Database Cursor)
71 * DBEnv (database environment)
72 * DBTxn (An explicit database transaction)
73 * DBLock (A lock handle)
74 * DBSequence (Sequence)
75 *
76 */
77
78/* --------------------------------------------------------------------- */
79
80/*
81 * Portions of this module, associated unit tests and build scripts are the
82 * result of a contract with The Written Word (http://thewrittenword.com/)
83 * Many thanks go out to them for causing me to raise the bar on quality and
84 * functionality, resulting in a better bsddb3 package for all of us to use.
85 *
86 * --Robin
87 */
88
89/* --------------------------------------------------------------------- */
90
91#include <stddef.h> /* for offsetof() */
92#include <Python.h>
93
94#define COMPILING_BSDDB_C
95#include "bsddb.h"
96#undef COMPILING_BSDDB_C
97
98static char *rcs_id = "$Id: _bsddb.c 78564 2010-03-01 21:08:21Z florent.xicluna $";
99
100/* --------------------------------------------------------------------- */
101/* Various macro definitions */
102
103#if (PY_VERSION_HEX < 0x02050000)
104typedef int Py_ssize_t;
105#endif
106
107#if (PY_VERSION_HEX < 0x02060000) /* really: before python trunk r63675 */
108/* This code now uses PyBytes* API function names instead of PyString*.
109 * These #defines map to their equivalent on earlier python versions. */
110#define PyBytes_FromStringAndSize PyString_FromStringAndSize
111#define PyBytes_FromString PyString_FromString
112#define PyBytes_AsStringAndSize PyString_AsStringAndSize
113#define PyBytes_Check PyString_Check
114#define PyBytes_GET_SIZE PyString_GET_SIZE
115#define PyBytes_AS_STRING PyString_AS_STRING
116#endif
117
118#if (PY_VERSION_HEX >= 0x03000000)
119#define NUMBER_Check PyLong_Check
120#define NUMBER_AsLong PyLong_AsLong
121#define NUMBER_FromLong PyLong_FromLong
122#else
123#define NUMBER_Check PyInt_Check
124#define NUMBER_AsLong PyInt_AsLong
125#define NUMBER_FromLong PyInt_FromLong
126#endif
127
128#ifdef WITH_THREAD
129
130/* These are for when calling Python --> C */
131#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
132#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
133
134/* For 2.3, use the PyGILState_ calls */
135#if (PY_VERSION_HEX >= 0x02030000)
136#define MYDB_USE_GILSTATE
137#endif
138
139/* and these are for calling C --> Python */
140#if defined(MYDB_USE_GILSTATE)
141#define MYDB_BEGIN_BLOCK_THREADS \
142 PyGILState_STATE __savestate = PyGILState_Ensure();
143#define MYDB_END_BLOCK_THREADS \
144 PyGILState_Release(__savestate);
145#else /* MYDB_USE_GILSTATE */
146/* Pre GILState API - do it the long old way */
147static PyInterpreterState* _db_interpreterState = NULL;
148#define MYDB_BEGIN_BLOCK_THREADS { \
149 PyThreadState* prevState; \
150 PyThreadState* newState; \
151 PyEval_AcquireLock(); \
152 newState = PyThreadState_New(_db_interpreterState); \
153 prevState = PyThreadState_Swap(newState);
154
155#define MYDB_END_BLOCK_THREADS \
156 newState = PyThreadState_Swap(prevState); \
157 PyThreadState_Clear(newState); \
158 PyEval_ReleaseLock(); \
159 PyThreadState_Delete(newState); \
160 }
161#endif /* MYDB_USE_GILSTATE */
162
163#else
164/* Compiled without threads - avoid all this cruft */
165#define MYDB_BEGIN_ALLOW_THREADS
166#define MYDB_END_ALLOW_THREADS
167#define MYDB_BEGIN_BLOCK_THREADS
168#define MYDB_END_BLOCK_THREADS
169
170#endif
171
172/* Should DB_INCOMPLETE be turned into a warning or an exception? */
173#define INCOMPLETE_IS_WARNING 1
174
175/* --------------------------------------------------------------------- */
176/* Exceptions */
177
178static PyObject* DBError; /* Base class, all others derive from this */
179static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
180static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
181static PyObject* DBKeyExistError; /* DB_KEYEXIST */
182static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
183static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
184static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
185static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
186static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
187static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
188static PyObject* DBNoServerError; /* DB_NOSERVER */
189static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
190static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
191static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
192static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
193
194#if !INCOMPLETE_IS_WARNING
195static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
196#endif
197
198static PyObject* DBInvalidArgError; /* EINVAL */
199static PyObject* DBAccessError; /* EACCES */
200static PyObject* DBNoSpaceError; /* ENOSPC */
201static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
202static PyObject* DBAgainError; /* EAGAIN */
203static PyObject* DBBusyError; /* EBUSY */
204static PyObject* DBFileExistsError; /* EEXIST */
205static PyObject* DBNoSuchFileError; /* ENOENT */
206static PyObject* DBPermissionsError; /* EPERM */
207
208#if (DBVER >= 42)
209static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
210#endif
211
212static PyObject* DBRepUnavailError; /* DB_REP_UNAVAIL */
213
214#if (DBVER < 43)
215#define DB_BUFFER_SMALL ENOMEM
216#endif
217
218
219/* --------------------------------------------------------------------- */
220/* Structure definitions */
221
222#if PYTHON_API_VERSION < 1010
223#error "Python 2.1 or later required"
224#endif
225
226
227/* Defaults for moduleFlags in DBEnvObject and DBObject. */
228#define DEFAULT_GET_RETURNS_NONE 1
229#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
230
231
232/* See comment in Python 2.6 "object.h" */
233#ifndef staticforward
234#define staticforward static
235#endif
236#ifndef statichere
237#define statichere static
238#endif
239
240staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
241 DBLock_Type;
242#if (DBVER >= 43)
243staticforward PyTypeObject DBSequence_Type;
244#endif
245
246#ifndef Py_TYPE
247/* for compatibility with Python 2.5 and earlier */
248#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
249#endif
250
251#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
252#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
253#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
254#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
255#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
256#if (DBVER >= 43)
257#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
258#endif
259
260#if (DBVER < 46)
261 #define _DBC_close(dbc) dbc->c_close(dbc)
262 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
263 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
264 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
265 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
266 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
267 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
268#else
269 #define _DBC_close(dbc) dbc->close(dbc)
270 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
271 #define _DBC_del(dbc,a) dbc->del(dbc,a)
272 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
273 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
274 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
275 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
276#endif
277
278
279/* --------------------------------------------------------------------- */
280/* Utility macros and functions */
281
282#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
283 { \
284 object->sibling_next=backlink; \
285 object->sibling_prev_p=&(backlink); \
286 backlink=object; \
287 if (object->sibling_next) { \
288 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
289 } \
290 }
291
292#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
293 { \
294 if (object->sibling_next) { \
295 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
296 } \
297 *(object->sibling_prev_p)=object->sibling_next; \
298 }
299
300#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
301 { \
302 if (object->sibling_next) { \
303 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
304 } \
305 if (object->sibling_prev_p) { \
306 *(object->sibling_prev_p)=object->sibling_next; \
307 } \
308 }
309
310#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
311 { \
312 object->sibling_next_txn=backlink; \
313 object->sibling_prev_p_txn=&(backlink); \
314 backlink=object; \
315 if (object->sibling_next_txn) { \
316 object->sibling_next_txn->sibling_prev_p_txn= \
317 &(object->sibling_next_txn); \
318 } \
319 }
320
321#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
322 { \
323 if (object->sibling_next_txn) { \
324 object->sibling_next_txn->sibling_prev_p_txn= \
325 object->sibling_prev_p_txn; \
326 } \
327 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
328 }
329
330
331#define RETURN_IF_ERR() \
332 if (makeDBError(err)) { \
333 return NULL; \
334 }
335
336#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
337
338#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
339 if ((nonNull) == NULL) { \
340 PyObject *errTuple = NULL; \
341 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
342 if (errTuple) { \
343 PyErr_SetObject((pyErrObj), errTuple); \
344 Py_DECREF(errTuple); \
345 } \
346 return NULL; \
347 }
348
349#define CHECK_DB_NOT_CLOSED(dbobj) \
350 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
351
352#define CHECK_ENV_NOT_CLOSED(env) \
353 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
354
355#define CHECK_CURSOR_NOT_CLOSED(curs) \
356 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
357
358#if (DBVER >= 43)
359#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
360 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
361#endif
362
363#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
364 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
365
366#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
367
368#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
369 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
370
371
372static int makeDBError(int err);
373
374
375/* Return the access method type of the DBObject */
376static int _DB_get_type(DBObject* self)
377{
378 DBTYPE type;
379 int err;
380
381 err = self->db->get_type(self->db, &type);
382 if (makeDBError(err)) {
383 return -1;
384 }
385 return type;
386}
387
388
389/* Create a DBT structure (containing key and data values) from Python
390 strings. Returns 1 on success, 0 on an error. */
391static int make_dbt(PyObject* obj, DBT* dbt)
392{
393 CLEAR_DBT(*dbt);
394 if (obj == Py_None) {
395 /* no need to do anything, the structure has already been zeroed */
396 }
397 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
398 PyErr_SetString(PyExc_TypeError,
399#if (PY_VERSION_HEX < 0x03000000)
400 "Data values must be of type string or None.");
401#else
402 "Data values must be of type bytes or None.");
403#endif
404 return 0;
405 }
406 return 1;
407}
408
409
410/* Recno and Queue DBs can have integer keys. This function figures out
411 what's been given, verifies that it's allowed, and then makes the DBT.
412
413 Caller MUST call FREE_DBT(key) when done. */
414static int
415make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
416{
417 db_recno_t recno;
418 int type;
419
420 CLEAR_DBT(*key);
421 if (keyobj == Py_None) {
422 type = _DB_get_type(self);
423 if (type == -1)
424 return 0;
425 if (type == DB_RECNO || type == DB_QUEUE) {
426 PyErr_SetString(
427 PyExc_TypeError,
428 "None keys not allowed for Recno and Queue DB's");
429 return 0;
430 }
431 /* no need to do anything, the structure has already been zeroed */
432 }
433
434 else if (PyBytes_Check(keyobj)) {
435 /* verify access method type */
436 type = _DB_get_type(self);
437 if (type == -1)
438 return 0;
439 if (type == DB_RECNO || type == DB_QUEUE) {
440 PyErr_SetString(
441 PyExc_TypeError,
442#if (PY_VERSION_HEX < 0x03000000)
443 "String keys not allowed for Recno and Queue DB's");
444#else
445 "Bytes keys not allowed for Recno and Queue DB's");
446#endif
447 return 0;
448 }
449
450 /*
451 * NOTE(gps): I don't like doing a data copy here, it seems
452 * wasteful. But without a clean way to tell FREE_DBT if it
453 * should free key->data or not we have to. Other places in
454 * the code check for DB_THREAD and forceably set DBT_MALLOC
455 * when we otherwise would leave flags 0 to indicate that.
456 */
457 key->data = malloc(PyBytes_GET_SIZE(keyobj));
458 if (key->data == NULL) {
459 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
460 return 0;
461 }
462 memcpy(key->data, PyBytes_AS_STRING(keyobj),
463 PyBytes_GET_SIZE(keyobj));
464 key->flags = DB_DBT_REALLOC;
465 key->size = PyBytes_GET_SIZE(keyobj);
466 }
467
468 else if (NUMBER_Check(keyobj)) {
469 /* verify access method type */
470 type = _DB_get_type(self);
471 if (type == -1)
472 return 0;
473 if (type == DB_BTREE && pflags != NULL) {
474 /* if BTREE then an Integer key is allowed with the
475 * DB_SET_RECNO flag */
476 *pflags |= DB_SET_RECNO;
477 }
478 else if (type != DB_RECNO && type != DB_QUEUE) {
479 PyErr_SetString(
480 PyExc_TypeError,
481 "Integer keys only allowed for Recno and Queue DB's");
482 return 0;
483 }
484
485 /* Make a key out of the requested recno, use allocated space so DB
486 * will be able to realloc room for the real key if needed. */
487 recno = NUMBER_AsLong(keyobj);
488 key->data = malloc(sizeof(db_recno_t));
489 if (key->data == NULL) {
490 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
491 return 0;
492 }
493 key->ulen = key->size = sizeof(db_recno_t);
494 memcpy(key->data, &recno, sizeof(db_recno_t));
495 key->flags = DB_DBT_REALLOC;
496 }
497 else {
498 PyErr_Format(PyExc_TypeError,
499#if (PY_VERSION_HEX < 0x03000000)
500 "String or Integer object expected for key, %s found",
501#else
502 "Bytes or Integer object expected for key, %s found",
503#endif
504 Py_TYPE(keyobj)->tp_name);
505 return 0;
506 }
507
508 return 1;
509}
510
511
512/* Add partial record access to an existing DBT data struct.
513 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
514 and the data storage/retrieval will be done using dlen and doff. */
515static int add_partial_dbt(DBT* d, int dlen, int doff) {
516 /* if neither were set we do nothing (-1 is the default value) */
517 if ((dlen == -1) && (doff == -1)) {
518 return 1;
519 }
520
521 if ((dlen < 0) || (doff < 0)) {
522 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
523 return 0;
524 }
525
526 d->flags = d->flags | DB_DBT_PARTIAL;
527 d->dlen = (unsigned int) dlen;
528 d->doff = (unsigned int) doff;
529 return 1;
530}
531
532/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
533/* TODO: make this use the native libc strlcpy() when available (BSD) */
534unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
535{
536 unsigned int srclen, copylen;
537
538 srclen = strlen(src);
539 if (n <= 0)
540 return srclen;
541 copylen = (srclen > n-1) ? n-1 : srclen;
542 /* populate dest[0] thru dest[copylen-1] */
543 memcpy(dest, src, copylen);
544 /* guarantee null termination */
545 dest[copylen] = 0;
546
547 return srclen;
548}
549
550/* Callback used to save away more information about errors from the DB
551 * library. */
552static char _db_errmsg[1024];
553#if (DBVER <= 42)
554static void _db_errorCallback(const char* prefix, char* msg)
555#else
556static void _db_errorCallback(const DB_ENV *db_env,
557 const char* prefix, const char* msg)
558#endif
559{
560 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
561}
562
563
564/*
565** We need these functions because some results
566** are undefined if pointer is NULL. Some other
567** give None instead of "".
568**
569** This functions are static and will be
570** -I hope- inlined.
571*/
572static const char *DummyString = "This string is a simple placeholder";
573static PyObject *Build_PyString(const char *p,int s)
574{
575 if (!p) {
576 p=DummyString;
577 assert(s==0);
578 }
579 return PyBytes_FromStringAndSize(p,s);
580}
581
582static PyObject *BuildValue_S(const void *p,int s)
583{
584 if (!p) {
585 p=DummyString;
586 assert(s==0);
587 }
588 return PyBytes_FromStringAndSize(p, s);
589}
590
591static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
592{
593PyObject *a, *b, *r;
594
595 if (!p1) {
596 p1=DummyString;
597 assert(s1==0);
598 }
599 if (!p2) {
600 p2=DummyString;
601 assert(s2==0);
602 }
603
604 if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
605 return NULL;
606 }
607 if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
608 Py_DECREF(a);
609 return NULL;
610 }
611
612#if (PY_VERSION_HEX >= 0x02040000)
613 r = PyTuple_Pack(2, a, b) ;
614#else
615 r = Py_BuildValue("OO", a, b);
616#endif
617 Py_DECREF(a);
618 Py_DECREF(b);
619 return r;
620}
621
622static PyObject *BuildValue_IS(int i,const void *p,int s)
623{
624 PyObject *a, *r;
625
626 if (!p) {
627 p=DummyString;
628 assert(s==0);
629 }
630
631 if (!(a = PyBytes_FromStringAndSize(p, s))) {
632 return NULL;
633 }
634
635 r = Py_BuildValue("iO", i, a);
636 Py_DECREF(a);
637 return r;
638}
639
640static PyObject *BuildValue_LS(long l,const void *p,int s)
641{
642 PyObject *a, *r;
643
644 if (!p) {
645 p=DummyString;
646 assert(s==0);
647 }
648
649 if (!(a = PyBytes_FromStringAndSize(p, s))) {
650 return NULL;
651 }
652
653 r = Py_BuildValue("lO", l, a);
654 Py_DECREF(a);
655 return r;
656}
657
658
659
660/* make a nice exception object to raise for errors. */
661static int makeDBError(int err)
662{
663 char errTxt[2048]; /* really big, just in case... */
664 PyObject *errObj = NULL;
665 PyObject *errTuple = NULL;
666 int exceptionRaised = 0;
667 unsigned int bytes_left;
668
669 switch (err) {
670 case 0: /* successful, no error */ break;
671
672#if (DBVER < 41)
673 case DB_INCOMPLETE:
674#if INCOMPLETE_IS_WARNING
675 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
676 /* Ensure that bytes_left never goes negative */
677 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
678 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
679 assert(bytes_left >= 0);
680 strcat(errTxt, " -- ");
681 strncat(errTxt, _db_errmsg, bytes_left);
682 }
683 _db_errmsg[0] = 0;
684 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
685
686#else /* do an exception instead */
687 errObj = DBIncompleteError;
688#endif
689 break;
690#endif /* DBVER < 41 */
691
692 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
693 case DB_KEYEXIST: errObj = DBKeyExistError; break;
694 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
695 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
696 case DB_NOTFOUND: errObj = DBNotFoundError; break;
697 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
698 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
699 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
700 case DB_NOSERVER: errObj = DBNoServerError; break;
701 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
702 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
703 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
704 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
705 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
706
707#if (DBVER >= 43)
708 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
709 case ENOMEM: errObj = PyExc_MemoryError; break;
710#endif
711 case EINVAL: errObj = DBInvalidArgError; break;
712 case EACCES: errObj = DBAccessError; break;
713 case ENOSPC: errObj = DBNoSpaceError; break;
714 case EAGAIN: errObj = DBAgainError; break;
715 case EBUSY : errObj = DBBusyError; break;
716 case EEXIST: errObj = DBFileExistsError; break;
717 case ENOENT: errObj = DBNoSuchFileError; break;
718 case EPERM : errObj = DBPermissionsError; break;
719
720#if (DBVER >= 42)
721 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
722#endif
723
724 case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
725
726 default: errObj = DBError; break;
727 }
728
729 if (errObj != NULL) {
730 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
731 /* Ensure that bytes_left never goes negative */
732 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
733 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
734 assert(bytes_left >= 0);
735 strcat(errTxt, " -- ");
736 strncat(errTxt, _db_errmsg, bytes_left);
737 }
738 _db_errmsg[0] = 0;
739
740 errTuple = Py_BuildValue("(is)", err, errTxt);
741 if (errTuple == NULL) {
742 Py_DECREF(errObj);
743 return !0;
744 }
745 PyErr_SetObject(errObj, errTuple);
746 Py_DECREF(errTuple);
747 }
748
749 return ((errObj != NULL) || exceptionRaised);
750}
751
752
753
754/* set a type exception */
755static void makeTypeError(char* expected, PyObject* found)
756{
757 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
758 expected, Py_TYPE(found)->tp_name);
759}
760
761
762/* verify that an obj is either None or a DBTxn, and set the txn pointer */
763static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
764{
765 if (txnobj == Py_None || txnobj == NULL) {
766 *txn = NULL;
767 return 1;
768 }
769 if (DBTxnObject_Check(txnobj)) {
770 *txn = ((DBTxnObject*)txnobj)->txn;
771 return 1;
772 }
773 else
774 makeTypeError("DBTxn", txnobj);
775 return 0;
776}
777
778
779/* Delete a key from a database
780 Returns 0 on success, -1 on an error. */
781static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
782{
783 int err;
784
785 MYDB_BEGIN_ALLOW_THREADS;
786 err = self->db->del(self->db, txn, key, 0);
787 MYDB_END_ALLOW_THREADS;
788 if (makeDBError(err)) {
789 return -1;
790 }
791 self->haveStat = 0;
792 return 0;
793}
794
795
796/* Store a key into a database
797 Returns 0 on success, -1 on an error. */
798static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
799{
800 int err;
801
802 MYDB_BEGIN_ALLOW_THREADS;
803 err = self->db->put(self->db, txn, key, data, flags);
804 MYDB_END_ALLOW_THREADS;
805 if (makeDBError(err)) {
806 return -1;
807 }
808 self->haveStat = 0;
809 return 0;
810}
811
812/* Get a key/data pair from a cursor */
813static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
814 PyObject *args, PyObject *kwargs, char *format)
815{
816 int err;
817 PyObject* retval = NULL;
818 DBT key, data;
819 int dlen = -1;
820 int doff = -1;
821 int flags = 0;
822 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
823
824 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
825 &flags, &dlen, &doff))
826 return NULL;
827
828 CHECK_CURSOR_NOT_CLOSED(self);
829
830 flags |= extra_flags;
831 CLEAR_DBT(key);
832 CLEAR_DBT(data);
833 if (!add_partial_dbt(&data, dlen, doff))
834 return NULL;
835
836 MYDB_BEGIN_ALLOW_THREADS;
837 err = _DBC_get(self->dbc, &key, &data, flags);
838 MYDB_END_ALLOW_THREADS;
839
840 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
841 && self->mydb->moduleFlags.getReturnsNone) {
842 Py_INCREF(Py_None);
843 retval = Py_None;
844 }
845 else if (makeDBError(err)) {
846 retval = NULL;
847 }
848 else { /* otherwise, success! */
849
850 /* if Recno or Queue, return the key as an Int */
851 switch (_DB_get_type(self->mydb)) {
852 case -1:
853 retval = NULL;
854 break;
855
856 case DB_RECNO:
857 case DB_QUEUE:
858 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
859 break;
860 case DB_HASH:
861 case DB_BTREE:
862 default:
863 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
864 break;
865 }
866 }
867 return retval;
868}
869
870
871/* add an integer to a dictionary using the given name as a key */
872static void _addIntToDict(PyObject* dict, char *name, int value)
873{
874 PyObject* v = NUMBER_FromLong((long) value);
875 if (!v || PyDict_SetItemString(dict, name, v))
876 PyErr_Clear();
877
878 Py_XDECREF(v);
879}
880
881/* The same, when the value is a time_t */
882static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
883{
884 PyObject* v;
885 /* if the value fits in regular int, use that. */
886#ifdef PY_LONG_LONG
887 if (sizeof(time_t) > sizeof(long))
888 v = PyLong_FromLongLong((PY_LONG_LONG) value);
889 else
890#endif
891 v = NUMBER_FromLong((long) value);
892 if (!v || PyDict_SetItemString(dict, name, v))
893 PyErr_Clear();
894
895 Py_XDECREF(v);
896}
897
898#if (DBVER >= 43)
899/* add an db_seq_t to a dictionary using the given name as a key */
900static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
901{
902 PyObject* v = PyLong_FromLongLong(value);
903 if (!v || PyDict_SetItemString(dict, name, v))
904 PyErr_Clear();
905
906 Py_XDECREF(v);
907}
908#endif
909
910static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
911{
912 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
913 if (!v || PyDict_SetItemString(dict, name, v))
914 PyErr_Clear();
915
916 Py_XDECREF(v);
917}
918
919/* --------------------------------------------------------------------- */
920/* Allocators and deallocators */
921
922static DBObject*
923newDBObject(DBEnvObject* arg, int flags)
924{
925 DBObject* self;
926 DB_ENV* db_env = NULL;
927 int err;
928
929 self = PyObject_New(DBObject, &DB_Type);
930 if (self == NULL)
931 return NULL;
932
933 self->haveStat = 0;
934 self->flags = 0;
935 self->setflags = 0;
936 self->myenvobj = NULL;
937 self->db = NULL;
938 self->children_cursors = NULL;
939#if (DBVER >=43)
940 self->children_sequences = NULL;
941#endif
942 self->associateCallback = NULL;
943 self->btCompareCallback = NULL;
944 self->primaryDBType = 0;
945 Py_INCREF(Py_None);
946 self->private_obj = Py_None;
947 self->in_weakreflist = NULL;
948
949 /* keep a reference to our python DBEnv object */
950 if (arg) {
951 Py_INCREF(arg);
952 self->myenvobj = arg;
953 db_env = arg->db_env;
954 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
955 } else {
956 self->sibling_prev_p=NULL;
957 self->sibling_next=NULL;
958 }
959 self->txn=NULL;
960 self->sibling_prev_p_txn=NULL;
961 self->sibling_next_txn=NULL;
962
963 if (self->myenvobj)
964 self->moduleFlags = self->myenvobj->moduleFlags;
965 else
966 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
967 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
968
969 MYDB_BEGIN_ALLOW_THREADS;
970 err = db_create(&self->db, db_env, flags);
971 if (self->db != NULL) {
972 self->db->set_errcall(self->db, _db_errorCallback);
973 self->db->app_private = (void*)self;
974 }
975 MYDB_END_ALLOW_THREADS;
976 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
977 * list so that a DBEnv can refuse to close without aborting any open
978 * DBTxns and closing any open DBs first. */
979 if (makeDBError(err)) {
980 if (self->myenvobj) {
981 Py_DECREF(self->myenvobj);
982 self->myenvobj = NULL;
983 }
984 Py_DECREF(self);
985 self = NULL;
986 }
987 return self;
988}
989
990
991/* Forward declaration */
992static PyObject *DB_close_internal(DBObject* self, int flags, int do_not_close);
993
994static void
995DB_dealloc(DBObject* self)
996{
997 PyObject *dummy;
998
999 if (self->db != NULL) {
1000 dummy=DB_close_internal(self, 0, 0);
1001 /*
1002 ** Raising exceptions while doing
1003 ** garbage collection is a fatal error.
1004 */
1005 if (dummy)
1006 Py_DECREF(dummy);
1007 else
1008 PyErr_Clear();
1009 }
1010 if (self->in_weakreflist != NULL) {
1011 PyObject_ClearWeakRefs((PyObject *) self);
1012 }
1013 if (self->myenvobj) {
1014 Py_DECREF(self->myenvobj);
1015 self->myenvobj = NULL;
1016 }
1017 if (self->associateCallback != NULL) {
1018 Py_DECREF(self->associateCallback);
1019 self->associateCallback = NULL;
1020 }
1021 if (self->btCompareCallback != NULL) {
1022 Py_DECREF(self->btCompareCallback);
1023 self->btCompareCallback = NULL;
1024 }
1025 Py_DECREF(self->private_obj);
1026 PyObject_Del(self);
1027}
1028
1029static DBCursorObject*
1030newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
1031{
1032 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
1033 if (self == NULL)
1034 return NULL;
1035
1036 self->dbc = dbc;
1037 self->mydb = db;
1038
1039 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
1040 if (txn && ((PyObject *)txn!=Py_None)) {
1041 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
1042 self->txn=txn;
1043 } else {
1044 self->txn=NULL;
1045 }
1046
1047 self->in_weakreflist = NULL;
1048 Py_INCREF(self->mydb);
1049 return self;
1050}
1051
1052
1053/* Forward declaration */
1054static PyObject *DBC_close_internal(DBCursorObject* self);
1055
1056static void
1057DBCursor_dealloc(DBCursorObject* self)
1058{
1059 PyObject *dummy;
1060
1061 if (self->dbc != NULL) {
1062 dummy=DBC_close_internal(self);
1063 /*
1064 ** Raising exceptions while doing
1065 ** garbage collection is a fatal error.
1066 */
1067 if (dummy)
1068 Py_DECREF(dummy);
1069 else
1070 PyErr_Clear();
1071 }
1072 if (self->in_weakreflist != NULL) {
1073 PyObject_ClearWeakRefs((PyObject *) self);
1074 }
1075 Py_DECREF(self->mydb);
1076 PyObject_Del(self);
1077}
1078
1079
1080static DBEnvObject*
1081newDBEnvObject(int flags)
1082{
1083 int err;
1084 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
1085 if (self == NULL)
1086 return NULL;
1087
1088 self->db_env = NULL;
1089 self->closed = 1;
1090 self->flags = flags;
1091 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1092 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
1093 self->children_dbs = NULL;
1094 self->children_txns = NULL;
1095 Py_INCREF(Py_None);
1096 self->private_obj = Py_None;
1097 Py_INCREF(Py_None);
1098 self->rep_transport = Py_None;
1099 self->in_weakreflist = NULL;
1100 self->event_notifyCallback = NULL;
1101
1102 MYDB_BEGIN_ALLOW_THREADS;
1103 err = db_env_create(&self->db_env, flags);
1104 MYDB_END_ALLOW_THREADS;
1105 if (makeDBError(err)) {
1106 Py_DECREF(self);
1107 self = NULL;
1108 }
1109 else {
1110 self->db_env->set_errcall(self->db_env, _db_errorCallback);
1111 self->db_env->app_private = self;
1112 }
1113 return self;
1114}
1115
1116/* Forward declaration */
1117static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
1118
1119static void
1120DBEnv_dealloc(DBEnvObject* self)
1121{
1122 PyObject *dummy;
1123
1124 if (self->db_env) {
1125 dummy=DBEnv_close_internal(self, 0);
1126 /*
1127 ** Raising exceptions while doing
1128 ** garbage collection is a fatal error.
1129 */
1130 if (dummy)
1131 Py_DECREF(dummy);
1132 else
1133 PyErr_Clear();
1134 }
1135
1136 Py_XDECREF(self->event_notifyCallback);
1137 self->event_notifyCallback = NULL;
1138
1139 if (self->in_weakreflist != NULL) {
1140 PyObject_ClearWeakRefs((PyObject *) self);
1141 }
1142 Py_DECREF(self->private_obj);
1143 Py_DECREF(self->rep_transport);
1144 PyObject_Del(self);
1145}
1146
1147
1148static DBTxnObject*
1149newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
1150{
1151 int err;
1152 DB_TXN *parent_txn = NULL;
1153
1154 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
1155 if (self == NULL)
1156 return NULL;
1157
1158 self->in_weakreflist = NULL;
1159 self->children_txns = NULL;
1160 self->children_dbs = NULL;
1161 self->children_cursors = NULL;
1162 self->children_sequences = NULL;
1163 self->flag_prepare = 0;
1164 self->parent_txn = NULL;
1165 self->env = NULL;
1166
1167 if (parent && ((PyObject *)parent!=Py_None)) {
1168 parent_txn = parent->txn;
1169 }
1170
1171 if (txn) {
1172 self->txn = txn;
1173 } else {
1174 MYDB_BEGIN_ALLOW_THREADS;
1175 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
1176 MYDB_END_ALLOW_THREADS;
1177
1178 if (makeDBError(err)) {
1179 Py_DECREF(self);
1180 return NULL;
1181 }
1182 }
1183
1184 /* Can't use 'parent' because could be 'parent==Py_None' */
1185 if (parent_txn) {
1186 self->parent_txn = parent;
1187 Py_INCREF(parent);
1188 self->env = NULL;
1189 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
1190 } else {
1191 self->parent_txn = NULL;
1192 Py_INCREF(myenv);
1193 self->env = myenv;
1194 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
1195 }
1196
1197 return self;
1198}
1199
1200/* Forward declaration */
1201static PyObject *
1202DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
1203
1204static void
1205DBTxn_dealloc(DBTxnObject* self)
1206{
1207 PyObject *dummy;
1208
1209 if (self->txn) {
1210 int flag_prepare = self->flag_prepare;
1211
1212 dummy=DBTxn_abort_discard_internal(self,0);
1213 /*
1214 ** Raising exceptions while doing
1215 ** garbage collection is a fatal error.
1216 */
1217 if (dummy)
1218 Py_DECREF(dummy);
1219 else
1220 PyErr_Clear();
1221
1222 if (!flag_prepare) {
1223 PyErr_Warn(PyExc_RuntimeWarning,
1224 "DBTxn aborted in destructor. No prior commit() or abort().");
1225 }
1226 }
1227
1228 if (self->in_weakreflist != NULL) {
1229 PyObject_ClearWeakRefs((PyObject *) self);
1230 }
1231
1232 if (self->env) {
1233 Py_DECREF(self->env);
1234 } else {
1235 Py_DECREF(self->parent_txn);
1236 }
1237 PyObject_Del(self);
1238}
1239
1240
1241static DBLockObject*
1242newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1243 db_lockmode_t lock_mode, int flags)
1244{
1245 int err;
1246 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
1247 if (self == NULL)
1248 return NULL;
1249 self->in_weakreflist = NULL;
1250
1251 MYDB_BEGIN_ALLOW_THREADS;
1252 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1253 &self->lock);
1254 MYDB_END_ALLOW_THREADS;
1255 if (makeDBError(err)) {
1256 Py_DECREF(self);
1257 self = NULL;
1258 }
1259
1260 return self;
1261}
1262
1263
1264static void
1265DBLock_dealloc(DBLockObject* self)
1266{
1267 if (self->in_weakreflist != NULL) {
1268 PyObject_ClearWeakRefs((PyObject *) self);
1269 }
1270 /* TODO: is this lock held? should we release it? */
1271
1272 PyObject_Del(self);
1273}
1274
1275
1276#if (DBVER >= 43)
1277static DBSequenceObject*
1278newDBSequenceObject(DBObject* mydb, int flags)
1279{
1280 int err;
1281 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1282 if (self == NULL)
1283 return NULL;
1284 Py_INCREF(mydb);
1285 self->mydb = mydb;
1286
1287 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
1288 self->txn = NULL;
1289
1290 self->in_weakreflist = NULL;
1291
1292 MYDB_BEGIN_ALLOW_THREADS;
1293 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1294 MYDB_END_ALLOW_THREADS;
1295 if (makeDBError(err)) {
1296 Py_DECREF(self);
1297 self = NULL;
1298 }
1299
1300 return self;
1301}
1302
1303/* Forward declaration */
1304static PyObject
1305*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
1306
1307static void
1308DBSequence_dealloc(DBSequenceObject* self)
1309{
1310 PyObject *dummy;
1311
1312 if (self->sequence != NULL) {
1313 dummy=DBSequence_close_internal(self,0,0);
1314 /*
1315 ** Raising exceptions while doing
1316 ** garbage collection is a fatal error.
1317 */
1318 if (dummy)
1319 Py_DECREF(dummy);
1320 else
1321 PyErr_Clear();
1322 }
1323
1324 if (self->in_weakreflist != NULL) {
1325 PyObject_ClearWeakRefs((PyObject *) self);
1326 }
1327
1328 Py_DECREF(self->mydb);
1329 PyObject_Del(self);
1330}
1331#endif
1332
1333/* --------------------------------------------------------------------- */
1334/* DB methods */
1335
1336static PyObject*
1337DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
1338{
1339 PyObject* txnobj = NULL;
1340 PyObject* dataobj;
1341 db_recno_t recno;
1342 DBT key, data;
1343 DB_TXN *txn = NULL;
1344 static char* kwnames[] = { "data", "txn", NULL };
1345
1346 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
1347 &dataobj, &txnobj))
1348 return NULL;
1349
1350 CHECK_DB_NOT_CLOSED(self);
1351
1352 /* make a dummy key out of a recno */
1353 recno = 0;
1354 CLEAR_DBT(key);
1355 key.data = &recno;
1356 key.size = sizeof(recno);
1357 key.ulen = key.size;
1358 key.flags = DB_DBT_USERMEM;
1359
1360 if (!make_dbt(dataobj, &data)) return NULL;
1361 if (!checkTxnObj(txnobj, &txn)) return NULL;
1362
1363 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1364 return NULL;
1365
1366 return NUMBER_FromLong(recno);
1367}
1368
1369
1370static int
1371_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1372 DBT* secKey)
1373{
1374 int retval = DB_DONOTINDEX;
1375 DBObject* secondaryDB = (DBObject*)db->app_private;
1376 PyObject* callback = secondaryDB->associateCallback;
1377 int type = secondaryDB->primaryDBType;
1378 PyObject* args;
1379 PyObject* result = NULL;
1380
1381
1382 if (callback != NULL) {
1383 MYDB_BEGIN_BLOCK_THREADS;
1384
1385 if (type == DB_RECNO || type == DB_QUEUE)
1386 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
1387 else
1388 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
1389 if (args != NULL) {
1390 result = PyEval_CallObject(callback, args);
1391 }
1392 if (args == NULL || result == NULL) {
1393 PyErr_Print();
1394 }
1395 else if (result == Py_None) {
1396 retval = DB_DONOTINDEX;
1397 }
1398 else if (NUMBER_Check(result)) {
1399 retval = NUMBER_AsLong(result);
1400 }
1401 else if (PyBytes_Check(result)) {
1402 char* data;
1403 Py_ssize_t size;
1404
1405 CLEAR_DBT(*secKey);
1406 PyBytes_AsStringAndSize(result, &data, &size);
1407 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1408 secKey->data = malloc(size); /* TODO, check this */
1409 if (secKey->data) {
1410 memcpy(secKey->data, data, size);
1411 secKey->size = size;
1412 retval = 0;
1413 }
1414 else {
1415 PyErr_SetString(PyExc_MemoryError,
1416 "malloc failed in _db_associateCallback");
1417 PyErr_Print();
1418 }
1419 }
1420 else {
1421 PyErr_SetString(
1422 PyExc_TypeError,
1423 "DB associate callback should return DB_DONOTINDEX or string.");
1424 PyErr_Print();
1425 }
1426
1427 Py_XDECREF(args);
1428 Py_XDECREF(result);
1429
1430 MYDB_END_BLOCK_THREADS;
1431 }
1432 return retval;
1433}
1434
1435
1436static PyObject*
1437DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1438{
1439 int err, flags=0;
1440 DBObject* secondaryDB;
1441 PyObject* callback;
1442#if (DBVER >= 41)
1443 PyObject *txnobj = NULL;
1444 DB_TXN *txn = NULL;
1445 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1446 NULL};
1447#else
1448 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1449#endif
1450
1451#if (DBVER >= 41)
1452 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1453 &secondaryDB, &callback, &flags,
1454 &txnobj)) {
1455#else
1456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1457 &secondaryDB, &callback, &flags)) {
1458#endif
1459 return NULL;
1460 }
1461
1462#if (DBVER >= 41)
1463 if (!checkTxnObj(txnobj, &txn)) return NULL;
1464#endif
1465
1466 CHECK_DB_NOT_CLOSED(self);
1467 if (!DBObject_Check(secondaryDB)) {
1468 makeTypeError("DB", (PyObject*)secondaryDB);
1469 return NULL;
1470 }
1471 CHECK_DB_NOT_CLOSED(secondaryDB);
1472 if (callback == Py_None) {
1473 callback = NULL;
1474 }
1475 else if (!PyCallable_Check(callback)) {
1476 makeTypeError("Callable", callback);
1477 return NULL;
1478 }
1479
1480 /* Save a reference to the callback in the secondary DB. */
1481 Py_XDECREF(secondaryDB->associateCallback);
1482 Py_XINCREF(callback);
1483 secondaryDB->associateCallback = callback;
1484 secondaryDB->primaryDBType = _DB_get_type(self);
1485
1486 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1487 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1488 * The global interepreter lock is not initialized until the first
1489 * thread is created using thread.start_new_thread() or fork() is
1490 * called. that would cause the ALLOW_THREADS here to segfault due
1491 * to a null pointer reference if no threads or child processes
1492 * have been created. This works around that and is a no-op if
1493 * threads have already been initialized.
1494 * (see pybsddb-users mailing list post on 2002-08-07)
1495 */
1496#ifdef WITH_THREAD
1497 PyEval_InitThreads();
1498#endif
1499 MYDB_BEGIN_ALLOW_THREADS;
1500#if (DBVER >= 41)
1501 err = self->db->associate(self->db,
1502 txn,
1503 secondaryDB->db,
1504 _db_associateCallback,
1505 flags);
1506#else
1507 err = self->db->associate(self->db,
1508 secondaryDB->db,
1509 _db_associateCallback,
1510 flags);
1511#endif
1512 MYDB_END_ALLOW_THREADS;
1513
1514 if (err) {
1515 Py_XDECREF(secondaryDB->associateCallback);
1516 secondaryDB->associateCallback = NULL;
1517 secondaryDB->primaryDBType = 0;
1518 }
1519
1520 RETURN_IF_ERR();
1521 RETURN_NONE();
1522}
1523
1524
1525static PyObject*
1526DB_close_internal(DBObject* self, int flags, int do_not_close)
1527{
1528 PyObject *dummy;
1529 int err = 0;
1530
1531 if (self->db != NULL) {
1532 /* Can be NULL if db is not in an environment */
1533 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
1534
1535 if (self->txn) {
1536 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1537 self->txn=NULL;
1538 }
1539
1540 while(self->children_cursors) {
1541 dummy=DBC_close_internal(self->children_cursors);
1542 Py_XDECREF(dummy);
1543 }
1544
1545#if (DBVER >= 43)
1546 while(self->children_sequences) {
1547 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1548 Py_XDECREF(dummy);
1549 }
1550#endif
1551
1552 /*
1553 ** "do_not_close" is used to dispose all related objects in the
1554 ** tree, without actually releasing the "root" object.
1555 ** This is done, for example, because function calls like
1556 ** "DB.verify()" implicitly close the underlying handle. So
1557 ** the handle doesn't need to be closed, but related objects
1558 ** must be cleaned up.
1559 */
1560 if (!do_not_close) {
1561 MYDB_BEGIN_ALLOW_THREADS;
1562 err = self->db->close(self->db, flags);
1563 MYDB_END_ALLOW_THREADS;
1564 self->db = NULL;
1565 }
1566 RETURN_IF_ERR();
1567 }
1568 RETURN_NONE();
1569}
1570
1571static PyObject*
1572DB_close(DBObject* self, PyObject* args)
1573{
1574 int flags=0;
1575 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1576 return NULL;
1577 return DB_close_internal(self, flags, 0);
1578}
1579
1580
1581static PyObject*
1582_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1583{
1584 int err, flags=0, type;
1585 PyObject* txnobj = NULL;
1586 PyObject* retval = NULL;
1587 DBT key, data;
1588 DB_TXN *txn = NULL;
1589 static char* kwnames[] = { "txn", "flags", NULL };
1590
1591 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1592 &txnobj, &flags))
1593 return NULL;
1594
1595 CHECK_DB_NOT_CLOSED(self);
1596 type = _DB_get_type(self);
1597 if (type == -1)
1598 return NULL;
1599 if (type != DB_QUEUE) {
1600 PyErr_SetString(PyExc_TypeError,
1601 "Consume methods only allowed for Queue DB's");
1602 return NULL;
1603 }
1604 if (!checkTxnObj(txnobj, &txn))
1605 return NULL;
1606
1607 CLEAR_DBT(key);
1608 CLEAR_DBT(data);
1609 if (CHECK_DBFLAG(self, DB_THREAD)) {
1610 /* Tell Berkeley DB to malloc the return value (thread safe) */
1611 data.flags = DB_DBT_MALLOC;
1612 key.flags = DB_DBT_MALLOC;
1613 }
1614
1615 MYDB_BEGIN_ALLOW_THREADS;
1616 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1617 MYDB_END_ALLOW_THREADS;
1618
1619 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1620 && self->moduleFlags.getReturnsNone) {
1621 err = 0;
1622 Py_INCREF(Py_None);
1623 retval = Py_None;
1624 }
1625 else if (!err) {
1626 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
1627 FREE_DBT(key);
1628 FREE_DBT(data);
1629 }
1630
1631 RETURN_IF_ERR();
1632 return retval;
1633}
1634
1635static PyObject*
1636DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1637{
1638 return _DB_consume(self, args, kwargs, DB_CONSUME);
1639}
1640
1641static PyObject*
1642DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1643 int consume_flag)
1644{
1645 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1646}
1647
1648
1649static PyObject*
1650DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1651{
1652 int err, flags=0;
1653 DBC* dbc;
1654 PyObject* txnobj = NULL;
1655 DB_TXN *txn = NULL;
1656 static char* kwnames[] = { "txn", "flags", NULL };
1657
1658 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1659 &txnobj, &flags))
1660 return NULL;
1661 CHECK_DB_NOT_CLOSED(self);
1662 if (!checkTxnObj(txnobj, &txn))
1663 return NULL;
1664
1665 MYDB_BEGIN_ALLOW_THREADS;
1666 err = self->db->cursor(self->db, txn, &dbc, flags);
1667 MYDB_END_ALLOW_THREADS;
1668 RETURN_IF_ERR();
1669 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
1670}
1671
1672
1673static PyObject*
1674DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1675{
1676 PyObject* txnobj = NULL;
1677 int flags = 0;
1678 PyObject* keyobj;
1679 DBT key;
1680 DB_TXN *txn = NULL;
1681 static char* kwnames[] = { "key", "txn", "flags", NULL };
1682
1683 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1684 &keyobj, &txnobj, &flags))
1685 return NULL;
1686 CHECK_DB_NOT_CLOSED(self);
1687 if (!make_key_dbt(self, keyobj, &key, NULL))
1688 return NULL;
1689 if (!checkTxnObj(txnobj, &txn)) {
1690 FREE_DBT(key);
1691 return NULL;
1692 }
1693
1694 if (-1 == _DB_delete(self, txn, &key, 0)) {
1695 FREE_DBT(key);
1696 return NULL;
1697 }
1698
1699 FREE_DBT(key);
1700 RETURN_NONE();
1701}
1702
1703
1704static PyObject*
1705DB_fd(DBObject* self)
1706{
1707 int err, the_fd;
1708
1709 CHECK_DB_NOT_CLOSED(self);
1710
1711 MYDB_BEGIN_ALLOW_THREADS;
1712 err = self->db->fd(self->db, &the_fd);
1713 MYDB_END_ALLOW_THREADS;
1714 RETURN_IF_ERR();
1715 return NUMBER_FromLong(the_fd);
1716}
1717
1718
1719static PyObject*
1720DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1721{
1722 int err, flags=0;
1723 PyObject* txnobj = NULL;
1724 PyObject* keyobj;
1725 PyObject* dfltobj = NULL;
1726 PyObject* retval = NULL;
1727 int dlen = -1;
1728 int doff = -1;
1729 DBT key, data;
1730 DB_TXN *txn = NULL;
1731 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1732 "doff", NULL};
1733
1734 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1735 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1736 &doff))
1737 return NULL;
1738
1739 CHECK_DB_NOT_CLOSED(self);
1740 if (!make_key_dbt(self, keyobj, &key, &flags))
1741 return NULL;
1742 if (!checkTxnObj(txnobj, &txn)) {
1743 FREE_DBT(key);
1744 return NULL;
1745 }
1746
1747 CLEAR_DBT(data);
1748 if (CHECK_DBFLAG(self, DB_THREAD)) {
1749 /* Tell Berkeley DB to malloc the return value (thread safe) */
1750 data.flags = DB_DBT_MALLOC;
1751 }
1752 if (!add_partial_dbt(&data, dlen, doff)) {
1753 FREE_DBT(key);
1754 return NULL;
1755 }
1756
1757 MYDB_BEGIN_ALLOW_THREADS;
1758 err = self->db->get(self->db, txn, &key, &data, flags);
1759 MYDB_END_ALLOW_THREADS;
1760
1761 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1762 err = 0;
1763 Py_INCREF(dfltobj);
1764 retval = dfltobj;
1765 }
1766 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1767 && self->moduleFlags.getReturnsNone) {
1768 err = 0;
1769 Py_INCREF(Py_None);
1770 retval = Py_None;
1771 }
1772 else if (!err) {
1773 if (flags & DB_SET_RECNO) /* return both key and data */
1774 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
1775 else /* return just the data */
1776 retval = Build_PyString(data.data, data.size);
1777 FREE_DBT(data);
1778 }
1779 FREE_DBT(key);
1780
1781 RETURN_IF_ERR();
1782 return retval;
1783}
1784
1785static PyObject*
1786DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1787{
1788 int err, flags=0;
1789 PyObject* txnobj = NULL;
1790 PyObject* keyobj;
1791 PyObject* dfltobj = NULL;
1792 PyObject* retval = NULL;
1793 int dlen = -1;
1794 int doff = -1;
1795 DBT key, pkey, data;
1796 DB_TXN *txn = NULL;
1797 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1798 "doff", NULL};
1799
1800 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1801 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1802 &doff))
1803 return NULL;
1804
1805 CHECK_DB_NOT_CLOSED(self);
1806 if (!make_key_dbt(self, keyobj, &key, &flags))
1807 return NULL;
1808 if (!checkTxnObj(txnobj, &txn)) {
1809 FREE_DBT(key);
1810 return NULL;
1811 }
1812
1813 CLEAR_DBT(data);
1814 if (CHECK_DBFLAG(self, DB_THREAD)) {
1815 /* Tell Berkeley DB to malloc the return value (thread safe) */
1816 data.flags = DB_DBT_MALLOC;
1817 }
1818 if (!add_partial_dbt(&data, dlen, doff)) {
1819 FREE_DBT(key);
1820 return NULL;
1821 }
1822
1823 CLEAR_DBT(pkey);
1824 pkey.flags = DB_DBT_MALLOC;
1825
1826 MYDB_BEGIN_ALLOW_THREADS;
1827 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1828 MYDB_END_ALLOW_THREADS;
1829
1830 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1831 err = 0;
1832 Py_INCREF(dfltobj);
1833 retval = dfltobj;
1834 }
1835 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1836 && self->moduleFlags.getReturnsNone) {
1837 err = 0;
1838 Py_INCREF(Py_None);
1839 retval = Py_None;
1840 }
1841 else if (!err) {
1842 PyObject *pkeyObj;
1843 PyObject *dataObj;
1844 dataObj = Build_PyString(data.data, data.size);
1845
1846 if (self->primaryDBType == DB_RECNO ||
1847 self->primaryDBType == DB_QUEUE)
1848 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
1849 else
1850 pkeyObj = Build_PyString(pkey.data, pkey.size);
1851
1852 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1853 {
1854 PyObject *keyObj;
1855 int type = _DB_get_type(self);
1856 if (type == DB_RECNO || type == DB_QUEUE)
1857 keyObj = NUMBER_FromLong(*(int *)key.data);
1858 else
1859 keyObj = Build_PyString(key.data, key.size);
1860#if (PY_VERSION_HEX >= 0x02040000)
1861 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
1862#else
1863 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1864#endif
1865 Py_DECREF(keyObj);
1866 }
1867 else /* return just the pkey and data */
1868 {
1869#if (PY_VERSION_HEX >= 0x02040000)
1870 retval = PyTuple_Pack(2, pkeyObj, dataObj);
1871#else
1872 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1873#endif
1874 }
1875 Py_DECREF(dataObj);
1876 Py_DECREF(pkeyObj);
1877 FREE_DBT(pkey);
1878 FREE_DBT(data);
1879 }
1880 FREE_DBT(key);
1881
1882 RETURN_IF_ERR();
1883 return retval;
1884}
1885
1886
1887/* Return size of entry */
1888static PyObject*
1889DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1890{
1891 int err, flags=0;
1892 PyObject* txnobj = NULL;
1893 PyObject* keyobj;
1894 PyObject* retval = NULL;
1895 DBT key, data;
1896 DB_TXN *txn = NULL;
1897 static char* kwnames[] = { "key", "txn", NULL };
1898
1899 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1900 &keyobj, &txnobj))
1901 return NULL;
1902 CHECK_DB_NOT_CLOSED(self);
1903 if (!make_key_dbt(self, keyobj, &key, &flags))
1904 return NULL;
1905 if (!checkTxnObj(txnobj, &txn)) {
1906 FREE_DBT(key);
1907 return NULL;
1908 }
1909 CLEAR_DBT(data);
1910
1911 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1912 thus getting the record size. */
1913 data.flags = DB_DBT_USERMEM;
1914 data.ulen = 0;
1915 MYDB_BEGIN_ALLOW_THREADS;
1916 err = self->db->get(self->db, txn, &key, &data, flags);
1917 MYDB_END_ALLOW_THREADS;
1918 if (err == DB_BUFFER_SMALL) {
1919 retval = NUMBER_FromLong((long)data.size);
1920 err = 0;
1921 }
1922
1923 FREE_DBT(key);
1924 FREE_DBT(data);
1925 RETURN_IF_ERR();
1926 return retval;
1927}
1928
1929
1930static PyObject*
1931DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1932{
1933 int err, flags=0;
1934 PyObject* txnobj = NULL;
1935 PyObject* keyobj;
1936 PyObject* dataobj;
1937 PyObject* retval = NULL;
1938 DBT key, data;
1939 void *orig_data;
1940 DB_TXN *txn = NULL;
1941 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1942
1943 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1944 &keyobj, &dataobj, &txnobj, &flags))
1945 return NULL;
1946
1947 CHECK_DB_NOT_CLOSED(self);
1948 if (!make_key_dbt(self, keyobj, &key, NULL))
1949 return NULL;
1950 if ( !make_dbt(dataobj, &data) ||
1951 !checkTxnObj(txnobj, &txn) )
1952 {
1953 FREE_DBT(key);
1954 return NULL;
1955 }
1956
1957 flags |= DB_GET_BOTH;
1958 orig_data = data.data;
1959
1960 if (CHECK_DBFLAG(self, DB_THREAD)) {
1961 /* Tell Berkeley DB to malloc the return value (thread safe) */
1962 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
1963 data.flags = DB_DBT_MALLOC;
1964 }
1965
1966 MYDB_BEGIN_ALLOW_THREADS;
1967 err = self->db->get(self->db, txn, &key, &data, flags);
1968 MYDB_END_ALLOW_THREADS;
1969
1970 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1971 && self->moduleFlags.getReturnsNone) {
1972 err = 0;
1973 Py_INCREF(Py_None);
1974 retval = Py_None;
1975 }
1976 else if (!err) {
1977 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
1978 retval = Build_PyString(data.data, data.size);
1979
1980 /* Even though the flags require DB_DBT_MALLOC, data is not always
1981 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1982 if (data.data != orig_data)
1983 FREE_DBT(data);
1984 }
1985
1986 FREE_DBT(key);
1987 RETURN_IF_ERR();
1988 return retval;
1989}
1990
1991
1992static PyObject*
1993DB_get_byteswapped(DBObject* self)
1994{
1995 int err = 0;
1996 int retval = -1;
1997
1998 CHECK_DB_NOT_CLOSED(self);
1999
2000 MYDB_BEGIN_ALLOW_THREADS;
2001 err = self->db->get_byteswapped(self->db, &retval);
2002 MYDB_END_ALLOW_THREADS;
2003 RETURN_IF_ERR();
2004 return NUMBER_FromLong(retval);
2005}
2006
2007
2008static PyObject*
2009DB_get_type(DBObject* self)
2010{
2011 int type;
2012
2013 CHECK_DB_NOT_CLOSED(self);
2014
2015 type = _DB_get_type(self);
2016 if (type == -1)
2017 return NULL;
2018 return NUMBER_FromLong(type);
2019}
2020
2021
2022static PyObject*
2023DB_join(DBObject* self, PyObject* args)
2024{
2025 int err, flags=0;
2026 int length, x;
2027 PyObject* cursorsObj;
2028 DBC** cursors;
2029 DBC* dbc;
2030
2031 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
2032 return NULL;
2033
2034 CHECK_DB_NOT_CLOSED(self);
2035
2036 if (!PySequence_Check(cursorsObj)) {
2037 PyErr_SetString(PyExc_TypeError,
2038 "Sequence of DBCursor objects expected");
2039 return NULL;
2040 }
2041
2042 length = PyObject_Length(cursorsObj);
2043 cursors = malloc((length+1) * sizeof(DBC*));
2044 if (!cursors) {
2045 PyErr_NoMemory();
2046 return NULL;
2047 }
2048
2049 cursors[length] = NULL;
2050 for (x=0; x<length; x++) {
2051 PyObject* item = PySequence_GetItem(cursorsObj, x);
2052 if (item == NULL) {
2053 free(cursors);
2054 return NULL;
2055 }
2056 if (!DBCursorObject_Check(item)) {
2057 PyErr_SetString(PyExc_TypeError,
2058 "Sequence of DBCursor objects expected");
2059 free(cursors);
2060 return NULL;
2061 }
2062 cursors[x] = ((DBCursorObject*)item)->dbc;
2063 Py_DECREF(item);
2064 }
2065
2066 MYDB_BEGIN_ALLOW_THREADS;
2067 err = self->db->join(self->db, cursors, &dbc, flags);
2068 MYDB_END_ALLOW_THREADS;
2069 free(cursors);
2070 RETURN_IF_ERR();
2071
2072 /* FIXME: this is a buggy interface. The returned cursor
2073 contains internal references to the passed in cursors
2074 but does not hold python references to them or prevent
2075 them from being closed prematurely. This can cause
2076 python to crash when things are done in the wrong order. */
2077 return (PyObject*) newDBCursorObject(dbc, NULL, self);
2078}
2079
2080
2081static PyObject*
2082DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
2083{
2084 int err, flags=0;
2085 PyObject* txnobj = NULL;
2086 PyObject* keyobj;
2087 DBT key;
2088 DB_TXN *txn = NULL;
2089 DB_KEY_RANGE range;
2090 static char* kwnames[] = { "key", "txn", "flags", NULL };
2091
2092 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
2093 &keyobj, &txnobj, &flags))
2094 return NULL;
2095 CHECK_DB_NOT_CLOSED(self);
2096 if (!make_dbt(keyobj, &key))
2097 /* BTree only, don't need to allow for an int key */
2098 return NULL;
2099 if (!checkTxnObj(txnobj, &txn))
2100 return NULL;
2101
2102 MYDB_BEGIN_ALLOW_THREADS;
2103 err = self->db->key_range(self->db, txn, &key, &range, flags);
2104 MYDB_END_ALLOW_THREADS;
2105
2106 RETURN_IF_ERR();
2107 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2108}
2109
2110
2111static PyObject*
2112DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2113{
2114 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2115 char* filename = NULL;
2116 char* dbname = NULL;
2117#if (DBVER >= 41)
2118 PyObject *txnobj = NULL;
2119 DB_TXN *txn = NULL;
2120 /* with dbname */
2121 static char* kwnames[] = {
2122 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2123 /* without dbname */
2124 static char* kwnames_basic[] = {
2125 "filename", "dbtype", "flags", "mode", "txn", NULL};
2126#else
2127 /* with dbname */
2128 static char* kwnames[] = {
2129 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2130 /* without dbname */
2131 static char* kwnames_basic[] = {
2132 "filename", "dbtype", "flags", "mode", NULL};
2133#endif
2134
2135#if (DBVER >= 41)
2136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2137 &filename, &dbname, &type, &flags, &mode,
2138 &txnobj))
2139#else
2140 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
2141 &filename, &dbname, &type, &flags,
2142 &mode))
2143#endif
2144 {
2145 PyErr_Clear();
2146 type = DB_UNKNOWN; flags = 0; mode = 0660;
2147 filename = NULL; dbname = NULL;
2148#if (DBVER >= 41)
2149 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2150 kwnames_basic,
2151 &filename, &type, &flags, &mode,
2152 &txnobj))
2153 return NULL;
2154#else
2155 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2156 kwnames_basic,
2157 &filename, &type, &flags, &mode))
2158 return NULL;
2159#endif
2160 }
2161
2162#if (DBVER >= 41)
2163 if (!checkTxnObj(txnobj, &txn)) return NULL;
2164#endif
2165
2166 if (NULL == self->db) {
2167 PyObject *t = Py_BuildValue("(is)", 0,
2168 "Cannot call open() twice for DB object");
2169 if (t) {
2170 PyErr_SetObject(DBError, t);
2171 Py_DECREF(t);
2172 }
2173 return NULL;
2174 }
2175
2176#if (DBVER >= 41)
2177 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2178 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2179 self->txn=(DBTxnObject *)txnobj;
2180 } else {
2181 self->txn=NULL;
2182 }
2183#else
2184 self->txn=NULL;
2185#endif
2186
2187 MYDB_BEGIN_ALLOW_THREADS;
2188#if (DBVER >= 41)
2189 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2190#else
2191 err = self->db->open(self->db, filename, dbname, type, flags, mode);
2192#endif
2193 MYDB_END_ALLOW_THREADS;
2194 if (makeDBError(err)) {
2195 PyObject *dummy;
2196
2197 dummy=DB_close_internal(self, 0, 0);
2198 Py_XDECREF(dummy);
2199 return NULL;
2200 }
2201
2202#if (DBVER >= 42)
2203 self->db->get_flags(self->db, &self->setflags);
2204#endif
2205
2206 self->flags = flags;
2207
2208 RETURN_NONE();
2209}
2210
2211
2212static PyObject*
2213DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2214{
2215 int flags=0;
2216 PyObject* txnobj = NULL;
2217 int dlen = -1;
2218 int doff = -1;
2219 PyObject* keyobj, *dataobj, *retval;
2220 DBT key, data;
2221 DB_TXN *txn = NULL;
2222 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
2223 "doff", NULL };
2224
2225 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2226 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2227 return NULL;
2228
2229 CHECK_DB_NOT_CLOSED(self);
2230 if (!make_key_dbt(self, keyobj, &key, NULL))
2231 return NULL;
2232 if ( !make_dbt(dataobj, &data) ||
2233 !add_partial_dbt(&data, dlen, doff) ||
2234 !checkTxnObj(txnobj, &txn) )
2235 {
2236 FREE_DBT(key);
2237 return NULL;
2238 }
2239
2240 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2241 FREE_DBT(key);
2242 return NULL;
2243 }
2244
2245 if (flags & DB_APPEND)
2246 retval = NUMBER_FromLong(*((db_recno_t*)key.data));
2247 else {
2248 retval = Py_None;
2249 Py_INCREF(retval);
2250 }
2251 FREE_DBT(key);
2252 return retval;
2253}
2254
2255
2256
2257static PyObject*
2258DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2259{
2260 char* filename;
2261 char* database = NULL;
2262 int err, flags=0;
2263 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
2264
2265 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2266 &filename, &database, &flags))
2267 return NULL;
2268 CHECK_DB_NOT_CLOSED(self);
2269
2270 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
2271
2272 MYDB_BEGIN_ALLOW_THREADS;
2273 err = self->db->remove(self->db, filename, database, flags);
2274 MYDB_END_ALLOW_THREADS;
2275
2276 self->db = NULL;
2277 RETURN_IF_ERR();
2278 RETURN_NONE();
2279}
2280
2281
2282
2283static PyObject*
2284DB_rename(DBObject* self, PyObject* args)
2285{
2286 char* filename;
2287 char* database;
2288 char* newname;
2289 int err, flags=0;
2290
2291 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2292 &flags))
2293 return NULL;
2294 CHECK_DB_NOT_CLOSED(self);
2295
2296 MYDB_BEGIN_ALLOW_THREADS;
2297 err = self->db->rename(self->db, filename, database, newname, flags);
2298 MYDB_END_ALLOW_THREADS;
2299 RETURN_IF_ERR();
2300 RETURN_NONE();
2301}
2302
2303
2304static PyObject*
2305DB_get_private(DBObject* self)
2306{
2307 /* We can give out the private field even if db is closed */
2308 Py_INCREF(self->private_obj);
2309 return self->private_obj;
2310}
2311
2312static PyObject*
2313DB_set_private(DBObject* self, PyObject* private_obj)
2314{
2315 /* We can set the private field even if db is closed */
2316 Py_DECREF(self->private_obj);
2317 Py_INCREF(private_obj);
2318 self->private_obj = private_obj;
2319 RETURN_NONE();
2320}
2321
2322
2323static PyObject*
2324DB_set_bt_minkey(DBObject* self, PyObject* args)
2325{
2326 int err, minkey;
2327
2328 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2329 return NULL;
2330 CHECK_DB_NOT_CLOSED(self);
2331
2332 MYDB_BEGIN_ALLOW_THREADS;
2333 err = self->db->set_bt_minkey(self->db, minkey);
2334 MYDB_END_ALLOW_THREADS;
2335 RETURN_IF_ERR();
2336 RETURN_NONE();
2337}
2338
2339static int
2340_default_cmp(const DBT *leftKey,
2341 const DBT *rightKey)
2342{
2343 int res;
2344 int lsize = leftKey->size, rsize = rightKey->size;
2345
2346 res = memcmp(leftKey->data, rightKey->data,
2347 lsize < rsize ? lsize : rsize);
2348
2349 if (res == 0) {
2350 if (lsize < rsize) {
2351 res = -1;
2352 }
2353 else if (lsize > rsize) {
2354 res = 1;
2355 }
2356 }
2357 return res;
2358}
2359
2360static int
2361_db_compareCallback(DB* db,
2362 const DBT *leftKey,
2363 const DBT *rightKey)
2364{
2365 int res = 0;
2366 PyObject *args;
2367 PyObject *result = NULL;
2368 DBObject *self = (DBObject *)db->app_private;
2369
2370 if (self == NULL || self->btCompareCallback == NULL) {
2371 MYDB_BEGIN_BLOCK_THREADS;
2372 PyErr_SetString(PyExc_TypeError,
2373 (self == 0
2374 ? "DB_bt_compare db is NULL."
2375 : "DB_bt_compare callback is NULL."));
2376 /* we're in a callback within the DB code, we can't raise */
2377 PyErr_Print();
2378 res = _default_cmp(leftKey, rightKey);
2379 MYDB_END_BLOCK_THREADS;
2380 } else {
2381 MYDB_BEGIN_BLOCK_THREADS;
2382
2383 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
2384 if (args != NULL) {
2385 result = PyEval_CallObject(self->btCompareCallback, args);
2386 }
2387 if (args == NULL || result == NULL) {
2388 /* we're in a callback within the DB code, we can't raise */
2389 PyErr_Print();
2390 res = _default_cmp(leftKey, rightKey);
2391 } else if (NUMBER_Check(result)) {
2392 res = NUMBER_AsLong(result);
2393 } else {
2394 PyErr_SetString(PyExc_TypeError,
2395 "DB_bt_compare callback MUST return an int.");
2396 /* we're in a callback within the DB code, we can't raise */
2397 PyErr_Print();
2398 res = _default_cmp(leftKey, rightKey);
2399 }
2400
2401 Py_XDECREF(args);
2402 Py_XDECREF(result);
2403
2404 MYDB_END_BLOCK_THREADS;
2405 }
2406 return res;
2407}
2408
2409static PyObject*
2410DB_set_bt_compare(DBObject* self, PyObject* comparator)
2411{
2412 int err;
2413 PyObject *tuple, *result;
2414
2415 CHECK_DB_NOT_CLOSED(self);
2416
2417 if (!PyCallable_Check(comparator)) {
2418 makeTypeError("Callable", comparator);
2419 return NULL;
2420 }
2421
2422 /*
2423 * Perform a test call of the comparator function with two empty
2424 * string objects here. verify that it returns an int (0).
2425 * err if not.
2426 */
2427 tuple = Py_BuildValue("(ss)", "", "");
2428 result = PyEval_CallObject(comparator, tuple);
2429 Py_DECREF(tuple);
2430 if (result == NULL)
2431 return NULL;
2432 if (!NUMBER_Check(result)) {
2433 Py_DECREF(result);
2434 PyErr_SetString(PyExc_TypeError,
2435 "callback MUST return an int");
2436 return NULL;
2437 } else if (NUMBER_AsLong(result) != 0) {
2438 Py_DECREF(result);
2439 PyErr_SetString(PyExc_TypeError,
2440 "callback failed to return 0 on two empty strings");
2441 return NULL;
2442 }
2443 Py_DECREF(result);
2444
2445 /* We don't accept multiple set_bt_compare operations, in order to
2446 * simplify the code. This would have no real use, as one cannot
2447 * change the function once the db is opened anyway */
2448 if (self->btCompareCallback != NULL) {
2449 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2450 return NULL;
2451 }
2452
2453 Py_INCREF(comparator);
2454 self->btCompareCallback = comparator;
2455
2456 /* This is to workaround a problem with un-initialized threads (see
2457 comment in DB_associate) */
2458#ifdef WITH_THREAD
2459 PyEval_InitThreads();
2460#endif
2461
2462 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2463
2464 if (err) {
2465 /* restore the old state in case of error */
2466 Py_DECREF(comparator);
2467 self->btCompareCallback = NULL;
2468 }
2469
2470 RETURN_IF_ERR();
2471 RETURN_NONE();
2472}
2473
2474
2475static PyObject*
2476DB_set_cachesize(DBObject* self, PyObject* args)
2477{
2478 int err;
2479 int gbytes = 0, bytes = 0, ncache = 0;
2480
2481 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2482 &gbytes,&bytes,&ncache))
2483 return NULL;
2484 CHECK_DB_NOT_CLOSED(self);
2485
2486 MYDB_BEGIN_ALLOW_THREADS;
2487 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2488 MYDB_END_ALLOW_THREADS;
2489 RETURN_IF_ERR();
2490 RETURN_NONE();
2491}
2492
2493
2494static PyObject*
2495DB_set_flags(DBObject* self, PyObject* args)
2496{
2497 int err, flags;
2498
2499 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2500 return NULL;
2501 CHECK_DB_NOT_CLOSED(self);
2502
2503 MYDB_BEGIN_ALLOW_THREADS;
2504 err = self->db->set_flags(self->db, flags);
2505 MYDB_END_ALLOW_THREADS;
2506 RETURN_IF_ERR();
2507
2508 self->setflags |= flags;
2509 RETURN_NONE();
2510}
2511
2512
2513static PyObject*
2514DB_set_h_ffactor(DBObject* self, PyObject* args)
2515{
2516 int err, ffactor;
2517
2518 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2519 return NULL;
2520 CHECK_DB_NOT_CLOSED(self);
2521
2522 MYDB_BEGIN_ALLOW_THREADS;
2523 err = self->db->set_h_ffactor(self->db, ffactor);
2524 MYDB_END_ALLOW_THREADS;
2525 RETURN_IF_ERR();
2526 RETURN_NONE();
2527}
2528
2529
2530static PyObject*
2531DB_set_h_nelem(DBObject* self, PyObject* args)
2532{
2533 int err, nelem;
2534
2535 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2536 return NULL;
2537 CHECK_DB_NOT_CLOSED(self);
2538
2539 MYDB_BEGIN_ALLOW_THREADS;
2540 err = self->db->set_h_nelem(self->db, nelem);
2541 MYDB_END_ALLOW_THREADS;
2542 RETURN_IF_ERR();
2543 RETURN_NONE();
2544}
2545
2546
2547static PyObject*
2548DB_set_lorder(DBObject* self, PyObject* args)
2549{
2550 int err, lorder;
2551
2552 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2553 return NULL;
2554 CHECK_DB_NOT_CLOSED(self);
2555
2556 MYDB_BEGIN_ALLOW_THREADS;
2557 err = self->db->set_lorder(self->db, lorder);
2558 MYDB_END_ALLOW_THREADS;
2559 RETURN_IF_ERR();
2560 RETURN_NONE();
2561}
2562
2563
2564static PyObject*
2565DB_set_pagesize(DBObject* self, PyObject* args)
2566{
2567 int err, pagesize;
2568
2569 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2570 return NULL;
2571 CHECK_DB_NOT_CLOSED(self);
2572
2573 MYDB_BEGIN_ALLOW_THREADS;
2574 err = self->db->set_pagesize(self->db, pagesize);
2575 MYDB_END_ALLOW_THREADS;
2576 RETURN_IF_ERR();
2577 RETURN_NONE();
2578}
2579
2580
2581static PyObject*
2582DB_set_re_delim(DBObject* self, PyObject* args)
2583{
2584 int err;
2585 char delim;
2586
2587 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2588 PyErr_Clear();
2589 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2590 return NULL;
2591 }
2592
2593 CHECK_DB_NOT_CLOSED(self);
2594
2595 MYDB_BEGIN_ALLOW_THREADS;
2596 err = self->db->set_re_delim(self->db, delim);
2597 MYDB_END_ALLOW_THREADS;
2598 RETURN_IF_ERR();
2599 RETURN_NONE();
2600}
2601
2602static PyObject*
2603DB_set_re_len(DBObject* self, PyObject* args)
2604{
2605 int err, len;
2606
2607 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2608 return NULL;
2609 CHECK_DB_NOT_CLOSED(self);
2610
2611 MYDB_BEGIN_ALLOW_THREADS;
2612 err = self->db->set_re_len(self->db, len);
2613 MYDB_END_ALLOW_THREADS;
2614 RETURN_IF_ERR();
2615 RETURN_NONE();
2616}
2617
2618
2619static PyObject*
2620DB_set_re_pad(DBObject* self, PyObject* args)
2621{
2622 int err;
2623 char pad;
2624
2625 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2626 PyErr_Clear();
2627 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2628 return NULL;
2629 }
2630 CHECK_DB_NOT_CLOSED(self);
2631
2632 MYDB_BEGIN_ALLOW_THREADS;
2633 err = self->db->set_re_pad(self->db, pad);
2634 MYDB_END_ALLOW_THREADS;
2635 RETURN_IF_ERR();
2636 RETURN_NONE();
2637}
2638
2639
2640static PyObject*
2641DB_set_re_source(DBObject* self, PyObject* args)
2642{
2643 int err;
2644 char *re_source;
2645
2646 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2647 return NULL;
2648 CHECK_DB_NOT_CLOSED(self);
2649
2650 MYDB_BEGIN_ALLOW_THREADS;
2651 err = self->db->set_re_source(self->db, re_source);
2652 MYDB_END_ALLOW_THREADS;
2653 RETURN_IF_ERR();
2654 RETURN_NONE();
2655}
2656
2657
2658static PyObject*
2659DB_set_q_extentsize(DBObject* self, PyObject* args)
2660{
2661 int err;
2662 int extentsize;
2663
2664 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2665 return NULL;
2666 CHECK_DB_NOT_CLOSED(self);
2667
2668 MYDB_BEGIN_ALLOW_THREADS;
2669 err = self->db->set_q_extentsize(self->db, extentsize);
2670 MYDB_END_ALLOW_THREADS;
2671 RETURN_IF_ERR();
2672 RETURN_NONE();
2673}
2674
2675static PyObject*
2676DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2677{
2678 int err, flags = 0, type;
2679 void* sp;
2680 PyObject* d;
2681#if (DBVER >= 43)
2682 PyObject* txnobj = NULL;
2683 DB_TXN *txn = NULL;
2684 static char* kwnames[] = { "flags", "txn", NULL };
2685#else
2686 static char* kwnames[] = { "flags", NULL };
2687#endif
2688
2689#if (DBVER >= 43)
2690 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2691 &flags, &txnobj))
2692 return NULL;
2693 if (!checkTxnObj(txnobj, &txn))
2694 return NULL;
2695#else
2696 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2697 return NULL;
2698#endif
2699 CHECK_DB_NOT_CLOSED(self);
2700
2701 MYDB_BEGIN_ALLOW_THREADS;
2702#if (DBVER >= 43)
2703 err = self->db->stat(self->db, txn, &sp, flags);
2704#else
2705 err = self->db->stat(self->db, &sp, flags);
2706#endif
2707 MYDB_END_ALLOW_THREADS;
2708 RETURN_IF_ERR();
2709
2710 self->haveStat = 1;
2711
2712 /* Turn the stat structure into a dictionary */
2713 type = _DB_get_type(self);
2714 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2715 free(sp);
2716 return NULL;
2717 }
2718
2719#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2720#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2721#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2722
2723 switch (type) {
2724 case DB_HASH:
2725 MAKE_HASH_ENTRY(magic);
2726 MAKE_HASH_ENTRY(version);
2727 MAKE_HASH_ENTRY(nkeys);
2728 MAKE_HASH_ENTRY(ndata);
2729#if (DBVER >= 46)
2730 MAKE_HASH_ENTRY(pagecnt);
2731#endif
2732 MAKE_HASH_ENTRY(pagesize);
2733#if (DBVER < 41)
2734 MAKE_HASH_ENTRY(nelem);
2735#endif
2736 MAKE_HASH_ENTRY(ffactor);
2737 MAKE_HASH_ENTRY(buckets);
2738 MAKE_HASH_ENTRY(free);
2739 MAKE_HASH_ENTRY(bfree);
2740 MAKE_HASH_ENTRY(bigpages);
2741 MAKE_HASH_ENTRY(big_bfree);
2742 MAKE_HASH_ENTRY(overflows);
2743 MAKE_HASH_ENTRY(ovfl_free);
2744 MAKE_HASH_ENTRY(dup);
2745 MAKE_HASH_ENTRY(dup_free);
2746 break;
2747
2748 case DB_BTREE:
2749 case DB_RECNO:
2750 MAKE_BT_ENTRY(magic);
2751 MAKE_BT_ENTRY(version);
2752 MAKE_BT_ENTRY(nkeys);
2753 MAKE_BT_ENTRY(ndata);
2754#if (DBVER >= 46)
2755 MAKE_BT_ENTRY(pagecnt);
2756#endif
2757 MAKE_BT_ENTRY(pagesize);
2758 MAKE_BT_ENTRY(minkey);
2759 MAKE_BT_ENTRY(re_len);
2760 MAKE_BT_ENTRY(re_pad);
2761 MAKE_BT_ENTRY(levels);
2762 MAKE_BT_ENTRY(int_pg);
2763 MAKE_BT_ENTRY(leaf_pg);
2764 MAKE_BT_ENTRY(dup_pg);
2765 MAKE_BT_ENTRY(over_pg);
2766#if (DBVER >= 43)
2767 MAKE_BT_ENTRY(empty_pg);
2768#endif
2769 MAKE_BT_ENTRY(free);
2770 MAKE_BT_ENTRY(int_pgfree);
2771 MAKE_BT_ENTRY(leaf_pgfree);
2772 MAKE_BT_ENTRY(dup_pgfree);
2773 MAKE_BT_ENTRY(over_pgfree);
2774 break;
2775
2776 case DB_QUEUE:
2777 MAKE_QUEUE_ENTRY(magic);
2778 MAKE_QUEUE_ENTRY(version);
2779 MAKE_QUEUE_ENTRY(nkeys);
2780 MAKE_QUEUE_ENTRY(ndata);
2781 MAKE_QUEUE_ENTRY(pagesize);
2782#if (DBVER >= 41)
2783 MAKE_QUEUE_ENTRY(extentsize);
2784#endif
2785 MAKE_QUEUE_ENTRY(pages);
2786 MAKE_QUEUE_ENTRY(re_len);
2787 MAKE_QUEUE_ENTRY(re_pad);
2788 MAKE_QUEUE_ENTRY(pgfree);
2789#if (DBVER == 31)
2790 MAKE_QUEUE_ENTRY(start);
2791#endif
2792 MAKE_QUEUE_ENTRY(first_recno);
2793 MAKE_QUEUE_ENTRY(cur_recno);
2794 break;
2795
2796 default:
2797 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2798 Py_DECREF(d);
2799 d = NULL;
2800 }
2801
2802#undef MAKE_HASH_ENTRY
2803#undef MAKE_BT_ENTRY
2804#undef MAKE_QUEUE_ENTRY
2805
2806 free(sp);
2807 return d;
2808}
2809
2810static PyObject*
2811DB_sync(DBObject* self, PyObject* args)
2812{
2813 int err;
2814 int flags = 0;
2815
2816 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2817 return NULL;
2818 CHECK_DB_NOT_CLOSED(self);
2819
2820 MYDB_BEGIN_ALLOW_THREADS;
2821 err = self->db->sync(self->db, flags);
2822 MYDB_END_ALLOW_THREADS;
2823 RETURN_IF_ERR();
2824 RETURN_NONE();
2825}
2826
2827
2828static PyObject*
2829DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2830{
2831 int err, flags=0;
2832 u_int32_t count=0;
2833 PyObject* txnobj = NULL;
2834 DB_TXN *txn = NULL;
2835 static char* kwnames[] = { "txn", "flags", NULL };
2836
2837 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2838 &txnobj, &flags))
2839 return NULL;
2840 CHECK_DB_NOT_CLOSED(self);
2841 if (!checkTxnObj(txnobj, &txn))
2842 return NULL;
2843
2844 MYDB_BEGIN_ALLOW_THREADS;
2845 err = self->db->truncate(self->db, txn, &count, flags);
2846 MYDB_END_ALLOW_THREADS;
2847 RETURN_IF_ERR();
2848 return NUMBER_FromLong(count);
2849}
2850
2851
2852static PyObject*
2853DB_upgrade(DBObject* self, PyObject* args)
2854{
2855 int err, flags=0;
2856 char *filename;
2857
2858 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2859 return NULL;
2860 CHECK_DB_NOT_CLOSED(self);
2861
2862 MYDB_BEGIN_ALLOW_THREADS;
2863 err = self->db->upgrade(self->db, filename, flags);
2864 MYDB_END_ALLOW_THREADS;
2865 RETURN_IF_ERR();
2866 RETURN_NONE();
2867}
2868
2869
2870static PyObject*
2871DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2872{
2873 int err, flags=0;
2874 char* fileName;
2875 char* dbName=NULL;
2876 char* outFileName=NULL;
2877 FILE* outFile=NULL;
2878 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2879 NULL };
2880
2881 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2882 &fileName, &dbName, &outFileName, &flags))
2883 return NULL;
2884
2885 CHECK_DB_NOT_CLOSED(self);
2886 if (outFileName)
2887 outFile = fopen(outFileName, "w");
2888 /* XXX(nnorwitz): it should probably be an exception if outFile
2889 can't be opened. */
2890
2891 { /* DB.verify acts as a DB handle destructor (like close) */
2892 PyObject *error;
2893
2894 error=DB_close_internal(self, 0, 1);
2895 if (error ) {
2896 return error;
2897 }
2898 }
2899
2900 MYDB_BEGIN_ALLOW_THREADS;
2901 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2902 MYDB_END_ALLOW_THREADS;
2903
2904 self->db = NULL; /* Implicit close; related objects already released */
2905
2906 if (outFile)
2907 fclose(outFile);
2908
2909 RETURN_IF_ERR();
2910 RETURN_NONE();
2911}
2912
2913
2914static PyObject*
2915DB_set_get_returns_none(DBObject* self, PyObject* args)
2916{
2917 int flags=0;
2918 int oldValue=0;
2919
2920 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2921 return NULL;
2922 CHECK_DB_NOT_CLOSED(self);
2923
2924 if (self->moduleFlags.getReturnsNone)
2925 ++oldValue;
2926 if (self->moduleFlags.cursorSetReturnsNone)
2927 ++oldValue;
2928 self->moduleFlags.getReturnsNone = (flags >= 1);
2929 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2930 return NUMBER_FromLong(oldValue);
2931}
2932
2933#if (DBVER >= 41)
2934static PyObject*
2935DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2936{
2937 int err;
2938 u_int32_t flags=0;
2939 char *passwd = NULL;
2940 static char* kwnames[] = { "passwd", "flags", NULL };
2941
2942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2943 &passwd, &flags)) {
2944 return NULL;
2945 }
2946
2947 MYDB_BEGIN_ALLOW_THREADS;
2948 err = self->db->set_encrypt(self->db, passwd, flags);
2949 MYDB_END_ALLOW_THREADS;
2950
2951 RETURN_IF_ERR();
2952 RETURN_NONE();
2953}
2954#endif /* DBVER >= 41 */
2955
2956
2957/*-------------------------------------------------------------- */
2958/* Mapping and Dictionary-like access routines */
2959
2960Py_ssize_t DB_length(PyObject* _self)
2961{
2962 int err;
2963 Py_ssize_t size = 0;
2964 int flags = 0;
2965 void* sp;
2966 DBObject* self = (DBObject*)_self;
2967
2968 if (self->db == NULL) {
2969 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2970 if (t) {
2971 PyErr_SetObject(DBError, t);
2972 Py_DECREF(t);
2973 }
2974 return -1;
2975 }
2976
2977 if (self->haveStat) { /* Has the stat function been called recently? If
2978 so, we can use the cached value. */
2979 flags = DB_FAST_STAT;
2980 }
2981
2982 MYDB_BEGIN_ALLOW_THREADS;
2983redo_stat_for_length:
2984#if (DBVER >= 43)
2985 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2986#else
2987 err = self->db->stat(self->db, &sp, flags);
2988#endif
2989
2990 /* All the stat structures have matching fields upto the ndata field,
2991 so we can use any of them for the type cast */
2992 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2993
2994 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
2995 * redo a full stat to make sure.
2996 * Fixes SF python bug 1493322, pybsddb bug 1184012
2997 */
2998 if (size == 0 && (flags & DB_FAST_STAT)) {
2999 flags = 0;
3000 if (!err)
3001 free(sp);
3002 goto redo_stat_for_length;
3003 }
3004
3005 MYDB_END_ALLOW_THREADS;
3006
3007 if (err)
3008 return -1;
3009
3010 self->haveStat = 1;
3011
3012 free(sp);
3013 return size;
3014}
3015
3016
3017PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
3018{
3019 int err;
3020 PyObject* retval;
3021 DBT key;
3022 DBT data;
3023
3024 CHECK_DB_NOT_CLOSED(self);
3025 if (!make_key_dbt(self, keyobj, &key, NULL))
3026 return NULL;
3027
3028 CLEAR_DBT(data);
3029 if (CHECK_DBFLAG(self, DB_THREAD)) {
3030 /* Tell Berkeley DB to malloc the return value (thread safe) */
3031 data.flags = DB_DBT_MALLOC;
3032 }
3033 MYDB_BEGIN_ALLOW_THREADS;
3034 err = self->db->get(self->db, NULL, &key, &data, 0);
3035 MYDB_END_ALLOW_THREADS;
3036 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3037 PyErr_SetObject(PyExc_KeyError, keyobj);
3038 retval = NULL;
3039 }
3040 else if (makeDBError(err)) {
3041 retval = NULL;
3042 }
3043 else {
3044 retval = Build_PyString(data.data, data.size);
3045 FREE_DBT(data);
3046 }
3047
3048 FREE_DBT(key);
3049 return retval;
3050}
3051
3052
3053static int
3054DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
3055{
3056 DBT key, data;
3057 int retval;
3058 int flags = 0;
3059
3060 if (self->db == NULL) {
3061 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
3062 if (t) {
3063 PyErr_SetObject(DBError, t);
3064 Py_DECREF(t);
3065 }
3066 return -1;
3067 }
3068
3069 if (!make_key_dbt(self, keyobj, &key, NULL))
3070 return -1;
3071
3072 if (dataobj != NULL) {
3073 if (!make_dbt(dataobj, &data))
3074 retval = -1;
3075 else {
3076 if (self->setflags & (DB_DUP|DB_DUPSORT))
3077 /* dictionaries shouldn't have duplicate keys */
3078 flags = DB_NOOVERWRITE;
3079 retval = _DB_put(self, NULL, &key, &data, flags);
3080
3081 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
3082 /* try deleting any old record that matches and then PUT it
3083 * again... */
3084 _DB_delete(self, NULL, &key, 0);
3085 PyErr_Clear();
3086 retval = _DB_put(self, NULL, &key, &data, flags);
3087 }
3088 }
3089 }
3090 else {
3091 /* dataobj == NULL, so delete the key */
3092 retval = _DB_delete(self, NULL, &key, 0);
3093 }
3094 FREE_DBT(key);
3095 return retval;
3096}
3097
3098
3099static PyObject*
3100DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
3101{
3102 int err;
3103 PyObject* keyobj;
3104 DBT key, data;
3105 PyObject* txnobj = NULL;
3106 DB_TXN *txn = NULL;
3107 static char* kwnames[] = {"key","txn", NULL};
3108
3109 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
3110 &keyobj, &txnobj))
3111 return NULL;
3112
3113 CHECK_DB_NOT_CLOSED(self);
3114 if (!make_key_dbt(self, keyobj, &key, NULL))
3115 return NULL;
3116 if (!checkTxnObj(txnobj, &txn)) {
3117 FREE_DBT(key);
3118 return NULL;
3119 }
3120
3121 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
3122 it has a record but can't allocate a buffer for the data. This saves
3123 having to deal with data we won't be using.
3124 */
3125 CLEAR_DBT(data);
3126 data.flags = DB_DBT_USERMEM;
3127
3128 MYDB_BEGIN_ALLOW_THREADS;
3129 err = self->db->get(self->db, txn, &key, &data, 0);
3130 MYDB_END_ALLOW_THREADS;
3131 FREE_DBT(key);
3132
3133 if (err == DB_BUFFER_SMALL || err == 0) {
3134 return NUMBER_FromLong(1);
3135 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3136 return NUMBER_FromLong(0);
3137 }
3138
3139 makeDBError(err);
3140 return NULL;
3141}
3142
3143
3144#define _KEYS_LIST 1
3145#define _VALUES_LIST 2
3146#define _ITEMS_LIST 3
3147
3148static PyObject*
3149_DB_make_list(DBObject* self, DB_TXN* txn, int type)
3150{
3151 int err, dbtype;
3152 DBT key;
3153 DBT data;
3154 DBC *cursor;
3155 PyObject* list;
3156 PyObject* item = NULL;
3157
3158 CHECK_DB_NOT_CLOSED(self);
3159 CLEAR_DBT(key);
3160 CLEAR_DBT(data);
3161
3162 dbtype = _DB_get_type(self);
3163 if (dbtype == -1)
3164 return NULL;
3165
3166 list = PyList_New(0);
3167 if (list == NULL)
3168 return NULL;
3169
3170 /* get a cursor */
3171 MYDB_BEGIN_ALLOW_THREADS;
3172 err = self->db->cursor(self->db, txn, &cursor, 0);
3173 MYDB_END_ALLOW_THREADS;
3174 if (makeDBError(err)) {
3175 Py_DECREF(list);
3176 return NULL;
3177 }
3178
3179 while (1) { /* use the cursor to traverse the DB, collecting items */
3180 MYDB_BEGIN_ALLOW_THREADS;
3181 err = _DBC_get(cursor, &key, &data, DB_NEXT);
3182 MYDB_END_ALLOW_THREADS;
3183
3184 if (err) {
3185 /* for any error, break out of the loop */
3186 break;
3187 }
3188
3189 switch (type) {
3190 case _KEYS_LIST:
3191 switch(dbtype) {
3192 case DB_BTREE:
3193 case DB_HASH:
3194 default:
3195 item = Build_PyString(key.data, key.size);
3196 break;
3197 case DB_RECNO:
3198 case DB_QUEUE:
3199 item = NUMBER_FromLong(*((db_recno_t*)key.data));
3200 break;
3201 }
3202 break;
3203
3204 case _VALUES_LIST:
3205 item = Build_PyString(data.data, data.size);
3206 break;
3207
3208 case _ITEMS_LIST:
3209 switch(dbtype) {
3210 case DB_BTREE:
3211 case DB_HASH:
3212 default:
3213 item = BuildValue_SS(key.data, key.size, data.data, data.size);
3214 break;
3215 case DB_RECNO:
3216 case DB_QUEUE:
3217 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3218 break;
3219 }
3220 break;
3221 default:
3222 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3223 item = NULL;
3224 break;
3225 }
3226 if (item == NULL) {
3227 Py_DECREF(list);
3228 list = NULL;
3229 goto done;
3230 }
3231 if (PyList_Append(list, item)) {
3232 Py_DECREF(list);
3233 Py_DECREF(item);
3234 list = NULL;
3235 goto done;
3236 }
3237 Py_DECREF(item);
3238 }
3239
3240 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3241 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
3242 Py_DECREF(list);
3243 list = NULL;
3244 }
3245
3246 done:
3247 MYDB_BEGIN_ALLOW_THREADS;
3248 _DBC_close(cursor);
3249 MYDB_END_ALLOW_THREADS;
3250 return list;
3251}
3252
3253
3254static PyObject*
3255DB_keys(DBObject* self, PyObject* args)
3256{
3257 PyObject* txnobj = NULL;
3258 DB_TXN *txn = NULL;
3259
3260 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
3261 return NULL;
3262 if (!checkTxnObj(txnobj, &txn))
3263 return NULL;
3264 return _DB_make_list(self, txn, _KEYS_LIST);
3265}
3266
3267
3268static PyObject*
3269DB_items(DBObject* self, PyObject* args)
3270{
3271 PyObject* txnobj = NULL;
3272 DB_TXN *txn = NULL;
3273
3274 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
3275 return NULL;
3276 if (!checkTxnObj(txnobj, &txn))
3277 return NULL;
3278 return _DB_make_list(self, txn, _ITEMS_LIST);
3279}
3280
3281
3282static PyObject*
3283DB_values(DBObject* self, PyObject* args)
3284{
3285 PyObject* txnobj = NULL;
3286 DB_TXN *txn = NULL;
3287
3288 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
3289 return NULL;
3290 if (!checkTxnObj(txnobj, &txn))
3291 return NULL;
3292 return _DB_make_list(self, txn, _VALUES_LIST);
3293}
3294
3295/* --------------------------------------------------------------------- */
3296/* DBCursor methods */
3297
3298
3299static PyObject*
3300DBC_close_internal(DBCursorObject* self)
3301{
3302 int err = 0;
3303
3304 if (self->dbc != NULL) {
3305 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3306 if (self->txn) {
3307 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3308 self->txn=NULL;
3309 }
3310
3311 MYDB_BEGIN_ALLOW_THREADS;
3312 err = _DBC_close(self->dbc);
3313 MYDB_END_ALLOW_THREADS;
3314 self->dbc = NULL;
3315 }
3316 RETURN_IF_ERR();
3317 RETURN_NONE();
3318}
3319
3320static PyObject*
3321DBC_close(DBCursorObject* self)
3322{
3323 return DBC_close_internal(self);
3324}
3325
3326
3327static PyObject*
3328DBC_count(DBCursorObject* self, PyObject* args)
3329{
3330 int err = 0;
3331 db_recno_t count;
3332 int flags = 0;
3333
3334 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3335 return NULL;
3336
3337 CHECK_CURSOR_NOT_CLOSED(self);
3338
3339 MYDB_BEGIN_ALLOW_THREADS;
3340 err = _DBC_count(self->dbc, &count, flags);
3341 MYDB_END_ALLOW_THREADS;
3342 RETURN_IF_ERR();
3343
3344 return NUMBER_FromLong(count);
3345}
3346
3347
3348static PyObject*
3349DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3350{
3351 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3352}
3353
3354
3355static PyObject*
3356DBC_delete(DBCursorObject* self, PyObject* args)
3357{
3358 int err, flags=0;
3359
3360 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3361 return NULL;
3362
3363 CHECK_CURSOR_NOT_CLOSED(self);
3364
3365 MYDB_BEGIN_ALLOW_THREADS;
3366 err = _DBC_del(self->dbc, flags);
3367 MYDB_END_ALLOW_THREADS;
3368 RETURN_IF_ERR();
3369
3370 self->mydb->haveStat = 0;
3371 RETURN_NONE();
3372}
3373
3374
3375static PyObject*
3376DBC_dup(DBCursorObject* self, PyObject* args)
3377{
3378 int err, flags =0;
3379 DBC* dbc = NULL;
3380
3381 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3382 return NULL;
3383
3384 CHECK_CURSOR_NOT_CLOSED(self);
3385
3386 MYDB_BEGIN_ALLOW_THREADS;
3387 err = _DBC_dup(self->dbc, &dbc, flags);
3388 MYDB_END_ALLOW_THREADS;
3389 RETURN_IF_ERR();
3390
3391 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
3392}
3393
3394static PyObject*
3395DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3396{
3397 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3398}
3399
3400
3401static PyObject*
3402DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3403{
3404 int err, flags=0;
3405 PyObject* keyobj = NULL;
3406 PyObject* dataobj = NULL;
3407 PyObject* retval = NULL;
3408 int dlen = -1;
3409 int doff = -1;
3410 DBT key, data;
3411 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3412 NULL };
3413
3414 CLEAR_DBT(key);
3415 CLEAR_DBT(data);
3416 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3417 &flags, &dlen, &doff))
3418 {
3419 PyErr_Clear();
3420 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3421 &kwnames[1],
3422 &keyobj, &flags, &dlen, &doff))
3423 {
3424 PyErr_Clear();
3425 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3426 kwnames, &keyobj, &dataobj,
3427 &flags, &dlen, &doff))
3428 {
3429 return NULL;
3430 }
3431 }
3432 }
3433
3434 CHECK_CURSOR_NOT_CLOSED(self);
3435
3436 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3437 return NULL;
3438 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3439 (!add_partial_dbt(&data, dlen, doff)) )
3440 {
3441 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3442 return NULL;
3443 }
3444
3445 MYDB_BEGIN_ALLOW_THREADS;
3446 err = _DBC_get(self->dbc, &key, &data, flags);
3447 MYDB_END_ALLOW_THREADS;
3448
3449 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3450 && self->mydb->moduleFlags.getReturnsNone) {
3451 Py_INCREF(Py_None);
3452 retval = Py_None;
3453 }
3454 else if (makeDBError(err)) {
3455 retval = NULL;
3456 }
3457 else {
3458 switch (_DB_get_type(self->mydb)) {
3459 case -1:
3460 retval = NULL;
3461 break;
3462 case DB_BTREE:
3463 case DB_HASH:
3464 default:
3465 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3466 break;
3467 case DB_RECNO:
3468 case DB_QUEUE:
3469 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3470 break;
3471 }
3472 }
3473 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3474 return retval;
3475}
3476
3477static PyObject*
3478DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3479{
3480 int err, flags=0;
3481 PyObject* keyobj = NULL;
3482 PyObject* dataobj = NULL;
3483 PyObject* retval = NULL;
3484 int dlen = -1;
3485 int doff = -1;
3486 DBT key, pkey, data;
3487 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3488 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3489
3490 CLEAR_DBT(key);
3491 CLEAR_DBT(data);
3492 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3493 &flags, &dlen, &doff))
3494 {
3495 PyErr_Clear();
3496 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3497 kwnames_keyOnly,
3498 &keyobj, &flags, &dlen, &doff))
3499 {
3500 PyErr_Clear();
3501 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3502 kwnames, &keyobj, &dataobj,
3503 &flags, &dlen, &doff))
3504 {
3505 return NULL;
3506 }
3507 }
3508 }
3509
3510 CHECK_CURSOR_NOT_CLOSED(self);
3511
3512 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3513 return NULL;
3514 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3515 (!add_partial_dbt(&data, dlen, doff)) ) {
3516 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3517 return NULL;
3518 }
3519
3520 CLEAR_DBT(pkey);
3521 pkey.flags = DB_DBT_MALLOC;
3522
3523 MYDB_BEGIN_ALLOW_THREADS;
3524 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
3525 MYDB_END_ALLOW_THREADS;
3526
3527 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3528 && self->mydb->moduleFlags.getReturnsNone) {
3529 Py_INCREF(Py_None);
3530 retval = Py_None;
3531 }
3532 else if (makeDBError(err)) {
3533 retval = NULL;
3534 }
3535 else {
3536 PyObject *pkeyObj;
3537 PyObject *dataObj;
3538 dataObj = Build_PyString(data.data, data.size);
3539
3540 if (self->mydb->primaryDBType == DB_RECNO ||
3541 self->mydb->primaryDBType == DB_QUEUE)
3542 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
3543 else
3544 pkeyObj = Build_PyString(pkey.data, pkey.size);
3545
3546 if (key.data && key.size) /* return key, pkey and data */
3547 {
3548 PyObject *keyObj;
3549 int type = _DB_get_type(self->mydb);
3550 if (type == DB_RECNO || type == DB_QUEUE)
3551 keyObj = NUMBER_FromLong(*(int *)key.data);
3552 else
3553 keyObj = Build_PyString(key.data, key.size);
3554#if (PY_VERSION_HEX >= 0x02040000)
3555 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
3556#else
3557 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3558#endif
3559 Py_DECREF(keyObj);
3560 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3561 }
3562 else /* return just the pkey and data */
3563 {
3564#if (PY_VERSION_HEX >= 0x02040000)
3565 retval = PyTuple_Pack(2, pkeyObj, dataObj);
3566#else
3567 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3568#endif
3569 }
3570 Py_DECREF(dataObj);
3571 Py_DECREF(pkeyObj);
3572 FREE_DBT(pkey);
3573 }
3574 /* the only time REALLOC should be set is if we used an integer
3575 * key that make_key_dbt malloc'd for us. always free these. */
3576 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
3577 FREE_DBT(key);
3578 }
3579 return retval;
3580}
3581
3582
3583static PyObject*
3584DBC_get_recno(DBCursorObject* self)
3585{
3586 int err;
3587 db_recno_t recno;
3588 DBT key;
3589 DBT data;
3590
3591 CHECK_CURSOR_NOT_CLOSED(self);
3592
3593 CLEAR_DBT(key);
3594 CLEAR_DBT(data);
3595
3596 MYDB_BEGIN_ALLOW_THREADS;
3597 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
3598 MYDB_END_ALLOW_THREADS;
3599 RETURN_IF_ERR();
3600
3601 recno = *((db_recno_t*)data.data);
3602 return NUMBER_FromLong(recno);
3603}
3604
3605
3606static PyObject*
3607DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3608{
3609 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3610}
3611
3612
3613static PyObject*
3614DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3615{
3616 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3617}
3618
3619
3620static PyObject*
3621DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3622{
3623 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3624}
3625
3626
3627static PyObject*
3628DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3629{
3630 int err, flags = 0;
3631 PyObject* keyobj, *dataobj;
3632 DBT key, data;
3633 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3634 NULL };
3635 int dlen = -1;
3636 int doff = -1;
3637
3638 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3639 &keyobj, &dataobj, &flags, &dlen, &doff))
3640 return NULL;
3641
3642 CHECK_CURSOR_NOT_CLOSED(self);
3643
3644 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3645 return NULL;
3646 if (!make_dbt(dataobj, &data) ||
3647 !add_partial_dbt(&data, dlen, doff) )
3648 {
3649 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3650 return NULL;
3651 }
3652
3653 MYDB_BEGIN_ALLOW_THREADS;
3654 err = _DBC_put(self->dbc, &key, &data, flags);
3655 MYDB_END_ALLOW_THREADS;
3656 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3657 RETURN_IF_ERR();
3658 self->mydb->haveStat = 0;
3659 RETURN_NONE();
3660}
3661
3662
3663static PyObject*
3664DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3665{
3666 int err, flags = 0;
3667 DBT key, data;
3668 PyObject* retval, *keyobj;
3669 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3670 int dlen = -1;
3671 int doff = -1;
3672
3673 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3674 &keyobj, &flags, &dlen, &doff))
3675 return NULL;
3676
3677 CHECK_CURSOR_NOT_CLOSED(self);
3678
3679 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3680 return NULL;
3681
3682 CLEAR_DBT(data);
3683 if (!add_partial_dbt(&data, dlen, doff)) {
3684 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3685 return NULL;
3686 }
3687
3688 MYDB_BEGIN_ALLOW_THREADS;
3689 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
3690 MYDB_END_ALLOW_THREADS;
3691 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3692 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3693 Py_INCREF(Py_None);
3694 retval = Py_None;
3695 }
3696 else if (makeDBError(err)) {
3697 retval = NULL;
3698 }
3699 else {
3700 switch (_DB_get_type(self->mydb)) {
3701 case -1:
3702 retval = NULL;
3703 break;
3704 case DB_BTREE:
3705 case DB_HASH:
3706 default:
3707 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3708 break;
3709 case DB_RECNO:
3710 case DB_QUEUE:
3711 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3712 break;
3713 }
3714 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3715 }
3716 /* the only time REALLOC should be set is if we used an integer
3717 * key that make_key_dbt malloc'd for us. always free these. */
3718 if (key.flags & DB_DBT_REALLOC) {
3719 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3720 }
3721
3722 return retval;
3723}
3724
3725
3726static PyObject*
3727DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3728{
3729 int err, flags = 0;
3730 DBT key, data;
3731 PyObject* retval, *keyobj;
3732 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3733 int dlen = -1;
3734 int doff = -1;
3735
3736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3737 &keyobj, &flags, &dlen, &doff))
3738 return NULL;
3739
3740 CHECK_CURSOR_NOT_CLOSED(self);
3741
3742 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3743 return NULL;
3744
3745 CLEAR_DBT(data);
3746 if (!add_partial_dbt(&data, dlen, doff)) {
3747 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3748 return NULL;
3749 }
3750 MYDB_BEGIN_ALLOW_THREADS;
3751 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3752 MYDB_END_ALLOW_THREADS;
3753 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3754 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3755 Py_INCREF(Py_None);
3756 retval = Py_None;
3757 }
3758 else if (makeDBError(err)) {
3759 retval = NULL;
3760 }
3761 else {
3762 switch (_DB_get_type(self->mydb)) {
3763 case -1:
3764 retval = NULL;
3765 break;
3766 case DB_BTREE:
3767 case DB_HASH:
3768 default:
3769 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3770 break;
3771 case DB_RECNO:
3772 case DB_QUEUE:
3773 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3774 break;
3775 }
3776 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3777 }
3778 /* the only time REALLOC should be set is if we used an integer
3779 * key that make_key_dbt malloc'd for us. always free these. */
3780 if (key.flags & DB_DBT_REALLOC) {
3781 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3782 }
3783
3784 return retval;
3785}
3786
3787static PyObject*
3788_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3789 int flags, unsigned int returnsNone)
3790{
3791 int err;
3792 DBT key, data;
3793 PyObject* retval;
3794
3795 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3796 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3797 return NULL;
3798 if (!make_dbt(dataobj, &data)) {
3799 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3800 return NULL;
3801 }
3802
3803 MYDB_BEGIN_ALLOW_THREADS;
3804 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3805 MYDB_END_ALLOW_THREADS;
3806 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3807 Py_INCREF(Py_None);
3808 retval = Py_None;
3809 }
3810 else if (makeDBError(err)) {
3811 retval = NULL;
3812 }
3813 else {
3814 switch (_DB_get_type(self->mydb)) {
3815 case -1:
3816 retval = NULL;
3817 break;
3818 case DB_BTREE:
3819 case DB_HASH:
3820 default:
3821 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3822 break;
3823 case DB_RECNO:
3824 case DB_QUEUE:
3825 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3826 break;
3827 }
3828 }
3829
3830 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3831 return retval;
3832}
3833
3834static PyObject*
3835DBC_get_both(DBCursorObject* self, PyObject* args)
3836{
3837 int flags=0;
3838 PyObject *keyobj, *dataobj;
3839
3840 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3841 return NULL;
3842
3843 /* if the cursor is closed, self->mydb may be invalid */
3844 CHECK_CURSOR_NOT_CLOSED(self);
3845
3846 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3847 self->mydb->moduleFlags.getReturnsNone);
3848}
3849
3850/* Return size of entry */
3851static PyObject*
3852DBC_get_current_size(DBCursorObject* self)
3853{
3854 int err, flags=DB_CURRENT;
3855 PyObject* retval = NULL;
3856 DBT key, data;
3857
3858 CHECK_CURSOR_NOT_CLOSED(self);
3859 CLEAR_DBT(key);
3860 CLEAR_DBT(data);
3861
3862 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3863 getting the record size. */
3864 data.flags = DB_DBT_USERMEM;
3865 data.ulen = 0;
3866 MYDB_BEGIN_ALLOW_THREADS;
3867 err = _DBC_get(self->dbc, &key, &data, flags);
3868 MYDB_END_ALLOW_THREADS;
3869 if (err == DB_BUFFER_SMALL || !err) {
3870 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3871 retval = NUMBER_FromLong((long)data.size);
3872 err = 0;
3873 }
3874
3875 RETURN_IF_ERR();
3876 return retval;
3877}
3878
3879static PyObject*
3880DBC_set_both(DBCursorObject* self, PyObject* args)
3881{
3882 int flags=0;
3883 PyObject *keyobj, *dataobj;
3884
3885 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3886 return NULL;
3887
3888 /* if the cursor is closed, self->mydb may be invalid */
3889 CHECK_CURSOR_NOT_CLOSED(self);
3890
3891 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3892 self->mydb->moduleFlags.cursorSetReturnsNone);
3893}
3894
3895
3896static PyObject*
3897DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3898{
3899 int err, irecno, flags=0;
3900 db_recno_t recno;
3901 DBT key, data;
3902 PyObject* retval;
3903 int dlen = -1;
3904 int doff = -1;
3905 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3906
3907 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3908 &irecno, &flags, &dlen, &doff))
3909 return NULL;
3910
3911 CHECK_CURSOR_NOT_CLOSED(self);
3912
3913 CLEAR_DBT(key);
3914 recno = (db_recno_t) irecno;
3915 /* use allocated space so DB will be able to realloc room for the real
3916 * key */
3917 key.data = malloc(sizeof(db_recno_t));
3918 if (key.data == NULL) {
3919 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3920 return NULL;
3921 }
3922 key.size = sizeof(db_recno_t);
3923 key.ulen = key.size;
3924 memcpy(key.data, &recno, sizeof(db_recno_t));
3925 key.flags = DB_DBT_REALLOC;
3926
3927 CLEAR_DBT(data);
3928 if (!add_partial_dbt(&data, dlen, doff)) {
3929 FREE_DBT(key);
3930 return NULL;
3931 }
3932
3933 MYDB_BEGIN_ALLOW_THREADS;
3934 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3935 MYDB_END_ALLOW_THREADS;
3936 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3937 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3938 Py_INCREF(Py_None);
3939 retval = Py_None;
3940 }
3941 else if (makeDBError(err)) {
3942 retval = NULL;
3943 }
3944 else { /* Can only be used for BTrees, so no need to return int key */
3945 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3946 }
3947 FREE_DBT(key);
3948
3949 return retval;
3950}
3951
3952
3953static PyObject*
3954DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3955{
3956 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3957}
3958
3959
3960static PyObject*
3961DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3962{
3963 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3964}
3965
3966
3967static PyObject*
3968DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3969{
3970 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3971}
3972
3973
3974static PyObject*
3975DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3976{
3977 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3978}
3979
3980
3981static PyObject*
3982DBC_join_item(DBCursorObject* self, PyObject* args)
3983{
3984 int err, flags=0;
3985 DBT key, data;
3986 PyObject* retval;
3987
3988 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3989 return NULL;
3990
3991 CHECK_CURSOR_NOT_CLOSED(self);
3992
3993 CLEAR_DBT(key);
3994 CLEAR_DBT(data);
3995
3996 MYDB_BEGIN_ALLOW_THREADS;
3997 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3998 MYDB_END_ALLOW_THREADS;
3999 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
4000 && self->mydb->moduleFlags.getReturnsNone) {
4001 Py_INCREF(Py_None);
4002 retval = Py_None;
4003 }
4004 else if (makeDBError(err)) {
4005 retval = NULL;
4006 }
4007 else {
4008 retval = BuildValue_S(key.data, key.size);
4009 }
4010
4011 return retval;
4012}
4013
4014
4015
4016/* --------------------------------------------------------------------- */
4017/* DBEnv methods */
4018
4019
4020static PyObject*
4021DBEnv_close_internal(DBEnvObject* self, int flags)
4022{
4023 PyObject *dummy;
4024 int err;
4025
4026 if (!self->closed) { /* Don't close more than once */
4027 while(self->children_txns) {
4028 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
4029 Py_XDECREF(dummy);
4030 }
4031 while(self->children_dbs) {
4032 dummy=DB_close_internal(self->children_dbs, 0, 0);
4033 Py_XDECREF(dummy);
4034 }
4035 }
4036
4037 self->closed = 1;
4038 if (self->db_env) {
4039 MYDB_BEGIN_ALLOW_THREADS;
4040 err = self->db_env->close(self->db_env, flags);
4041 MYDB_END_ALLOW_THREADS;
4042 /* after calling DBEnv->close, regardless of error, this DBEnv
4043 * may not be accessed again (Berkeley DB docs). */
4044 self->db_env = NULL;
4045 RETURN_IF_ERR();
4046 }
4047 RETURN_NONE();
4048}
4049
4050static PyObject*
4051DBEnv_close(DBEnvObject* self, PyObject* args)
4052{
4053 int flags = 0;
4054
4055 if (!PyArg_ParseTuple(args, "|i:close", &flags))
4056 return NULL;
4057 return DBEnv_close_internal(self, flags);
4058}
4059
4060
4061static PyObject*
4062DBEnv_open(DBEnvObject* self, PyObject* args)
4063{
4064 int err, flags=0, mode=0660;
4065 char *db_home;
4066
4067 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
4068 return NULL;
4069
4070 CHECK_ENV_NOT_CLOSED(self);
4071
4072 MYDB_BEGIN_ALLOW_THREADS;
4073 err = self->db_env->open(self->db_env, db_home, flags, mode);
4074 MYDB_END_ALLOW_THREADS;
4075 RETURN_IF_ERR();
4076 self->closed = 0;
4077 self->flags = flags;
4078 RETURN_NONE();
4079}
4080
4081
4082static PyObject*
4083DBEnv_remove(DBEnvObject* self, PyObject* args)
4084{
4085 int err, flags=0;
4086 char *db_home;
4087
4088 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
4089 return NULL;
4090 CHECK_ENV_NOT_CLOSED(self);
4091 MYDB_BEGIN_ALLOW_THREADS;
4092 err = self->db_env->remove(self->db_env, db_home, flags);
4093 MYDB_END_ALLOW_THREADS;
4094 RETURN_IF_ERR();
4095 RETURN_NONE();
4096}
4097
4098#if (DBVER >= 41)
4099static PyObject*
4100DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4101{
4102 int err;
4103 u_int32_t flags=0;
4104 char *file = NULL;
4105 char *database = NULL;
4106 PyObject *txnobj = NULL;
4107 DB_TXN *txn = NULL;
4108 static char* kwnames[] = { "file", "database", "txn", "flags",
4109 NULL };
4110
4111 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
4112 &file, &database, &txnobj, &flags)) {
4113 return NULL;
4114 }
4115 if (!checkTxnObj(txnobj, &txn)) {
4116 return NULL;
4117 }
4118 CHECK_ENV_NOT_CLOSED(self);
4119 MYDB_BEGIN_ALLOW_THREADS;
4120 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4121 MYDB_END_ALLOW_THREADS;
4122 RETURN_IF_ERR();
4123 RETURN_NONE();
4124}
4125
4126static PyObject*
4127DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4128{
4129 int err;
4130 u_int32_t flags=0;
4131 char *file = NULL;
4132 char *database = NULL;
4133 char *newname = NULL;
4134 PyObject *txnobj = NULL;
4135 DB_TXN *txn = NULL;
4136 static char* kwnames[] = { "file", "database", "newname", "txn",
4137 "flags", NULL };
4138
4139 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
4140 &file, &database, &newname, &txnobj, &flags)) {
4141 return NULL;
4142 }
4143 if (!checkTxnObj(txnobj, &txn)) {
4144 return NULL;
4145 }
4146 CHECK_ENV_NOT_CLOSED(self);
4147 MYDB_BEGIN_ALLOW_THREADS;
4148 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4149 flags);
4150 MYDB_END_ALLOW_THREADS;
4151 RETURN_IF_ERR();
4152 RETURN_NONE();
4153}
4154
4155static PyObject*
4156DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4157{
4158 int err;
4159 u_int32_t flags=0;
4160 char *passwd = NULL;
4161 static char* kwnames[] = { "passwd", "flags", NULL };
4162
4163 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4164 &passwd, &flags)) {
4165 return NULL;
4166 }
4167
4168 MYDB_BEGIN_ALLOW_THREADS;
4169 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4170 MYDB_END_ALLOW_THREADS;
4171
4172 RETURN_IF_ERR();
4173 RETURN_NONE();
4174}
4175#endif /* DBVER >= 41 */
4176
4177static PyObject*
4178DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4179{
4180 int err;
4181 u_int32_t flags=0;
4182 u_int32_t timeout = 0;
4183 static char* kwnames[] = { "timeout", "flags", NULL };
4184
4185 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4186 &timeout, &flags)) {
4187 return NULL;
4188 }
4189
4190 MYDB_BEGIN_ALLOW_THREADS;
4191 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4192 MYDB_END_ALLOW_THREADS;
4193
4194 RETURN_IF_ERR();
4195 RETURN_NONE();
4196}
4197
4198static PyObject*
4199DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4200{
4201 int err;
4202 long shm_key = 0;
4203
4204 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4205 return NULL;
4206 CHECK_ENV_NOT_CLOSED(self);
4207
4208 err = self->db_env->set_shm_key(self->db_env, shm_key);
4209 RETURN_IF_ERR();
4210 RETURN_NONE();
4211}
4212
4213static PyObject*
4214DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4215{
4216 int err, gbytes=0, bytes=0, ncache=0;
4217
4218 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4219 &gbytes, &bytes, &ncache))
4220 return NULL;
4221 CHECK_ENV_NOT_CLOSED(self);
4222
4223 MYDB_BEGIN_ALLOW_THREADS;
4224 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4225 MYDB_END_ALLOW_THREADS;
4226 RETURN_IF_ERR();
4227 RETURN_NONE();
4228}
4229
4230
4231static PyObject*
4232DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4233{
4234 int err, flags=0, onoff=0;
4235
4236 if (!PyArg_ParseTuple(args, "ii:set_flags",
4237 &flags, &onoff))
4238 return NULL;
4239 CHECK_ENV_NOT_CLOSED(self);
4240
4241 MYDB_BEGIN_ALLOW_THREADS;
4242 err = self->db_env->set_flags(self->db_env, flags, onoff);
4243 MYDB_END_ALLOW_THREADS;
4244 RETURN_IF_ERR();
4245 RETURN_NONE();
4246}
4247
4248
4249#if (DBVER >= 47)
4250static PyObject*
4251DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
4252{
4253 int err, flags, onoff;
4254
4255 if (!PyArg_ParseTuple(args, "ii:log_set_config",
4256 &flags, &onoff))
4257 return NULL;
4258 CHECK_ENV_NOT_CLOSED(self);
4259
4260 MYDB_BEGIN_ALLOW_THREADS;
4261 err = self->db_env->log_set_config(self->db_env, flags, onoff);
4262 MYDB_END_ALLOW_THREADS;
4263 RETURN_IF_ERR();
4264 RETURN_NONE();
4265}
4266#endif /* DBVER >= 47 */
4267
4268
4269static PyObject*
4270DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4271{
4272 int err;
4273 char *dir;
4274
4275 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4276 return NULL;
4277 CHECK_ENV_NOT_CLOSED(self);
4278
4279 MYDB_BEGIN_ALLOW_THREADS;
4280 err = self->db_env->set_data_dir(self->db_env, dir);
4281 MYDB_END_ALLOW_THREADS;
4282 RETURN_IF_ERR();
4283 RETURN_NONE();
4284}
4285
4286
4287static PyObject*
4288DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4289{
4290 int err, lg_bsize;
4291
4292 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4293 return NULL;
4294 CHECK_ENV_NOT_CLOSED(self);
4295
4296 MYDB_BEGIN_ALLOW_THREADS;
4297 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4298 MYDB_END_ALLOW_THREADS;
4299 RETURN_IF_ERR();
4300 RETURN_NONE();
4301}
4302
4303
4304static PyObject*
4305DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4306{
4307 int err;
4308 char *dir;
4309
4310 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4311 return NULL;
4312 CHECK_ENV_NOT_CLOSED(self);
4313
4314 MYDB_BEGIN_ALLOW_THREADS;
4315 err = self->db_env->set_lg_dir(self->db_env, dir);
4316 MYDB_END_ALLOW_THREADS;
4317 RETURN_IF_ERR();
4318 RETURN_NONE();
4319}
4320
4321static PyObject*
4322DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4323{
4324 int err, lg_max;
4325
4326 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4327 return NULL;
4328 CHECK_ENV_NOT_CLOSED(self);
4329
4330 MYDB_BEGIN_ALLOW_THREADS;
4331 err = self->db_env->set_lg_max(self->db_env, lg_max);
4332 MYDB_END_ALLOW_THREADS;
4333 RETURN_IF_ERR();
4334 RETURN_NONE();
4335}
4336
4337#if (DBVER >= 42)
4338static PyObject*
4339DBEnv_get_lg_max(DBEnvObject* self)
4340{
4341 int err;
4342 u_int32_t lg_max;
4343
4344 CHECK_ENV_NOT_CLOSED(self);
4345
4346 MYDB_BEGIN_ALLOW_THREADS;
4347 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4348 MYDB_END_ALLOW_THREADS;
4349 RETURN_IF_ERR();
4350 return NUMBER_FromLong(lg_max);
4351}
4352#endif
4353
4354
4355static PyObject*
4356DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4357{
4358 int err, lg_max;
4359
4360 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4361 return NULL;
4362 CHECK_ENV_NOT_CLOSED(self);
4363
4364 MYDB_BEGIN_ALLOW_THREADS;
4365 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4366 MYDB_END_ALLOW_THREADS;
4367 RETURN_IF_ERR();
4368 RETURN_NONE();
4369}
4370
4371
4372static PyObject*
4373DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4374{
4375 int err, lk_detect;
4376
4377 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4378 return NULL;
4379 CHECK_ENV_NOT_CLOSED(self);
4380
4381 MYDB_BEGIN_ALLOW_THREADS;
4382 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4383 MYDB_END_ALLOW_THREADS;
4384 RETURN_IF_ERR();
4385 RETURN_NONE();
4386}
4387
4388
4389#if (DBVER < 45)
4390static PyObject*
4391DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4392{
4393 int err, max;
4394
4395 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4396 return NULL;
4397 CHECK_ENV_NOT_CLOSED(self);
4398
4399 MYDB_BEGIN_ALLOW_THREADS;
4400 err = self->db_env->set_lk_max(self->db_env, max);
4401 MYDB_END_ALLOW_THREADS;
4402 RETURN_IF_ERR();
4403 RETURN_NONE();
4404}
4405#endif
4406
4407
4408
4409static PyObject*
4410DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4411{
4412 int err, max;
4413
4414 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4415 return NULL;
4416 CHECK_ENV_NOT_CLOSED(self);
4417
4418 MYDB_BEGIN_ALLOW_THREADS;
4419 err = self->db_env->set_lk_max_locks(self->db_env, max);
4420 MYDB_END_ALLOW_THREADS;
4421 RETURN_IF_ERR();
4422 RETURN_NONE();
4423}
4424
4425
4426static PyObject*
4427DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4428{
4429 int err, max;
4430
4431 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4432 return NULL;
4433 CHECK_ENV_NOT_CLOSED(self);
4434
4435 MYDB_BEGIN_ALLOW_THREADS;
4436 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4437 MYDB_END_ALLOW_THREADS;
4438 RETURN_IF_ERR();
4439 RETURN_NONE();
4440}
4441
4442
4443static PyObject*
4444DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4445{
4446 int err, max;
4447
4448 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4449 return NULL;
4450 CHECK_ENV_NOT_CLOSED(self);
4451
4452 MYDB_BEGIN_ALLOW_THREADS;
4453 err = self->db_env->set_lk_max_objects(self->db_env, max);
4454 MYDB_END_ALLOW_THREADS;
4455 RETURN_IF_ERR();
4456 RETURN_NONE();
4457}
4458
4459
4460static PyObject*
4461DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4462{
4463 int err, mp_mmapsize;
4464
4465 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4466 return NULL;
4467 CHECK_ENV_NOT_CLOSED(self);
4468
4469 MYDB_BEGIN_ALLOW_THREADS;
4470 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4471 MYDB_END_ALLOW_THREADS;
4472 RETURN_IF_ERR();
4473 RETURN_NONE();
4474}
4475
4476
4477static PyObject*
4478DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4479{
4480 int err;
4481 char *dir;
4482
4483 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4484 return NULL;
4485 CHECK_ENV_NOT_CLOSED(self);
4486
4487 MYDB_BEGIN_ALLOW_THREADS;
4488 err = self->db_env->set_tmp_dir(self->db_env, dir);
4489 MYDB_END_ALLOW_THREADS;
4490 RETURN_IF_ERR();
4491 RETURN_NONE();
4492}
4493
4494
4495static PyObject*
4496DBEnv_txn_recover(DBEnvObject* self)
4497{
4498 int flags = DB_FIRST;
4499 int err, i;
4500 PyObject *list, *tuple, *gid;
4501 DBTxnObject *txn;
4502#define PREPLIST_LEN 16
4503 DB_PREPLIST preplist[PREPLIST_LEN];
4504 long retp;
4505
4506 CHECK_ENV_NOT_CLOSED(self);
4507
4508 list=PyList_New(0);
4509 if (!list)
4510 return NULL;
4511 while (!0) {
4512 MYDB_BEGIN_ALLOW_THREADS
4513 err=self->db_env->txn_recover(self->db_env,
4514 preplist, PREPLIST_LEN, &retp, flags);
4515#undef PREPLIST_LEN
4516 MYDB_END_ALLOW_THREADS
4517 if (err) {
4518 Py_DECREF(list);
4519 RETURN_IF_ERR();
4520 }
4521 if (!retp) break;
4522 flags=DB_NEXT; /* Prepare for next loop pass */
4523 for (i=0; i<retp; i++) {
4524 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
4525 DB_XIDDATASIZE);
4526 if (!gid) {
4527 Py_DECREF(list);
4528 return NULL;
4529 }
4530 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4531 if (!txn) {
4532 Py_DECREF(list);
4533 Py_DECREF(gid);
4534 return NULL;
4535 }
4536 txn->flag_prepare=1; /* Recover state */
4537 tuple=PyTuple_New(2);
4538 if (!tuple) {
4539 Py_DECREF(list);
4540 Py_DECREF(gid);
4541 Py_DECREF(txn);
4542 return NULL;
4543 }
4544 if (PyTuple_SetItem(tuple, 0, gid)) {
4545 Py_DECREF(list);
4546 Py_DECREF(gid);
4547 Py_DECREF(txn);
4548 Py_DECREF(tuple);
4549 return NULL;
4550 }
4551 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4552 Py_DECREF(list);
4553 Py_DECREF(txn);
4554 Py_DECREF(tuple); /* This delete the "gid" also */
4555 return NULL;
4556 }
4557 if (PyList_Append(list, tuple)) {
4558 Py_DECREF(list);
4559 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4560 return NULL;
4561 }
4562 Py_DECREF(tuple);
4563 }
4564 }
4565 return list;
4566}
4567
4568static PyObject*
4569DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4570{
4571 int flags = 0;
4572 PyObject* txnobj = NULL;
4573 DB_TXN *txn = NULL;
4574 static char* kwnames[] = { "parent", "flags", NULL };
4575
4576 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4577 &txnobj, &flags))
4578 return NULL;
4579
4580 if (!checkTxnObj(txnobj, &txn))
4581 return NULL;
4582 CHECK_ENV_NOT_CLOSED(self);
4583
4584 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
4585}
4586
4587
4588static PyObject*
4589DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4590{
4591 int err, kbyte=0, min=0, flags=0;
4592
4593 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4594 return NULL;
4595 CHECK_ENV_NOT_CLOSED(self);
4596
4597 MYDB_BEGIN_ALLOW_THREADS;
4598 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4599 MYDB_END_ALLOW_THREADS;
4600 RETURN_IF_ERR();
4601 RETURN_NONE();
4602}
4603
4604
4605static PyObject*
4606DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4607{
4608 int err, max;
4609
4610 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4611 return NULL;
4612 CHECK_ENV_NOT_CLOSED(self);
4613
4614 err = self->db_env->set_tx_max(self->db_env, max);
4615 RETURN_IF_ERR();
4616 RETURN_NONE();
4617}
4618
4619
4620static PyObject*
4621DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4622{
4623 int err;
4624 long stamp;
4625 time_t timestamp;
4626
4627 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
4628 return NULL;
4629 CHECK_ENV_NOT_CLOSED(self);
4630 timestamp = (time_t)stamp;
4631 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
4632 RETURN_IF_ERR();
4633 RETURN_NONE();
4634}
4635
4636
4637static PyObject*
4638DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4639{
4640 int err, atype, flags=0;
4641 int aborted = 0;
4642
4643 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4644 return NULL;
4645 CHECK_ENV_NOT_CLOSED(self);
4646
4647 MYDB_BEGIN_ALLOW_THREADS;
4648 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4649 MYDB_END_ALLOW_THREADS;
4650 RETURN_IF_ERR();
4651 return NUMBER_FromLong(aborted);
4652}
4653
4654
4655static PyObject*
4656DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4657{
4658 int flags=0;
4659 int locker, lock_mode;
4660 DBT obj;
4661 PyObject* objobj;
4662
4663 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4664 return NULL;
4665
4666
4667 if (!make_dbt(objobj, &obj))
4668 return NULL;
4669
4670 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4671}
4672
4673
4674static PyObject*
4675DBEnv_lock_id(DBEnvObject* self)
4676{
4677 int err;
4678 u_int32_t theID;
4679
4680 CHECK_ENV_NOT_CLOSED(self);
4681 MYDB_BEGIN_ALLOW_THREADS;
4682 err = self->db_env->lock_id(self->db_env, &theID);
4683 MYDB_END_ALLOW_THREADS;
4684 RETURN_IF_ERR();
4685
4686 return NUMBER_FromLong((long)theID);
4687}
4688
4689static PyObject*
4690DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4691{
4692 int err;
4693 u_int32_t theID;
4694
4695 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4696 return NULL;
4697
4698 CHECK_ENV_NOT_CLOSED(self);
4699 MYDB_BEGIN_ALLOW_THREADS;
4700 err = self->db_env->lock_id_free(self->db_env, theID);
4701 MYDB_END_ALLOW_THREADS;
4702 RETURN_IF_ERR();
4703 RETURN_NONE();
4704}
4705
4706static PyObject*
4707DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4708{
4709 int err;
4710 DBLockObject* dblockobj;
4711
4712 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4713 return NULL;
4714
4715 CHECK_ENV_NOT_CLOSED(self);
4716 MYDB_BEGIN_ALLOW_THREADS;
4717 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4718 MYDB_END_ALLOW_THREADS;
4719 RETURN_IF_ERR();
4720 RETURN_NONE();
4721}
4722
4723#if (DBVER >= 44)
4724static PyObject*
4725DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4726{
4727 int err;
4728 char *file;
4729 u_int32_t flags = 0;
4730 static char* kwnames[] = { "file", "flags", NULL};
4731
4732 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4733 &file, &flags))
4734 return NULL;
4735 CHECK_ENV_NOT_CLOSED(self);
4736
4737 MYDB_BEGIN_ALLOW_THREADS;
4738 err = self->db_env->lsn_reset(self->db_env, file, flags);
4739 MYDB_END_ALLOW_THREADS;
4740 RETURN_IF_ERR();
4741 RETURN_NONE();
4742}
4743#endif /* DBVER >= 4.4 */
4744
4745static PyObject*
4746DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4747{
4748 int err;
4749 DB_LOG_STAT* statp = NULL;
4750 PyObject* d = NULL;
4751 u_int32_t flags = 0;
4752
4753 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4754 return NULL;
4755 CHECK_ENV_NOT_CLOSED(self);
4756
4757 MYDB_BEGIN_ALLOW_THREADS;
4758 err = self->db_env->log_stat(self->db_env, &statp, flags);
4759 MYDB_END_ALLOW_THREADS;
4760 RETURN_IF_ERR();
4761
4762 /* Turn the stat structure into a dictionary */
4763 d = PyDict_New();
4764 if (d == NULL) {
4765 if (statp)
4766 free(statp);
4767 return NULL;
4768 }
4769
4770#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4771
4772 MAKE_ENTRY(magic);
4773 MAKE_ENTRY(version);
4774 MAKE_ENTRY(mode);
4775 MAKE_ENTRY(lg_bsize);
4776#if (DBVER >= 44)
4777 MAKE_ENTRY(lg_size);
4778 MAKE_ENTRY(record);
4779#endif
4780#if (DBVER < 41)
4781 MAKE_ENTRY(lg_max);
4782#endif
4783 MAKE_ENTRY(w_mbytes);
4784 MAKE_ENTRY(w_bytes);
4785 MAKE_ENTRY(wc_mbytes);
4786 MAKE_ENTRY(wc_bytes);
4787 MAKE_ENTRY(wcount);
4788 MAKE_ENTRY(wcount_fill);
4789#if (DBVER >= 44)
4790 MAKE_ENTRY(rcount);
4791#endif
4792 MAKE_ENTRY(scount);
4793 MAKE_ENTRY(cur_file);
4794 MAKE_ENTRY(cur_offset);
4795 MAKE_ENTRY(disk_file);
4796 MAKE_ENTRY(disk_offset);
4797 MAKE_ENTRY(maxcommitperflush);
4798 MAKE_ENTRY(mincommitperflush);
4799 MAKE_ENTRY(regsize);
4800 MAKE_ENTRY(region_wait);
4801 MAKE_ENTRY(region_nowait);
4802
4803#undef MAKE_ENTRY
4804 free(statp);
4805 return d;
4806} /* DBEnv_log_stat */
4807
4808
4809static PyObject*
4810DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4811{
4812 int err;
4813 DB_LOCK_STAT* sp;
4814 PyObject* d = NULL;
4815 u_int32_t flags = 0;
4816
4817 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4818 return NULL;
4819 CHECK_ENV_NOT_CLOSED(self);
4820
4821 MYDB_BEGIN_ALLOW_THREADS;
4822 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4823 MYDB_END_ALLOW_THREADS;
4824 RETURN_IF_ERR();
4825
4826 /* Turn the stat structure into a dictionary */
4827 d = PyDict_New();
4828 if (d == NULL) {
4829 free(sp);
4830 return NULL;
4831 }
4832
4833#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4834
4835#if (DBVER < 41)
4836 MAKE_ENTRY(lastid);
4837#endif
4838#if (DBVER >=41)
4839 MAKE_ENTRY(id);
4840 MAKE_ENTRY(cur_maxid);
4841#endif
4842 MAKE_ENTRY(nmodes);
4843 MAKE_ENTRY(maxlocks);
4844 MAKE_ENTRY(maxlockers);
4845 MAKE_ENTRY(maxobjects);
4846 MAKE_ENTRY(nlocks);
4847 MAKE_ENTRY(maxnlocks);
4848 MAKE_ENTRY(nlockers);
4849 MAKE_ENTRY(maxnlockers);
4850 MAKE_ENTRY(nobjects);
4851 MAKE_ENTRY(maxnobjects);
4852 MAKE_ENTRY(nrequests);
4853 MAKE_ENTRY(nreleases);
4854#if (DBVER >= 44)
4855 MAKE_ENTRY(nupgrade);
4856 MAKE_ENTRY(ndowngrade);
4857#endif
4858#if (DBVER < 44)
4859 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
4860 MAKE_ENTRY(nconflicts);
4861#else
4862 MAKE_ENTRY(lock_nowait);
4863 MAKE_ENTRY(lock_wait);
4864#endif
4865 MAKE_ENTRY(ndeadlocks);
4866#if (DBVER >= 41)
4867 MAKE_ENTRY(locktimeout);
4868 MAKE_ENTRY(txntimeout);
4869#endif
4870 MAKE_ENTRY(nlocktimeouts);
4871 MAKE_ENTRY(ntxntimeouts);
4872#if (DBVER >= 46)
4873 MAKE_ENTRY(objs_wait);
4874 MAKE_ENTRY(objs_nowait);
4875 MAKE_ENTRY(lockers_wait);
4876 MAKE_ENTRY(lockers_nowait);
4877#if (DBVER >= 47)
4878 MAKE_ENTRY(lock_wait);
4879 MAKE_ENTRY(lock_nowait);
4880#else
4881 MAKE_ENTRY(locks_wait);
4882 MAKE_ENTRY(locks_nowait);
4883#endif
4884 MAKE_ENTRY(hash_len);
4885#endif
4886 MAKE_ENTRY(regsize);
4887 MAKE_ENTRY(region_wait);
4888 MAKE_ENTRY(region_nowait);
4889
4890#undef MAKE_ENTRY
4891 free(sp);
4892 return d;
4893}
4894
4895static PyObject*
4896DBEnv_log_flush(DBEnvObject* self)
4897{
4898 int err;
4899
4900 CHECK_ENV_NOT_CLOSED(self);
4901
4902 MYDB_BEGIN_ALLOW_THREADS
4903 err = self->db_env->log_flush(self->db_env, NULL);
4904 MYDB_END_ALLOW_THREADS
4905
4906 RETURN_IF_ERR();
4907 RETURN_NONE();
4908}
4909
4910static PyObject*
4911DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4912{
4913 int flags=0;
4914 int err;
4915 char **log_list = NULL;
4916 PyObject* list;
4917 PyObject* item = NULL;
4918
4919 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4920 return NULL;
4921
4922 CHECK_ENV_NOT_CLOSED(self);
4923 MYDB_BEGIN_ALLOW_THREADS;
4924 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4925 MYDB_END_ALLOW_THREADS;
4926 RETURN_IF_ERR();
4927
4928 list = PyList_New(0);
4929 if (list == NULL) {
4930 if (log_list)
4931 free(log_list);
4932 return NULL;
4933 }
4934
4935 if (log_list) {
4936 char **log_list_start;
4937 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4938 item = PyBytes_FromString (*log_list);
4939 if (item == NULL) {
4940 Py_DECREF(list);
4941 list = NULL;
4942 break;
4943 }
4944 if (PyList_Append(list, item)) {
4945 Py_DECREF(list);
4946 list = NULL;
4947 Py_DECREF(item);
4948 break;
4949 }
4950 Py_DECREF(item);
4951 }
4952 free(log_list_start);
4953 }
4954 return list;
4955}
4956
4957
4958static PyObject*
4959DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4960{
4961 int err;
4962 DB_TXN_STAT* sp;
4963 PyObject* d = NULL;
4964 u_int32_t flags=0;
4965
4966 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4967 return NULL;
4968 CHECK_ENV_NOT_CLOSED(self);
4969
4970 MYDB_BEGIN_ALLOW_THREADS;
4971 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4972 MYDB_END_ALLOW_THREADS;
4973 RETURN_IF_ERR();
4974
4975 /* Turn the stat structure into a dictionary */
4976 d = PyDict_New();
4977 if (d == NULL) {
4978 free(sp);
4979 return NULL;
4980 }
4981
4982#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4983#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4984#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
4985
4986 MAKE_DB_LSN_ENTRY(last_ckp);
4987 MAKE_TIME_T_ENTRY(time_ckp);
4988 MAKE_ENTRY(last_txnid);
4989 MAKE_ENTRY(maxtxns);
4990 MAKE_ENTRY(nactive);
4991 MAKE_ENTRY(maxnactive);
4992#if (DBVER >= 45)
4993 MAKE_ENTRY(nsnapshot);
4994 MAKE_ENTRY(maxnsnapshot);
4995#endif
4996 MAKE_ENTRY(nbegins);
4997 MAKE_ENTRY(naborts);
4998 MAKE_ENTRY(ncommits);
4999 MAKE_ENTRY(nrestores);
5000 MAKE_ENTRY(regsize);
5001 MAKE_ENTRY(region_wait);
5002 MAKE_ENTRY(region_nowait);
5003
5004#undef MAKE_DB_LSN_ENTRY
5005#undef MAKE_ENTRY
5006#undef MAKE_TIME_T_ENTRY
5007 free(sp);
5008 return d;
5009}
5010
5011
5012static PyObject*
5013DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
5014{
5015 int flags=0;
5016 int oldValue=0;
5017
5018 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
5019 return NULL;
5020 CHECK_ENV_NOT_CLOSED(self);
5021
5022 if (self->moduleFlags.getReturnsNone)
5023 ++oldValue;
5024 if (self->moduleFlags.cursorSetReturnsNone)
5025 ++oldValue;
5026 self->moduleFlags.getReturnsNone = (flags >= 1);
5027 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
5028 return NUMBER_FromLong(oldValue);
5029}
5030
5031static PyObject*
5032DBEnv_get_private(DBEnvObject* self)
5033{
5034 /* We can give out the private field even if dbenv is closed */
5035 Py_INCREF(self->private_obj);
5036 return self->private_obj;
5037}
5038
5039static PyObject*
5040DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
5041{
5042 /* We can set the private field even if dbenv is closed */
5043 Py_DECREF(self->private_obj);
5044 Py_INCREF(private_obj);
5045 self->private_obj = private_obj;
5046 RETURN_NONE();
5047}
5048
5049
5050static PyObject*
5051DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5052{
5053 int err;
5054 char *host;
5055 long cl_timeout=0, sv_timeout=0;
5056
5057 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
5058
5059 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
5060 &host, &cl_timeout, &sv_timeout))
5061 return NULL;
5062 CHECK_ENV_NOT_CLOSED(self);
5063
5064 MYDB_BEGIN_ALLOW_THREADS;
5065 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
5066 sv_timeout, 0);
5067 MYDB_END_ALLOW_THREADS;
5068 RETURN_IF_ERR();
5069 RETURN_NONE();
5070}
5071
5072static PyObject*
5073DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
5074{
5075 int err;
5076 int which, onoff;
5077
5078 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
5079 return NULL;
5080 }
5081 CHECK_ENV_NOT_CLOSED(self);
5082 MYDB_BEGIN_ALLOW_THREADS;
5083 err = self->db_env->set_verbose(self->db_env, which, onoff);
5084 MYDB_END_ALLOW_THREADS;
5085 RETURN_IF_ERR();
5086 RETURN_NONE();
5087}
5088
5089#if (DBVER >= 42)
5090static PyObject*
5091DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
5092{
5093 int err;
5094 int which;
5095 int verbose;
5096
5097 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
5098 return NULL;
5099 }
5100 CHECK_ENV_NOT_CLOSED(self);
5101 MYDB_BEGIN_ALLOW_THREADS;
5102 err = self->db_env->get_verbose(self->db_env, which, &verbose);
5103 MYDB_END_ALLOW_THREADS;
5104 RETURN_IF_ERR();
5105 return PyBool_FromLong(verbose);
5106}
5107#endif
5108
5109#if (DBVER >= 45)
5110static void
5111_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
5112{
5113 DBEnvObject *dbenv;
5114 PyObject* callback;
5115 PyObject* args;
5116 PyObject* result = NULL;
5117
5118 MYDB_BEGIN_BLOCK_THREADS;
5119 dbenv = (DBEnvObject *)db_env->app_private;
5120 callback = dbenv->event_notifyCallback;
5121 if (callback) {
5122 if (event == DB_EVENT_REP_NEWMASTER) {
5123 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
5124 } else {
5125 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5126 }
5127 if (args) {
5128 result = PyEval_CallObject(callback, args);
5129 }
5130 if ((!args) || (!result)) {
5131 PyErr_Print();
5132 }
5133 Py_XDECREF(args);
5134 Py_XDECREF(result);
5135 }
5136 MYDB_END_BLOCK_THREADS;
5137}
5138#endif
5139
5140#if (DBVER >= 45)
5141static PyObject*
5142DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
5143{
5144 int err;
5145
5146 CHECK_ENV_NOT_CLOSED(self);
5147
5148 if (!PyCallable_Check(notifyFunc)) {
5149 makeTypeError("Callable", notifyFunc);
5150 return NULL;
5151 }
5152
5153 Py_XDECREF(self->event_notifyCallback);
5154 Py_INCREF(notifyFunc);
5155 self->event_notifyCallback = notifyFunc;
5156
5157 /* This is to workaround a problem with un-initialized threads (see
5158 comment in DB_associate) */
5159#ifdef WITH_THREAD
5160 PyEval_InitThreads();
5161#endif
5162
5163 MYDB_BEGIN_ALLOW_THREADS;
5164 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5165 MYDB_END_ALLOW_THREADS;
5166
5167 if (err) {
5168 Py_DECREF(notifyFunc);
5169 self->event_notifyCallback = NULL;
5170 }
5171
5172 RETURN_IF_ERR();
5173 RETURN_NONE();
5174}
5175#endif
5176
5177
5178/* --------------------------------------------------------------------- */
5179/* REPLICATION METHODS: Base Replication */
5180
5181
5182static PyObject*
5183DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
5184{
5185 int err;
5186 PyObject *control_py, *rec_py;
5187 DBT control, rec;
5188 int envid;
5189#if (DBVER >= 42)
5190 DB_LSN lsn;
5191#endif
5192
5193 if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
5194 &rec_py, &envid))
5195 return NULL;
5196 CHECK_ENV_NOT_CLOSED(self);
5197
5198 if (!make_dbt(control_py, &control))
5199 return NULL;
5200 if (!make_dbt(rec_py, &rec))
5201 return NULL;
5202
5203 MYDB_BEGIN_ALLOW_THREADS;
5204#if (DBVER >= 46)
5205 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5206 envid, &lsn);
5207#else
5208#if (DBVER >= 42)
5209 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5210 &envid, &lsn);
5211#else
5212 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5213 &envid);
5214#endif
5215#endif
5216 MYDB_END_ALLOW_THREADS;
5217 switch (err) {
5218 case DB_REP_NEWMASTER :
5219 return Py_BuildValue("(iO)", envid, Py_None);
5220 break;
5221
5222 case DB_REP_DUPMASTER :
5223 case DB_REP_HOLDELECTION :
5224#if (DBVER >= 44)
5225 case DB_REP_IGNORE :
5226 case DB_REP_JOIN_FAILURE :
5227#endif
5228 return Py_BuildValue("(iO)", err, Py_None);
5229 break;
5230 case DB_REP_NEWSITE :
5231 {
5232 PyObject *tmp, *r;
5233
5234 if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
5235 return NULL;
5236 }
5237
5238 r = Py_BuildValue("(iO)", err, tmp);
5239 Py_DECREF(tmp);
5240 return r;
5241 break;
5242 }
5243#if (DBVER >= 42)
5244 case DB_REP_NOTPERM :
5245 case DB_REP_ISPERM :
5246 return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
5247 break;
5248#endif
5249 }
5250 RETURN_IF_ERR();
5251 return Py_BuildValue("(OO)", Py_None, Py_None);
5252}
5253
5254static int
5255_DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
5256 const DB_LSN *lsn, int envid, u_int32_t flags)
5257{
5258 DBEnvObject *dbenv;
5259 PyObject* rep_transport;
5260 PyObject* args;
5261 PyObject *a, *b;
5262 PyObject* result = NULL;
5263 int ret=0;
5264
5265 MYDB_BEGIN_BLOCK_THREADS;
5266 dbenv = (DBEnvObject *)db_env->app_private;
5267 rep_transport = dbenv->rep_transport;
5268
5269 /*
5270 ** The errors in 'a' or 'b' are detected in "Py_BuildValue".
5271 */
5272 a = PyBytes_FromStringAndSize(control->data, control->size);
5273 b = PyBytes_FromStringAndSize(rec->data, rec->size);
5274
5275 args = Py_BuildValue(
5276#if (PY_VERSION_HEX >= 0x02040000)
5277 "(OOO(ll)iI)",
5278#else
5279 "(OOO(ll)ii)",
5280#endif
5281 dbenv,
5282 a, b,
5283 lsn->file, lsn->offset, envid, flags);
5284 if (args) {
5285 result = PyEval_CallObject(rep_transport, args);
5286 }
5287
5288 if ((!args) || (!result)) {
5289 PyErr_Print();
5290 ret = -1;
5291 }
5292 Py_XDECREF(a);
5293 Py_XDECREF(b);
5294 Py_XDECREF(args);
5295 Py_XDECREF(result);
5296 MYDB_END_BLOCK_THREADS;
5297 return ret;
5298}
5299
5300#if (DBVER <= 41)
5301static int
5302_DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec,
5303 int envid, u_int32_t flags)
5304{
5305 DB_LSN lsn;
5306
5307 lsn.file = -1; /* Dummy values */
5308 lsn.offset = -1;
5309 return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid,
5310 flags);
5311}
5312#endif
5313
5314static PyObject*
5315DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
5316{
5317 int err;
5318 int envid;
5319 PyObject *rep_transport;
5320
5321 if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
5322 return NULL;
5323 CHECK_ENV_NOT_CLOSED(self);
5324 if (!PyCallable_Check(rep_transport)) {
5325 makeTypeError("Callable", rep_transport);
5326 return NULL;
5327 }
5328
5329 MYDB_BEGIN_ALLOW_THREADS;
5330#if (DBVER >=45)
5331 err = self->db_env->rep_set_transport(self->db_env, envid,
5332 &_DBEnv_rep_transportCallback);
5333#else
5334#if (DBVER >= 42)
5335 err = self->db_env->set_rep_transport(self->db_env, envid,
5336 &_DBEnv_rep_transportCallback);
5337#else
5338 err = self->db_env->set_rep_transport(self->db_env, envid,
5339 &_DBEnv_rep_transportCallbackOLD);
5340#endif
5341#endif
5342 MYDB_END_ALLOW_THREADS;
5343 RETURN_IF_ERR();
5344
5345 Py_DECREF(self->rep_transport);
5346 Py_INCREF(rep_transport);
5347 self->rep_transport = rep_transport;
5348 RETURN_NONE();
5349}
5350
5351#if (DBVER >= 47)
5352static PyObject*
5353DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
5354{
5355 int err;
5356 unsigned int minimum, maximum;
5357
5358 if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
5359 return NULL;
5360 CHECK_ENV_NOT_CLOSED(self);
5361
5362 MYDB_BEGIN_ALLOW_THREADS;
5363 err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
5364 MYDB_END_ALLOW_THREADS;
5365 RETURN_IF_ERR();
5366 RETURN_NONE();
5367}
5368
5369static PyObject*
5370DBEnv_rep_get_request(DBEnvObject* self)
5371{
5372 int err;
5373 u_int32_t minimum, maximum;
5374
5375 CHECK_ENV_NOT_CLOSED(self);
5376 MYDB_BEGIN_ALLOW_THREADS;
5377 err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
5378 MYDB_END_ALLOW_THREADS;
5379 RETURN_IF_ERR();
5380#if (PY_VERSION_HEX >= 0x02040000)
5381 return Py_BuildValue("II", minimum, maximum);
5382#else
5383 return Py_BuildValue("ii", minimum, maximum);
5384#endif
5385}
5386#endif
5387
5388#if (DBVER >= 45)
5389static PyObject*
5390DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
5391{
5392 int err;
5393 int limit;
5394
5395 if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
5396 return NULL;
5397 CHECK_ENV_NOT_CLOSED(self);
5398
5399 MYDB_BEGIN_ALLOW_THREADS;
5400 err = self->db_env->rep_set_limit(self->db_env, 0, limit);
5401 MYDB_END_ALLOW_THREADS;
5402 RETURN_IF_ERR();
5403 RETURN_NONE();
5404}
5405
5406static PyObject*
5407DBEnv_rep_get_limit(DBEnvObject* self)
5408{
5409 int err;
5410 u_int32_t gbytes, bytes;
5411
5412 CHECK_ENV_NOT_CLOSED(self);
5413 MYDB_BEGIN_ALLOW_THREADS;
5414 err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
5415 MYDB_END_ALLOW_THREADS;
5416 RETURN_IF_ERR();
5417 return NUMBER_FromLong(bytes);
5418}
5419#endif
5420
5421#if (DBVER >= 44)
5422static PyObject*
5423DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
5424{
5425 int err;
5426 int which;
5427 int onoff;
5428
5429 if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
5430 return NULL;
5431 CHECK_ENV_NOT_CLOSED(self);
5432
5433 MYDB_BEGIN_ALLOW_THREADS;
5434 err = self->db_env->rep_set_config(self->db_env, which, onoff);
5435 MYDB_END_ALLOW_THREADS;
5436 RETURN_IF_ERR();
5437 RETURN_NONE();
5438}
5439
5440static PyObject*
5441DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
5442{
5443 int err;
5444 int which;
5445 int onoff;
5446
5447 if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
5448 return NULL;
5449 }
5450 CHECK_ENV_NOT_CLOSED(self);
5451 MYDB_BEGIN_ALLOW_THREADS;
5452 err = self->db_env->rep_get_config(self->db_env, which, &onoff);
5453 MYDB_END_ALLOW_THREADS;
5454 RETURN_IF_ERR();
5455 return PyBool_FromLong(onoff);
5456}
5457#endif
5458
5459#if (DBVER >= 46)
5460static PyObject*
5461DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
5462{
5463 int err;
5464 u_int32_t nsites, nvotes;
5465
5466 if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
5467 return NULL;
5468 }
5469 CHECK_ENV_NOT_CLOSED(self);
5470 MYDB_BEGIN_ALLOW_THREADS;
5471 err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0);
5472 MYDB_END_ALLOW_THREADS;
5473 RETURN_IF_ERR();
5474 RETURN_NONE();
5475}
5476#endif
5477
5478static PyObject*
5479DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5480{
5481 int err;
5482 PyObject *cdata_py = Py_None;
5483 DBT cdata;
5484 int flags;
5485 static char* kwnames[] = {"flags","cdata", NULL};
5486
5487 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5488 "i|O:rep_start", kwnames, &flags, &cdata_py))
5489 {
5490 return NULL;
5491 }
5492 CHECK_ENV_NOT_CLOSED(self);
5493
5494 if (!make_dbt(cdata_py, &cdata))
5495 return NULL;
5496
5497 MYDB_BEGIN_ALLOW_THREADS;
5498 err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
5499 flags);
5500 MYDB_END_ALLOW_THREADS;
5501 RETURN_IF_ERR();
5502 RETURN_NONE();
5503}
5504
5505#if (DBVER >= 44)
5506static PyObject*
5507DBEnv_rep_sync(DBEnvObject* self)
5508{
5509 int err;
5510
5511 CHECK_ENV_NOT_CLOSED(self);
5512 MYDB_BEGIN_ALLOW_THREADS;
5513 err = self->db_env->rep_sync(self->db_env, 0);
5514 MYDB_END_ALLOW_THREADS;
5515 RETURN_IF_ERR();
5516 RETURN_NONE();
5517}
5518#endif
5519
5520
5521#if (DBVER >= 45)
5522static PyObject*
5523DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5524{
5525 int err;
5526 int nsites;
5527
5528 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5529 return NULL;
5530 }
5531 CHECK_ENV_NOT_CLOSED(self);
5532 MYDB_BEGIN_ALLOW_THREADS;
5533 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5534 MYDB_END_ALLOW_THREADS;
5535 RETURN_IF_ERR();
5536 RETURN_NONE();
5537}
5538
5539static PyObject*
5540DBEnv_rep_get_nsites(DBEnvObject* self)
5541{
5542 int err;
5543#if (DBVER >= 47)
5544 u_int32_t nsites;
5545#else
5546 int nsites;
5547#endif
5548
5549 CHECK_ENV_NOT_CLOSED(self);
5550 MYDB_BEGIN_ALLOW_THREADS;
5551 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5552 MYDB_END_ALLOW_THREADS;
5553 RETURN_IF_ERR();
5554 return NUMBER_FromLong(nsites);
5555}
5556
5557static PyObject*
5558DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5559{
5560 int err;
5561 int priority;
5562
5563 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5564 return NULL;
5565 }
5566 CHECK_ENV_NOT_CLOSED(self);
5567 MYDB_BEGIN_ALLOW_THREADS;
5568 err = self->db_env->rep_set_priority(self->db_env, priority);
5569 MYDB_END_ALLOW_THREADS;
5570 RETURN_IF_ERR();
5571 RETURN_NONE();
5572}
5573
5574static PyObject*
5575DBEnv_rep_get_priority(DBEnvObject* self)
5576{
5577 int err;
5578#if (DBVER >= 47)
5579 u_int32_t priority;
5580#else
5581 int priority;
5582#endif
5583
5584 CHECK_ENV_NOT_CLOSED(self);
5585 MYDB_BEGIN_ALLOW_THREADS;
5586 err = self->db_env->rep_get_priority(self->db_env, &priority);
5587 MYDB_END_ALLOW_THREADS;
5588 RETURN_IF_ERR();
5589 return NUMBER_FromLong(priority);
5590}
5591
5592static PyObject*
5593DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5594{
5595 int err;
5596 int which, timeout;
5597
5598 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5599 return NULL;
5600 }
5601 CHECK_ENV_NOT_CLOSED(self);
5602 MYDB_BEGIN_ALLOW_THREADS;
5603 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5604 MYDB_END_ALLOW_THREADS;
5605 RETURN_IF_ERR();
5606 RETURN_NONE();
5607}
5608
5609static PyObject*
5610DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5611{
5612 int err;
5613 int which;
5614 u_int32_t timeout;
5615
5616 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5617 return NULL;
5618 }
5619 CHECK_ENV_NOT_CLOSED(self);
5620 MYDB_BEGIN_ALLOW_THREADS;
5621 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5622 MYDB_END_ALLOW_THREADS;
5623 RETURN_IF_ERR();
5624 return NUMBER_FromLong(timeout);
5625}
5626#endif
5627
5628/* --------------------------------------------------------------------- */
5629/* REPLICATION METHODS: Replication Manager */
5630
5631#if (DBVER >= 45)
5632static PyObject*
5633DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5634 kwargs)
5635{
5636 int err;
5637 int nthreads, flags;
5638 static char* kwnames[] = {"nthreads","flags", NULL};
5639
5640 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5641 "ii:repmgr_start", kwnames, &nthreads, &flags))
5642 {
5643 return NULL;
5644 }
5645 CHECK_ENV_NOT_CLOSED(self);
5646 MYDB_BEGIN_ALLOW_THREADS;
5647 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5648 MYDB_END_ALLOW_THREADS;
5649 RETURN_IF_ERR();
5650 RETURN_NONE();
5651}
5652
5653static PyObject*
5654DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5655 kwargs)
5656{
5657 int err;
5658 char *host;
5659 int port;
5660 int flags = 0;
5661 static char* kwnames[] = {"host", "port", "flags", NULL};
5662
5663 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5664 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5665 {
5666 return NULL;
5667 }
5668 CHECK_ENV_NOT_CLOSED(self);
5669 MYDB_BEGIN_ALLOW_THREADS;
5670 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5671 MYDB_END_ALLOW_THREADS;
5672 RETURN_IF_ERR();
5673 RETURN_NONE();
5674}
5675
5676static PyObject*
5677DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5678 kwargs)
5679{
5680 int err;
5681 char *host;
5682 int port;
5683 int flags = 0;
5684 int eidp;
5685 static char* kwnames[] = {"host", "port", "flags", NULL};
5686
5687 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5688 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5689 {
5690 return NULL;
5691 }
5692 CHECK_ENV_NOT_CLOSED(self);
5693 MYDB_BEGIN_ALLOW_THREADS;
5694 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5695 MYDB_END_ALLOW_THREADS;
5696 RETURN_IF_ERR();
5697 return NUMBER_FromLong(eidp);
5698}
5699
5700static PyObject*
5701DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5702{
5703 int err;
5704 int ack_policy;
5705
5706 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5707 {
5708 return NULL;
5709 }
5710 CHECK_ENV_NOT_CLOSED(self);
5711 MYDB_BEGIN_ALLOW_THREADS;
5712 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5713 MYDB_END_ALLOW_THREADS;
5714 RETURN_IF_ERR();
5715 RETURN_NONE();
5716}
5717
5718static PyObject*
5719DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
5720{
5721 int err;
5722 int ack_policy;
5723
5724 CHECK_ENV_NOT_CLOSED(self);
5725 MYDB_BEGIN_ALLOW_THREADS;
5726 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5727 MYDB_END_ALLOW_THREADS;
5728 RETURN_IF_ERR();
5729 return NUMBER_FromLong(ack_policy);
5730}
5731
5732static PyObject*
5733DBEnv_repmgr_site_list(DBEnvObject* self)
5734{
5735 int err;
5736 unsigned int countp;
5737 DB_REPMGR_SITE *listp;
5738 PyObject *stats, *key, *tuple;
5739
5740 CHECK_ENV_NOT_CLOSED(self);
5741 MYDB_BEGIN_ALLOW_THREADS;
5742 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5743 MYDB_END_ALLOW_THREADS;
5744 RETURN_IF_ERR();
5745
5746 stats=PyDict_New();
5747 if (stats == NULL) {
5748 free(listp);
5749 return NULL;
5750 }
5751
5752 for(;countp--;) {
5753 key=NUMBER_FromLong(listp[countp].eid);
5754 if(!key) {
5755 Py_DECREF(stats);
5756 free(listp);
5757 return NULL;
5758 }
5759#if (PY_VERSION_HEX >= 0x02040000)
5760 tuple=Py_BuildValue("(sII)", listp[countp].host,
5761 listp[countp].port, listp[countp].status);
5762#else
5763 tuple=Py_BuildValue("(sii)", listp[countp].host,
5764 listp[countp].port, listp[countp].status);
5765#endif
5766 if(!tuple) {
5767 Py_DECREF(key);
5768 Py_DECREF(stats);
5769 free(listp);
5770 return NULL;
5771 }
5772 if(PyDict_SetItem(stats, key, tuple)) {
5773 Py_DECREF(key);
5774 Py_DECREF(tuple);
5775 Py_DECREF(stats);
5776 free(listp);
5777 return NULL;
5778 }
5779 Py_DECREF(key);
5780 Py_DECREF(tuple);
5781 }
5782 free(listp);
5783 return stats;
5784}
5785#endif
5786
5787#if (DBVER >= 46)
5788static PyObject*
5789DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5790{
5791 int err;
5792 int flags=0;
5793 static char* kwnames[] = { "flags", NULL };
5794
5795 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5796 kwnames, &flags))
5797 {
5798 return NULL;
5799 }
5800 CHECK_ENV_NOT_CLOSED(self);
5801 MYDB_BEGIN_ALLOW_THREADS;
5802 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5803 MYDB_END_ALLOW_THREADS;
5804 RETURN_IF_ERR();
5805 RETURN_NONE();
5806}
5807
5808static PyObject*
5809DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5810{
5811 int err;
5812 int flags=0;
5813 DB_REPMGR_STAT *statp;
5814 PyObject *stats;
5815 static char* kwnames[] = { "flags", NULL };
5816
5817 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5818 kwnames, &flags))
5819 {
5820 return NULL;
5821 }
5822 CHECK_ENV_NOT_CLOSED(self);
5823 MYDB_BEGIN_ALLOW_THREADS;
5824 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5825 MYDB_END_ALLOW_THREADS;
5826 RETURN_IF_ERR();
5827
5828 stats=PyDict_New();
5829 if (stats == NULL) {
5830 free(statp);
5831 return NULL;
5832 }
5833
5834#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5835
5836 MAKE_ENTRY(perm_failed);
5837 MAKE_ENTRY(msgs_queued);
5838 MAKE_ENTRY(msgs_dropped);
5839 MAKE_ENTRY(connection_drop);
5840 MAKE_ENTRY(connect_fail);
5841
5842#undef MAKE_ENTRY
5843
5844 free(statp);
5845 return stats;
5846}
5847#endif
5848
5849
5850/* --------------------------------------------------------------------- */
5851/* DBTxn methods */
5852
5853
5854static void _close_transaction_cursors(DBTxnObject* txn)
5855{
5856 PyObject *dummy;
5857
5858 while(txn->children_cursors) {
5859 PyErr_Warn(PyExc_RuntimeWarning,
5860 "Must close cursors before resolving a transaction.");
5861 dummy=DBC_close_internal(txn->children_cursors);
5862 Py_XDECREF(dummy);
5863 }
5864}
5865
5866static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5867{
5868 DBObject *db;
5869#if (DBVER >= 43)
5870 DBSequenceObject *dbs;
5871#endif
5872
5873 while (txn->children_dbs) {
5874 db=txn->children_dbs;
5875 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5876 if (txn->parent_txn) {
5877 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5878 db->txn=txn->parent_txn;
5879 } else {
5880 /* The db is already linked to its environment,
5881 ** so nothing to do.
5882 */
5883 db->txn=NULL;
5884 }
5885 }
5886
5887#if (DBVER >= 43)
5888 while (txn->children_sequences) {
5889 dbs=txn->children_sequences;
5890 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5891 if (txn->parent_txn) {
5892 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5893 dbs->txn=txn->parent_txn;
5894 } else {
5895 /* The sequence is already linked to its
5896 ** parent db. Nothing to do.
5897 */
5898 dbs->txn=NULL;
5899 }
5900 }
5901#endif
5902}
5903
5904
5905static PyObject*
5906DBTxn_commit(DBTxnObject* self, PyObject* args)
5907{
5908 int flags=0, err;
5909 DB_TXN *txn;
5910
5911 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5912 return NULL;
5913
5914 _close_transaction_cursors(self);
5915
5916 if (!self->txn) {
5917 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
5918 "after txn_commit, txn_abort "
5919 "or txn_discard");
5920 if (t) {
5921 PyErr_SetObject(DBError, t);
5922 Py_DECREF(t);
5923 }
5924 return NULL;
5925 }
5926 self->flag_prepare=0;
5927 txn = self->txn;
5928 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
5929
5930 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5931
5932 MYDB_BEGIN_ALLOW_THREADS;
5933 err = txn->commit(txn, flags);
5934 MYDB_END_ALLOW_THREADS;
5935
5936 _promote_transaction_dbs_and_sequences(self);
5937
5938 RETURN_IF_ERR();
5939 RETURN_NONE();
5940}
5941
5942static PyObject*
5943DBTxn_prepare(DBTxnObject* self, PyObject* args)
5944{
5945 int err;
5946 char* gid=NULL;
5947 int gid_size=0;
5948
5949 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
5950 return NULL;
5951
5952 if (gid_size != DB_XIDDATASIZE) {
5953 PyErr_SetString(PyExc_TypeError,
5954 "gid must be DB_XIDDATASIZE bytes long");
5955 return NULL;
5956 }
5957
5958 if (!self->txn) {
5959 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
5960 "after txn_commit, txn_abort "
5961 "or txn_discard");
5962 if (t) {
5963 PyErr_SetObject(DBError, t);
5964 Py_DECREF(t);
5965 }
5966 return NULL;
5967 }
5968 self->flag_prepare=1; /* Prepare state */
5969 MYDB_BEGIN_ALLOW_THREADS;
5970 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
5971 MYDB_END_ALLOW_THREADS;
5972 RETURN_IF_ERR();
5973 RETURN_NONE();
5974}
5975
5976
5977static PyObject*
5978DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
5979{
5980 PyObject *dummy;
5981 int err=0;
5982 DB_TXN *txn;
5983
5984 if (!self->txn) {
5985 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
5986 "after txn_commit, txn_abort "
5987 "or txn_discard");
5988 if (t) {
5989 PyErr_SetObject(DBError, t);
5990 Py_DECREF(t);
5991 }
5992 return NULL;
5993 }
5994 txn = self->txn;
5995 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
5996
5997 _close_transaction_cursors(self);
5998#if (DBVER >= 43)
5999 while (self->children_sequences) {
6000 dummy=DBSequence_close_internal(self->children_sequences,0,0);
6001 Py_XDECREF(dummy);
6002 }
6003#endif
6004 while (self->children_dbs) {
6005 dummy=DB_close_internal(self->children_dbs, 0, 0);
6006 Py_XDECREF(dummy);
6007 }
6008
6009 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
6010
6011 MYDB_BEGIN_ALLOW_THREADS;
6012 if (discard) {
6013 assert(!self->flag_prepare);
6014 err = txn->discard(txn,0);
6015 } else {
6016 /*
6017 ** If the transaction is in the "prepare" or "recover" state,
6018 ** we better do not implicitly abort it.
6019 */
6020 if (!self->flag_prepare) {
6021 err = txn->abort(txn);
6022 }
6023 }
6024 MYDB_END_ALLOW_THREADS;
6025 RETURN_IF_ERR();
6026 RETURN_NONE();
6027}
6028
6029static PyObject*
6030DBTxn_abort(DBTxnObject* self)
6031{
6032 self->flag_prepare=0;
6033 _close_transaction_cursors(self);
6034
6035 return DBTxn_abort_discard_internal(self,0);
6036}
6037
6038static PyObject*
6039DBTxn_discard(DBTxnObject* self)
6040{
6041 self->flag_prepare=0;
6042 _close_transaction_cursors(self);
6043
6044 return DBTxn_abort_discard_internal(self,1);
6045}
6046
6047
6048static PyObject*
6049DBTxn_id(DBTxnObject* self)
6050{
6051 int id;
6052
6053 if (!self->txn) {
6054 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
6055 "after txn_commit, txn_abort "
6056 "or txn_discard");
6057 if (t) {
6058 PyErr_SetObject(DBError, t);
6059 Py_DECREF(t);
6060 }
6061 return NULL;
6062 }
6063 MYDB_BEGIN_ALLOW_THREADS;
6064 id = self->txn->id(self->txn);
6065 MYDB_END_ALLOW_THREADS;
6066 return NUMBER_FromLong(id);
6067}
6068
6069#if (DBVER >= 43)
6070/* --------------------------------------------------------------------- */
6071/* DBSequence methods */
6072
6073
6074static PyObject*
6075DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
6076{
6077 int err=0;
6078
6079 if (self->sequence!=NULL) {
6080 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
6081 if (self->txn) {
6082 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
6083 self->txn=NULL;
6084 }
6085
6086 /*
6087 ** "do_not_close" is used to dispose all related objects in the
6088 ** tree, without actually releasing the "root" object.
6089 ** This is done, for example, because function calls like
6090 ** "DBSequence.remove()" implicitly close the underlying handle. So
6091 ** the handle doesn't need to be closed, but related objects
6092 ** must be cleaned up.
6093 */
6094 if (!do_not_close) {
6095 MYDB_BEGIN_ALLOW_THREADS
6096 err = self->sequence->close(self->sequence, flags);
6097 MYDB_END_ALLOW_THREADS
6098 }
6099 self->sequence = NULL;
6100
6101 RETURN_IF_ERR();
6102 }
6103
6104 RETURN_NONE();
6105}
6106
6107static PyObject*
6108DBSequence_close(DBSequenceObject* self, PyObject* args)
6109{
6110 int flags=0;
6111 if (!PyArg_ParseTuple(args,"|i:close", &flags))
6112 return NULL;
6113
6114 return DBSequence_close_internal(self,flags,0);
6115}
6116
6117static PyObject*
6118DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6119{
6120 int err, flags = 0;
6121 int delta = 1;
6122 db_seq_t value;
6123 PyObject *txnobj = NULL;
6124 DB_TXN *txn = NULL;
6125 static char* kwnames[] = {"delta", "txn", "flags", NULL };
6126 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
6127 return NULL;
6128 CHECK_SEQUENCE_NOT_CLOSED(self)
6129
6130 if (!checkTxnObj(txnobj, &txn))
6131 return NULL;
6132
6133 MYDB_BEGIN_ALLOW_THREADS
6134 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
6135 MYDB_END_ALLOW_THREADS
6136
6137 RETURN_IF_ERR();
6138 return PyLong_FromLongLong(value);
6139}
6140
6141static PyObject*
6142DBSequence_get_dbp(DBSequenceObject* self)
6143{
6144 CHECK_SEQUENCE_NOT_CLOSED(self)
6145 Py_INCREF(self->mydb);
6146 return (PyObject* )self->mydb;
6147}
6148
6149static PyObject*
6150DBSequence_get_key(DBSequenceObject* self)
6151{
6152 int err;
6153 DBT key;
6154 PyObject *retval = NULL;
6155
6156 key.flags = DB_DBT_MALLOC;
6157 CHECK_SEQUENCE_NOT_CLOSED(self)
6158 MYDB_BEGIN_ALLOW_THREADS
6159 err = self->sequence->get_key(self->sequence, &key);
6160 MYDB_END_ALLOW_THREADS
6161
6162 if (!err)
6163 retval = Build_PyString(key.data, key.size);
6164
6165 FREE_DBT(key);
6166 RETURN_IF_ERR();
6167
6168 return retval;
6169}
6170
6171static PyObject*
6172DBSequence_init_value(DBSequenceObject* self, PyObject* args)
6173{
6174 int err;
6175 PY_LONG_LONG value;
6176 db_seq_t value2;
6177 if (!PyArg_ParseTuple(args,"L:init_value", &value))
6178 return NULL;
6179 CHECK_SEQUENCE_NOT_CLOSED(self)
6180
6181 value2=value; /* If truncation, compiler should show a warning */
6182 MYDB_BEGIN_ALLOW_THREADS
6183 err = self->sequence->initial_value(self->sequence, value2);
6184 MYDB_END_ALLOW_THREADS
6185
6186 RETURN_IF_ERR();
6187
6188 RETURN_NONE();
6189}
6190
6191static PyObject*
6192DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6193{
6194 int err, flags = 0;
6195 PyObject* keyobj;
6196 PyObject *txnobj = NULL;
6197 DB_TXN *txn = NULL;
6198 DBT key;
6199
6200 static char* kwnames[] = {"key", "txn", "flags", NULL };
6201 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
6202 return NULL;
6203
6204 if (!checkTxnObj(txnobj, &txn))
6205 return NULL;
6206
6207 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
6208 return NULL;
6209
6210 MYDB_BEGIN_ALLOW_THREADS
6211 err = self->sequence->open(self->sequence, txn, &key, flags);
6212 MYDB_END_ALLOW_THREADS
6213
6214 FREE_DBT(key);
6215 RETURN_IF_ERR();
6216
6217 if (txn) {
6218 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
6219 self->txn=(DBTxnObject *)txnobj;
6220 }
6221
6222 RETURN_NONE();
6223}
6224
6225static PyObject*
6226DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6227{
6228 PyObject *dummy;
6229 int err, flags = 0;
6230 PyObject *txnobj = NULL;
6231 DB_TXN *txn = NULL;
6232
6233 static char* kwnames[] = {"txn", "flags", NULL };
6234 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
6235 return NULL;
6236
6237 if (!checkTxnObj(txnobj, &txn))
6238 return NULL;
6239
6240 CHECK_SEQUENCE_NOT_CLOSED(self)
6241
6242 MYDB_BEGIN_ALLOW_THREADS
6243 err = self->sequence->remove(self->sequence, txn, flags);
6244 MYDB_END_ALLOW_THREADS
6245
6246 dummy=DBSequence_close_internal(self,flags,1);
6247 Py_XDECREF(dummy);
6248
6249 RETURN_IF_ERR();
6250 RETURN_NONE();
6251}
6252
6253static PyObject*
6254DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
6255{
6256 int err, size;
6257 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
6258 return NULL;
6259 CHECK_SEQUENCE_NOT_CLOSED(self)
6260
6261 MYDB_BEGIN_ALLOW_THREADS
6262 err = self->sequence->set_cachesize(self->sequence, size);
6263 MYDB_END_ALLOW_THREADS
6264
6265 RETURN_IF_ERR();
6266 RETURN_NONE();
6267}
6268
6269static PyObject*
6270DBSequence_get_cachesize(DBSequenceObject* self)
6271{
6272 int err, size;
6273
6274 CHECK_SEQUENCE_NOT_CLOSED(self)
6275
6276 MYDB_BEGIN_ALLOW_THREADS
6277 err = self->sequence->get_cachesize(self->sequence, &size);
6278 MYDB_END_ALLOW_THREADS
6279
6280 RETURN_IF_ERR();
6281 return NUMBER_FromLong(size);
6282}
6283
6284static PyObject*
6285DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
6286{
6287 int err, flags = 0;
6288 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
6289 return NULL;
6290 CHECK_SEQUENCE_NOT_CLOSED(self)
6291
6292 MYDB_BEGIN_ALLOW_THREADS
6293 err = self->sequence->set_flags(self->sequence, flags);
6294 MYDB_END_ALLOW_THREADS
6295
6296 RETURN_IF_ERR();
6297 RETURN_NONE();
6298}
6299
6300static PyObject*
6301DBSequence_get_flags(DBSequenceObject* self)
6302{
6303 unsigned int flags;
6304 int err;
6305
6306 CHECK_SEQUENCE_NOT_CLOSED(self)
6307
6308 MYDB_BEGIN_ALLOW_THREADS
6309 err = self->sequence->get_flags(self->sequence, &flags);
6310 MYDB_END_ALLOW_THREADS
6311
6312 RETURN_IF_ERR();
6313 return NUMBER_FromLong((int)flags);
6314}
6315
6316static PyObject*
6317DBSequence_set_range(DBSequenceObject* self, PyObject* args)
6318{
6319 int err;
6320 PY_LONG_LONG min, max;
6321 db_seq_t min2, max2;
6322 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
6323 return NULL;
6324 CHECK_SEQUENCE_NOT_CLOSED(self)
6325
6326 min2=min; /* If truncation, compiler should show a warning */
6327 max2=max;
6328 MYDB_BEGIN_ALLOW_THREADS
6329 err = self->sequence->set_range(self->sequence, min2, max2);
6330 MYDB_END_ALLOW_THREADS
6331
6332 RETURN_IF_ERR();
6333 RETURN_NONE();
6334}
6335
6336static PyObject*
6337DBSequence_get_range(DBSequenceObject* self)
6338{
6339 int err;
6340 PY_LONG_LONG min, max;
6341 db_seq_t min2, max2;
6342
6343 CHECK_SEQUENCE_NOT_CLOSED(self)
6344
6345 MYDB_BEGIN_ALLOW_THREADS
6346 err = self->sequence->get_range(self->sequence, &min2, &max2);
6347 MYDB_END_ALLOW_THREADS
6348
6349 RETURN_IF_ERR();
6350 min=min2; /* If truncation, compiler should show a warning */
6351 max=max2;
6352 return Py_BuildValue("(LL)", min, max);
6353}
6354
6355static PyObject*
6356DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6357{
6358 int err, flags = 0;
6359 DB_SEQUENCE_STAT* sp = NULL;
6360 PyObject* dict_stat;
6361 static char* kwnames[] = {"flags", NULL };
6362 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
6363 return NULL;
6364 CHECK_SEQUENCE_NOT_CLOSED(self);
6365
6366 MYDB_BEGIN_ALLOW_THREADS;
6367 err = self->sequence->stat(self->sequence, &sp, flags);
6368 MYDB_END_ALLOW_THREADS;
6369 RETURN_IF_ERR();
6370
6371 if ((dict_stat = PyDict_New()) == NULL) {
6372 free(sp);
6373 return NULL;
6374 }
6375
6376
6377#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
6378#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
6379
6380 MAKE_INT_ENTRY(wait);
6381 MAKE_INT_ENTRY(nowait);
6382 MAKE_LONG_LONG_ENTRY(current);
6383 MAKE_LONG_LONG_ENTRY(value);
6384 MAKE_LONG_LONG_ENTRY(last_value);
6385 MAKE_LONG_LONG_ENTRY(min);
6386 MAKE_LONG_LONG_ENTRY(max);
6387 MAKE_INT_ENTRY(cache_size);
6388 MAKE_INT_ENTRY(flags);
6389
6390#undef MAKE_INT_ENTRY
6391#undef MAKE_LONG_LONG_ENTRY
6392
6393 free(sp);
6394 return dict_stat;
6395}
6396#endif
6397
6398
6399/* --------------------------------------------------------------------- */
6400/* Method definition tables and type objects */
6401
6402static PyMethodDef DB_methods[] = {
6403 {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS},
6404 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
6405 {"close", (PyCFunction)DB_close, METH_VARARGS},
6406 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
6407 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
6408 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
6409 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
6410 {"fd", (PyCFunction)DB_fd, METH_NOARGS},
6411 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
6412 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
6413 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
6414 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS},
6415 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
6416 {"get_type", (PyCFunction)DB_get_type, METH_NOARGS},
6417 {"join", (PyCFunction)DB_join, METH_VARARGS},
6418 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
6419 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS},
6420 {"items", (PyCFunction)DB_items, METH_VARARGS},
6421 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6422 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6423 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6424 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6425 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6426 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
6427 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O},
6428 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
6429#if (DBVER >= 41)
6430 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6431#endif
6432 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6433 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6434 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6435 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6436 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6437 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6438 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6439 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6440 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
6441 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
6442 {"set_private", (PyCFunction)DB_set_private, METH_O},
6443 {"get_private", (PyCFunction)DB_get_private, METH_NOARGS},
6444 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
6445 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
6446 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
6447 {"type", (PyCFunction)DB_get_type, METH_NOARGS},
6448 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6449 {"values", (PyCFunction)DB_values, METH_VARARGS},
6450 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6451 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6452 {NULL, NULL} /* sentinel */
6453};
6454
6455
6456static PyMappingMethods DB_mapping = {
6457 DB_length, /*mp_length*/
6458 (binaryfunc)DB_subscript, /*mp_subscript*/
6459 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6460};
6461
6462
6463static PyMethodDef DBCursor_methods[] = {
6464 {"close", (PyCFunction)DBC_close, METH_NOARGS},
6465 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6466 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6467 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6468 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6469 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6470 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
6471 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
6472 {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS},
6473 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6474 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6475 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6476 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6477 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6478 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6479 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
6480 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
6481 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
6482 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6483 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6484 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6485 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6486 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6487 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6488 {NULL, NULL} /* sentinel */
6489};
6490
6491
6492static PyMethodDef DBEnv_methods[] = {
6493 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6494 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6495 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
6496#if (DBVER >= 41)
6497 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6498 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6499 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6500#endif
6501 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
6502 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
6503 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6504 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
6505 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
6506#if (DBVER >= 47)
6507 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
6508#endif
6509 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6510 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6511 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
6512#if (DBVER >= 42)
6513 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS},
6514#endif
6515 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
6516 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
6517#if (DBVER < 45)
6518 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
6519#endif
6520 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6521 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6522 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
6523 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6524 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6525 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6526 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6527 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6528 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
6529 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
6530 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6531 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
6532 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS},
6533 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
6534 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6535 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6536 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
6537 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS},
6538 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
6539#if (DBVER >= 44)
6540 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6541#endif
6542 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
6543 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS},
6544 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
6545 METH_VARARGS||METH_KEYWORDS},
6546 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6547#if (DBVER >= 42)
6548 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6549#endif
6550 {"set_private", (PyCFunction)DBEnv_set_private, METH_O},
6551 {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS},
6552 {"rep_start", (PyCFunction)DBEnv_rep_start,
6553 METH_VARARGS|METH_KEYWORDS},
6554 {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
6555 {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
6556 METH_VARARGS},
6557#if (DBVER >= 46)
6558 {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS},
6559#endif
6560#if (DBVER >= 44)
6561 {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS},
6562 {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS},
6563 {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS},
6564#endif
6565#if (DBVER >= 45)
6566 {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS},
6567 {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS},
6568#endif
6569#if (DBVER >= 47)
6570 {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS},
6571 {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS},
6572#endif
6573#if (DBVER >= 45)
6574 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
6575#endif
6576#if (DBVER >= 45)
6577 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
6578 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
6579 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
6580 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
6581 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6582 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6583#endif
6584#if (DBVER >= 45)
6585 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6586 METH_VARARGS|METH_KEYWORDS},
6587 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6588 METH_VARARGS|METH_KEYWORDS},
6589 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6590 METH_VARARGS|METH_KEYWORDS},
6591 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6592 METH_VARARGS},
6593 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
6594 METH_NOARGS},
6595 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
6596 METH_NOARGS},
6597#endif
6598#if (DBVER >= 46)
6599 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6600 METH_VARARGS|METH_KEYWORDS},
6601 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6602 METH_VARARGS|METH_KEYWORDS},
6603#endif
6604 {NULL, NULL} /* sentinel */
6605};
6606
6607
6608static PyMethodDef DBTxn_methods[] = {
6609 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6610 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
6611 {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS},
6612 {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS},
6613 {"id", (PyCFunction)DBTxn_id, METH_NOARGS},
6614 {NULL, NULL} /* sentinel */
6615};
6616
6617
6618#if (DBVER >= 43)
6619static PyMethodDef DBSequence_methods[] = {
6620 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6621 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
6622 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS},
6623 {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS},
6624 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6625 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6626 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6627 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
6628 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS},
6629 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
6630 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS},
6631 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
6632 {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS},
6633 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6634 {NULL, NULL} /* sentinel */
6635};
6636#endif
6637
6638
6639static PyObject*
6640DBEnv_db_home_get(DBEnvObject* self)
6641{
6642 const char *home = NULL;
6643
6644 CHECK_ENV_NOT_CLOSED(self);
6645
6646#if (DBVER >= 42)
6647 self->db_env->get_home(self->db_env, &home);
6648#else
6649 home=self->db_env->db_home;
6650#endif
6651
6652 if (home == NULL) {
6653 RETURN_NONE();
6654 }
6655 return PyBytes_FromString(home);
6656}
6657
6658static PyGetSetDef DBEnv_getsets[] = {
6659 {"db_home", (getter)DBEnv_db_home_get, NULL,},
6660 {NULL}
6661};
6662
6663
6664statichere PyTypeObject DB_Type = {
6665#if (PY_VERSION_HEX < 0x03000000)
6666 PyObject_HEAD_INIT(NULL)
6667 0, /*ob_size*/
6668#else
6669 PyVarObject_HEAD_INIT(NULL, 0)
6670#endif
6671 "DB", /*tp_name*/
6672 sizeof(DBObject), /*tp_basicsize*/
6673 0, /*tp_itemsize*/
6674 /* methods */
6675 (destructor)DB_dealloc, /*tp_dealloc*/
6676 0, /*tp_print*/
6677 0, /*tp_getattr*/
6678 0, /*tp_setattr*/
6679 0, /*tp_compare*/
6680 0, /*tp_repr*/
6681 0, /*tp_as_number*/
6682 0, /*tp_as_sequence*/
6683 &DB_mapping,/*tp_as_mapping*/
6684 0, /*tp_hash*/
6685 0, /* tp_call */
6686 0, /* tp_str */
6687 0, /* tp_getattro */
6688 0, /* tp_setattro */
6689 0, /* tp_as_buffer */
6690#if (PY_VERSION_HEX < 0x03000000)
6691 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6692#else
6693 Py_TPFLAGS_DEFAULT, /* tp_flags */
6694#endif
6695 0, /* tp_doc */
6696 0, /* tp_traverse */
6697 0, /* tp_clear */
6698 0, /* tp_richcompare */
6699 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
6700 0, /*tp_iter*/
6701 0, /*tp_iternext*/
6702 DB_methods, /*tp_methods*/
6703 0, /*tp_members*/
6704};
6705
6706
6707statichere PyTypeObject DBCursor_Type = {
6708#if (PY_VERSION_HEX < 0x03000000)
6709 PyObject_HEAD_INIT(NULL)
6710 0, /*ob_size*/
6711#else
6712 PyVarObject_HEAD_INIT(NULL, 0)
6713#endif
6714 "DBCursor", /*tp_name*/
6715 sizeof(DBCursorObject), /*tp_basicsize*/
6716 0, /*tp_itemsize*/
6717 /* methods */
6718 (destructor)DBCursor_dealloc,/*tp_dealloc*/
6719 0, /*tp_print*/
6720 0, /*tp_getattr*/
6721 0, /*tp_setattr*/
6722 0, /*tp_compare*/
6723 0, /*tp_repr*/
6724 0, /*tp_as_number*/
6725 0, /*tp_as_sequence*/
6726 0, /*tp_as_mapping*/
6727 0, /*tp_hash*/
6728 0, /*tp_call*/
6729 0, /*tp_str*/
6730 0, /*tp_getattro*/
6731 0, /*tp_setattro*/
6732 0, /*tp_as_buffer*/
6733#if (PY_VERSION_HEX < 0x03000000)
6734 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6735#else
6736 Py_TPFLAGS_DEFAULT, /* tp_flags */
6737#endif
6738 0, /* tp_doc */
6739 0, /* tp_traverse */
6740 0, /* tp_clear */
6741 0, /* tp_richcompare */
6742 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
6743 0, /*tp_iter*/
6744 0, /*tp_iternext*/
6745 DBCursor_methods, /*tp_methods*/
6746 0, /*tp_members*/
6747};
6748
6749
6750statichere PyTypeObject DBEnv_Type = {
6751#if (PY_VERSION_HEX < 0x03000000)
6752 PyObject_HEAD_INIT(NULL)
6753 0, /*ob_size*/
6754#else
6755 PyVarObject_HEAD_INIT(NULL, 0)
6756#endif
6757 "DBEnv", /*tp_name*/
6758 sizeof(DBEnvObject), /*tp_basicsize*/
6759 0, /*tp_itemsize*/
6760 /* methods */
6761 (destructor)DBEnv_dealloc, /*tp_dealloc*/
6762 0, /*tp_print*/
6763 0, /*tp_getattr*/
6764 0, /*tp_setattr*/
6765 0, /*tp_compare*/
6766 0, /*tp_repr*/
6767 0, /*tp_as_number*/
6768 0, /*tp_as_sequence*/
6769 0, /*tp_as_mapping*/
6770 0, /*tp_hash*/
6771 0, /* tp_call */
6772 0, /* tp_str */
6773 0, /* tp_getattro */
6774 0, /* tp_setattro */
6775 0, /* tp_as_buffer */
6776#if (PY_VERSION_HEX < 0x03000000)
6777 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6778#else
6779 Py_TPFLAGS_DEFAULT, /* tp_flags */
6780#endif
6781 0, /* tp_doc */
6782 0, /* tp_traverse */
6783 0, /* tp_clear */
6784 0, /* tp_richcompare */
6785 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
6786 0, /* tp_iter */
6787 0, /* tp_iternext */
6788 DBEnv_methods, /* tp_methods */
6789 0, /* tp_members */
6790 DBEnv_getsets, /* tp_getsets */
6791};
6792
6793statichere PyTypeObject DBTxn_Type = {
6794#if (PY_VERSION_HEX < 0x03000000)
6795 PyObject_HEAD_INIT(NULL)
6796 0, /*ob_size*/
6797#else
6798 PyVarObject_HEAD_INIT(NULL, 0)
6799#endif
6800 "DBTxn", /*tp_name*/
6801 sizeof(DBTxnObject), /*tp_basicsize*/
6802 0, /*tp_itemsize*/
6803 /* methods */
6804 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6805 0, /*tp_print*/
6806 0, /*tp_getattr*/
6807 0, /*tp_setattr*/
6808 0, /*tp_compare*/
6809 0, /*tp_repr*/
6810 0, /*tp_as_number*/
6811 0, /*tp_as_sequence*/
6812 0, /*tp_as_mapping*/
6813 0, /*tp_hash*/
6814 0, /* tp_call */
6815 0, /* tp_str */
6816 0, /* tp_getattro */
6817 0, /* tp_setattro */
6818 0, /* tp_as_buffer */
6819#if (PY_VERSION_HEX < 0x03000000)
6820 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6821#else
6822 Py_TPFLAGS_DEFAULT, /* tp_flags */
6823#endif
6824 0, /* tp_doc */
6825 0, /* tp_traverse */
6826 0, /* tp_clear */
6827 0, /* tp_richcompare */
6828 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
6829 0, /*tp_iter*/
6830 0, /*tp_iternext*/
6831 DBTxn_methods, /*tp_methods*/
6832 0, /*tp_members*/
6833};
6834
6835
6836statichere PyTypeObject DBLock_Type = {
6837#if (PY_VERSION_HEX < 0x03000000)
6838 PyObject_HEAD_INIT(NULL)
6839 0, /*ob_size*/
6840#else
6841 PyVarObject_HEAD_INIT(NULL, 0)
6842#endif
6843 "DBLock", /*tp_name*/
6844 sizeof(DBLockObject), /*tp_basicsize*/
6845 0, /*tp_itemsize*/
6846 /* methods */
6847 (destructor)DBLock_dealloc, /*tp_dealloc*/
6848 0, /*tp_print*/
6849 0, /*tp_getattr*/
6850 0, /*tp_setattr*/
6851 0, /*tp_compare*/
6852 0, /*tp_repr*/
6853 0, /*tp_as_number*/
6854 0, /*tp_as_sequence*/
6855 0, /*tp_as_mapping*/
6856 0, /*tp_hash*/
6857 0, /* tp_call */
6858 0, /* tp_str */
6859 0, /* tp_getattro */
6860 0, /* tp_setattro */
6861 0, /* tp_as_buffer */
6862#if (PY_VERSION_HEX < 0x03000000)
6863 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6864#else
6865 Py_TPFLAGS_DEFAULT, /* tp_flags */
6866#endif
6867 0, /* tp_doc */
6868 0, /* tp_traverse */
6869 0, /* tp_clear */
6870 0, /* tp_richcompare */
6871 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
6872};
6873
6874#if (DBVER >= 43)
6875statichere PyTypeObject DBSequence_Type = {
6876#if (PY_VERSION_HEX < 0x03000000)
6877 PyObject_HEAD_INIT(NULL)
6878 0, /*ob_size*/
6879#else
6880 PyVarObject_HEAD_INIT(NULL, 0)
6881#endif
6882 "DBSequence", /*tp_name*/
6883 sizeof(DBSequenceObject), /*tp_basicsize*/
6884 0, /*tp_itemsize*/
6885 /* methods */
6886 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6887 0, /*tp_print*/
6888 0, /*tp_getattr*/
6889 0, /*tp_setattr*/
6890 0, /*tp_compare*/
6891 0, /*tp_repr*/
6892 0, /*tp_as_number*/
6893 0, /*tp_as_sequence*/
6894 0, /*tp_as_mapping*/
6895 0, /*tp_hash*/
6896 0, /* tp_call */
6897 0, /* tp_str */
6898 0, /* tp_getattro */
6899 0, /* tp_setattro */
6900 0, /* tp_as_buffer */
6901#if (PY_VERSION_HEX < 0x03000000)
6902 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6903#else
6904 Py_TPFLAGS_DEFAULT, /* tp_flags */
6905#endif
6906 0, /* tp_doc */
6907 0, /* tp_traverse */
6908 0, /* tp_clear */
6909 0, /* tp_richcompare */
6910 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
6911 0, /*tp_iter*/
6912 0, /*tp_iternext*/
6913 DBSequence_methods, /*tp_methods*/
6914 0, /*tp_members*/
6915};
6916#endif
6917
6918/* --------------------------------------------------------------------- */
6919/* Module-level functions */
6920
6921static PyObject*
6922DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6923{
6924 PyObject* dbenvobj = NULL;
6925 int flags = 0;
6926 static char* kwnames[] = { "dbEnv", "flags", NULL};
6927
6928 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6929 &dbenvobj, &flags))
6930 return NULL;
6931 if (dbenvobj == Py_None)
6932 dbenvobj = NULL;
6933 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6934 makeTypeError("DBEnv", dbenvobj);
6935 return NULL;
6936 }
6937
6938 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6939}
6940
6941
6942static PyObject*
6943DBEnv_construct(PyObject* self, PyObject* args)
6944{
6945 int flags = 0;
6946 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6947 return (PyObject* )newDBEnvObject(flags);
6948}
6949
6950#if (DBVER >= 43)
6951static PyObject*
6952DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6953{
6954 PyObject* dbobj;
6955 int flags = 0;
6956 static char* kwnames[] = { "db", "flags", NULL};
6957
6958 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6959 return NULL;
6960 if (!DBObject_Check(dbobj)) {
6961 makeTypeError("DB", dbobj);
6962 return NULL;
6963 }
6964 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6965}
6966#endif
6967
6968static char bsddb_version_doc[] =
6969"Returns a tuple of major, minor, and patch release numbers of the\n\
6970underlying DB library.";
6971
6972static PyObject*
6973bsddb_version(PyObject* self)
6974{
6975 int major, minor, patch;
6976
6977 db_version(&major, &minor, &patch);
6978 return Py_BuildValue("(iii)", major, minor, patch);
6979}
6980
6981
6982/* List of functions defined in the module */
6983static PyMethodDef bsddb_methods[] = {
6984 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6985 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
6986#if (DBVER >= 43)
6987 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
6988#endif
6989 {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc},
6990 {NULL, NULL} /* sentinel */
6991};
6992
6993
6994/* API structure */
6995static BSDDB_api bsddb_api;
6996
6997
6998/* --------------------------------------------------------------------- */
6999/* Module initialization */
7000
7001
7002/* Convenience routine to export an integer value.
7003 * Errors are silently ignored, for better or for worse...
7004 */
7005#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
7006
7007#define MODULE_NAME_MAX_LEN 11
7008static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
7009
7010#if (PY_VERSION_HEX >= 0x03000000)
7011static struct PyModuleDef bsddbmodule = {
7012 PyModuleDef_HEAD_INIT,
7013 _bsddbModuleName, /* Name of module */
7014 NULL, /* module documentation, may be NULL */
7015 -1, /* size of per-interpreter state of the module,
7016 or -1 if the module keeps state in global variables. */
7017 bsddb_methods,
7018 NULL, /* Reload */
7019 NULL, /* Traverse */
7020 NULL, /* Clear */
7021 NULL /* Free */
7022};
7023#endif
7024
7025
7026#if (PY_VERSION_HEX < 0x03000000)
7027DL_EXPORT(void) init_bsddb(void)
7028#else
7029PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */
7030#endif
7031{
7032 PyObject* m;
7033 PyObject* d;
7034 PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
7035 PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
7036 PyObject* cvsid_s = PyBytes_FromString( rcs_id );
7037 PyObject* py_api;
7038
7039 /* Initialize object types */
7040 if ((PyType_Ready(&DB_Type) < 0)
7041 || (PyType_Ready(&DBCursor_Type) < 0)
7042 || (PyType_Ready(&DBEnv_Type) < 0)
7043 || (PyType_Ready(&DBTxn_Type) < 0)
7044 || (PyType_Ready(&DBLock_Type) < 0)
7045#if (DBVER >= 43)
7046 || (PyType_Ready(&DBSequence_Type) < 0)
7047#endif
7048 ) {
7049#if (PY_VERSION_HEX < 0x03000000)
7050 return;
7051#else
7052 return NULL;
7053#endif
7054 }
7055
7056#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
7057 /* Save the current interpreter, so callbacks can do the right thing. */
7058 _db_interpreterState = PyThreadState_GET()->interp;
7059#endif
7060
7061 /* Create the module and add the functions */
7062#if (PY_VERSION_HEX < 0x03000000)
7063 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
7064#else
7065 m=PyModule_Create(&bsddbmodule);
7066#endif
7067 if (m == NULL) {
7068#if (PY_VERSION_HEX < 0x03000000)
7069 return;
7070#else
7071 return NULL;
7072#endif
7073 }
7074
7075 /* Add some symbolic constants to the module */
7076 d = PyModule_GetDict(m);
7077 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
7078 PyDict_SetItemString(d, "cvsid", cvsid_s);
7079 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
7080 Py_DECREF(pybsddb_version_s);
7081 pybsddb_version_s = NULL;
7082 Py_DECREF(cvsid_s);
7083 cvsid_s = NULL;
7084 Py_DECREF(db_version_s);
7085 db_version_s = NULL;
7086
7087 ADD_INT(d, DB_VERSION_MAJOR);
7088 ADD_INT(d, DB_VERSION_MINOR);
7089 ADD_INT(d, DB_VERSION_PATCH);
7090
7091 ADD_INT(d, DB_MAX_PAGES);
7092 ADD_INT(d, DB_MAX_RECORDS);
7093
7094#if (DBVER >= 42)
7095 ADD_INT(d, DB_RPCCLIENT);
7096#else
7097 ADD_INT(d, DB_CLIENT);
7098 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
7099 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
7100#endif
7101 ADD_INT(d, DB_XA_CREATE);
7102
7103 ADD_INT(d, DB_CREATE);
7104 ADD_INT(d, DB_NOMMAP);
7105 ADD_INT(d, DB_THREAD);
7106#if (DBVER >= 45)
7107 ADD_INT(d, DB_MULTIVERSION);
7108#endif
7109
7110 ADD_INT(d, DB_FORCE);
7111 ADD_INT(d, DB_INIT_CDB);
7112 ADD_INT(d, DB_INIT_LOCK);
7113 ADD_INT(d, DB_INIT_LOG);
7114 ADD_INT(d, DB_INIT_MPOOL);
7115 ADD_INT(d, DB_INIT_TXN);
7116 ADD_INT(d, DB_JOINENV);
7117
7118 ADD_INT(d, DB_XIDDATASIZE);
7119
7120 ADD_INT(d, DB_RECOVER);
7121 ADD_INT(d, DB_RECOVER_FATAL);
7122 ADD_INT(d, DB_TXN_NOSYNC);
7123 ADD_INT(d, DB_USE_ENVIRON);
7124 ADD_INT(d, DB_USE_ENVIRON_ROOT);
7125
7126 ADD_INT(d, DB_LOCKDOWN);
7127 ADD_INT(d, DB_PRIVATE);
7128 ADD_INT(d, DB_SYSTEM_MEM);
7129
7130 ADD_INT(d, DB_TXN_SYNC);
7131 ADD_INT(d, DB_TXN_NOWAIT);
7132
7133 ADD_INT(d, DB_EXCL);
7134 ADD_INT(d, DB_FCNTL_LOCKING);
7135 ADD_INT(d, DB_ODDFILESIZE);
7136 ADD_INT(d, DB_RDWRMASTER);
7137 ADD_INT(d, DB_RDONLY);
7138 ADD_INT(d, DB_TRUNCATE);
7139 ADD_INT(d, DB_EXTENT);
7140 ADD_INT(d, DB_CDB_ALLDB);
7141 ADD_INT(d, DB_VERIFY);
7142 ADD_INT(d, DB_UPGRADE);
7143
7144 ADD_INT(d, DB_AGGRESSIVE);
7145 ADD_INT(d, DB_NOORDERCHK);
7146 ADD_INT(d, DB_ORDERCHKONLY);
7147 ADD_INT(d, DB_PR_PAGE);
7148
7149 ADD_INT(d, DB_PR_RECOVERYTEST);
7150 ADD_INT(d, DB_SALVAGE);
7151
7152 ADD_INT(d, DB_LOCK_NORUN);
7153 ADD_INT(d, DB_LOCK_DEFAULT);
7154 ADD_INT(d, DB_LOCK_OLDEST);
7155 ADD_INT(d, DB_LOCK_RANDOM);
7156 ADD_INT(d, DB_LOCK_YOUNGEST);
7157 ADD_INT(d, DB_LOCK_MAXLOCKS);
7158 ADD_INT(d, DB_LOCK_MINLOCKS);
7159 ADD_INT(d, DB_LOCK_MINWRITE);
7160
7161 ADD_INT(d, DB_LOCK_EXPIRE);
7162#if (DBVER >= 43)
7163 ADD_INT(d, DB_LOCK_MAXWRITE);
7164#endif
7165
7166 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
7167
7168 ADD_INT(d, DB_LOCK_DUMP);
7169 ADD_INT(d, DB_LOCK_GET);
7170 ADD_INT(d, DB_LOCK_INHERIT);
7171 ADD_INT(d, DB_LOCK_PUT);
7172 ADD_INT(d, DB_LOCK_PUT_ALL);
7173 ADD_INT(d, DB_LOCK_PUT_OBJ);
7174
7175 ADD_INT(d, DB_LOCK_NG);
7176 ADD_INT(d, DB_LOCK_READ);
7177 ADD_INT(d, DB_LOCK_WRITE);
7178 ADD_INT(d, DB_LOCK_NOWAIT);
7179 ADD_INT(d, DB_LOCK_WAIT);
7180 ADD_INT(d, DB_LOCK_IWRITE);
7181 ADD_INT(d, DB_LOCK_IREAD);
7182 ADD_INT(d, DB_LOCK_IWR);
7183#if (DBVER < 44)
7184 ADD_INT(d, DB_LOCK_DIRTY);
7185#else
7186 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
7187#endif
7188 ADD_INT(d, DB_LOCK_WWRITE);
7189
7190 ADD_INT(d, DB_LOCK_RECORD);
7191 ADD_INT(d, DB_LOCK_UPGRADE);
7192 ADD_INT(d, DB_LOCK_SWITCH);
7193 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
7194
7195 ADD_INT(d, DB_LOCK_NOWAIT);
7196 ADD_INT(d, DB_LOCK_RECORD);
7197 ADD_INT(d, DB_LOCK_UPGRADE);
7198
7199 ADD_INT(d, DB_LSTAT_ABORTED);
7200#if (DBVER < 43)
7201 ADD_INT(d, DB_LSTAT_ERR);
7202#endif
7203 ADD_INT(d, DB_LSTAT_FREE);
7204 ADD_INT(d, DB_LSTAT_HELD);
7205
7206 ADD_INT(d, DB_LSTAT_PENDING);
7207 ADD_INT(d, DB_LSTAT_WAITING);
7208
7209 ADD_INT(d, DB_ARCH_ABS);
7210 ADD_INT(d, DB_ARCH_DATA);
7211 ADD_INT(d, DB_ARCH_LOG);
7212#if (DBVER >= 42)
7213 ADD_INT(d, DB_ARCH_REMOVE);
7214#endif
7215
7216 ADD_INT(d, DB_BTREE);
7217 ADD_INT(d, DB_HASH);
7218 ADD_INT(d, DB_RECNO);
7219 ADD_INT(d, DB_QUEUE);
7220 ADD_INT(d, DB_UNKNOWN);
7221
7222 ADD_INT(d, DB_DUP);
7223 ADD_INT(d, DB_DUPSORT);
7224 ADD_INT(d, DB_RECNUM);
7225 ADD_INT(d, DB_RENUMBER);
7226 ADD_INT(d, DB_REVSPLITOFF);
7227 ADD_INT(d, DB_SNAPSHOT);
7228
7229 ADD_INT(d, DB_JOIN_NOSORT);
7230
7231 ADD_INT(d, DB_AFTER);
7232 ADD_INT(d, DB_APPEND);
7233 ADD_INT(d, DB_BEFORE);
7234#if (DBVER < 45)
7235 ADD_INT(d, DB_CACHED_COUNTS);
7236#endif
7237
7238#if (DBVER >= 41)
7239 _addIntToDict(d, "DB_CHECKPOINT", 0);
7240#else
7241 ADD_INT(d, DB_CHECKPOINT);
7242 ADD_INT(d, DB_CURLSN);
7243#endif
7244#if (DBVER <= 41)
7245 ADD_INT(d, DB_COMMIT);
7246#endif
7247 ADD_INT(d, DB_CONSUME);
7248 ADD_INT(d, DB_CONSUME_WAIT);
7249 ADD_INT(d, DB_CURRENT);
7250 ADD_INT(d, DB_FAST_STAT);
7251 ADD_INT(d, DB_FIRST);
7252 ADD_INT(d, DB_FLUSH);
7253 ADD_INT(d, DB_GET_BOTH);
7254 ADD_INT(d, DB_GET_RECNO);
7255 ADD_INT(d, DB_JOIN_ITEM);
7256 ADD_INT(d, DB_KEYFIRST);
7257 ADD_INT(d, DB_KEYLAST);
7258 ADD_INT(d, DB_LAST);
7259 ADD_INT(d, DB_NEXT);
7260 ADD_INT(d, DB_NEXT_DUP);
7261 ADD_INT(d, DB_NEXT_NODUP);
7262 ADD_INT(d, DB_NODUPDATA);
7263 ADD_INT(d, DB_NOOVERWRITE);
7264 ADD_INT(d, DB_NOSYNC);
7265 ADD_INT(d, DB_POSITION);
7266 ADD_INT(d, DB_PREV);
7267 ADD_INT(d, DB_PREV_NODUP);
7268#if (DBVER < 45)
7269 ADD_INT(d, DB_RECORDCOUNT);
7270#endif
7271 ADD_INT(d, DB_SET);
7272 ADD_INT(d, DB_SET_RANGE);
7273 ADD_INT(d, DB_SET_RECNO);
7274 ADD_INT(d, DB_WRITECURSOR);
7275
7276 ADD_INT(d, DB_OPFLAGS_MASK);
7277 ADD_INT(d, DB_RMW);
7278 ADD_INT(d, DB_DIRTY_READ);
7279 ADD_INT(d, DB_MULTIPLE);
7280 ADD_INT(d, DB_MULTIPLE_KEY);
7281
7282#if (DBVER >= 44)
7283 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
7284 ADD_INT(d, DB_READ_COMMITTED);
7285#endif
7286
7287 ADD_INT(d, DB_DONOTINDEX);
7288
7289#if (DBVER >= 41)
7290 _addIntToDict(d, "DB_INCOMPLETE", 0);
7291#else
7292 ADD_INT(d, DB_INCOMPLETE);
7293#endif
7294 ADD_INT(d, DB_KEYEMPTY);
7295 ADD_INT(d, DB_KEYEXIST);
7296 ADD_INT(d, DB_LOCK_DEADLOCK);
7297 ADD_INT(d, DB_LOCK_NOTGRANTED);
7298 ADD_INT(d, DB_NOSERVER);
7299 ADD_INT(d, DB_NOSERVER_HOME);
7300 ADD_INT(d, DB_NOSERVER_ID);
7301 ADD_INT(d, DB_NOTFOUND);
7302 ADD_INT(d, DB_OLD_VERSION);
7303 ADD_INT(d, DB_RUNRECOVERY);
7304 ADD_INT(d, DB_VERIFY_BAD);
7305 ADD_INT(d, DB_PAGE_NOTFOUND);
7306 ADD_INT(d, DB_SECONDARY_BAD);
7307 ADD_INT(d, DB_STAT_CLEAR);
7308 ADD_INT(d, DB_REGION_INIT);
7309 ADD_INT(d, DB_NOLOCKING);
7310 ADD_INT(d, DB_YIELDCPU);
7311 ADD_INT(d, DB_PANIC_ENVIRONMENT);
7312 ADD_INT(d, DB_NOPANIC);
7313
7314#if (DBVER >= 41)
7315 ADD_INT(d, DB_OVERWRITE);
7316#endif
7317
7318#ifdef DB_REGISTER
7319 ADD_INT(d, DB_REGISTER);
7320#endif
7321
7322#if (DBVER >= 42)
7323 ADD_INT(d, DB_TIME_NOTGRANTED);
7324 ADD_INT(d, DB_TXN_NOT_DURABLE);
7325 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
7326 ADD_INT(d, DB_DIRECT_DB);
7327 ADD_INT(d, DB_INIT_REP);
7328 ADD_INT(d, DB_ENCRYPT);
7329 ADD_INT(d, DB_CHKSUM);
7330#endif
7331
7332#if (DBVER >= 42) && (DBVER < 47)
7333 ADD_INT(d, DB_LOG_AUTOREMOVE);
7334 ADD_INT(d, DB_DIRECT_LOG);
7335#endif
7336
7337#if (DBVER >= 47)
7338 ADD_INT(d, DB_LOG_DIRECT);
7339 ADD_INT(d, DB_LOG_DSYNC);
7340 ADD_INT(d, DB_LOG_IN_MEMORY);
7341 ADD_INT(d, DB_LOG_AUTO_REMOVE);
7342 ADD_INT(d, DB_LOG_ZERO);
7343#endif
7344
7345#if (DBVER >= 44)
7346 ADD_INT(d, DB_DSYNC_DB);
7347#endif
7348
7349#if (DBVER >= 45)
7350 ADD_INT(d, DB_TXN_SNAPSHOT);
7351#endif
7352
7353 ADD_INT(d, DB_VERB_DEADLOCK);
7354#if (DBVER >= 46)
7355 ADD_INT(d, DB_VERB_FILEOPS);
7356 ADD_INT(d, DB_VERB_FILEOPS_ALL);
7357#endif
7358 ADD_INT(d, DB_VERB_RECOVERY);
7359#if (DBVER >= 44)
7360 ADD_INT(d, DB_VERB_REGISTER);
7361#endif
7362 ADD_INT(d, DB_VERB_REPLICATION);
7363 ADD_INT(d, DB_VERB_WAITSFOR);
7364
7365#if (DBVER >= 45)
7366 ADD_INT(d, DB_EVENT_PANIC);
7367 ADD_INT(d, DB_EVENT_REP_CLIENT);
7368#if (DBVER >= 46)
7369 ADD_INT(d, DB_EVENT_REP_ELECTED);
7370#endif
7371 ADD_INT(d, DB_EVENT_REP_MASTER);
7372 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
7373#if (DBVER >= 46)
7374 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
7375#endif
7376 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
7377 ADD_INT(d, DB_EVENT_WRITE_FAILED);
7378#endif
7379
7380 ADD_INT(d, DB_REP_DUPMASTER);
7381 ADD_INT(d, DB_REP_HOLDELECTION);
7382#if (DBVER >= 44)
7383 ADD_INT(d, DB_REP_IGNORE);
7384 ADD_INT(d, DB_REP_JOIN_FAILURE);
7385#endif
7386#if (DBVER >= 42)
7387 ADD_INT(d, DB_REP_ISPERM);
7388 ADD_INT(d, DB_REP_NOTPERM);
7389#endif
7390 ADD_INT(d, DB_REP_NEWSITE);
7391
7392 ADD_INT(d, DB_REP_MASTER);
7393 ADD_INT(d, DB_REP_CLIENT);
7394#if (DBVER >= 45)
7395 ADD_INT(d, DB_REP_ELECTION);
7396
7397 ADD_INT(d, DB_REP_ACK_TIMEOUT);
7398 ADD_INT(d, DB_REP_CONNECTION_RETRY);
7399 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
7400 ADD_INT(d, DB_REP_ELECTION_RETRY);
7401#endif
7402#if (DBVER >= 46)
7403 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
7404 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
7405#endif
7406
7407#if (DBVER >= 45)
7408 ADD_INT(d, DB_REPMGR_PEER);
7409 ADD_INT(d, DB_REPMGR_ACKS_ALL);
7410 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
7411 ADD_INT(d, DB_REPMGR_ACKS_NONE);
7412 ADD_INT(d, DB_REPMGR_ACKS_ONE);
7413 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
7414 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
7415 ADD_INT(d, DB_REPMGR_CONNECTED);
7416 ADD_INT(d, DB_REPMGR_DISCONNECTED);
7417 ADD_INT(d, DB_STAT_CLEAR);
7418 ADD_INT(d, DB_STAT_ALL);
7419#endif
7420
7421#if (DBVER >= 43)
7422 ADD_INT(d, DB_BUFFER_SMALL);
7423 ADD_INT(d, DB_SEQ_DEC);
7424 ADD_INT(d, DB_SEQ_INC);
7425 ADD_INT(d, DB_SEQ_WRAP);
7426#endif
7427
7428#if (DBVER >= 43) && (DBVER < 47)
7429 ADD_INT(d, DB_LOG_INMEMORY);
7430 ADD_INT(d, DB_DSYNC_LOG);
7431#endif
7432
7433#if (DBVER >= 41)
7434 ADD_INT(d, DB_ENCRYPT_AES);
7435 ADD_INT(d, DB_AUTO_COMMIT);
7436#else
7437 /* allow Berkeley DB 4.1 aware apps to run on older versions */
7438 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
7439#endif
7440
7441 ADD_INT(d, EINVAL);
7442 ADD_INT(d, EACCES);
7443 ADD_INT(d, ENOSPC);
7444 ADD_INT(d, ENOMEM);
7445 ADD_INT(d, EAGAIN);
7446 ADD_INT(d, EBUSY);
7447 ADD_INT(d, EEXIST);
7448 ADD_INT(d, ENOENT);
7449 ADD_INT(d, EPERM);
7450
7451 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
7452 ADD_INT(d, DB_SET_TXN_TIMEOUT);
7453
7454 /* The exception name must be correct for pickled exception *
7455 * objects to unpickle properly. */
7456#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
7457#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
7458#else
7459#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
7460#endif
7461
7462 /* All the rest of the exceptions derive only from DBError */
7463#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
7464 PyDict_SetItemString(d, #name, name)
7465
7466 /* The base exception class is DBError */
7467 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
7468 MAKE_EX(DBError);
7469
7470#if (PY_VERSION_HEX < 0x03000000)
7471 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
7472 * from both DBError and KeyError, since the API only supports
7473 * using one base class. */
7474 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
7475 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
7476 "class DBKeyEmptyError(DBError, KeyError): pass",
7477 Py_file_input, d, d);
7478 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
7479 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
7480 PyDict_DelItemString(d, "KeyError");
7481#else
7482 /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
7483 ** derive from several classes. We use this new API only for Python 3.0,
7484 ** though.
7485 */
7486 {
7487 PyObject* bases;
7488
7489 bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
7490
7491#define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
7492 PyDict_SetItemString(d, #name, name)
7493 MAKE_EX2(DBNotFoundError);
7494 MAKE_EX2(DBKeyEmptyError);
7495
7496#undef MAKE_EX2
7497
7498 Py_XDECREF(bases);
7499 }
7500#endif
7501
7502
7503#if !INCOMPLETE_IS_WARNING
7504 MAKE_EX(DBIncompleteError);
7505#endif
7506 MAKE_EX(DBCursorClosedError);
7507 MAKE_EX(DBKeyEmptyError);
7508 MAKE_EX(DBKeyExistError);
7509 MAKE_EX(DBLockDeadlockError);
7510 MAKE_EX(DBLockNotGrantedError);
7511 MAKE_EX(DBOldVersionError);
7512 MAKE_EX(DBRunRecoveryError);
7513 MAKE_EX(DBVerifyBadError);
7514 MAKE_EX(DBNoServerError);
7515 MAKE_EX(DBNoServerHomeError);
7516 MAKE_EX(DBNoServerIDError);
7517 MAKE_EX(DBPageNotFoundError);
7518 MAKE_EX(DBSecondaryBadError);
7519
7520 MAKE_EX(DBInvalidArgError);
7521 MAKE_EX(DBAccessError);
7522 MAKE_EX(DBNoSpaceError);
7523 MAKE_EX(DBNoMemoryError);
7524 MAKE_EX(DBAgainError);
7525 MAKE_EX(DBBusyError);
7526 MAKE_EX(DBFileExistsError);
7527 MAKE_EX(DBNoSuchFileError);
7528 MAKE_EX(DBPermissionsError);
7529
7530#if (DBVER >= 42)
7531 MAKE_EX(DBRepHandleDeadError);
7532#endif
7533
7534 MAKE_EX(DBRepUnavailError);
7535
7536#undef MAKE_EX
7537
7538 /* Initiliase the C API structure and add it to the module */
7539 bsddb_api.db_type = &DB_Type;
7540 bsddb_api.dbcursor_type = &DBCursor_Type;
7541 bsddb_api.dbenv_type = &DBEnv_Type;
7542 bsddb_api.dbtxn_type = &DBTxn_Type;
7543 bsddb_api.dblock_type = &DBLock_Type;
7544#if (DBVER >= 43)
7545 bsddb_api.dbsequence_type = &DBSequence_Type;
7546#endif
7547 bsddb_api.makeDBError = makeDBError;
7548
7549 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7550 PyDict_SetItemString(d, "api", py_api);
7551 Py_DECREF(py_api);
7552
7553 /* Check for errors */
7554 if (PyErr_Occurred()) {
7555 PyErr_Print();
7556 Py_FatalError("can't initialize module _bsddb/_pybsddb");
7557 Py_DECREF(m);
7558 m = NULL;
7559 }
7560#if (PY_VERSION_HEX < 0x03000000)
7561 return;
7562#else
7563 return m;
7564#endif
7565}
7566
7567/* allow this module to be named _pybsddb so that it can be installed
7568 * and imported on top of python >= 2.3 that includes its own older
7569 * copy of the library named _bsddb without importing the old version. */
7570#if (PY_VERSION_HEX < 0x03000000)
7571DL_EXPORT(void) init_pybsddb(void)
7572#else
7573PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */
7574#endif
7575{
7576 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
7577#if (PY_VERSION_HEX < 0x03000000)
7578 init_bsddb();
7579#else
7580 return PyInit__bsddb(); /* Note the two underscores */
7581#endif
7582}
Note: See TracBrowser for help on using the repository browser.