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