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