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