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