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