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