PageRenderTime 130ms CodeModel.GetById 23ms app.highlight 87ms RepoModel.GetById 1ms app.codeStats 1ms

/Modules/_bsddb.c

http://unladen-swallow.googlecode.com/
C | 7581 lines | 6090 code | 1117 blank | 374 comment | 772 complexity | b1b0974700e2265929347f1ae37b6bf2 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*----------------------------------------------------------------------
   2  Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
   3  and Andrew Kuchling. All rights reserved.
   4
   5  Redistribution and use in source and binary forms, with or without
   6  modification, are permitted provided that the following conditions are
   7  met:
   8
   9    o Redistributions of source code must retain the above copyright
  10      notice, this list of conditions, and the disclaimer that follows.
  11
  12    o Redistributions in binary form must reproduce the above copyright
  13      notice, this list of conditions, and the following disclaimer in
  14      the documentation and/or other materials provided with the
  15      distribution.
  16
  17    o Neither the name of Digital Creations nor the names of its
  18      contributors may be used to endorse or promote products derived
  19      from this software without specific prior written permission.
  20
  21  THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
  22  IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  23  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  24  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL
  25  CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  29  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  30  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  31  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  32  DAMAGE.
  33------------------------------------------------------------------------*/
  34
  35
  36/*
  37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
  38 * written to replace a SWIG-generated file.  It has since been updated
  39 * to compile with Berkeley DB versions 3.2 through 4.2.
  40 *
  41 * This module was started by Andrew Kuchling to remove the dependency
  42 * on SWIG in a package by Gregory P. Smith who based his work on a
  43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
  44 * Berkeley DB 2.7.x.
  45 *
  46 * Development of this module then returned full circle back to Robin Dunn
  47 * who worked on behalf of Digital Creations to complete the wrapping of
  48 * the DB 3.x API and to build a solid unit test suite.  Robin has
  49 * since gone onto other projects (wxPython).
  50 *
  51 * Gregory P. Smith <greg@krypto.org> was once again the maintainer.
  52 *
  53 * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>.
  54 * Jesus Cea licenses this code to PSF under a Contributor Agreement.
  55 *
  56 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
  57 * Things can change faster than the header of this file is updated.  This
  58 * file is shared with the PyBSDDB project at SourceForge:
  59 *
  60 * http://pybsddb.sf.net
  61 *
  62 * This file should remain backward compatible with Python 2.1, but see PEP
  63 * 291 for the most current backward compatibility requirements:
  64 *
  65 * http://www.python.org/peps/pep-0291.html
  66 *
  67 * This module contains 6 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 *
  76 */
  77
  78/* --------------------------------------------------------------------- */
  79
  80/*
  81 * Portions of this module, associated unit tests and build scripts are the
  82 * result of a contract with The Written Word (http://thewrittenword.com/)
  83 * Many thanks go out to them for causing me to raise the bar on quality and
  84 * functionality, resulting in a better bsddb3 package for all of us to use.
  85 *
  86 * --Robin
  87 */
  88
  89/* --------------------------------------------------------------------- */
  90
  91#include <stddef.h>   /* for offsetof() */
  92#include <Python.h>
  93
  94#define COMPILING_BSDDB_C
  95#include "bsddb.h"
  96#undef COMPILING_BSDDB_C
  97
  98static char *rcs_id = "$Id: _bsddb.c 66568 2008-09-23 18:54:08Z jesus.cea $";
  99
 100/* --------------------------------------------------------------------- */
 101/* Various macro definitions */
 102
 103#if (PY_VERSION_HEX < 0x02050000)
 104typedef int Py_ssize_t;
 105#endif
 106
 107#if (PY_VERSION_HEX < 0x02060000)  /* really: before python trunk r63675 */
 108/* This code now uses PyBytes* API function names instead of PyString*.
 109 * These #defines map to their equivalent on earlier python versions.    */
 110#define PyBytes_FromStringAndSize PyString_FromStringAndSize
 111#define PyBytes_FromString PyString_FromString
 112#define PyBytes_AsStringAndSize PyString_AsStringAndSize
 113#define PyBytes_Check PyString_Check
 114#define PyBytes_GET_SIZE PyString_GET_SIZE
 115#define PyBytes_AS_STRING PyString_AS_STRING
 116#endif
 117
 118#if (PY_VERSION_HEX >= 0x03000000)
 119#define NUMBER_Check    PyLong_Check
 120#define NUMBER_AsLong   PyLong_AsLong
 121#define NUMBER_FromLong PyLong_FromLong
 122#else
 123#define NUMBER_Check    PyInt_Check
 124#define NUMBER_AsLong   PyInt_AsLong
 125#define NUMBER_FromLong PyInt_FromLong
 126#endif
 127
 128#ifdef WITH_THREAD
 129
 130/* These are for when calling Python --> C */
 131#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
 132#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
 133
 134/* For 2.3, use the PyGILState_ calls */
 135#if (PY_VERSION_HEX >= 0x02030000)
 136#define MYDB_USE_GILSTATE
 137#endif
 138
 139/* and these are for calling C --> Python */
 140#if defined(MYDB_USE_GILSTATE)
 141#define MYDB_BEGIN_BLOCK_THREADS \
 142		PyGILState_STATE __savestate = PyGILState_Ensure();
 143#define MYDB_END_BLOCK_THREADS \
 144		PyGILState_Release(__savestate);
 145#else /* MYDB_USE_GILSTATE */
 146/* Pre GILState API - do it the long old way */
 147static PyInterpreterState* _db_interpreterState = NULL;
 148#define MYDB_BEGIN_BLOCK_THREADS {                              \
 149        PyThreadState* prevState;                               \
 150        PyThreadState* newState;                                \
 151        PyEval_AcquireLock();                                   \
 152        newState  = PyThreadState_New(_db_interpreterState);    \
 153        prevState = PyThreadState_Swap(newState);
 154
 155#define MYDB_END_BLOCK_THREADS                                  \
 156        newState = PyThreadState_Swap(prevState);               \
 157        PyThreadState_Clear(newState);                          \
 158        PyEval_ReleaseLock();                                   \
 159        PyThreadState_Delete(newState);                         \
 160        }
 161#endif /* MYDB_USE_GILSTATE */
 162
 163#else
 164/* Compiled without threads - avoid all this cruft */
 165#define MYDB_BEGIN_ALLOW_THREADS
 166#define MYDB_END_ALLOW_THREADS
 167#define MYDB_BEGIN_BLOCK_THREADS
 168#define MYDB_END_BLOCK_THREADS
 169
 170#endif
 171
 172/* Should DB_INCOMPLETE be turned into a warning or an exception? */
 173#define INCOMPLETE_IS_WARNING 1
 174
 175/* --------------------------------------------------------------------- */
 176/* Exceptions */
 177
 178static PyObject* DBError;               /* Base class, all others derive from this */
 179static PyObject* DBCursorClosedError;   /* raised when trying to use a closed cursor object */
 180static PyObject* DBKeyEmptyError;       /* DB_KEYEMPTY: also derives from KeyError */
 181static PyObject* DBKeyExistError;       /* DB_KEYEXIST */
 182static PyObject* DBLockDeadlockError;   /* DB_LOCK_DEADLOCK */
 183static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
 184static PyObject* DBNotFoundError;       /* DB_NOTFOUND: also derives from KeyError */
 185static PyObject* DBOldVersionError;     /* DB_OLD_VERSION */
 186static PyObject* DBRunRecoveryError;    /* DB_RUNRECOVERY */
 187static PyObject* DBVerifyBadError;      /* DB_VERIFY_BAD */
 188static PyObject* DBNoServerError;       /* DB_NOSERVER */
 189static PyObject* DBNoServerHomeError;   /* DB_NOSERVER_HOME */
 190static PyObject* DBNoServerIDError;     /* DB_NOSERVER_ID */
 191static PyObject* DBPageNotFoundError;   /* DB_PAGE_NOTFOUND */
 192static PyObject* DBSecondaryBadError;   /* DB_SECONDARY_BAD */
 193
 194#if !INCOMPLETE_IS_WARNING
 195static PyObject* DBIncompleteError;     /* DB_INCOMPLETE */
 196#endif
 197
 198static PyObject* DBInvalidArgError;     /* EINVAL */
 199static PyObject* DBAccessError;         /* EACCES */
 200static PyObject* DBNoSpaceError;        /* ENOSPC */
 201static PyObject* DBNoMemoryError;       /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
 202static PyObject* DBAgainError;          /* EAGAIN */
 203static PyObject* DBBusyError;           /* EBUSY  */
 204static PyObject* DBFileExistsError;     /* EEXIST */
 205static PyObject* DBNoSuchFileError;     /* ENOENT */
 206static PyObject* DBPermissionsError;    /* EPERM  */
 207
 208#if (DBVER >= 42)
 209static PyObject* DBRepHandleDeadError;  /* DB_REP_HANDLE_DEAD */
 210#endif
 211
 212static PyObject* DBRepUnavailError;     /* DB_REP_UNAVAIL */
 213
 214#if (DBVER < 43)
 215#define	DB_BUFFER_SMALL		ENOMEM
 216#endif
 217
 218
 219/* --------------------------------------------------------------------- */
 220/* Structure definitions */
 221
 222#if PYTHON_API_VERSION < 1010
 223#error "Python 2.1 or later required"
 224#endif
 225
 226
 227/* Defaults for moduleFlags in DBEnvObject and DBObject. */
 228#define DEFAULT_GET_RETURNS_NONE                1
 229#define DEFAULT_CURSOR_SET_RETURNS_NONE         1   /* 0 in pybsddb < 4.2, python < 2.4 */
 230
 231
 232/* See comment in Python 2.6 "object.h" */
 233#ifndef staticforward
 234#define staticforward static
 235#endif
 236#ifndef statichere
 237#define statichere static
 238#endif
 239
 240staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
 241              DBLock_Type;
 242#if (DBVER >= 43)
 243staticforward PyTypeObject DBSequence_Type;
 244#endif
 245
 246#ifndef Py_TYPE
 247/* for compatibility with Python 2.5 and earlier */
 248#define Py_TYPE(ob)              (((PyObject*)(ob))->ob_type)
 249#endif
 250
 251#define DBObject_Check(v)           (Py_TYPE(v) == &DB_Type)
 252#define DBCursorObject_Check(v)     (Py_TYPE(v) == &DBCursor_Type)
 253#define DBEnvObject_Check(v)        (Py_TYPE(v) == &DBEnv_Type)
 254#define DBTxnObject_Check(v)        (Py_TYPE(v) == &DBTxn_Type)
 255#define DBLockObject_Check(v)       (Py_TYPE(v) == &DBLock_Type)
 256#if (DBVER >= 43)
 257#define DBSequenceObject_Check(v)   (Py_TYPE(v) == &DBSequence_Type)
 258#endif
 259
 260#if (DBVER < 46)
 261  #define _DBC_close(dbc)           dbc->c_close(dbc)
 262  #define _DBC_count(dbc,a,b)       dbc->c_count(dbc,a,b)
 263  #define _DBC_del(dbc,a)           dbc->c_del(dbc,a)
 264  #define _DBC_dup(dbc,a,b)         dbc->c_dup(dbc,a,b)
 265  #define _DBC_get(dbc,a,b,c)       dbc->c_get(dbc,a,b,c)
 266  #define _DBC_pget(dbc,a,b,c,d)    dbc->c_pget(dbc,a,b,c,d)
 267  #define _DBC_put(dbc,a,b,c)       dbc->c_put(dbc,a,b,c)
 268#else
 269  #define _DBC_close(dbc)           dbc->close(dbc)
 270  #define _DBC_count(dbc,a,b)       dbc->count(dbc,a,b)
 271  #define _DBC_del(dbc,a)           dbc->del(dbc,a)
 272  #define _DBC_dup(dbc,a,b)         dbc->dup(dbc,a,b)
 273  #define _DBC_get(dbc,a,b,c)       dbc->get(dbc,a,b,c)
 274  #define _DBC_pget(dbc,a,b,c,d)    dbc->pget(dbc,a,b,c,d)
 275  #define _DBC_put(dbc,a,b,c)       dbc->put(dbc,a,b,c)
 276#endif
 277
 278
 279/* --------------------------------------------------------------------- */
 280/* Utility macros and functions */
 281
 282#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object)                   \
 283    {                                                                   \
 284        object->sibling_next=backlink;                                  \
 285        object->sibling_prev_p=&(backlink);                             \
 286        backlink=object;                                                \
 287        if (object->sibling_next) {                                     \
 288          object->sibling_next->sibling_prev_p=&(object->sibling_next); \
 289        }                                                               \
 290    }
 291
 292#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object)                          \
 293    {                                                                    \
 294        if (object->sibling_next) {                                      \
 295            object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
 296        }                                                                \
 297        *(object->sibling_prev_p)=object->sibling_next;                  \
 298    }
 299
 300#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object)               \
 301    {                                                                    \
 302        if (object->sibling_next) {                                      \
 303            object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
 304        }                                                                \
 305        if (object->sibling_prev_p) {                                    \
 306            *(object->sibling_prev_p)=object->sibling_next;              \
 307        }                                                                \
 308    }
 309
 310#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object)  \
 311    {                                                      \
 312        object->sibling_next_txn=backlink;                 \
 313        object->sibling_prev_p_txn=&(backlink);            \
 314        backlink=object;                                   \
 315        if (object->sibling_next_txn) {                    \
 316            object->sibling_next_txn->sibling_prev_p_txn=  \
 317                &(object->sibling_next_txn);               \
 318        }                                                  \
 319    }
 320
 321#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object)             \
 322    {                                                           \
 323        if (object->sibling_next_txn) {                         \
 324            object->sibling_next_txn->sibling_prev_p_txn=       \
 325                object->sibling_prev_p_txn;                     \
 326        }                                                       \
 327        *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
 328    }
 329
 330
 331#define RETURN_IF_ERR()          \
 332    if (makeDBError(err)) {      \
 333        return NULL;             \
 334    }
 335
 336#define RETURN_NONE()  Py_INCREF(Py_None); return Py_None;
 337
 338#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
 339    if ((nonNull) == NULL) {          \
 340        PyObject *errTuple = NULL;    \
 341        errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
 342        if (errTuple) { \
 343            PyErr_SetObject((pyErrObj), errTuple);  \
 344            Py_DECREF(errTuple);          \
 345        } \
 346        return NULL;                  \
 347    }
 348
 349#define CHECK_DB_NOT_CLOSED(dbobj) \
 350        _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
 351
 352#define CHECK_ENV_NOT_CLOSED(env) \
 353        _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
 354
 355#define CHECK_CURSOR_NOT_CLOSED(curs) \
 356        _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
 357
 358#if (DBVER >= 43)
 359#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
 360        _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
 361#endif
 362
 363#define CHECK_DBFLAG(mydb, flag)    (((mydb)->flags & (flag)) || \
 364                                     (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
 365
 366#define CLEAR_DBT(dbt)              (memset(&(dbt), 0, sizeof(dbt)))
 367
 368#define FREE_DBT(dbt)               if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
 369                                         dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
 370
 371
 372static int makeDBError(int err);
 373
 374
 375/* Return the access method type of the DBObject */
 376static int _DB_get_type(DBObject* self)
 377{
 378    DBTYPE type;
 379    int err;
 380
 381    err = self->db->get_type(self->db, &type);
 382    if (makeDBError(err)) {
 383        return -1;
 384    }
 385    return type;
 386}
 387
 388
 389/* Create a DBT structure (containing key and data values) from Python
 390   strings.  Returns 1 on success, 0 on an error. */
 391static int make_dbt(PyObject* obj, DBT* dbt)
 392{
 393    CLEAR_DBT(*dbt);
 394    if (obj == Py_None) {
 395        /* no need to do anything, the structure has already been zeroed */
 396    }
 397    else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
 398        PyErr_SetString(PyExc_TypeError,
 399#if (PY_VERSION_HEX < 0x03000000)
 400                        "Data values must be of type string or None.");
 401#else
 402                        "Data values must be of type bytes or None.");
 403#endif
 404        return 0;
 405    }
 406    return 1;
 407}
 408
 409
 410/* Recno and Queue DBs can have integer keys.  This function figures out
 411   what's been given, verifies that it's allowed, and then makes the DBT.
 412
 413   Caller MUST call FREE_DBT(key) when done. */
 414static int
 415make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
 416{
 417    db_recno_t recno;
 418    int type;
 419
 420    CLEAR_DBT(*key);
 421    if (keyobj == Py_None) {
 422        type = _DB_get_type(self);
 423        if (type == -1)
 424            return 0;
 425        if (type == DB_RECNO || type == DB_QUEUE) {
 426            PyErr_SetString(
 427                PyExc_TypeError,
 428                "None keys not allowed for Recno and Queue DB's");
 429            return 0;
 430        }
 431        /* no need to do anything, the structure has already been zeroed */
 432    }
 433
 434    else if (PyBytes_Check(keyobj)) {
 435        /* verify access method type */
 436        type = _DB_get_type(self);
 437        if (type == -1)
 438            return 0;
 439        if (type == DB_RECNO || type == DB_QUEUE) {
 440            PyErr_SetString(
 441                PyExc_TypeError,
 442#if (PY_VERSION_HEX < 0x03000000)
 443                "String keys not allowed for Recno and Queue DB's");
 444#else
 445                "Bytes keys not allowed for Recno and Queue DB's");
 446#endif
 447            return 0;
 448        }
 449
 450        /*
 451         * NOTE(gps): I don't like doing a data copy here, it seems
 452         * wasteful.  But without a clean way to tell FREE_DBT if it
 453         * should free key->data or not we have to.  Other places in
 454         * the code check for DB_THREAD and forceably set DBT_MALLOC
 455         * when we otherwise would leave flags 0 to indicate that.
 456         */
 457        key->data = malloc(PyBytes_GET_SIZE(keyobj));
 458        if (key->data == NULL) {
 459            PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
 460            return 0;
 461        }
 462        memcpy(key->data, PyBytes_AS_STRING(keyobj),
 463               PyBytes_GET_SIZE(keyobj));
 464        key->flags = DB_DBT_REALLOC;
 465        key->size = PyBytes_GET_SIZE(keyobj);
 466    }
 467
 468    else if (NUMBER_Check(keyobj)) {
 469        /* verify access method type */
 470        type = _DB_get_type(self);
 471        if (type == -1)
 472            return 0;
 473        if (type == DB_BTREE && pflags != NULL) {
 474            /* if BTREE then an Integer key is allowed with the
 475             * DB_SET_RECNO flag */
 476            *pflags |= DB_SET_RECNO;
 477        }
 478        else if (type != DB_RECNO && type != DB_QUEUE) {
 479            PyErr_SetString(
 480                PyExc_TypeError,
 481                "Integer keys only allowed for Recno and Queue DB's");
 482            return 0;
 483        }
 484
 485        /* Make a key out of the requested recno, use allocated space so DB
 486         * will be able to realloc room for the real key if needed. */
 487        recno = NUMBER_AsLong(keyobj);
 488        key->data = malloc(sizeof(db_recno_t));
 489        if (key->data == NULL) {
 490            PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
 491            return 0;
 492        }
 493        key->ulen = key->size = sizeof(db_recno_t);
 494        memcpy(key->data, &recno, sizeof(db_recno_t));
 495        key->flags = DB_DBT_REALLOC;
 496    }
 497    else {
 498        PyErr_Format(PyExc_TypeError,
 499#if (PY_VERSION_HEX < 0x03000000)
 500                     "String or Integer object expected for key, %s found",
 501#else
 502                     "Bytes or Integer object expected for key, %s found",
 503#endif
 504                     Py_TYPE(keyobj)->tp_name);
 505        return 0;
 506    }
 507
 508    return 1;
 509}
 510
 511
 512/* Add partial record access to an existing DBT data struct.
 513   If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
 514   and the data storage/retrieval will be done using dlen and doff. */
 515static int add_partial_dbt(DBT* d, int dlen, int doff) {
 516    /* if neither were set we do nothing (-1 is the default value) */
 517    if ((dlen == -1) && (doff == -1)) {
 518        return 1;
 519    }
 520
 521    if ((dlen < 0) || (doff < 0)) {
 522        PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
 523        return 0;
 524    }
 525
 526    d->flags = d->flags | DB_DBT_PARTIAL;
 527    d->dlen = (unsigned int) dlen;
 528    d->doff = (unsigned int) doff;
 529    return 1;
 530}
 531
 532/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
 533/* TODO: make this use the native libc strlcpy() when available (BSD)      */
 534unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
 535{
 536    unsigned int srclen, copylen;
 537
 538    srclen = strlen(src);
 539    if (n <= 0)
 540	return srclen;
 541    copylen = (srclen > n-1) ? n-1 : srclen;
 542    /* populate dest[0] thru dest[copylen-1] */
 543    memcpy(dest, src, copylen);
 544    /* guarantee null termination */
 545    dest[copylen] = 0;
 546
 547    return srclen;
 548}
 549
 550/* Callback used to save away more information about errors from the DB
 551 * library. */
 552static char _db_errmsg[1024];
 553#if (DBVER <= 42)
 554static void _db_errorCallback(const char* prefix, char* msg)
 555#else
 556static void _db_errorCallback(const DB_ENV *db_env,
 557	const char* prefix, const char* msg)
 558#endif
 559{
 560    our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
 561}
 562
 563
 564/*
 565** We need these functions because some results
 566** are undefined if pointer is NULL. Some other
 567** give None instead of "".
 568**
 569** This functions are static and will be
 570** -I hope- inlined.
 571*/
 572static const char *DummyString = "This string is a simple placeholder";
 573static PyObject *Build_PyString(const char *p,int s)
 574{
 575  if (!p) {
 576    p=DummyString;
 577    assert(s==0);
 578  }
 579  return PyBytes_FromStringAndSize(p,s);
 580}
 581
 582static PyObject *BuildValue_S(const void *p,int s)
 583{
 584  if (!p) {
 585    p=DummyString;
 586    assert(s==0);
 587  }
 588  return PyBytes_FromStringAndSize(p, s);
 589}
 590
 591static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
 592{
 593PyObject *a, *b, *r;
 594
 595  if (!p1) {
 596    p1=DummyString;
 597    assert(s1==0);
 598  }
 599  if (!p2) {
 600    p2=DummyString;
 601    assert(s2==0);
 602  }
 603
 604  if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
 605      return NULL;
 606  }
 607  if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
 608      Py_DECREF(a);
 609      return NULL;
 610  }
 611
 612#if (PY_VERSION_HEX >= 0x02040000)
 613  r = PyTuple_Pack(2, a, b) ;
 614#else
 615  r = Py_BuildValue("OO", a, b);
 616#endif
 617  Py_DECREF(a);
 618  Py_DECREF(b);
 619  return r;
 620}
 621
 622static PyObject *BuildValue_IS(int i,const void *p,int s)
 623{
 624  PyObject *a, *r;
 625
 626  if (!p) {
 627    p=DummyString;
 628    assert(s==0);
 629  }
 630
 631  if (!(a = PyBytes_FromStringAndSize(p, s))) {
 632      return NULL;
 633  }
 634
 635  r = Py_BuildValue("iO", i, a);
 636  Py_DECREF(a);
 637  return r;
 638}
 639
 640static PyObject *BuildValue_LS(long l,const void *p,int s)
 641{
 642  PyObject *a, *r;
 643
 644  if (!p) {
 645    p=DummyString;
 646    assert(s==0);
 647  }
 648
 649  if (!(a = PyBytes_FromStringAndSize(p, s))) {
 650      return NULL;
 651  }
 652
 653  r = Py_BuildValue("lO", l, a);
 654  Py_DECREF(a);
 655  return r;
 656}
 657
 658
 659
 660/* make a nice exception object to raise for errors. */
 661static int makeDBError(int err)
 662{
 663    char errTxt[2048];  /* really big, just in case... */
 664    PyObject *errObj = NULL;
 665    PyObject *errTuple = NULL;
 666    int exceptionRaised = 0;
 667    unsigned int bytes_left;
 668
 669    switch (err) {
 670        case 0:                     /* successful, no error */      break;
 671
 672#if (DBVER < 41)
 673        case DB_INCOMPLETE:
 674#if INCOMPLETE_IS_WARNING
 675            bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
 676            /* Ensure that bytes_left never goes negative */
 677            if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
 678                bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
 679		assert(bytes_left >= 0);
 680                strcat(errTxt, " -- ");
 681                strncat(errTxt, _db_errmsg, bytes_left);
 682            }
 683            _db_errmsg[0] = 0;
 684            exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
 685
 686#else  /* do an exception instead */
 687        errObj = DBIncompleteError;
 688#endif
 689        break;
 690#endif /* DBVER < 41 */
 691
 692        case DB_KEYEMPTY:           errObj = DBKeyEmptyError;       break;
 693        case DB_KEYEXIST:           errObj = DBKeyExistError;       break;
 694        case DB_LOCK_DEADLOCK:      errObj = DBLockDeadlockError;   break;
 695        case DB_LOCK_NOTGRANTED:    errObj = DBLockNotGrantedError; break;
 696        case DB_NOTFOUND:           errObj = DBNotFoundError;       break;
 697        case DB_OLD_VERSION:        errObj = DBOldVersionError;     break;
 698        case DB_RUNRECOVERY:        errObj = DBRunRecoveryError;    break;
 699        case DB_VERIFY_BAD:         errObj = DBVerifyBadError;      break;
 700        case DB_NOSERVER:           errObj = DBNoServerError;       break;
 701        case DB_NOSERVER_HOME:      errObj = DBNoServerHomeError;   break;
 702        case DB_NOSERVER_ID:        errObj = DBNoServerIDError;     break;
 703        case DB_PAGE_NOTFOUND:      errObj = DBPageNotFoundError;   break;
 704        case DB_SECONDARY_BAD:      errObj = DBSecondaryBadError;   break;
 705        case DB_BUFFER_SMALL:       errObj = DBNoMemoryError;       break;
 706
 707#if (DBVER >= 43)
 708	/* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
 709	case ENOMEM:  errObj = PyExc_MemoryError;   break;
 710#endif
 711        case EINVAL:  errObj = DBInvalidArgError;   break;
 712        case EACCES:  errObj = DBAccessError;       break;
 713        case ENOSPC:  errObj = DBNoSpaceError;      break;
 714        case EAGAIN:  errObj = DBAgainError;        break;
 715        case EBUSY :  errObj = DBBusyError;         break;
 716        case EEXIST:  errObj = DBFileExistsError;   break;
 717        case ENOENT:  errObj = DBNoSuchFileError;   break;
 718        case EPERM :  errObj = DBPermissionsError;  break;
 719
 720#if (DBVER >= 42)
 721        case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
 722#endif
 723
 724        case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
 725
 726        default:      errObj = DBError;             break;
 727    }
 728
 729    if (errObj != NULL) {
 730        bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
 731        /* Ensure that bytes_left never goes negative */
 732        if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
 733            bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
 734            assert(bytes_left >= 0);
 735            strcat(errTxt, " -- ");
 736            strncat(errTxt, _db_errmsg, bytes_left);
 737        }
 738        _db_errmsg[0] = 0;
 739
 740        errTuple = Py_BuildValue("(is)", err, errTxt);
 741        if (errTuple == NULL) {
 742            Py_DECREF(errObj);
 743            return !0;
 744        }
 745        PyErr_SetObject(errObj, errTuple);
 746        Py_DECREF(errTuple);
 747    }
 748
 749    return ((errObj != NULL) || exceptionRaised);
 750}
 751
 752
 753
 754/* set a type exception */
 755static void makeTypeError(char* expected, PyObject* found)
 756{
 757    PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
 758                 expected, Py_TYPE(found)->tp_name);
 759}
 760
 761
 762/* verify that an obj is either None or a DBTxn, and set the txn pointer */
 763static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
 764{
 765    if (txnobj == Py_None || txnobj == NULL) {
 766        *txn = NULL;
 767        return 1;
 768    }
 769    if (DBTxnObject_Check(txnobj)) {
 770        *txn = ((DBTxnObject*)txnobj)->txn;
 771        return 1;
 772    }
 773    else
 774        makeTypeError("DBTxn", txnobj);
 775    return 0;
 776}
 777
 778
 779/* Delete a key from a database
 780  Returns 0 on success, -1 on an error.  */
 781static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
 782{
 783    int err;
 784
 785    MYDB_BEGIN_ALLOW_THREADS;
 786    err = self->db->del(self->db, txn, key, 0);
 787    MYDB_END_ALLOW_THREADS;
 788    if (makeDBError(err)) {
 789        return -1;
 790    }
 791    self->haveStat = 0;
 792    return 0;
 793}
 794
 795
 796/* Store a key into a database
 797   Returns 0 on success, -1 on an error.  */
 798static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
 799{
 800    int err;
 801
 802    MYDB_BEGIN_ALLOW_THREADS;
 803    err = self->db->put(self->db, txn, key, data, flags);
 804    MYDB_END_ALLOW_THREADS;
 805    if (makeDBError(err)) {
 806        return -1;
 807    }
 808    self->haveStat = 0;
 809    return 0;
 810}
 811
 812/* Get a key/data pair from a cursor */
 813static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
 814			       PyObject *args, PyObject *kwargs, char *format)
 815{
 816    int err;
 817    PyObject* retval = NULL;
 818    DBT key, data;
 819    int dlen = -1;
 820    int doff = -1;
 821    int flags = 0;
 822    static char* kwnames[] = { "flags", "dlen", "doff", NULL };
 823
 824    if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
 825				     &flags, &dlen, &doff)) 
 826      return NULL;
 827
 828    CHECK_CURSOR_NOT_CLOSED(self);
 829
 830    flags |= extra_flags;
 831    CLEAR_DBT(key);
 832    CLEAR_DBT(data);
 833    if (!add_partial_dbt(&data, dlen, doff))
 834        return NULL;
 835
 836    MYDB_BEGIN_ALLOW_THREADS;
 837    err = _DBC_get(self->dbc, &key, &data, flags);
 838    MYDB_END_ALLOW_THREADS;
 839
 840    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
 841	    && self->mydb->moduleFlags.getReturnsNone) {
 842        Py_INCREF(Py_None);
 843        retval = Py_None;
 844    }
 845    else if (makeDBError(err)) {
 846        retval = NULL;
 847    }
 848    else {  /* otherwise, success! */
 849
 850        /* if Recno or Queue, return the key as an Int */
 851        switch (_DB_get_type(self->mydb)) {
 852        case -1:
 853            retval = NULL;
 854            break;
 855
 856        case DB_RECNO:
 857        case DB_QUEUE:
 858            retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
 859            break;
 860        case DB_HASH:
 861        case DB_BTREE:
 862        default:
 863            retval = BuildValue_SS(key.data, key.size, data.data, data.size);
 864            break;
 865        }
 866    }
 867    return retval;
 868}
 869
 870
 871/* add an integer to a dictionary using the given name as a key */
 872static void _addIntToDict(PyObject* dict, char *name, int value)
 873{
 874    PyObject* v = NUMBER_FromLong((long) value);
 875    if (!v || PyDict_SetItemString(dict, name, v))
 876        PyErr_Clear();
 877
 878    Py_XDECREF(v);
 879}
 880
 881/* The same, when the value is a time_t */
 882static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
 883{
 884    PyObject* v;
 885	/* if the value fits in regular int, use that. */
 886#ifdef PY_LONG_LONG
 887	if (sizeof(time_t) > sizeof(long))
 888		v = PyLong_FromLongLong((PY_LONG_LONG) value);
 889	else
 890#endif
 891		v = NUMBER_FromLong((long) value);
 892    if (!v || PyDict_SetItemString(dict, name, v))
 893        PyErr_Clear();
 894
 895    Py_XDECREF(v);
 896}
 897
 898#if (DBVER >= 43)
 899/* add an db_seq_t to a dictionary using the given name as a key */
 900static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
 901{
 902    PyObject* v = PyLong_FromLongLong(value);
 903    if (!v || PyDict_SetItemString(dict, name, v))
 904        PyErr_Clear();
 905
 906    Py_XDECREF(v);
 907}
 908#endif
 909
 910static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
 911{
 912    PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
 913    if (!v || PyDict_SetItemString(dict, name, v))
 914        PyErr_Clear();
 915
 916    Py_XDECREF(v);
 917}
 918
 919/* --------------------------------------------------------------------- */
 920/* Allocators and deallocators */
 921
 922static DBObject*
 923newDBObject(DBEnvObject* arg, int flags)
 924{
 925    DBObject* self;
 926    DB_ENV* db_env = NULL;
 927    int err;
 928
 929    self = PyObject_New(DBObject, &DB_Type);
 930    if (self == NULL)
 931        return NULL;
 932
 933    self->haveStat = 0;
 934    self->flags = 0;
 935    self->setflags = 0;
 936    self->myenvobj = NULL;
 937    self->db = NULL;
 938    self->children_cursors = NULL;
 939#if (DBVER >=43)
 940    self->children_sequences = NULL;
 941#endif
 942    self->associateCallback = NULL;
 943    self->btCompareCallback = NULL;
 944    self->primaryDBType = 0;
 945    Py_INCREF(Py_None);
 946    self->private_obj = Py_None;
 947    self->in_weakreflist = NULL;
 948
 949    /* keep a reference to our python DBEnv object */
 950    if (arg) {
 951        Py_INCREF(arg);
 952        self->myenvobj = arg;
 953        db_env = arg->db_env;
 954        INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
 955    } else {
 956      self->sibling_prev_p=NULL;
 957      self->sibling_next=NULL;
 958    }
 959    self->txn=NULL;
 960    self->sibling_prev_p_txn=NULL;
 961    self->sibling_next_txn=NULL;
 962
 963    if (self->myenvobj)
 964        self->moduleFlags = self->myenvobj->moduleFlags;
 965    else
 966        self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
 967        self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
 968
 969    MYDB_BEGIN_ALLOW_THREADS;
 970    err = db_create(&self->db, db_env, flags);
 971    if (self->db != NULL) {
 972        self->db->set_errcall(self->db, _db_errorCallback);
 973        self->db->app_private = (void*)self;
 974    }
 975    MYDB_END_ALLOW_THREADS;
 976    /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
 977     * list so that a DBEnv can refuse to close without aborting any open
 978     * DBTxns and closing any open DBs first. */
 979    if (makeDBError(err)) {
 980        if (self->myenvobj) {
 981            Py_DECREF(self->myenvobj);
 982            self->myenvobj = NULL;
 983        }
 984        Py_DECREF(self);
 985        self = NULL;
 986    }
 987    return self;
 988}
 989
 990
 991/* Forward declaration */
 992static PyObject *DB_close_internal(DBObject* self, int flags, int do_not_close);
 993
 994static void
 995DB_dealloc(DBObject* self)
 996{
 997  PyObject *dummy;
 998
 999    if (self->db != NULL) {
1000        dummy=DB_close_internal(self, 0, 0);
1001        /*
1002        ** Raising exceptions while doing
1003        ** garbage collection is a fatal error.
1004        */
1005        if (dummy)
1006            Py_DECREF(dummy);
1007        else
1008            PyErr_Clear();
1009    }
1010    if (self->in_weakreflist != NULL) {
1011        PyObject_ClearWeakRefs((PyObject *) self);
1012    }
1013    if (self->myenvobj) {
1014        Py_DECREF(self->myenvobj);
1015        self->myenvobj = NULL;
1016    }
1017    if (self->associateCallback != NULL) {
1018        Py_DECREF(self->associateCallback);
1019        self->associateCallback = NULL;
1020    }
1021    if (self->btCompareCallback != NULL) {
1022        Py_DECREF(self->btCompareCallback);
1023        self->btCompareCallback = NULL;
1024    }
1025    Py_DECREF(self->private_obj);
1026    PyObject_Del(self);
1027}
1028
1029static DBCursorObject*
1030newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
1031{
1032    DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
1033    if (self == NULL)
1034        return NULL;
1035
1036    self->dbc = dbc;
1037    self->mydb = db;
1038
1039    INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
1040    if (txn && ((PyObject *)txn!=Py_None)) {
1041	    INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
1042	    self->txn=txn;
1043    } else {
1044	    self->txn=NULL;
1045    }
1046
1047    self->in_weakreflist = NULL;
1048    Py_INCREF(self->mydb);
1049    return self;
1050}
1051
1052
1053/* Forward declaration */
1054static PyObject *DBC_close_internal(DBCursorObject* self);
1055
1056static void
1057DBCursor_dealloc(DBCursorObject* self)
1058{
1059    PyObject *dummy;
1060
1061    if (self->dbc != NULL) {
1062        dummy=DBC_close_internal(self);
1063        /*
1064        ** Raising exceptions while doing
1065        ** garbage collection is a fatal error.
1066        */
1067        if (dummy)
1068            Py_DECREF(dummy);
1069        else
1070            PyErr_Clear();
1071    }
1072    if (self->in_weakreflist != NULL) {
1073        PyObject_ClearWeakRefs((PyObject *) self);
1074    }
1075    Py_DECREF(self->mydb);
1076    PyObject_Del(self);
1077}
1078
1079
1080static DBEnvObject*
1081newDBEnvObject(int flags)
1082{
1083    int err;
1084    DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
1085    if (self == NULL)
1086        return NULL;
1087
1088    self->db_env = NULL;
1089    self->closed = 1;
1090    self->flags = flags;
1091    self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1092    self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
1093    self->children_dbs = NULL;
1094    self->children_txns = NULL;
1095    Py_INCREF(Py_None);
1096    self->private_obj = Py_None;
1097    Py_INCREF(Py_None);
1098    self->rep_transport = Py_None;
1099    self->in_weakreflist = NULL;
1100    self->event_notifyCallback = NULL;
1101
1102    MYDB_BEGIN_ALLOW_THREADS;
1103    err = db_env_create(&self->db_env, flags);
1104    MYDB_END_ALLOW_THREADS;
1105    if (makeDBError(err)) {
1106        Py_DECREF(self);
1107        self = NULL;
1108    }
1109    else {
1110        self->db_env->set_errcall(self->db_env, _db_errorCallback);
1111        self->db_env->app_private = self;
1112    }
1113    return self;
1114}
1115
1116/* Forward declaration */
1117static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
1118
1119static void
1120DBEnv_dealloc(DBEnvObject* self)
1121{
1122  PyObject *dummy;
1123
1124    if (self->db_env) {
1125        dummy=DBEnv_close_internal(self, 0);
1126        /*
1127        ** Raising exceptions while doing
1128        ** garbage collection is a fatal error.
1129        */
1130        if (dummy)
1131            Py_DECREF(dummy);
1132        else
1133            PyErr_Clear();
1134    }
1135
1136    Py_XDECREF(self->event_notifyCallback);
1137    self->event_notifyCallback = NULL;
1138
1139    if (self->in_weakreflist != NULL) {
1140        PyObject_ClearWeakRefs((PyObject *) self);
1141    }
1142    Py_DECREF(self->private_obj);
1143    Py_DECREF(self->rep_transport);
1144    PyObject_Del(self);
1145}
1146
1147
1148static DBTxnObject*
1149newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
1150{
1151    int err;
1152    DB_TXN *parent_txn = NULL;
1153
1154    DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
1155    if (self == NULL)
1156        return NULL;
1157
1158    self->in_weakreflist = NULL;
1159    self->children_txns = NULL;
1160    self->children_dbs = NULL;
1161    self->children_cursors = NULL;
1162    self->children_sequences = NULL;
1163    self->flag_prepare = 0;
1164    self->parent_txn = NULL;
1165    self->env = NULL;
1166
1167    if (parent && ((PyObject *)parent!=Py_None)) {
1168        parent_txn = parent->txn;
1169    }
1170
1171    if (txn) {
1172        self->txn = txn;
1173    } else {
1174        MYDB_BEGIN_ALLOW_THREADS;
1175        err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
1176        MYDB_END_ALLOW_THREADS;
1177
1178        if (makeDBError(err)) {
1179            Py_DECREF(self);
1180            return NULL;
1181        }
1182    }
1183
1184    /* Can't use 'parent' because could be 'parent==Py_None' */
1185    if (parent_txn) {
1186        self->parent_txn = parent;
1187        Py_INCREF(parent);
1188        self->env = NULL;
1189        INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
1190    } else {
1191        self->parent_txn = NULL;
1192        Py_INCREF(myenv);
1193        self->env = myenv;
1194        INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
1195    }
1196
1197    return self;
1198}
1199
1200/* Forward declaration */
1201static PyObject *
1202DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
1203
1204static void
1205DBTxn_dealloc(DBTxnObject* self)
1206{
1207  PyObject *dummy;
1208
1209    if (self->txn) {
1210        int flag_prepare = self->flag_prepare;
1211
1212        dummy=DBTxn_abort_discard_internal(self,0);
1213        /*
1214        ** Raising exceptions while doing
1215        ** garbage collection is a fatal error.
1216        */
1217        if (dummy)
1218            Py_DECREF(dummy);
1219        else
1220            PyErr_Clear();
1221
1222        if (!flag_prepare) {
1223            PyErr_Warn(PyExc_RuntimeWarning,
1224              "DBTxn aborted in destructor.  No prior commit() or abort().");
1225        }
1226    }
1227
1228    if (self->in_weakreflist != NULL) {
1229        PyObject_ClearWeakRefs((PyObject *) self);
1230    }
1231
1232    if (self->env) {
1233        Py_DECREF(self->env);
1234    } else {
1235        Py_DECREF(self->parent_txn);
1236    }
1237    PyObject_Del(self);
1238}
1239
1240
1241static DBLockObject*
1242newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1243                db_lockmode_t lock_mode, int flags)
1244{
1245    int err;
1246    DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
1247    if (self == NULL)
1248        return NULL;
1249    self->in_weakreflist = NULL;
1250
1251    MYDB_BEGIN_ALLOW_THREADS;
1252    err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1253                                  &self->lock);
1254    MYDB_END_ALLOW_THREADS;
1255    if (makeDBError(err)) {
1256        Py_DECREF(self);
1257        self = NULL;
1258    }
1259
1260    return self;
1261}
1262
1263
1264static void
1265DBLock_dealloc(DBLockObject* self)
1266{
1267    if (self->in_weakreflist != NULL) {
1268        PyObject_ClearWeakRefs((PyObject *) self);
1269    }
1270    /* TODO: is this lock held? should we release it? */
1271
1272    PyObject_Del(self);
1273}
1274
1275
1276#if (DBVER >= 43)
1277static DBSequenceObject*
1278newDBSequenceObject(DBObject* mydb,  int flags)
1279{
1280    int err;
1281    DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1282    if (self == NULL)
1283        return NULL;
1284    Py_INCREF(mydb);
1285    self->mydb = mydb;
1286
1287    INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
1288    self->txn = NULL;
1289
1290    self->in_weakreflist = NULL;
1291
1292    MYDB_BEGIN_ALLOW_THREADS;
1293    err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1294    MYDB_END_ALLOW_THREADS;
1295    if (makeDBError(err)) {
1296        Py_DECREF(self);
1297        self = NULL;
1298    }
1299
1300    return self;
1301}
1302
1303/* Forward declaration */
1304static PyObject
1305*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
1306
1307static void
1308DBSequence_dealloc(DBSequenceObject* self)
1309{
1310    PyObject *dummy;
1311
1312    if (self->sequence != NULL) {
1313        dummy=DBSequence_close_internal(self,0,0);
1314        /*
1315        ** Raising exceptions while doing
1316        ** garbage collection is a fatal error.
1317        */
1318        if (dummy)
1319            Py_DECREF(dummy);
1320        else
1321            PyErr_Clear();
1322    }
1323
1324    if (self->in_weakreflist != NULL) {
1325        PyObject_ClearWeakRefs((PyObject *) self);
1326    }
1327
1328    Py_DECREF(self->mydb);
1329    PyObject_Del(self);
1330}
1331#endif
1332
1333/* --------------------------------------------------------------------- */
1334/* DB methods */
1335
1336static PyObject*
1337DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
1338{
1339    PyObject* txnobj = NULL;
1340    PyObject* dataobj;
1341    db_recno_t recno;
1342    DBT key, data;
1343    DB_TXN *txn = NULL;
1344    static char* kwnames[] = { "data", "txn", NULL };
1345
1346    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
1347                                     &dataobj, &txnobj))
1348        return NULL;
1349
1350    CHECK_DB_NOT_CLOSED(self);
1351
1352    /* make a dummy key out of a recno */
1353    recno = 0;
1354    CLEAR_DBT(key);
1355    key.data = &recno;
1356    key.size = sizeof(recno);
1357    key.ulen = key.size;
1358    key.flags = DB_DBT_USERMEM;
1359
1360    if (!make_dbt(dataobj, &data)) return NULL;
1361    if (!checkTxnObj(txnobj, &txn)) return NULL;
1362
1363    if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1364        return NULL;
1365
1366    return NUMBER_FromLong(recno);
1367}
1368
1369
1370static int
1371_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1372                      DBT* secKey)
1373{
1374    int       retval = DB_DONOTINDEX;
1375    DBObject* secondaryDB = (DBObject*)db->app_private;
1376    PyObject* callback = secondaryDB->associateCallback;
1377    int       type = secondaryDB->primaryDBType;
1378    PyObject* args;
1379    PyObject* result = NULL;
1380
1381
1382    if (callback != NULL) {
1383        MYDB_BEGIN_BLOCK_THREADS;
1384
1385        if (type == DB_RECNO || type == DB_QUEUE)
1386            args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
1387        else
1388            args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
1389        if (args != NULL) {
1390                result = PyEval_CallObject(callback, args);
1391        }
1392        if (args == NULL || result == NULL) {
1393            PyErr_Print();
1394        }
1395        else if (result == Py_None) {
1396            retval = DB_DONOTINDEX;
1397        }
1398        else if (NUMBER_Check(result)) {
1399            retval = NUMBER_AsLong(result);
1400        }
1401        else if (PyBytes_Check(result)) {
1402            char* data;
1403            Py_ssize_t size;
1404
1405            CLEAR_DBT(*secKey);
1406            PyBytes_AsStringAndSize(result, &data, &size);
1407            secKey->flags = DB_DBT_APPMALLOC;   /* DB will free */
1408            secKey->data = malloc(size);        /* TODO, check this */
1409	    if (secKey->data) {
1410		memcpy(secKey->data, data, size);
1411		secKey->size = size;
1412		retval = 0;
1413	    }
1414	    else {
1415		PyErr_SetString(PyExc_MemoryError,
1416                                "malloc failed in _db_associateCallback");
1417		PyErr_Print();
1418	    }
1419        }
1420        else {
1421            PyErr_SetString(
1422               PyExc_TypeError,
1423               "DB associate callback should return DB_DONOTINDEX or string.");
1424            PyErr_Print();
1425        }
1426
1427        Py_XDECREF(args);
1428        Py_XDECREF(result);
1429
1430        MYDB_END_BLOCK_THREADS;
1431    }
1432    return retval;
1433}
1434
1435
1436static PyObject*
1437DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1438{
1439    int err, flags=0;
1440    DBObject* secondaryDB;
1441    PyObject* callback;
1442#if (DBVER >= 41)
1443    PyObject *txnobj = NULL;
1444    DB_TXN *txn = NULL;
1445    static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1446                                    NULL};
1447#else
1448    static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1449#endif
1450
1451#if (DBVER >= 41)
1452    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1453                                     &secondaryDB, &callback, &flags,
1454                                     &txnobj)) {
1455#else
1456    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1457                                     &secondaryDB, &callback, &flags)) {
1458#endif
1459        return NULL;
1460    }
1461
1462#if (DBVER >= 41)
1463    if (!checkTxnObj(txnobj, &txn)) return NULL;
1464#endif
1465
1466    CHECK_DB_NOT_CLOSED(self);
1467    if (!DBObject_Check(secondaryDB)) {
1468        makeTypeError("DB", (PyObject*)secondaryDB);
1469        return NULL;
1470    }
1471    CHECK_DB_NOT_CLOSED(secondaryDB);
1472    if (callback == Py_None) {
1473        callback = NULL;
1474    }
1475    else if (!PyCallable_Check(callback)) {
1476        makeTypeError("Callable", callback);
1477        return NULL;
1478    }
1479
1480    /* Save a reference to the callback in the secondary DB. */
1481    Py_XDECREF(secondaryDB->associateCallback);
1482    Py_XINCREF(callback);
1483    secondaryDB->associateCallback = callback;
1484    secondaryDB->primaryDBType = _DB_get_type(self);
1485
1486    /* PyEval_InitThreads is called here due to a quirk in python 1.5
1487     * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1488     * The global interepreter lock is not initialized until the first
1489     * thread is created using thread.start_new_thread() or fork() is
1490     * called.  that would cause the ALLOW_THREADS here to segfault due
1491     * to a null pointer reference if no threads or child processes
1492     * have been created.  This works around that and is a no-op if
1493     * threads have already been initialized.
1494     *  (see pybsddb-users mailing list post on 2002-08-07)
1495     */
1496#ifdef WITH_THREAD
1497    PyEval_InitThreads();
1498#endif
1499    MYDB_BEGIN_ALLOW_THREADS;
1500#if (DBVER >= 41)
1501    err = self->db->associate(self->db,
1502	                      txn,
1503                              secondaryDB->db,
1504                              _db_associateCallback,
1505                              flags);
1506#else
1507    err = self->db->associate(self->db,
1508                              secondaryDB->db,
1509                              _db_associateCallback,
1510                              flags);
1511#endif
1512    MYDB_END_ALLOW_THREADS;
1513
1514    if (err) {
1515        Py_XDECREF(secondaryDB->associateCallback);
1516        secondaryDB->associateCallback = NULL;
1517        secondaryDB->primaryDBType = 0;
1518    }
1519
1520    RETURN_IF_ERR();
1521    RETURN_NONE();
1522}
1523
1524
1525static PyObject*
1526DB_close_internal(DBObject* self, int flags, int do_not_close)
1527{
1528    PyObject *dummy;
1529    int err = 0;
1530
1531    if (self->db != NULL) {
1532        /* Can be NULL if db is not in an environment */
1533        EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
1534
1535        if (self->txn) {
1536            EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1537            self->txn=NULL;
1538        }
1539
1540        while(self->children_cursors) {
1541          dummy=DBC_close_internal(self->children_cursors);
1542          Py_XDECREF(dummy);
1543        }
1544
1545#if (DBVER >= 43)
1546        while(self->children_sequences) {
1547            dummy=DBSequence_close_internal(self->children_sequences,0,0);
1548            Py_XDECREF(dummy);
1549        }
1550#endif
1551
1552        /*
1553        ** "do_not_close" is used to dispose all related objects in the
1554        ** tree, without actually releasing the "root" object.
1555        ** This is done, for example, because function calls like
1556        ** "DB.verify()" implicitly close the underlying handle. So
1557        ** the handle doesn't need to be closed, but related objects
1558        ** must be cleaned up.
1559        */
1560        if (!do_not_close) {
1561            MYDB_BEGIN_ALLOW_THREADS;
1562            err = self->db->close(self->db, flags);
1563            MYDB_END_ALLOW_THREADS;
1564            self->db = NULL;
1565        }
1566        RETURN_IF_ERR();
1567    }
1568    RETURN_NONE();
1569}
1570
1571static PyObject*
1572DB_close(DBObject* self, PyObject* args)
1573{
1574    int flags=0;
1575    if (!PyArg_ParseTuple(args,"|i:close", &flags))
1576        return NULL;
1577    return DB_close_internal(self, flags, 0);
1578}
1579
1580
1581static PyObject*
1582_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1583{
1584    int err, flags=0, type;
1585    PyObject* txnobj = NULL;
1586    PyObject* retval = NULL;
1587    DBT key, data;
1588    DB_TXN *txn = NULL;
1589    static char* kwnames[] = { "txn", "flags", NULL };
1590
1591    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1592                                     &txnobj, &flags))
1593        return NULL;
1594
1595    CHECK_DB_NOT_CLOSED(self);
1596    type = _DB_get_type(self);
1597    if (type == -1)
1598        return NULL;
1599    if (type != DB_QUEUE) {
1600        PyErr_SetString(PyExc_TypeError,
1601                        "Consume methods only allowed for Queue DB's");
1602        return NULL;
1603    }
1604    if (!checkTxnObj(txnobj, &txn))
1605        return NULL;
1606
1607    CLEAR_DBT(key);
1608    CLEAR_DBT(data);
1609    if (CHECK_DBFLAG(self, DB_THREAD)) {
1610        /* Tell Berkeley DB to malloc the return value (thread safe) */
1611        data.flags = DB_DBT_MALLOC;
1612        key.flags = DB_DBT_MALLOC;
1613    }
1614
1615    MYDB_BEGIN_ALLOW_THREADS;
1616    err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1617    MYDB_END_ALLOW_THREADS;
1618
1619    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1620	    && self->moduleFlags.getReturnsNone) {
1621        err = 0;
1622        Py_INCREF(Py_None);
1623        retval = Py_None;
1624    }
1625    else if (!err) {
1626        retval = BuildValue_SS(key.data, key.size, data.data, data.size);
1627        FREE_DBT(key);
1628        FREE_DBT(data);
1629    }
1630
1631    RETURN_IF_ERR();
1632    return retval;
1633}
1634
1635static PyObject*
1636DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1637{
1638    return _DB_consume(self, args, kwargs, DB_CONSUME);
1639}
1640
1641static PyObject*
1642DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1643                int consume_flag)
1644{
1645    return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1646}
1647
1648
1649static PyObject*
1650DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1651{
1652    int err, flags=0;
1653    DBC* dbc;
1654    PyObject* txnobj = NULL;
1655    DB_TXN *txn = NULL;
1656    static char* kwnames[] = { "txn", "flags", NULL };
1657
1658    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1659              

Large files files are truncated, but you can click here to view the full file