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 * More datatypes added:
77 *
78 * DBLogCursor (Log Cursor)
79 *
80 */
81
82 /* --------------------------------------------------------------------- */
83
84 /*
85 * Portions of this module, associated unit tests and build scripts are the
86 * result of a contract with The Written Word (http://thewrittenword.com/)
87 * Many thanks go out to them for causing me to raise the bar on quality and
88 * functionality, resulting in a better bsddb3 package for all of us to use.
89 *
90 * --Robin
91 */
92
93 /* --------------------------------------------------------------------- */
94
95 #include <stddef.h> /* for offsetof() */
96 #include <Python.h>
97
98 #define COMPILING_BSDDB_C
99 #include "bsddb.h"
100 #undef COMPILING_BSDDB_C
101
102 static char *rcs_id = "$Id$";
103
104 /* --------------------------------------------------------------------- */
105 /* Various macro definitions */
106
107 #if (PY_VERSION_HEX < 0x02050000)
108 typedef int Py_ssize_t;
109 #endif
110
111 #if (PY_VERSION_HEX < 0x02060000) /* really: before python trunk r63675 */
112 /* This code now uses PyBytes* API function names instead of PyString*.
113 * These #defines map to their equivalent on earlier python versions. */
114 #define PyBytes_FromStringAndSize PyString_FromStringAndSize
115 #define PyBytes_FromString PyString_FromString
116 #define PyBytes_AsStringAndSize PyString_AsStringAndSize
117 #define PyBytes_Check PyString_Check
118 #define PyBytes_GET_SIZE PyString_GET_SIZE
119 #define PyBytes_AS_STRING PyString_AS_STRING
120 #endif
121
122 #if (PY_VERSION_HEX >= 0x03000000)
123 #define NUMBER_Check PyLong_Check
124 #define NUMBER_AsLong PyLong_AsLong
125 #define NUMBER_FromLong PyLong_FromLong
126 #else
127 #define NUMBER_Check PyInt_Check
128 #define NUMBER_AsLong PyInt_AsLong
129 #define NUMBER_FromLong PyInt_FromLong
130 #endif
131
132 #ifdef WITH_THREAD
133
134 /* These are for when calling Python --> C */
135 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
136 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
137
138 /* For 2.3, use the PyGILState_ calls */
139 #if (PY_VERSION_HEX >= 0x02030000)
140 #define MYDB_USE_GILSTATE
141 #endif
142
143 /* and these are for calling C --> Python */
144 #if defined(MYDB_USE_GILSTATE)
145 #define MYDB_BEGIN_BLOCK_THREADS \
146 PyGILState_STATE __savestate = PyGILState_Ensure();
147 #define MYDB_END_BLOCK_THREADS \
148 PyGILState_Release(__savestate);
149 #else /* MYDB_USE_GILSTATE */
150 /* Pre GILState API - do it the long old way */
151 static PyInterpreterState* _db_interpreterState = NULL;
152 #define MYDB_BEGIN_BLOCK_THREADS { \
153 PyThreadState* prevState; \
154 PyThreadState* newState; \
155 PyEval_AcquireLock(); \
156 newState = PyThreadState_New(_db_interpreterState); \
157 prevState = PyThreadState_Swap(newState);
158
159 #define MYDB_END_BLOCK_THREADS \
160 newState = PyThreadState_Swap(prevState); \
161 PyThreadState_Clear(newState); \
162 PyEval_ReleaseLock(); \
163 PyThreadState_Delete(newState); \
164 }
165 #endif /* MYDB_USE_GILSTATE */
166
167 #else
168 /* Compiled without threads - avoid all this cruft */
169 #define MYDB_BEGIN_ALLOW_THREADS
170 #define MYDB_END_ALLOW_THREADS
171 #define MYDB_BEGIN_BLOCK_THREADS
172 #define MYDB_END_BLOCK_THREADS
173
174 #endif
175
176 /* --------------------------------------------------------------------- */
177 /* Exceptions */
178
179 static PyObject* DBError; /* Base class, all others derive from this */
180 static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
181 static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
182 static PyObject* DBKeyExistError; /* DB_KEYEXIST */
183 static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
184 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
185 static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
186 static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
187 static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
188 static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
189 static PyObject* DBNoServerError; /* DB_NOSERVER */
190 static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
191 static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
192 static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
193 static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
194
195 static PyObject* DBInvalidArgError; /* EINVAL */
196 static PyObject* DBAccessError; /* EACCES */
197 static PyObject* DBNoSpaceError; /* ENOSPC */
198 static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
199 static PyObject* DBAgainError; /* EAGAIN */
200 static PyObject* DBBusyError; /* EBUSY */
201 static PyObject* DBFileExistsError; /* EEXIST */
202 static PyObject* DBNoSuchFileError; /* ENOENT */
203 static PyObject* DBPermissionsError; /* EPERM */
204
205 #if (DBVER >= 42)
206 static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
207 #endif
208 #if (DBVER >= 44)
209 static PyObject* DBRepLockoutError; /* DB_REP_LOCKOUT */
210 #endif
211
212 #if (DBVER >= 46)
213 static PyObject* DBRepLeaseExpiredError; /* DB_REP_LEASE_EXPIRED */
214 #endif
215
216 #if (DBVER >= 47)
217 static PyObject* DBForeignConflictError; /* DB_FOREIGN_CONFLICT */
218 #endif
219
220
221 static PyObject* DBRepUnavailError; /* DB_REP_UNAVAIL */
222
223 #if (DBVER < 43)
224 #define DB_BUFFER_SMALL ENOMEM
225 #endif
226
227 #if (DBVER < 48)
228 #define DB_GID_SIZE DB_XIDDATASIZE
229 #endif
230
231
232 /* --------------------------------------------------------------------- */
233 /* Structure definitions */
234
235 #if PYTHON_API_VERSION < 1010
236 #error "Python 2.1 or later required"
237 #endif
238
239
240 /* Defaults for moduleFlags in DBEnvObject and DBObject. */
241 #define DEFAULT_GET_RETURNS_NONE 1
242 #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
243
244
245 /* See comment in Python 2.6 "object.h" */
246 #ifndef staticforward
247 #define staticforward static
248 #endif
249 #ifndef statichere
250 #define statichere static
251 #endif
252
253 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
254 DBLock_Type, DBLogCursor_Type;
255 #if (DBVER >= 43)
256 staticforward PyTypeObject DBSequence_Type;
257 #endif
258
259 #ifndef Py_TYPE
260 /* for compatibility with Python 2.5 and earlier */
261 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
262 #endif
263
264 #define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
265 #define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
266 #define DBLogCursorObject_Check(v) (Py_TYPE(v) == &DBLogCursor_Type)
267 #define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
268 #define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
269 #define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
270 #if (DBVER >= 43)
271 #define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
272 #endif
273
274 #if (DBVER < 46)
275 #define _DBC_close(dbc) dbc->c_close(dbc)
276 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
277 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
278 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
279 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
280 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
281 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
282 #else
283 #define _DBC_close(dbc) dbc->close(dbc)
284 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
285 #define _DBC_del(dbc,a) dbc->del(dbc,a)
286 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
287 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
288 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
289 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
290 #endif
291
292
293 /* --------------------------------------------------------------------- */
294 /* Utility macros and functions */
295
296 #define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
297 { \
298 object->sibling_next=backlink; \
299 object->sibling_prev_p=&(backlink); \
300 backlink=object; \
301 if (object->sibling_next) { \
302 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
303 } \
304 }
305
306 #define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
307 { \
308 if (object->sibling_next) { \
309 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
310 } \
311 *(object->sibling_prev_p)=object->sibling_next; \
312 }
313
314 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
315 { \
316 if (object->sibling_next) { \
317 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
318 } \
319 if (object->sibling_prev_p) { \
320 *(object->sibling_prev_p)=object->sibling_next; \
321 } \
322 }
323
324 #define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
325 { \
326 object->sibling_next_txn=backlink; \
327 object->sibling_prev_p_txn=&(backlink); \
328 backlink=object; \
329 if (object->sibling_next_txn) { \
330 object->sibling_next_txn->sibling_prev_p_txn= \
331 &(object->sibling_next_txn); \
332 } \
333 }
334
335 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
336 { \
337 if (object->sibling_next_txn) { \
338 object->sibling_next_txn->sibling_prev_p_txn= \
339 object->sibling_prev_p_txn; \
340 } \
341 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
342 }
343
344
345 #define RETURN_IF_ERR() \
346 if (makeDBError(err)) { \
347 return NULL; \
348 }
349
350 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
351
352 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
353 if ((nonNull) == NULL) { \
354 PyObject *errTuple = NULL; \
355 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
356 if (errTuple) { \
357 PyErr_SetObject((pyErrObj), errTuple); \
358 Py_DECREF(errTuple); \
359 } \
360 return NULL; \
361 }
362
363 #define CHECK_DB_NOT_CLOSED(dbobj) \
364 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
365
366 #define CHECK_ENV_NOT_CLOSED(env) \
367 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
368
369 #define CHECK_CURSOR_NOT_CLOSED(curs) \
370 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
371
372 #define CHECK_LOGCURSOR_NOT_CLOSED(logcurs) \
373 _CHECK_OBJECT_NOT_CLOSED(logcurs->logc, DBCursorClosedError, DBLogCursor)
374
375 #if (DBVER >= 43)
376 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
377 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
378 #endif
379
380 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
381 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
382
383 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
384
385 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
386 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
387
388
389 static int makeDBError(int err);
390
391
392 /* Return the access method type of the DBObject */
393 static int _DB_get_type(DBObject* self)
394 {
395 DBTYPE type;
396 int err;
397
398 err = self->db->get_type(self->db, &type);
399 if (makeDBError(err)) {
400 return -1;
401 }
402 return type;
403 }
404
405
406 /* Create a DBT structure (containing key and data values) from Python
407 strings. Returns 1 on success, 0 on an error. */
408 static int make_dbt(PyObject* obj, DBT* dbt)
409 {
410 CLEAR_DBT(*dbt);
411 if (obj == Py_None) {
412 /* no need to do anything, the structure has already been zeroed */
413 }
414 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
415 PyErr_SetString(PyExc_TypeError,
416 #if (PY_VERSION_HEX < 0x03000000)
417 "Data values must be of type string or None.");
418 #else
419 "Data values must be of type bytes or None.");
420 #endif
421 return 0;
422 }
423 return 1;
424 }
425
426
427 /* Recno and Queue DBs can have integer keys. This function figures out
428 what's been given, verifies that it's allowed, and then makes the DBT.
429
430 Caller MUST call FREE_DBT(key) when done. */
431 static int
432 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
433 {
434 db_recno_t recno;
435 int type;
436
437 CLEAR_DBT(*key);
438 if (keyobj == Py_None) {
439 type = _DB_get_type(self);
440 if (type == -1)
441 return 0;
442 if (type == DB_RECNO || type == DB_QUEUE) {
443 PyErr_SetString(
444 PyExc_TypeError,
445 "None keys not allowed for Recno and Queue DB's");
446 return 0;
447 }
448 /* no need to do anything, the structure has already been zeroed */
449 }
450
451 else if (PyBytes_Check(keyobj)) {
452 /* verify access method type */
453 type = _DB_get_type(self);
454 if (type == -1)
455 return 0;
456 if (type == DB_RECNO || type == DB_QUEUE) {
457 PyErr_SetString(
458 PyExc_TypeError,
459 #if (PY_VERSION_HEX < 0x03000000)
460 "String keys not allowed for Recno and Queue DB's");
461 #else
462 "Bytes keys not allowed for Recno and Queue DB's");
463 #endif
464 return 0;
465 }
466
467 /*
468 * NOTE(gps): I don't like doing a data copy here, it seems
469 * wasteful. But without a clean way to tell FREE_DBT if it
470 * should free key->data or not we have to. Other places in
471 * the code check for DB_THREAD and forceably set DBT_MALLOC
472 * when we otherwise would leave flags 0 to indicate that.
473 */
474 key->data = malloc(PyBytes_GET_SIZE(keyobj));
475 if (key->data == NULL) {
476 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
477 return 0;
478 }
479 memcpy(key->data, PyBytes_AS_STRING(keyobj),
480 PyBytes_GET_SIZE(keyobj));
481 key->flags = DB_DBT_REALLOC;
482 key->size = PyBytes_GET_SIZE(keyobj);
483 }
484
485 else if (NUMBER_Check(keyobj)) {
486 /* verify access method type */
487 type = _DB_get_type(self);
488 if (type == -1)
489 return 0;
490 if (type == DB_BTREE && pflags != NULL) {
491 /* if BTREE then an Integer key is allowed with the
492 * DB_SET_RECNO flag */
493 *pflags |= DB_SET_RECNO;
494 }
495 else if (type != DB_RECNO && type != DB_QUEUE) {
496 PyErr_SetString(
497 PyExc_TypeError,
498 "Integer keys only allowed for Recno and Queue DB's");
499 return 0;
500 }
501
502 /* Make a key out of the requested recno, use allocated space so DB
503 * will be able to realloc room for the real key if needed. */
504 recno = NUMBER_AsLong(keyobj);
505 key->data = malloc(sizeof(db_recno_t));
506 if (key->data == NULL) {
507 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
508 return 0;
509 }
510 key->ulen = key->size = sizeof(db_recno_t);
511 memcpy(key->data, &recno, sizeof(db_recno_t));
512 key->flags = DB_DBT_REALLOC;
513 }
514 else {
515 PyErr_Format(PyExc_TypeError,
516 #if (PY_VERSION_HEX < 0x03000000)
517 "String or Integer object expected for key, %s found",
518 #else
519 "Bytes or Integer object expected for key, %s found",
520 #endif
521 Py_TYPE(keyobj)->tp_name);
522 return 0;
523 }
524
525 return 1;
526 }
527
528
529 /* Add partial record access to an existing DBT data struct.
530 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
531 and the data storage/retrieval will be done using dlen and doff. */
532 static int add_partial_dbt(DBT* d, int dlen, int doff) {
533 /* if neither were set we do nothing (-1 is the default value) */
534 if ((dlen == -1) && (doff == -1)) {
535 return 1;
536 }
537
538 if ((dlen < 0) || (doff < 0)) {
539 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
540 return 0;
541 }
542
543 d->flags = d->flags | DB_DBT_PARTIAL;
544 d->dlen = (unsigned int) dlen;
545 d->doff = (unsigned int) doff;
546 return 1;
547 }
548
549 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
550 /* TODO: make this use the native libc strlcpy() when available (BSD) */
551 unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
552 {
553 unsigned int srclen, copylen;
554
555 srclen = strlen(src);
556 if (n <= 0)
557 return srclen;
558 copylen = (srclen > n-1) ? n-1 : srclen;
559 /* populate dest[0] thru dest[copylen-1] */
560 memcpy(dest, src, copylen);
561 /* guarantee null termination */
562 dest[copylen] = 0;
563
564 return srclen;
565 }
566
567 /* Callback used to save away more information about errors from the DB
568 * library. */
569 static char _db_errmsg[1024];
570 #if (DBVER <= 42)
571 static void _db_errorCallback(const char* prefix, char* msg)
572 #else
573 static void _db_errorCallback(const DB_ENV *db_env,
574 const char* prefix, const char* msg)
575 #endif
576 {
577 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
578 }
579
580
581 /*
582 ** We need these functions because some results
583 ** are undefined if pointer is NULL. Some other
584 ** give None instead of "".
585 **
586 ** This functions are static and will be
587 ** -I hope- inlined.
588 */
589 static const char *DummyString = "This string is a simple placeholder";
590 static PyObject *Build_PyString(const char *p,int s)
591 {
592 if (!p) {
593 p=DummyString;
594 assert(s==0);
595 }
596 return PyBytes_FromStringAndSize(p,s);
597 }
598
599 static PyObject *BuildValue_S(const void *p,int s)
600 {
601 if (!p) {
602 p=DummyString;
603 assert(s==0);
604 }
605 return PyBytes_FromStringAndSize(p, s);
606 }
607
608 static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
609 {
610 PyObject *a, *b, *r;
611
612 if (!p1) {
613 p1=DummyString;
614 assert(s1==0);
615 }
616 if (!p2) {
617 p2=DummyString;
618 assert(s2==0);
619 }
620
621 if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
622 return NULL;
623 }
624 if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
625 Py_DECREF(a);
626 return NULL;
627 }
628
629 #if (PY_VERSION_HEX >= 0x02040000)
630 r = PyTuple_Pack(2, a, b) ;
631 #else
632 r = Py_BuildValue("OO", a, b);
633 #endif
634 Py_DECREF(a);
635 Py_DECREF(b);
636 return r;
637 }
638
639 static PyObject *BuildValue_IS(int i,const void *p,int s)
640 {
641 PyObject *a, *r;
642
643 if (!p) {
644 p=DummyString;
645 assert(s==0);
646 }
647
648 if (!(a = PyBytes_FromStringAndSize(p, s))) {
649 return NULL;
650 }
651
652 r = Py_BuildValue("iO", i, a);
653 Py_DECREF(a);
654 return r;
655 }
656
657 static PyObject *BuildValue_LS(long l,const void *p,int s)
658 {
659 PyObject *a, *r;
660
661 if (!p) {
662 p=DummyString;
663 assert(s==0);
664 }
665
666 if (!(a = PyBytes_FromStringAndSize(p, s))) {
667 return NULL;
668 }
669
670 r = Py_BuildValue("lO", l, a);
671 Py_DECREF(a);
672 return r;
673 }
674
675
676
677 /* make a nice exception object to raise for errors. */
678 static int makeDBError(int err)
679 {
680 char errTxt[2048]; /* really big, just in case... */
681 PyObject *errObj = NULL;
682 PyObject *errTuple = NULL;
683 int exceptionRaised = 0;
684 unsigned int bytes_left;
685
686 switch (err) {
687 case 0: /* successful, no error */
688 return 0;
689
690 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
691 case DB_KEYEXIST: errObj = DBKeyExistError; break;
692 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
693 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
694 case DB_NOTFOUND: errObj = DBNotFoundError; break;
695 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
696 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
697 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
698 case DB_NOSERVER: errObj = DBNoServerError; break;
699 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
700 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
701 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
702 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
703 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
704
705 #if (DBVER >= 43)
706 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
707 case ENOMEM: errObj = PyExc_MemoryError; break;
708 #endif
709 case EINVAL: errObj = DBInvalidArgError; break;
710 case EACCES: errObj = DBAccessError; break;
711 case ENOSPC: errObj = DBNoSpaceError; break;
712 case EAGAIN: errObj = DBAgainError; break;
713 case EBUSY : errObj = DBBusyError; break;
714 case EEXIST: errObj = DBFileExistsError; break;
715 case ENOENT: errObj = DBNoSuchFileError; break;
716 case EPERM : errObj = DBPermissionsError; break;
717
718 #if (DBVER >= 42)
719 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
720 #endif
721 #if (DBVER >= 44)
722 case DB_REP_LOCKOUT : errObj = DBRepLockoutError; break;
723 #endif
724
725 #if (DBVER >= 46)
726 case DB_REP_LEASE_EXPIRED : errObj = DBRepLeaseExpiredError; break;
727 #endif
728
729 #if (DBVER >= 47)
730 case DB_FOREIGN_CONFLICT : errObj = DBForeignConflictError; break;
731 #endif
732
733 case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
734
735 default: errObj = DBError; break;
736 }
737
738 if (errObj != NULL) {
739 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
740 /* Ensure that bytes_left never goes negative */
741 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
742 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
743 assert(bytes_left >= 0);
744 strcat(errTxt, " -- ");
745 strncat(errTxt, _db_errmsg, bytes_left);
746 }
747 _db_errmsg[0] = 0;
748
749 errTuple = Py_BuildValue("(is)", err, errTxt);
750 if (errTuple == NULL) {
751 Py_DECREF(errObj);
752 return !0;
753 }
754 PyErr_SetObject(errObj, errTuple);
755 Py_DECREF(errTuple);
756 }
757
758 return ((errObj != NULL) || exceptionRaised);
759 }
760
761
762
763 /* set a type exception */
764 static void makeTypeError(char* expected, PyObject* found)
765 {
766 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
767 expected, Py_TYPE(found)->tp_name);
768 }
769
770
771 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
772 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
773 {
774 if (txnobj == Py_None || txnobj == NULL) {
775 *txn = NULL;
776 return 1;
777 }
778 if (DBTxnObject_Check(txnobj)) {
779 *txn = ((DBTxnObject*)txnobj)->txn;
780 return 1;
781 }
782 else
783 makeTypeError("DBTxn", txnobj);
784 return 0;
785 }
786
787
788 /* Delete a key from a database
789 Returns 0 on success, -1 on an error. */
790 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
791 {
792 int err;
793
794 MYDB_BEGIN_ALLOW_THREADS;
795 err = self->db->del(self->db, txn, key, 0);
796 MYDB_END_ALLOW_THREADS;
797 if (makeDBError(err)) {
798 return -1;
799 }
800 return 0;
801 }
802
803
804 /* Store a key into a database
805 Returns 0 on success, -1 on an error. */
806 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
807 {
808 int err;
809
810 MYDB_BEGIN_ALLOW_THREADS;
811 err = self->db->put(self->db, txn, key, data, flags);
812 MYDB_END_ALLOW_THREADS;
813 if (makeDBError(err)) {
814 return -1;
815 }
816 return 0;
817 }
818
819 /* Get a key/data pair from a cursor */
820 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
821 PyObject *args, PyObject *kwargs, char *format)
822 {
823 int err;
824 PyObject* retval = NULL;
825 DBT key, data;
826 int dlen = -1;
827 int doff = -1;
828 int flags = 0;
829 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
830
831 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
832 &flags, &dlen, &doff))
833 return NULL;
834
835 CHECK_CURSOR_NOT_CLOSED(self);
836
837 flags |= extra_flags;
838 CLEAR_DBT(key);
839 CLEAR_DBT(data);
840 if (!add_partial_dbt(&data, dlen, doff))
841 return NULL;
842
843 MYDB_BEGIN_ALLOW_THREADS;
844 err = _DBC_get(self->dbc, &key, &data, flags);
845 MYDB_END_ALLOW_THREADS;
846
847 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
848 && self->mydb->moduleFlags.getReturnsNone) {
849 Py_INCREF(Py_None);
850 retval = Py_None;
851 }
852 else if (makeDBError(err)) {
853 retval = NULL;
854 }
855 else { /* otherwise, success! */
856
857 /* if Recno or Queue, return the key as an Int */
858 switch (_DB_get_type(self->mydb)) {
859 case -1:
860 retval = NULL;
861 break;
862
863 case DB_RECNO:
864 case DB_QUEUE:
865 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
866 break;
867 case DB_HASH:
868 case DB_BTREE:
869 default:
870 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
871 break;
872 }
873 }
874 return retval;
875 }
876
877
878 /* add an integer to a dictionary using the given name as a key */
879 static void _addIntToDict(PyObject* dict, char *name, int value)
880 {
881 PyObject* v = NUMBER_FromLong((long) value);
882 if (!v || PyDict_SetItemString(dict, name, v))
883 PyErr_Clear();
884
885 Py_XDECREF(v);
886 }
887
888 /* The same, when the value is a time_t */
889 static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
890 {
891 PyObject* v;
892 /* if the value fits in regular int, use that. */
893 #ifdef PY_LONG_LONG
894 if (sizeof(time_t) > sizeof(long))
895 v = PyLong_FromLongLong((PY_LONG_LONG) value);
896 else
897 #endif
898 v = NUMBER_FromLong((long) value);
899 if (!v || PyDict_SetItemString(dict, name, v))
900 PyErr_Clear();
901
902 Py_XDECREF(v);
903 }
904
905 #if (DBVER >= 43)
906 /* add an db_seq_t to a dictionary using the given name as a key */
907 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
908 {
909 PyObject* v = PyLong_FromLongLong(value);
910 if (!v || PyDict_SetItemString(dict, name, v))
911 PyErr_Clear();
912
913 Py_XDECREF(v);
914 }
915 #endif
916
917 static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
918 {
919 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
920 if (!v || PyDict_SetItemString(dict, name, v))
921 PyErr_Clear();
922
923 Py_XDECREF(v);
924 }
925
926 /* --------------------------------------------------------------------- */
927 /* Allocators and deallocators */
928
929 static DBObject*
930 newDBObject(DBEnvObject* arg, int flags)
931 {
932 DBObject* self;
933 DB_ENV* db_env = NULL;
934 int err;
935
936 self = PyObject_New(DBObject, &DB_Type);
937 if (self == NULL)
938 return NULL;
939
940 self->flags = 0;
941 self->setflags = 0;
942 self->myenvobj = NULL;
943 self->db = NULL;
944 self->children_cursors = NULL;
945 #if (DBVER >=43)
946 self->children_sequences = NULL;
947 #endif
948 self->associateCallback = NULL;
949 self->btCompareCallback = NULL;
950 self->primaryDBType = 0;
951 Py_INCREF(Py_None);
952 self->private_obj = Py_None;
953 self->in_weakreflist = NULL;
954
955 /* keep a reference to our python DBEnv object */
956 if (arg) {
957 Py_INCREF(arg);
958 self->myenvobj = arg;
959 db_env = arg->db_env;
960 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
961 } else {
962 self->sibling_prev_p=NULL;
963 self->sibling_next=NULL;
964 }
965 self->txn=NULL;
966 self->sibling_prev_p_txn=NULL;
967 self->sibling_next_txn=NULL;
968
969 if (self->myenvobj)
970 self->moduleFlags = self->myenvobj->moduleFlags;
971 else
972 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
973 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
974
975 MYDB_BEGIN_ALLOW_THREADS;
976 err = db_create(&self->db, db_env, flags);
977 if (self->db != NULL) {
978 self->db->set_errcall(self->db, _db_errorCallback);
979 self->db->app_private = (void*)self;
980 }
981 MYDB_END_ALLOW_THREADS;
982 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
983 * list so that a DBEnv can refuse to close without aborting any open
984 * DBTxns and closing any open DBs first. */
985 if (makeDBError(err)) {
986 if (self->myenvobj) {
987 Py_DECREF(self->myenvobj);
988 self->myenvobj = NULL;
989 }
990 Py_DECREF(self);
991 self = NULL;
992 }
993 return self;
994 }
995
996
997 /* Forward declaration */
998 static PyObject *DB_close_internal(DBObject* self, int flags, int do_not_close);
999
1000 static void
1001 DB_dealloc(DBObject* self)
1002 {
1003 PyObject *dummy;
1004
1005 if (self->db != NULL) {
1006 dummy=DB_close_internal(self, 0, 0);
1007 /*
1008 ** Raising exceptions while doing
1009 ** garbage collection is a fatal error.
1010 */
1011 if (dummy)
1012 Py_DECREF(dummy);
1013 else
1014 PyErr_Clear();
1015 }
1016 if (self->in_weakreflist != NULL) {
1017 PyObject_ClearWeakRefs((PyObject *) self);
1018 }
1019 if (self->myenvobj) {
1020 Py_DECREF(self->myenvobj);
1021 self->myenvobj = NULL;
1022 }
1023 if (self->associateCallback != NULL) {
1024 Py_DECREF(self->associateCallback);
1025 self->associateCallback = NULL;
1026 }
1027 if (self->btCompareCallback != NULL) {
1028 Py_DECREF(self->btCompareCallback);
1029 self->btCompareCallback = NULL;
1030 }
1031 Py_DECREF(self->private_obj);
1032 PyObject_Del(self);
1033 }
1034
1035 static DBCursorObject*
1036 newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
1037 {
1038 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
1039 if (self == NULL)
1040 return NULL;
1041
1042 self->dbc = dbc;
1043 self->mydb = db;
1044
1045 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
1046 if (txn && ((PyObject *)txn!=Py_None)) {
1047 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
1048 self->txn=txn;
1049 } else {
1050 self->txn=NULL;
1051 }
1052
1053 self->in_weakreflist = NULL;
1054 Py_INCREF(self->mydb);
1055 return self;
1056 }
1057
1058
1059 /* Forward declaration */
1060 static PyObject *DBC_close_internal(DBCursorObject* self);
1061
1062 static void
1063 DBCursor_dealloc(DBCursorObject* self)
1064 {
1065 PyObject *dummy;
1066
1067 if (self->dbc != NULL) {
1068 dummy=DBC_close_internal(self);
1069 /*
1070 ** Raising exceptions while doing
1071 ** garbage collection is a fatal error.
1072 */
1073 if (dummy)
1074 Py_DECREF(dummy);
1075 else
1076 PyErr_Clear();
1077 }
1078 if (self->in_weakreflist != NULL) {
1079 PyObject_ClearWeakRefs((PyObject *) self);
1080 }
1081 Py_DECREF(self->mydb);
1082 PyObject_Del(self);
1083 }
1084
1085
1086 static DBLogCursorObject*
1087 newDBLogCursorObject(DB_LOGC* dblogc, DBEnvObject* env)
1088 {
1089 DBLogCursorObject* self;
1090
1091 self = PyObject_New(DBLogCursorObject, &DBLogCursor_Type);
1092
1093 if (self == NULL)
1094 return NULL;
1095
1096 self->logc = dblogc;
1097 self->env = env;
1098
1099 INSERT_IN_DOUBLE_LINKED_LIST(self->env->children_logcursors, self);
1100
1101 self->in_weakreflist = NULL;
1102 Py_INCREF(self->env);
1103 return self;
1104 }
1105
1106
1107 /* Forward declaration */
1108 static PyObject *DBLogCursor_close_internal(DBLogCursorObject* self);
1109
1110 static void
1111 DBLogCursor_dealloc(DBLogCursorObject* self)
1112 {
1113 PyObject *dummy;
1114
1115 if (self->logc != NULL) {
1116 dummy = DBLogCursor_close_internal(self);
1117 /*
1118 ** Raising exceptions while doing
1119 ** garbage collection is a fatal error.
1120 */
1121 if (dummy)
1122 Py_DECREF(dummy);
1123 else
1124 PyErr_Clear();
1125 }
1126 if (self->in_weakreflist != NULL) {
1127 PyObject_ClearWeakRefs((PyObject *) self);
1128 }
1129 Py_DECREF(self->env);
1130 PyObject_Del(self);
1131 }
1132
1133
1134 static DBEnvObject*
1135 newDBEnvObject(int flags)
1136 {
1137 int err;
1138 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
1139 if (self == NULL)
1140 return NULL;
1141
1142 self->db_env = NULL;
1143 self->closed = 1;
1144 self->flags = flags;
1145 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1146 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
1147 self->children_dbs = NULL;
1148 self->children_txns = NULL;
1149 self->children_logcursors = NULL ;
1150 Py_INCREF(Py_None);
1151 self->private_obj = Py_None;
1152 Py_INCREF(Py_None);
1153 self->rep_transport = Py_None;
1154 self->in_weakreflist = NULL;
1155 self->event_notifyCallback = NULL;
1156
1157 MYDB_BEGIN_ALLOW_THREADS;
1158 err = db_env_create(&self->db_env, flags);
1159 MYDB_END_ALLOW_THREADS;
1160 if (makeDBError(err)) {
1161 Py_DECREF(self);
1162 self = NULL;
1163 }
1164 else {
1165 self->db_env->set_errcall(self->db_env, _db_errorCallback);
1166 self->db_env->app_private = self;
1167 }
1168 return self;
1169 }
1170
1171 /* Forward declaration */
1172 static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
1173
1174 static void
1175 DBEnv_dealloc(DBEnvObject* self)
1176 {
1177 PyObject *dummy;
1178
1179 if (self->db_env) {
1180 dummy=DBEnv_close_internal(self, 0);
1181 /*
1182 ** Raising exceptions while doing
1183 ** garbage collection is a fatal error.
1184 */
1185 if (dummy)
1186 Py_DECREF(dummy);
1187 else
1188 PyErr_Clear();
1189 }
1190
1191 Py_XDECREF(self->event_notifyCallback);
1192 self->event_notifyCallback = NULL;
1193
1194 if (self->in_weakreflist != NULL) {
1195 PyObject_ClearWeakRefs((PyObject *) self);
1196 }
1197 Py_DECREF(self->private_obj);
1198 Py_DECREF(self->rep_transport);
1199 PyObject_Del(self);
1200 }
1201
1202
1203 static DBTxnObject*
1204 newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
1205 {
1206 int err;
1207 DB_TXN *parent_txn = NULL;
1208
1209 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
1210 if (self == NULL)
1211 return NULL;
1212
1213 self->in_weakreflist = NULL;
1214 self->children_txns = NULL;
1215 self->children_dbs = NULL;
1216 self->children_cursors = NULL;
1217 self->children_sequences = NULL;
1218 self->flag_prepare = 0;
1219 self->parent_txn = NULL;
1220 self->env = NULL;
1221 /* We initialize just in case "txn_begin" fails */
1222 self->txn = NULL;
1223
1224 if (parent && ((PyObject *)parent!=Py_None)) {
1225 parent_txn = parent->txn;
1226 }
1227
1228 if (txn) {
1229 self->txn = txn;
1230 } else {
1231 MYDB_BEGIN_ALLOW_THREADS;
1232 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
1233 MYDB_END_ALLOW_THREADS;
1234
1235 if (makeDBError(err)) {
1236 /* Free object half initialized */
1237 Py_DECREF(self);
1238 return NULL;
1239 }
1240 }
1241
1242 /* Can't use 'parent' because could be 'parent==Py_None' */
1243 if (parent_txn) {
1244 self->parent_txn = parent;
1245 Py_INCREF(parent);
1246 self->env = NULL;
1247 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
1248 } else {
1249 self->parent_txn = NULL;
1250 Py_INCREF(myenv);
1251 self->env = myenv;
1252 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
1253 }
1254
1255 return self;
1256 }
1257
1258 /* Forward declaration */
1259 static PyObject *
1260 DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
1261
1262 static void
1263 DBTxn_dealloc(DBTxnObject* self)
1264 {
1265 PyObject *dummy;
1266
1267 if (self->txn) {
1268 int flag_prepare = self->flag_prepare;
1269
1270 dummy=DBTxn_abort_discard_internal(self, 0);
1271 /*
1272 ** Raising exceptions while doing
1273 ** garbage collection is a fatal error.
1274 */
1275 if (dummy)
1276 Py_DECREF(dummy);
1277 else
1278 PyErr_Clear();
1279
1280 if (!flag_prepare) {
1281 PyErr_Warn(PyExc_RuntimeWarning,
1282 "DBTxn aborted in destructor. No prior commit() or abort().");
1283 }
1284 }
1285
1286 if (self->in_weakreflist != NULL) {
1287 PyObject_ClearWeakRefs((PyObject *) self);
1288 }
1289
1290 if (self->env) {
1291 Py_DECREF(self->env);
1292 } else {
1293 /*
1294 ** We can have "self->env==NULL" and "self->parent_txn==NULL"
1295 ** if something happens when creating the transaction object
1296 ** and we abort the object while half done.
1297 */
1298 Py_XDECREF(self->parent_txn);
1299 }
1300 PyObject_Del(self);
1301 }
1302
1303
1304 static DBLockObject*
1305 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1306 db_lockmode_t lock_mode, int flags)
1307 {
1308 int err;
1309 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
1310 if (self == NULL)
1311 return NULL;
1312 self->in_weakreflist = NULL;
1313 self->lock_initialized = 0; /* Just in case the call fails */
1314
1315 MYDB_BEGIN_ALLOW_THREADS;
1316 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1317 &self->lock);
1318 MYDB_END_ALLOW_THREADS;
1319 if (makeDBError(err)) {
1320 Py_DECREF(self);
1321 self = NULL;
1322 } else {
1323 self->lock_initialized = 1;
1324 }
1325
1326 return self;
1327 }
1328
1329
1330 static void
1331 DBLock_dealloc(DBLockObject* self)
1332 {
1333 if (self->in_weakreflist != NULL) {
1334 PyObject_ClearWeakRefs((PyObject *) self);
1335 }
1336 /* TODO: is this lock held? should we release it? */
1337 /* CAUTION: The lock can be not initialized if the creation has failed */
1338
1339 PyObject_Del(self);
1340 }
1341
1342
1343 #if (DBVER >= 43)
1344 static DBSequenceObject*
1345 newDBSequenceObject(DBObject* mydb, int flags)
1346 {
1347 int err;
1348 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1349 if (self == NULL)
1350 return NULL;
1351 Py_INCREF(mydb);
1352 self->mydb = mydb;
1353
1354 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
1355 self->txn = NULL;
1356
1357 self->in_weakreflist = NULL;
1358 self->sequence = NULL; /* Just in case the call fails */
1359
1360 MYDB_BEGIN_ALLOW_THREADS;
1361 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1362 MYDB_END_ALLOW_THREADS;
1363 if (makeDBError(err)) {
1364 Py_DECREF(self);
1365 self = NULL;
1366 }
1367
1368 return self;
1369 }
1370
1371 /* Forward declaration */
1372 static PyObject
1373 *DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
1374
1375 static void
1376 DBSequence_dealloc(DBSequenceObject* self)
1377 {
1378 PyObject *dummy;
1379
1380 if (self->sequence != NULL) {
1381 dummy=DBSequence_close_internal(self,0,0);
1382 /*
1383 ** Raising exceptions while doing
1384 ** garbage collection is a fatal error.
1385 */
1386 if (dummy)
1387 Py_DECREF(dummy);
1388 else
1389 PyErr_Clear();
1390 }
1391
1392 if (self->in_weakreflist != NULL) {
1393 PyObject_ClearWeakRefs((PyObject *) self);
1394 }
1395
1396 Py_DECREF(self->mydb);
1397 PyObject_Del(self);
1398 }
1399 #endif
1400
1401 /* --------------------------------------------------------------------- */
1402 /* DB methods */
1403
1404 static PyObject*
1405 DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
1406 {
1407 PyObject* txnobj = NULL;
1408 PyObject* dataobj;
1409 db_recno_t recno;
1410 DBT key, data;
1411 DB_TXN *txn = NULL;
1412 static char* kwnames[] = { "data", "txn", NULL };
1413
1414 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
1415 &dataobj, &txnobj))
1416 return NULL;
1417
1418 CHECK_DB_NOT_CLOSED(self);
1419
1420 /* make a dummy key out of a recno */
1421 recno = 0;
1422 CLEAR_DBT(key);
1423 key.data = &recno;
1424 key.size = sizeof(recno);
1425 key.ulen = key.size;
1426 key.flags = DB_DBT_USERMEM;
1427
1428 if (!make_dbt(dataobj, &data)) return NULL;
1429 if (!checkTxnObj(txnobj, &txn)) return NULL;
1430
1431 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1432 return NULL;
1433
1434 return NUMBER_FromLong(recno);
1435 }
1436
1437
1438 static int
1439 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1440 DBT* secKey)
1441 {
1442 int retval = DB_DONOTINDEX;
1443 DBObject* secondaryDB = (DBObject*)db->app_private;
1444 PyObject* callback = secondaryDB->associateCallback;
1445 int type = secondaryDB->primaryDBType;
1446 PyObject* args;
1447 PyObject* result = NULL;
1448
1449
1450 if (callback != NULL) {
1451 MYDB_BEGIN_BLOCK_THREADS;
1452
1453 if (type == DB_RECNO || type == DB_QUEUE)
1454 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
1455 else
1456 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
1457 if (args != NULL) {
1458 result = PyEval_CallObject(callback, args);
1459 }
1460 if (args == NULL || result == NULL) {
1461 PyErr_Print();
1462 }
1463 else if (result == Py_None) {
1464 retval = DB_DONOTINDEX;
1465 }
1466 else if (NUMBER_Check(result)) {
1467 retval = NUMBER_AsLong(result);
1468 }
1469 else if (PyBytes_Check(result)) {
1470 char* data;
1471 Py_ssize_t size;
1472
1473 CLEAR_DBT(*secKey);
1474 PyBytes_AsStringAndSize(result, &data, &size);
1475 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1476 secKey->data = malloc(size); /* TODO, check this */
1477 if (secKey->data) {
1478 memcpy(secKey->data, data, size);
1479 secKey->size = size;
1480 retval = 0;
1481 }
1482 else {
1483 PyErr_SetString(PyExc_MemoryError,
1484 "malloc failed in _db_associateCallback");
1485 PyErr_Print();
1486 }
1487 }
1488 #if (DBVER >= 46)
1489 else if (PyList_Check(result))
1490 {
1491 char* data;
1492 Py_ssize_t size;
1493 int i, listlen;
1494 DBT* dbts;
1495
1496 listlen = PyList_Size(result);
1497
1498 dbts = (DBT *)malloc(sizeof(DBT) * listlen);
1499
1500 for (i=0; i<listlen; i++)
1501 {
1502 if (!PyBytes_Check(PyList_GetItem(result, i)))
1503 {
1504 PyErr_SetString(
1505 PyExc_TypeError,
1506 #if (PY_VERSION_HEX < 0x03000000)
1507 "The list returned by DB->associate callback should be a list of strings.");
1508 #else
1509 "The list returned by DB->associate callback should be a list of bytes.");
1510 #endif
1511 PyErr_Print();
1512 }
1513
1514 PyBytes_AsStringAndSize(
1515 PyList_GetItem(result, i),
1516 &data, &size);
1517
1518 CLEAR_DBT(dbts[i]);
1519 dbts[i].data = malloc(size); /* TODO, check this */
1520
1521 if (dbts[i].data)
1522 {
1523 memcpy(dbts[i].data, data, size);
1524 dbts[i].size = size;
1525 dbts[i].ulen = dbts[i].size;
1526 dbts[i].flags = DB_DBT_APPMALLOC; /* DB will free */
1527 }
1528 else
1529 {
1530 PyErr_SetString(PyExc_MemoryError,
1531 "malloc failed in _db_associateCallback (list)");
1532 PyErr_Print();
1533 }
1534 }
1535
1536 CLEAR_DBT(*secKey);
1537
1538 secKey->data = dbts;
1539 secKey->size = listlen;
1540 secKey->flags = DB_DBT_APPMALLOC | DB_DBT_MULTIPLE;
1541 retval = 0;
1542 }
1543 #endif
1544 else {
1545 PyErr_SetString(
1546 PyExc_TypeError,
1547 #if (PY_VERSION_HEX < 0x03000000)
1548 "DB associate callback should return DB_DONOTINDEX/string/list of strings.");
1549 #else
1550 "DB associate callback should return DB_DONOTINDEX/bytes/list of bytes.");
1551 #endif
1552 PyErr_Print();
1553 }
1554
1555 Py_XDECREF(args);
1556 Py_XDECREF(result);
1557
1558 MYDB_END_BLOCK_THREADS;
1559 }
1560 return retval;
1561 }
1562
1563
1564 static PyObject*
1565 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1566 {
1567 int err, flags=0;
1568 DBObject* secondaryDB;
1569 PyObject* callback;
1570 PyObject *txnobj = NULL;
1571 DB_TXN *txn = NULL;
1572 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1573 NULL};
1574
1575 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1576 &secondaryDB, &callback, &flags,
1577 &txnobj)) {
1578 return NULL;
1579 }
1580
1581 if (!checkTxnObj(txnobj, &txn)) return NULL;
1582
1583 CHECK_DB_NOT_CLOSED(self);
1584 if (!DBObject_Check(secondaryDB)) {
1585 makeTypeError("DB", (PyObject*)secondaryDB);
1586 return NULL;
1587 }
1588 CHECK_DB_NOT_CLOSED(secondaryDB);
1589 if (callback == Py_None) {
1590 callback = NULL;
1591 }
1592 else if (!PyCallable_Check(callback)) {
1593 makeTypeError("Callable", callback);
1594 return NULL;
1595 }
1596
1597 /* Save a reference to the callback in the secondary DB. */
1598 Py_XDECREF(secondaryDB->associateCallback);
1599 Py_XINCREF(callback);
1600 secondaryDB->associateCallback = callback;
1601 secondaryDB->primaryDBType = _DB_get_type(self);
1602
1603 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1604 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1605 * The global interepreter lock is not initialized until the first
1606 * thread is created using thread.start_new_thread() or fork() is
1607 * called. that would cause the ALLOW_THREADS here to segfault due
1608 * to a null pointer reference if no threads or child processes
1609 * have been created. This works around that and is a no-op if
1610 * threads have already been initialized.
1611 * (see pybsddb-users mailing list post on 2002-08-07)
1612 */
1613 #ifdef WITH_THREAD
1614 PyEval_InitThreads();
1615 #endif
1616 MYDB_BEGIN_ALLOW_THREADS;
1617 err = self->db->associate(self->db,
1618 txn,
1619 secondaryDB->db,
1620 _db_associateCallback,
1621 flags);
1622 MYDB_END_ALLOW_THREADS;
1623
1624 if (err) {
1625 Py_XDECREF(secondaryDB->associateCallback);
1626 secondaryDB->associateCallback = NULL;
1627 secondaryDB->primaryDBType = 0;
1628 }
1629
1630 RETURN_IF_ERR();
1631 RETURN_NONE();
1632 }
1633
1634
1635 static PyObject*
1636 DB_close_internal(DBObject* self, int flags, int do_not_close)
1637 {
1638 PyObject *dummy;
1639 int err = 0;
1640
1641 if (self->db != NULL) {
1642 /* Can be NULL if db is not in an environment */
1643 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
1644
1645 if (self->txn) {
1646 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1647 self->txn=NULL;
1648 }
1649
1650 while(self->children_cursors) {
1651 dummy=DBC_close_internal(self->children_cursors);
1652 Py_XDECREF(dummy);
1653 }
1654
1655 #if (DBVER >= 43)
1656 while(self->children_sequences) {
1657 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1658 Py_XDECREF(dummy);
1659 }
1660 #endif
1661
1662 /*
1663 ** "do_not_close" is used to dispose all related objects in the
1664 ** tree, without actually releasing the "root" object.
1665 ** This is done, for example, because function calls like
1666 ** "DB.verify()" implicitly close the underlying handle. So
1667 ** the handle doesn't need to be closed, but related objects
1668 ** must be cleaned up.
1669 */
1670 if (!do_not_close) {
1671 MYDB_BEGIN_ALLOW_THREADS;
1672 err = self->db->close(self->db, flags);
1673 MYDB_END_ALLOW_THREADS;
1674 self->db = NULL;
1675 }
1676 RETURN_IF_ERR();
1677 }
1678 RETURN_NONE();
1679 }
1680
1681 static PyObject*
1682 DB_close(DBObject* self, PyObject* args)
1683 {
1684 int flags=0;
1685 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1686 return NULL;
1687 return DB_close_internal(self, flags, 0);
1688 }
1689
1690
1691 static PyObject*
1692 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1693 {
1694 int err, flags=0, type;
1695 PyObject* txnobj = NULL;
1696 PyObject* retval = NULL;
1697 DBT key, data;
1698 DB_TXN *txn = NULL;
1699 static char* kwnames[] = { "txn", "flags", NULL };
1700
1701 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1702 &txnobj, &flags))
1703 return NULL;
1704
1705 CHECK_DB_NOT_CLOSED(self);
1706 type = _DB_get_type(self);
1707 if (type == -1)
1708 return NULL;
1709 if (type != DB_QUEUE) {
1710 PyErr_SetString(PyExc_TypeError,
1711 "Consume methods only allowed for Queue DB's");
1712 return NULL;
1713 }
1714 if (!checkTxnObj(txnobj, &txn))
1715 return NULL;
1716
1717 CLEAR_DBT(key);
1718 CLEAR_DBT(data);
1719 if (CHECK_DBFLAG(self, DB_THREAD)) {
1720 /* Tell Berkeley DB to malloc the return value (thread safe) */
1721 data.flags = DB_DBT_MALLOC;
1722 key.flags = DB_DBT_MALLOC;
1723 }
1724
1725 MYDB_BEGIN_ALLOW_THREADS;
1726 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1727 MYDB_END_ALLOW_THREADS;
1728
1729 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1730 && self->moduleFlags.getReturnsNone) {
1731 err = 0;
1732 Py_INCREF(Py_None);
1733 retval = Py_None;
1734 }
1735 else if (!err) {
1736 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
1737 FREE_DBT(key);
1738 FREE_DBT(data);
1739 }
1740
1741 RETURN_IF_ERR();
1742 return retval;
1743 }
1744
1745 static PyObject*
1746 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1747 {
1748 return _DB_consume(self, args, kwargs, DB_CONSUME);
1749 }
1750
1751 static PyObject*
1752 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1753 int consume_flag)
1754 {
1755 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1756 }
1757
1758
1759 static PyObject*
1760 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1761 {
1762 int err, flags=0;
1763 DBC* dbc;
1764 PyObject* txnobj = NULL;
1765 DB_TXN *txn = NULL;
1766 static char* kwnames[] = { "txn", "flags", NULL };
1767
1768 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1769 &txnobj, &flags))
1770 return NULL;
1771 CHECK_DB_NOT_CLOSED(self);
1772 if (!checkTxnObj(txnobj, &txn))
1773 return NULL;
1774
1775 MYDB_BEGIN_ALLOW_THREADS;
1776 err = self->db->cursor(self->db, txn, &dbc, flags);
1777 MYDB_END_ALLOW_THREADS;
1778 RETURN_IF_ERR();
1779 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
1780 }
1781
1782
1783 static PyObject*
1784 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1785 {
1786 PyObject* txnobj = NULL;
1787 int flags = 0;
1788 PyObject* keyobj;
1789 DBT key;
1790 DB_TXN *txn = NULL;
1791 static char* kwnames[] = { "key", "txn", "flags", NULL };
1792
1793 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1794 &keyobj, &txnobj, &flags))
1795 return NULL;
1796 CHECK_DB_NOT_CLOSED(self);
1797 if (!make_key_dbt(self, keyobj, &key, NULL))
1798 return NULL;
1799 if (!checkTxnObj(txnobj, &txn)) {
1800 FREE_DBT(key);
1801 return NULL;
1802 }
1803
1804 if (-1 == _DB_delete(self, txn, &key, 0)) {
1805 FREE_DBT(key);
1806 return NULL;
1807 }
1808
1809 FREE_DBT(key);
1810 RETURN_NONE();
1811 }
1812
1813
1814 #if (DBVER >= 47)
1815 /*
1816 ** This function is available since Berkeley DB 4.4,
1817 ** but 4.6 version is so buggy that we only support
1818 ** it from BDB 4.7 and newer.
1819 */
1820 static PyObject*
1821 DB_compact(DBObject* self, PyObject* args, PyObject* kwargs)
1822 {
1823 PyObject* txnobj = NULL;
1824 PyObject *startobj = NULL, *stopobj = NULL;
1825 int flags = 0;
1826 DB_TXN *txn = NULL;
1827 DBT *start_p = NULL, *stop_p = NULL;
1828 DBT start, stop;
1829 int err;
1830 DB_COMPACT c_data = { 0 };
1831 static char* kwnames[] = { "txn", "start", "stop", "flags",
1832 "compact_fillpercent", "compact_pages",
1833 "compact_timeout", NULL };
1834
1835
1836 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOiiiI:compact", kwnames,
1837 &txnobj, &startobj, &stopobj, &flags,
1838 &c_data.compact_fillpercent,
1839 &c_data.compact_pages,
1840 &c_data.compact_timeout))
1841 return NULL;
1842
1843 CHECK_DB_NOT_CLOSED(self);
1844 if (!checkTxnObj(txnobj, &txn)) {
1845 return NULL;
1846 }
1847
1848 if (startobj && make_key_dbt(self, startobj, &start, NULL)) {
1849 start_p = &start;
1850 }
1851 if (stopobj && make_key_dbt(self, stopobj, &stop, NULL)) {
1852 stop_p = &stop;
1853 }
1854
1855 MYDB_BEGIN_ALLOW_THREADS;
1856 err = self->db->compact(self->db, txn, start_p, stop_p, &c_data,
1857 flags, NULL);
1858 MYDB_END_ALLOW_THREADS;
1859
1860 if (startobj)
1861 FREE_DBT(start);
1862 if (stopobj)
1863 FREE_DBT(stop);
1864
1865 RETURN_IF_ERR();
1866
1867 return PyLong_FromUnsignedLong(c_data.compact_pages_truncated);
1868 }
1869 #endif
1870
1871
1872 static PyObject*
1873 DB_fd(DBObject* self)
1874 {
1875 int err, the_fd;
1876
1877 CHECK_DB_NOT_CLOSED(self);
1878
1879 MYDB_BEGIN_ALLOW_THREADS;
1880 err = self->db->fd(self->db, &the_fd);
1881 MYDB_END_ALLOW_THREADS;
1882 RETURN_IF_ERR();
1883 return NUMBER_FromLong(the_fd);
1884 }
1885
1886
1887 #if (DBVER >= 46)
1888 static PyObject*
1889 DB_exists(DBObject* self, PyObject* args, PyObject* kwargs)
1890 {
1891 int err, flags=0;
1892 PyObject* txnobj = NULL;
1893 PyObject* keyobj;
1894 DBT key;
1895 DB_TXN *txn;
1896
1897 static char* kwnames[] = {"key", "txn", "flags", NULL};
1898
1899 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:exists", kwnames,
1900 &keyobj, &txnobj, &flags))
1901 return NULL;
1902
1903 CHECK_DB_NOT_CLOSED(self);
1904 if (!make_key_dbt(self, keyobj, &key, NULL))
1905 return NULL;
1906 if (!checkTxnObj(txnobj, &txn)) {
1907 FREE_DBT(key);
1908 return NULL;
1909 }
1910
1911 MYDB_BEGIN_ALLOW_THREADS;
1912 err = self->db->exists(self->db, txn, &key, flags);
1913 MYDB_END_ALLOW_THREADS;
1914
1915 FREE_DBT(key);
1916
1917 if (!err) {
1918 Py_INCREF(Py_True);
1919 return Py_True;
1920 }
1921 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)) {
1922 Py_INCREF(Py_False);
1923 return Py_False;
1924 }
1925
1926 /*
1927 ** If we reach there, there was an error. The
1928 ** "return" should be unreachable.
1929 */
1930 RETURN_IF_ERR();
1931 assert(0); /* This coude SHOULD be unreachable */
1932 return NULL;
1933 }
1934 #endif
1935
1936 static PyObject*
1937 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1938 {
1939 int err, flags=0;
1940 PyObject* txnobj = NULL;
1941 PyObject* keyobj;
1942 PyObject* dfltobj = NULL;
1943 PyObject* retval = NULL;
1944 int dlen = -1;
1945 int doff = -1;
1946 DBT key, data;
1947 DB_TXN *txn = NULL;
1948 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1949 "doff", NULL};
1950
1951 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1952 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1953 &doff))
1954 return NULL;
1955
1956 CHECK_DB_NOT_CLOSED(self);
1957 if (!make_key_dbt(self, keyobj, &key, &flags))
1958 return NULL;
1959 if (!checkTxnObj(txnobj, &txn)) {
1960 FREE_DBT(key);
1961 return NULL;
1962 }
1963
1964 CLEAR_DBT(data);
1965 if (CHECK_DBFLAG(self, DB_THREAD)) {
1966 /* Tell Berkeley DB to malloc the return value (thread safe) */
1967 data.flags = DB_DBT_MALLOC;
1968 }
1969 if (!add_partial_dbt(&data, dlen, doff)) {
1970 FREE_DBT(key);
1971 return NULL;
1972 }
1973
1974 MYDB_BEGIN_ALLOW_THREADS;
1975 err = self->db->get(self->db, txn, &key, &data, flags);
1976 MYDB_END_ALLOW_THREADS;
1977
1978 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1979 err = 0;
1980 Py_INCREF(dfltobj);
1981 retval = dfltobj;
1982 }
1983 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1984 && self->moduleFlags.getReturnsNone) {
1985 err = 0;
1986 Py_INCREF(Py_None);
1987 retval = Py_None;
1988 }
1989 else if (!err) {
1990 if (flags & DB_SET_RECNO) /* return both key and data */
1991 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
1992 else /* return just the data */
1993 retval = Build_PyString(data.data, data.size);
1994 FREE_DBT(data);
1995 }
1996 FREE_DBT(key);
1997
1998 RETURN_IF_ERR();
1999 return retval;
2000 }
2001
2002 static PyObject*
2003 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
2004 {
2005 int err, flags=0;
2006 PyObject* txnobj = NULL;
2007 PyObject* keyobj;
2008 PyObject* dfltobj = NULL;
2009 PyObject* retval = NULL;
2010 int dlen = -1;
2011 int doff = -1;
2012 DBT key, pkey, data;
2013 DB_TXN *txn = NULL;
2014 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
2015 "doff", NULL};
2016
2017 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
2018 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
2019 &doff))
2020 return NULL;
2021
2022 CHECK_DB_NOT_CLOSED(self);
2023 if (!make_key_dbt(self, keyobj, &key, &flags))
2024 return NULL;
2025 if (!checkTxnObj(txnobj, &txn)) {
2026 FREE_DBT(key);
2027 return NULL;
2028 }
2029
2030 CLEAR_DBT(data);
2031 if (CHECK_DBFLAG(self, DB_THREAD)) {
2032 /* Tell Berkeley DB to malloc the return value (thread safe) */
2033 data.flags = DB_DBT_MALLOC;
2034 }
2035 if (!add_partial_dbt(&data, dlen, doff)) {
2036 FREE_DBT(key);
2037 return NULL;
2038 }
2039
2040 CLEAR_DBT(pkey);
2041 pkey.flags = DB_DBT_MALLOC;
2042
2043 MYDB_BEGIN_ALLOW_THREADS;
2044 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
2045 MYDB_END_ALLOW_THREADS;
2046
2047 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
2048 err = 0;
2049 Py_INCREF(dfltobj);
2050 retval = dfltobj;
2051 }
2052 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
2053 && self->moduleFlags.getReturnsNone) {
2054 err = 0;
2055 Py_INCREF(Py_None);
2056 retval = Py_None;
2057 }
2058 else if (!err) {
2059 PyObject *pkeyObj;
2060 PyObject *dataObj;
2061 dataObj = Build_PyString(data.data, data.size);
2062
2063 if (self->primaryDBType == DB_RECNO ||
2064 self->primaryDBType == DB_QUEUE)
2065 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
2066 else
2067 pkeyObj = Build_PyString(pkey.data, pkey.size);
2068
2069 if (flags & DB_SET_RECNO) /* return key , pkey and data */
2070 {
2071 PyObject *keyObj;
2072 int type = _DB_get_type(self);
2073 if (type == DB_RECNO || type == DB_QUEUE)
2074 keyObj = NUMBER_FromLong(*(int *)key.data);
2075 else
2076 keyObj = Build_PyString(key.data, key.size);
2077 #if (PY_VERSION_HEX >= 0x02040000)
2078 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
2079 #else
2080 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
2081 #endif
2082 Py_DECREF(keyObj);
2083 }
2084 else /* return just the pkey and data */
2085 {
2086 #if (PY_VERSION_HEX >= 0x02040000)
2087 retval = PyTuple_Pack(2, pkeyObj, dataObj);
2088 #else
2089 retval = Py_BuildValue("OO", pkeyObj, dataObj);
2090 #endif
2091 }
2092 Py_DECREF(dataObj);
2093 Py_DECREF(pkeyObj);
2094 FREE_DBT(pkey);
2095 FREE_DBT(data);
2096 }
2097 FREE_DBT(key);
2098
2099 RETURN_IF_ERR();
2100 return retval;
2101 }
2102
2103
2104 /* Return size of entry */
2105 static PyObject*
2106 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
2107 {
2108 int err, flags=0;
2109 PyObject* txnobj = NULL;
2110 PyObject* keyobj;
2111 PyObject* retval = NULL;
2112 DBT key, data;
2113 DB_TXN *txn = NULL;
2114 static char* kwnames[] = { "key", "txn", NULL };
2115
2116 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
2117 &keyobj, &txnobj))
2118 return NULL;
2119 CHECK_DB_NOT_CLOSED(self);
2120 if (!make_key_dbt(self, keyobj, &key, &flags))
2121 return NULL;
2122 if (!checkTxnObj(txnobj, &txn)) {
2123 FREE_DBT(key);
2124 return NULL;
2125 }
2126 CLEAR_DBT(data);
2127
2128 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
2129 thus getting the record size. */
2130 data.flags = DB_DBT_USERMEM;
2131 data.ulen = 0;
2132 MYDB_BEGIN_ALLOW_THREADS;
2133 err = self->db->get(self->db, txn, &key, &data, flags);
2134 MYDB_END_ALLOW_THREADS;
2135 if (err == DB_BUFFER_SMALL) {
2136 retval = NUMBER_FromLong((long)data.size);
2137 err = 0;
2138 }
2139
2140 FREE_DBT(key);
2141 FREE_DBT(data);
2142 RETURN_IF_ERR();
2143 return retval;
2144 }
2145
2146
2147 static PyObject*
2148 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
2149 {
2150 int err, flags=0;
2151 PyObject* txnobj = NULL;
2152 PyObject* keyobj;
2153 PyObject* dataobj;
2154 PyObject* retval = NULL;
2155 DBT key, data;
2156 void *orig_data;
2157 DB_TXN *txn = NULL;
2158 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
2159
2160 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
2161 &keyobj, &dataobj, &txnobj, &flags))
2162 return NULL;
2163
2164 CHECK_DB_NOT_CLOSED(self);
2165 if (!make_key_dbt(self, keyobj, &key, NULL))
2166 return NULL;
2167 if ( !make_dbt(dataobj, &data) ||
2168 !checkTxnObj(txnobj, &txn) )
2169 {
2170 FREE_DBT(key);
2171 return NULL;
2172 }
2173
2174 flags |= DB_GET_BOTH;
2175 orig_data = data.data;
2176
2177 if (CHECK_DBFLAG(self, DB_THREAD)) {
2178 /* Tell Berkeley DB to malloc the return value (thread safe) */
2179 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
2180 data.flags = DB_DBT_MALLOC;
2181 }
2182
2183 MYDB_BEGIN_ALLOW_THREADS;
2184 err = self->db->get(self->db, txn, &key, &data, flags);
2185 MYDB_END_ALLOW_THREADS;
2186
2187 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
2188 && self->moduleFlags.getReturnsNone) {
2189 err = 0;
2190 Py_INCREF(Py_None);
2191 retval = Py_None;
2192 }
2193 else if (!err) {
2194 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
2195 retval = Build_PyString(data.data, data.size);
2196
2197 /* Even though the flags require DB_DBT_MALLOC, data is not always
2198 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
2199 if (data.data != orig_data)
2200 FREE_DBT(data);
2201 }
2202
2203 FREE_DBT(key);
2204 RETURN_IF_ERR();
2205 return retval;
2206 }
2207
2208
2209 static PyObject*
2210 DB_get_byteswapped(DBObject* self)
2211 {
2212 int err = 0;
2213 int retval = -1;
2214
2215 CHECK_DB_NOT_CLOSED(self);
2216
2217 MYDB_BEGIN_ALLOW_THREADS;
2218 err = self->db->get_byteswapped(self->db, &retval);
2219 MYDB_END_ALLOW_THREADS;
2220 RETURN_IF_ERR();
2221 return NUMBER_FromLong(retval);
2222 }
2223
2224
2225 static PyObject*
2226 DB_get_type(DBObject* self)
2227 {
2228 int type;
2229
2230 CHECK_DB_NOT_CLOSED(self);
2231
2232 type = _DB_get_type(self);
2233 if (type == -1)
2234 return NULL;
2235 return NUMBER_FromLong(type);
2236 }
2237
2238
2239 static PyObject*
2240 DB_join(DBObject* self, PyObject* args)
2241 {
2242 int err, flags=0;
2243 int length, x;
2244 PyObject* cursorsObj;
2245 DBC** cursors;
2246 DBC* dbc;
2247
2248 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
2249 return NULL;
2250
2251 CHECK_DB_NOT_CLOSED(self);
2252
2253 if (!PySequence_Check(cursorsObj)) {
2254 PyErr_SetString(PyExc_TypeError,
2255 "Sequence of DBCursor objects expected");
2256 return NULL;
2257 }
2258
2259 length = PyObject_Length(cursorsObj);
2260 cursors = malloc((length+1) * sizeof(DBC*));
2261 if (!cursors) {
2262 PyErr_NoMemory();
2263 return NULL;
2264 }
2265
2266 cursors[length] = NULL;
2267 for (x=0; x<length; x++) {
2268 PyObject* item = PySequence_GetItem(cursorsObj, x);
2269 if (item == NULL) {
2270 free(cursors);
2271 return NULL;
2272 }
2273 if (!DBCursorObject_Check(item)) {
2274 PyErr_SetString(PyExc_TypeError,
2275 "Sequence of DBCursor objects expected");
2276 free(cursors);
2277 return NULL;
2278 }
2279 cursors[x] = ((DBCursorObject*)item)->dbc;
2280 Py_DECREF(item);
2281 }
2282
2283 MYDB_BEGIN_ALLOW_THREADS;
2284 err = self->db->join(self->db, cursors, &dbc, flags);
2285 MYDB_END_ALLOW_THREADS;
2286 free(cursors);
2287 RETURN_IF_ERR();
2288
2289 /* FIXME: this is a buggy interface. The returned cursor
2290 contains internal references to the passed in cursors
2291 but does not hold python references to them or prevent
2292 them from being closed prematurely. This can cause
2293 python to crash when things are done in the wrong order. */
2294 return (PyObject*) newDBCursorObject(dbc, NULL, self);
2295 }
2296
2297
2298 static PyObject*
2299 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
2300 {
2301 int err, flags=0;
2302 PyObject* txnobj = NULL;
2303 PyObject* keyobj;
2304 DBT key;
2305 DB_TXN *txn = NULL;
2306 DB_KEY_RANGE range;
2307 static char* kwnames[] = { "key", "txn", "flags", NULL };
2308
2309 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
2310 &keyobj, &txnobj, &flags))
2311 return NULL;
2312 CHECK_DB_NOT_CLOSED(self);
2313 if (!make_dbt(keyobj, &key))
2314 /* BTree only, don't need to allow for an int key */
2315 return NULL;
2316 if (!checkTxnObj(txnobj, &txn))
2317 return NULL;
2318
2319 MYDB_BEGIN_ALLOW_THREADS;
2320 err = self->db->key_range(self->db, txn, &key, &range, flags);
2321 MYDB_END_ALLOW_THREADS;
2322
2323 RETURN_IF_ERR();
2324 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2325 }
2326
2327
2328 static PyObject*
2329 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2330 {
2331 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2332 char* filename = NULL;
2333 char* dbname = NULL;
2334 PyObject *txnobj = NULL;
2335 DB_TXN *txn = NULL;
2336 /* with dbname */
2337 static char* kwnames[] = {
2338 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2339 /* without dbname */
2340 static char* kwnames_basic[] = {
2341 "filename", "dbtype", "flags", "mode", "txn", NULL};
2342
2343 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2344 &filename, &dbname, &type, &flags, &mode,
2345 &txnobj))
2346 {
2347 PyErr_Clear();
2348 type = DB_UNKNOWN; flags = 0; mode = 0660;
2349 filename = NULL; dbname = NULL;
2350 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2351 kwnames_basic,
2352 &filename, &type, &flags, &mode,
2353 &txnobj))
2354 return NULL;
2355 }
2356
2357 if (!checkTxnObj(txnobj, &txn)) return NULL;
2358
2359 if (NULL == self->db) {
2360 PyObject *t = Py_BuildValue("(is)", 0,
2361 "Cannot call open() twice for DB object");
2362 if (t) {
2363 PyErr_SetObject(DBError, t);
2364 Py_DECREF(t);
2365 }
2366 return NULL;
2367 }
2368
2369 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2370 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2371 self->txn=(DBTxnObject *)txnobj;
2372 } else {
2373 self->txn=NULL;
2374 }
2375
2376 MYDB_BEGIN_ALLOW_THREADS;
2377 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2378 MYDB_END_ALLOW_THREADS;
2379
2380 if (makeDBError(err)) {
2381 PyObject *dummy;
2382
2383 dummy=DB_close_internal(self, 0, 0);
2384 Py_XDECREF(dummy);
2385 return NULL;
2386 }
2387
2388 #if (DBVER >= 42)
2389 self->db->get_flags(self->db, &self->setflags);
2390 #endif
2391
2392 self->flags = flags;
2393
2394 RETURN_NONE();
2395 }
2396
2397
2398 static PyObject*
2399 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2400 {
2401 int flags=0;
2402 PyObject* txnobj = NULL;
2403 int dlen = -1;
2404 int doff = -1;
2405 PyObject* keyobj, *dataobj, *retval;
2406 DBT key, data;
2407 DB_TXN *txn = NULL;
2408 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
2409 "doff", NULL };
2410
2411 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2412 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2413 return NULL;
2414
2415 CHECK_DB_NOT_CLOSED(self);
2416 if (!make_key_dbt(self, keyobj, &key, NULL))
2417 return NULL;
2418 if ( !make_dbt(dataobj, &data) ||
2419 !add_partial_dbt(&data, dlen, doff) ||
2420 !checkTxnObj(txnobj, &txn) )
2421 {
2422 FREE_DBT(key);
2423 return NULL;
2424 }
2425
2426 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2427 FREE_DBT(key);
2428 return NULL;
2429 }
2430
2431 if (flags & DB_APPEND)
2432 retval = NUMBER_FromLong(*((db_recno_t*)key.data));
2433 else {
2434 retval = Py_None;
2435 Py_INCREF(retval);
2436 }
2437 FREE_DBT(key);
2438 return retval;
2439 }
2440
2441
2442
2443 static PyObject*
2444 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2445 {
2446 char* filename;
2447 char* database = NULL;
2448 int err, flags=0;
2449 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
2450
2451 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2452 &filename, &database, &flags))
2453 return NULL;
2454 CHECK_DB_NOT_CLOSED(self);
2455
2456 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
2457
2458 MYDB_BEGIN_ALLOW_THREADS;
2459 err = self->db->remove(self->db, filename, database, flags);
2460 MYDB_END_ALLOW_THREADS;
2461
2462 self->db = NULL;
2463 RETURN_IF_ERR();
2464 RETURN_NONE();
2465 }
2466
2467
2468
2469 static PyObject*
2470 DB_rename(DBObject* self, PyObject* args)
2471 {
2472 char* filename;
2473 char* database;
2474 char* newname;
2475 int err, flags=0;
2476
2477 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2478 &flags))
2479 return NULL;
2480 CHECK_DB_NOT_CLOSED(self);
2481
2482 MYDB_BEGIN_ALLOW_THREADS;
2483 err = self->db->rename(self->db, filename, database, newname, flags);
2484 MYDB_END_ALLOW_THREADS;
2485 RETURN_IF_ERR();
2486 RETURN_NONE();
2487 }
2488
2489
2490 static PyObject*
2491 DB_get_private(DBObject* self)
2492 {
2493 /* We can give out the private field even if db is closed */
2494 Py_INCREF(self->private_obj);
2495 return self->private_obj;
2496 }
2497
2498 static PyObject*
2499 DB_set_private(DBObject* self, PyObject* private_obj)
2500 {
2501 /* We can set the private field even if db is closed */
2502 Py_DECREF(self->private_obj);
2503 Py_INCREF(private_obj);
2504 self->private_obj = private_obj;
2505 RETURN_NONE();
2506 }
2507
2508 #if (DBVER >= 46)
2509 static PyObject*
2510 DB_set_priority(DBObject* self, PyObject* args)
2511 {
2512 int err, priority;
2513
2514 if (!PyArg_ParseTuple(args,"i:set_priority", &priority))
2515 return NULL;
2516 CHECK_DB_NOT_CLOSED(self);
2517
2518 MYDB_BEGIN_ALLOW_THREADS;
2519 err = self->db->set_priority(self->db, priority);
2520 MYDB_END_ALLOW_THREADS;
2521 RETURN_IF_ERR();
2522 RETURN_NONE();
2523 }
2524
2525 static PyObject*
2526 DB_get_priority(DBObject* self)
2527 {
2528 int err = 0;
2529 DB_CACHE_PRIORITY priority;
2530
2531 CHECK_DB_NOT_CLOSED(self);
2532
2533 MYDB_BEGIN_ALLOW_THREADS;
2534 err = self->db->get_priority(self->db, &priority);
2535 MYDB_END_ALLOW_THREADS;
2536 RETURN_IF_ERR();
2537 return NUMBER_FromLong(priority);
2538 }
2539 #endif
2540
2541 static PyObject*
2542 DB_set_q_extentsize(DBObject* self, PyObject* args)
2543 {
2544 int err;
2545 u_int32_t extentsize;
2546
2547 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2548 return NULL;
2549 CHECK_DB_NOT_CLOSED(self);
2550
2551 MYDB_BEGIN_ALLOW_THREADS;
2552 err = self->db->set_q_extentsize(self->db, extentsize);
2553 MYDB_END_ALLOW_THREADS;
2554 RETURN_IF_ERR();
2555 RETURN_NONE();
2556 }
2557
2558 #if (DBVER >= 42)
2559 static PyObject*
2560 DB_get_q_extentsize(DBObject* self)
2561 {
2562 int err = 0;
2563 u_int32_t extentsize;
2564
2565 CHECK_DB_NOT_CLOSED(self);
2566
2567 MYDB_BEGIN_ALLOW_THREADS;
2568 err = self->db->get_q_extentsize(self->db, &extentsize);
2569 MYDB_END_ALLOW_THREADS;
2570 RETURN_IF_ERR();
2571 return NUMBER_FromLong(extentsize);
2572 }
2573 #endif
2574
2575 static PyObject*
2576 DB_set_bt_minkey(DBObject* self, PyObject* args)
2577 {
2578 int err, minkey;
2579
2580 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey))
2581 return NULL;
2582 CHECK_DB_NOT_CLOSED(self);
2583
2584 MYDB_BEGIN_ALLOW_THREADS;
2585 err = self->db->set_bt_minkey(self->db, minkey);
2586 MYDB_END_ALLOW_THREADS;
2587 RETURN_IF_ERR();
2588 RETURN_NONE();
2589 }
2590
2591 #if (DBVER >= 42)
2592 static PyObject*
2593 DB_get_bt_minkey(DBObject* self)
2594 {
2595 int err;
2596 u_int32_t bt_minkey;
2597
2598 CHECK_DB_NOT_CLOSED(self);
2599
2600 MYDB_BEGIN_ALLOW_THREADS;
2601 err = self->db->get_bt_minkey(self->db, &bt_minkey);
2602 MYDB_END_ALLOW_THREADS;
2603 RETURN_IF_ERR();
2604 return NUMBER_FromLong(bt_minkey);
2605 }
2606 #endif
2607
2608 static int
2609 _default_cmp(const DBT *leftKey,
2610 const DBT *rightKey)
2611 {
2612 int res;
2613 int lsize = leftKey->size, rsize = rightKey->size;
2614
2615 res = memcmp(leftKey->data, rightKey->data,
2616 lsize < rsize ? lsize : rsize);
2617
2618 if (res == 0) {
2619 if (lsize < rsize) {
2620 res = -1;
2621 }
2622 else if (lsize > rsize) {
2623 res = 1;
2624 }
2625 }
2626 return res;
2627 }
2628
2629 static int
2630 _db_compareCallback(DB* db,
2631 const DBT *leftKey,
2632 const DBT *rightKey)
2633 {
2634 int res = 0;
2635 PyObject *args;
2636 PyObject *result = NULL;
2637 DBObject *self = (DBObject *)db->app_private;
2638
2639 if (self == NULL || self->btCompareCallback == NULL) {
2640 MYDB_BEGIN_BLOCK_THREADS;
2641 PyErr_SetString(PyExc_TypeError,
2642 (self == 0
2643 ? "DB_bt_compare db is NULL."
2644 : "DB_bt_compare callback is NULL."));
2645 /* we're in a callback within the DB code, we can't raise */
2646 PyErr_Print();
2647 res = _default_cmp(leftKey, rightKey);
2648 MYDB_END_BLOCK_THREADS;
2649 } else {
2650 MYDB_BEGIN_BLOCK_THREADS;
2651
2652 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
2653 if (args != NULL) {
2654 result = PyEval_CallObject(self->btCompareCallback, args);
2655 }
2656 if (args == NULL || result == NULL) {
2657 /* we're in a callback within the DB code, we can't raise */
2658 PyErr_Print();
2659 res = _default_cmp(leftKey, rightKey);
2660 } else if (NUMBER_Check(result)) {
2661 res = NUMBER_AsLong(result);
2662 } else {
2663 PyErr_SetString(PyExc_TypeError,
2664 "DB_bt_compare callback MUST return an int.");
2665 /* we're in a callback within the DB code, we can't raise */
2666 PyErr_Print();
2667 res = _default_cmp(leftKey, rightKey);
2668 }
2669
2670 Py_XDECREF(args);
2671 Py_XDECREF(result);
2672
2673 MYDB_END_BLOCK_THREADS;
2674 }
2675 return res;
2676 }
2677
2678 static PyObject*
2679 DB_set_bt_compare(DBObject* self, PyObject* comparator)
2680 {
2681 int err;
2682 PyObject *tuple, *result;
2683
2684 CHECK_DB_NOT_CLOSED(self);
2685
2686 if (!PyCallable_Check(comparator)) {
2687 makeTypeError("Callable", comparator);
2688 return NULL;
2689 }
2690
2691 /*
2692 * Perform a test call of the comparator function with two empty
2693 * string objects here. verify that it returns an int (0).
2694 * err if not.
2695 */
2696 tuple = Py_BuildValue("(ss)", "", "");
2697 result = PyEval_CallObject(comparator, tuple);
2698 Py_DECREF(tuple);
2699 if (result == NULL)
2700 return NULL;
2701 if (!NUMBER_Check(result)) {
2702 Py_DECREF(result);
2703 PyErr_SetString(PyExc_TypeError,
2704 "callback MUST return an int");
2705 return NULL;
2706 } else if (NUMBER_AsLong(result) != 0) {
2707 Py_DECREF(result);
2708 PyErr_SetString(PyExc_TypeError,
2709 "callback failed to return 0 on two empty strings");
2710 return NULL;
2711 }
2712 Py_DECREF(result);
2713
2714 /* We don't accept multiple set_bt_compare operations, in order to
2715 * simplify the code. This would have no real use, as one cannot
2716 * change the function once the db is opened anyway */
2717 if (self->btCompareCallback != NULL) {
2718 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2719 return NULL;
2720 }
2721
2722 Py_INCREF(comparator);
2723 self->btCompareCallback = comparator;
2724
2725 /* This is to workaround a problem with un-initialized threads (see
2726 comment in DB_associate) */
2727 #ifdef WITH_THREAD
2728 PyEval_InitThreads();
2729 #endif
2730
2731 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2732
2733 if (err) {
2734 /* restore the old state in case of error */
2735 Py_DECREF(comparator);
2736 self->btCompareCallback = NULL;
2737 }
2738
2739 RETURN_IF_ERR();
2740 RETURN_NONE();
2741 }
2742
2743
2744 static PyObject*
2745 DB_set_cachesize(DBObject* self, PyObject* args)
2746 {
2747 int err;
2748 int gbytes = 0, bytes = 0, ncache = 0;
2749
2750 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2751 &gbytes,&bytes,&ncache))
2752 return NULL;
2753 CHECK_DB_NOT_CLOSED(self);
2754
2755 MYDB_BEGIN_ALLOW_THREADS;
2756 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2757 MYDB_END_ALLOW_THREADS;
2758 RETURN_IF_ERR();
2759 RETURN_NONE();
2760 }
2761
2762 #if (DBVER >= 42)
2763 static PyObject*
2764 DB_get_cachesize(DBObject* self)
2765 {
2766 int err;
2767 u_int32_t gbytes, bytes;
2768 int ncache;
2769
2770 CHECK_DB_NOT_CLOSED(self);
2771
2772 MYDB_BEGIN_ALLOW_THREADS;
2773 err = self->db->get_cachesize(self->db, &gbytes, &bytes, &ncache);
2774 MYDB_END_ALLOW_THREADS;
2775
2776 RETURN_IF_ERR();
2777
2778 return Py_BuildValue("(iii)", gbytes, bytes, ncache);
2779 }
2780 #endif
2781
2782 static PyObject*
2783 DB_set_flags(DBObject* self, PyObject* args)
2784 {
2785 int err, flags;
2786
2787 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2788 return NULL;
2789 CHECK_DB_NOT_CLOSED(self);
2790
2791 MYDB_BEGIN_ALLOW_THREADS;
2792 err = self->db->set_flags(self->db, flags);
2793 MYDB_END_ALLOW_THREADS;
2794 RETURN_IF_ERR();
2795
2796 self->setflags |= flags;
2797 RETURN_NONE();
2798 }
2799
2800 #if (DBVER >= 42)
2801 static PyObject*
2802 DB_get_flags(DBObject* self)
2803 {
2804 int err;
2805 u_int32_t flags;
2806
2807 CHECK_DB_NOT_CLOSED(self);
2808
2809 MYDB_BEGIN_ALLOW_THREADS;
2810 err = self->db->get_flags(self->db, &flags);
2811 MYDB_END_ALLOW_THREADS;
2812 RETURN_IF_ERR();
2813 return NUMBER_FromLong(flags);
2814 }
2815 #endif
2816
2817 static PyObject*
2818 DB_set_h_ffactor(DBObject* self, PyObject* args)
2819 {
2820 int err, ffactor;
2821
2822 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2823 return NULL;
2824 CHECK_DB_NOT_CLOSED(self);
2825
2826 MYDB_BEGIN_ALLOW_THREADS;
2827 err = self->db->set_h_ffactor(self->db, ffactor);
2828 MYDB_END_ALLOW_THREADS;
2829 RETURN_IF_ERR();
2830 RETURN_NONE();
2831 }
2832
2833 #if (DBVER >= 42)
2834 static PyObject*
2835 DB_get_h_ffactor(DBObject* self)
2836 {
2837 int err;
2838 u_int32_t ffactor;
2839
2840 CHECK_DB_NOT_CLOSED(self);
2841
2842 MYDB_BEGIN_ALLOW_THREADS;
2843 err = self->db->get_h_ffactor(self->db, &ffactor);
2844 MYDB_END_ALLOW_THREADS;
2845 RETURN_IF_ERR();
2846 return NUMBER_FromLong(ffactor);
2847 }
2848 #endif
2849
2850 static PyObject*
2851 DB_set_h_nelem(DBObject* self, PyObject* args)
2852 {
2853 int err, nelem;
2854
2855 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2856 return NULL;
2857 CHECK_DB_NOT_CLOSED(self);
2858
2859 MYDB_BEGIN_ALLOW_THREADS;
2860 err = self->db->set_h_nelem(self->db, nelem);
2861 MYDB_END_ALLOW_THREADS;
2862 RETURN_IF_ERR();
2863 RETURN_NONE();
2864 }
2865
2866 #if (DBVER >= 42)
2867 static PyObject*
2868 DB_get_h_nelem(DBObject* self)
2869 {
2870 int err;
2871 u_int32_t nelem;
2872
2873 CHECK_DB_NOT_CLOSED(self);
2874
2875 MYDB_BEGIN_ALLOW_THREADS;
2876 err = self->db->get_h_nelem(self->db, &nelem);
2877 MYDB_END_ALLOW_THREADS;
2878 RETURN_IF_ERR();
2879 return NUMBER_FromLong(nelem);
2880 }
2881 #endif
2882
2883 static PyObject*
2884 DB_set_lorder(DBObject* self, PyObject* args)
2885 {
2886 int err, lorder;
2887
2888 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2889 return NULL;
2890 CHECK_DB_NOT_CLOSED(self);
2891
2892 MYDB_BEGIN_ALLOW_THREADS;
2893 err = self->db->set_lorder(self->db, lorder);
2894 MYDB_END_ALLOW_THREADS;
2895 RETURN_IF_ERR();
2896 RETURN_NONE();
2897 }
2898
2899 #if (DBVER >= 42)
2900 static PyObject*
2901 DB_get_lorder(DBObject* self)
2902 {
2903 int err;
2904 int lorder;
2905
2906 CHECK_DB_NOT_CLOSED(self);
2907
2908 MYDB_BEGIN_ALLOW_THREADS;
2909 err = self->db->get_lorder(self->db, &lorder);
2910 MYDB_END_ALLOW_THREADS;
2911 RETURN_IF_ERR();
2912 return NUMBER_FromLong(lorder);
2913 }
2914 #endif
2915
2916 static PyObject*
2917 DB_set_pagesize(DBObject* self, PyObject* args)
2918 {
2919 int err, pagesize;
2920
2921 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2922 return NULL;
2923 CHECK_DB_NOT_CLOSED(self);
2924
2925 MYDB_BEGIN_ALLOW_THREADS;
2926 err = self->db->set_pagesize(self->db, pagesize);
2927 MYDB_END_ALLOW_THREADS;
2928 RETURN_IF_ERR();
2929 RETURN_NONE();
2930 }
2931
2932 #if (DBVER >= 42)
2933 static PyObject*
2934 DB_get_pagesize(DBObject* self)
2935 {
2936 int err;
2937 u_int32_t pagesize;
2938
2939 CHECK_DB_NOT_CLOSED(self);
2940
2941 MYDB_BEGIN_ALLOW_THREADS;
2942 err = self->db->get_pagesize(self->db, &pagesize);
2943 MYDB_END_ALLOW_THREADS;
2944 RETURN_IF_ERR();
2945 return NUMBER_FromLong(pagesize);
2946 }
2947 #endif
2948
2949 static PyObject*
2950 DB_set_re_delim(DBObject* self, PyObject* args)
2951 {
2952 int err;
2953 char delim;
2954
2955 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2956 PyErr_Clear();
2957 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2958 return NULL;
2959 }
2960
2961 CHECK_DB_NOT_CLOSED(self);
2962
2963 MYDB_BEGIN_ALLOW_THREADS;
2964 err = self->db->set_re_delim(self->db, delim);
2965 MYDB_END_ALLOW_THREADS;
2966 RETURN_IF_ERR();
2967 RETURN_NONE();
2968 }
2969
2970 #if (DBVER >= 42)
2971 static PyObject*
2972 DB_get_re_delim(DBObject* self)
2973 {
2974 int err, re_delim;
2975
2976 CHECK_DB_NOT_CLOSED(self);
2977
2978 MYDB_BEGIN_ALLOW_THREADS;
2979 err = self->db->get_re_delim(self->db, &re_delim);
2980 MYDB_END_ALLOW_THREADS;
2981 RETURN_IF_ERR();
2982 return NUMBER_FromLong(re_delim);
2983 }
2984 #endif
2985
2986 static PyObject*
2987 DB_set_re_len(DBObject* self, PyObject* args)
2988 {
2989 int err, len;
2990
2991 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2992 return NULL;
2993 CHECK_DB_NOT_CLOSED(self);
2994
2995 MYDB_BEGIN_ALLOW_THREADS;
2996 err = self->db->set_re_len(self->db, len);
2997 MYDB_END_ALLOW_THREADS;
2998 RETURN_IF_ERR();
2999 RETURN_NONE();
3000 }
3001
3002 #if (DBVER >= 42)
3003 static PyObject*
3004 DB_get_re_len(DBObject* self)
3005 {
3006 int err;
3007 u_int32_t re_len;
3008
3009 CHECK_DB_NOT_CLOSED(self);
3010
3011 MYDB_BEGIN_ALLOW_THREADS;
3012 err = self->db->get_re_len(self->db, &re_len);
3013 MYDB_END_ALLOW_THREADS;
3014 RETURN_IF_ERR();
3015 return NUMBER_FromLong(re_len);
3016 }
3017 #endif
3018
3019 static PyObject*
3020 DB_set_re_pad(DBObject* self, PyObject* args)
3021 {
3022 int err;
3023 char pad;
3024
3025 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
3026 PyErr_Clear();
3027 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
3028 return NULL;
3029 }
3030 CHECK_DB_NOT_CLOSED(self);
3031
3032 MYDB_BEGIN_ALLOW_THREADS;
3033 err = self->db->set_re_pad(self->db, pad);
3034 MYDB_END_ALLOW_THREADS;
3035 RETURN_IF_ERR();
3036 RETURN_NONE();
3037 }
3038
3039 #if (DBVER >= 42)
3040 static PyObject*
3041 DB_get_re_pad(DBObject* self)
3042 {
3043 int err, re_pad;
3044
3045 CHECK_DB_NOT_CLOSED(self);
3046
3047 MYDB_BEGIN_ALLOW_THREADS;
3048 err = self->db->get_re_pad(self->db, &re_pad);
3049 MYDB_END_ALLOW_THREADS;
3050 RETURN_IF_ERR();
3051 return NUMBER_FromLong(re_pad);
3052 }
3053 #endif
3054
3055 static PyObject*
3056 DB_set_re_source(DBObject* self, PyObject* args)
3057 {
3058 int err;
3059 char *source;
3060
3061 if (!PyArg_ParseTuple(args,"s:set_re_source", &source))
3062 return NULL;
3063 CHECK_DB_NOT_CLOSED(self);
3064
3065 MYDB_BEGIN_ALLOW_THREADS;
3066 err = self->db->set_re_source(self->db, source);
3067 MYDB_END_ALLOW_THREADS;
3068 RETURN_IF_ERR();
3069 RETURN_NONE();
3070 }
3071
3072 #if (DBVER >= 42)
3073 static PyObject*
3074 DB_get_re_source(DBObject* self)
3075 {
3076 int err;
3077 const char *source;
3078
3079 CHECK_DB_NOT_CLOSED(self);
3080
3081 MYDB_BEGIN_ALLOW_THREADS;
3082 err = self->db->get_re_source(self->db, &source);
3083 MYDB_END_ALLOW_THREADS;
3084 RETURN_IF_ERR();
3085 return PyBytes_FromString(source);
3086 }
3087 #endif
3088
3089 static PyObject*
3090 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
3091 {
3092 int err, flags = 0, type;
3093 void* sp;
3094 PyObject* d;
3095 #if (DBVER >= 43)
3096 PyObject* txnobj = NULL;
3097 DB_TXN *txn = NULL;
3098 static char* kwnames[] = { "flags", "txn", NULL };
3099 #else
3100 static char* kwnames[] = { "flags", NULL };
3101 #endif
3102
3103 #if (DBVER >= 43)
3104 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
3105 &flags, &txnobj))
3106 return NULL;
3107 if (!checkTxnObj(txnobj, &txn))
3108 return NULL;
3109 #else
3110 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
3111 return NULL;
3112 #endif
3113 CHECK_DB_NOT_CLOSED(self);
3114
3115 MYDB_BEGIN_ALLOW_THREADS;
3116 #if (DBVER >= 43)
3117 err = self->db->stat(self->db, txn, &sp, flags);
3118 #else
3119 err = self->db->stat(self->db, &sp, flags);
3120 #endif
3121 MYDB_END_ALLOW_THREADS;
3122 RETURN_IF_ERR();
3123
3124 /* Turn the stat structure into a dictionary */
3125 type = _DB_get_type(self);
3126 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
3127 free(sp);
3128 return NULL;
3129 }
3130
3131 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
3132 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
3133 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
3134
3135 switch (type) {
3136 case DB_HASH:
3137 MAKE_HASH_ENTRY(magic);
3138 MAKE_HASH_ENTRY(version);
3139 MAKE_HASH_ENTRY(nkeys);
3140 MAKE_HASH_ENTRY(ndata);
3141 #if (DBVER >= 46)
3142 MAKE_HASH_ENTRY(pagecnt);
3143 #endif
3144 MAKE_HASH_ENTRY(pagesize);
3145 MAKE_HASH_ENTRY(ffactor);
3146 MAKE_HASH_ENTRY(buckets);
3147 MAKE_HASH_ENTRY(free);
3148 MAKE_HASH_ENTRY(bfree);
3149 MAKE_HASH_ENTRY(bigpages);
3150 MAKE_HASH_ENTRY(big_bfree);
3151 MAKE_HASH_ENTRY(overflows);
3152 MAKE_HASH_ENTRY(ovfl_free);
3153 MAKE_HASH_ENTRY(dup);
3154 MAKE_HASH_ENTRY(dup_free);
3155 break;
3156
3157 case DB_BTREE:
3158 case DB_RECNO:
3159 MAKE_BT_ENTRY(magic);
3160 MAKE_BT_ENTRY(version);
3161 MAKE_BT_ENTRY(nkeys);
3162 MAKE_BT_ENTRY(ndata);
3163 #if (DBVER >= 46)
3164 MAKE_BT_ENTRY(pagecnt);
3165 #endif
3166 MAKE_BT_ENTRY(pagesize);
3167 MAKE_BT_ENTRY(minkey);
3168 MAKE_BT_ENTRY(re_len);
3169 MAKE_BT_ENTRY(re_pad);
3170 MAKE_BT_ENTRY(levels);
3171 MAKE_BT_ENTRY(int_pg);
3172 MAKE_BT_ENTRY(leaf_pg);
3173 MAKE_BT_ENTRY(dup_pg);
3174 MAKE_BT_ENTRY(over_pg);
3175 #if (DBVER >= 43)
3176 MAKE_BT_ENTRY(empty_pg);
3177 #endif
3178 MAKE_BT_ENTRY(free);
3179 MAKE_BT_ENTRY(int_pgfree);
3180 MAKE_BT_ENTRY(leaf_pgfree);
3181 MAKE_BT_ENTRY(dup_pgfree);
3182 MAKE_BT_ENTRY(over_pgfree);
3183 break;
3184
3185 case DB_QUEUE:
3186 MAKE_QUEUE_ENTRY(magic);
3187 MAKE_QUEUE_ENTRY(version);
3188 MAKE_QUEUE_ENTRY(nkeys);
3189 MAKE_QUEUE_ENTRY(ndata);
3190 MAKE_QUEUE_ENTRY(pagesize);
3191 MAKE_QUEUE_ENTRY(extentsize);
3192 MAKE_QUEUE_ENTRY(pages);
3193 MAKE_QUEUE_ENTRY(re_len);
3194 MAKE_QUEUE_ENTRY(re_pad);
3195 MAKE_QUEUE_ENTRY(pgfree);
3196 #if (DBVER == 31)
3197 MAKE_QUEUE_ENTRY(start);
3198 #endif
3199 MAKE_QUEUE_ENTRY(first_recno);
3200 MAKE_QUEUE_ENTRY(cur_recno);
3201 break;
3202
3203 default:
3204 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
3205 Py_DECREF(d);
3206 d = NULL;
3207 }
3208
3209 #undef MAKE_HASH_ENTRY
3210 #undef MAKE_BT_ENTRY
3211 #undef MAKE_QUEUE_ENTRY
3212
3213 free(sp);
3214 return d;
3215 }
3216
3217 #if (DBVER >= 43)
3218 static PyObject*
3219 DB_stat_print(DBObject* self, PyObject* args, PyObject *kwargs)
3220 {
3221 int err;
3222 int flags=0;
3223 static char* kwnames[] = { "flags", NULL };
3224
3225 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
3226 kwnames, &flags))
3227 {
3228 return NULL;
3229 }
3230 CHECK_DB_NOT_CLOSED(self);
3231 MYDB_BEGIN_ALLOW_THREADS;
3232 err = self->db->stat_print(self->db, flags);
3233 MYDB_END_ALLOW_THREADS;
3234 RETURN_IF_ERR();
3235 RETURN_NONE();
3236 }
3237 #endif
3238
3239
3240 static PyObject*
3241 DB_sync(DBObject* self, PyObject* args)
3242 {
3243 int err;
3244 int flags = 0;
3245
3246 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
3247 return NULL;
3248 CHECK_DB_NOT_CLOSED(self);
3249
3250 MYDB_BEGIN_ALLOW_THREADS;
3251 err = self->db->sync(self->db, flags);
3252 MYDB_END_ALLOW_THREADS;
3253 RETURN_IF_ERR();
3254 RETURN_NONE();
3255 }
3256
3257
3258 static PyObject*
3259 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
3260 {
3261 int err, flags=0;
3262 u_int32_t count=0;
3263 PyObject* txnobj = NULL;
3264 DB_TXN *txn = NULL;
3265 static char* kwnames[] = { "txn", "flags", NULL };
3266
3267 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
3268 &txnobj, &flags))
3269 return NULL;
3270 CHECK_DB_NOT_CLOSED(self);
3271 if (!checkTxnObj(txnobj, &txn))
3272 return NULL;
3273
3274 MYDB_BEGIN_ALLOW_THREADS;
3275 err = self->db->truncate(self->db, txn, &count, flags);
3276 MYDB_END_ALLOW_THREADS;
3277 RETURN_IF_ERR();
3278 return NUMBER_FromLong(count);
3279 }
3280
3281
3282 static PyObject*
3283 DB_upgrade(DBObject* self, PyObject* args)
3284 {
3285 int err, flags=0;
3286 char *filename;
3287
3288 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
3289 return NULL;
3290 CHECK_DB_NOT_CLOSED(self);
3291
3292 MYDB_BEGIN_ALLOW_THREADS;
3293 err = self->db->upgrade(self->db, filename, flags);
3294 MYDB_END_ALLOW_THREADS;
3295 RETURN_IF_ERR();
3296 RETURN_NONE();
3297 }
3298
3299
3300 static PyObject*
3301 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
3302 {
3303 int err, flags=0;
3304 char* fileName;
3305 char* dbName=NULL;
3306 char* outFileName=NULL;
3307 FILE* outFile=NULL;
3308 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
3309 NULL };
3310
3311 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
3312 &fileName, &dbName, &outFileName, &flags))
3313 return NULL;
3314
3315 CHECK_DB_NOT_CLOSED(self);
3316 if (outFileName)
3317 outFile = fopen(outFileName, "w");
3318 /* XXX(nnorwitz): it should probably be an exception if outFile
3319 can't be opened. */
3320
3321 { /* DB.verify acts as a DB handle destructor (like close) */
3322 PyObject *error;
3323
3324 error=DB_close_internal(self, 0, 1);
3325 if (error) {
3326 return error;
Resource leak: outFile
(emitted by cppcheck)
Resource leak: outFile
(emitted by cppcheck)
3327 }
3328 }
3329
3330 MYDB_BEGIN_ALLOW_THREADS;
3331 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
3332 MYDB_END_ALLOW_THREADS;
3333
3334 self->db = NULL; /* Implicit close; related objects already released */
3335
3336 if (outFile)
3337 fclose(outFile);
3338
3339 RETURN_IF_ERR();
3340 RETURN_NONE();
3341 }
3342
3343
3344 static PyObject*
3345 DB_set_get_returns_none(DBObject* self, PyObject* args)
3346 {
3347 int flags=0;
3348 int oldValue=0;
3349
3350 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
3351 return NULL;
3352 CHECK_DB_NOT_CLOSED(self);
3353
3354 if (self->moduleFlags.getReturnsNone)
3355 ++oldValue;
3356 if (self->moduleFlags.cursorSetReturnsNone)
3357 ++oldValue;
3358 self->moduleFlags.getReturnsNone = (flags >= 1);
3359 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
3360 return NUMBER_FromLong(oldValue);
3361 }
3362
3363 static PyObject*
3364 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
3365 {
3366 int err;
3367 u_int32_t flags=0;
3368 char *passwd = NULL;
3369 static char* kwnames[] = { "passwd", "flags", NULL };
3370
3371 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3372 &passwd, &flags)) {
3373 return NULL;
3374 }
3375
3376 MYDB_BEGIN_ALLOW_THREADS;
3377 err = self->db->set_encrypt(self->db, passwd, flags);
3378 MYDB_END_ALLOW_THREADS;
3379
3380 RETURN_IF_ERR();
3381 RETURN_NONE();
3382 }
3383
3384 #if (DBVER >= 42)
3385 static PyObject*
3386 DB_get_encrypt_flags(DBObject* self)
3387 {
3388 int err;
3389 u_int32_t flags;
3390
3391 MYDB_BEGIN_ALLOW_THREADS;
3392 err = self->db->get_encrypt_flags(self->db, &flags);
3393 MYDB_END_ALLOW_THREADS;
3394
3395 RETURN_IF_ERR();
3396
3397 return NUMBER_FromLong(flags);
3398 }
3399 #endif
3400
3401
3402
3403 /*-------------------------------------------------------------- */
3404 /* Mapping and Dictionary-like access routines */
3405
3406 Py_ssize_t DB_length(PyObject* _self)
3407 {
3408 int err;
3409 Py_ssize_t size = 0;
3410 void* sp;
3411 DBObject* self = (DBObject*)_self;
3412
3413 if (self->db == NULL) {
3414 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
3415 if (t) {
3416 PyErr_SetObject(DBError, t);
3417 Py_DECREF(t);
3418 }
3419 return -1;
3420 }
3421
3422 MYDB_BEGIN_ALLOW_THREADS;
3423 #if (DBVER >= 43)
3424 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, 0);
3425 #else
3426 err = self->db->stat(self->db, &sp, 0);
3427 #endif
3428 MYDB_END_ALLOW_THREADS;
3429
3430 /* All the stat structures have matching fields upto the ndata field,
3431 so we can use any of them for the type cast */
3432 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
3433
3434 if (err)
3435 return -1;
3436
3437 free(sp);
3438 return size;
3439 }
3440
3441
3442 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
3443 {
3444 int err;
3445 PyObject* retval;
3446 DBT key;
3447 DBT data;
3448
3449 CHECK_DB_NOT_CLOSED(self);
3450 if (!make_key_dbt(self, keyobj, &key, NULL))
3451 return NULL;
3452
3453 CLEAR_DBT(data);
3454 if (CHECK_DBFLAG(self, DB_THREAD)) {
3455 /* Tell Berkeley DB to malloc the return value (thread safe) */
3456 data.flags = DB_DBT_MALLOC;
3457 }
3458 MYDB_BEGIN_ALLOW_THREADS;
3459 err = self->db->get(self->db, NULL, &key, &data, 0);
3460 MYDB_END_ALLOW_THREADS;
3461 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3462 PyErr_SetObject(PyExc_KeyError, keyobj);
3463 retval = NULL;
3464 }
3465 else if (makeDBError(err)) {
3466 retval = NULL;
3467 }
3468 else {
3469 retval = Build_PyString(data.data, data.size);
3470 FREE_DBT(data);
3471 }
3472
3473 FREE_DBT(key);
3474 return retval;
3475 }
3476
3477
3478 static int
3479 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
3480 {
3481 DBT key, data;
3482 int retval;
3483 int flags = 0;
3484
3485 if (self->db == NULL) {
3486 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
3487 if (t) {
3488 PyErr_SetObject(DBError, t);
3489 Py_DECREF(t);
3490 }
3491 return -1;
3492 }
3493
3494 if (!make_key_dbt(self, keyobj, &key, NULL))
3495 return -1;
3496
3497 if (dataobj != NULL) {
3498 if (!make_dbt(dataobj, &data))
3499 retval = -1;
3500 else {
3501 if (self->setflags & (DB_DUP|DB_DUPSORT))
3502 /* dictionaries shouldn't have duplicate keys */
3503 flags = DB_NOOVERWRITE;
3504 retval = _DB_put(self, NULL, &key, &data, flags);
3505
3506 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
3507 /* try deleting any old record that matches and then PUT it
3508 * again... */
3509 _DB_delete(self, NULL, &key, 0);
3510 PyErr_Clear();
3511 retval = _DB_put(self, NULL, &key, &data, flags);
3512 }
3513 }
3514 }
3515 else {
3516 /* dataobj == NULL, so delete the key */
3517 retval = _DB_delete(self, NULL, &key, 0);
3518 }
3519 FREE_DBT(key);
3520 return retval;
3521 }
3522
3523
3524 static PyObject*
3525 _DB_has_key(DBObject* self, PyObject* keyobj, PyObject* txnobj)
3526 {
3527 int err;
3528 DBT key;
3529 DB_TXN *txn = NULL;
3530
3531 CHECK_DB_NOT_CLOSED(self);
3532 if (!make_key_dbt(self, keyobj, &key, NULL))
3533 return NULL;
3534 if (!checkTxnObj(txnobj, &txn)) {
3535 FREE_DBT(key);
3536 return NULL;
3537 }
3538
3539 #if (DBVER < 46)
3540 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
3541 it has a record but can't allocate a buffer for the data. This saves
3542 having to deal with data we won't be using.
3543 */
3544 {
3545 DBT data ;
3546 CLEAR_DBT(data);
3547 data.flags = DB_DBT_USERMEM;
3548
3549 MYDB_BEGIN_ALLOW_THREADS;
3550 err = self->db->get(self->db, txn, &key, &data, 0);
3551 MYDB_END_ALLOW_THREADS;
3552 }
3553 #else
3554 MYDB_BEGIN_ALLOW_THREADS;
3555 err = self->db->exists(self->db, txn, &key, 0);
3556 MYDB_END_ALLOW_THREADS;
3557 #endif
3558
3559 FREE_DBT(key);
3560
3561 /*
3562 ** DB_BUFFER_SMALL is only used if we use "get".
3563 ** We can drop it when we only use "exists",
3564 ** when we drop suport for Berkeley DB < 4.6.
3565 */
3566 if (err == DB_BUFFER_SMALL || err == 0) {
3567 Py_INCREF(Py_True);
3568 return Py_True;
3569 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3570 Py_INCREF(Py_False);
3571 return Py_False;
3572 }
3573
3574 makeDBError(err);
3575 return NULL;
3576 }
3577
3578 static PyObject*
3579 DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
3580 {
3581 PyObject* keyobj;
3582 PyObject* txnobj = NULL;
3583 static char* kwnames[] = {"key","txn", NULL};
3584
3585 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
3586 &keyobj, &txnobj))
3587 return NULL;
3588
3589 return _DB_has_key(self, keyobj, txnobj);
3590 }
3591
3592
3593 static int DB_contains(DBObject* self, PyObject* keyobj)
3594 {
3595 PyObject* result;
3596 int result2 = 0;
3597
3598 result = _DB_has_key(self, keyobj, NULL) ;
3599 if (result == NULL) {
3600 return -1; /* Propague exception */
3601 }
3602 if (result != Py_False) {
3603 result2 = 1;
3604 }
3605
3606 Py_DECREF(result);
3607 return result2;
3608 }
3609
3610
3611 #define _KEYS_LIST 1
3612 #define _VALUES_LIST 2
3613 #define _ITEMS_LIST 3
3614
3615 static PyObject*
3616 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
3617 {
3618 int err, dbtype;
3619 DBT key;
3620 DBT data;
3621 DBC *cursor;
3622 PyObject* list;
3623 PyObject* item = NULL;
3624
3625 CHECK_DB_NOT_CLOSED(self);
3626 CLEAR_DBT(key);
3627 CLEAR_DBT(data);
3628
3629 dbtype = _DB_get_type(self);
3630 if (dbtype == -1)
3631 return NULL;
3632
3633 list = PyList_New(0);
3634 if (list == NULL)
3635 return NULL;
3636
3637 /* get a cursor */
3638 MYDB_BEGIN_ALLOW_THREADS;
3639 err = self->db->cursor(self->db, txn, &cursor, 0);
3640 MYDB_END_ALLOW_THREADS;
3641 if (makeDBError(err)) {
3642 Py_DECREF(list);
3643 return NULL;
3644 }
3645
3646 while (1) { /* use the cursor to traverse the DB, collecting items */
3647 MYDB_BEGIN_ALLOW_THREADS;
3648 err = _DBC_get(cursor, &key, &data, DB_NEXT);
3649 MYDB_END_ALLOW_THREADS;
3650
3651 if (err) {
3652 /* for any error, break out of the loop */
3653 break;
3654 }
3655
3656 switch (type) {
3657 case _KEYS_LIST:
3658 switch(dbtype) {
3659 case DB_BTREE:
3660 case DB_HASH:
3661 default:
3662 item = Build_PyString(key.data, key.size);
3663 break;
3664 case DB_RECNO:
3665 case DB_QUEUE:
3666 item = NUMBER_FromLong(*((db_recno_t*)key.data));
3667 break;
3668 }
3669 break;
3670
3671 case _VALUES_LIST:
3672 item = Build_PyString(data.data, data.size);
3673 break;
3674
3675 case _ITEMS_LIST:
3676 switch(dbtype) {
3677 case DB_BTREE:
3678 case DB_HASH:
3679 default:
3680 item = BuildValue_SS(key.data, key.size, data.data, data.size);
3681 break;
3682 case DB_RECNO:
3683 case DB_QUEUE:
3684 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3685 break;
3686 }
3687 break;
3688 default:
3689 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3690 item = NULL;
3691 break;
3692 }
3693 if (item == NULL) {
3694 Py_DECREF(list);
3695 list = NULL;
3696 goto done;
3697 }
3698 if (PyList_Append(list, item)) {
3699 Py_DECREF(list);
3700 Py_DECREF(item);
3701 list = NULL;
3702 goto done;
3703 }
3704 Py_DECREF(item);
3705 }
3706
3707 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3708 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
3709 Py_DECREF(list);
3710 list = NULL;
3711 }
3712
3713 done:
3714 MYDB_BEGIN_ALLOW_THREADS;
3715 _DBC_close(cursor);
3716 MYDB_END_ALLOW_THREADS;
3717 return list;
3718 }
3719
3720
3721 static PyObject*
3722 DB_keys(DBObject* self, PyObject* args)
3723 {
3724 PyObject* txnobj = NULL;
3725 DB_TXN *txn = NULL;
3726
3727 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
3728 return NULL;
3729 if (!checkTxnObj(txnobj, &txn))
3730 return NULL;
3731 return _DB_make_list(self, txn, _KEYS_LIST);
3732 }
3733
3734
3735 static PyObject*
3736 DB_items(DBObject* self, PyObject* args)
3737 {
3738 PyObject* txnobj = NULL;
3739 DB_TXN *txn = NULL;
3740
3741 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
3742 return NULL;
3743 if (!checkTxnObj(txnobj, &txn))
3744 return NULL;
3745 return _DB_make_list(self, txn, _ITEMS_LIST);
3746 }
3747
3748
3749 static PyObject*
3750 DB_values(DBObject* self, PyObject* args)
3751 {
3752 PyObject* txnobj = NULL;
3753 DB_TXN *txn = NULL;
3754
3755 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
3756 return NULL;
3757 if (!checkTxnObj(txnobj, &txn))
3758 return NULL;
3759 return _DB_make_list(self, txn, _VALUES_LIST);
3760 }
3761
3762 /* --------------------------------------------------------------------- */
3763 /* DBLogCursor methods */
3764
3765
3766 static PyObject*
3767 DBLogCursor_close_internal(DBLogCursorObject* self)
3768 {
3769 int err = 0;
3770
3771 if (self->logc != NULL) {
3772 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3773
3774 MYDB_BEGIN_ALLOW_THREADS;
3775 err = self->logc->close(self->logc, 0);
3776 MYDB_END_ALLOW_THREADS;
3777 self->logc = NULL;
3778 }
3779 RETURN_IF_ERR();
3780 RETURN_NONE();
3781 }
3782
3783 static PyObject*
3784 DBLogCursor_close(DBLogCursorObject* self)
3785 {
3786 return DBLogCursor_close_internal(self);
3787 }
3788
3789
3790 static PyObject*
3791 _DBLogCursor_get(DBLogCursorObject* self, int flag, DB_LSN *lsn2)
3792 {
3793 int err;
3794 DBT data;
3795 DB_LSN lsn = {0, 0};
3796 PyObject *dummy, *retval;
3797
3798 CLEAR_DBT(data);
3799 data.flags = DB_DBT_MALLOC; /* Berkeley DB must do the malloc */
3800
3801 CHECK_LOGCURSOR_NOT_CLOSED(self);
3802
3803 if (lsn2)
3804 lsn = *lsn2;
3805
3806 MYDB_BEGIN_ALLOW_THREADS;
3807 err = self->logc->get(self->logc, &lsn, &data, flag);
3808 MYDB_END_ALLOW_THREADS;
3809
3810 if (err == DB_NOTFOUND) {
3811 Py_INCREF(Py_None);
3812 retval = Py_None;
3813 }
3814 else if (makeDBError(err)) {
3815 retval = NULL;
3816 }
3817 else {
3818 retval = dummy = BuildValue_S(data.data, data.size);
3819 if (dummy) {
3820 retval = Py_BuildValue("(ii)O", lsn.file, lsn.offset, dummy);
3821 Py_DECREF(dummy);
3822 }
3823 }
3824
3825 FREE_DBT(data);
3826 return retval;
3827 }
3828
3829 static PyObject*
3830 DBLogCursor_current(DBLogCursorObject* self)
3831 {
3832 return _DBLogCursor_get(self, DB_CURRENT, NULL);
3833 }
3834
3835 static PyObject*
3836 DBLogCursor_first(DBLogCursorObject* self)
3837 {
3838 return _DBLogCursor_get(self, DB_FIRST, NULL);
3839 }
3840
3841 static PyObject*
3842 DBLogCursor_last(DBLogCursorObject* self)
3843 {
3844 return _DBLogCursor_get(self, DB_LAST, NULL);
3845 }
3846
3847 static PyObject*
3848 DBLogCursor_next(DBLogCursorObject* self)
3849 {
3850 return _DBLogCursor_get(self, DB_NEXT, NULL);
3851 }
3852
3853 static PyObject*
3854 DBLogCursor_prev(DBLogCursorObject* self)
3855 {
3856 return _DBLogCursor_get(self, DB_PREV, NULL);
3857 }
3858
3859 static PyObject*
3860 DBLogCursor_set(DBLogCursorObject* self, PyObject* args)
3861 {
3862 DB_LSN lsn;
3863
3864 if (!PyArg_ParseTuple(args, "(ii):set", &lsn.file, &lsn.offset))
3865 return NULL;
3866
3867 return _DBLogCursor_get(self, DB_SET, &lsn);
3868 }
3869
3870
3871
3872 /* --------------------------------------------------------------------- */
3873 /* DBCursor methods */
3874
3875
3876 static PyObject*
3877 DBC_close_internal(DBCursorObject* self)
3878 {
3879 int err = 0;
3880
3881 if (self->dbc != NULL) {
3882 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3883 if (self->txn) {
3884 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3885 self->txn=NULL;
3886 }
3887
3888 MYDB_BEGIN_ALLOW_THREADS;
3889 err = _DBC_close(self->dbc);
3890 MYDB_END_ALLOW_THREADS;
3891 self->dbc = NULL;
3892 }
3893 RETURN_IF_ERR();
3894 RETURN_NONE();
3895 }
3896
3897 static PyObject*
3898 DBC_close(DBCursorObject* self)
3899 {
3900 return DBC_close_internal(self);
3901 }
3902
3903
3904 static PyObject*
3905 DBC_count(DBCursorObject* self, PyObject* args)
3906 {
3907 int err = 0;
3908 db_recno_t count;
3909 int flags = 0;
3910
3911 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3912 return NULL;
3913
3914 CHECK_CURSOR_NOT_CLOSED(self);
3915
3916 MYDB_BEGIN_ALLOW_THREADS;
3917 err = _DBC_count(self->dbc, &count, flags);
3918 MYDB_END_ALLOW_THREADS;
3919 RETURN_IF_ERR();
3920
3921 return NUMBER_FromLong(count);
3922 }
3923
3924
3925 static PyObject*
3926 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3927 {
3928 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3929 }
3930
3931
3932 static PyObject*
3933 DBC_delete(DBCursorObject* self, PyObject* args)
3934 {
3935 int err, flags=0;
3936
3937 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3938 return NULL;
3939
3940 CHECK_CURSOR_NOT_CLOSED(self);
3941
3942 MYDB_BEGIN_ALLOW_THREADS;
3943 err = _DBC_del(self->dbc, flags);
3944 MYDB_END_ALLOW_THREADS;
3945 RETURN_IF_ERR();
3946
3947 RETURN_NONE();
3948 }
3949
3950
3951 static PyObject*
3952 DBC_dup(DBCursorObject* self, PyObject* args)
3953 {
3954 int err, flags =0;
3955 DBC* dbc = NULL;
3956
3957 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3958 return NULL;
3959
3960 CHECK_CURSOR_NOT_CLOSED(self);
3961
3962 MYDB_BEGIN_ALLOW_THREADS;
3963 err = _DBC_dup(self->dbc, &dbc, flags);
3964 MYDB_END_ALLOW_THREADS;
3965 RETURN_IF_ERR();
3966
3967 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
3968 }
3969
3970 static PyObject*
3971 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3972 {
3973 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3974 }
3975
3976
3977 static PyObject*
3978 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3979 {
3980 int err, flags=0;
3981 PyObject* keyobj = NULL;
3982 PyObject* dataobj = NULL;
3983 PyObject* retval = NULL;
3984 int dlen = -1;
3985 int doff = -1;
3986 DBT key, data;
3987 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3988 NULL };
3989
3990 CLEAR_DBT(key);
3991 CLEAR_DBT(data);
3992 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3993 &flags, &dlen, &doff))
3994 {
3995 PyErr_Clear();
3996 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3997 &kwnames[1],
3998 &keyobj, &flags, &dlen, &doff))
3999 {
4000 PyErr_Clear();
4001 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
4002 kwnames, &keyobj, &dataobj,
4003 &flags, &dlen, &doff))
4004 {
4005 return NULL;
4006 }
4007 }
4008 }
4009
4010 CHECK_CURSOR_NOT_CLOSED(self);
4011
4012 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
4013 return NULL;
4014 if ( (dataobj && !make_dbt(dataobj, &data)) ||
4015 (!add_partial_dbt(&data, dlen, doff)) )
4016 {
4017 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4018 return NULL;
4019 }
4020
4021 MYDB_BEGIN_ALLOW_THREADS;
4022 err = _DBC_get(self->dbc, &key, &data, flags);
4023 MYDB_END_ALLOW_THREADS;
4024
4025 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
4026 && self->mydb->moduleFlags.getReturnsNone) {
4027 Py_INCREF(Py_None);
4028 retval = Py_None;
4029 }
4030 else if (makeDBError(err)) {
4031 retval = NULL;
4032 }
4033 else {
4034 switch (_DB_get_type(self->mydb)) {
4035 case -1:
4036 retval = NULL;
4037 break;
4038 case DB_BTREE:
4039 case DB_HASH:
4040 default:
4041 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
4042 break;
4043 case DB_RECNO:
4044 case DB_QUEUE:
4045 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
4046 break;
4047 }
4048 }
4049 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4050 return retval;
4051 }
4052
4053 static PyObject*
4054 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
4055 {
4056 int err, flags=0;
4057 PyObject* keyobj = NULL;
4058 PyObject* dataobj = NULL;
4059 PyObject* retval = NULL;
4060 int dlen = -1;
4061 int doff = -1;
4062 DBT key, pkey, data;
4063 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
4064 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
4065
4066 CLEAR_DBT(key);
4067 CLEAR_DBT(data);
4068 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
4069 &flags, &dlen, &doff))
4070 {
4071 PyErr_Clear();
4072 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
4073 kwnames_keyOnly,
4074 &keyobj, &flags, &dlen, &doff))
4075 {
4076 PyErr_Clear();
4077 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
4078 kwnames, &keyobj, &dataobj,
4079 &flags, &dlen, &doff))
4080 {
4081 return NULL;
4082 }
4083 }
4084 }
4085
4086 CHECK_CURSOR_NOT_CLOSED(self);
4087
4088 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
4089 return NULL;
4090 if ( (dataobj && !make_dbt(dataobj, &data)) ||
4091 (!add_partial_dbt(&data, dlen, doff)) ) {
4092 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4093 return NULL;
4094 }
4095
4096 CLEAR_DBT(pkey);
4097 pkey.flags = DB_DBT_MALLOC;
4098
4099 MYDB_BEGIN_ALLOW_THREADS;
4100 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
4101 MYDB_END_ALLOW_THREADS;
4102
4103 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
4104 && self->mydb->moduleFlags.getReturnsNone) {
4105 Py_INCREF(Py_None);
4106 retval = Py_None;
4107 }
4108 else if (makeDBError(err)) {
4109 retval = NULL;
4110 }
4111 else {
4112 PyObject *pkeyObj;
4113 PyObject *dataObj;
4114 dataObj = Build_PyString(data.data, data.size);
4115
4116 if (self->mydb->primaryDBType == DB_RECNO ||
4117 self->mydb->primaryDBType == DB_QUEUE)
4118 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
4119 else
4120 pkeyObj = Build_PyString(pkey.data, pkey.size);
4121
4122 if (key.data && key.size) /* return key, pkey and data */
4123 {
4124 PyObject *keyObj;
4125 int type = _DB_get_type(self->mydb);
4126 if (type == DB_RECNO || type == DB_QUEUE)
4127 keyObj = NUMBER_FromLong(*(int *)key.data);
4128 else
4129 keyObj = Build_PyString(key.data, key.size);
4130 #if (PY_VERSION_HEX >= 0x02040000)
4131 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
4132 #else
4133 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
4134 #endif
4135 Py_DECREF(keyObj);
4136 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4137 }
4138 else /* return just the pkey and data */
4139 {
4140 #if (PY_VERSION_HEX >= 0x02040000)
4141 retval = PyTuple_Pack(2, pkeyObj, dataObj);
4142 #else
4143 retval = Py_BuildValue("OO", pkeyObj, dataObj);
4144 #endif
4145 }
4146 Py_DECREF(dataObj);
4147 Py_DECREF(pkeyObj);
4148 FREE_DBT(pkey);
4149 }
4150 /* the only time REALLOC should be set is if we used an integer
4151 * key that make_key_dbt malloc'd for us. always free these. */
4152 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
4153 FREE_DBT(key);
4154 }
4155 return retval;
4156 }
4157
4158
4159 static PyObject*
4160 DBC_get_recno(DBCursorObject* self)
4161 {
4162 int err;
4163 db_recno_t recno;
4164 DBT key;
4165 DBT data;
4166
4167 CHECK_CURSOR_NOT_CLOSED(self);
4168
4169 CLEAR_DBT(key);
4170 CLEAR_DBT(data);
4171
4172 MYDB_BEGIN_ALLOW_THREADS;
4173 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
4174 MYDB_END_ALLOW_THREADS;
4175 RETURN_IF_ERR();
4176
4177 recno = *((db_recno_t*)data.data);
4178 return NUMBER_FromLong(recno);
4179 }
4180
4181
4182 static PyObject*
4183 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
4184 {
4185 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
4186 }
4187
4188
4189 static PyObject*
4190 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
4191 {
4192 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
4193 }
4194
4195
4196 static PyObject*
4197 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
4198 {
4199 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
4200 }
4201
4202
4203 static PyObject*
4204 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
4205 {
4206 int err, flags = 0;
4207 PyObject* keyobj, *dataobj;
4208 DBT key, data;
4209 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
4210 NULL };
4211 int dlen = -1;
4212 int doff = -1;
4213
4214 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
4215 &keyobj, &dataobj, &flags, &dlen, &doff))
4216 return NULL;
4217
4218 CHECK_CURSOR_NOT_CLOSED(self);
4219
4220 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4221 return NULL;
4222 if (!make_dbt(dataobj, &data) ||
4223 !add_partial_dbt(&data, dlen, doff) )
4224 {
4225 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4226 return NULL;
4227 }
4228
4229 MYDB_BEGIN_ALLOW_THREADS;
4230 err = _DBC_put(self->dbc, &key, &data, flags);
4231 MYDB_END_ALLOW_THREADS;
4232 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4233 RETURN_IF_ERR();
4234 RETURN_NONE();
4235 }
4236
4237
4238 static PyObject*
4239 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
4240 {
4241 int err, flags = 0;
4242 DBT key, data;
4243 PyObject* retval, *keyobj;
4244 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
4245 int dlen = -1;
4246 int doff = -1;
4247
4248 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
4249 &keyobj, &flags, &dlen, &doff))
4250 return NULL;
4251
4252 CHECK_CURSOR_NOT_CLOSED(self);
4253
4254 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4255 return NULL;
4256
4257 CLEAR_DBT(data);
4258 if (!add_partial_dbt(&data, dlen, doff)) {
4259 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4260 return NULL;
4261 }
4262
4263 MYDB_BEGIN_ALLOW_THREADS;
4264 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
4265 MYDB_END_ALLOW_THREADS;
4266 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
4267 && self->mydb->moduleFlags.cursorSetReturnsNone) {
4268 Py_INCREF(Py_None);
4269 retval = Py_None;
4270 }
4271 else if (makeDBError(err)) {
4272 retval = NULL;
4273 }
4274 else {
4275 switch (_DB_get_type(self->mydb)) {
4276 case -1:
4277 retval = NULL;
4278 break;
4279 case DB_BTREE:
4280 case DB_HASH:
4281 default:
4282 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
4283 break;
4284 case DB_RECNO:
4285 case DB_QUEUE:
4286 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
4287 break;
4288 }
4289 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4290 }
4291 /* the only time REALLOC should be set is if we used an integer
4292 * key that make_key_dbt malloc'd for us. always free these. */
4293 if (key.flags & DB_DBT_REALLOC) {
4294 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4295 }
4296
4297 return retval;
4298 }
4299
4300
4301 static PyObject*
4302 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
4303 {
4304 int err, flags = 0;
4305 DBT key, data;
4306 PyObject* retval, *keyobj;
4307 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
4308 int dlen = -1;
4309 int doff = -1;
4310
4311 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
4312 &keyobj, &flags, &dlen, &doff))
4313 return NULL;
4314
4315 CHECK_CURSOR_NOT_CLOSED(self);
4316
4317 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4318 return NULL;
4319
4320 CLEAR_DBT(data);
4321 if (!add_partial_dbt(&data, dlen, doff)) {
4322 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4323 return NULL;
4324 }
4325 MYDB_BEGIN_ALLOW_THREADS;
4326 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
4327 MYDB_END_ALLOW_THREADS;
4328 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
4329 && self->mydb->moduleFlags.cursorSetReturnsNone) {
4330 Py_INCREF(Py_None);
4331 retval = Py_None;
4332 }
4333 else if (makeDBError(err)) {
4334 retval = NULL;
4335 }
4336 else {
4337 switch (_DB_get_type(self->mydb)) {
4338 case -1:
4339 retval = NULL;
4340 break;
4341 case DB_BTREE:
4342 case DB_HASH:
4343 default:
4344 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
4345 break;
4346 case DB_RECNO:
4347 case DB_QUEUE:
4348 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
4349 break;
4350 }
4351 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4352 }
4353 /* the only time REALLOC should be set is if we used an integer
4354 * key that make_key_dbt malloc'd for us. always free these. */
4355 if (key.flags & DB_DBT_REALLOC) {
4356 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4357 }
4358
4359 return retval;
4360 }
4361
4362 static PyObject*
4363 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
4364 int flags, unsigned int returnsNone)
4365 {
4366 int err;
4367 DBT key, data;
4368 PyObject* retval;
4369
4370 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
4371 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4372 return NULL;
4373 if (!make_dbt(dataobj, &data)) {
4374 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4375 return NULL;
4376 }
4377
4378 MYDB_BEGIN_ALLOW_THREADS;
4379 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
4380 MYDB_END_ALLOW_THREADS;
4381 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
4382 Py_INCREF(Py_None);
4383 retval = Py_None;
4384 }
4385 else if (makeDBError(err)) {
4386 retval = NULL;
4387 }
4388 else {
4389 switch (_DB_get_type(self->mydb)) {
4390 case -1:
4391 retval = NULL;
4392 break;
4393 case DB_BTREE:
4394 case DB_HASH:
4395 default:
4396 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
4397 break;
4398 case DB_RECNO:
4399 case DB_QUEUE:
4400 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
4401 break;
4402 }
4403 }
4404
4405 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
4406 return retval;
4407 }
4408
4409 static PyObject*
4410 DBC_get_both(DBCursorObject* self, PyObject* args)
4411 {
4412 int flags=0;
4413 PyObject *keyobj, *dataobj;
4414
4415 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
4416 return NULL;
4417
4418 /* if the cursor is closed, self->mydb may be invalid */
4419 CHECK_CURSOR_NOT_CLOSED(self);
4420
4421 return _DBC_get_set_both(self, keyobj, dataobj, flags,
4422 self->mydb->moduleFlags.getReturnsNone);
4423 }
4424
4425 /* Return size of entry */
4426 static PyObject*
4427 DBC_get_current_size(DBCursorObject* self)
4428 {
4429 int err, flags=DB_CURRENT;
4430 PyObject* retval = NULL;
4431 DBT key, data;
4432
4433 CHECK_CURSOR_NOT_CLOSED(self);
4434 CLEAR_DBT(key);
4435 CLEAR_DBT(data);
4436
4437 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
4438 getting the record size. */
4439 data.flags = DB_DBT_USERMEM;
4440 data.ulen = 0;
4441 MYDB_BEGIN_ALLOW_THREADS;
4442 err = _DBC_get(self->dbc, &key, &data, flags);
4443 MYDB_END_ALLOW_THREADS;
4444 if (err == DB_BUFFER_SMALL || !err) {
4445 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
4446 retval = NUMBER_FromLong((long)data.size);
4447 err = 0;
4448 }
4449
4450 RETURN_IF_ERR();
4451 return retval;
4452 }
4453
4454 static PyObject*
4455 DBC_set_both(DBCursorObject* self, PyObject* args)
4456 {
4457 int flags=0;
4458 PyObject *keyobj, *dataobj;
4459
4460 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
4461 return NULL;
4462
4463 /* if the cursor is closed, self->mydb may be invalid */
4464 CHECK_CURSOR_NOT_CLOSED(self);
4465
4466 return _DBC_get_set_both(self, keyobj, dataobj, flags,
4467 self->mydb->moduleFlags.cursorSetReturnsNone);
4468 }
4469
4470
4471 static PyObject*
4472 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
4473 {
4474 int err, irecno, flags=0;
4475 db_recno_t recno;
4476 DBT key, data;
4477 PyObject* retval;
4478 int dlen = -1;
4479 int doff = -1;
4480 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
4481
4482 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
4483 &irecno, &flags, &dlen, &doff))
4484 return NULL;
4485
4486 CHECK_CURSOR_NOT_CLOSED(self);
4487
4488 CLEAR_DBT(key);
4489 recno = (db_recno_t) irecno;
4490 /* use allocated space so DB will be able to realloc room for the real
4491 * key */
4492 key.data = malloc(sizeof(db_recno_t));
4493 if (key.data == NULL) {
4494 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
4495 return NULL;
4496 }
4497 key.size = sizeof(db_recno_t);
4498 key.ulen = key.size;
4499 memcpy(key.data, &recno, sizeof(db_recno_t));
4500 key.flags = DB_DBT_REALLOC;
4501
4502 CLEAR_DBT(data);
4503 if (!add_partial_dbt(&data, dlen, doff)) {
4504 FREE_DBT(key);
4505 return NULL;
4506 }
4507
4508 MYDB_BEGIN_ALLOW_THREADS;
4509 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
4510 MYDB_END_ALLOW_THREADS;
4511 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
4512 && self->mydb->moduleFlags.cursorSetReturnsNone) {
4513 Py_INCREF(Py_None);
4514 retval = Py_None;
4515 }
4516 else if (makeDBError(err)) {
4517 retval = NULL;
4518 }
4519 else { /* Can only be used for BTrees, so no need to return int key */
4520 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
4521 }
4522 FREE_DBT(key);
4523
4524 return retval;
4525 }
4526
4527
4528 static PyObject*
4529 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
4530 {
4531 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
4532 }
4533
4534
4535 static PyObject*
4536 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
4537 {
4538 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
4539 }
4540
4541
4542 static PyObject*
4543 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
4544 {
4545 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
4546 }
4547
4548 #if (DBVER >= 46)
4549 static PyObject*
4550 DBC_prev_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
4551 {
4552 return _DBCursor_get(self,DB_PREV_DUP,args,kwargs,"|iii:prev_dup");
4553 }
4554 #endif
4555
4556 static PyObject*
4557 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
4558 {
4559 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
4560 }
4561
4562
4563 static PyObject*
4564 DBC_join_item(DBCursorObject* self, PyObject* args)
4565 {
4566 int err, flags=0;
4567 DBT key, data;
4568 PyObject* retval;
4569
4570 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
4571 return NULL;
4572
4573 CHECK_CURSOR_NOT_CLOSED(self);
4574
4575 CLEAR_DBT(key);
4576 CLEAR_DBT(data);
4577
4578 MYDB_BEGIN_ALLOW_THREADS;
4579 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
4580 MYDB_END_ALLOW_THREADS;
4581 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
4582 && self->mydb->moduleFlags.getReturnsNone) {
4583 Py_INCREF(Py_None);
4584 retval = Py_None;
4585 }
4586 else if (makeDBError(err)) {
4587 retval = NULL;
4588 }
4589 else {
4590 retval = BuildValue_S(key.data, key.size);
4591 }
4592
4593 return retval;
4594 }
4595
4596
4597 #if (DBVER >= 46)
4598 static PyObject*
4599 DBC_set_priority(DBCursorObject* self, PyObject* args, PyObject* kwargs)
4600 {
4601 int err, priority;
4602 static char* kwnames[] = { "priority", NULL };
4603
4604 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_priority", kwnames,
4605 &priority))
4606 return NULL;
4607
4608 CHECK_CURSOR_NOT_CLOSED(self);
4609
4610 MYDB_BEGIN_ALLOW_THREADS;
4611 err = self->dbc->set_priority(self->dbc, priority);
4612 MYDB_END_ALLOW_THREADS;
4613 RETURN_IF_ERR();
4614 RETURN_NONE();
4615 }
4616
4617
4618 static PyObject*
4619 DBC_get_priority(DBCursorObject* self)
4620 {
4621 int err;
4622 DB_CACHE_PRIORITY priority;
4623
4624 CHECK_CURSOR_NOT_CLOSED(self);
4625
4626 MYDB_BEGIN_ALLOW_THREADS;
4627 err = self->dbc->get_priority(self->dbc, &priority);
4628 MYDB_END_ALLOW_THREADS;
4629 RETURN_IF_ERR();
4630 return NUMBER_FromLong(priority);
4631 }
4632 #endif
4633
4634
4635
4636 /* --------------------------------------------------------------------- */
4637 /* DBEnv methods */
4638
4639
4640 static PyObject*
4641 DBEnv_close_internal(DBEnvObject* self, int flags)
4642 {
4643 PyObject *dummy;
4644 int err;
4645
4646 if (!self->closed) { /* Don't close more than once */
4647 while(self->children_txns) {
4648 dummy = DBTxn_abort_discard_internal(self->children_txns, 0);
4649 Py_XDECREF(dummy);
4650 }
4651 while(self->children_dbs) {
4652 dummy = DB_close_internal(self->children_dbs, 0, 0);
4653 Py_XDECREF(dummy);
4654 }
4655 while(self->children_logcursors) {
4656 dummy = DBLogCursor_close_internal(self->children_logcursors);
4657 Py_XDECREF(dummy);
4658 }
4659 }
4660
4661 self->closed = 1;
4662 if (self->db_env) {
4663 MYDB_BEGIN_ALLOW_THREADS;
4664 err = self->db_env->close(self->db_env, flags);
4665 MYDB_END_ALLOW_THREADS;
4666 /* after calling DBEnv->close, regardless of error, this DBEnv
4667 * may not be accessed again (Berkeley DB docs). */
4668 self->db_env = NULL;
4669 RETURN_IF_ERR();
4670 }
4671 RETURN_NONE();
4672 }
4673
4674 static PyObject*
4675 DBEnv_close(DBEnvObject* self, PyObject* args)
4676 {
4677 int flags = 0;
4678
4679 if (!PyArg_ParseTuple(args, "|i:close", &flags))
4680 return NULL;
4681 return DBEnv_close_internal(self, flags);
4682 }
4683
4684
4685 static PyObject*
4686 DBEnv_open(DBEnvObject* self, PyObject* args)
4687 {
4688 int err, flags=0, mode=0660;
4689 char *db_home;
4690
4691 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
4692 return NULL;
4693
4694 CHECK_ENV_NOT_CLOSED(self);
4695
4696 MYDB_BEGIN_ALLOW_THREADS;
4697 err = self->db_env->open(self->db_env, db_home, flags, mode);
4698 MYDB_END_ALLOW_THREADS;
4699 RETURN_IF_ERR();
4700 self->closed = 0;
4701 self->flags = flags;
4702 RETURN_NONE();
4703 }
4704
4705
4706 static PyObject*
4707 DBEnv_memp_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
4708 {
4709 int err;
4710 DB_MPOOL_STAT *gsp;
4711 DB_MPOOL_FSTAT **fsp, **fsp2;
4712 PyObject* d = NULL, *d2, *d3, *r;
4713 u_int32_t flags = 0;
4714 static char* kwnames[] = { "flags", NULL };
4715
4716 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:memp_stat",
4717 kwnames, &flags))
4718 return NULL;
4719
4720 CHECK_ENV_NOT_CLOSED(self);
4721
4722 MYDB_BEGIN_ALLOW_THREADS;
4723 err = self->db_env->memp_stat(self->db_env, &gsp, &fsp, flags);
4724 MYDB_END_ALLOW_THREADS;
4725 RETURN_IF_ERR();
4726
4727 /* Turn the stat structure into a dictionary */
4728 d = PyDict_New();
4729 if (d == NULL) {
4730 if (gsp)
4731 free(gsp);
4732 return NULL;
4733 }
4734
4735 #define MAKE_ENTRY(name) _addIntToDict(d, #name, gsp->st_##name)
4736
4737 MAKE_ENTRY(gbytes);
4738 MAKE_ENTRY(ncache);
4739 #if (DBVER >= 46)
4740 MAKE_ENTRY(max_ncache);
4741 #endif
4742 MAKE_ENTRY(regsize);
4743 #if (DBVER >= 43)
4744 MAKE_ENTRY(mmapsize);
4745 MAKE_ENTRY(maxopenfd);
4746 MAKE_ENTRY(maxwrite);
4747 MAKE_ENTRY(maxwrite_sleep);
4748 #endif
4749 MAKE_ENTRY(map);
4750 MAKE_ENTRY(cache_hit);
4751 MAKE_ENTRY(cache_miss);
4752 MAKE_ENTRY(page_create);
4753 MAKE_ENTRY(page_in);
4754 MAKE_ENTRY(page_out);
4755 MAKE_ENTRY(ro_evict);
4756 MAKE_ENTRY(rw_evict);
4757 MAKE_ENTRY(page_trickle);
4758 MAKE_ENTRY(pages);
4759 MAKE_ENTRY(page_clean);
4760 MAKE_ENTRY(page_dirty);
4761 MAKE_ENTRY(hash_buckets);
4762 MAKE_ENTRY(hash_searches);
4763 MAKE_ENTRY(hash_longest);
4764 MAKE_ENTRY(hash_examined);
4765 MAKE_ENTRY(hash_nowait);
4766 MAKE_ENTRY(hash_wait);
4767 #if (DBVER >= 45)
4768 MAKE_ENTRY(hash_max_nowait);
4769 #endif
4770 MAKE_ENTRY(hash_max_wait);
4771 MAKE_ENTRY(region_wait);
4772 MAKE_ENTRY(region_nowait);
4773 #if (DBVER >= 45)
4774 MAKE_ENTRY(mvcc_frozen);
4775 MAKE_ENTRY(mvcc_thawed);
4776 MAKE_ENTRY(mvcc_freed);
4777 #endif
4778 MAKE_ENTRY(alloc);
4779 MAKE_ENTRY(alloc_buckets);
4780 MAKE_ENTRY(alloc_max_buckets);
4781 MAKE_ENTRY(alloc_pages);
4782 MAKE_ENTRY(alloc_max_pages);
4783 #if (DBVER >= 45)
4784 MAKE_ENTRY(io_wait);
4785 #endif
4786 #if (DBVER >= 48)
4787 MAKE_ENTRY(sync_interrupted);
4788 #endif
4789
4790 #undef MAKE_ENTRY
4791 free(gsp);
4792
4793 d2 = PyDict_New();
4794 if (d2 == NULL) {
4795 Py_DECREF(d);
4796 if (fsp)
4797 free(fsp);
4798 return NULL;
4799 }
4800 #define MAKE_ENTRY(name) _addIntToDict(d3, #name, (*fsp2)->st_##name)
4801 for(fsp2=fsp;*fsp2; fsp2++) {
4802 d3 = PyDict_New();
4803 if (d3 == NULL) {
4804 Py_DECREF(d);
4805 Py_DECREF(d2);
4806 if (fsp)
4807 free(fsp);
4808 return NULL;
4809 }
4810 MAKE_ENTRY(pagesize);
4811 MAKE_ENTRY(cache_hit);
4812 MAKE_ENTRY(cache_miss);
4813 MAKE_ENTRY(map);
4814 MAKE_ENTRY(page_create);
4815 MAKE_ENTRY(page_in);
4816 MAKE_ENTRY(page_out);
4817 if(PyDict_SetItemString(d2, (*fsp2)->file_name, d3)) {
4818 Py_DECREF(d);
4819 Py_DECREF(d2);
4820 Py_DECREF(d3);
4821 if (fsp)
4822 free(fsp);
4823 return NULL;
4824 }
4825 Py_DECREF(d3);
4826 }
4827
4828 #undef MAKE_ENTRY
4829 free(fsp);
4830
4831 r = Py_BuildValue("(OO)", d, d2);
4832 Py_DECREF(d);
4833 Py_DECREF(d2);
4834 return r;
4835 }
4836
4837 #if (DBVER >= 43)
4838 static PyObject*
4839 DBEnv_memp_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
4840 {
4841 int err;
4842 int flags=0;
4843 static char* kwnames[] = { "flags", NULL };
4844
4845 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:memp_stat_print",
4846 kwnames, &flags))
4847 {
4848 return NULL;
4849 }
4850 CHECK_ENV_NOT_CLOSED(self);
4851 MYDB_BEGIN_ALLOW_THREADS;
4852 err = self->db_env->memp_stat_print(self->db_env, flags);
4853 MYDB_END_ALLOW_THREADS;
4854 RETURN_IF_ERR();
4855 RETURN_NONE();
4856 }
4857 #endif
4858
4859
4860 static PyObject*
4861 DBEnv_memp_trickle(DBEnvObject* self, PyObject* args)
4862 {
4863 int err, percent, nwrotep;
4864
4865 if (!PyArg_ParseTuple(args, "i:memp_trickle", &percent))
4866 return NULL;
4867 CHECK_ENV_NOT_CLOSED(self);
4868 MYDB_BEGIN_ALLOW_THREADS;
4869 err = self->db_env->memp_trickle(self->db_env, percent, &nwrotep);
4870 MYDB_END_ALLOW_THREADS;
4871 RETURN_IF_ERR();
4872 return NUMBER_FromLong(nwrotep);
4873 }
4874
4875 static PyObject*
4876 DBEnv_memp_sync(DBEnvObject* self, PyObject* args)
4877 {
4878 int err;
4879 DB_LSN lsn = {0, 0};
4880 DB_LSN *lsn_p = NULL;
4881
4882 if (!PyArg_ParseTuple(args, "|(ii):memp_sync", &lsn.file, &lsn.offset))
4883 return NULL;
4884 if ((lsn.file!=0) || (lsn.offset!=0)) {
4885 lsn_p = &lsn;
4886 }
4887 CHECK_ENV_NOT_CLOSED(self);
4888 MYDB_BEGIN_ALLOW_THREADS;
4889 err = self->db_env->memp_sync(self->db_env, lsn_p);
4890 MYDB_END_ALLOW_THREADS;
4891 RETURN_IF_ERR();
4892 RETURN_NONE();
4893 }
4894
4895 static PyObject*
4896 DBEnv_remove(DBEnvObject* self, PyObject* args)
4897 {
4898 int err, flags=0;
4899 char *db_home;
4900
4901 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
4902 return NULL;
4903 CHECK_ENV_NOT_CLOSED(self);
4904 MYDB_BEGIN_ALLOW_THREADS;
4905 err = self->db_env->remove(self->db_env, db_home, flags);
4906 MYDB_END_ALLOW_THREADS;
4907 RETURN_IF_ERR();
4908 RETURN_NONE();
4909 }
4910
4911 static PyObject*
4912 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4913 {
4914 int err;
4915 u_int32_t flags=0;
4916 char *file = NULL;
4917 char *database = NULL;
4918 PyObject *txnobj = NULL;
4919 DB_TXN *txn = NULL;
4920 static char* kwnames[] = { "file", "database", "txn", "flags",
4921 NULL };
4922
4923 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
4924 &file, &database, &txnobj, &flags)) {
4925 return NULL;
4926 }
4927 if (!checkTxnObj(txnobj, &txn)) {
4928 return NULL;
4929 }
4930 CHECK_ENV_NOT_CLOSED(self);
4931 MYDB_BEGIN_ALLOW_THREADS;
4932 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4933 MYDB_END_ALLOW_THREADS;
4934 RETURN_IF_ERR();
4935 RETURN_NONE();
4936 }
4937
4938 static PyObject*
4939 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4940 {
4941 int err;
4942 u_int32_t flags=0;
4943 char *file = NULL;
4944 char *database = NULL;
4945 char *newname = NULL;
4946 PyObject *txnobj = NULL;
4947 DB_TXN *txn = NULL;
4948 static char* kwnames[] = { "file", "database", "newname", "txn",
4949 "flags", NULL };
4950
4951 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
4952 &file, &database, &newname, &txnobj, &flags)) {
4953 return NULL;
4954 }
4955 if (!checkTxnObj(txnobj, &txn)) {
4956 return NULL;
4957 }
4958 CHECK_ENV_NOT_CLOSED(self);
4959 MYDB_BEGIN_ALLOW_THREADS;
4960 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4961 flags);
4962 MYDB_END_ALLOW_THREADS;
4963 RETURN_IF_ERR();
4964 RETURN_NONE();
4965 }
4966
4967
4968
4969 static PyObject*
4970 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4971 {
4972 int err;
4973 u_int32_t flags=0;
4974 char *passwd = NULL;
4975 static char* kwnames[] = { "passwd", "flags", NULL };
4976
4977 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4978 &passwd, &flags)) {
4979 return NULL;
4980 }
4981
4982 MYDB_BEGIN_ALLOW_THREADS;
4983 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4984 MYDB_END_ALLOW_THREADS;
4985
4986 RETURN_IF_ERR();
4987 RETURN_NONE();
4988 }
4989
4990 #if (DBVER >= 42)
4991 static PyObject*
4992 DBEnv_get_encrypt_flags(DBEnvObject* self)
4993 {
4994 int err;
4995 u_int32_t flags;
4996
4997 CHECK_ENV_NOT_CLOSED(self);
4998
4999 MYDB_BEGIN_ALLOW_THREADS;
5000 err = self->db_env->get_encrypt_flags(self->db_env, &flags);
5001 MYDB_END_ALLOW_THREADS;
5002
5003 RETURN_IF_ERR();
5004
5005 return NUMBER_FromLong(flags);
5006 }
5007
5008 static PyObject*
5009 DBEnv_get_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5010 {
5011 int err;
5012 int flag;
5013 u_int32_t timeout;
5014 static char* kwnames[] = {"flag", NULL };
5015
5016 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:get_timeout", kwnames,
5017 &flag)) {
5018 return NULL;
5019 }
5020 CHECK_ENV_NOT_CLOSED(self);
5021
5022 MYDB_BEGIN_ALLOW_THREADS;
5023 err = self->db_env->get_timeout(self->db_env, &timeout, flag);
5024 MYDB_END_ALLOW_THREADS;
5025 RETURN_IF_ERR();
5026 return NUMBER_FromLong(timeout);
5027 }
5028 #endif
5029
5030
5031 static PyObject*
5032 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5033 {
5034 int err;
5035 u_int32_t flags=0;
5036 u_int32_t timeout = 0;
5037 static char* kwnames[] = { "timeout", "flags", NULL };
5038
5039 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
5040 &timeout, &flags)) {
5041 return NULL;
5042 }
5043
5044 MYDB_BEGIN_ALLOW_THREADS;
5045 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
5046 MYDB_END_ALLOW_THREADS;
5047
5048 RETURN_IF_ERR();
5049 RETURN_NONE();
5050 }
5051
5052 static PyObject*
5053 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
5054 {
5055 int err;
5056 long shm_key = 0;
5057
5058 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
5059 return NULL;
5060 CHECK_ENV_NOT_CLOSED(self);
5061
5062 err = self->db_env->set_shm_key(self->db_env, shm_key);
5063 RETURN_IF_ERR();
5064 RETURN_NONE();
5065 }
5066
5067 #if (DBVER >= 42)
5068 static PyObject*
5069 DBEnv_get_shm_key(DBEnvObject* self)
5070 {
5071 int err;
5072 long shm_key;
5073
5074 CHECK_ENV_NOT_CLOSED(self);
5075
5076 MYDB_BEGIN_ALLOW_THREADS;
5077 err = self->db_env->get_shm_key(self->db_env, &shm_key);
5078 MYDB_END_ALLOW_THREADS;
5079
5080 RETURN_IF_ERR();
5081
5082 return NUMBER_FromLong(shm_key);
5083 }
5084 #endif
5085
5086 #if (DBVER >= 46)
5087 static PyObject*
5088 DBEnv_set_cache_max(DBEnvObject* self, PyObject* args)
5089 {
5090 int err, gbytes, bytes;
5091
5092 if (!PyArg_ParseTuple(args, "ii:set_cache_max",
5093 &gbytes, &bytes))
5094 return NULL;
5095 CHECK_ENV_NOT_CLOSED(self);
5096
5097 MYDB_BEGIN_ALLOW_THREADS;
5098 err = self->db_env->set_cache_max(self->db_env, gbytes, bytes);
5099 MYDB_END_ALLOW_THREADS;
5100 RETURN_IF_ERR();
5101 RETURN_NONE();
5102 }
5103
5104 static PyObject*
5105 DBEnv_get_cache_max(DBEnvObject* self)
5106 {
5107 int err;
5108 u_int32_t gbytes, bytes;
5109
5110 CHECK_ENV_NOT_CLOSED(self);
5111
5112 MYDB_BEGIN_ALLOW_THREADS;
5113 err = self->db_env->get_cache_max(self->db_env, &gbytes, &bytes);
5114 MYDB_END_ALLOW_THREADS;
5115
5116 RETURN_IF_ERR();
5117
5118 return Py_BuildValue("(ii)", gbytes, bytes);
5119 }
5120 #endif
5121
5122 #if (DBVER >= 46)
5123 static PyObject*
5124 DBEnv_set_thread_count(DBEnvObject* self, PyObject* args)
5125 {
5126 int err;
5127 u_int32_t count;
5128
5129 if (!PyArg_ParseTuple(args, "i:set_thread_count", &count))
5130 return NULL;
5131 CHECK_ENV_NOT_CLOSED(self);
5132
5133 MYDB_BEGIN_ALLOW_THREADS;
5134 err = self->db_env->set_thread_count(self->db_env, count);
5135 MYDB_END_ALLOW_THREADS;
5136 RETURN_IF_ERR();
5137 RETURN_NONE();
5138 }
5139
5140 static PyObject*
5141 DBEnv_get_thread_count(DBEnvObject* self)
5142 {
5143 int err;
5144 u_int32_t count;
5145
5146 CHECK_ENV_NOT_CLOSED(self);
5147
5148 MYDB_BEGIN_ALLOW_THREADS;
5149 err = self->db_env->get_thread_count(self->db_env, &count);
5150 MYDB_END_ALLOW_THREADS;
5151 RETURN_IF_ERR();
5152 return NUMBER_FromLong(count);
5153 }
5154 #endif
5155
5156 static PyObject*
5157 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
5158 {
5159 int err, gbytes=0, bytes=0, ncache=0;
5160
5161 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
5162 &gbytes, &bytes, &ncache))
5163 return NULL;
5164 CHECK_ENV_NOT_CLOSED(self);
5165
5166 MYDB_BEGIN_ALLOW_THREADS;
5167 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
5168 MYDB_END_ALLOW_THREADS;
5169 RETURN_IF_ERR();
5170 RETURN_NONE();
5171 }
5172
5173 #if (DBVER >= 42)
5174 static PyObject*
5175 DBEnv_get_cachesize(DBEnvObject* self)
5176 {
5177 int err;
5178 u_int32_t gbytes, bytes;
5179 int ncache;
5180
5181 CHECK_ENV_NOT_CLOSED(self);
5182
5183 MYDB_BEGIN_ALLOW_THREADS;
5184 err = self->db_env->get_cachesize(self->db_env, &gbytes, &bytes, &ncache);
5185 MYDB_END_ALLOW_THREADS;
5186
5187 RETURN_IF_ERR();
5188
5189 return Py_BuildValue("(iii)", gbytes, bytes, ncache);
5190 }
5191 #endif
5192
5193
5194 static PyObject*
5195 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
5196 {
5197 int err, flags=0, onoff=0;
5198
5199 if (!PyArg_ParseTuple(args, "ii:set_flags",
5200 &flags, &onoff))
5201 return NULL;
5202 CHECK_ENV_NOT_CLOSED(self);
5203
5204 MYDB_BEGIN_ALLOW_THREADS;
5205 err = self->db_env->set_flags(self->db_env, flags, onoff);
5206 MYDB_END_ALLOW_THREADS;
5207 RETURN_IF_ERR();
5208 RETURN_NONE();
5209 }
5210
5211 #if (DBVER >= 42)
5212 static PyObject*
5213 DBEnv_get_flags(DBEnvObject* self)
5214 {
5215 int err;
5216 u_int32_t flags;
5217
5218 CHECK_ENV_NOT_CLOSED(self);
5219
5220 MYDB_BEGIN_ALLOW_THREADS;
5221 err = self->db_env->get_flags(self->db_env, &flags);
5222 MYDB_END_ALLOW_THREADS;
5223 RETURN_IF_ERR();
5224 return NUMBER_FromLong(flags);
5225 }
5226 #endif
5227
5228 #if (DBVER >= 47)
5229 static PyObject*
5230 DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
5231 {
5232 int err, flags, onoff;
5233
5234 if (!PyArg_ParseTuple(args, "ii:log_set_config",
5235 &flags, &onoff))
5236 return NULL;
5237 CHECK_ENV_NOT_CLOSED(self);
5238
5239 MYDB_BEGIN_ALLOW_THREADS;
5240 err = self->db_env->log_set_config(self->db_env, flags, onoff);
5241 MYDB_END_ALLOW_THREADS;
5242 RETURN_IF_ERR();
5243 RETURN_NONE();
5244 }
5245
5246 static PyObject*
5247 DBEnv_log_get_config(DBEnvObject* self, PyObject* args)
5248 {
5249 int err, flag, onoff;
5250
5251 if (!PyArg_ParseTuple(args, "i:log_get_config", &flag))
5252 return NULL;
5253 CHECK_ENV_NOT_CLOSED(self);
5254
5255 MYDB_BEGIN_ALLOW_THREADS;
5256 err = self->db_env->log_get_config(self->db_env, flag, &onoff);
5257 MYDB_END_ALLOW_THREADS;
5258 RETURN_IF_ERR();
5259 return PyBool_FromLong(onoff);
5260 }
5261 #endif /* DBVER >= 47 */
5262
5263 #if (DBVER >= 44)
5264 static PyObject*
5265 DBEnv_mutex_set_max(DBEnvObject* self, PyObject* args)
5266 {
5267 int err;
5268 int value;
5269
5270 if (!PyArg_ParseTuple(args, "i:mutex_set_max", &value))
5271 return NULL;
5272
5273 CHECK_ENV_NOT_CLOSED(self);
5274
5275 MYDB_BEGIN_ALLOW_THREADS;
5276 err = self->db_env->mutex_set_max(self->db_env, value);
5277 MYDB_END_ALLOW_THREADS;
5278
5279 RETURN_IF_ERR();
5280 RETURN_NONE();
5281 }
5282
5283 static PyObject*
5284 DBEnv_mutex_get_max(DBEnvObject* self)
5285 {
5286 int err;
5287 u_int32_t value;
5288
5289 CHECK_ENV_NOT_CLOSED(self);
5290
5291 MYDB_BEGIN_ALLOW_THREADS;
5292 err = self->db_env->mutex_get_max(self->db_env, &value);
5293 MYDB_END_ALLOW_THREADS;
5294
5295 RETURN_IF_ERR();
5296
5297 return NUMBER_FromLong(value);
5298 }
5299
5300 static PyObject*
5301 DBEnv_mutex_set_align(DBEnvObject* self, PyObject* args)
5302 {
5303 int err;
5304 int align;
5305
5306 if (!PyArg_ParseTuple(args, "i:mutex_set_align", &align))
5307 return NULL;
5308
5309 CHECK_ENV_NOT_CLOSED(self);
5310
5311 MYDB_BEGIN_ALLOW_THREADS;
5312 err = self->db_env->mutex_set_align(self->db_env, align);
5313 MYDB_END_ALLOW_THREADS;
5314
5315 RETURN_IF_ERR();
5316 RETURN_NONE();
5317 }
5318
5319 static PyObject*
5320 DBEnv_mutex_get_align(DBEnvObject* self)
5321 {
5322 int err;
5323 u_int32_t align;
5324
5325 CHECK_ENV_NOT_CLOSED(self);
5326
5327 MYDB_BEGIN_ALLOW_THREADS;
5328 err = self->db_env->mutex_get_align(self->db_env, &align);
5329 MYDB_END_ALLOW_THREADS;
5330
5331 RETURN_IF_ERR();
5332
5333 return NUMBER_FromLong(align);
5334 }
5335
5336 static PyObject*
5337 DBEnv_mutex_set_increment(DBEnvObject* self, PyObject* args)
5338 {
5339 int err;
5340 int increment;
5341
5342 if (!PyArg_ParseTuple(args, "i:mutex_set_increment", &increment))
5343 return NULL;
5344
5345 CHECK_ENV_NOT_CLOSED(self);
5346
5347 MYDB_BEGIN_ALLOW_THREADS;
5348 err = self->db_env->mutex_set_increment(self->db_env, increment);
5349 MYDB_END_ALLOW_THREADS;
5350
5351 RETURN_IF_ERR();
5352 RETURN_NONE();
5353 }
5354
5355 static PyObject*
5356 DBEnv_mutex_get_increment(DBEnvObject* self)
5357 {
5358 int err;
5359 u_int32_t increment;
5360
5361 CHECK_ENV_NOT_CLOSED(self);
5362
5363 MYDB_BEGIN_ALLOW_THREADS;
5364 err = self->db_env->mutex_get_increment(self->db_env, &increment);
5365 MYDB_END_ALLOW_THREADS;
5366
5367 RETURN_IF_ERR();
5368
5369 return NUMBER_FromLong(increment);
5370 }
5371
5372 static PyObject*
5373 DBEnv_mutex_set_tas_spins(DBEnvObject* self, PyObject* args)
5374 {
5375 int err;
5376 int tas_spins;
5377
5378 if (!PyArg_ParseTuple(args, "i:mutex_set_tas_spins", &tas_spins))
5379 return NULL;
5380
5381 CHECK_ENV_NOT_CLOSED(self);
5382
5383 MYDB_BEGIN_ALLOW_THREADS;
5384 err = self->db_env->mutex_set_tas_spins(self->db_env, tas_spins);
5385 MYDB_END_ALLOW_THREADS;
5386
5387 RETURN_IF_ERR();
5388 RETURN_NONE();
5389 }
5390
5391 static PyObject*
5392 DBEnv_mutex_get_tas_spins(DBEnvObject* self)
5393 {
5394 int err;
5395 u_int32_t tas_spins;
5396
5397 CHECK_ENV_NOT_CLOSED(self);
5398
5399 MYDB_BEGIN_ALLOW_THREADS;
5400 err = self->db_env->mutex_get_tas_spins(self->db_env, &tas_spins);
5401 MYDB_END_ALLOW_THREADS;
5402
5403 RETURN_IF_ERR();
5404
5405 return NUMBER_FromLong(tas_spins);
5406 }
5407 #endif
5408
5409 static PyObject*
5410 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
5411 {
5412 int err;
5413 char *dir;
5414
5415 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
5416 return NULL;
5417 CHECK_ENV_NOT_CLOSED(self);
5418
5419 MYDB_BEGIN_ALLOW_THREADS;
5420 err = self->db_env->set_data_dir(self->db_env, dir);
5421 MYDB_END_ALLOW_THREADS;
5422 RETURN_IF_ERR();
5423 RETURN_NONE();
5424 }
5425
5426 #if (DBVER >= 42)
5427 static PyObject*
5428 DBEnv_get_data_dirs(DBEnvObject* self)
5429 {
5430 int err;
5431 PyObject *tuple;
5432 PyObject *item;
5433 const char **dirpp;
5434 int size, i;
5435
5436 CHECK_ENV_NOT_CLOSED(self);
5437
5438 MYDB_BEGIN_ALLOW_THREADS;
5439 err = self->db_env->get_data_dirs(self->db_env, &dirpp);
5440 MYDB_END_ALLOW_THREADS;
5441
5442 RETURN_IF_ERR();
5443
5444 /*
5445 ** Calculate size. Python C API
5446 ** actually allows for tuple resizing,
5447 ** but this is simple enough.
5448 */
5449 for (size=0; *(dirpp+size) ; size++);
5450
5451 tuple = PyTuple_New(size);
5452 if (!tuple)
5453 return NULL;
5454
5455 for (i=0; i<size; i++) {
5456 item = PyBytes_FromString (*(dirpp+i));
5457 if (item == NULL) {
5458 Py_DECREF(tuple);
5459 tuple = NULL;
5460 break;
5461 }
5462 PyTuple_SET_ITEM(tuple, i, item);
5463 }
5464 return tuple;
5465 }
5466 #endif
5467
5468 #if (DBVER >= 44)
5469 static PyObject*
5470 DBEnv_set_lg_filemode(DBEnvObject* self, PyObject* args)
5471 {
5472 int err, filemode;
5473
5474 if (!PyArg_ParseTuple(args, "i:set_lg_filemode", &filemode))
5475 return NULL;
5476 CHECK_ENV_NOT_CLOSED(self);
5477
5478 MYDB_BEGIN_ALLOW_THREADS;
5479 err = self->db_env->set_lg_filemode(self->db_env, filemode);
5480 MYDB_END_ALLOW_THREADS;
5481 RETURN_IF_ERR();
5482 RETURN_NONE();
5483 }
5484
5485 static PyObject*
5486 DBEnv_get_lg_filemode(DBEnvObject* self)
5487 {
5488 int err, filemode;
5489
5490 CHECK_ENV_NOT_CLOSED(self);
5491
5492 MYDB_BEGIN_ALLOW_THREADS;
5493 err = self->db_env->get_lg_filemode(self->db_env, &filemode);
5494 MYDB_END_ALLOW_THREADS;
5495 RETURN_IF_ERR();
5496 return NUMBER_FromLong(filemode);
5497 }
5498 #endif
5499
5500 static PyObject*
5501 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
5502 {
5503 int err, lg_bsize;
5504
5505 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
5506 return NULL;
5507 CHECK_ENV_NOT_CLOSED(self);
5508
5509 MYDB_BEGIN_ALLOW_THREADS;
5510 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
5511 MYDB_END_ALLOW_THREADS;
5512 RETURN_IF_ERR();
5513 RETURN_NONE();
5514 }
5515
5516 #if (DBVER >= 42)
5517 static PyObject*
5518 DBEnv_get_lg_bsize(DBEnvObject* self)
5519 {
5520 int err;
5521 u_int32_t lg_bsize;
5522
5523 CHECK_ENV_NOT_CLOSED(self);
5524
5525 MYDB_BEGIN_ALLOW_THREADS;
5526 err = self->db_env->get_lg_bsize(self->db_env, &lg_bsize);
5527 MYDB_END_ALLOW_THREADS;
5528 RETURN_IF_ERR();
5529 return NUMBER_FromLong(lg_bsize);
5530 }
5531 #endif
5532
5533 static PyObject*
5534 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
5535 {
5536 int err;
5537 char *dir;
5538
5539 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
5540 return NULL;
5541 CHECK_ENV_NOT_CLOSED(self);
5542
5543 MYDB_BEGIN_ALLOW_THREADS;
5544 err = self->db_env->set_lg_dir(self->db_env, dir);
5545 MYDB_END_ALLOW_THREADS;
5546 RETURN_IF_ERR();
5547 RETURN_NONE();
5548 }
5549
5550 #if (DBVER >= 42)
5551 static PyObject*
5552 DBEnv_get_lg_dir(DBEnvObject* self)
5553 {
5554 int err;
5555 const char *dirp;
5556
5557 CHECK_ENV_NOT_CLOSED(self);
5558
5559 MYDB_BEGIN_ALLOW_THREADS;
5560 err = self->db_env->get_lg_dir(self->db_env, &dirp);
5561 MYDB_END_ALLOW_THREADS;
5562 RETURN_IF_ERR();
5563 return PyBytes_FromString(dirp);
5564 }
5565 #endif
5566
5567 static PyObject*
5568 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
5569 {
5570 int err, lg_max;
5571
5572 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
5573 return NULL;
5574 CHECK_ENV_NOT_CLOSED(self);
5575
5576 MYDB_BEGIN_ALLOW_THREADS;
5577 err = self->db_env->set_lg_max(self->db_env, lg_max);
5578 MYDB_END_ALLOW_THREADS;
5579 RETURN_IF_ERR();
5580 RETURN_NONE();
5581 }
5582
5583 #if (DBVER >= 42)
5584 static PyObject*
5585 DBEnv_get_lg_max(DBEnvObject* self)
5586 {
5587 int err;
5588 u_int32_t lg_max;
5589
5590 CHECK_ENV_NOT_CLOSED(self);
5591
5592 MYDB_BEGIN_ALLOW_THREADS;
5593 err = self->db_env->get_lg_max(self->db_env, &lg_max);
5594 MYDB_END_ALLOW_THREADS;
5595 RETURN_IF_ERR();
5596 return NUMBER_FromLong(lg_max);
5597 }
5598 #endif
5599
5600
5601 static PyObject*
5602 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
5603 {
5604 int err, lg_max;
5605
5606 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
5607 return NULL;
5608 CHECK_ENV_NOT_CLOSED(self);
5609
5610 MYDB_BEGIN_ALLOW_THREADS;
5611 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
5612 MYDB_END_ALLOW_THREADS;
5613 RETURN_IF_ERR();
5614 RETURN_NONE();
5615 }
5616
5617 #if (DBVER >= 42)
5618 static PyObject*
5619 DBEnv_get_lg_regionmax(DBEnvObject* self)
5620 {
5621 int err;
5622 u_int32_t lg_regionmax;
5623
5624 CHECK_ENV_NOT_CLOSED(self);
5625
5626 MYDB_BEGIN_ALLOW_THREADS;
5627 err = self->db_env->get_lg_regionmax(self->db_env, &lg_regionmax);
5628 MYDB_END_ALLOW_THREADS;
5629 RETURN_IF_ERR();
5630 return NUMBER_FromLong(lg_regionmax);
5631 }
5632 #endif
5633
5634 #if (DBVER >= 47)
5635 static PyObject*
5636 DBEnv_set_lk_partitions(DBEnvObject* self, PyObject* args)
5637 {
5638 int err, lk_partitions;
5639
5640 if (!PyArg_ParseTuple(args, "i:set_lk_partitions", &lk_partitions))
5641 return NULL;
5642 CHECK_ENV_NOT_CLOSED(self);
5643
5644 MYDB_BEGIN_ALLOW_THREADS;
5645 err = self->db_env->set_lk_partitions(self->db_env, lk_partitions);
5646 MYDB_END_ALLOW_THREADS;
5647 RETURN_IF_ERR();
5648 RETURN_NONE();
5649 }
5650
5651 static PyObject*
5652 DBEnv_get_lk_partitions(DBEnvObject* self)
5653 {
5654 int err;
5655 u_int32_t lk_partitions;
5656
5657 CHECK_ENV_NOT_CLOSED(self);
5658
5659 MYDB_BEGIN_ALLOW_THREADS;
5660 err = self->db_env->get_lk_partitions(self->db_env, &lk_partitions);
5661 MYDB_END_ALLOW_THREADS;
5662 RETURN_IF_ERR();
5663 return NUMBER_FromLong(lk_partitions);
5664 }
5665 #endif
5666
5667 static PyObject*
5668 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
5669 {
5670 int err, lk_detect;
5671
5672 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
5673 return NULL;
5674 CHECK_ENV_NOT_CLOSED(self);
5675
5676 MYDB_BEGIN_ALLOW_THREADS;
5677 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
5678 MYDB_END_ALLOW_THREADS;
5679 RETURN_IF_ERR();
5680 RETURN_NONE();
5681 }
5682
5683 #if (DBVER >= 42)
5684 static PyObject*
5685 DBEnv_get_lk_detect(DBEnvObject* self)
5686 {
5687 int err;
5688 u_int32_t lk_detect;
5689
5690 CHECK_ENV_NOT_CLOSED(self);
5691
5692 MYDB_BEGIN_ALLOW_THREADS;
5693 err = self->db_env->get_lk_detect(self->db_env, &lk_detect);
5694 MYDB_END_ALLOW_THREADS;
5695 RETURN_IF_ERR();
5696 return NUMBER_FromLong(lk_detect);
5697 }
5698 #endif
5699
5700
5701 #if (DBVER < 45)
5702 static PyObject*
5703 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
5704 {
5705 int err, max;
5706
5707 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
5708 return NULL;
5709 CHECK_ENV_NOT_CLOSED(self);
5710
5711 MYDB_BEGIN_ALLOW_THREADS;
5712 err = self->db_env->set_lk_max(self->db_env, max);
5713 MYDB_END_ALLOW_THREADS;
5714 RETURN_IF_ERR();
5715 RETURN_NONE();
5716 }
5717 #endif
5718
5719
5720
5721 static PyObject*
5722 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
5723 {
5724 int err, max;
5725
5726 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
5727 return NULL;
5728 CHECK_ENV_NOT_CLOSED(self);
5729
5730 MYDB_BEGIN_ALLOW_THREADS;
5731 err = self->db_env->set_lk_max_locks(self->db_env, max);
5732 MYDB_END_ALLOW_THREADS;
5733 RETURN_IF_ERR();
5734 RETURN_NONE();
5735 }
5736
5737 #if (DBVER >= 42)
5738 static PyObject*
5739 DBEnv_get_lk_max_locks(DBEnvObject* self)
5740 {
5741 int err;
5742 u_int32_t lk_max;
5743
5744 CHECK_ENV_NOT_CLOSED(self);
5745
5746 MYDB_BEGIN_ALLOW_THREADS;
5747 err = self->db_env->get_lk_max_locks(self->db_env, &lk_max);
5748 MYDB_END_ALLOW_THREADS;
5749 RETURN_IF_ERR();
5750 return NUMBER_FromLong(lk_max);
5751 }
5752 #endif
5753
5754 static PyObject*
5755 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
5756 {
5757 int err, max;
5758
5759 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
5760 return NULL;
5761 CHECK_ENV_NOT_CLOSED(self);
5762
5763 MYDB_BEGIN_ALLOW_THREADS;
5764 err = self->db_env->set_lk_max_lockers(self->db_env, max);
5765 MYDB_END_ALLOW_THREADS;
5766 RETURN_IF_ERR();
5767 RETURN_NONE();
5768 }
5769
5770 #if (DBVER >= 42)
5771 static PyObject*
5772 DBEnv_get_lk_max_lockers(DBEnvObject* self)
5773 {
5774 int err;
5775 u_int32_t lk_max;
5776
5777 CHECK_ENV_NOT_CLOSED(self);
5778
5779 MYDB_BEGIN_ALLOW_THREADS;
5780 err = self->db_env->get_lk_max_lockers(self->db_env, &lk_max);
5781 MYDB_END_ALLOW_THREADS;
5782 RETURN_IF_ERR();
5783 return NUMBER_FromLong(lk_max);
5784 }
5785 #endif
5786
5787 static PyObject*
5788 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
5789 {
5790 int err, max;
5791
5792 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
5793 return NULL;
5794 CHECK_ENV_NOT_CLOSED(self);
5795
5796 MYDB_BEGIN_ALLOW_THREADS;
5797 err = self->db_env->set_lk_max_objects(self->db_env, max);
5798 MYDB_END_ALLOW_THREADS;
5799 RETURN_IF_ERR();
5800 RETURN_NONE();
5801 }
5802
5803 #if (DBVER >= 42)
5804 static PyObject*
5805 DBEnv_get_lk_max_objects(DBEnvObject* self)
5806 {
5807 int err;
5808 u_int32_t lk_max;
5809
5810 CHECK_ENV_NOT_CLOSED(self);
5811
5812 MYDB_BEGIN_ALLOW_THREADS;
5813 err = self->db_env->get_lk_max_objects(self->db_env, &lk_max);
5814 MYDB_END_ALLOW_THREADS;
5815 RETURN_IF_ERR();
5816 return NUMBER_FromLong(lk_max);
5817 }
5818 #endif
5819
5820 #if (DBVER >= 42)
5821 static PyObject*
5822 DBEnv_get_mp_mmapsize(DBEnvObject* self)
5823 {
5824 int err;
5825 size_t mmapsize;
5826
5827 CHECK_ENV_NOT_CLOSED(self);
5828
5829 MYDB_BEGIN_ALLOW_THREADS;
5830 err = self->db_env->get_mp_mmapsize(self->db_env, &mmapsize);
5831 MYDB_END_ALLOW_THREADS;
5832 RETURN_IF_ERR();
5833 return NUMBER_FromLong(mmapsize);
5834 }
5835 #endif
5836
5837
5838 static PyObject*
5839 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
5840 {
5841 int err, mp_mmapsize;
5842
5843 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
5844 return NULL;
5845 CHECK_ENV_NOT_CLOSED(self);
5846
5847 MYDB_BEGIN_ALLOW_THREADS;
5848 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
5849 MYDB_END_ALLOW_THREADS;
5850 RETURN_IF_ERR();
5851 RETURN_NONE();
5852 }
5853
5854
5855 static PyObject*
5856 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
5857 {
5858 int err;
5859 char *dir;
5860
5861 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
5862 return NULL;
5863 CHECK_ENV_NOT_CLOSED(self);
5864
5865 MYDB_BEGIN_ALLOW_THREADS;
5866 err = self->db_env->set_tmp_dir(self->db_env, dir);
5867 MYDB_END_ALLOW_THREADS;
5868 RETURN_IF_ERR();
5869 RETURN_NONE();
5870 }
5871
5872
5873 #if (DBVER >= 42)
5874 static PyObject*
5875 DBEnv_get_tmp_dir(DBEnvObject* self)
5876 {
5877 int err;
5878 const char *dirpp;
5879
5880 CHECK_ENV_NOT_CLOSED(self);
5881
5882 MYDB_BEGIN_ALLOW_THREADS;
5883 err = self->db_env->get_tmp_dir(self->db_env, &dirpp);
5884 MYDB_END_ALLOW_THREADS;
5885
5886 RETURN_IF_ERR();
5887
5888 return PyBytes_FromString(dirpp);
5889 }
5890 #endif
5891
5892
5893 static PyObject*
5894 DBEnv_txn_recover(DBEnvObject* self)
5895 {
5896 int flags = DB_FIRST;
5897 int err, i;
5898 PyObject *list, *tuple, *gid;
5899 DBTxnObject *txn;
5900 #define PREPLIST_LEN 16
5901 DB_PREPLIST preplist[PREPLIST_LEN];
5902 #if (DBVER < 48)
5903 long retp;
5904 #else
5905 u_int32_t retp;
5906 #endif
5907
5908 CHECK_ENV_NOT_CLOSED(self);
5909
5910 list=PyList_New(0);
5911 if (!list)
5912 return NULL;
5913 while (!0) {
5914 MYDB_BEGIN_ALLOW_THREADS
5915 err=self->db_env->txn_recover(self->db_env,
5916 preplist, PREPLIST_LEN, &retp, flags);
5917 #undef PREPLIST_LEN
5918 MYDB_END_ALLOW_THREADS
5919 if (err) {
5920 Py_DECREF(list);
5921 RETURN_IF_ERR();
5922 }
5923 if (!retp) break;
5924 flags=DB_NEXT; /* Prepare for next loop pass */
5925 for (i=0; i<retp; i++) {
5926 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
5927 DB_GID_SIZE);
5928 if (!gid) {
5929 Py_DECREF(list);
5930 return NULL;
5931 }
5932 txn=newDBTxnObject(self, NULL, preplist[i].txn, 0);
5933 if (!txn) {
5934 Py_DECREF(list);
5935 Py_DECREF(gid);
5936 return NULL;
5937 }
5938 txn->flag_prepare=1; /* Recover state */
5939 tuple=PyTuple_New(2);
5940 if (!tuple) {
5941 Py_DECREF(list);
5942 Py_DECREF(gid);
5943 Py_DECREF(txn);
5944 return NULL;
5945 }
5946 if (PyTuple_SetItem(tuple, 0, gid)) {
5947 Py_DECREF(list);
5948 Py_DECREF(gid);
5949 Py_DECREF(txn);
5950 Py_DECREF(tuple);
5951 return NULL;
5952 }
5953 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
5954 Py_DECREF(list);
5955 Py_DECREF(txn);
5956 Py_DECREF(tuple); /* This delete the "gid" also */
5957 return NULL;
5958 }
5959 if (PyList_Append(list, tuple)) {
5960 Py_DECREF(list);
5961 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
5962 return NULL;
5963 }
5964 Py_DECREF(tuple);
5965 }
5966 }
5967 return list;
5968 }
5969
5970 static PyObject*
5971 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5972 {
5973 int flags = 0;
5974 PyObject* txnobj = NULL;
5975 DB_TXN *txn = NULL;
5976 static char* kwnames[] = { "parent", "flags", NULL };
5977
5978 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
5979 &txnobj, &flags))
5980 return NULL;
5981
5982 if (!checkTxnObj(txnobj, &txn))
5983 return NULL;
5984 CHECK_ENV_NOT_CLOSED(self);
5985
5986 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
5987 }
5988
5989
5990 static PyObject*
5991 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
5992 {
5993 int err, kbyte=0, min=0, flags=0;
5994
5995 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
5996 return NULL;
5997 CHECK_ENV_NOT_CLOSED(self);
5998
5999 MYDB_BEGIN_ALLOW_THREADS;
6000 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
6001 MYDB_END_ALLOW_THREADS;
6002 RETURN_IF_ERR();
6003 RETURN_NONE();
6004 }
6005
6006
6007 #if (DBVER >= 42)
6008 static PyObject*
6009 DBEnv_get_tx_max(DBEnvObject* self)
6010 {
6011 int err;
6012 u_int32_t max;
6013
6014 CHECK_ENV_NOT_CLOSED(self);
6015
6016 MYDB_BEGIN_ALLOW_THREADS;
6017 err = self->db_env->get_tx_max(self->db_env, &max);
6018 MYDB_END_ALLOW_THREADS;
6019 RETURN_IF_ERR();
6020 return PyLong_FromUnsignedLong(max);
6021 }
6022 #endif
6023
6024
6025 static PyObject*
6026 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
6027 {
6028 int err, max;
6029
6030 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
6031 return NULL;
6032 CHECK_ENV_NOT_CLOSED(self);
6033
6034 MYDB_BEGIN_ALLOW_THREADS;
6035 err = self->db_env->set_tx_max(self->db_env, max);
6036 MYDB_END_ALLOW_THREADS;
6037 RETURN_IF_ERR();
6038 RETURN_NONE();
6039 }
6040
6041
6042 #if (DBVER >= 42)
6043 static PyObject*
6044 DBEnv_get_tx_timestamp(DBEnvObject* self)
6045 {
6046 int err;
6047 time_t timestamp;
6048
6049 CHECK_ENV_NOT_CLOSED(self);
6050
6051 MYDB_BEGIN_ALLOW_THREADS;
6052 err = self->db_env->get_tx_timestamp(self->db_env, ×tamp);
6053 MYDB_END_ALLOW_THREADS;
6054 RETURN_IF_ERR();
6055 return NUMBER_FromLong(timestamp);
6056 }
6057 #endif
6058
6059 static PyObject*
6060 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
6061 {
6062 int err;
6063 long stamp;
6064 time_t timestamp;
6065
6066 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
6067 return NULL;
6068 CHECK_ENV_NOT_CLOSED(self);
6069 timestamp = (time_t)stamp;
6070 MYDB_BEGIN_ALLOW_THREADS;
6071 err = self->db_env->set_tx_timestamp(self->db_env, ×tamp);
6072 MYDB_END_ALLOW_THREADS;
6073 RETURN_IF_ERR();
6074 RETURN_NONE();
6075 }
6076
6077
6078 static PyObject*
6079 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
6080 {
6081 int err, atype, flags=0;
6082 int aborted = 0;
6083
6084 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
6085 return NULL;
6086 CHECK_ENV_NOT_CLOSED(self);
6087
6088 MYDB_BEGIN_ALLOW_THREADS;
6089 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
6090 MYDB_END_ALLOW_THREADS;
6091 RETURN_IF_ERR();
6092 return NUMBER_FromLong(aborted);
6093 }
6094
6095
6096 static PyObject*
6097 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
6098 {
6099 int flags=0;
6100 int locker, lock_mode;
6101 DBT obj;
6102 PyObject* objobj;
6103
6104 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
6105 return NULL;
6106
6107
6108 if (!make_dbt(objobj, &obj))
6109 return NULL;
6110
6111 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
6112 }
6113
6114
6115 static PyObject*
6116 DBEnv_lock_id(DBEnvObject* self)
6117 {
6118 int err;
6119 u_int32_t theID;
6120
6121 CHECK_ENV_NOT_CLOSED(self);
6122 MYDB_BEGIN_ALLOW_THREADS;
6123 err = self->db_env->lock_id(self->db_env, &theID);
6124 MYDB_END_ALLOW_THREADS;
6125 RETURN_IF_ERR();
6126
6127 return NUMBER_FromLong((long)theID);
6128 }
6129
6130 static PyObject*
6131 DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
6132 {
6133 int err;
6134 u_int32_t theID;
6135
6136 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
6137 return NULL;
6138
6139 CHECK_ENV_NOT_CLOSED(self);
6140 MYDB_BEGIN_ALLOW_THREADS;
6141 err = self->db_env->lock_id_free(self->db_env, theID);
6142 MYDB_END_ALLOW_THREADS;
6143 RETURN_IF_ERR();
6144 RETURN_NONE();
6145 }
6146
6147 static PyObject*
6148 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
6149 {
6150 int err;
6151 DBLockObject* dblockobj;
6152
6153 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
6154 return NULL;
6155
6156 CHECK_ENV_NOT_CLOSED(self);
6157 MYDB_BEGIN_ALLOW_THREADS;
6158 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
6159 MYDB_END_ALLOW_THREADS;
6160 RETURN_IF_ERR();
6161 RETURN_NONE();
6162 }
6163
6164 #if (DBVER >= 44)
6165 static PyObject*
6166 DBEnv_fileid_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
6167 {
6168 int err;
6169 char *file;
6170 u_int32_t flags = 0;
6171 static char* kwnames[] = { "file", "flags", NULL};
6172
6173 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:fileid_reset", kwnames,
6174 &file, &flags))
6175 return NULL;
6176 CHECK_ENV_NOT_CLOSED(self);
6177
6178 MYDB_BEGIN_ALLOW_THREADS;
6179 err = self->db_env->fileid_reset(self->db_env, file, flags);
6180 MYDB_END_ALLOW_THREADS;
6181 RETURN_IF_ERR();
6182 RETURN_NONE();
6183 }
6184
6185 static PyObject*
6186 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
6187 {
6188 int err;
6189 char *file;
6190 u_int32_t flags = 0;
6191 static char* kwnames[] = { "file", "flags", NULL};
6192
6193 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
6194 &file, &flags))
6195 return NULL;
6196 CHECK_ENV_NOT_CLOSED(self);
6197
6198 MYDB_BEGIN_ALLOW_THREADS;
6199 err = self->db_env->lsn_reset(self->db_env, file, flags);
6200 MYDB_END_ALLOW_THREADS;
6201 RETURN_IF_ERR();
6202 RETURN_NONE();
6203 }
6204 #endif /* DBVER >= 4.4 */
6205
6206
6207 #if (DBVER >= 43)
6208 static PyObject*
6209 DBEnv_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
6210 {
6211 int err;
6212 int flags=0;
6213 static char* kwnames[] = { "flags", NULL };
6214
6215 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
6216 kwnames, &flags))
6217 {
6218 return NULL;
6219 }
6220 CHECK_ENV_NOT_CLOSED(self);
6221 MYDB_BEGIN_ALLOW_THREADS;
6222 err = self->db_env->stat_print(self->db_env, flags);
6223 MYDB_END_ALLOW_THREADS;
6224 RETURN_IF_ERR();
6225 RETURN_NONE();
6226 }
6227 #endif
6228
6229
6230 static PyObject*
6231 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
6232 {
6233 int err;
6234 DB_LOG_STAT* statp = NULL;
6235 PyObject* d = NULL;
6236 u_int32_t flags = 0;
6237
6238 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
6239 return NULL;
6240 CHECK_ENV_NOT_CLOSED(self);
6241
6242 MYDB_BEGIN_ALLOW_THREADS;
6243 err = self->db_env->log_stat(self->db_env, &statp, flags);
6244 MYDB_END_ALLOW_THREADS;
6245 RETURN_IF_ERR();
6246
6247 /* Turn the stat structure into a dictionary */
6248 d = PyDict_New();
6249 if (d == NULL) {
6250 if (statp)
6251 free(statp);
6252 return NULL;
6253 }
6254
6255 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
6256
6257 MAKE_ENTRY(magic);
6258 MAKE_ENTRY(version);
6259 MAKE_ENTRY(mode);
6260 MAKE_ENTRY(lg_bsize);
6261 #if (DBVER >= 44)
6262 MAKE_ENTRY(lg_size);
6263 MAKE_ENTRY(record);
6264 #endif
6265 MAKE_ENTRY(w_mbytes);
6266 MAKE_ENTRY(w_bytes);
6267 MAKE_ENTRY(wc_mbytes);
6268 MAKE_ENTRY(wc_bytes);
6269 MAKE_ENTRY(wcount);
6270 MAKE_ENTRY(wcount_fill);
6271 #if (DBVER >= 44)
6272 MAKE_ENTRY(rcount);
6273 #endif
6274 MAKE_ENTRY(scount);
6275 MAKE_ENTRY(cur_file);
6276 MAKE_ENTRY(cur_offset);
6277 MAKE_ENTRY(disk_file);
6278 MAKE_ENTRY(disk_offset);
6279 MAKE_ENTRY(maxcommitperflush);
6280 MAKE_ENTRY(mincommitperflush);
6281 MAKE_ENTRY(regsize);
6282 MAKE_ENTRY(region_wait);
6283 MAKE_ENTRY(region_nowait);
6284
6285 #undef MAKE_ENTRY
6286 free(statp);
6287 return d;
6288 } /* DBEnv_log_stat */
6289
6290
6291 #if (DBVER >= 43)
6292 static PyObject*
6293 DBEnv_log_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
6294 {
6295 int err;
6296 int flags=0;
6297 static char* kwnames[] = { "flags", NULL };
6298
6299 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:log_stat_print",
6300 kwnames, &flags))
6301 {
6302 return NULL;
6303 }
6304 CHECK_ENV_NOT_CLOSED(self);
6305 MYDB_BEGIN_ALLOW_THREADS;
6306 err = self->db_env->log_stat_print(self->db_env, flags);
6307 MYDB_END_ALLOW_THREADS;
6308 RETURN_IF_ERR();
6309 RETURN_NONE();
6310 }
6311 #endif
6312
6313
6314 static PyObject*
6315 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
6316 {
6317 int err;
6318 DB_LOCK_STAT* sp;
6319 PyObject* d = NULL;
6320 u_int32_t flags = 0;
6321
6322 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
6323 return NULL;
6324 CHECK_ENV_NOT_CLOSED(self);
6325
6326 MYDB_BEGIN_ALLOW_THREADS;
6327 err = self->db_env->lock_stat(self->db_env, &sp, flags);
6328 MYDB_END_ALLOW_THREADS;
6329 RETURN_IF_ERR();
6330
6331 /* Turn the stat structure into a dictionary */
6332 d = PyDict_New();
6333 if (d == NULL) {
6334 free(sp);
6335 return NULL;
6336 }
6337
6338 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
6339
6340 MAKE_ENTRY(id);
6341 MAKE_ENTRY(cur_maxid);
6342 MAKE_ENTRY(nmodes);
6343 MAKE_ENTRY(maxlocks);
6344 MAKE_ENTRY(maxlockers);
6345 MAKE_ENTRY(maxobjects);
6346 MAKE_ENTRY(nlocks);
6347 MAKE_ENTRY(maxnlocks);
6348 MAKE_ENTRY(nlockers);
6349 MAKE_ENTRY(maxnlockers);
6350 MAKE_ENTRY(nobjects);
6351 MAKE_ENTRY(maxnobjects);
6352 MAKE_ENTRY(nrequests);
6353 MAKE_ENTRY(nreleases);
6354 #if (DBVER >= 44)
6355 MAKE_ENTRY(nupgrade);
6356 MAKE_ENTRY(ndowngrade);
6357 #endif
6358 #if (DBVER < 44)
6359 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
6360 MAKE_ENTRY(nconflicts);
6361 #else
6362 MAKE_ENTRY(lock_nowait);
6363 MAKE_ENTRY(lock_wait);
6364 #endif
6365 MAKE_ENTRY(ndeadlocks);
6366 MAKE_ENTRY(locktimeout);
6367 MAKE_ENTRY(txntimeout);
6368 MAKE_ENTRY(nlocktimeouts);
6369 MAKE_ENTRY(ntxntimeouts);
6370 #if (DBVER >= 46)
6371 MAKE_ENTRY(objs_wait);
6372 MAKE_ENTRY(objs_nowait);
6373 MAKE_ENTRY(lockers_wait);
6374 MAKE_ENTRY(lockers_nowait);
6375 #if (DBVER >= 47)
6376 MAKE_ENTRY(lock_wait);
6377 MAKE_ENTRY(lock_nowait);
6378 #else
6379 MAKE_ENTRY(locks_wait);
6380 MAKE_ENTRY(locks_nowait);
6381 #endif
6382 MAKE_ENTRY(hash_len);
6383 #endif
6384 MAKE_ENTRY(regsize);
6385 MAKE_ENTRY(region_wait);
6386 MAKE_ENTRY(region_nowait);
6387
6388 #undef MAKE_ENTRY
6389 free(sp);
6390 return d;
6391 }
6392
6393 #if (DBVER >= 43)
6394 static PyObject*
6395 DBEnv_lock_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
6396 {
6397 int err;
6398 int flags=0;
6399 static char* kwnames[] = { "flags", NULL };
6400
6401 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:lock_stat_print",
6402 kwnames, &flags))
6403 {
6404 return NULL;
6405 }
6406 CHECK_ENV_NOT_CLOSED(self);
6407 MYDB_BEGIN_ALLOW_THREADS;
6408 err = self->db_env->lock_stat_print(self->db_env, flags);
6409 MYDB_END_ALLOW_THREADS;
6410 RETURN_IF_ERR();
6411 RETURN_NONE();
6412 }
6413 #endif
6414
6415
6416 static PyObject*
6417 DBEnv_log_cursor(DBEnvObject* self)
6418 {
6419 int err;
6420 DB_LOGC* dblogc;
6421
6422 CHECK_ENV_NOT_CLOSED(self);
6423
6424 MYDB_BEGIN_ALLOW_THREADS;
6425 err = self->db_env->log_cursor(self->db_env, &dblogc, 0);
6426 MYDB_END_ALLOW_THREADS;
6427 RETURN_IF_ERR();
6428 return (PyObject*) newDBLogCursorObject(dblogc, self);
6429 }
6430
6431
6432 static PyObject*
6433 DBEnv_log_flush(DBEnvObject* self)
6434 {
6435 int err;
6436
6437 CHECK_ENV_NOT_CLOSED(self);
6438
6439 MYDB_BEGIN_ALLOW_THREADS
6440 err = self->db_env->log_flush(self->db_env, NULL);
6441 MYDB_END_ALLOW_THREADS
6442
6443 RETURN_IF_ERR();
6444 RETURN_NONE();
6445 }
6446
6447 static PyObject*
6448 DBEnv_log_file(DBEnvObject* self, PyObject* args)
6449 {
6450 int err;
6451 DB_LSN lsn = {0, 0};
6452 int size = 20;
6453 char *name = NULL;
6454 PyObject *retval;
6455
6456 if (!PyArg_ParseTuple(args, "(ii):log_file", &lsn.file, &lsn.offset))
6457 return NULL;
6458
6459 CHECK_ENV_NOT_CLOSED(self);
6460
6461 do {
6462 name = malloc(size);
6463 if (!name) {
6464 PyErr_NoMemory();
6465 return NULL;
6466 }
6467 MYDB_BEGIN_ALLOW_THREADS;
6468 err = self->db_env->log_file(self->db_env, &lsn, name, size);
6469 MYDB_END_ALLOW_THREADS;
6470 if (err == EINVAL) {
6471 free(name);
6472 size *= 2;
6473 } else if (err) {
6474 free(name);
6475 RETURN_IF_ERR();
6476 assert(0); /* Unreachable... supposely */
6477 return NULL;
6478 }
6479 /*
6480 ** If the final buffer we try is too small, we will
6481 ** get this exception:
6482 ** DBInvalidArgError:
6483 ** (22, 'Invalid argument -- DB_ENV->log_file: name buffer is too short')
6484 */
6485 } while ((err == EINVAL) && (size<(1<<17)));
6486
6487 RETURN_IF_ERR(); /* Maybe the size is not the problem */
6488
6489 retval = Py_BuildValue("s", name);
6490 free(name);
6491 return retval;
6492 }
6493
6494
6495 #if (DBVER >= 44)
6496 static PyObject*
6497 DBEnv_log_printf(DBEnvObject* self, PyObject* args, PyObject *kwargs)
6498 {
6499 int err;
6500 char *string;
6501 PyObject *txnobj = NULL;
6502 DB_TXN *txn = NULL;
6503 static char* kwnames[] = {"string", "txn", NULL };
6504
6505 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|O:log_printf", kwnames,
6506 &string, &txnobj))
6507 return NULL;
6508
6509 CHECK_ENV_NOT_CLOSED(self);
6510
6511 if (!checkTxnObj(txnobj, &txn))
6512 return NULL;
6513
6514 /*
6515 ** Do not use the format string directly, to avoid attacks.
6516 */
6517 MYDB_BEGIN_ALLOW_THREADS;
6518 err = self->db_env->log_printf(self->db_env, txn, "%s", string);
6519 MYDB_END_ALLOW_THREADS;
6520
6521 RETURN_IF_ERR();
6522 RETURN_NONE();
6523 }
6524 #endif
6525
6526
6527 static PyObject*
6528 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
6529 {
6530 int flags=0;
6531 int err;
6532 char **log_list = NULL;
6533 PyObject* list;
6534 PyObject* item = NULL;
6535
6536 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
6537 return NULL;
6538
6539 CHECK_ENV_NOT_CLOSED(self);
6540 MYDB_BEGIN_ALLOW_THREADS;
6541 err = self->db_env->log_archive(self->db_env, &log_list, flags);
6542 MYDB_END_ALLOW_THREADS;
6543 RETURN_IF_ERR();
6544
6545 list = PyList_New(0);
6546 if (list == NULL) {
6547 if (log_list)
6548 free(log_list);
6549 return NULL;
6550 }
6551
6552 if (log_list) {
6553 char **log_list_start;
6554 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
6555 item = PyBytes_FromString (*log_list);
6556 if (item == NULL) {
6557 Py_DECREF(list);
6558 list = NULL;
6559 break;
6560 }
6561 if (PyList_Append(list, item)) {
6562 Py_DECREF(list);
6563 list = NULL;
6564 Py_DECREF(item);
6565 break;
6566 }
6567 Py_DECREF(item);
6568 }
6569 free(log_list_start);
6570 }
6571 return list;
6572 }
6573
6574
6575 #if (DBVER >= 44)
6576 static PyObject*
6577 DBEnv_mutex_stat(DBEnvObject* self, PyObject* args)
6578 {
6579 int err;
6580 DB_MUTEX_STAT* statp = NULL;
6581 PyObject* d = NULL;
6582 u_int32_t flags = 0;
6583
6584 if (!PyArg_ParseTuple(args, "|i:mutex_stat", &flags))
6585 return NULL;
6586 CHECK_ENV_NOT_CLOSED(self);
6587
6588 MYDB_BEGIN_ALLOW_THREADS;
6589 err = self->db_env->mutex_stat(self->db_env, &statp, flags);
6590 MYDB_END_ALLOW_THREADS;
6591 RETURN_IF_ERR();
6592
6593 /* Turn the stat structure into a dictionary */
6594 d = PyDict_New();
6595 if (d == NULL) {
6596 if (statp)
6597 free(statp);
6598 return NULL;
6599 }
6600
6601 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
6602
6603 MAKE_ENTRY(mutex_align);
6604 MAKE_ENTRY(mutex_tas_spins);
6605 MAKE_ENTRY(mutex_cnt);
6606 MAKE_ENTRY(mutex_free);
6607 MAKE_ENTRY(mutex_inuse);
6608 MAKE_ENTRY(mutex_inuse_max);
6609 MAKE_ENTRY(regsize);
6610 MAKE_ENTRY(region_wait);
6611 MAKE_ENTRY(region_nowait);
6612
6613 #undef MAKE_ENTRY
6614 free(statp);
6615 return d;
6616 }
6617 #endif
6618
6619
6620 #if (DBVER >= 44)
6621 static PyObject*
6622 DBEnv_mutex_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
6623 {
6624 int err;
6625 int flags=0;
6626 static char* kwnames[] = { "flags", NULL };
6627
6628 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:mutex_stat_print",
6629 kwnames, &flags))
6630 {
6631 return NULL;
6632 }
6633 CHECK_ENV_NOT_CLOSED(self);
6634 MYDB_BEGIN_ALLOW_THREADS;
6635 err = self->db_env->mutex_stat_print(self->db_env, flags);
6636 MYDB_END_ALLOW_THREADS;
6637 RETURN_IF_ERR();
6638 RETURN_NONE();
6639 }
6640 #endif
6641
6642
6643 #if (DBVER >= 43)
6644 static PyObject*
6645 DBEnv_txn_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
6646 {
6647 int err;
6648 int flags=0;
6649 static char* kwnames[] = { "flags", NULL };
6650
6651 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
6652 kwnames, &flags))
6653 {
6654 return NULL;
6655 }
6656
6657 CHECK_ENV_NOT_CLOSED(self);
6658
6659 MYDB_BEGIN_ALLOW_THREADS;
6660 err = self->db_env->txn_stat_print(self->db_env, flags);
6661 MYDB_END_ALLOW_THREADS;
6662 RETURN_IF_ERR();
6663 RETURN_NONE();
6664 }
6665 #endif
6666
6667
6668 static PyObject*
6669 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
6670 {
6671 int err;
6672 DB_TXN_STAT* sp;
6673 PyObject* d = NULL;
6674 u_int32_t flags=0;
6675
6676 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
6677 return NULL;
6678 CHECK_ENV_NOT_CLOSED(self);
6679
6680 MYDB_BEGIN_ALLOW_THREADS;
6681 err = self->db_env->txn_stat(self->db_env, &sp, flags);
6682 MYDB_END_ALLOW_THREADS;
6683 RETURN_IF_ERR();
6684
6685 /* Turn the stat structure into a dictionary */
6686 d = PyDict_New();
6687 if (d == NULL) {
6688 free(sp);
6689 return NULL;
6690 }
6691
6692 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
6693 #define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
6694 #define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
6695
6696 MAKE_DB_LSN_ENTRY(last_ckp);
6697 MAKE_TIME_T_ENTRY(time_ckp);
6698 MAKE_ENTRY(last_txnid);
6699 MAKE_ENTRY(maxtxns);
6700 MAKE_ENTRY(nactive);
6701 MAKE_ENTRY(maxnactive);
6702 #if (DBVER >= 45)
6703 MAKE_ENTRY(nsnapshot);
6704 MAKE_ENTRY(maxnsnapshot);
6705 #endif
6706 MAKE_ENTRY(nbegins);
6707 MAKE_ENTRY(naborts);
6708 MAKE_ENTRY(ncommits);
6709 MAKE_ENTRY(nrestores);
6710 MAKE_ENTRY(regsize);
6711 MAKE_ENTRY(region_wait);
6712 MAKE_ENTRY(region_nowait);
6713
6714 #undef MAKE_DB_LSN_ENTRY
6715 #undef MAKE_ENTRY
6716 #undef MAKE_TIME_T_ENTRY
6717 free(sp);
6718 return d;
6719 }
6720
6721
6722 static PyObject*
6723 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
6724 {
6725 int flags=0;
6726 int oldValue=0;
6727
6728 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
6729 return NULL;
6730 CHECK_ENV_NOT_CLOSED(self);
6731
6732 if (self->moduleFlags.getReturnsNone)
6733 ++oldValue;
6734 if (self->moduleFlags.cursorSetReturnsNone)
6735 ++oldValue;
6736 self->moduleFlags.getReturnsNone = (flags >= 1);
6737 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
6738 return NUMBER_FromLong(oldValue);
6739 }
6740
6741 static PyObject*
6742 DBEnv_get_private(DBEnvObject* self)
6743 {
6744 /* We can give out the private field even if dbenv is closed */
6745 Py_INCREF(self->private_obj);
6746 return self->private_obj;
6747 }
6748
6749 static PyObject*
6750 DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
6751 {
6752 /* We can set the private field even if dbenv is closed */
6753 Py_DECREF(self->private_obj);
6754 Py_INCREF(private_obj);
6755 self->private_obj = private_obj;
6756 RETURN_NONE();
6757 }
6758
6759
6760 #if (DBVER < 48)
6761 static PyObject*
6762 DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
6763 {
6764 int err;
6765 char *host;
6766 long cl_timeout=0, sv_timeout=0;
6767
6768 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
6769
6770 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
6771 &host, &cl_timeout, &sv_timeout))
6772 return NULL;
6773 CHECK_ENV_NOT_CLOSED(self);
6774
6775 MYDB_BEGIN_ALLOW_THREADS;
6776 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
6777 sv_timeout, 0);
6778 MYDB_END_ALLOW_THREADS;
6779 RETURN_IF_ERR();
6780 RETURN_NONE();
6781 }
6782 #endif
6783
6784 #if (DBVER >= 43)
6785 static PyObject*
6786 DBEnv_set_mp_max_openfd(DBEnvObject* self, PyObject* args)
6787 {
6788 int err;
6789 int maxopenfd;
6790
6791 if (!PyArg_ParseTuple(args, "i:set_mp_max_openfd", &maxopenfd)) {
6792 return NULL;
6793 }
6794 CHECK_ENV_NOT_CLOSED(self);
6795 MYDB_BEGIN_ALLOW_THREADS;
6796 err = self->db_env->set_mp_max_openfd(self->db_env, maxopenfd);
6797 MYDB_END_ALLOW_THREADS;
6798 RETURN_IF_ERR();
6799 RETURN_NONE();
6800 }
6801
6802 static PyObject*
6803 DBEnv_get_mp_max_openfd(DBEnvObject* self)
6804 {
6805 int err;
6806 int maxopenfd;
6807
6808 CHECK_ENV_NOT_CLOSED(self);
6809
6810 MYDB_BEGIN_ALLOW_THREADS;
6811 err = self->db_env->get_mp_max_openfd(self->db_env, &maxopenfd);
6812 MYDB_END_ALLOW_THREADS;
6813 RETURN_IF_ERR();
6814 return NUMBER_FromLong(maxopenfd);
6815 }
6816
6817
6818 static PyObject*
6819 DBEnv_set_mp_max_write(DBEnvObject* self, PyObject* args)
6820 {
6821 int err;
6822 int maxwrite, maxwrite_sleep;
6823
6824 if (!PyArg_ParseTuple(args, "ii:set_mp_max_write", &maxwrite,
6825 &maxwrite_sleep)) {
6826 return NULL;
6827 }
6828 CHECK_ENV_NOT_CLOSED(self);
6829 MYDB_BEGIN_ALLOW_THREADS;
6830 err = self->db_env->set_mp_max_write(self->db_env, maxwrite,
6831 maxwrite_sleep);
6832 MYDB_END_ALLOW_THREADS;
6833 RETURN_IF_ERR();
6834 RETURN_NONE();
6835 }
6836
6837 static PyObject*
6838 DBEnv_get_mp_max_write(DBEnvObject* self)
6839 {
6840 int err;
6841 int maxwrite;
6842 #if (DBVER >= 46)
6843 db_timeout_t maxwrite_sleep;
6844 #else
6845 int maxwrite_sleep;
6846 #endif
6847
6848 CHECK_ENV_NOT_CLOSED(self);
6849
6850 MYDB_BEGIN_ALLOW_THREADS;
6851 err = self->db_env->get_mp_max_write(self->db_env, &maxwrite,
6852 &maxwrite_sleep);
6853 MYDB_END_ALLOW_THREADS;
6854 RETURN_IF_ERR();
6855
6856 return Py_BuildValue("(ii)", maxwrite, (int)maxwrite_sleep);
6857 }
6858 #endif
6859
6860
6861 static PyObject*
6862 DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
6863 {
6864 int err;
6865 int which, onoff;
6866
6867 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
6868 return NULL;
6869 }
6870 CHECK_ENV_NOT_CLOSED(self);
6871 MYDB_BEGIN_ALLOW_THREADS;
6872 err = self->db_env->set_verbose(self->db_env, which, onoff);
6873 MYDB_END_ALLOW_THREADS;
6874 RETURN_IF_ERR();
6875 RETURN_NONE();
6876 }
6877
6878 #if (DBVER >= 42)
6879 static PyObject*
6880 DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
6881 {
6882 int err;
6883 int which;
6884 int verbose;
6885
6886 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
6887 return NULL;
6888 }
6889 CHECK_ENV_NOT_CLOSED(self);
6890 MYDB_BEGIN_ALLOW_THREADS;
6891 err = self->db_env->get_verbose(self->db_env, which, &verbose);
6892 MYDB_END_ALLOW_THREADS;
6893 RETURN_IF_ERR();
6894 return PyBool_FromLong(verbose);
6895 }
6896 #endif
6897
6898 #if (DBVER >= 45)
6899 static void
6900 _dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
6901 {
6902 DBEnvObject *dbenv;
6903 PyObject* callback;
6904 PyObject* args;
6905 PyObject* result = NULL;
6906
6907 MYDB_BEGIN_BLOCK_THREADS;
6908 dbenv = (DBEnvObject *)db_env->app_private;
6909 callback = dbenv->event_notifyCallback;
6910 if (callback) {
6911 if (event == DB_EVENT_REP_NEWMASTER) {
6912 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
6913 } else {
6914 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
6915 }
6916 if (args) {
6917 result = PyEval_CallObject(callback, args);
6918 }
6919 if ((!args) || (!result)) {
6920 PyErr_Print();
6921 }
6922 Py_XDECREF(args);
6923 Py_XDECREF(result);
6924 }
6925 MYDB_END_BLOCK_THREADS;
6926 }
6927 #endif
6928
6929 #if (DBVER >= 45)
6930 static PyObject*
6931 DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
6932 {
6933 int err;
6934
6935 CHECK_ENV_NOT_CLOSED(self);
6936
6937 if (!PyCallable_Check(notifyFunc)) {
6938 makeTypeError("Callable", notifyFunc);
6939 return NULL;
6940 }
6941
6942 Py_XDECREF(self->event_notifyCallback);
6943 Py_INCREF(notifyFunc);
6944 self->event_notifyCallback = notifyFunc;
6945
6946 /* This is to workaround a problem with un-initialized threads (see
6947 comment in DB_associate) */
6948 #ifdef WITH_THREAD
6949 PyEval_InitThreads();
6950 #endif
6951
6952 MYDB_BEGIN_ALLOW_THREADS;
6953 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
6954 MYDB_END_ALLOW_THREADS;
6955
6956 if (err) {
6957 Py_DECREF(notifyFunc);
6958 self->event_notifyCallback = NULL;
6959 }
6960
6961 RETURN_IF_ERR();
6962 RETURN_NONE();
6963 }
6964 #endif
6965
6966
6967 /* --------------------------------------------------------------------- */
6968 /* REPLICATION METHODS: Base Replication */
6969
6970
6971 static PyObject*
6972 DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
6973 {
6974 int err;
6975 PyObject *control_py, *rec_py;
6976 DBT control, rec;
6977 int envid;
6978 #if (DBVER >= 42)
6979 DB_LSN lsn;
6980 #endif
6981
6982 if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
6983 &rec_py, &envid))
6984 return NULL;
6985 CHECK_ENV_NOT_CLOSED(self);
6986
6987 if (!make_dbt(control_py, &control))
6988 return NULL;
6989 if (!make_dbt(rec_py, &rec))
6990 return NULL;
6991
6992 MYDB_BEGIN_ALLOW_THREADS;
6993 #if (DBVER >= 46)
6994 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
6995 envid, &lsn);
6996 #else
6997 #if (DBVER >= 42)
6998 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
6999 &envid, &lsn);
7000 #else
7001 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
7002 &envid);
7003 #endif
7004 #endif
7005 MYDB_END_ALLOW_THREADS;
7006 switch (err) {
7007 case DB_REP_NEWMASTER :
7008 return Py_BuildValue("(iO)", envid, Py_None);
7009 break;
7010
7011 case DB_REP_DUPMASTER :
7012 case DB_REP_HOLDELECTION :
7013 #if (DBVER >= 44)
7014 case DB_REP_IGNORE :
7015 case DB_REP_JOIN_FAILURE :
7016 #endif
7017 return Py_BuildValue("(iO)", err, Py_None);
7018 break;
7019 case DB_REP_NEWSITE :
7020 {
7021 PyObject *tmp, *r;
7022
7023 if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
7024 return NULL;
7025 }
7026
7027 r = Py_BuildValue("(iO)", err, tmp);
7028 Py_DECREF(tmp);
7029 return r;
7030 break;
7031 }
7032 #if (DBVER >= 42)
7033 case DB_REP_NOTPERM :
7034 case DB_REP_ISPERM :
7035 return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
7036 break;
7037 #endif
7038 }
7039 RETURN_IF_ERR();
7040 return Py_BuildValue("(OO)", Py_None, Py_None);
7041 }
7042
7043 static int
7044 _DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
7045 const DB_LSN *lsn, int envid, u_int32_t flags)
7046 {
7047 DBEnvObject *dbenv;
7048 PyObject* rep_transport;
7049 PyObject* args;
7050 PyObject *a, *b;
7051 PyObject* result = NULL;
7052 int ret=0;
7053
7054 MYDB_BEGIN_BLOCK_THREADS;
7055 dbenv = (DBEnvObject *)db_env->app_private;
7056 rep_transport = dbenv->rep_transport;
7057
7058 /*
7059 ** The errors in 'a' or 'b' are detected in "Py_BuildValue".
7060 */
7061 a = PyBytes_FromStringAndSize(control->data, control->size);
7062 b = PyBytes_FromStringAndSize(rec->data, rec->size);
7063
7064 args = Py_BuildValue(
7065 #if (PY_VERSION_HEX >= 0x02040000)
7066 "(OOO(ll)iI)",
7067 #else
7068 "(OOO(ll)ii)",
7069 #endif
7070 dbenv,
7071 a, b,
7072 lsn->file, lsn->offset, envid, flags);
7073 if (args) {
7074 result = PyEval_CallObject(rep_transport, args);
7075 }
7076
7077 if ((!args) || (!result)) {
7078 PyErr_Print();
7079 ret = -1;
7080 }
7081 Py_XDECREF(a);
7082 Py_XDECREF(b);
7083 Py_XDECREF(args);
7084 Py_XDECREF(result);
7085 MYDB_END_BLOCK_THREADS;
7086 return ret;
7087 }
7088
7089 #if (DBVER <= 41)
7090 static int
7091 _DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec,
7092 int envid, u_int32_t flags)
7093 {
7094 DB_LSN lsn;
7095
7096 lsn.file = -1; /* Dummy values */
7097 lsn.offset = -1;
7098 return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid,
7099 flags);
7100 }
7101 #endif
7102
7103 static PyObject*
7104 DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
7105 {
7106 int err;
7107 int envid;
7108 PyObject *rep_transport;
7109
7110 if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
7111 return NULL;
7112 CHECK_ENV_NOT_CLOSED(self);
7113 if (!PyCallable_Check(rep_transport)) {
7114 makeTypeError("Callable", rep_transport);
7115 return NULL;
7116 }
7117
7118 MYDB_BEGIN_ALLOW_THREADS;
7119 #if (DBVER >=45)
7120 err = self->db_env->rep_set_transport(self->db_env, envid,
7121 &_DBEnv_rep_transportCallback);
7122 #else
7123 #if (DBVER >= 42)
7124 err = self->db_env->set_rep_transport(self->db_env, envid,
7125 &_DBEnv_rep_transportCallback);
7126 #else
7127 err = self->db_env->set_rep_transport(self->db_env, envid,
7128 &_DBEnv_rep_transportCallbackOLD);
7129 #endif
7130 #endif
7131 MYDB_END_ALLOW_THREADS;
7132 RETURN_IF_ERR();
7133
7134 Py_DECREF(self->rep_transport);
7135 Py_INCREF(rep_transport);
7136 self->rep_transport = rep_transport;
7137 RETURN_NONE();
7138 }
7139
7140 #if (DBVER >= 47)
7141 static PyObject*
7142 DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
7143 {
7144 int err;
7145 unsigned int minimum, maximum;
7146
7147 if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
7148 return NULL;
7149 CHECK_ENV_NOT_CLOSED(self);
7150
7151 MYDB_BEGIN_ALLOW_THREADS;
7152 err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
7153 MYDB_END_ALLOW_THREADS;
7154 RETURN_IF_ERR();
7155 RETURN_NONE();
7156 }
7157
7158 static PyObject*
7159 DBEnv_rep_get_request(DBEnvObject* self)
7160 {
7161 int err;
7162 u_int32_t minimum, maximum;
7163
7164 CHECK_ENV_NOT_CLOSED(self);
7165 MYDB_BEGIN_ALLOW_THREADS;
7166 err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
7167 MYDB_END_ALLOW_THREADS;
7168 RETURN_IF_ERR();
7169 #if (PY_VERSION_HEX >= 0x02040000)
7170 return Py_BuildValue("II", minimum, maximum);
7171 #else
7172 return Py_BuildValue("ii", minimum, maximum);
7173 #endif
7174 }
7175 #endif
7176
7177 #if (DBVER >= 45)
7178 static PyObject*
7179 DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
7180 {
7181 int err;
7182 int limit;
7183
7184 if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
7185 return NULL;
7186 CHECK_ENV_NOT_CLOSED(self);
7187
7188 MYDB_BEGIN_ALLOW_THREADS;
7189 err = self->db_env->rep_set_limit(self->db_env, 0, limit);
7190 MYDB_END_ALLOW_THREADS;
7191 RETURN_IF_ERR();
7192 RETURN_NONE();
7193 }
7194
7195 static PyObject*
7196 DBEnv_rep_get_limit(DBEnvObject* self)
7197 {
7198 int err;
7199 u_int32_t gbytes, bytes;
7200
7201 CHECK_ENV_NOT_CLOSED(self);
7202 MYDB_BEGIN_ALLOW_THREADS;
7203 err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
7204 MYDB_END_ALLOW_THREADS;
7205 RETURN_IF_ERR();
7206 return NUMBER_FromLong(bytes);
7207 }
7208 #endif
7209
7210 #if (DBVER >= 44)
7211 static PyObject*
7212 DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
7213 {
7214 int err;
7215 int which;
7216 int onoff;
7217
7218 if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
7219 return NULL;
7220 CHECK_ENV_NOT_CLOSED(self);
7221
7222 MYDB_BEGIN_ALLOW_THREADS;
7223 err = self->db_env->rep_set_config(self->db_env, which, onoff);
7224 MYDB_END_ALLOW_THREADS;
7225 RETURN_IF_ERR();
7226 RETURN_NONE();
7227 }
7228
7229 static PyObject*
7230 DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
7231 {
7232 int err;
7233 int which;
7234 int onoff;
7235
7236 if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
7237 return NULL;
7238 }
7239 CHECK_ENV_NOT_CLOSED(self);
7240 MYDB_BEGIN_ALLOW_THREADS;
7241 err = self->db_env->rep_get_config(self->db_env, which, &onoff);
7242 MYDB_END_ALLOW_THREADS;
7243 RETURN_IF_ERR();
7244 return PyBool_FromLong(onoff);
7245 }
7246 #endif
7247
7248 #if (DBVER >= 46)
7249 static PyObject*
7250 DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
7251 {
7252 int err;
7253 u_int32_t nsites, nvotes;
7254
7255 if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
7256 return NULL;
7257 }
7258 CHECK_ENV_NOT_CLOSED(self);
7259 MYDB_BEGIN_ALLOW_THREADS;
7260 err = self->db_env->rep_elect(self->db_env, nsites, nvotes, 0);
7261 MYDB_END_ALLOW_THREADS;
7262 RETURN_IF_ERR();
7263 RETURN_NONE();
7264 }
7265 #endif
7266
7267 static PyObject*
7268 DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
7269 {
7270 int err;
7271 PyObject *cdata_py = Py_None;
7272 DBT cdata;
7273 int flags;
7274 static char* kwnames[] = {"flags","cdata", NULL};
7275
7276 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
7277 "i|O:rep_start", kwnames, &flags, &cdata_py))
7278 {
7279 return NULL;
7280 }
7281 CHECK_ENV_NOT_CLOSED(self);
7282
7283 if (!make_dbt(cdata_py, &cdata))
7284 return NULL;
7285
7286 MYDB_BEGIN_ALLOW_THREADS;
7287 err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
7288 flags);
7289 MYDB_END_ALLOW_THREADS;
7290 RETURN_IF_ERR();
7291 RETURN_NONE();
7292 }
7293
7294 #if (DBVER >= 44)
7295 static PyObject*
7296 DBEnv_rep_sync(DBEnvObject* self)
7297 {
7298 int err;
7299
7300 CHECK_ENV_NOT_CLOSED(self);
7301 MYDB_BEGIN_ALLOW_THREADS;
7302 err = self->db_env->rep_sync(self->db_env, 0);
7303 MYDB_END_ALLOW_THREADS;
7304 RETURN_IF_ERR();
7305 RETURN_NONE();
7306 }
7307 #endif
7308
7309
7310 #if (DBVER >= 45)
7311 static PyObject*
7312 DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
7313 {
7314 int err;
7315 int nsites;
7316
7317 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
7318 return NULL;
7319 }
7320 CHECK_ENV_NOT_CLOSED(self);
7321 MYDB_BEGIN_ALLOW_THREADS;
7322 err = self->db_env->rep_set_nsites(self->db_env, nsites);
7323 MYDB_END_ALLOW_THREADS;
7324 RETURN_IF_ERR();
7325 RETURN_NONE();
7326 }
7327
7328 static PyObject*
7329 DBEnv_rep_get_nsites(DBEnvObject* self)
7330 {
7331 int err;
7332 #if (DBVER >= 47)
7333 u_int32_t nsites;
7334 #else
7335 int nsites;
7336 #endif
7337
7338 CHECK_ENV_NOT_CLOSED(self);
7339 MYDB_BEGIN_ALLOW_THREADS;
7340 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
7341 MYDB_END_ALLOW_THREADS;
7342 RETURN_IF_ERR();
7343 return NUMBER_FromLong(nsites);
7344 }
7345
7346 static PyObject*
7347 DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
7348 {
7349 int err;
7350 int priority;
7351
7352 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
7353 return NULL;
7354 }
7355 CHECK_ENV_NOT_CLOSED(self);
7356 MYDB_BEGIN_ALLOW_THREADS;
7357 err = self->db_env->rep_set_priority(self->db_env, priority);
7358 MYDB_END_ALLOW_THREADS;
7359 RETURN_IF_ERR();
7360 RETURN_NONE();
7361 }
7362
7363 static PyObject*
7364 DBEnv_rep_get_priority(DBEnvObject* self)
7365 {
7366 int err;
7367 #if (DBVER >= 47)
7368 u_int32_t priority;
7369 #else
7370 int priority;
7371 #endif
7372
7373 CHECK_ENV_NOT_CLOSED(self);
7374 MYDB_BEGIN_ALLOW_THREADS;
7375 err = self->db_env->rep_get_priority(self->db_env, &priority);
7376 MYDB_END_ALLOW_THREADS;
7377 RETURN_IF_ERR();
7378 return NUMBER_FromLong(priority);
7379 }
7380
7381 static PyObject*
7382 DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
7383 {
7384 int err;
7385 int which, timeout;
7386
7387 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
7388 return NULL;
7389 }
7390 CHECK_ENV_NOT_CLOSED(self);
7391 MYDB_BEGIN_ALLOW_THREADS;
7392 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
7393 MYDB_END_ALLOW_THREADS;
7394 RETURN_IF_ERR();
7395 RETURN_NONE();
7396 }
7397
7398 static PyObject*
7399 DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
7400 {
7401 int err;
7402 int which;
7403 u_int32_t timeout;
7404
7405 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
7406 return NULL;
7407 }
7408 CHECK_ENV_NOT_CLOSED(self);
7409 MYDB_BEGIN_ALLOW_THREADS;
7410 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
7411 MYDB_END_ALLOW_THREADS;
7412 RETURN_IF_ERR();
7413 return NUMBER_FromLong(timeout);
7414 }
7415 #endif
7416
7417
7418 #if (DBVER >= 47)
7419 static PyObject*
7420 DBEnv_rep_set_clockskew(DBEnvObject* self, PyObject* args)
7421 {
7422 int err;
7423 unsigned int fast, slow;
7424
7425 #if (PY_VERSION_HEX >= 0x02040000)
7426 if (!PyArg_ParseTuple(args,"II:rep_set_clockskew", &fast, &slow))
7427 return NULL;
7428 #else
7429 if (!PyArg_ParseTuple(args,"ii:rep_set_clockskew", &fast, &slow))
7430 return NULL;
7431 #endif
7432
7433 CHECK_ENV_NOT_CLOSED(self);
7434
7435 MYDB_BEGIN_ALLOW_THREADS;
7436 err = self->db_env->rep_set_clockskew(self->db_env, fast, slow);
7437 MYDB_END_ALLOW_THREADS;
7438 RETURN_IF_ERR();
7439 RETURN_NONE();
7440 }
7441
7442 static PyObject*
7443 DBEnv_rep_get_clockskew(DBEnvObject* self)
7444 {
7445 int err;
7446 unsigned int fast, slow;
7447
7448 CHECK_ENV_NOT_CLOSED(self);
7449 MYDB_BEGIN_ALLOW_THREADS;
7450 err = self->db_env->rep_get_clockskew(self->db_env, &fast, &slow);
7451 MYDB_END_ALLOW_THREADS;
7452 RETURN_IF_ERR();
7453 #if (PY_VERSION_HEX >= 0x02040000)
7454 return Py_BuildValue("(II)", fast, slow);
7455 #else
7456 return Py_BuildValue("(ii)", fast, slow);
7457 #endif
7458 }
7459 #endif
7460
7461 #if (DBVER >= 43)
7462 static PyObject*
7463 DBEnv_rep_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
7464 {
7465 int err;
7466 int flags=0;
7467 static char* kwnames[] = { "flags", NULL };
7468
7469 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:rep_stat_print",
7470 kwnames, &flags))
7471 {
7472 return NULL;
7473 }
7474 CHECK_ENV_NOT_CLOSED(self);
7475 MYDB_BEGIN_ALLOW_THREADS;
7476 err = self->db_env->rep_stat_print(self->db_env, flags);
7477 MYDB_END_ALLOW_THREADS;
7478 RETURN_IF_ERR();
7479 RETURN_NONE();
7480 }
7481 #endif
7482
7483 static PyObject*
7484 DBEnv_rep_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
7485 {
7486 int err;
7487 int flags=0;
7488 DB_REP_STAT *statp;
7489 PyObject *stats;
7490 static char* kwnames[] = { "flags", NULL };
7491
7492 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:rep_stat",
7493 kwnames, &flags))
7494 {
7495 return NULL;
7496 }
7497 CHECK_ENV_NOT_CLOSED(self);
7498 MYDB_BEGIN_ALLOW_THREADS;
7499 err = self->db_env->rep_stat(self->db_env, &statp, flags);
7500 MYDB_END_ALLOW_THREADS;
7501 RETURN_IF_ERR();
7502
7503 stats=PyDict_New();
7504 if (stats == NULL) {
7505 free(statp);
7506 return NULL;
7507 }
7508
7509 #define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
7510 #define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(stats , #name, statp->st_##name)
7511
7512 #if (DBVER >= 44)
7513 MAKE_ENTRY(bulk_fills);
7514 MAKE_ENTRY(bulk_overflows);
7515 MAKE_ENTRY(bulk_records);
7516 MAKE_ENTRY(bulk_transfers);
7517 MAKE_ENTRY(client_rerequests);
7518 MAKE_ENTRY(client_svc_miss);
7519 MAKE_ENTRY(client_svc_req);
7520 #endif
7521 MAKE_ENTRY(dupmasters);
7522 #if (DBVER >= 43)
7523 MAKE_ENTRY(egen);
7524 MAKE_ENTRY(election_nvotes);
7525 MAKE_ENTRY(startup_complete);
7526 MAKE_ENTRY(pg_duplicated);
7527 MAKE_ENTRY(pg_records);
7528 MAKE_ENTRY(pg_requested);
7529 MAKE_ENTRY(next_pg);
7530 MAKE_ENTRY(waiting_pg);
7531 #endif
7532 MAKE_ENTRY(election_cur_winner);
7533 MAKE_ENTRY(election_gen);
7534 MAKE_DB_LSN_ENTRY(election_lsn);
7535 MAKE_ENTRY(election_nsites);
7536 MAKE_ENTRY(election_priority);
7537 #if (DBVER >= 44)
7538 MAKE_ENTRY(election_sec);
7539 MAKE_ENTRY(election_usec);
7540 #endif
7541 MAKE_ENTRY(election_status);
7542 MAKE_ENTRY(election_tiebreaker);
7543 MAKE_ENTRY(election_votes);
7544 MAKE_ENTRY(elections);
7545 MAKE_ENTRY(elections_won);
7546 MAKE_ENTRY(env_id);
7547 MAKE_ENTRY(env_priority);
7548 MAKE_ENTRY(gen);
7549 MAKE_ENTRY(log_duplicated);
7550 MAKE_ENTRY(log_queued);
7551 MAKE_ENTRY(log_queued_max);
7552 MAKE_ENTRY(log_queued_total);
7553 MAKE_ENTRY(log_records);
7554 MAKE_ENTRY(log_requested);
7555 MAKE_ENTRY(master);
7556 MAKE_ENTRY(master_changes);
7557 #if (DBVER >= 47)
7558 MAKE_ENTRY(max_lease_sec);
7559 MAKE_ENTRY(max_lease_usec);
7560 MAKE_DB_LSN_ENTRY(max_perm_lsn);
7561 #endif
7562 MAKE_ENTRY(msgs_badgen);
7563 MAKE_ENTRY(msgs_processed);
7564 MAKE_ENTRY(msgs_recover);
7565 MAKE_ENTRY(msgs_send_failures);
7566 MAKE_ENTRY(msgs_sent);
7567 MAKE_ENTRY(newsites);
7568 MAKE_DB_LSN_ENTRY(next_lsn);
7569 MAKE_ENTRY(nsites);
7570 MAKE_ENTRY(nthrottles);
7571 MAKE_ENTRY(outdated);
7572 #if (DBVER >= 46)
7573 MAKE_ENTRY(startsync_delayed);
7574 #endif
7575 MAKE_ENTRY(status);
7576 MAKE_ENTRY(txns_applied);
7577 MAKE_DB_LSN_ENTRY(waiting_lsn);
7578
7579 #undef MAKE_DB_LSN_ENTRY
7580 #undef MAKE_ENTRY
7581
7582 free(statp);
7583 return stats;
7584 }
7585
7586 /* --------------------------------------------------------------------- */
7587 /* REPLICATION METHODS: Replication Manager */
7588
7589 #if (DBVER >= 45)
7590 static PyObject*
7591 DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
7592 kwargs)
7593 {
7594 int err;
7595 int nthreads, flags;
7596 static char* kwnames[] = {"nthreads","flags", NULL};
7597
7598 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
7599 "ii:repmgr_start", kwnames, &nthreads, &flags))
7600 {
7601 return NULL;
7602 }
7603 CHECK_ENV_NOT_CLOSED(self);
7604 MYDB_BEGIN_ALLOW_THREADS;
7605 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
7606 MYDB_END_ALLOW_THREADS;
7607 RETURN_IF_ERR();
7608 RETURN_NONE();
7609 }
7610
7611 static PyObject*
7612 DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
7613 kwargs)
7614 {
7615 int err;
7616 char *host;
7617 int port;
7618 int flags = 0;
7619 static char* kwnames[] = {"host", "port", "flags", NULL};
7620
7621 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
7622 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
7623 {
7624 return NULL;
7625 }
7626 CHECK_ENV_NOT_CLOSED(self);
7627 MYDB_BEGIN_ALLOW_THREADS;
7628 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
7629 MYDB_END_ALLOW_THREADS;
7630 RETURN_IF_ERR();
7631 RETURN_NONE();
7632 }
7633
7634 static PyObject*
7635 DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
7636 kwargs)
7637 {
7638 int err;
7639 char *host;
7640 int port;
7641 int flags = 0;
7642 int eidp;
7643 static char* kwnames[] = {"host", "port", "flags", NULL};
7644
7645 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
7646 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
7647 {
7648 return NULL;
7649 }
7650 CHECK_ENV_NOT_CLOSED(self);
7651 MYDB_BEGIN_ALLOW_THREADS;
7652 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
7653 MYDB_END_ALLOW_THREADS;
7654 RETURN_IF_ERR();
7655 return NUMBER_FromLong(eidp);
7656 }
7657
7658 static PyObject*
7659 DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
7660 {
7661 int err;
7662 int ack_policy;
7663
7664 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
7665 {
7666 return NULL;
7667 }
7668 CHECK_ENV_NOT_CLOSED(self);
7669 MYDB_BEGIN_ALLOW_THREADS;
7670 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
7671 MYDB_END_ALLOW_THREADS;
7672 RETURN_IF_ERR();
7673 RETURN_NONE();
7674 }
7675
7676 static PyObject*
7677 DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
7678 {
7679 int err;
7680 int ack_policy;
7681
7682 CHECK_ENV_NOT_CLOSED(self);
7683 MYDB_BEGIN_ALLOW_THREADS;
7684 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
7685 MYDB_END_ALLOW_THREADS;
7686 RETURN_IF_ERR();
7687 return NUMBER_FromLong(ack_policy);
7688 }
7689
7690 static PyObject*
7691 DBEnv_repmgr_site_list(DBEnvObject* self)
7692 {
7693 int err;
7694 unsigned int countp;
7695 DB_REPMGR_SITE *listp;
7696 PyObject *stats, *key, *tuple;
7697
7698 CHECK_ENV_NOT_CLOSED(self);
7699 MYDB_BEGIN_ALLOW_THREADS;
7700 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
7701 MYDB_END_ALLOW_THREADS;
7702 RETURN_IF_ERR();
7703
7704 stats=PyDict_New();
7705 if (stats == NULL) {
7706 free(listp);
7707 return NULL;
7708 }
7709
7710 for(;countp--;) {
7711 key=NUMBER_FromLong(listp[countp].eid);
7712 if(!key) {
7713 Py_DECREF(stats);
7714 free(listp);
7715 return NULL;
7716 }
7717 #if (PY_VERSION_HEX >= 0x02040000)
7718 tuple=Py_BuildValue("(sII)", listp[countp].host,
7719 listp[countp].port, listp[countp].status);
7720 #else
7721 tuple=Py_BuildValue("(sii)", listp[countp].host,
7722 listp[countp].port, listp[countp].status);
7723 #endif
7724 if(!tuple) {
7725 Py_DECREF(key);
7726 Py_DECREF(stats);
7727 free(listp);
7728 return NULL;
7729 }
7730 if(PyDict_SetItem(stats, key, tuple)) {
7731 Py_DECREF(key);
7732 Py_DECREF(tuple);
7733 Py_DECREF(stats);
7734 free(listp);
7735 return NULL;
7736 }
7737 Py_DECREF(key);
7738 Py_DECREF(tuple);
7739 }
7740 free(listp);
7741 return stats;
7742 }
7743 #endif
7744
7745 #if (DBVER >= 46)
7746 static PyObject*
7747 DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
7748 {
7749 int err;
7750 int flags=0;
7751 static char* kwnames[] = { "flags", NULL };
7752
7753 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
7754 kwnames, &flags))
7755 {
7756 return NULL;
7757 }
7758 CHECK_ENV_NOT_CLOSED(self);
7759 MYDB_BEGIN_ALLOW_THREADS;
7760 err = self->db_env->repmgr_stat_print(self->db_env, flags);
7761 MYDB_END_ALLOW_THREADS;
7762 RETURN_IF_ERR();
7763 RETURN_NONE();
7764 }
7765
7766 static PyObject*
7767 DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
7768 {
7769 int err;
7770 int flags=0;
7771 DB_REPMGR_STAT *statp;
7772 PyObject *stats;
7773 static char* kwnames[] = { "flags", NULL };
7774
7775 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
7776 kwnames, &flags))
7777 {
7778 return NULL;
7779 }
7780 CHECK_ENV_NOT_CLOSED(self);
7781 MYDB_BEGIN_ALLOW_THREADS;
7782 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
7783 MYDB_END_ALLOW_THREADS;
7784 RETURN_IF_ERR();
7785
7786 stats=PyDict_New();
7787 if (stats == NULL) {
7788 free(statp);
7789 return NULL;
7790 }
7791
7792 #define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
7793
7794 MAKE_ENTRY(perm_failed);
7795 MAKE_ENTRY(msgs_queued);
7796 MAKE_ENTRY(msgs_dropped);
7797 MAKE_ENTRY(connection_drop);
7798 MAKE_ENTRY(connect_fail);
7799
7800 #undef MAKE_ENTRY
7801
7802 free(statp);
7803 return stats;
7804 }
7805 #endif
7806
7807
7808 /* --------------------------------------------------------------------- */
7809 /* DBTxn methods */
7810
7811
7812 static void _close_transaction_cursors(DBTxnObject* txn)
7813 {
7814 PyObject *dummy;
7815
7816 while(txn->children_cursors) {
7817 PyErr_Warn(PyExc_RuntimeWarning,
7818 "Must close cursors before resolving a transaction.");
7819 dummy=DBC_close_internal(txn->children_cursors);
7820 Py_XDECREF(dummy);
7821 }
7822 }
7823
7824 static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
7825 {
7826 DBObject *db;
7827 #if (DBVER >= 43)
7828 DBSequenceObject *dbs;
7829 #endif
7830
7831 while (txn->children_dbs) {
7832 db=txn->children_dbs;
7833 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
7834 if (txn->parent_txn) {
7835 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
7836 db->txn=txn->parent_txn;
7837 } else {
7838 /* The db is already linked to its environment,
7839 ** so nothing to do.
7840 */
7841 db->txn=NULL;
7842 }
7843 }
7844
7845 #if (DBVER >= 43)
7846 while (txn->children_sequences) {
7847 dbs=txn->children_sequences;
7848 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
7849 if (txn->parent_txn) {
7850 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
7851 dbs->txn=txn->parent_txn;
7852 } else {
7853 /* The sequence is already linked to its
7854 ** parent db. Nothing to do.
7855 */
7856 dbs->txn=NULL;
7857 }
7858 }
7859 #endif
7860 }
7861
7862
7863 static PyObject*
7864 DBTxn_commit(DBTxnObject* self, PyObject* args)
7865 {
7866 int flags=0, err;
7867 DB_TXN *txn;
7868
7869 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
7870 return NULL;
7871
7872 _close_transaction_cursors(self);
7873
7874 if (!self->txn) {
7875 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
7876 "after txn_commit, txn_abort "
7877 "or txn_discard");
7878 if (t) {
7879 PyErr_SetObject(DBError, t);
7880 Py_DECREF(t);
7881 }
7882 return NULL;
7883 }
7884 self->flag_prepare=0;
7885 txn = self->txn;
7886 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
7887
7888 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
7889
7890 MYDB_BEGIN_ALLOW_THREADS;
7891 err = txn->commit(txn, flags);
7892 MYDB_END_ALLOW_THREADS;
7893
7894 _promote_transaction_dbs_and_sequences(self);
7895
7896 RETURN_IF_ERR();
7897 RETURN_NONE();
7898 }
7899
7900 static PyObject*
7901 DBTxn_prepare(DBTxnObject* self, PyObject* args)
7902 {
7903 int err;
7904 char* gid=NULL;
7905 int gid_size=0;
7906
7907 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
7908 return NULL;
7909
7910 if (gid_size != DB_GID_SIZE) {
7911 PyErr_SetString(PyExc_TypeError,
7912 "gid must be DB_GID_SIZE bytes long");
7913 return NULL;
7914 }
7915
7916 if (!self->txn) {
7917 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
7918 "after txn_commit, txn_abort "
7919 "or txn_discard");
7920 if (t) {
7921 PyErr_SetObject(DBError, t);
7922 Py_DECREF(t);
7923 }
7924 return NULL;
7925 }
7926 self->flag_prepare=1; /* Prepare state */
7927 MYDB_BEGIN_ALLOW_THREADS;
7928 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
7929 MYDB_END_ALLOW_THREADS;
7930 RETURN_IF_ERR();
7931 RETURN_NONE();
7932 }
7933
7934
7935 static PyObject*
7936 DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
7937 {
7938 PyObject *dummy;
7939 int err=0;
7940 DB_TXN *txn;
7941
7942 if (!self->txn) {
7943 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
7944 "after txn_commit, txn_abort "
7945 "or txn_discard");
7946 if (t) {
7947 PyErr_SetObject(DBError, t);
7948 Py_DECREF(t);
7949 }
7950 return NULL;
7951 }
7952 txn = self->txn;
7953 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
7954
7955 _close_transaction_cursors(self);
7956 #if (DBVER >= 43)
7957 while (self->children_sequences) {
7958 dummy=DBSequence_close_internal(self->children_sequences,0,0);
7959 Py_XDECREF(dummy);
7960 }
7961 #endif
7962 while (self->children_dbs) {
7963 dummy=DB_close_internal(self->children_dbs, 0, 0);
7964 Py_XDECREF(dummy);
7965 }
7966
7967 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
7968
7969 MYDB_BEGIN_ALLOW_THREADS;
7970 if (discard) {
7971 assert(!self->flag_prepare);
7972 err = txn->discard(txn,0);
7973 } else {
7974 /*
7975 ** If the transaction is in the "prepare" or "recover" state,
7976 ** we better do not implicitly abort it.
7977 */
7978 if (!self->flag_prepare) {
7979 err = txn->abort(txn);
7980 }
7981 }
7982 MYDB_END_ALLOW_THREADS;
7983 RETURN_IF_ERR();
7984 RETURN_NONE();
7985 }
7986
7987 static PyObject*
7988 DBTxn_abort(DBTxnObject* self)
7989 {
7990 self->flag_prepare=0;
7991 _close_transaction_cursors(self);
7992
7993 return DBTxn_abort_discard_internal(self,0);
7994 }
7995
7996 static PyObject*
7997 DBTxn_discard(DBTxnObject* self)
7998 {
7999 self->flag_prepare=0;
8000 _close_transaction_cursors(self);
8001
8002 return DBTxn_abort_discard_internal(self,1);
8003 }
8004
8005
8006 static PyObject*
8007 DBTxn_id(DBTxnObject* self)
8008 {
8009 int id;
8010
8011 if (!self->txn) {
8012 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
8013 "after txn_commit, txn_abort "
8014 "or txn_discard");
8015 if (t) {
8016 PyErr_SetObject(DBError, t);
8017 Py_DECREF(t);
8018 }
8019 return NULL;
8020 }
8021 MYDB_BEGIN_ALLOW_THREADS;
8022 id = self->txn->id(self->txn);
8023 MYDB_END_ALLOW_THREADS;
8024 return NUMBER_FromLong(id);
8025 }
8026
8027
8028 static PyObject*
8029 DBTxn_set_timeout(DBTxnObject* self, PyObject* args, PyObject* kwargs)
8030 {
8031 int err;
8032 u_int32_t flags=0;
8033 u_int32_t timeout = 0;
8034 static char* kwnames[] = { "timeout", "flags", NULL };
8035
8036 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
8037 &timeout, &flags)) {
8038 return NULL;
8039 }
8040
8041 MYDB_BEGIN_ALLOW_THREADS;
8042 err = self->txn->set_timeout(self->txn, (db_timeout_t)timeout, flags);
8043 MYDB_END_ALLOW_THREADS;
8044
8045 RETURN_IF_ERR();
8046 RETURN_NONE();
8047 }
8048
8049
8050 #if (DBVER >= 44)
8051 static PyObject*
8052 DBTxn_set_name(DBTxnObject* self, PyObject* args)
8053 {
8054 int err;
8055 const char *name;
8056
8057 if (!PyArg_ParseTuple(args, "s:set_name", &name))
8058 return NULL;
8059
8060 MYDB_BEGIN_ALLOW_THREADS;
8061 err = self->txn->set_name(self->txn, name);
8062 MYDB_END_ALLOW_THREADS;
8063
8064 RETURN_IF_ERR();
8065 RETURN_NONE();
8066 }
8067 #endif
8068
8069
8070 #if (DBVER >= 44)
8071 static PyObject*
8072 DBTxn_get_name(DBTxnObject* self)
8073 {
8074 int err;
8075 const char *name;
8076
8077 MYDB_BEGIN_ALLOW_THREADS;
8078 err = self->txn->get_name(self->txn, &name);
8079 MYDB_END_ALLOW_THREADS;
8080
8081 RETURN_IF_ERR();
8082 #if (PY_VERSION_HEX < 0x03000000)
8083 if (!name) {
8084 return PyString_FromString("");
8085 }
8086 return PyString_FromString(name);
8087 #else
8088 if (!name) {
8089 return PyUnicode_FromString("");
8090 }
8091 return PyUnicode_FromString(name);
8092 #endif
8093 }
8094 #endif
8095
8096
8097 #if (DBVER >= 43)
8098 /* --------------------------------------------------------------------- */
8099 /* DBSequence methods */
8100
8101
8102 static PyObject*
8103 DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
8104 {
8105 int err=0;
8106
8107 if (self->sequence!=NULL) {
8108 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
8109 if (self->txn) {
8110 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
8111 self->txn=NULL;
8112 }
8113
8114 /*
8115 ** "do_not_close" is used to dispose all related objects in the
8116 ** tree, without actually releasing the "root" object.
8117 ** This is done, for example, because function calls like
8118 ** "DBSequence.remove()" implicitly close the underlying handle. So
8119 ** the handle doesn't need to be closed, but related objects
8120 ** must be cleaned up.
8121 */
8122 if (!do_not_close) {
8123 MYDB_BEGIN_ALLOW_THREADS
8124 err = self->sequence->close(self->sequence, flags);
8125 MYDB_END_ALLOW_THREADS
8126 }
8127 self->sequence = NULL;
8128
8129 RETURN_IF_ERR();
8130 }
8131
8132 RETURN_NONE();
8133 }
8134
8135 static PyObject*
8136 DBSequence_close(DBSequenceObject* self, PyObject* args)
8137 {
8138 int flags=0;
8139 if (!PyArg_ParseTuple(args,"|i:close", &flags))
8140 return NULL;
8141
8142 return DBSequence_close_internal(self,flags,0);
8143 }
8144
8145 static PyObject*
8146 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
8147 {
8148 int err, flags = 0;
8149 int delta = 1;
8150 db_seq_t value;
8151 PyObject *txnobj = NULL;
8152 DB_TXN *txn = NULL;
8153 static char* kwnames[] = {"delta", "txn", "flags", NULL };
8154 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
8155 return NULL;
8156 CHECK_SEQUENCE_NOT_CLOSED(self)
8157
8158 if (!checkTxnObj(txnobj, &txn))
8159 return NULL;
8160
8161 MYDB_BEGIN_ALLOW_THREADS
8162 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
8163 MYDB_END_ALLOW_THREADS
8164
8165 RETURN_IF_ERR();
8166 return PyLong_FromLongLong(value);
8167 }
8168
8169 static PyObject*
8170 DBSequence_get_dbp(DBSequenceObject* self)
8171 {
8172 CHECK_SEQUENCE_NOT_CLOSED(self)
8173 Py_INCREF(self->mydb);
8174 return (PyObject* )self->mydb;
8175 }
8176
8177 static PyObject*
8178 DBSequence_get_key(DBSequenceObject* self)
8179 {
8180 int err;
8181 DBT key;
8182 PyObject *retval = NULL;
8183
8184 key.flags = DB_DBT_MALLOC;
8185 CHECK_SEQUENCE_NOT_CLOSED(self)
8186 MYDB_BEGIN_ALLOW_THREADS
8187 err = self->sequence->get_key(self->sequence, &key);
8188 MYDB_END_ALLOW_THREADS
8189
8190 if (!err)
8191 retval = Build_PyString(key.data, key.size);
8192
8193 FREE_DBT(key);
8194 RETURN_IF_ERR();
8195
8196 return retval;
8197 }
8198
8199 static PyObject*
8200 DBSequence_initial_value(DBSequenceObject* self, PyObject* args)
8201 {
8202 int err;
8203 PY_LONG_LONG value;
8204 db_seq_t value2;
8205 if (!PyArg_ParseTuple(args,"L:initial_value", &value))
8206 return NULL;
8207 CHECK_SEQUENCE_NOT_CLOSED(self)
8208
8209 value2=value; /* If truncation, compiler should show a warning */
8210 MYDB_BEGIN_ALLOW_THREADS
8211 err = self->sequence->initial_value(self->sequence, value2);
8212 MYDB_END_ALLOW_THREADS
8213
8214 RETURN_IF_ERR();
8215
8216 RETURN_NONE();
8217 }
8218
8219 static PyObject*
8220 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
8221 {
8222 int err, flags = 0;
8223 PyObject* keyobj;
8224 PyObject *txnobj = NULL;
8225 DB_TXN *txn = NULL;
8226 DBT key;
8227
8228 static char* kwnames[] = {"key", "txn", "flags", NULL };
8229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
8230 return NULL;
8231
8232 if (!checkTxnObj(txnobj, &txn))
8233 return NULL;
8234
8235 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
8236 return NULL;
8237
8238 MYDB_BEGIN_ALLOW_THREADS
8239 err = self->sequence->open(self->sequence, txn, &key, flags);
8240 MYDB_END_ALLOW_THREADS
8241
8242 FREE_DBT(key);
8243 RETURN_IF_ERR();
8244
8245 if (txn) {
8246 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
8247 self->txn=(DBTxnObject *)txnobj;
8248 }
8249
8250 RETURN_NONE();
8251 }
8252
8253 static PyObject*
8254 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
8255 {
8256 PyObject *dummy;
8257 int err, flags = 0;
8258 PyObject *txnobj = NULL;
8259 DB_TXN *txn = NULL;
8260
8261 static char* kwnames[] = {"txn", "flags", NULL };
8262 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
8263 return NULL;
8264
8265 if (!checkTxnObj(txnobj, &txn))
8266 return NULL;
8267
8268 CHECK_SEQUENCE_NOT_CLOSED(self)
8269
8270 MYDB_BEGIN_ALLOW_THREADS
8271 err = self->sequence->remove(self->sequence, txn, flags);
8272 MYDB_END_ALLOW_THREADS
8273
8274 dummy=DBSequence_close_internal(self,flags,1);
8275 Py_XDECREF(dummy);
8276
8277 RETURN_IF_ERR();
8278 RETURN_NONE();
8279 }
8280
8281 static PyObject*
8282 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
8283 {
8284 int err, size;
8285 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
8286 return NULL;
8287 CHECK_SEQUENCE_NOT_CLOSED(self)
8288
8289 MYDB_BEGIN_ALLOW_THREADS
8290 err = self->sequence->set_cachesize(self->sequence, size);
8291 MYDB_END_ALLOW_THREADS
8292
8293 RETURN_IF_ERR();
8294 RETURN_NONE();
8295 }
8296
8297 static PyObject*
8298 DBSequence_get_cachesize(DBSequenceObject* self)
8299 {
8300 int err, size;
8301
8302 CHECK_SEQUENCE_NOT_CLOSED(self)
8303
8304 MYDB_BEGIN_ALLOW_THREADS
8305 err = self->sequence->get_cachesize(self->sequence, &size);
8306 MYDB_END_ALLOW_THREADS
8307
8308 RETURN_IF_ERR();
8309 return NUMBER_FromLong(size);
8310 }
8311
8312 static PyObject*
8313 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
8314 {
8315 int err, flags = 0;
8316 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
8317 return NULL;
8318 CHECK_SEQUENCE_NOT_CLOSED(self)
8319
8320 MYDB_BEGIN_ALLOW_THREADS
8321 err = self->sequence->set_flags(self->sequence, flags);
8322 MYDB_END_ALLOW_THREADS
8323
8324 RETURN_IF_ERR();
8325 RETURN_NONE();
8326 }
8327
8328 static PyObject*
8329 DBSequence_get_flags(DBSequenceObject* self)
8330 {
8331 unsigned int flags;
8332 int err;
8333
8334 CHECK_SEQUENCE_NOT_CLOSED(self)
8335
8336 MYDB_BEGIN_ALLOW_THREADS
8337 err = self->sequence->get_flags(self->sequence, &flags);
8338 MYDB_END_ALLOW_THREADS
8339
8340 RETURN_IF_ERR();
8341 return NUMBER_FromLong((int)flags);
8342 }
8343
8344 static PyObject*
8345 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
8346 {
8347 int err;
8348 PY_LONG_LONG min, max;
8349 db_seq_t min2, max2;
8350 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
8351 return NULL;
8352 CHECK_SEQUENCE_NOT_CLOSED(self)
8353
8354 min2=min; /* If truncation, compiler should show a warning */
8355 max2=max;
8356 MYDB_BEGIN_ALLOW_THREADS
8357 err = self->sequence->set_range(self->sequence, min2, max2);
8358 MYDB_END_ALLOW_THREADS
8359
8360 RETURN_IF_ERR();
8361 RETURN_NONE();
8362 }
8363
8364 static PyObject*
8365 DBSequence_get_range(DBSequenceObject* self)
8366 {
8367 int err;
8368 PY_LONG_LONG min, max;
8369 db_seq_t min2, max2;
8370
8371 CHECK_SEQUENCE_NOT_CLOSED(self)
8372
8373 MYDB_BEGIN_ALLOW_THREADS
8374 err = self->sequence->get_range(self->sequence, &min2, &max2);
8375 MYDB_END_ALLOW_THREADS
8376
8377 RETURN_IF_ERR();
8378 min=min2; /* If truncation, compiler should show a warning */
8379 max=max2;
8380 return Py_BuildValue("(LL)", min, max);
8381 }
8382
8383
8384 static PyObject*
8385 DBSequence_stat_print(DBSequenceObject* self, PyObject* args, PyObject *kwargs)
8386 {
8387 int err;
8388 int flags=0;
8389 static char* kwnames[] = { "flags", NULL };
8390
8391 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
8392 kwnames, &flags))
8393 {
8394 return NULL;
8395 }
8396
8397 CHECK_SEQUENCE_NOT_CLOSED(self);
8398
8399 MYDB_BEGIN_ALLOW_THREADS;
8400 err = self->sequence->stat_print(self->sequence, flags);
8401 MYDB_END_ALLOW_THREADS;
8402 RETURN_IF_ERR();
8403 RETURN_NONE();
8404 }
8405
8406 static PyObject*
8407 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
8408 {
8409 int err, flags = 0;
8410 DB_SEQUENCE_STAT* sp = NULL;
8411 PyObject* dict_stat;
8412 static char* kwnames[] = {"flags", NULL };
8413 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
8414 return NULL;
8415 CHECK_SEQUENCE_NOT_CLOSED(self);
8416
8417 MYDB_BEGIN_ALLOW_THREADS;
8418 err = self->sequence->stat(self->sequence, &sp, flags);
8419 MYDB_END_ALLOW_THREADS;
8420 RETURN_IF_ERR();
8421
8422 if ((dict_stat = PyDict_New()) == NULL) {
8423 free(sp);
8424 return NULL;
8425 }
8426
8427
8428 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
8429 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
8430
8431 MAKE_INT_ENTRY(wait);
8432 MAKE_INT_ENTRY(nowait);
8433 MAKE_LONG_LONG_ENTRY(current);
8434 MAKE_LONG_LONG_ENTRY(value);
8435 MAKE_LONG_LONG_ENTRY(last_value);
8436 MAKE_LONG_LONG_ENTRY(min);
8437 MAKE_LONG_LONG_ENTRY(max);
8438 MAKE_INT_ENTRY(cache_size);
8439 MAKE_INT_ENTRY(flags);
8440
8441 #undef MAKE_INT_ENTRY
8442 #undef MAKE_LONG_LONG_ENTRY
8443
8444 free(sp);
8445 return dict_stat;
8446 }
8447 #endif
8448
8449
8450 /* --------------------------------------------------------------------- */
8451 /* Method definition tables and type objects */
8452
8453 static PyMethodDef DB_methods[] = {
8454 {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS},
8455 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
8456 {"close", (PyCFunction)DB_close, METH_VARARGS},
8457 #if (DBVER >= 47)
8458 {"compact", (PyCFunction)DB_compact, METH_VARARGS|METH_KEYWORDS},
8459 #endif
8460 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
8461 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
8462 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
8463 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
8464 {"fd", (PyCFunction)DB_fd, METH_NOARGS},
8465 #if (DBVER >= 46)
8466 {"exists", (PyCFunction)DB_exists,
8467 METH_VARARGS|METH_KEYWORDS},
8468 #endif
8469 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
8470 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
8471 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
8472 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS},
8473 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
8474 {"get_type", (PyCFunction)DB_get_type, METH_NOARGS},
8475 {"join", (PyCFunction)DB_join, METH_VARARGS},
8476 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
8477 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS},
8478 {"items", (PyCFunction)DB_items, METH_VARARGS},
8479 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
8480 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
8481 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
8482 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
8483 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
8484 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
8485 #if (DBVER >= 42)
8486 {"get_bt_minkey", (PyCFunction)DB_get_bt_minkey, METH_NOARGS},
8487 #endif
8488 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O},
8489 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
8490 #if (DBVER >= 42)
8491 {"get_cachesize", (PyCFunction)DB_get_cachesize, METH_NOARGS},
8492 #endif
8493 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
8494 #if (DBVER >= 42)
8495 {"get_encrypt_flags", (PyCFunction)DB_get_encrypt_flags, METH_NOARGS},
8496 #endif
8497
8498 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
8499 #if (DBVER >= 42)
8500 {"get_flags", (PyCFunction)DB_get_flags, METH_NOARGS},
8501 #endif
8502 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
8503 #if (DBVER >= 42)
8504 {"get_h_ffactor", (PyCFunction)DB_get_h_ffactor, METH_NOARGS},
8505 #endif
8506 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
8507 #if (DBVER >= 42)
8508 {"get_h_nelem", (PyCFunction)DB_get_h_nelem, METH_NOARGS},
8509 #endif
8510 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
8511 #if (DBVER >= 42)
8512 {"get_lorder", (PyCFunction)DB_get_lorder, METH_NOARGS},
8513 #endif
8514 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
8515 #if (DBVER >= 42)
8516 {"get_pagesize", (PyCFunction)DB_get_pagesize, METH_NOARGS},
8517 #endif
8518 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
8519 #if (DBVER >= 42)
8520 {"get_re_delim", (PyCFunction)DB_get_re_delim, METH_NOARGS},
8521 #endif
8522 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
8523 #if (DBVER >= 42)
8524 {"get_re_len", (PyCFunction)DB_get_re_len, METH_NOARGS},
8525 #endif
8526 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
8527 #if (DBVER >= 42)
8528 {"get_re_pad", (PyCFunction)DB_get_re_pad, METH_NOARGS},
8529 #endif
8530 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
8531 #if (DBVER >= 42)
8532 {"get_re_source", (PyCFunction)DB_get_re_source, METH_NOARGS},
8533 #endif
8534 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
8535 #if (DBVER >= 42)
8536 {"get_q_extentsize",(PyCFunction)DB_get_q_extentsize, METH_NOARGS},
8537 #endif
8538 {"set_private", (PyCFunction)DB_set_private, METH_O},
8539 {"get_private", (PyCFunction)DB_get_private, METH_NOARGS},
8540 #if (DBVER >= 46)
8541 {"set_priority", (PyCFunction)DB_set_priority, METH_VARARGS},
8542 {"get_priority", (PyCFunction)DB_get_priority, METH_NOARGS},
8543 #endif
8544 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
8545 #if (DBVER >= 43)
8546 {"stat_print", (PyCFunction)DB_stat_print,
8547 METH_VARARGS|METH_KEYWORDS},
8548 #endif
8549 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
8550 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
8551 {"type", (PyCFunction)DB_get_type, METH_NOARGS},
8552 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
8553 {"values", (PyCFunction)DB_values, METH_VARARGS},
8554 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
8555 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
8556 {NULL, NULL} /* sentinel */
8557 };
8558
8559
8560 /* We need this to support __contains__() */
8561 static PySequenceMethods DB_sequence = {
8562 0, /* sq_length, mapping wins here */
8563 0, /* sq_concat */
8564 0, /* sq_repeat */
8565 0, /* sq_item */
8566 0, /* sq_slice */
8567 0, /* sq_ass_item */
8568 0, /* sq_ass_slice */
8569 (objobjproc)DB_contains, /* sq_contains */
8570 0, /* sq_inplace_concat */
8571 0, /* sq_inplace_repeat */
8572 };
8573
8574 static PyMappingMethods DB_mapping = {
8575 DB_length, /*mp_length*/
8576 (binaryfunc)DB_subscript, /*mp_subscript*/
8577 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
8578 };
8579
8580
8581 static PyMethodDef DBCursor_methods[] = {
8582 {"close", (PyCFunction)DBC_close, METH_NOARGS},
8583 {"count", (PyCFunction)DBC_count, METH_VARARGS},
8584 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
8585 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
8586 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
8587 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
8588 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
8589 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
8590 {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS},
8591 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
8592 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
8593 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
8594 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
8595 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
8596 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
8597 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
8598 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
8599 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
8600 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
8601 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
8602 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
8603 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
8604 #if (DBVER >= 46)
8605 {"prev_dup", (PyCFunction)DBC_prev_dup,
8606 METH_VARARGS|METH_KEYWORDS},
8607 #endif
8608 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
8609 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
8610 #if (DBVER >= 46)
8611 {"set_priority", (PyCFunction)DBC_set_priority,
8612 METH_VARARGS|METH_KEYWORDS},
8613 {"get_priority", (PyCFunction)DBC_get_priority, METH_NOARGS},
8614 #endif
8615 {NULL, NULL} /* sentinel */
8616 };
8617
8618
8619 static PyMethodDef DBLogCursor_methods[] = {
8620 {"close", (PyCFunction)DBLogCursor_close, METH_NOARGS},
8621 {"current", (PyCFunction)DBLogCursor_current, METH_NOARGS},
8622 {"first", (PyCFunction)DBLogCursor_first, METH_NOARGS},
8623 {"last", (PyCFunction)DBLogCursor_last, METH_NOARGS},
8624 {"next", (PyCFunction)DBLogCursor_next, METH_NOARGS},
8625 {"prev", (PyCFunction)DBLogCursor_prev, METH_NOARGS},
8626 {"set", (PyCFunction)DBLogCursor_set, METH_VARARGS},
8627 {NULL, NULL} /* sentinel */
8628 };
8629
8630
8631 static PyMethodDef DBEnv_methods[] = {
8632 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
8633 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
8634 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
8635 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
8636 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
8637 #if (DBVER >= 46)
8638 {"set_thread_count", (PyCFunction)DBEnv_set_thread_count, METH_VARARGS},
8639 {"get_thread_count", (PyCFunction)DBEnv_get_thread_count, METH_NOARGS},
8640 #endif
8641 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
8642 #if (DBVER >= 42)
8643 {"get_encrypt_flags", (PyCFunction)DBEnv_get_encrypt_flags, METH_NOARGS},
8644 {"get_timeout", (PyCFunction)DBEnv_get_timeout,
8645 METH_VARARGS|METH_KEYWORDS},
8646 #endif
8647 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
8648 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
8649 #if (DBVER >= 42)
8650 {"get_shm_key", (PyCFunction)DBEnv_get_shm_key, METH_NOARGS},
8651 #endif
8652 #if (DBVER >= 46)
8653 {"set_cache_max", (PyCFunction)DBEnv_set_cache_max, METH_VARARGS},
8654 {"get_cache_max", (PyCFunction)DBEnv_get_cache_max, METH_NOARGS},
8655 #endif
8656 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
8657 #if (DBVER >= 42)
8658 {"get_cachesize", (PyCFunction)DBEnv_get_cachesize, METH_NOARGS},
8659 #endif
8660 {"memp_trickle", (PyCFunction)DBEnv_memp_trickle, METH_VARARGS},
8661 {"memp_sync", (PyCFunction)DBEnv_memp_sync, METH_VARARGS},
8662 {"memp_stat", (PyCFunction)DBEnv_memp_stat,
8663 METH_VARARGS|METH_KEYWORDS},
8664 #if (DBVER >= 43)
8665 {"memp_stat_print", (PyCFunction)DBEnv_memp_stat_print,
8666 METH_VARARGS|METH_KEYWORDS},
8667 #endif
8668 #if (DBVER >= 44)
8669 {"mutex_set_max", (PyCFunction)DBEnv_mutex_set_max, METH_VARARGS},
8670 {"mutex_get_max", (PyCFunction)DBEnv_mutex_get_max, METH_NOARGS},
8671 {"mutex_set_align", (PyCFunction)DBEnv_mutex_set_align, METH_VARARGS},
8672 {"mutex_get_align", (PyCFunction)DBEnv_mutex_get_align, METH_NOARGS},
8673 {"mutex_set_increment", (PyCFunction)DBEnv_mutex_set_increment,
8674 METH_VARARGS},
8675 {"mutex_get_increment", (PyCFunction)DBEnv_mutex_get_increment,
8676 METH_NOARGS},
8677 {"mutex_set_tas_spins", (PyCFunction)DBEnv_mutex_set_tas_spins,
8678 METH_VARARGS},
8679 {"mutex_get_tas_spins", (PyCFunction)DBEnv_mutex_get_tas_spins,
8680 METH_NOARGS},
8681 {"mutex_stat", (PyCFunction)DBEnv_mutex_stat, METH_VARARGS},
8682 #if (DBVER >= 44)
8683 {"mutex_stat_print", (PyCFunction)DBEnv_mutex_stat_print,
8684 METH_VARARGS|METH_KEYWORDS},
8685 #endif
8686 #endif
8687 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
8688 #if (DBVER >= 42)
8689 {"get_data_dirs", (PyCFunction)DBEnv_get_data_dirs, METH_NOARGS},
8690 #endif
8691 #if (DBVER >= 42)
8692 {"get_flags", (PyCFunction)DBEnv_get_flags, METH_NOARGS},
8693 #endif
8694 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
8695 #if (DBVER >= 47)
8696 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
8697 {"log_get_config", (PyCFunction)DBEnv_log_get_config, METH_VARARGS},
8698 #endif
8699 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
8700 #if (DBVER >= 42)
8701 {"get_lg_bsize", (PyCFunction)DBEnv_get_lg_bsize, METH_NOARGS},
8702 #endif
8703 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
8704 #if (DBVER >= 42)
8705 {"get_lg_dir", (PyCFunction)DBEnv_get_lg_dir, METH_NOARGS},
8706 #endif
8707 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
8708 #if (DBVER >= 42)
8709 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS},
8710 #endif
8711 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
8712 #if (DBVER >= 42)
8713 {"get_lg_regionmax",(PyCFunction)DBEnv_get_lg_regionmax, METH_NOARGS},
8714 #endif
8715 #if (DBVER >= 44)
8716 {"set_lg_filemode", (PyCFunction)DBEnv_set_lg_filemode, METH_VARARGS},
8717 {"get_lg_filemode", (PyCFunction)DBEnv_get_lg_filemode, METH_NOARGS},
8718 #endif
8719 #if (DBVER >= 47)
8720 {"set_lk_partitions", (PyCFunction)DBEnv_set_lk_partitions, METH_VARARGS},
8721 {"get_lk_partitions", (PyCFunction)DBEnv_get_lk_partitions, METH_NOARGS},
8722 #endif
8723 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
8724 #if (DBVER >= 42)
8725 {"get_lk_detect", (PyCFunction)DBEnv_get_lk_detect, METH_NOARGS},
8726 #endif
8727 #if (DBVER < 45)
8728 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
8729 #endif
8730 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
8731 #if (DBVER >= 42)
8732 {"get_lk_max_locks", (PyCFunction)DBEnv_get_lk_max_locks, METH_NOARGS},
8733 #endif
8734 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
8735 #if (DBVER >= 42)
8736 {"get_lk_max_lockers", (PyCFunction)DBEnv_get_lk_max_lockers, METH_NOARGS},
8737 #endif
8738 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
8739 #if (DBVER >= 42)
8740 {"get_lk_max_objects", (PyCFunction)DBEnv_get_lk_max_objects, METH_NOARGS},
8741 #endif
8742 #if (DBVER >= 43)
8743 {"stat_print", (PyCFunction)DBEnv_stat_print,
8744 METH_VARARGS|METH_KEYWORDS},
8745 #endif
8746 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
8747 #if (DBVER >= 42)
8748 {"get_mp_mmapsize", (PyCFunction)DBEnv_get_mp_mmapsize, METH_NOARGS},
8749 #endif
8750 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
8751 #if (DBVER >= 42)
8752 {"get_tmp_dir", (PyCFunction)DBEnv_get_tmp_dir, METH_NOARGS},
8753 #endif
8754 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
8755 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
8756 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
8757 #if (DBVER >= 43)
8758 {"txn_stat_print", (PyCFunction)DBEnv_txn_stat_print,
8759 METH_VARARGS|METH_KEYWORDS},
8760 #endif
8761 #if (DBVER >= 42)
8762 {"get_tx_max", (PyCFunction)DBEnv_get_tx_max, METH_NOARGS},
8763 {"get_tx_timestamp", (PyCFunction)DBEnv_get_tx_timestamp, METH_NOARGS},
8764 #endif
8765 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
8766 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
8767 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
8768 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
8769 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS},
8770 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
8771 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
8772 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
8773 #if (DBVER >= 43)
8774 {"lock_stat_print", (PyCFunction)DBEnv_lock_stat_print,
8775 METH_VARARGS|METH_KEYWORDS},
8776 #endif
8777 {"log_cursor", (PyCFunction)DBEnv_log_cursor, METH_NOARGS},
8778 {"log_file", (PyCFunction)DBEnv_log_file, METH_VARARGS},
8779 #if (DBVER >= 44)
8780 {"log_printf", (PyCFunction)DBEnv_log_printf,
8781 METH_VARARGS|METH_KEYWORDS},
8782 #endif
8783 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
8784 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS},
8785 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
8786 #if (DBVER >= 43)
8787 {"log_stat_print", (PyCFunction)DBEnv_log_stat_print,
8788 METH_VARARGS|METH_KEYWORDS},
8789 #endif
8790 #if (DBVER >= 44)
8791 {"fileid_reset", (PyCFunction)DBEnv_fileid_reset, METH_VARARGS|METH_KEYWORDS},
8792 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
8793 #endif
8794 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
8795 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS},
8796 #if (DBVER < 48)
8797 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
8798 METH_VARARGS|METH_KEYWORDS},
8799 #endif
8800 #if (DBVER >= 43)
8801 {"set_mp_max_openfd", (PyCFunction)DBEnv_set_mp_max_openfd, METH_VARARGS},
8802 {"get_mp_max_openfd", (PyCFunction)DBEnv_get_mp_max_openfd, METH_NOARGS},
8803 {"set_mp_max_write", (PyCFunction)DBEnv_set_mp_max_write, METH_VARARGS},
8804 {"get_mp_max_write", (PyCFunction)DBEnv_get_mp_max_write, METH_NOARGS},
8805 #endif
8806 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
8807 #if (DBVER >= 42)
8808 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
8809 #endif
8810 {"set_private", (PyCFunction)DBEnv_set_private, METH_O},
8811 {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS},
8812 {"rep_start", (PyCFunction)DBEnv_rep_start,
8813 METH_VARARGS|METH_KEYWORDS},
8814 {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
8815 {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
8816 METH_VARARGS},
8817 #if (DBVER >= 46)
8818 {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS},
8819 #endif
8820 #if (DBVER >= 44)
8821 {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS},
8822 {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS},
8823 {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS},
8824 #endif
8825 #if (DBVER >= 45)
8826 {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS},
8827 {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS},
8828 #endif
8829 #if (DBVER >= 47)
8830 {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS},
8831 {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS},
8832 #endif
8833 #if (DBVER >= 45)
8834 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
8835 #endif
8836 #if (DBVER >= 45)
8837 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
8838 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
8839 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
8840 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
8841 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
8842 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
8843 #endif
8844 #if (DBVER >= 47)
8845 {"rep_set_clockskew", (PyCFunction)DBEnv_rep_set_clockskew, METH_VARARGS},
8846 {"rep_get_clockskew", (PyCFunction)DBEnv_rep_get_clockskew, METH_VARARGS},
8847 #endif
8848 {"rep_stat", (PyCFunction)DBEnv_rep_stat,
8849 METH_VARARGS|METH_KEYWORDS},
8850 #if (DBVER >= 43)
8851 {"rep_stat_print", (PyCFunction)DBEnv_rep_stat_print,
8852 METH_VARARGS|METH_KEYWORDS},
8853 #endif
8854
8855 #if (DBVER >= 45)
8856 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
8857 METH_VARARGS|METH_KEYWORDS},
8858 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
8859 METH_VARARGS|METH_KEYWORDS},
8860 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
8861 METH_VARARGS|METH_KEYWORDS},
8862 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
8863 METH_VARARGS},
8864 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
8865 METH_NOARGS},
8866 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
8867 METH_NOARGS},
8868 #endif
8869 #if (DBVER >= 46)
8870 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
8871 METH_VARARGS|METH_KEYWORDS},
8872 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
8873 METH_VARARGS|METH_KEYWORDS},
8874 #endif
8875 {NULL, NULL} /* sentinel */
8876 };
8877
8878
8879 static PyMethodDef DBTxn_methods[] = {
8880 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
8881 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
8882 {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS},
8883 {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS},
8884 {"id", (PyCFunction)DBTxn_id, METH_NOARGS},
8885 {"set_timeout", (PyCFunction)DBTxn_set_timeout,
8886 METH_VARARGS|METH_KEYWORDS},
8887 #if (DBVER >= 44)
8888 {"set_name", (PyCFunction)DBTxn_set_name, METH_VARARGS},
8889 {"get_name", (PyCFunction)DBTxn_get_name, METH_NOARGS},
8890 #endif
8891 {NULL, NULL} /* sentinel */
8892 };
8893
8894
8895 #if (DBVER >= 43)
8896 static PyMethodDef DBSequence_methods[] = {
8897 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
8898 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
8899 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS},
8900 {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS},
8901 {"initial_value", (PyCFunction)DBSequence_initial_value, METH_VARARGS},
8902 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
8903 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
8904 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
8905 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS},
8906 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
8907 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS},
8908 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
8909 {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS},
8910 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
8911 {"stat_print", (PyCFunction)DBSequence_stat_print,
8912 METH_VARARGS|METH_KEYWORDS},
8913 {NULL, NULL} /* sentinel */
8914 };
8915 #endif
8916
8917
8918 static PyObject*
8919 DBEnv_db_home_get(DBEnvObject* self)
8920 {
8921 const char *home = NULL;
8922
8923 CHECK_ENV_NOT_CLOSED(self);
8924
8925 #if (DBVER >= 42)
8926 MYDB_BEGIN_ALLOW_THREADS;
8927 self->db_env->get_home(self->db_env, &home);
8928 MYDB_END_ALLOW_THREADS;
8929 #else
8930 home=self->db_env->db_home;
8931 #endif
8932
8933 if (home == NULL) {
8934 RETURN_NONE();
8935 }
8936 return PyBytes_FromString(home);
8937 }
8938
8939 static PyGetSetDef DBEnv_getsets[] = {
8940 {"db_home", (getter)DBEnv_db_home_get, NULL,},
8941 {NULL}
8942 };
8943
8944
8945 statichere PyTypeObject DB_Type = {
8946 #if (PY_VERSION_HEX < 0x03000000)
8947 PyObject_HEAD_INIT(NULL)
8948 0, /*ob_size*/
8949 #else
8950 PyVarObject_HEAD_INIT(NULL, 0)
8951 #endif
8952 "DB", /*tp_name*/
8953 sizeof(DBObject), /*tp_basicsize*/
8954 0, /*tp_itemsize*/
8955 /* methods */
8956 (destructor)DB_dealloc, /*tp_dealloc*/
8957 0, /*tp_print*/
8958 0, /*tp_getattr*/
8959 0, /*tp_setattr*/
8960 0, /*tp_compare*/
8961 0, /*tp_repr*/
8962 0, /*tp_as_number*/
8963 &DB_sequence,/*tp_as_sequence*/
8964 &DB_mapping,/*tp_as_mapping*/
8965 0, /*tp_hash*/
8966 0, /* tp_call */
8967 0, /* tp_str */
8968 0, /* tp_getattro */
8969 0, /* tp_setattro */
8970 0, /* tp_as_buffer */
8971 #if (PY_VERSION_HEX < 0x03000000)
8972 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
8973 #else
8974 Py_TPFLAGS_DEFAULT, /* tp_flags */
8975 #endif
8976 0, /* tp_doc */
8977 0, /* tp_traverse */
8978 0, /* tp_clear */
8979 0, /* tp_richcompare */
8980 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
8981 0, /*tp_iter*/
8982 0, /*tp_iternext*/
8983 DB_methods, /*tp_methods*/
8984 0, /*tp_members*/
8985 };
8986
8987
8988 statichere PyTypeObject DBCursor_Type = {
8989 #if (PY_VERSION_HEX < 0x03000000)
8990 PyObject_HEAD_INIT(NULL)
8991 0, /*ob_size*/
8992 #else
8993 PyVarObject_HEAD_INIT(NULL, 0)
8994 #endif
8995 "DBCursor", /*tp_name*/
8996 sizeof(DBCursorObject), /*tp_basicsize*/
8997 0, /*tp_itemsize*/
8998 /* methods */
8999 (destructor)DBCursor_dealloc,/*tp_dealloc*/
9000 0, /*tp_print*/
9001 0, /*tp_getattr*/
9002 0, /*tp_setattr*/
9003 0, /*tp_compare*/
9004 0, /*tp_repr*/
9005 0, /*tp_as_number*/
9006 0, /*tp_as_sequence*/
9007 0, /*tp_as_mapping*/
9008 0, /*tp_hash*/
9009 0, /*tp_call*/
9010 0, /*tp_str*/
9011 0, /*tp_getattro*/
9012 0, /*tp_setattro*/
9013 0, /*tp_as_buffer*/
9014 #if (PY_VERSION_HEX < 0x03000000)
9015 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
9016 #else
9017 Py_TPFLAGS_DEFAULT, /* tp_flags */
9018 #endif
9019 0, /* tp_doc */
9020 0, /* tp_traverse */
9021 0, /* tp_clear */
9022 0, /* tp_richcompare */
9023 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
9024 0, /*tp_iter*/
9025 0, /*tp_iternext*/
9026 DBCursor_methods, /*tp_methods*/
9027 0, /*tp_members*/
9028 };
9029
9030
9031 statichere PyTypeObject DBLogCursor_Type = {
9032 #if (PY_VERSION_HEX < 0x03000000)
9033 PyObject_HEAD_INIT(NULL)
9034 0, /*ob_size*/
9035 #else
9036 PyVarObject_HEAD_INIT(NULL, 0)
9037 #endif
9038 "DBLogCursor", /*tp_name*/
9039 sizeof(DBLogCursorObject), /*tp_basicsize*/
9040 0, /*tp_itemsize*/
9041 /* methods */
9042 (destructor)DBLogCursor_dealloc,/*tp_dealloc*/
9043 0, /*tp_print*/
9044 0, /*tp_getattr*/
9045 0, /*tp_setattr*/
9046 0, /*tp_compare*/
9047 0, /*tp_repr*/
9048 0, /*tp_as_number*/
9049 0, /*tp_as_sequence*/
9050 0, /*tp_as_mapping*/
9051 0, /*tp_hash*/
9052 0, /*tp_call*/
9053 0, /*tp_str*/
9054 0, /*tp_getattro*/
9055 0, /*tp_setattro*/
9056 0, /*tp_as_buffer*/
9057 #if (PY_VERSION_HEX < 0x03000000)
9058 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
9059 #else
9060 Py_TPFLAGS_DEFAULT, /* tp_flags */
9061 #endif
9062 0, /* tp_doc */
9063 0, /* tp_traverse */
9064 0, /* tp_clear */
9065 0, /* tp_richcompare */
9066 offsetof(DBLogCursorObject, in_weakreflist), /* tp_weaklistoffset */
9067 0, /*tp_iter*/
9068 0, /*tp_iternext*/
9069 DBLogCursor_methods, /*tp_methods*/
9070 0, /*tp_members*/
9071 };
9072
9073
9074 statichere PyTypeObject DBEnv_Type = {
9075 #if (PY_VERSION_HEX < 0x03000000)
9076 PyObject_HEAD_INIT(NULL)
9077 0, /*ob_size*/
9078 #else
9079 PyVarObject_HEAD_INIT(NULL, 0)
9080 #endif
9081 "DBEnv", /*tp_name*/
9082 sizeof(DBEnvObject), /*tp_basicsize*/
9083 0, /*tp_itemsize*/
9084 /* methods */
9085 (destructor)DBEnv_dealloc, /*tp_dealloc*/
9086 0, /*tp_print*/
9087 0, /*tp_getattr*/
9088 0, /*tp_setattr*/
9089 0, /*tp_compare*/
9090 0, /*tp_repr*/
9091 0, /*tp_as_number*/
9092 0, /*tp_as_sequence*/
9093 0, /*tp_as_mapping*/
9094 0, /*tp_hash*/
9095 0, /* tp_call */
9096 0, /* tp_str */
9097 0, /* tp_getattro */
9098 0, /* tp_setattro */
9099 0, /* tp_as_buffer */
9100 #if (PY_VERSION_HEX < 0x03000000)
9101 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
9102 #else
9103 Py_TPFLAGS_DEFAULT, /* tp_flags */
9104 #endif
9105 0, /* tp_doc */
9106 0, /* tp_traverse */
9107 0, /* tp_clear */
9108 0, /* tp_richcompare */
9109 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
9110 0, /* tp_iter */
9111 0, /* tp_iternext */
9112 DBEnv_methods, /* tp_methods */
9113 0, /* tp_members */
9114 DBEnv_getsets, /* tp_getsets */
9115 };
9116
9117 statichere PyTypeObject DBTxn_Type = {
9118 #if (PY_VERSION_HEX < 0x03000000)
9119 PyObject_HEAD_INIT(NULL)
9120 0, /*ob_size*/
9121 #else
9122 PyVarObject_HEAD_INIT(NULL, 0)
9123 #endif
9124 "DBTxn", /*tp_name*/
9125 sizeof(DBTxnObject), /*tp_basicsize*/
9126 0, /*tp_itemsize*/
9127 /* methods */
9128 (destructor)DBTxn_dealloc, /*tp_dealloc*/
9129 0, /*tp_print*/
9130 0, /*tp_getattr*/
9131 0, /*tp_setattr*/
9132 0, /*tp_compare*/
9133 0, /*tp_repr*/
9134 0, /*tp_as_number*/
9135 0, /*tp_as_sequence*/
9136 0, /*tp_as_mapping*/
9137 0, /*tp_hash*/
9138 0, /* tp_call */
9139 0, /* tp_str */
9140 0, /* tp_getattro */
9141 0, /* tp_setattro */
9142 0, /* tp_as_buffer */
9143 #if (PY_VERSION_HEX < 0x03000000)
9144 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
9145 #else
9146 Py_TPFLAGS_DEFAULT, /* tp_flags */
9147 #endif
9148 0, /* tp_doc */
9149 0, /* tp_traverse */
9150 0, /* tp_clear */
9151 0, /* tp_richcompare */
9152 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
9153 0, /*tp_iter*/
9154 0, /*tp_iternext*/
9155 DBTxn_methods, /*tp_methods*/
9156 0, /*tp_members*/
9157 };
9158
9159
9160 statichere PyTypeObject DBLock_Type = {
9161 #if (PY_VERSION_HEX < 0x03000000)
9162 PyObject_HEAD_INIT(NULL)
9163 0, /*ob_size*/
9164 #else
9165 PyVarObject_HEAD_INIT(NULL, 0)
9166 #endif
9167 "DBLock", /*tp_name*/
9168 sizeof(DBLockObject), /*tp_basicsize*/
9169 0, /*tp_itemsize*/
9170 /* methods */
9171 (destructor)DBLock_dealloc, /*tp_dealloc*/
9172 0, /*tp_print*/
9173 0, /*tp_getattr*/
9174 0, /*tp_setattr*/
9175 0, /*tp_compare*/
9176 0, /*tp_repr*/
9177 0, /*tp_as_number*/
9178 0, /*tp_as_sequence*/
9179 0, /*tp_as_mapping*/
9180 0, /*tp_hash*/
9181 0, /* tp_call */
9182 0, /* tp_str */
9183 0, /* tp_getattro */
9184 0, /* tp_setattro */
9185 0, /* tp_as_buffer */
9186 #if (PY_VERSION_HEX < 0x03000000)
9187 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
9188 #else
9189 Py_TPFLAGS_DEFAULT, /* tp_flags */
9190 #endif
9191 0, /* tp_doc */
9192 0, /* tp_traverse */
9193 0, /* tp_clear */
9194 0, /* tp_richcompare */
9195 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
9196 };
9197
9198 #if (DBVER >= 43)
9199 statichere PyTypeObject DBSequence_Type = {
9200 #if (PY_VERSION_HEX < 0x03000000)
9201 PyObject_HEAD_INIT(NULL)
9202 0, /*ob_size*/
9203 #else
9204 PyVarObject_HEAD_INIT(NULL, 0)
9205 #endif
9206 "DBSequence", /*tp_name*/
9207 sizeof(DBSequenceObject), /*tp_basicsize*/
9208 0, /*tp_itemsize*/
9209 /* methods */
9210 (destructor)DBSequence_dealloc, /*tp_dealloc*/
9211 0, /*tp_print*/
9212 0, /*tp_getattr*/
9213 0, /*tp_setattr*/
9214 0, /*tp_compare*/
9215 0, /*tp_repr*/
9216 0, /*tp_as_number*/
9217 0, /*tp_as_sequence*/
9218 0, /*tp_as_mapping*/
9219 0, /*tp_hash*/
9220 0, /* tp_call */
9221 0, /* tp_str */
9222 0, /* tp_getattro */
9223 0, /* tp_setattro */
9224 0, /* tp_as_buffer */
9225 #if (PY_VERSION_HEX < 0x03000000)
9226 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
9227 #else
9228 Py_TPFLAGS_DEFAULT, /* tp_flags */
9229 #endif
9230 0, /* tp_doc */
9231 0, /* tp_traverse */
9232 0, /* tp_clear */
9233 0, /* tp_richcompare */
9234 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
9235 0, /*tp_iter*/
9236 0, /*tp_iternext*/
9237 DBSequence_methods, /*tp_methods*/
9238 0, /*tp_members*/
9239 };
9240 #endif
9241
9242 /* --------------------------------------------------------------------- */
9243 /* Module-level functions */
9244
9245 static PyObject*
9246 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
9247 {
9248 PyObject* dbenvobj = NULL;
9249 int flags = 0;
9250 static char* kwnames[] = { "dbEnv", "flags", NULL};
9251
9252 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
9253 &dbenvobj, &flags))
9254 return NULL;
9255 if (dbenvobj == Py_None)
9256 dbenvobj = NULL;
9257 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
9258 makeTypeError("DBEnv", dbenvobj);
9259 return NULL;
9260 }
9261
9262 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
9263 }
9264
9265
9266 static PyObject*
9267 DBEnv_construct(PyObject* self, PyObject* args)
9268 {
9269 int flags = 0;
9270 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
9271 return (PyObject* )newDBEnvObject(flags);
9272 }
9273
9274 #if (DBVER >= 43)
9275 static PyObject*
9276 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
9277 {
9278 PyObject* dbobj;
9279 int flags = 0;
9280 static char* kwnames[] = { "db", "flags", NULL};
9281
9282 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
9283 return NULL;
9284 if (!DBObject_Check(dbobj)) {
9285 makeTypeError("DB", dbobj);
9286 return NULL;
9287 }
9288 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
9289 }
9290 #endif
9291
9292 static char bsddb_version_doc[] =
9293 "Returns a tuple of major, minor, and patch release numbers of the\n\
9294 underlying DB library.";
9295
9296 static PyObject*
9297 bsddb_version(PyObject* self)
9298 {
9299 int major, minor, patch;
9300
9301 db_version(&major, &minor, &patch);
9302 return Py_BuildValue("(iii)", major, minor, patch);
9303 }
9304
9305
9306 /* List of functions defined in the module */
9307 static PyMethodDef bsddb_methods[] = {
9308 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
9309 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
9310 #if (DBVER >= 43)
9311 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
9312 #endif
9313 {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc},
9314 {NULL, NULL} /* sentinel */
9315 };
9316
9317
9318 /* API structure */
9319 static BSDDB_api bsddb_api;
9320
9321
9322 /* --------------------------------------------------------------------- */
9323 /* Module initialization */
9324
9325
9326 /* Convenience routine to export an integer value.
9327 * Errors are silently ignored, for better or for worse...
9328 */
9329 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
9330
9331 #define MODULE_NAME_MAX_LEN 11
9332 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
9333
9334 #if (PY_VERSION_HEX >= 0x03000000)
9335 static struct PyModuleDef bsddbmodule = {
9336 PyModuleDef_HEAD_INIT,
9337 _bsddbModuleName, /* Name of module */
9338 NULL, /* module documentation, may be NULL */
9339 -1, /* size of per-interpreter state of the module,
9340 or -1 if the module keeps state in global variables. */
9341 bsddb_methods,
9342 NULL, /* Reload */
9343 NULL, /* Traverse */
9344 NULL, /* Clear */
9345 NULL /* Free */
9346 };
9347 #endif
9348
9349
9350 #if (PY_VERSION_HEX < 0x03000000)
9351 DL_EXPORT(void) init_bsddb(void)
9352 #else
9353 PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */
9354 #endif
9355 {
9356 PyObject* m;
9357 PyObject* d;
9358 PyObject* py_api;
9359 PyObject* pybsddb_version_s;
9360 PyObject* db_version_s;
9361 PyObject* cvsid_s;
9362
9363 #if (PY_VERSION_HEX < 0x03000000)
9364 pybsddb_version_s = PyString_FromString(PY_BSDDB_VERSION);
9365 db_version_s = PyString_FromString(DB_VERSION_STRING);
9366 cvsid_s = PyString_FromString(rcs_id);
9367 #else
9368 /* This data should be ascii, so UTF-8 conversion is fine */
9369 pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
9370 db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
9371 cvsid_s = PyUnicode_FromString(rcs_id);
9372 #endif
9373
9374 /* Initialize object types */
9375 if ((PyType_Ready(&DB_Type) < 0)
9376 || (PyType_Ready(&DBCursor_Type) < 0)
9377 || (PyType_Ready(&DBLogCursor_Type) < 0)
9378 || (PyType_Ready(&DBEnv_Type) < 0)
9379 || (PyType_Ready(&DBTxn_Type) < 0)
9380 || (PyType_Ready(&DBLock_Type) < 0)
9381 #if (DBVER >= 43)
9382 || (PyType_Ready(&DBSequence_Type) < 0)
9383 #endif
9384 ) {
9385 #if (PY_VERSION_HEX < 0x03000000)
9386 return;
9387 #else
9388 return NULL;
9389 #endif
9390 }
9391
9392 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
9393 /* Save the current interpreter, so callbacks can do the right thing. */
9394 _db_interpreterState = PyThreadState_GET()->interp;
9395 #endif
9396
9397 /* Create the module and add the functions */
9398 #if (PY_VERSION_HEX < 0x03000000)
9399 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
9400 #else
9401 m=PyModule_Create(&bsddbmodule);
9402 #endif
9403 if (m == NULL) {
9404 #if (PY_VERSION_HEX < 0x03000000)
9405 return;
9406 #else
9407 return NULL;
9408 #endif
9409 }
9410
9411 /* Add some symbolic constants to the module */
9412 d = PyModule_GetDict(m);
9413 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
9414 PyDict_SetItemString(d, "cvsid", cvsid_s);
9415 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
9416 Py_DECREF(pybsddb_version_s);
9417 pybsddb_version_s = NULL;
9418 Py_DECREF(cvsid_s);
9419 cvsid_s = NULL;
9420 Py_DECREF(db_version_s);
9421 db_version_s = NULL;
9422
9423 ADD_INT(d, DB_VERSION_MAJOR);
9424 ADD_INT(d, DB_VERSION_MINOR);
9425 ADD_INT(d, DB_VERSION_PATCH);
9426
9427 ADD_INT(d, DB_MAX_PAGES);
9428 ADD_INT(d, DB_MAX_RECORDS);
9429
9430 #if (DBVER < 48)
9431 #if (DBVER >= 42)
9432 ADD_INT(d, DB_RPCCLIENT);
9433 #else
9434 ADD_INT(d, DB_CLIENT);
9435 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
9436 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
9437 #endif
9438 #endif
9439
9440 #if (DBVER < 48)
9441 ADD_INT(d, DB_XA_CREATE);
9442 #endif
9443
9444 ADD_INT(d, DB_CREATE);
9445 ADD_INT(d, DB_NOMMAP);
9446 ADD_INT(d, DB_THREAD);
9447 #if (DBVER >= 45)
9448 ADD_INT(d, DB_MULTIVERSION);
9449 #endif
9450
9451 ADD_INT(d, DB_FORCE);
9452 ADD_INT(d, DB_INIT_CDB);
9453 ADD_INT(d, DB_INIT_LOCK);
9454 ADD_INT(d, DB_INIT_LOG);
9455 ADD_INT(d, DB_INIT_MPOOL);
9456 ADD_INT(d, DB_INIT_TXN);
9457 ADD_INT(d, DB_JOINENV);
9458
9459 #if (DBVER >= 48)
9460 ADD_INT(d, DB_GID_SIZE);
9461 #else
9462 ADD_INT(d, DB_XIDDATASIZE);
9463 /* Allow new code to work in old BDB releases */
9464 _addIntToDict(d, "DB_GID_SIZE", DB_XIDDATASIZE);
9465 #endif
9466
9467 ADD_INT(d, DB_RECOVER);
9468 ADD_INT(d, DB_RECOVER_FATAL);
9469 ADD_INT(d, DB_TXN_NOSYNC);
9470 ADD_INT(d, DB_USE_ENVIRON);
9471 ADD_INT(d, DB_USE_ENVIRON_ROOT);
9472
9473 ADD_INT(d, DB_LOCKDOWN);
9474 ADD_INT(d, DB_PRIVATE);
9475 ADD_INT(d, DB_SYSTEM_MEM);
9476
9477 ADD_INT(d, DB_TXN_SYNC);
9478 ADD_INT(d, DB_TXN_NOWAIT);
9479
9480 #if (DBVER >= 46)
9481 ADD_INT(d, DB_TXN_WAIT);
9482 #endif
9483
9484 ADD_INT(d, DB_EXCL);
9485 ADD_INT(d, DB_FCNTL_LOCKING);
9486 ADD_INT(d, DB_ODDFILESIZE);
9487 ADD_INT(d, DB_RDWRMASTER);
9488 ADD_INT(d, DB_RDONLY);
9489 ADD_INT(d, DB_TRUNCATE);
9490 ADD_INT(d, DB_EXTENT);
9491 ADD_INT(d, DB_CDB_ALLDB);
9492 ADD_INT(d, DB_VERIFY);
9493 ADD_INT(d, DB_UPGRADE);
9494
9495 ADD_INT(d, DB_PRINTABLE);
9496 ADD_INT(d, DB_AGGRESSIVE);
9497 ADD_INT(d, DB_NOORDERCHK);
9498 ADD_INT(d, DB_ORDERCHKONLY);
9499 ADD_INT(d, DB_PR_PAGE);
9500
9501 ADD_INT(d, DB_PR_RECOVERYTEST);
9502 ADD_INT(d, DB_SALVAGE);
9503
9504 ADD_INT(d, DB_LOCK_NORUN);
9505 ADD_INT(d, DB_LOCK_DEFAULT);
9506 ADD_INT(d, DB_LOCK_OLDEST);
9507 ADD_INT(d, DB_LOCK_RANDOM);
9508 ADD_INT(d, DB_LOCK_YOUNGEST);
9509 ADD_INT(d, DB_LOCK_MAXLOCKS);
9510 ADD_INT(d, DB_LOCK_MINLOCKS);
9511 ADD_INT(d, DB_LOCK_MINWRITE);
9512
9513 ADD_INT(d, DB_LOCK_EXPIRE);
9514 #if (DBVER >= 43)
9515 ADD_INT(d, DB_LOCK_MAXWRITE);
9516 #endif
9517
9518 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
9519
9520 ADD_INT(d, DB_LOCK_DUMP);
9521 ADD_INT(d, DB_LOCK_GET);
9522 ADD_INT(d, DB_LOCK_INHERIT);
9523 ADD_INT(d, DB_LOCK_PUT);
9524 ADD_INT(d, DB_LOCK_PUT_ALL);
9525 ADD_INT(d, DB_LOCK_PUT_OBJ);
9526
9527 ADD_INT(d, DB_LOCK_NG);
9528 ADD_INT(d, DB_LOCK_READ);
9529 ADD_INT(d, DB_LOCK_WRITE);
9530 ADD_INT(d, DB_LOCK_NOWAIT);
9531 ADD_INT(d, DB_LOCK_WAIT);
9532 ADD_INT(d, DB_LOCK_IWRITE);
9533 ADD_INT(d, DB_LOCK_IREAD);
9534 ADD_INT(d, DB_LOCK_IWR);
9535 #if (DBVER < 44)
9536 ADD_INT(d, DB_LOCK_DIRTY);
9537 #else
9538 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
9539 #endif
9540 ADD_INT(d, DB_LOCK_WWRITE);
9541
9542 ADD_INT(d, DB_LOCK_RECORD);
9543 ADD_INT(d, DB_LOCK_UPGRADE);
9544 ADD_INT(d, DB_LOCK_SWITCH);
9545 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
9546
9547 ADD_INT(d, DB_LOCK_NOWAIT);
9548 ADD_INT(d, DB_LOCK_RECORD);
9549 ADD_INT(d, DB_LOCK_UPGRADE);
9550
9551 ADD_INT(d, DB_LSTAT_ABORTED);
9552 #if (DBVER < 43)
9553 ADD_INT(d, DB_LSTAT_ERR);
9554 #endif
9555 ADD_INT(d, DB_LSTAT_FREE);
9556 ADD_INT(d, DB_LSTAT_HELD);
9557
9558 ADD_INT(d, DB_LSTAT_PENDING);
9559 ADD_INT(d, DB_LSTAT_WAITING);
9560
9561 ADD_INT(d, DB_ARCH_ABS);
9562 ADD_INT(d, DB_ARCH_DATA);
9563 ADD_INT(d, DB_ARCH_LOG);
9564 #if (DBVER >= 42)
9565 ADD_INT(d, DB_ARCH_REMOVE);
9566 #endif
9567
9568 ADD_INT(d, DB_BTREE);
9569 ADD_INT(d, DB_HASH);
9570 ADD_INT(d, DB_RECNO);
9571 ADD_INT(d, DB_QUEUE);
9572 ADD_INT(d, DB_UNKNOWN);
9573
9574 ADD_INT(d, DB_DUP);
9575 ADD_INT(d, DB_DUPSORT);
9576 ADD_INT(d, DB_RECNUM);
9577 ADD_INT(d, DB_RENUMBER);
9578 ADD_INT(d, DB_REVSPLITOFF);
9579 ADD_INT(d, DB_SNAPSHOT);
9580
9581 #if (DBVER >= 43)
9582 ADD_INT(d, DB_INORDER);
9583 #endif
9584
9585 ADD_INT(d, DB_JOIN_NOSORT);
9586
9587 ADD_INT(d, DB_AFTER);
9588 ADD_INT(d, DB_APPEND);
9589 ADD_INT(d, DB_BEFORE);
9590 #if (DBVER < 45)
9591 ADD_INT(d, DB_CACHED_COUNTS);
9592 #endif
9593
9594 #if (DBVER <= 41)
9595 ADD_INT(d, DB_COMMIT);
9596 #endif
9597 ADD_INT(d, DB_CONSUME);
9598 ADD_INT(d, DB_CONSUME_WAIT);
9599 ADD_INT(d, DB_CURRENT);
9600 ADD_INT(d, DB_FAST_STAT);
9601 ADD_INT(d, DB_FIRST);
9602 ADD_INT(d, DB_FLUSH);
9603 ADD_INT(d, DB_GET_BOTH);
9604 ADD_INT(d, DB_GET_BOTH_RANGE);
9605 ADD_INT(d, DB_GET_RECNO);
9606 ADD_INT(d, DB_JOIN_ITEM);
9607 ADD_INT(d, DB_KEYFIRST);
9608 ADD_INT(d, DB_KEYLAST);
9609 ADD_INT(d, DB_LAST);
9610 ADD_INT(d, DB_NEXT);
9611 ADD_INT(d, DB_NEXT_DUP);
9612 ADD_INT(d, DB_NEXT_NODUP);
9613 ADD_INT(d, DB_NODUPDATA);
9614 ADD_INT(d, DB_NOOVERWRITE);
9615 ADD_INT(d, DB_NOSYNC);
9616 ADD_INT(d, DB_POSITION);
9617 ADD_INT(d, DB_PREV);
9618 ADD_INT(d, DB_PREV_NODUP);
9619 #if (DBVER >= 46)
9620 ADD_INT(d, DB_PREV_DUP);
9621 #endif
9622 #if (DBVER < 45)
9623 ADD_INT(d, DB_RECORDCOUNT);
9624 #endif
9625 ADD_INT(d, DB_SET);
9626 ADD_INT(d, DB_SET_RANGE);
9627 ADD_INT(d, DB_SET_RECNO);
9628 ADD_INT(d, DB_WRITECURSOR);
9629
9630 ADD_INT(d, DB_OPFLAGS_MASK);
9631 ADD_INT(d, DB_RMW);
9632 ADD_INT(d, DB_DIRTY_READ);
9633 ADD_INT(d, DB_MULTIPLE);
9634 ADD_INT(d, DB_MULTIPLE_KEY);
9635
9636 #if (DBVER >= 44)
9637 ADD_INT(d, DB_IMMUTABLE_KEY);
9638 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
9639 ADD_INT(d, DB_READ_COMMITTED);
9640 #endif
9641
9642 #if (DBVER >= 44)
9643 ADD_INT(d, DB_FREELIST_ONLY);
9644 ADD_INT(d, DB_FREE_SPACE);
9645 #endif
9646
9647 ADD_INT(d, DB_DONOTINDEX);
9648
9649 ADD_INT(d, DB_KEYEMPTY);
9650 ADD_INT(d, DB_KEYEXIST);
9651 ADD_INT(d, DB_LOCK_DEADLOCK);
9652 ADD_INT(d, DB_LOCK_NOTGRANTED);
9653 ADD_INT(d, DB_NOSERVER);
9654 ADD_INT(d, DB_NOSERVER_HOME);
9655 ADD_INT(d, DB_NOSERVER_ID);
9656 ADD_INT(d, DB_NOTFOUND);
9657 ADD_INT(d, DB_OLD_VERSION);
9658 ADD_INT(d, DB_RUNRECOVERY);
9659 ADD_INT(d, DB_VERIFY_BAD);
9660 ADD_INT(d, DB_PAGE_NOTFOUND);
9661 ADD_INT(d, DB_SECONDARY_BAD);
9662 ADD_INT(d, DB_STAT_CLEAR);
9663 ADD_INT(d, DB_REGION_INIT);
9664 ADD_INT(d, DB_NOLOCKING);
9665 ADD_INT(d, DB_YIELDCPU);
9666 ADD_INT(d, DB_PANIC_ENVIRONMENT);
9667 ADD_INT(d, DB_NOPANIC);
9668
9669 ADD_INT(d, DB_OVERWRITE);
9670
9671 #if (DBVER >= 43)
9672 ADD_INT(d, DB_STAT_SUBSYSTEM);
9673 ADD_INT(d, DB_STAT_MEMP_HASH);
9674 #endif
9675
9676 #if (DBVER >= 48)
9677 ADD_INT(d, DB_OVERWRITE_DUP);
9678 #endif
9679
9680 #if (DBVER >= 47)
9681 ADD_INT(d, DB_FOREIGN_ABORT);
9682 ADD_INT(d, DB_FOREIGN_CASCADE);
9683 ADD_INT(d, DB_FOREIGN_NULLIFY);
9684 #endif
9685
9686 #if (DBVER >= 44)
9687 ADD_INT(d, DB_REGISTER);
9688 #endif
9689
9690 ADD_INT(d, DB_EID_INVALID);
9691 ADD_INT(d, DB_EID_BROADCAST);
9692
9693 #if (DBVER >= 42)
9694 ADD_INT(d, DB_TIME_NOTGRANTED);
9695 ADD_INT(d, DB_TXN_NOT_DURABLE);
9696 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
9697 ADD_INT(d, DB_DIRECT_DB);
9698 ADD_INT(d, DB_INIT_REP);
9699 ADD_INT(d, DB_ENCRYPT);
9700 ADD_INT(d, DB_CHKSUM);
9701 #endif
9702
9703 #if (DBVER >= 42) && (DBVER < 47)
9704 ADD_INT(d, DB_LOG_AUTOREMOVE);
9705 ADD_INT(d, DB_DIRECT_LOG);
9706 #endif
9707
9708 #if (DBVER >= 47)
9709 ADD_INT(d, DB_LOG_DIRECT);
9710 ADD_INT(d, DB_LOG_DSYNC);
9711 ADD_INT(d, DB_LOG_IN_MEMORY);
9712 ADD_INT(d, DB_LOG_AUTO_REMOVE);
9713 ADD_INT(d, DB_LOG_ZERO);
9714 #endif
9715
9716 #if (DBVER >= 44)
9717 ADD_INT(d, DB_DSYNC_DB);
9718 #endif
9719
9720 #if (DBVER >= 45)
9721 ADD_INT(d, DB_TXN_SNAPSHOT);
9722 #endif
9723
9724 ADD_INT(d, DB_VERB_DEADLOCK);
9725 #if (DBVER >= 46)
9726 ADD_INT(d, DB_VERB_FILEOPS);
9727 ADD_INT(d, DB_VERB_FILEOPS_ALL);
9728 #endif
9729 ADD_INT(d, DB_VERB_RECOVERY);
9730 #if (DBVER >= 44)
9731 ADD_INT(d, DB_VERB_REGISTER);
9732 #endif
9733 ADD_INT(d, DB_VERB_REPLICATION);
9734 ADD_INT(d, DB_VERB_WAITSFOR);
9735
9736 #if (DBVER >= 45)
9737 ADD_INT(d, DB_EVENT_PANIC);
9738 ADD_INT(d, DB_EVENT_REP_CLIENT);
9739 #if (DBVER >= 46)
9740 ADD_INT(d, DB_EVENT_REP_ELECTED);
9741 #endif
9742 ADD_INT(d, DB_EVENT_REP_MASTER);
9743 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
9744 #if (DBVER >= 46)
9745 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
9746 #endif
9747 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
9748 ADD_INT(d, DB_EVENT_WRITE_FAILED);
9749 #endif
9750
9751 ADD_INT(d, DB_REP_DUPMASTER);
9752 ADD_INT(d, DB_REP_HOLDELECTION);
9753 #if (DBVER >= 44)
9754 ADD_INT(d, DB_REP_IGNORE);
9755 ADD_INT(d, DB_REP_JOIN_FAILURE);
9756 #endif
9757 #if (DBVER >= 42)
9758 ADD_INT(d, DB_REP_ISPERM);
9759 ADD_INT(d, DB_REP_NOTPERM);
9760 #endif
9761 ADD_INT(d, DB_REP_NEWSITE);
9762
9763 ADD_INT(d, DB_REP_MASTER);
9764 ADD_INT(d, DB_REP_CLIENT);
9765
9766 ADD_INT(d, DB_REP_PERMANENT);
9767
9768 #if (DBVER >= 44)
9769 ADD_INT(d, DB_REP_CONF_NOAUTOINIT);
9770 ADD_INT(d, DB_REP_CONF_DELAYCLIENT);
9771 ADD_INT(d, DB_REP_CONF_BULK);
9772 ADD_INT(d, DB_REP_CONF_NOWAIT);
9773 ADD_INT(d, DB_REP_ANYWHERE);
9774 ADD_INT(d, DB_REP_REREQUEST);
9775 #endif
9776
9777 #if (DBVER >= 42)
9778 ADD_INT(d, DB_REP_NOBUFFER);
9779 #endif
9780
9781 #if (DBVER >= 46)
9782 ADD_INT(d, DB_REP_LEASE_EXPIRED);
9783 ADD_INT(d, DB_IGNORE_LEASE);
9784 #endif
9785
9786 #if (DBVER >= 47)
9787 ADD_INT(d, DB_REP_CONF_LEASE);
9788 ADD_INT(d, DB_REPMGR_CONF_2SITE_STRICT);
9789 #endif
9790
9791 #if (DBVER >= 45)
9792 ADD_INT(d, DB_REP_ELECTION);
9793
9794 ADD_INT(d, DB_REP_ACK_TIMEOUT);
9795 ADD_INT(d, DB_REP_CONNECTION_RETRY);
9796 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
9797 ADD_INT(d, DB_REP_ELECTION_RETRY);
9798 #endif
9799 #if (DBVER >= 46)
9800 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
9801 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
9802 ADD_INT(d, DB_REP_LEASE_TIMEOUT);
9803 #endif
9804 #if (DBVER >= 47)
9805 ADD_INT(d, DB_REP_HEARTBEAT_MONITOR);
9806 ADD_INT(d, DB_REP_HEARTBEAT_SEND);
9807 #endif
9808
9809 #if (DBVER >= 45)
9810 ADD_INT(d, DB_REPMGR_PEER);
9811 ADD_INT(d, DB_REPMGR_ACKS_ALL);
9812 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
9813 ADD_INT(d, DB_REPMGR_ACKS_NONE);
9814 ADD_INT(d, DB_REPMGR_ACKS_ONE);
9815 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
9816 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
9817 ADD_INT(d, DB_REPMGR_CONNECTED);
9818 ADD_INT(d, DB_REPMGR_DISCONNECTED);
9819 ADD_INT(d, DB_STAT_ALL);
9820 #endif
9821
9822 #if (DBVER >= 43)
9823 ADD_INT(d, DB_BUFFER_SMALL);
9824 ADD_INT(d, DB_SEQ_DEC);
9825 ADD_INT(d, DB_SEQ_INC);
9826 ADD_INT(d, DB_SEQ_WRAP);
9827 #endif
9828
9829 #if (DBVER >= 43) && (DBVER < 47)
9830 ADD_INT(d, DB_LOG_INMEMORY);
9831 ADD_INT(d, DB_DSYNC_LOG);
9832 #endif
9833
9834 ADD_INT(d, DB_ENCRYPT_AES);
9835 ADD_INT(d, DB_AUTO_COMMIT);
9836 ADD_INT(d, DB_PRIORITY_VERY_LOW);
9837 ADD_INT(d, DB_PRIORITY_LOW);
9838 ADD_INT(d, DB_PRIORITY_DEFAULT);
9839 ADD_INT(d, DB_PRIORITY_HIGH);
9840 ADD_INT(d, DB_PRIORITY_VERY_HIGH);
9841
9842 #if (DBVER >= 46)
9843 ADD_INT(d, DB_PRIORITY_UNCHANGED);
9844 #endif
9845
9846 ADD_INT(d, EINVAL);
9847 ADD_INT(d, EACCES);
9848 ADD_INT(d, ENOSPC);
9849 ADD_INT(d, ENOMEM);
9850 ADD_INT(d, EAGAIN);
9851 ADD_INT(d, EBUSY);
9852 ADD_INT(d, EEXIST);
9853 ADD_INT(d, ENOENT);
9854 ADD_INT(d, EPERM);
9855
9856 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
9857 ADD_INT(d, DB_SET_TXN_TIMEOUT);
9858
9859 /* The exception name must be correct for pickled exception *
9860 * objects to unpickle properly. */
9861 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
9862 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
9863 #else
9864 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
9865 #endif
9866
9867 /* All the rest of the exceptions derive only from DBError */
9868 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
9869 PyDict_SetItemString(d, #name, name)
9870
9871 /* The base exception class is DBError */
9872 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
9873 MAKE_EX(DBError);
9874
9875 #if (PY_VERSION_HEX < 0x03000000)
9876 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
9877 * from both DBError and KeyError, since the API only supports
9878 * using one base class. */
9879 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
9880 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
9881 "class DBKeyEmptyError(DBError, KeyError): pass",
9882 Py_file_input, d, d);
9883 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
9884 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
9885 PyDict_DelItemString(d, "KeyError");
9886 #else
9887 /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
9888 ** derive from several classes. We use this new API only for Python 3.0,
9889 ** though.
9890 */
9891 {
9892 PyObject* bases;
9893
9894 bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
9895
9896 #define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
9897 PyDict_SetItemString(d, #name, name)
9898 MAKE_EX2(DBNotFoundError);
9899 MAKE_EX2(DBKeyEmptyError);
9900
9901 #undef MAKE_EX2
9902
9903 Py_XDECREF(bases);
9904 }
9905 #endif
9906
9907 MAKE_EX(DBCursorClosedError);
9908 MAKE_EX(DBKeyExistError);
9909 MAKE_EX(DBLockDeadlockError);
9910 MAKE_EX(DBLockNotGrantedError);
9911 MAKE_EX(DBOldVersionError);
9912 MAKE_EX(DBRunRecoveryError);
9913 MAKE_EX(DBVerifyBadError);
9914 MAKE_EX(DBNoServerError);
9915 MAKE_EX(DBNoServerHomeError);
9916 MAKE_EX(DBNoServerIDError);
9917 MAKE_EX(DBPageNotFoundError);
9918 MAKE_EX(DBSecondaryBadError);
9919
9920 MAKE_EX(DBInvalidArgError);
9921 MAKE_EX(DBAccessError);
9922 MAKE_EX(DBNoSpaceError);
9923 MAKE_EX(DBNoMemoryError);
9924 MAKE_EX(DBAgainError);
9925 MAKE_EX(DBBusyError);
9926 MAKE_EX(DBFileExistsError);
9927 MAKE_EX(DBNoSuchFileError);
9928 MAKE_EX(DBPermissionsError);
9929
9930 #if (DBVER >= 42)
9931 MAKE_EX(DBRepHandleDeadError);
9932 #endif
9933 #if (DBVER >= 44)
9934 MAKE_EX(DBRepLockoutError);
9935 #endif
9936
9937 MAKE_EX(DBRepUnavailError);
9938
9939 #if (DBVER >= 46)
9940 MAKE_EX(DBRepLeaseExpiredError);
9941 #endif
9942
9943 #if (DBVER >= 47)
9944 MAKE_EX(DBForeignConflictError);
9945 #endif
9946
9947 #undef MAKE_EX
9948
9949 /* Initialise the C API structure and add it to the module */
9950 bsddb_api.db_type = &DB_Type;
9951 bsddb_api.dbcursor_type = &DBCursor_Type;
9952 bsddb_api.dblogcursor_type = &DBLogCursor_Type;
9953 bsddb_api.dbenv_type = &DBEnv_Type;
9954 bsddb_api.dbtxn_type = &DBTxn_Type;
9955 bsddb_api.dblock_type = &DBLock_Type;
9956 #if (DBVER >= 43)
9957 bsddb_api.dbsequence_type = &DBSequence_Type;
9958 #endif
9959 bsddb_api.makeDBError = makeDBError;
9960
9961 /*
9962 ** Capsules exist from Python 3.1, but I
9963 ** don't want to break the API compatibility
9964 ** for already published Python versions.
9965 */
9966 #if (PY_VERSION_HEX < 0x03020000)
9967 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
9968 #else
9969 {
9970 char py_api_name[250];
9971
9972 strcpy(py_api_name, _bsddbModuleName);
9973 strcat(py_api_name, ".api");
9974
9975 py_api = PyCapsule_New((void*)&bsddb_api, py_api_name, NULL);
9976 }
9977 #endif
9978
9979 /* Check error control */
9980 /*
9981 ** PyErr_NoMemory();
9982 ** py_api = NULL;
9983 */
9984
9985 if (py_api) {
9986 PyDict_SetItemString(d, "api", py_api);
9987 Py_DECREF(py_api);
9988 } else { /* Something bad happened */
9989 PyErr_WriteUnraisable(m);
9990 if(PyErr_Warn(PyExc_RuntimeWarning,
9991 "_bsddb/_pybsddb C API will be not available")) {
9992 PyErr_WriteUnraisable(m);
9993 }
9994 PyErr_Clear();
9995 }
9996
9997 /* Check for errors */
9998 if (PyErr_Occurred()) {
9999 PyErr_Print();
10000 Py_FatalError("can't initialize module _bsddb/_pybsddb");
10001 Py_DECREF(m);
10002 m = NULL;
10003 }
10004 #if (PY_VERSION_HEX < 0x03000000)
10005 return;
10006 #else
10007 return m;
10008 #endif
10009 }
10010
10011 /* allow this module to be named _pybsddb so that it can be installed
10012 * and imported on top of python >= 2.3 that includes its own older
10013 * copy of the library named _bsddb without importing the old version. */
10014 #if (PY_VERSION_HEX < 0x03000000)
10015 DL_EXPORT(void) init_pybsddb(void)
10016 #else
10017 PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */
10018 #endif
10019 {
10020 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
10021 #if (PY_VERSION_HEX < 0x03000000)
10022 init_bsddb();
10023 #else
10024 return PyInit__bsddb(); /* Note the two underscores */
10025 #endif
10026 }