Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

python/_rpmdb.c

Go to the documentation of this file.
00001 
00005 /*----------------------------------------------------------------------
00006   Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
00007   and Andrew Kuchling. All rights reserved.
00008 
00009   Redistribution and use in source and binary forms, with or without
00010   modification, are permitted provided that the following conditions are
00011   met:
00012 
00013     o Redistributions of source code must retain the above copyright
00014       notice, this list of conditions, and the disclaimer that follows.
00015 
00016     o Redistributions in binary form must reproduce the above copyright
00017       notice, this list of conditions, and the following disclaimer in
00018       the documentation and/or other materials provided with the
00019       distribution.
00020 
00021     o Neither the name of Digital Creations nor the names of its
00022       contributors may be used to endorse or promote products derived
00023       from this software without specific prior written permission.
00024 
00025   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
00026   IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00027   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00028   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL
00029   CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00030   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00031   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00032   OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00033   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
00034   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00035   USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00036   DAMAGE.
00037 ------------------------------------------------------------------------*/
00038 
00039 
00040 /*
00041  * Handwritten code to wrap version 3.x of the Berkeley DB library,
00042  * written to replace a SWIG-generated file.
00043  *
00044  * This module was started by Andrew Kuchling to remove the dependency
00045  * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
00046  * based his work on a similar package by Robin Dunn <robin@alldunn.com>
00047  * which wrapped Berkeley DB 2.7.x.
00048  *
00049  * Development of this module has now returned full circle back to
00050  * Robin Dunn who is working in behalf of Digital Creations to complete
00051  * the wrapping of the DB 3.x API and to build a solid unit test suite.
00052  *
00053  * This module contains 5 types:
00054  *
00055  * DB           (Database)
00056  * DBCursor     (Database Cursor)
00057  * DBEnv        (database environment)
00058  * DBTxn        (An explicit database transaction)
00059  * DBLock       (A lock handle)
00060  *
00061  */
00062 
00063 /* --------------------------------------------------------------------- */
00064 
00065 /*
00066  * Portions of this module, associated unit tests and build scripts are the
00067  * result of a contract with The Written Word (http://thewrittenword.com/)
00068  * Many thanks go out to them for causing me to raise the bar on quality and
00069  * functionality, resulting in a better bsddb3 package for all of us to use.
00070  *
00071  * --Robin
00072  *
00073  * All I've done is steal the bsddb3-3.3.1 code, and changed "bsddb3" to
00074  * "rpmdb" and "_db" to "_rpmdb" in order to avoid symbol conflicts.
00075  *
00076  * bsddb3 is Nice Stuff, I couldn't possibly do a better job.
00077  *
00078  * --Jeff
00079  *
00080  */
00081 
00082 /* --------------------------------------------------------------------- */
00083 
00084 #include <Python.h>
00085 #include <db.h>
00086 
00087 /* --------------------------------------------------------------------- */
00088 /* Various macro definitions */
00089 
00090 /* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
00091 #define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
00092 
00093 #define PY_BSDDB_VERSION "3.4.2"
00094 
00095 static char *rcs_id = "$Id: _rpmdb.c,v 1.7.2.1 2003/07/08 19:00:34 jbj Exp $";
00096 
00097 
00098 #ifdef WITH_THREAD
00099 
00100 /* These are for when calling Python --> C */
00101 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
00102 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
00103 
00104 /* and these are for calling C --> Python */
00105 static PyInterpreterState* _db_interpreterState = NULL;
00106 #define MYDB_BEGIN_BLOCK_THREADS {                              \
00107         PyThreadState* prevState;                               \
00108         PyThreadState* newState;                                \
00109         PyEval_AcquireLock();                                   \
00110         newState  = PyThreadState_New(_db_interpreterState);    \
00111         prevState = PyThreadState_Swap(newState);
00112 
00113 #define MYDB_END_BLOCK_THREADS                                  \
00114         newState = PyThreadState_Swap(prevState);               \
00115         PyThreadState_Clear(newState);                          \
00116         PyEval_ReleaseLock();                                   \
00117         PyThreadState_Delete(newState);                         \
00118         }
00119 
00120 #else
00121 
00122 #define MYDB_BEGIN_ALLOW_THREADS
00123 #define MYDB_END_ALLOW_THREADS
00124 #define MYDB_BEGIN_BLOCK_THREADS
00125 #define MYDB_END_BLOCK_THREADS
00126 
00127 #endif
00128 
00129 
00130 /* What is the default behaviour when DB->get or DBCursor->get returns a
00131    DB_NOTFOUND error?  Return None or raise an exception? */
00132 #define GET_RETURNS_NONE_DEFAULT 1
00133 
00134 
00135 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
00136 #define INCOMPLETE_IS_WARNING 1
00137 
00138 /* --------------------------------------------------------------------- */
00139 /* Exceptions */
00140 
00141 static PyObject* DBError;               /* Base class, all others derive from this */
00142 static PyObject* DBKeyEmptyError;       /* DB_KEYEMPTY */
00143 static PyObject* DBKeyExistError;       /* DB_KEYEXIST */
00144 static PyObject* DBLockDeadlockError;   /* DB_LOCK_DEADLOCK */
00145 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
00146 static PyObject* DBNotFoundError;       /* DB_NOTFOUND: also derives from KeyError */
00147 static PyObject* DBOldVersionError;     /* DB_OLD_VERSION */
00148 static PyObject* DBRunRecoveryError;    /* DB_RUNRECOVERY */
00149 static PyObject* DBVerifyBadError;      /* DB_VERIFY_BAD */
00150 static PyObject* DBNoServerError;       /* DB_NOSERVER */
00151 static PyObject* DBNoServerHomeError;   /* DB_NOSERVER_HOME */
00152 static PyObject* DBNoServerIDError;     /* DB_NOSERVER_ID */
00153 #if (DBVER >= 33)
00154 static PyObject* DBPageNotFoundError;   /* DB_PAGE_NOTFOUND */
00155 static PyObject* DBSecondaryBadError;   /* DB_SECONDARY_BAD */
00156 #endif
00157 
00158 #if !INCOMPLETE_IS_WARNING
00159 static PyObject* DBIncompleteError;     /* DB_INCOMPLETE */
00160 #endif
00161 
00162 static PyObject* DBInvalidArgError;     /* EINVAL */
00163 static PyObject* DBAccessError;         /* EACCES */
00164 static PyObject* DBNoSpaceError;        /* ENOSPC */
00165 static PyObject* DBNoMemoryError;       /* ENOMEM */
00166 static PyObject* DBAgainError;          /* EAGAIN */
00167 static PyObject* DBBusyError;           /* EBUSY  */
00168 static PyObject* DBFileExistsError;     /* EEXIST */
00169 static PyObject* DBNoSuchFileError;     /* ENOENT */
00170 static PyObject* DBPermissionsError;    /* EPERM  */
00171 
00172 
00173 
00174 /* --------------------------------------------------------------------- */
00175 /* Structure definitions */
00176 
00177 typedef struct {
00178     PyObject_HEAD
00179     DB_ENV*     db_env;
00180     int         flags;             /* saved flags from open() */
00181     int         closed;
00182     int         getReturnsNone;
00183 } DBEnvObject;
00184 
00185 
00186 typedef struct {
00187     PyObject_HEAD
00188     DB*             db;
00189     DBEnvObject*    myenvobj;  /* PyObject containing the DB_ENV */
00190     int             flags;     /* saved flags from open() */
00191     int             setflags;  /* saved flags from set_flags() */
00192     int             haveStat;
00193     int             getReturnsNone;
00194 #if (DBVER >= 33)
00195     PyObject*       associateCallback;
00196     int             primaryDBType;
00197 #endif
00198 } DBObject;
00199 
00200 
00201 typedef struct {
00202     PyObject_HEAD
00203     DBC*            dbc;
00204     DBObject*       mydb;
00205 } DBCursorObject;
00206 
00207 
00208 typedef struct {
00209     PyObject_HEAD
00210     DB_TXN*         txn;
00211 } DBTxnObject;
00212 
00213 
00214 typedef struct {
00215     PyObject_HEAD
00216     DB_LOCK         lock;
00217 } DBLockObject;
00218 
00219 
00220 
00221 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
00222 
00223 #define DBObject_Check(v)           ((v)->ob_type == &DB_Type)
00224 #define DBCursorObject_Check(v)     ((v)->ob_type == &DBCursor_Type)
00225 #define DBEnvObject_Check(v)        ((v)->ob_type == &DBEnv_Type)
00226 #define DBTxnObject_Check(v)        ((v)->ob_type == &DBTxn_Type)
00227 #define DBLockObject_Check(v)       ((v)->ob_type == &DBLock_Type)
00228 
00229 
00230 /* --------------------------------------------------------------------- */
00231 /* Utility macros and functions */
00232 
00233 #define RETURN_IF_ERR()          \
00234     if (makeDBError(err)) {      \
00235         return NULL;             \
00236     }
00237 
00238 #define RETURN_NONE()  Py_INCREF(Py_None); return Py_None;
00239 
00240 #define CHECK_DB_NOT_CLOSED(dbobj)                              \
00241     if (dbobj->db == NULL) {                                    \
00242         PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,       \
00243                                 "DB object has been closed"));  \
00244         return NULL;                                            \
00245     }
00246 
00247 #define CHECK_ENV_NOT_CLOSED(env)                               \
00248     if (env->db_env == NULL) {                                  \
00249         PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,       \
00250                                  "DBEnv object has been closed"));\
00251         return NULL;                                            \
00252     }
00253 
00254 #define CHECK_CURSOR_NOT_CLOSED(curs) \
00255     if (curs->dbc == NULL) {                                  \
00256         PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,       \
00257                                  "DBCursor object has been closed"));\
00258         return NULL;                                            \
00259     }
00260 
00261 
00262 
00263 #define CHECK_DBFLAG(mydb, flag)    (((mydb)->flags & (flag)) || \
00264                                      (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
00265 
00266 #define CLEAR_DBT(dbt)              (memset(&(dbt), 0, sizeof(dbt)))
00267 
00268 #define FREE_DBT(dbt)               if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
00269                                          dbt.data != NULL) { free(dbt.data); }
00270 
00271 
00272 static int makeDBError(int err);
00273 
00274 
00275 /* Return the access method type of the DBObject */
00276 static int _DB_get_type(DBObject* self)
00277 {
00278 #if (DBVER >= 33)
00279     DBTYPE type;
00280     int err;
00281     err = self->db->get_type(self->db, &type);
00282     if (makeDBError(err)) {
00283         return -1;
00284     }
00285     return type;
00286 #else
00287     return self->db->get_type(self->db);
00288 #endif
00289 }
00290 
00291 
00292 /* Create a DBT structure (containing key and data values) from Python
00293    strings.  Returns 1 on success, 0 on an error. */
00294 static int make_dbt(PyObject* obj, DBT* dbt)
00295 {
00296     CLEAR_DBT(*dbt);
00297     if (obj == Py_None) {
00298         /* no need to do anything, the structure has already been zeroed */
00299     }
00300     else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
00301         PyErr_SetString(PyExc_TypeError,
00302                         "Key and Data values must be of type string or None.");
00303         return 0;
00304     }
00305     return 1;
00306 }
00307 
00308 
00309 /* Recno and Queue DBs can have integer keys.  This function figures out
00310    what's been given, verifies that it's allowed, and then makes the DBT.
00311 
00312    Caller should call FREE_DBT(key) when done. */
00313 static int make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
00314 {
00315     db_recno_t recno;
00316     int type;
00317 
00318     CLEAR_DBT(*key);
00319     if (keyobj == Py_None) {  /* TODO: is None really okay for keys? */
00320         /* no need to do anything, the structure has already been zeroed */
00321     }
00322 
00323     else if (PyString_Check(keyobj)) {
00324         /* verify access method type */
00325         type = _DB_get_type(self);
00326         if (type == -1)
00327             return 0;
00328         if (type == DB_RECNO || type == DB_QUEUE) {
00329             PyErr_SetString(PyExc_TypeError, "String keys not allowed for Recno and Queue DB's");
00330             return 0;
00331         }
00332 
00333         key->data = PyString_AS_STRING(keyobj);
00334         key->size = PyString_GET_SIZE(keyobj);
00335     }
00336 
00337     else if (PyInt_Check(keyobj)) {
00338         /* verify access method type */
00339         type = _DB_get_type(self);
00340         if (type == -1)
00341             return 0;
00342         if (type == DB_BTREE && pflags != NULL) {
00343             /* if BTREE then an Integer key is allowed with the DB_SET_RECNO flag */
00344             *pflags |= DB_SET_RECNO;
00345         }
00346         else if (type != DB_RECNO && type != DB_QUEUE) {
00347             PyErr_SetString(PyExc_TypeError, "Integer keys only allowed for Recno and Queue DB's");
00348             return 0;
00349         }
00350 
00351         /* Make a key out of the requested recno, use allocated space so DB will
00352            be able to realloc room for the real key if needed. */
00353         recno = PyInt_AS_LONG(keyobj);
00354         key->data = malloc(sizeof(db_recno_t));
00355         if (key->data == NULL) {
00356             PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
00357             return 0;
00358         }
00359         key->ulen = key->size = sizeof(db_recno_t);
00360         memcpy(key->data, &recno, sizeof(db_recno_t));
00361         key->flags = DB_DBT_REALLOC;
00362     }
00363     else {
00364         PyErr_Format(PyExc_TypeError,
00365                      "String or Integer object expected for key, %s found",
00366                      keyobj->ob_type->tp_name);
00367         return 0;
00368     }
00369 
00370     return 1;
00371 }
00372 
00373 
00374 /* Add partial record access to an existing DBT data struct.
00375    If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
00376    and the data storage/retrieval will be done using dlen and doff. */
00377 static int add_partial_dbt(DBT* d, int dlen, int doff) {
00378     /* if neither were set we do nothing (-1 is the default value) */
00379     if ((dlen == -1) && (doff == -1)) {
00380         return 1;
00381     }
00382 
00383     if ((dlen < 0) || (doff < 0)) {
00384         PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
00385         return 0;
00386     }
00387 
00388     d->flags = d->flags | DB_DBT_PARTIAL;
00389     d->dlen = (unsigned int) dlen;
00390     d->doff = (unsigned int) doff;
00391     return 1;
00392 }
00393 
00394 
00395 /* Callback used to save away more information about errors from the DB library. */
00396 static char _db_errmsg[1024];
00397 static void _db_errorCallback(const char* prefix, char* msg)
00398 {
00399     strcpy(_db_errmsg, msg);
00400 }
00401 
00402 
00403 /* make a nice exception object to raise for errors. */
00404 static int makeDBError(int err)
00405 {
00406     char errTxt[2048];  /* really big, just in case... */
00407     PyObject* errObj = NULL;
00408     int exceptionRaised = 0;
00409 
00410     switch (err) {
00411         case 0:                     /* successful, no error */      break;
00412 
00413 #if (DBVER < 41)
00414         case DB_INCOMPLETE:
00415 #if INCOMPLETE_IS_WARNING
00416             strcpy(errTxt, db_strerror(err));
00417             if (_db_errmsg[0]) {
00418                 strcat(errTxt, " -- ");
00419                 strcat(errTxt, _db_errmsg);
00420                 _db_errmsg[0] = 0;
00421             }
00422 #if PYTHON_API_VERSION >= 1010 /* if Python 2.1 or better use warning framework */
00423             exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
00424 #else
00425             fprintf(stderr, errTxt);
00426             fprintf(stderr, "\n");
00427 #endif
00428 
00429 #else  /* do an exception instead */
00430         errObj = DBIncompleteError;
00431 #endif
00432         break;
00433 #endif
00434 
00435         case DB_KEYEMPTY:           errObj = DBKeyEmptyError;       break;
00436         case DB_KEYEXIST:           errObj = DBKeyExistError;       break;
00437         case DB_LOCK_DEADLOCK:      errObj = DBLockDeadlockError;   break;
00438         case DB_LOCK_NOTGRANTED:    errObj = DBLockNotGrantedError; break;
00439         case DB_NOTFOUND:           errObj = DBNotFoundError;       break;
00440         case DB_OLD_VERSION:        errObj = DBOldVersionError;     break;
00441         case DB_RUNRECOVERY:        errObj = DBRunRecoveryError;    break;
00442         case DB_VERIFY_BAD:         errObj = DBVerifyBadError;      break;
00443         case DB_NOSERVER:           errObj = DBNoServerError;       break;
00444         case DB_NOSERVER_HOME:      errObj = DBNoServerHomeError;   break;
00445         case DB_NOSERVER_ID:        errObj = DBNoServerIDError;     break;
00446 #if (DBVER >= 33)
00447         case DB_PAGE_NOTFOUND:      errObj = DBPageNotFoundError;   break;
00448         case DB_SECONDARY_BAD:      errObj = DBSecondaryBadError;   break;
00449 #endif
00450 
00451         case EINVAL:  errObj = DBInvalidArgError;   break;
00452         case EACCES:  errObj = DBAccessError;       break;
00453         case ENOSPC:  errObj = DBNoSpaceError;      break;
00454         case ENOMEM:  errObj = DBNoMemoryError;     break;
00455         case EAGAIN:  errObj = DBAgainError;        break;
00456         case EBUSY :  errObj = DBBusyError;         break;
00457         case EEXIST:  errObj = DBFileExistsError;   break;
00458         case ENOENT:  errObj = DBNoSuchFileError;   break;
00459         case EPERM :  errObj = DBPermissionsError;  break;
00460 
00461         default:      errObj = DBError;             break;
00462     }
00463 
00464     if (errObj != NULL) {
00465         strcpy(errTxt, db_strerror(err));
00466         if (_db_errmsg[0]) {
00467             strcat(errTxt, " -- ");
00468             strcat(errTxt, _db_errmsg);
00469             _db_errmsg[0] = 0;
00470         }
00471         PyErr_SetObject(errObj, Py_BuildValue("(is)", err, errTxt));
00472     }
00473 
00474     return ((errObj != NULL) || exceptionRaised);
00475 }
00476 
00477 
00478 
00479 /* set a type exception */
00480 static void makeTypeError(char* expected, PyObject* found)
00481 {
00482     PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
00483                  expected, found->ob_type->tp_name);
00484 }
00485 
00486 
00487 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
00488 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
00489 {
00490     if (txnobj == Py_None || txnobj == NULL) {
00491         *txn = NULL;
00492         return 1;
00493     }
00494     if (DBTxnObject_Check(txnobj)) {
00495         *txn = ((DBTxnObject*)txnobj)->txn;
00496         return 1;
00497     }
00498     else
00499         makeTypeError("DBTxn", txnobj);
00500     return 0;
00501 }
00502 
00503 
00504 /* Delete a key from a database
00505   Returns 0 on success, -1 on an error.  */
00506 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
00507 {
00508     int err;
00509 
00510     MYDB_BEGIN_ALLOW_THREADS;
00511     err = self->db->del(self->db, txn, key, 0);
00512     MYDB_END_ALLOW_THREADS;
00513     if (makeDBError(err)) {
00514         return -1;
00515     }
00516     self->haveStat = 0;
00517     return 0;
00518 }
00519 
00520 
00521 /* Store a key into a database
00522    Returns 0 on success, -1 on an error.  */
00523 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
00524 {
00525     int err;
00526 
00527     MYDB_BEGIN_ALLOW_THREADS;
00528     err = self->db->put(self->db, txn, key, data, flags);
00529     MYDB_END_ALLOW_THREADS;
00530     if (makeDBError(err)) {
00531         return -1;
00532     }
00533     self->haveStat = 0;
00534     return 0;
00535 }
00536 
00537 /* Get a key/data pair from a cursor */
00538 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
00539                                PyObject *args, PyObject *kwargs, char *format)
00540 {
00541     int err;
00542     PyObject* retval = NULL;
00543     DBT key, data;
00544     int dlen = -1;
00545     int doff = -1;
00546     int flags = 0;
00547     char* kwnames[] = { "flags", "dlen", "doff", NULL };
00548 
00549     if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
00550                                      &flags, &dlen, &doff)) 
00551       return NULL;
00552 
00553     CHECK_CURSOR_NOT_CLOSED(self);
00554 
00555     flags |= extra_flags;
00556     CLEAR_DBT(key);
00557     CLEAR_DBT(data);
00558     if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
00559         /* Tell BerkeleyDB to malloc the return value (thread safe) */
00560         data.flags = DB_DBT_MALLOC;
00561         key.flags = DB_DBT_MALLOC;
00562     }
00563     if (!add_partial_dbt(&data, dlen, doff))
00564         return NULL;
00565 
00566     MYDB_BEGIN_ALLOW_THREADS;
00567     err = self->dbc->c_get(self->dbc, &key, &data, flags);
00568     MYDB_END_ALLOW_THREADS;
00569 
00570     if ((err == DB_NOTFOUND) && self->mydb->getReturnsNone) {
00571         Py_INCREF(Py_None);
00572         retval = Py_None;
00573     }
00574     else if (makeDBError(err)) {
00575         retval = NULL;
00576     }
00577     else {  /* otherwise, success! */
00578 
00579         /* if Recno or Queue, return the key as an Int */
00580         switch (_DB_get_type(self->mydb)) {
00581         case -1:
00582             retval = NULL;
00583             break;
00584 
00585         case DB_RECNO:
00586         case DB_QUEUE:
00587             retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
00588                                    data.data, data.size);
00589             break;
00590         case DB_HASH:
00591         case DB_BTREE:
00592         default:
00593             retval = Py_BuildValue("s#s#", key.data, key.size,
00594                                    data.data, data.size);
00595             break;
00596         }
00597     }
00598     if (!err) {
00599         FREE_DBT(key);
00600         FREE_DBT(data);
00601     }
00602     return retval;
00603 }
00604 
00605 
00606 /* add an integer to a dictionary using the given name as a key */
00607 static void _addIntToDict(PyObject* dict, char *name, int value)
00608 {
00609     PyObject* v = PyInt_FromLong((long) value);
00610     if (!v || PyDict_SetItemString(dict, name, v))
00611         PyErr_Clear();
00612 
00613     Py_XDECREF(v);
00614 }
00615 
00616 
00617 
00618 
00619 /* --------------------------------------------------------------------- */
00620 /* Allocators and deallocators */
00621 
00622 static DBObject*
00623 newDBObject(DBEnvObject* arg, int flags)
00624 {
00625     DBObject* self;
00626     DB_ENV* db_env = NULL;
00627     int err;
00628 
00629 #if PYTHON_API_VERSION <= 1007
00630     /* 1.5 compatibility */
00631     self = PyObject_NEW(DBObject, &DB_Type);
00632 #else
00633     self = PyObject_New(DBObject, &DB_Type);
00634 #endif
00635 
00636     if (self == NULL)
00637         return NULL;
00638 
00639     self->haveStat = 0;
00640     self->flags = 0;
00641     self->setflags = 0;
00642     self->myenvobj = NULL;
00643 #if (DBVER >= 33)
00644     self->associateCallback = NULL;
00645     self->primaryDBType = 0;
00646 #endif
00647 
00648     /* keep a reference to our python DBEnv object */
00649     if (arg) {
00650         Py_INCREF(arg);
00651         self->myenvobj = arg;
00652         db_env = arg->db_env;
00653     }
00654 
00655     if (self->myenvobj)
00656         self->getReturnsNone = self->myenvobj->getReturnsNone;
00657     else
00658         self->getReturnsNone = GET_RETURNS_NONE_DEFAULT;
00659 
00660     MYDB_BEGIN_ALLOW_THREADS;
00661     err = db_create(&self->db, db_env, flags);
00662     self->db->set_errcall(self->db, _db_errorCallback);
00663 #if (DBVER >= 33)
00664     self->db->app_private = (void*)self;
00665 #endif
00666     MYDB_END_ALLOW_THREADS;
00667     if (makeDBError(err)) {
00668         if (self->myenvobj) {
00669             Py_DECREF(self->myenvobj);
00670             self->myenvobj = NULL;
00671         }
00672         self = NULL;
00673     }
00674     return self;
00675 }
00676 
00677 
00678 static void
00679 DB_dealloc(DBObject* self)
00680 {
00681     if (self->db != NULL) {
00682         /* avoid closing a DB when its DBEnv has been closed out from under it */
00683         if (!self->myenvobj ||
00684             (self->myenvobj && self->myenvobj->db_env)) {
00685             MYDB_BEGIN_ALLOW_THREADS;
00686             self->db->close(self->db, 0);
00687             MYDB_END_ALLOW_THREADS;
00688 #if PYTHON_API_VERSION >= 1010 /* if Python 2.1 or better use warning framework */
00689         } else {
00690             PyErr_Warn(PyExc_RuntimeWarning,
00691                 "DB could not be closed in destructor: DBEnv already closed");
00692 #endif
00693         }
00694         self->db = NULL;
00695     }
00696     if (self->myenvobj) {
00697         Py_DECREF(self->myenvobj);
00698         self->myenvobj = NULL;
00699     }
00700 #if (DBVER >= 33)
00701     if (self->associateCallback != NULL) {
00702         Py_DECREF(self->associateCallback);
00703         self->associateCallback = NULL;
00704     }
00705 #endif
00706 #if PYTHON_API_VERSION <= 1007
00707     PyMem_DEL(self);
00708 #else
00709     PyObject_Del(self);
00710 #endif
00711 }
00712 
00713 
00714 static DBCursorObject*
00715 newDBCursorObject(DBC* dbc, DBObject* db)
00716 {
00717     DBCursorObject* self;
00718 #if PYTHON_API_VERSION <= 1007
00719     self = PyObject_NEW(DBCursorObject, &DBCursor_Type);
00720 #else
00721     self = PyObject_New(DBCursorObject, &DBCursor_Type);
00722 #endif
00723     if (self == NULL)
00724         return NULL;
00725 
00726     self->dbc = dbc;
00727     self->mydb = db;
00728     Py_INCREF(self->mydb);
00729     return self;
00730 }
00731 
00732 
00733 static void
00734 DBCursor_dealloc(DBCursorObject* self)
00735 {
00736     int err;
00737     if (self->dbc != NULL) {
00738         MYDB_BEGIN_ALLOW_THREADS;
00739         err = self->dbc->c_close(self->dbc);
00740         self->dbc = NULL;
00741         MYDB_END_ALLOW_THREADS;
00742     }
00743     Py_XDECREF( self->mydb );
00744 #if PYTHON_API_VERSION <= 1007
00745     PyMem_DEL(self);
00746 #else
00747     PyObject_Del(self);
00748 #endif
00749 }
00750 
00751 
00752 static DBEnvObject*
00753 newDBEnvObject(int flags)
00754 {
00755     int err;
00756     DBEnvObject* self;
00757 #if PYTHON_API_VERSION <= 1007
00758     self = PyObject_NEW(DBEnvObject, &DBEnv_Type);
00759 #else
00760     self = PyObject_New(DBEnvObject, &DBEnv_Type);
00761 #endif
00762 
00763     if (self == NULL)
00764         return NULL;
00765 
00766     self->closed = 1;
00767     self->flags = flags;
00768     self->getReturnsNone = GET_RETURNS_NONE_DEFAULT;
00769 
00770     MYDB_BEGIN_ALLOW_THREADS;
00771     err = db_env_create(&self->db_env, flags);
00772     MYDB_END_ALLOW_THREADS;
00773     if (makeDBError(err)) {
00774         self = NULL;
00775     }
00776     else {
00777         self->db_env->set_errcall(self->db_env, _db_errorCallback);
00778     }
00779     return self;
00780 }
00781 
00782 
00783 static void
00784 DBEnv_dealloc(DBEnvObject* self)
00785 {
00786     if (!self->closed) {
00787         MYDB_BEGIN_ALLOW_THREADS;
00788         self->db_env->close(self->db_env, 0);
00789         MYDB_END_ALLOW_THREADS;
00790     }
00791 #if PYTHON_API_VERSION <= 1007
00792     PyMem_DEL(self);
00793 #else
00794     PyObject_Del(self);
00795 #endif
00796 }
00797 
00798 
00799 static DBTxnObject*
00800 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
00801 {
00802     int err;
00803     DBTxnObject* self;
00804 
00805 #if PYTHON_API_VERSION <= 1007
00806     self = PyObject_NEW(DBTxnObject, &DBTxn_Type);
00807 #else
00808     self = PyObject_New(DBTxnObject, &DBTxn_Type);
00809 #endif
00810     if (self == NULL)
00811         return NULL;
00812 
00813     MYDB_BEGIN_ALLOW_THREADS;
00814 #if (DBVER >= 40)
00815     err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
00816 #else
00817     err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
00818 #endif
00819     MYDB_END_ALLOW_THREADS;
00820     if (makeDBError(err)) {
00821         self = NULL;
00822     }
00823     return self;
00824 }
00825 
00826 
00827 static void
00828 DBTxn_dealloc(DBTxnObject* self)
00829 {
00830     /* XXX nothing to do for transaction objects?!? */
00831 
00832     /* TODO: if it hasn't been commited, should we abort it? */
00833 
00834 #if PYTHON_API_VERSION <= 1007
00835     PyMem_DEL(self);
00836 #else
00837     PyObject_Del(self);
00838 #endif
00839 }
00840 
00841 
00842 static DBLockObject*
00843 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
00844                 db_lockmode_t lock_mode, int flags)
00845 {
00846     int err;
00847     DBLockObject* self;
00848 
00849 #if PYTHON_API_VERSION <= 1007
00850     self = PyObject_NEW(DBLockObject, &DBLock_Type);
00851 #else
00852     self = PyObject_New(DBLockObject, &DBLock_Type);
00853 #endif
00854     if (self == NULL)
00855         return NULL;
00856 
00857     MYDB_BEGIN_ALLOW_THREADS;
00858 #if (DBVER >= 40)
00859     err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
00860 #else
00861     err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
00862 #endif
00863     MYDB_END_ALLOW_THREADS;
00864     if (makeDBError(err)) {
00865         self = NULL;
00866     }
00867 
00868     return self;
00869 }
00870 
00871 
00872 static void
00873 DBLock_dealloc(DBLockObject* self)
00874 {
00875     /* TODO: if it hasn't been released, should we do it? */
00876 
00877 #if PYTHON_API_VERSION <= 1007
00878     PyMem_DEL(self);
00879 #else
00880     PyObject_Del(self);
00881 #endif
00882 }
00883 
00884 
00885 /* --------------------------------------------------------------------- */
00886 /* DB methods */
00887 
00888 static PyObject*
00889 DB_append(DBObject* self, PyObject* args)
00890 {
00891     PyObject* txnobj = NULL;
00892     PyObject* dataobj;
00893     db_recno_t recno;
00894     DBT key, data;
00895     DB_TXN *txn = NULL;
00896 
00897     if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
00898         return NULL;
00899 
00900     CHECK_DB_NOT_CLOSED(self);
00901 
00902     /* make a dummy key out of a recno */
00903     recno = 0;
00904     CLEAR_DBT(key);
00905     key.data = &recno;
00906     key.size = sizeof(recno);
00907     key.ulen = key.size;
00908     key.flags = DB_DBT_USERMEM;
00909 
00910     if (!make_dbt(dataobj, &data)) return NULL;
00911     if (!checkTxnObj(txnobj, &txn)) return NULL;
00912 
00913     if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
00914         return NULL;
00915 
00916     return PyInt_FromLong(recno);
00917 }
00918 
00919 
00920 #if (DBVER >= 33)
00921 
00922 static int
00923 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData, DBT* secKey)
00924 {
00925     int       retval = DB_DONOTINDEX;
00926     DBObject* secondaryDB = (DBObject*)db->app_private;
00927     PyObject* callback = secondaryDB->associateCallback;
00928     int       type = secondaryDB->primaryDBType;
00929     PyObject* key;
00930     PyObject* data;
00931     PyObject* args;
00932     PyObject* result;
00933 
00934 
00935     if (callback != NULL) {
00936         MYDB_BEGIN_BLOCK_THREADS;
00937 
00938         if (type == DB_RECNO || type == DB_QUEUE) {
00939             key = PyInt_FromLong( *((db_recno_t*)priKey->data));
00940         }
00941         else {
00942             key  = PyString_FromStringAndSize(priKey->data, priKey->size);
00943         }
00944         data = PyString_FromStringAndSize(priData->data, priData->size);
00945         args = PyTuple_New(2);
00946         PyTuple_SET_ITEM(args, 0, key);  /* steals reference */
00947         PyTuple_SET_ITEM(args, 1, data); /* steals reference */
00948 
00949         result = PyEval_CallObject(callback, args);
00950 
00951         if (result == NULL) {
00952             PyErr_Print();
00953         }
00954         else if (result == Py_None) {
00955             retval = DB_DONOTINDEX;
00956         }
00957         else if (PyInt_Check(result)) {
00958             retval = PyInt_AsLong(result);
00959         }
00960         else if (PyString_Check(result)) {
00961             char* data;
00962             int   size;
00963 
00964             CLEAR_DBT(*secKey);
00965 #if PYTHON_API_VERSION <= 1007
00966             /* 1.5 compatibility */
00967             size = PyString_Size(result);
00968             data = PyString_AsString(result);
00969 #else
00970             PyString_AsStringAndSize(result, &data, &size);
00971 #endif
00972             secKey->flags = DB_DBT_APPMALLOC;   /* DB will free */
00973             secKey->data = malloc(size);        /* TODO, check this */
00974             memcpy(secKey->data, data, size);
00975             secKey->size = size;
00976             retval = 0;
00977         }
00978         else {
00979             PyErr_SetString(PyExc_TypeError,
00980                             "DB associate callback should return DB_DONOTINDEX or a string.");
00981             PyErr_Print();
00982         }
00983 
00984         Py_DECREF(args);
00985         if (result) {
00986             Py_DECREF(result);
00987         }
00988 
00989         MYDB_END_BLOCK_THREADS;
00990     }
00991     return retval;
00992 }
00993 
00994 
00995 static PyObject*
00996 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
00997 {
00998     int err, flags=0;
00999     DBObject* secondaryDB;
01000     PyObject* callback;
01001     char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
01002 
01003     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
01004                                      &secondaryDB, &callback, &flags))
01005         return NULL;
01006 
01007     CHECK_DB_NOT_CLOSED(self);
01008     if (!DBObject_Check(secondaryDB)) {
01009         makeTypeError("DB", (PyObject*)secondaryDB);
01010         return NULL;
01011     }
01012     if (callback == Py_None) {
01013         callback = NULL;
01014     }
01015     else if (!PyCallable_Check(callback)) {
01016         makeTypeError("Callable", callback);
01017         return NULL;
01018     }
01019 
01020     /* Save a reference to the callback in the secondary DB. */
01021     if (self->associateCallback != NULL) {
01022         Py_DECREF(self->associateCallback);
01023     }
01024     Py_INCREF(callback);
01025     secondaryDB->associateCallback = callback;
01026     secondaryDB->primaryDBType = _DB_get_type(self);
01027 
01028     /* PyEval_InitThreads is called here due to a quirk in python 1.5
01029      * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
01030      * The global interepreter lock is not initialized until the first
01031      * thread is created using thread.start_new_thread() or fork() is
01032      * called.  that would cause the ALLOW_THREADS here to segfault due
01033      * to a null pointer reference if no threads or child processes
01034      * have been created.  This works around that and is a no-op if
01035      * threads have already been initialized.
01036      *  (see pybsddb-users mailing list post on 2002-08-07)
01037      */
01038     PyEval_InitThreads();
01039     MYDB_BEGIN_ALLOW_THREADS;
01040 #if (DBVER >= 41)
01041     err = self->db->associate(self->db, NULL,
01042                               secondaryDB->db,
01043                               _db_associateCallback,
01044                               flags);
01045 #else
01046     err = self->db->associate(self->db,
01047                               secondaryDB->db,
01048                               _db_associateCallback,
01049                               flags);
01050 #endif
01051     MYDB_END_ALLOW_THREADS;
01052 
01053     if (err) {
01054         Py_DECREF(self->associateCallback);
01055         self->associateCallback = NULL;
01056         secondaryDB->primaryDBType = 0;
01057     }
01058 
01059     RETURN_IF_ERR();
01060     RETURN_NONE();
01061 }
01062 
01063 
01064 #endif
01065 
01066 
01067 static PyObject*
01068 DB_close(DBObject* self, PyObject* args)
01069 {
01070     int err, flags=0;
01071     if (!PyArg_ParseTuple(args,"|i:close", &flags))
01072         return NULL;
01073     if (self->db != NULL) {
01074         if (self->myenvobj)
01075             CHECK_ENV_NOT_CLOSED(self->myenvobj);
01076         MYDB_BEGIN_ALLOW_THREADS;
01077         err = self->db->close(self->db, flags);
01078         MYDB_END_ALLOW_THREADS;
01079         self->db = NULL;
01080         RETURN_IF_ERR();
01081     }
01082     RETURN_NONE();
01083 }
01084 
01085 
01086 #if (DBVER >= 32)
01087 static PyObject*
01088 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
01089 {
01090     int err, flags=0, type;
01091     PyObject* txnobj = NULL;
01092     PyObject* retval = NULL;
01093     DBT key, data;
01094     DB_TXN *txn = NULL;
01095     char* kwnames[] = { "txn", "flags", NULL };
01096 
01097     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
01098                                      &txnobj, &flags))
01099         return NULL;
01100 
01101     CHECK_DB_NOT_CLOSED(self);
01102     type = _DB_get_type(self);
01103     if (type == -1)
01104         return NULL;
01105     if (type != DB_QUEUE) {
01106         PyErr_SetString(PyExc_TypeError, "Consume methods only allowed for Queue DB's");
01107         return NULL;
01108     }
01109     if (!checkTxnObj(txnobj, &txn))
01110         return NULL;
01111 
01112     CLEAR_DBT(key);
01113     CLEAR_DBT(data);
01114     if (CHECK_DBFLAG(self, DB_THREAD)) {
01115         /* Tell BerkeleyDB to malloc the return value (thread safe) */
01116         data.flags = DB_DBT_MALLOC;
01117         key.flags = DB_DBT_MALLOC;
01118     }
01119 
01120     MYDB_BEGIN_ALLOW_THREADS;
01121     err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
01122     MYDB_END_ALLOW_THREADS;
01123 
01124     if ((err == DB_NOTFOUND) && self->getReturnsNone) {
01125         err = 0;
01126         Py_INCREF(Py_None);
01127         retval = Py_None;
01128     }
01129     else if (!err) {
01130         retval = Py_BuildValue("s#s#", key.data, key.size, data.data, data.size);
01131         FREE_DBT(key);
01132         FREE_DBT(data);
01133     }
01134 
01135     RETURN_IF_ERR();
01136     return retval;
01137 }
01138 
01139 static PyObject*
01140 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
01141 {
01142     return _DB_consume(self, args, kwargs, DB_CONSUME);
01143 }
01144 
01145 static PyObject*
01146 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
01147 {
01148     return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
01149 }
01150 #endif
01151 
01152 
01153 
01154 static PyObject*
01155 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
01156 {
01157     int err, flags=0;
01158     DBC* dbc;
01159     PyObject* txnobj = NULL;
01160     DB_TXN *txn = NULL;
01161     char* kwnames[] = { "txn", "flags", NULL };
01162 
01163     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
01164                                      &txnobj, &flags))
01165         return NULL;
01166     CHECK_DB_NOT_CLOSED(self);
01167     if (!checkTxnObj(txnobj, &txn))
01168         return NULL;
01169 
01170     MYDB_BEGIN_ALLOW_THREADS;
01171     err = self->db->cursor(self->db, txn, &dbc, flags);
01172     MYDB_END_ALLOW_THREADS;
01173     RETURN_IF_ERR();
01174     return (PyObject*) newDBCursorObject(dbc, self);
01175 }
01176 
01177 
01178 static PyObject*
01179 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
01180 {
01181     PyObject* txnobj = NULL;
01182     int flags = 0;
01183     PyObject* keyobj;
01184     DBT key;
01185     DB_TXN *txn = NULL;
01186     char* kwnames[] = { "key", "txn", "flags", NULL };
01187 
01188     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
01189                                      &keyobj, &txnobj, &flags))
01190         return NULL;
01191     CHECK_DB_NOT_CLOSED(self);
01192     if (!make_key_dbt(self, keyobj, &key, NULL))
01193         return NULL;
01194     if (!checkTxnObj(txnobj, &txn))
01195         return NULL;
01196 
01197     if (-1 == _DB_delete(self, txn, &key, 0))
01198         return NULL;
01199 
01200     FREE_DBT(key);
01201     RETURN_NONE();
01202 }
01203 
01204 
01205 static PyObject*
01206 DB_fd(DBObject* self, PyObject* args)
01207 {
01208     int err, the_fd;
01209 
01210     if (!PyArg_ParseTuple(args,":fd"))
01211         return NULL;
01212     CHECK_DB_NOT_CLOSED(self);
01213 
01214     MYDB_BEGIN_ALLOW_THREADS;
01215     err = self->db->fd(self->db, &the_fd);
01216     MYDB_END_ALLOW_THREADS;
01217     RETURN_IF_ERR();
01218     return PyInt_FromLong(the_fd);
01219 }
01220 
01221 
01222 static PyObject*
01223 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
01224 {
01225     int err, flags=0;
01226     PyObject* txnobj = NULL;
01227     PyObject* keyobj;
01228     PyObject* dfltobj = NULL;
01229     PyObject* retval = NULL;
01230     int dlen = -1;
01231     int doff = -1;
01232     DBT key, data;
01233     DB_TXN *txn = NULL;
01234     char* kwnames[] = { "key", "default", "txn", "flags", "dlen", "doff", NULL };
01235 
01236     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
01237                                      &keyobj, &dfltobj, &txnobj, &flags, &dlen, &doff))
01238         return NULL;
01239 
01240     CHECK_DB_NOT_CLOSED(self);
01241     if (!make_key_dbt(self, keyobj, &key, &flags))
01242         return NULL;
01243     if (!checkTxnObj(txnobj, &txn))
01244         return NULL;
01245 
01246     CLEAR_DBT(data);
01247     if (CHECK_DBFLAG(self, DB_THREAD)) {
01248         /* Tell BerkeleyDB to malloc the return value (thread safe) */
01249         data.flags = DB_DBT_MALLOC;
01250     }
01251     if (!add_partial_dbt(&data, dlen, doff))
01252         return NULL;
01253 
01254     MYDB_BEGIN_ALLOW_THREADS;
01255     err = self->db->get(self->db, txn, &key, &data, flags);
01256     MYDB_END_ALLOW_THREADS;
01257 
01258     if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
01259         err = 0;
01260         Py_INCREF(dfltobj);
01261         retval = dfltobj;
01262     }
01263     else if ((err == DB_NOTFOUND) && self->getReturnsNone) {
01264         err = 0;
01265         Py_INCREF(Py_None);
01266         retval = Py_None;
01267     }
01268     else if (!err) {
01269         if (flags & DB_SET_RECNO) /* return both key and data */
01270             retval = Py_BuildValue("s#s#", key.data, key.size, data.data, data.size);
01271         else /* return just the data */
01272             retval = PyString_FromStringAndSize((char*)data.data, data.size);
01273         FREE_DBT(key);
01274         FREE_DBT(data);
01275     }
01276 
01277     RETURN_IF_ERR();
01278     return retval;
01279 }
01280 
01281 
01282 /* Return size of entry */
01283 static PyObject*
01284 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
01285 {
01286     int err, flags=0;
01287     PyObject* txnobj = NULL;
01288     PyObject* keyobj;
01289     PyObject* retval = NULL;
01290     DBT key, data;
01291     DB_TXN *txn = NULL;
01292     char* kwnames[] = { "key", "txn", NULL };
01293 
01294     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
01295                                      &keyobj, &txnobj))
01296         return NULL;
01297     CHECK_DB_NOT_CLOSED(self);
01298     if (!make_key_dbt(self, keyobj, &key, &flags))
01299         return NULL;
01300     if (!checkTxnObj(txnobj, &txn))
01301         return NULL;
01302     CLEAR_DBT(data);
01303 
01304     /* We don't allocate any memory, forcing a ENOMEM error and thus
01305        getting the record size. */
01306     data.flags = DB_DBT_USERMEM;
01307     data.ulen = 0;
01308     MYDB_BEGIN_ALLOW_THREADS;
01309     err = self->db->get(self->db, txn, &key, &data, flags);
01310     MYDB_END_ALLOW_THREADS;
01311     if (err == ENOMEM) {
01312         retval = PyInt_FromLong((long)data.size);
01313         err = 0;
01314     }
01315 
01316     FREE_DBT(key);
01317     FREE_DBT(data);
01318     RETURN_IF_ERR();
01319     return retval;
01320 }
01321 
01322 
01323 static PyObject*
01324 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
01325 {
01326     int err, flags=0;
01327     PyObject* txnobj = NULL;
01328     PyObject* keyobj;
01329     PyObject* dataobj;
01330     PyObject* retval = NULL;
01331     DBT key, data;
01332     DB_TXN *txn = NULL;
01333     char* kwnames[] = { "key", "data", "txn", "flags", NULL };
01334 
01335 
01336     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
01337                                      &keyobj, &dataobj, &txnobj, &flags))
01338         return NULL;
01339 
01340     CHECK_DB_NOT_CLOSED(self);
01341     if (!make_key_dbt(self, keyobj, &key, NULL))
01342         return NULL;
01343     if (!make_dbt(dataobj, &data))
01344         return NULL;
01345     if (!checkTxnObj(txnobj, &txn))
01346         return NULL;
01347 
01348     flags |= DB_GET_BOTH;
01349 
01350     if (CHECK_DBFLAG(self, DB_THREAD)) {
01351         /* Tell BerkeleyDB to malloc the return value (thread safe) */
01352         data.flags = DB_DBT_MALLOC;
01353         /* TODO: Is this flag needed?  We're passing a data object that should
01354                  match what's in the DB, so there should be no need to malloc.
01355                  We run the risk of freeing something twice!  Check this. */
01356     }
01357 
01358     MYDB_BEGIN_ALLOW_THREADS;
01359     err = self->db->get(self->db, txn, &key, &data, flags);
01360     MYDB_END_ALLOW_THREADS;
01361 
01362     if ((err == DB_NOTFOUND) && self->getReturnsNone) {
01363         err = 0;
01364         Py_INCREF(Py_None);
01365         retval = Py_None;
01366     }
01367     else if (!err) {
01368         retval = PyString_FromStringAndSize((char*)data.data, data.size);
01369         FREE_DBT(data); /* Only if retrieval was successful */
01370     }
01371 
01372     FREE_DBT(key);
01373     RETURN_IF_ERR();
01374     return retval;
01375 }
01376 
01377 
01378 static PyObject*
01379 DB_get_byteswapped(DBObject* self, PyObject* args)
01380 {
01381 #if (DBVER >= 33)
01382     int err = 0;
01383 #endif
01384     int retval = -1;
01385 
01386     if (!PyArg_ParseTuple(args,":get_byteswapped"))
01387         return NULL;
01388     CHECK_DB_NOT_CLOSED(self);
01389 
01390 #if (DBVER >= 33)
01391     MYDB_BEGIN_ALLOW_THREADS;
01392     err = self->db->get_byteswapped(self->db, &retval);
01393     MYDB_END_ALLOW_THREADS;
01394     RETURN_IF_ERR();
01395 #else
01396     MYDB_BEGIN_ALLOW_THREADS;
01397     retval = self->db->get_byteswapped(self->db);
01398     MYDB_END_ALLOW_THREADS;
01399 #endif
01400     return PyInt_FromLong(retval);
01401 }
01402 
01403 
01404 static PyObject*
01405 DB_get_type(DBObject* self, PyObject* args)
01406 {
01407     int type;
01408 
01409     if (!PyArg_ParseTuple(args,":get_type"))
01410         return NULL;
01411     CHECK_DB_NOT_CLOSED(self);
01412 
01413     MYDB_BEGIN_ALLOW_THREADS;
01414     type = _DB_get_type(self);
01415     MYDB_END_ALLOW_THREADS;
01416     if (type == -1)
01417         return NULL;
01418     return PyInt_FromLong(type);
01419 }
01420 
01421 
01422 static PyObject*
01423 DB_join(DBObject* self, PyObject* args)
01424 {
01425     int err, flags=0;
01426     int length, x;
01427     PyObject* cursorsObj;
01428     DBC** cursors;
01429     DBC*  dbc;
01430 
01431 
01432     if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
01433         return NULL;
01434 
01435     CHECK_DB_NOT_CLOSED(self);
01436 
01437     if (!PySequence_Check(cursorsObj)) {
01438         PyErr_SetString(PyExc_TypeError, "Sequence of DBCursor objects expected");
01439         return NULL;
01440     }
01441 
01442     length = PyObject_Length(cursorsObj);
01443     cursors = malloc((length+1) * sizeof(DBC*));
01444     cursors[length] = NULL;
01445     for (x=0; x<length; x++) {
01446         PyObject* item = PySequence_GetItem(cursorsObj, x);
01447         if (!DBCursorObject_Check(item)) {
01448             PyErr_SetString(PyExc_TypeError, "Sequence of DBCursor objects expected");
01449             free(cursors);
01450             return NULL;
01451         }
01452         cursors[x] = ((DBCursorObject*)item)->dbc;
01453     }
01454 
01455     MYDB_BEGIN_ALLOW_THREADS;
01456     err = self->db->join(self->db, cursors, &dbc, flags);
01457     MYDB_END_ALLOW_THREADS;
01458     free(cursors);
01459     RETURN_IF_ERR();
01460 
01461     return (PyObject*) newDBCursorObject(dbc, self);
01462 }
01463 
01464 
01465 static PyObject*
01466 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
01467 {
01468     int err, flags=0;
01469     PyObject* txnobj = NULL;
01470     PyObject* keyobj;
01471     DBT key;
01472     DB_TXN *txn = NULL;
01473     DB_KEY_RANGE range;
01474     char* kwnames[] = { "key", "txn", "flags", NULL };
01475 
01476     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
01477                                      &keyobj, &txnobj, &flags))
01478         return NULL;
01479     CHECK_DB_NOT_CLOSED(self);
01480     if (!make_dbt(keyobj, &key))   /* BTree only, don't need to allow for an int key */
01481         return NULL;
01482     if (!checkTxnObj(txnobj, &txn))
01483         return NULL;
01484 
01485     MYDB_BEGIN_ALLOW_THREADS;
01486     err = self->db->key_range(self->db, txn, &key, &range, flags);
01487     MYDB_END_ALLOW_THREADS;
01488 
01489     RETURN_IF_ERR();
01490     return Py_BuildValue("ddd", range.less, range.equal, range.greater);
01491 }
01492 
01493 
01494 static PyObject*
01495 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
01496 {
01497     int err, type = DB_UNKNOWN, flags=0, mode=0660;
01498     char* filename = NULL;
01499     char* dbname = NULL;
01500     char* kwnames[] = { "filename", "dbname", "dbtype", "flags", "mode", NULL };
01501     char* kwnames2[] = { "filename", "dbtype", "flags", "mode", NULL };
01502 
01503     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
01504                                      &filename, &dbname, &type, &flags, &mode)) {
01505         PyErr_Clear();
01506         type = DB_UNKNOWN; flags = 0; mode = 0660;
01507         filename = NULL; dbname = NULL;
01508         if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open", kwnames2,
01509                                          &filename, &type, &flags, &mode))
01510             return NULL;
01511     }
01512 
01513     if (NULL == self->db) {
01514         PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
01515                                  "Cannot call open() twice for DB object"));
01516         return NULL;
01517     }
01518 
01519     MYDB_BEGIN_ALLOW_THREADS;
01520 #if (DBVER >= 41)
01521     err = self->db->open(self->db, NULL, filename, dbname, type, flags, mode);
01522 #else
01523     err = self->db->open(self->db, filename, dbname, type, flags, mode);
01524 #endif
01525     MYDB_END_ALLOW_THREADS;
01526     if (makeDBError(err)) {
01527         self->db = NULL;
01528         return NULL;
01529     }
01530 
01531     self->flags = flags;
01532     RETURN_NONE();
01533 }
01534 
01535 
01536 static PyObject*
01537 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
01538 {
01539     int flags=0;
01540     PyObject* txnobj = NULL;
01541     int dlen = -1;
01542     int doff = -1;
01543     PyObject* keyobj, *dataobj, *retval;
01544     DBT key, data;
01545     DB_TXN *txn = NULL;
01546     char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
01547 
01548     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
01549                          &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
01550         return NULL;
01551 
01552     CHECK_DB_NOT_CLOSED(self);
01553     if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL;
01554     if (!make_dbt(dataobj, &data)) return NULL;
01555     if (!add_partial_dbt(&data, dlen, doff)) return NULL;
01556     if (!checkTxnObj(txnobj, &txn)) return NULL;
01557 
01558     if (-1 == _DB_put(self, txn, &key, &data, flags)) {
01559         FREE_DBT(key);
01560         return NULL;
01561     }
01562 
01563     if (flags & DB_APPEND)
01564         retval = PyInt_FromLong(*((db_recno_t*)key.data));
01565     else {
01566         retval = Py_None;
01567         Py_INCREF(retval);
01568     }
01569     FREE_DBT(key);
01570     return retval;
01571 }
01572 
01573 
01574 
01575 static PyObject*
01576 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
01577 {
01578     char* filename;
01579     char* database = NULL;
01580     int err, flags=0;
01581     char* kwnames[] = { "filename", "dbname", "flags", NULL};
01582 
01583     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
01584                                      &filename, &database, &flags))
01585         return NULL;
01586     CHECK_DB_NOT_CLOSED(self);
01587 
01588     MYDB_BEGIN_ALLOW_THREADS;
01589     err = self->db->remove(self->db, filename, database, flags);
01590     MYDB_END_ALLOW_THREADS;
01591     RETURN_IF_ERR();
01592     RETURN_NONE();
01593 }
01594 
01595 
01596 
01597 static PyObject*
01598 DB_rename(DBObject* self, PyObject* args)
01599 {
01600     char* filename;
01601     char* database;
01602     char* newname;
01603     int err, flags=0;
01604 
01605     if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname, &flags))
01606         return NULL;
01607     CHECK_DB_NOT_CLOSED(self);
01608 
01609     MYDB_BEGIN_ALLOW_THREADS;
01610     err = self->db->rename(self->db, filename, database, newname, flags);
01611     MYDB_END_ALLOW_THREADS;
01612     RETURN_IF_ERR();
01613     RETURN_NONE();
01614 }
01615 
01616 
01617 static PyObject*
01618 DB_set_bt_minkey(DBObject* self, PyObject* args)
01619 {
01620     int err, minkey;
01621 
01622     if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
01623         return NULL;
01624     CHECK_DB_NOT_CLOSED(self);
01625 
01626     MYDB_BEGIN_ALLOW_THREADS;
01627     err = self->db->set_bt_minkey(self->db, minkey);
01628     MYDB_END_ALLOW_THREADS;
01629     RETURN_IF_ERR();
01630     RETURN_NONE();
01631 }
01632 
01633 
01634 static PyObject*
01635 DB_set_cachesize(DBObject* self, PyObject* args)
01636 {
01637     int err;
01638     int gbytes = 0, bytes = 0, ncache = 0;
01639 
01640     if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
01641                           &gbytes,&bytes,&ncache))
01642         return NULL;
01643     CHECK_DB_NOT_CLOSED(self);
01644 
01645     MYDB_BEGIN_ALLOW_THREADS;
01646     err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
01647     MYDB_END_ALLOW_THREADS;
01648     RETURN_IF_ERR();
01649     RETURN_NONE();
01650 }
01651 
01652 
01653 static PyObject*
01654 DB_set_flags(DBObject* self, PyObject* args)
01655 {
01656     int err, flags;
01657 
01658     if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
01659         return NULL;
01660     CHECK_DB_NOT_CLOSED(self);
01661 
01662     MYDB_BEGIN_ALLOW_THREADS;
01663     err = self->db->set_flags(self->db, flags);
01664     MYDB_END_ALLOW_THREADS;
01665     RETURN_IF_ERR();
01666 
01667     self->setflags |= flags;
01668     RETURN_NONE();
01669 }
01670 
01671 
01672 static PyObject*
01673 DB_set_h_ffactor(DBObject* self, PyObject* args)
01674 {
01675     int err, ffactor;
01676 
01677     if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
01678         return NULL;
01679     CHECK_DB_NOT_CLOSED(self);
01680 
01681     MYDB_BEGIN_ALLOW_THREADS;
01682     err = self->db->set_h_ffactor(self->db, ffactor);
01683     MYDB_END_ALLOW_THREADS;
01684     RETURN_IF_ERR();
01685     RETURN_NONE();
01686 }
01687 
01688 
01689 static PyObject*
01690 DB_set_h_nelem(DBObject* self, PyObject* args)
01691 {
01692     int err, nelem;
01693 
01694     if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
01695         return NULL;
01696     CHECK_DB_NOT_CLOSED(self);
01697 
01698     MYDB_BEGIN_ALLOW_THREADS;
01699     err = self->db->set_h_nelem(self->db, nelem);
01700     MYDB_END_ALLOW_THREADS;
01701     RETURN_IF_ERR();
01702     RETURN_NONE();
01703 }
01704 
01705 
01706 static PyObject*
01707 DB_set_lorder(DBObject* self, PyObject* args)
01708 {
01709     int err, lorder;
01710 
01711     if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
01712         return NULL;
01713     CHECK_DB_NOT_CLOSED(self);
01714 
01715     MYDB_BEGIN_ALLOW_THREADS;
01716     err = self->db->set_lorder(self->db, lorder);
01717     MYDB_END_ALLOW_THREADS;
01718     RETURN_IF_ERR();
01719     RETURN_NONE();
01720 }
01721 
01722 
01723 static PyObject*
01724 DB_set_pagesize(DBObject* self, PyObject* args)
01725 {
01726     int err, pagesize;
01727 
01728     if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
01729         return NULL;
01730     CHECK_DB_NOT_CLOSED(self);
01731 
01732     MYDB_BEGIN_ALLOW_THREADS;
01733     err = self->db->set_pagesize(self->db, pagesize);
01734     MYDB_END_ALLOW_THREADS;
01735     RETURN_IF_ERR();
01736     RETURN_NONE();
01737 }
01738 
01739 
01740 static PyObject*
01741 DB_set_re_delim(DBObject* self, PyObject* args)
01742 {
01743     int err;
01744     char delim;
01745 
01746     if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
01747         PyErr_Clear();
01748         if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
01749             return NULL;
01750     }
01751 
01752     CHECK_DB_NOT_CLOSED(self);
01753 
01754     MYDB_BEGIN_ALLOW_THREADS;
01755     err = self->db->set_re_delim(self->db, delim);
01756     MYDB_END_ALLOW_THREADS;
01757     RETURN_IF_ERR();
01758     RETURN_NONE();
01759 }
01760 
01761 static PyObject*
01762 DB_set_re_len(DBObject* self, PyObject* args)
01763 {
01764     int err, len;
01765 
01766     if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
01767         return NULL;
01768     CHECK_DB_NOT_CLOSED(self);
01769 
01770     MYDB_BEGIN_ALLOW_THREADS;
01771     err = self->db->set_re_len(self->db, len);
01772     MYDB_END_ALLOW_THREADS;
01773     RETURN_IF_ERR();
01774     RETURN_NONE();
01775 }
01776 
01777 
01778 static PyObject*
01779 DB_set_re_pad(DBObject* self, PyObject* args)
01780 {
01781     int err;
01782     char pad;
01783 
01784     if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
01785         PyErr_Clear();
01786         if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
01787             return NULL;
01788     }
01789     CHECK_DB_NOT_CLOSED(self);
01790 
01791     MYDB_BEGIN_ALLOW_THREADS;
01792     err = self->db->set_re_pad(self->db, pad);
01793     MYDB_END_ALLOW_THREADS;
01794     RETURN_IF_ERR();
01795     RETURN_NONE();
01796 }
01797 
01798 
01799 static PyObject*
01800 DB_set_re_source(DBObject* self, PyObject* args)
01801 {
01802     int err;
01803     char *re_source;
01804 
01805     if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
01806         return NULL;
01807     CHECK_DB_NOT_CLOSED(self);
01808 
01809     MYDB_BEGIN_ALLOW_THREADS;
01810     err = self->db->set_re_source(self->db, re_source);
01811     MYDB_END_ALLOW_THREADS;
01812     RETURN_IF_ERR();
01813     RETURN_NONE();
01814 }
01815 
01816 
01817 #if (DBVER >= 32)
01818 static PyObject*
01819 DB_set_q_extentsize(DBObject* self, PyObject* args)
01820 {
01821     int err;
01822     int extentsize;
01823 
01824     if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
01825         return NULL;
01826     CHECK_DB_NOT_CLOSED(self);
01827 
01828     MYDB_BEGIN_ALLOW_THREADS;
01829     err = self->db->set_q_extentsize(self->db, extentsize);
01830     MYDB_END_ALLOW_THREADS;
01831     RETURN_IF_ERR();
01832     RETURN_NONE();
01833 }
01834 #endif
01835 
01836 static PyObject*
01837 DB_stat(DBObject* self, PyObject* args)
01838 {
01839     int err, flags = 0, type;
01840     void* sp;
01841     PyObject* d;
01842 
01843 
01844     if (!PyArg_ParseTuple(args, "|i:stat", &flags))
01845         return NULL;
01846     CHECK_DB_NOT_CLOSED(self);
01847 
01848     MYDB_BEGIN_ALLOW_THREADS;
01849 #if (DBVER >= 33)
01850     err = self->db->stat(self->db, &sp, flags);
01851 #else
01852     err = self->db->stat(self->db, &sp, NULL, flags);
01853 #endif
01854     MYDB_END_ALLOW_THREADS;
01855     RETURN_IF_ERR();
01856 
01857     self->haveStat = 1;
01858 
01859     /* Turn the stat structure into a dictionary */
01860     type = _DB_get_type(self);
01861     if ((type == -1) || ((d = PyDict_New()) == NULL)) {
01862         free(sp);
01863         return NULL;
01864     }
01865 
01866 #define MAKE_HASH_ENTRY(name)  _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
01867 #define MAKE_BT_ENTRY(name)    _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
01868 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
01869 
01870     switch (type) {
01871     case DB_HASH:
01872         MAKE_HASH_ENTRY(magic);
01873         MAKE_HASH_ENTRY(version);
01874         MAKE_HASH_ENTRY(nkeys);
01875         MAKE_HASH_ENTRY(ndata);
01876         MAKE_HASH_ENTRY(pagesize);
01877 #if (DBVER < 41)
01878         MAKE_HASH_ENTRY(nelem);
01879 #endif
01880         MAKE_HASH_ENTRY(ffactor);
01881         MAKE_HASH_ENTRY(buckets);
01882         MAKE_HASH_ENTRY(free);
01883         MAKE_HASH_ENTRY(bfree);
01884         MAKE_HASH_ENTRY(bigpages);
01885         MAKE_HASH_ENTRY(big_bfree);
01886         MAKE_HASH_ENTRY(overflows);
01887         MAKE_HASH_ENTRY(ovfl_free);
01888         MAKE_HASH_ENTRY(dup);
01889         MAKE_HASH_ENTRY(dup_free);
01890         break;
01891 
01892     case DB_BTREE:
01893     case DB_RECNO:
01894         MAKE_BT_ENTRY(magic);
01895         MAKE_BT_ENTRY(version);
01896         MAKE_BT_ENTRY(nkeys);
01897         MAKE_BT_ENTRY(ndata);
01898         MAKE_BT_ENTRY(pagesize);
01899         MAKE_BT_ENTRY(minkey);
01900         MAKE_BT_ENTRY(re_len);
01901         MAKE_BT_ENTRY(re_pad);
01902         MAKE_BT_ENTRY(levels);
01903         MAKE_BT_ENTRY(int_pg);
01904         MAKE_BT_ENTRY(leaf_pg);
01905         MAKE_BT_ENTRY(dup_pg);
01906         MAKE_BT_ENTRY(over_pg);
01907         MAKE_BT_ENTRY(free);
01908         MAKE_BT_ENTRY(int_pgfree);
01909         MAKE_BT_ENTRY(leaf_pgfree);
01910         MAKE_BT_ENTRY(dup_pgfree);
01911         MAKE_BT_ENTRY(over_pgfree);
01912         break;
01913 
01914     case DB_QUEUE:
01915         MAKE_QUEUE_ENTRY(magic);
01916         MAKE_QUEUE_ENTRY(version);
01917         MAKE_QUEUE_ENTRY(nkeys);
01918         MAKE_QUEUE_ENTRY(ndata);
01919         MAKE_QUEUE_ENTRY(pagesize);
01920         MAKE_QUEUE_ENTRY(pages);
01921         MAKE_QUEUE_ENTRY(re_len);
01922         MAKE_QUEUE_ENTRY(re_pad);
01923         MAKE_QUEUE_ENTRY(pgfree);
01924 #if (DBVER == 31)
01925         MAKE_QUEUE_ENTRY(start);
01926 #endif
01927         MAKE_QUEUE_ENTRY(first_recno);
01928         MAKE_QUEUE_ENTRY(cur_recno);
01929         break;
01930 
01931     default:
01932         PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
01933         Py_DECREF(d);
01934         d = NULL;
01935     }
01936 
01937 #undef MAKE_HASH_ENTRY
01938 #undef MAKE_BT_ENTRY
01939 #undef MAKE_QUEUE_ENTRY
01940 
01941     free(sp);
01942     return d;
01943 }
01944 
01945 static PyObject*
01946 DB_sync(DBObject* self, PyObject* args)
01947 {
01948     int err;
01949     int flags = 0;
01950 
01951     if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
01952         return NULL;
01953     CHECK_DB_NOT_CLOSED(self);
01954 
01955     MYDB_BEGIN_ALLOW_THREADS;
01956     err = self->db->sync(self->db, flags);
01957     MYDB_END_ALLOW_THREADS;
01958     RETURN_IF_ERR();
01959     RETURN_NONE();
01960 }
01961 
01962 
01963 #if (DBVER >= 33)
01964 static PyObject*
01965 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
01966 {
01967     int err, flags=0;
01968     u_int32_t count=0;
01969     PyObject* txnobj = NULL;
01970     DB_TXN *txn = NULL;
01971     char* kwnames[] = { "txn", "flags", NULL };
01972 
01973     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
01974                                      &txnobj, &flags))
01975         return NULL;
01976     CHECK_DB_NOT_CLOSED(self);
01977     if (!checkTxnObj(txnobj, &txn))
01978         return NULL;
01979 
01980     MYDB_BEGIN_ALLOW_THREADS;
01981     err = self->db->truncate(self->db, txn, &count, flags);
01982     MYDB_END_ALLOW_THREADS;
01983     RETURN_IF_ERR();
01984     return PyInt_FromLong(count);
01985 }
01986 #endif
01987 
01988 
01989 static PyObject*
01990 DB_upgrade(DBObject* self, PyObject* args)
01991 {
01992     int err, flags=0;
01993     char *filename;
01994 
01995     if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
01996         return NULL;
01997     CHECK_DB_NOT_CLOSED(self);
01998 
01999     MYDB_BEGIN_ALLOW_THREADS;
02000     err = self->db->upgrade(self->db, filename, flags);
02001     MYDB_END_ALLOW_THREADS;
02002     RETURN_IF_ERR();
02003     RETURN_NONE();
02004 }
02005 
02006 
02007 static PyObject*
02008 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
02009 {
02010     int err, flags=0;
02011     char* fileName;
02012     char* dbName=NULL;
02013     char* outFileName=NULL;
02014     FILE* outFile=NULL;
02015     char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
02016 
02017     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
02018                                      &fileName, &dbName, &outFileName, &flags))
02019         return NULL;
02020 
02021     CHECK_DB_NOT_CLOSED(self);
02022     if (outFileName)
02023         outFile = fopen(outFileName, "w");
02024 
02025     MYDB_BEGIN_ALLOW_THREADS;
02026     err = self->db->verify(self->db, fileName, dbName, outFile, flags);
02027     MYDB_END_ALLOW_THREADS;
02028     if (outFileName)
02029         fclose(outFile);
02030     RETURN_IF_ERR();
02031     RETURN_NONE();
02032 }
02033 
02034 
02035 static PyObject*
02036 DB_set_get_returns_none(DBObject* self, PyObject* args)
02037 {
02038     int flags=0;
02039     int oldValue;
02040 
02041     if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
02042         return NULL;
02043     CHECK_DB_NOT_CLOSED(self);
02044 
02045     oldValue = self->getReturnsNone;
02046     self->getReturnsNone = flags;
02047     return PyInt_FromLong(oldValue);
02048 }
02049 
02050 
02051 /*-------------------------------------------------------------- */
02052 /* Mapping and Dictionary-like access routines */
02053 
02054 static int DB_length(DBObject* self)
02055 {
02056     int err;
02057     long size = 0;
02058     int flags = 0;
02059     void* sp;
02060 
02061     if (self->db == NULL) {
02062         PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, "DB object has been closed"));
02063         return -1;
02064     }
02065 
02066     if (self->haveStat) {  /* Has the stat function been called recently?  If
02067                               so, we can use the cached value. */
02068         flags = DB_CACHED_COUNTS;
02069     }
02070 
02071     MYDB_BEGIN_ALLOW_THREADS;
02072 #if (DBVER >= 33)
02073     err = self->db->stat(self->db, &sp, flags);
02074 #else
02075     err = self->db->stat(self->db, &sp, NULL, flags);
02076 #endif
02077     MYDB_END_ALLOW_THREADS;
02078 
02079     if (err)
02080         return -1;
02081 
02082     self->haveStat = 1;
02083 
02084     /* All the stat structures have matching fields upto the ndata field,
02085        so we can use any of them for the type cast */
02086     size = ((DB_BTREE_STAT*)sp)->bt_ndata;
02087     free(sp);
02088     return size;
02089 }
02090 
02091 
02092 static PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
02093 {
02094     int err;
02095     PyObject* retval;
02096     DBT key;
02097     DBT data;
02098 
02099     CHECK_DB_NOT_CLOSED(self);
02100     if (!make_key_dbt(self, keyobj, &key, NULL))
02101         return NULL;
02102 
02103     CLEAR_DBT(data);
02104     if (CHECK_DBFLAG(self, DB_THREAD)) {
02105         /* Tell BerkeleyDB to malloc the return value (thread safe) */
02106         data.flags = DB_DBT_MALLOC;
02107     }
02108     MYDB_BEGIN_ALLOW_THREADS;
02109     err = self->db->get(self->db, NULL, &key, &data, 0);
02110     MYDB_END_ALLOW_THREADS;
02111     if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
02112         PyErr_SetObject(PyExc_KeyError, keyobj);
02113         retval = NULL;
02114     }
02115     else if (makeDBError(err)) {
02116         retval = NULL;
02117     }
02118     else {
02119         retval = PyString_FromStringAndSize((char*)data.data, data.size);
02120         FREE_DBT(data);
02121     }
02122 
02123     FREE_DBT(key);
02124     return retval;
02125 }
02126 
02127 
02128 static int
02129 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
02130 {
02131     DBT key, data;
02132     int retval;
02133     int flags = 0;
02134 
02135     if (self->db == NULL) {
02136         PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, "DB object has been closed"));
02137         return -1;
02138     }
02139 
02140     if (!make_key_dbt(self, keyobj, &key, NULL))
02141         return -1;
02142 
02143     if (dataobj != NULL) {
02144         if (!make_dbt(dataobj, &data))
02145             retval =  -1;
02146         else {
02147             if (self->setflags & (DB_DUP|DB_DUPSORT))
02148                 flags = DB_NOOVERWRITE;         /* dictionaries shouldn't have duplicate keys */
02149             retval = _DB_put(self, NULL, &key, &data, flags);
02150 
02151             if ((retval == -1) &&  (self->setflags & (DB_DUP|DB_DUPSORT))) {
02152                 /* try deleting any old record that matches and then PUT it again... */
02153                 _DB_delete(self, NULL, &key, 0);
02154                 PyErr_Clear();
02155                 retval = _DB_put(self, NULL, &key, &data, flags);
02156             }
02157         }
02158     }
02159     else {
02160         /* dataobj == NULL, so delete the key */
02161         retval = _DB_delete(self, NULL, &key, 0);
02162     }
02163     FREE_DBT(key);
02164     return retval;
02165 }
02166 
02167 
02168 static PyObject*
02169 DB_has_key(DBObject* self, PyObject* args)
02170 {
02171     int err;
02172     PyObject* keyobj;
02173     DBT key, data;
02174     PyObject* txnobj = NULL;
02175     DB_TXN *txn = NULL;
02176 
02177     if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj ))
02178         return NULL;
02179     CHECK_DB_NOT_CLOSED(self);
02180     if (!make_key_dbt(self, keyobj, &key, NULL))
02181         return NULL;
02182     if (!checkTxnObj(txnobj, &txn))
02183         return NULL;
02184 
02185     /* This causes ENOMEM to be returned when the db has the key because
02186        it has a record but can't allocate a buffer for the data.  This saves
02187        having to deal with data we won't be using.
02188      */
02189     CLEAR_DBT(data);
02190     data.flags = DB_DBT_USERMEM;
02191 
02192     MYDB_BEGIN_ALLOW_THREADS;
02193     err = self->db->get(self->db, NULL, &key, &data, 0);
02194     MYDB_END_ALLOW_THREADS;
02195     FREE_DBT(key);
02196     return PyInt_FromLong((err == ENOMEM) || (err == 0));
02197 }
02198 
02199 
02200 #define _KEYS_LIST      1
02201 #define _VALUES_LIST    2
02202 #define _ITEMS_LIST     3
02203 
02204 static PyObject*
02205 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
02206 {
02207     int err, dbtype;
02208     DBT key;
02209     DBT data;
02210     DBC *cursor;
02211     PyObject* list;
02212     PyObject* item = NULL;
02213 
02214     CHECK_DB_NOT_CLOSED(self);
02215     CLEAR_DBT(key);
02216     CLEAR_DBT(data);
02217 
02218     dbtype = _DB_get_type(self);
02219     if (dbtype == -1)
02220         return NULL;
02221 
02222     list = PyList_New(0);
02223     if (list == NULL) {
02224         PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
02225         return NULL;
02226     }
02227 
02228     /* get a cursor */
02229     MYDB_BEGIN_ALLOW_THREADS;
02230     err = self->db->cursor(self->db, NULL, &cursor, 0);
02231     MYDB_END_ALLOW_THREADS;
02232     RETURN_IF_ERR();
02233 
02234     if (CHECK_DBFLAG(self, DB_THREAD)) {
02235         key.flags = DB_DBT_REALLOC;
02236         data.flags = DB_DBT_REALLOC;
02237     }
02238 
02239     while (1) { /* use the cursor to traverse the DB, collecting items */
02240         MYDB_BEGIN_ALLOW_THREADS;
02241         err = cursor->c_get(cursor, &key, &data, DB_NEXT);
02242         MYDB_END_ALLOW_THREADS;
02243 
02244         if (err) {
02245             /* for any error, break out of the loop */
02246             break;
02247         }
02248 
02249         switch (type) {
02250         case _KEYS_LIST:
02251             switch(dbtype) {
02252             case DB_BTREE:
02253             case DB_HASH:
02254             default:
02255                 item = PyString_FromStringAndSize((char*)key.data, key.size);
02256                 break;
02257             case DB_RECNO:
02258             case DB_QUEUE:
02259                 item = PyInt_FromLong(*((db_recno_t*)key.data));
02260                 break;
02261             }
02262             break;
02263 
02264         case _VALUES_LIST:
02265             item = PyString_FromStringAndSize((char*)data.data, data.size);
02266             break;
02267 
02268         case _ITEMS_LIST:
02269             switch(dbtype) {
02270             case DB_BTREE:
02271             case DB_HASH:
02272             default:
02273                 item = Py_BuildValue("s#s#", key.data, key.size, data.data, data.size);
02274                 break;
02275             case DB_RECNO:
02276             case DB_QUEUE:
02277                 item = Py_BuildValue("is#", *((db_recno_t*)key.data), data.data, data.size);
02278                 break;
02279             }
02280             break;
02281         }
02282         if (item == NULL) {
02283             Py_DECREF(list);
02284             PyErr_SetString(PyExc_MemoryError, "List item creation failed");
02285             list = NULL;
02286             goto done;
02287         }
02288         PyList_Append(list, item);
02289         Py_DECREF(item);
02290     }
02291 
02292     /* DB_NOTFOUND is okay, it just means we got to the end */
02293     if (err != DB_NOTFOUND && makeDBError(err)) {
02294         Py_DECREF(list);
02295         list = NULL;
02296     }
02297 
02298  done:
02299     FREE_DBT(key);
02300     FREE_DBT(data);
02301     MYDB_BEGIN_ALLOW_THREADS;
02302     cursor->c_close(cursor);
02303     MYDB_END_ALLOW_THREADS;
02304     return list;
02305 }
02306 
02307 
02308 static PyObject*
02309 DB_keys(DBObject* self, PyObject* args)
02310 {
02311     PyObject* txnobj = NULL;
02312     DB_TXN *txn = NULL;
02313 
02314     if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
02315         return NULL;
02316     if (!checkTxnObj(txnobj, &txn))
02317         return NULL;
02318     return _DB_make_list(self, txn, _KEYS_LIST);
02319 }
02320 
02321 
02322 static PyObject*
02323 DB_items(DBObject* self, PyObject* args)
02324 {
02325     PyObject* txnobj = NULL;
02326     DB_TXN *txn = NULL;
02327 
02328     if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
02329         return NULL;
02330     if (!checkTxnObj(txnobj, &txn))
02331         return NULL;
02332     return _DB_make_list(self, txn, _ITEMS_LIST);
02333 }
02334 
02335 
02336 static PyObject*
02337 DB_values(DBObject* self, PyObject* args)
02338 {
02339     PyObject* txnobj = NULL;
02340     DB_TXN *txn = NULL;
02341 
02342     if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
02343         return NULL;
02344     if (!checkTxnObj(txnobj, &txn))
02345         return NULL;
02346     return _DB_make_list(self, txn, _VALUES_LIST);
02347 }
02348 
02349 
02350 /* --------------------------------------------------------------------- */
02351 /* DBCursor methods */
02352 
02353 
02354 static PyObject*
02355 DBC_close(DBCursorObject* self, PyObject* args)
02356 {
02357     int err = 0;
02358 
02359     if (!PyArg_ParseTuple(args, ":close"))
02360         return NULL;
02361 
02362     if (self->dbc != NULL) {
02363         MYDB_BEGIN_ALLOW_THREADS;
02364         err = self->dbc->c_close(self->dbc);
02365         self->dbc = NULL;
02366         MYDB_END_ALLOW_THREADS;
02367     }
02368     RETURN_IF_ERR();
02369     RETURN_NONE();
02370 }
02371 
02372 
02373 static PyObject*
02374 DBC_count(DBCursorObject* self, PyObject* args)
02375 {
02376     int err = 0;
02377     db_recno_t count;
02378     int flags = 0;
02379 
02380     if (!PyArg_ParseTuple(args, "|i:count", &flags))
02381         return NULL;
02382 
02383     CHECK_CURSOR_NOT_CLOSED(self);
02384 
02385     MYDB_BEGIN_ALLOW_THREADS;
02386     err = self->dbc->c_count(self->dbc, &count, flags);
02387     MYDB_END_ALLOW_THREADS;
02388     RETURN_IF_ERR();
02389 
02390     return PyInt_FromLong(count);
02391 }
02392 
02393 
02394 static PyObject*
02395 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
02396 {
02397     return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
02398 }
02399 
02400 
02401 static PyObject*
02402 DBC_delete(DBCursorObject* self, PyObject* args)
02403 {
02404     int err, flags=0;
02405 
02406     if (!PyArg_ParseTuple(args, "|i:delete", &flags))
02407         return NULL;
02408 
02409     CHECK_CURSOR_NOT_CLOSED(self);
02410 
02411     MYDB_BEGIN_ALLOW_THREADS;
02412     err = self->dbc->c_del(self->dbc, flags);
02413     MYDB_END_ALLOW_THREADS;
02414     RETURN_IF_ERR();
02415 
02416     self->mydb->haveStat = 0;
02417     RETURN_NONE();
02418 }
02419 
02420 
02421 static PyObject*
02422 DBC_dup(DBCursorObject* self, PyObject* args)
02423 {
02424     int err, flags =0;
02425     DBC* dbc = NULL;
02426 
02427     if (!PyArg_ParseTuple(args, "|i:dup", &flags))
02428         return NULL;
02429 
02430     CHECK_CURSOR_NOT_CLOSED(self);
02431 
02432     MYDB_BEGIN_ALLOW_THREADS;
02433     err = self->dbc->c_dup(self->dbc, &dbc, flags);
02434     MYDB_END_ALLOW_THREADS;
02435     RETURN_IF_ERR();
02436 
02437     return (PyObject*) newDBCursorObject(dbc, self->mydb);
02438 }
02439 
02440 static PyObject*
02441 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
02442 {
02443     return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
02444 }
02445 
02446 
02447 static PyObject*
02448 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
02449 {
02450     int err, flags=0;
02451     PyObject* keyobj = NULL;
02452     PyObject* dataobj = NULL;
02453     PyObject* retval = NULL;
02454     int dlen = -1;
02455     int doff = -1;
02456     DBT key, data;
02457     char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
02458 
02459     CLEAR_DBT(key);
02460     CLEAR_DBT(data);
02461     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
02462                                      &flags, &dlen, &doff)) {
02463         PyErr_Clear();
02464         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get", &kwnames[1], 
02465                                          &keyobj, &flags, &dlen, &doff)) {
02466             PyErr_Clear();
02467             if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get", kwnames,
02468                                   &keyobj, &dataobj, &flags, &dlen, &doff)) {
02469                 return NULL;
02470             }
02471         }
02472     }
02473 
02474     CHECK_CURSOR_NOT_CLOSED(self);
02475 
02476     if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
02477         return NULL;
02478     if (dataobj && !make_dbt(dataobj, &data))
02479         return NULL;
02480     if (!add_partial_dbt(&data, dlen, doff))
02481         return NULL;
02482 
02483     if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
02484         data.flags = DB_DBT_MALLOC;
02485         key.flags = DB_DBT_MALLOC;
02486     }
02487 
02488     MYDB_BEGIN_ALLOW_THREADS;
02489     err = self->dbc->c_get(self->dbc, &key, &data, flags);
02490     MYDB_END_ALLOW_THREADS;
02491 
02492 
02493     if ((err == DB_NOTFOUND) && self->mydb->getReturnsNone) {
02494         Py_INCREF(Py_None);
02495         retval = Py_None;
02496     }
02497     else if (makeDBError(err)) {
02498         retval = NULL;
02499     }
02500     else {
02501         switch (_DB_get_type(self->mydb)) {
02502         case -1:
02503             retval = NULL;
02504             break;
02505         case DB_BTREE:
02506         case DB_HASH:
02507         default:
02508             retval = Py_BuildValue("s#s#", key.data, key.size,
02509                                    data.data, data.size);
02510             break;
02511         case DB_RECNO:
02512         case DB_QUEUE:
02513             retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
02514                                    data.data, data.size);
02515             break;
02516         }
02517         FREE_DBT(key);
02518         FREE_DBT(data);
02519     }
02520     return retval;
02521 }
02522 
02523 
02524 static PyObject*
02525 DBC_get_recno(DBCursorObject* self, PyObject* args)
02526 {
02527     int err;
02528     db_recno_t recno;
02529     DBT key;
02530     DBT data;
02531 
02532     if (!PyArg_ParseTuple(args, ":get_recno"))
02533         return NULL;
02534 
02535     CHECK_CURSOR_NOT_CLOSED(self);
02536 
02537     CLEAR_DBT(key);
02538     CLEAR_DBT(data);
02539     if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
02540         /* Tell BerkeleyDB to malloc the return value (thread safe) */
02541         data.flags = DB_DBT_MALLOC;
02542         key.flags = DB_DBT_MALLOC;
02543     }
02544 
02545     MYDB_BEGIN_ALLOW_THREADS;
02546     err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
02547     MYDB_END_ALLOW_THREADS;
02548     RETURN_IF_ERR();
02549 
02550     recno = *((db_recno_t*)data.data);
02551     FREE_DBT(key);
02552     FREE_DBT(data);
02553     return PyInt_FromLong(recno);
02554 }
02555 
02556 
02557 static PyObject*
02558 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
02559 {
02560     return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
02561 }
02562 
02563 
02564 static PyObject*
02565 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
02566 {
02567     return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
02568 }
02569 
02570 
02571 static PyObject*
02572 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
02573 {
02574     return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
02575 }
02576 
02577 
02578 static PyObject*
02579 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
02580 {
02581     int err, flags = 0;
02582     PyObject* keyobj, *dataobj;
02583     DBT key, data;
02584     char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
02585     int dlen = -1;
02586     int doff = -1;
02587 
02588     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
02589                                      &keyobj, &dataobj, &flags, &dlen, &doff))
02590         return NULL;
02591 
02592     CHECK_CURSOR_NOT_CLOSED(self);
02593 
02594     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
02595         return NULL;
02596     if (!make_dbt(dataobj, &data))
02597         return NULL;
02598     if (!add_partial_dbt(&data, dlen, doff)) return NULL;
02599 
02600     MYDB_BEGIN_ALLOW_THREADS;
02601     err = self->dbc->c_put(self->dbc, &key, &data, flags);
02602     MYDB_END_ALLOW_THREADS;
02603     FREE_DBT(key);
02604     RETURN_IF_ERR();
02605     self->mydb->haveStat = 0;
02606     RETURN_NONE();
02607 }
02608 
02609 
02610 static PyObject*
02611 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
02612 {
02613     int err, flags = 0;
02614     DBT key, data;
02615     PyObject* retval, *keyobj;
02616     char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
02617     int dlen = -1;
02618     int doff = -1;
02619 
02620     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
02621                                      &keyobj, &flags, &dlen, &doff))
02622         return NULL;
02623 
02624     CHECK_CURSOR_NOT_CLOSED(self);
02625 
02626     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
02627         return NULL;
02628 
02629     CLEAR_DBT(data);
02630     if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
02631         /* Tell BerkeleyDB to malloc the return value (thread safe) */
02632         data.flags = DB_DBT_MALLOC;
02633     }
02634     if (!add_partial_dbt(&data, dlen, doff))
02635         return NULL;
02636 
02637     MYDB_BEGIN_ALLOW_THREADS;
02638     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
02639     MYDB_END_ALLOW_THREADS;
02640     if (makeDBError(err)) {
02641         retval = NULL;
02642     }
02643     else {
02644         switch (_DB_get_type(self->mydb)) {
02645         case -1:
02646             retval = NULL;
02647             break;
02648         case DB_BTREE:
02649         case DB_HASH:
02650         default:
02651             retval = Py_BuildValue("s#s#", key.data, key.size,
02652                                    data.data, data.size);
02653             break;
02654         case DB_RECNO:
02655         case DB_QUEUE:
02656             retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
02657                                    data.data, data.size);
02658             break;
02659         }
02660         FREE_DBT(key);
02661         FREE_DBT(data);
02662     }
02663 
02664     return retval;
02665 }
02666 
02667 
02668 static PyObject*
02669 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
02670 {
02671     int err, flags = 0;
02672     DBT key, data;
02673     PyObject* retval, *keyobj;
02674     char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
02675     int dlen = -1;
02676     int doff = -1;
02677 
02678     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
02679                                      &keyobj, &flags, &dlen, &doff))
02680         return NULL;
02681 
02682     CHECK_CURSOR_NOT_CLOSED(self);
02683 
02684     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
02685         return NULL;
02686 
02687     CLEAR_DBT(data);
02688     if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
02689         /* Tell BerkeleyDB to malloc the return value (thread safe) */
02690         data.flags = DB_DBT_MALLOC;
02691         key.flags = DB_DBT_MALLOC;
02692     }
02693     if (!add_partial_dbt(&data, dlen, doff))
02694         return NULL;
02695     MYDB_BEGIN_ALLOW_THREADS;
02696     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
02697     MYDB_END_ALLOW_THREADS;
02698     if (makeDBError(err)) {
02699         retval = NULL;
02700     }
02701     else {
02702         switch (_DB_get_type(self->mydb)) {
02703         case -1:
02704             retval = NULL;
02705             break;
02706         case DB_BTREE:
02707         case DB_HASH:
02708         default:
02709             retval = Py_BuildValue("s#s#", key.data, key.size,
02710                                    data.data, data.size);
02711             break;
02712         case DB_RECNO:
02713         case DB_QUEUE:
02714             retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
02715                                    data.data, data.size);
02716             break;
02717         }
02718         FREE_DBT(key);
02719         FREE_DBT(data);
02720     }
02721 
02722     return retval;
02723 }
02724 
02725 
02726 static PyObject*
02727 DBC_get_both(DBCursorObject* self, PyObject* args)
02728 {
02729     int err, flags=0;
02730     DBT key, data;
02731     PyObject* retval, *keyobj, *dataobj;
02732 
02733     if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
02734         return NULL;
02735 
02736     CHECK_CURSOR_NOT_CLOSED(self);
02737 
02738     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
02739         return NULL;
02740     if (!make_dbt(dataobj, &data))
02741         return NULL;
02742 
02743     MYDB_BEGIN_ALLOW_THREADS;
02744     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
02745     MYDB_END_ALLOW_THREADS;
02746     if (makeDBError(err)) {
02747         retval = NULL;
02748     }
02749     else {
02750         switch (_DB_get_type(self->mydb)) {
02751         case -1:
02752             retval = NULL;
02753             break;
02754         case DB_BTREE:
02755         case DB_HASH:
02756         default:
02757             retval = Py_BuildValue("s#s#", key.data, key.size,
02758                                    data.data, data.size);
02759             break;
02760         case DB_RECNO:
02761         case DB_QUEUE:
02762             retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
02763                                    data.data, data.size);
02764             break;
02765         }
02766     }
02767 
02768     FREE_DBT(key);
02769     return retval;
02770 }
02771 
02772 
02773 static PyObject*
02774 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
02775 {
02776     int err, irecno, flags=0;
02777     db_recno_t recno;
02778     DBT key, data;
02779     PyObject* retval;
02780     int dlen = -1;
02781     int doff = -1;
02782     char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
02783 
02784     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
02785                                      &irecno, &flags, &dlen, &doff))
02786       return NULL;
02787 
02788     CHECK_CURSOR_NOT_CLOSED(self);
02789 
02790     CLEAR_DBT(key);
02791     recno = (db_recno_t) irecno;
02792     /* use allocated space so DB will be able to realloc room for the real key */
02793     key.data = malloc(sizeof(db_recno_t));
02794     if (key.data == NULL) {
02795         PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
02796         return NULL;
02797     }
02798     key.size = sizeof(db_recno_t);
02799     key.ulen = key.size;
02800     memcpy(key.data, &recno, sizeof(db_recno_t));
02801     key.flags = DB_DBT_REALLOC;
02802 
02803     CLEAR_DBT(data);
02804     if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
02805         /* Tell BerkeleyDB to malloc the return value (thread safe) */
02806         data.flags = DB_DBT_MALLOC;
02807     }
02808     if (!add_partial_dbt(&data, dlen, doff))
02809         return NULL;
02810 
02811     MYDB_BEGIN_ALLOW_THREADS;
02812     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
02813     MYDB_END_ALLOW_THREADS;
02814     if (makeDBError(err)) {
02815         retval = NULL;
02816     }
02817     else {  /* Can only be used for BTrees, so no need to return int key */
02818         retval = Py_BuildValue("s#s#", key.data, key.size,
02819                                data.data, data.size);
02820         FREE_DBT(key);
02821         FREE_DBT(data);
02822     }
02823 
02824     return retval;
02825 }
02826 
02827 
02828 static PyObject*
02829 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
02830 {
02831     return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
02832 }
02833 
02834 
02835 static PyObject*
02836 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
02837 {
02838     return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
02839 }
02840 
02841 
02842 static PyObject*
02843 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
02844 {
02845     return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
02846 }
02847 
02848 
02849 static PyObject*
02850 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
02851 {
02852     return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
02853 }
02854 
02855 
02856 static PyObject*
02857 DBC_join_item(DBCursorObject* self, PyObject* args)
02858 {
02859     int err;
02860     DBT key, data;
02861     PyObject* retval;
02862 
02863     if (!PyArg_ParseTuple(args, ":join_item"))
02864         return NULL;
02865 
02866     CHECK_CURSOR_NOT_CLOSED(self);
02867 
02868     CLEAR_DBT(key);
02869     CLEAR_DBT(data);
02870     if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
02871         /* Tell BerkeleyDB to malloc the return value (thread safe) */
02872         key.flags = DB_DBT_MALLOC;
02873     }
02874 
02875     MYDB_BEGIN_ALLOW_THREADS;
02876     err = self->dbc->c_get(self->dbc, &key, &data, DB_JOIN_ITEM);
02877     MYDB_END_ALLOW_THREADS;
02878     if (makeDBError(err)) {
02879         retval = NULL;
02880     }
02881     else {
02882         retval = Py_BuildValue("s#s#", key.data, key.size);
02883         FREE_DBT(key);
02884     }
02885 
02886     return retval;
02887 }
02888 
02889 
02890 
02891 /* --------------------------------------------------------------------- */
02892 /* DBEnv methods */
02893 
02894 
02895 static PyObject*
02896 DBEnv_close(DBEnvObject* self, PyObject* args)
02897 {
02898     int err, flags = 0;
02899 
02900     if (!PyArg_ParseTuple(args, "|i:close", &flags))
02901         return NULL;
02902     if (!self->closed) {      /* Don't close more than once */
02903         MYDB_BEGIN_ALLOW_THREADS;
02904         err = self->db_env->close(self->db_env, flags);
02905         MYDB_END_ALLOW_THREADS;
02906         /* after calling DBEnv->close, regardless of error, this DBEnv
02907          * may not be accessed again (BerkeleyDB docs). */
02908         self->closed = 1;
02909         self->db_env = NULL;
02910         RETURN_IF_ERR();
02911     }
02912     RETURN_NONE();
02913 }
02914 
02915 
02916 static PyObject*
02917 DBEnv_open(DBEnvObject* self, PyObject* args)
02918 {
02919     int err, flags=0, mode=0660;
02920     char *db_home;
02921 
02922     if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
02923         return NULL;
02924 
02925     CHECK_ENV_NOT_CLOSED(self);
02926 
02927     MYDB_BEGIN_ALLOW_THREADS;
02928     err = self->db_env->open(self->db_env, db_home, flags, mode);
02929     MYDB_END_ALLOW_THREADS;
02930     RETURN_IF_ERR();
02931     self->closed = 0;
02932     self->flags = flags;
02933     RETURN_NONE();
02934 }
02935 
02936 
02937 static PyObject*
02938 DBEnv_remove(DBEnvObject* self, PyObject* args)
02939 {
02940     int err, flags=0;
02941     char *db_home;
02942 
02943     if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
02944         return NULL;
02945     CHECK_ENV_NOT_CLOSED(self);
02946     MYDB_BEGIN_ALLOW_THREADS;
02947     err = self->db_env->remove(self->db_env, db_home, flags);
02948     MYDB_END_ALLOW_THREADS;
02949     RETURN_IF_ERR();
02950     RETURN_NONE();
02951 }
02952 
02953 
02954 static PyObject*
02955 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
02956 {
02957     int err, gbytes=0, bytes=0, ncache=0;
02958 
02959     if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
02960                           &gbytes, &bytes, &ncache))
02961         return NULL;
02962     CHECK_ENV_NOT_CLOSED(self);
02963 
02964     MYDB_BEGIN_ALLOW_THREADS;
02965     err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
02966     MYDB_END_ALLOW_THREADS;
02967     RETURN_IF_ERR();
02968     RETURN_NONE();
02969 }
02970 
02971 
02972 #if (DBVER >= 32)
02973 static PyObject*
02974 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
02975 {
02976     int err, flags=0, onoff=0;
02977 
02978     if (!PyArg_ParseTuple(args, "ii:set_flags",
02979                           &flags, &onoff))
02980         return NULL;
02981     CHECK_ENV_NOT_CLOSED(self);
02982 
02983     MYDB_BEGIN_ALLOW_THREADS;
02984     err = self->db_env->set_flags(self->db_env, flags, onoff);
02985     MYDB_END_ALLOW_THREADS;
02986     RETURN_IF_ERR();
02987     RETURN_NONE();
02988 }
02989 #endif
02990 
02991 
02992 static PyObject*
02993 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
02994 {
02995     int err;
02996     char *dir;
02997 
02998     if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
02999         return NULL;
03000     CHECK_ENV_NOT_CLOSED(self);
03001 
03002     MYDB_BEGIN_ALLOW_THREADS;
03003     err = self->db_env->set_data_dir(self->db_env, dir);
03004     MYDB_END_ALLOW_THREADS;
03005     RETURN_IF_ERR();
03006     RETURN_NONE();
03007 }
03008 
03009 
03010 static PyObject*
03011 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
03012 {
03013     int err, lg_bsize;
03014 
03015     if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
03016         return NULL;
03017     CHECK_ENV_NOT_CLOSED(self);
03018 
03019     MYDB_BEGIN_ALLOW_THREADS;
03020     err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
03021     MYDB_END_ALLOW_THREADS;
03022     RETURN_IF_ERR();
03023     RETURN_NONE();
03024 }
03025 
03026 
03027 static PyObject*
03028 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
03029 {
03030     int err;
03031     char *dir;
03032 
03033     if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
03034         return NULL;
03035     CHECK_ENV_NOT_CLOSED(self);
03036 
03037     MYDB_BEGIN_ALLOW_THREADS;
03038     err = self->db_env->set_lg_dir(self->db_env, dir);
03039     MYDB_END_ALLOW_THREADS;
03040     RETURN_IF_ERR();
03041     RETURN_NONE();
03042 }
03043 
03044 static PyObject*
03045 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
03046 {
03047     int err, lg_max;
03048 
03049     if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
03050         return NULL;
03051     CHECK_ENV_NOT_CLOSED(self);
03052 
03053     MYDB_BEGIN_ALLOW_THREADS;
03054     err = self->db_env->set_lg_max(self->db_env, lg_max);
03055     MYDB_END_ALLOW_THREADS;
03056     RETURN_IF_ERR();
03057     RETURN_NONE();
03058 }
03059 
03060 
03061 static PyObject*
03062 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
03063 {
03064     int err, lk_detect;
03065 
03066     if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
03067         return NULL;
03068     CHECK_ENV_NOT_CLOSED(self);
03069 
03070     MYDB_BEGIN_ALLOW_THREADS;
03071     err = self->db_env->set_lk_detect(self->db_env, lk_detect);
03072     MYDB_END_ALLOW_THREADS;
03073     RETURN_IF_ERR();
03074     RETURN_NONE();
03075 }
03076 
03077 
03078 static PyObject*
03079 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
03080 {
03081     int err, max;
03082 
03083     if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
03084         return NULL;
03085     CHECK_ENV_NOT_CLOSED(self);
03086 
03087     MYDB_BEGIN_ALLOW_THREADS;
03088     err = self->db_env->set_lk_max(self->db_env, max);
03089     MYDB_END_ALLOW_THREADS;
03090     RETURN_IF_ERR();
03091     RETURN_NONE();
03092 }
03093 
03094 
03095 #if (DBVER >= 32)
03096 
03097 static PyObject*
03098 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
03099 {
03100     int err, max;
03101 
03102     if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
03103         return NULL;
03104     CHECK_ENV_NOT_CLOSED(self);
03105 
03106     MYDB_BEGIN_ALLOW_THREADS;
03107     err = self->db_env->set_lk_max_locks(self->db_env, max);
03108     MYDB_END_ALLOW_THREADS;
03109     RETURN_IF_ERR();
03110     RETURN_NONE();
03111 }
03112 
03113 
03114 static PyObject*
03115 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
03116 {
03117     int err, max;
03118 
03119     if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
03120         return NULL;
03121     CHECK_ENV_NOT_CLOSED(self);
03122 
03123     MYDB_BEGIN_ALLOW_THREADS;
03124     err = self->db_env->set_lk_max_lockers(self->db_env, max);
03125     MYDB_END_ALLOW_THREADS;
03126     RETURN_IF_ERR();
03127     RETURN_NONE();
03128 }
03129 
03130 
03131 static PyObject*
03132 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
03133 {
03134     int err, max;
03135 
03136     if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
03137         return NULL;
03138     CHECK_ENV_NOT_CLOSED(self);
03139 
03140     MYDB_BEGIN_ALLOW_THREADS;
03141     err = self->db_env->set_lk_max_objects(self->db_env, max);
03142     MYDB_END_ALLOW_THREADS;
03143     RETURN_IF_ERR();
03144     RETURN_NONE();
03145 }
03146 
03147 #endif
03148 
03149 
03150 static PyObject*
03151 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
03152 {
03153     int err, mp_mmapsize;
03154 
03155     if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
03156         return NULL;
03157     CHECK_ENV_NOT_CLOSED(self);
03158 
03159     MYDB_BEGIN_ALLOW_THREADS;
03160     err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
03161     MYDB_END_ALLOW_THREADS;
03162     RETURN_IF_ERR();
03163     RETURN_NONE();
03164 }
03165 
03166 
03167 static PyObject*
03168 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
03169 {
03170     int err;
03171     char *dir;
03172 
03173     if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
03174         return NULL;
03175     CHECK_ENV_NOT_CLOSED(self);
03176 
03177     MYDB_BEGIN_ALLOW_THREADS;
03178     err = self->db_env->set_tmp_dir(self->db_env, dir);
03179     MYDB_END_ALLOW_THREADS;
03180     RETURN_IF_ERR();
03181     RETURN_NONE();
03182 }
03183 
03184 
03185 static PyObject*
03186 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
03187 {
03188     int flags = 0;
03189     PyObject* txnobj = NULL;
03190     DB_TXN *txn = NULL;
03191     char* kwnames[] = { "parent", "flags", NULL };
03192 
03193     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
03194                                      &txnobj, &flags))
03195         return NULL;
03196 
03197     if (!checkTxnObj(txnobj, &txn))
03198         return NULL;
03199     CHECK_ENV_NOT_CLOSED(self);
03200 
03201     return (PyObject*)newDBTxnObject(self, txn, flags);
03202 }
03203 
03204 
03205 static PyObject*
03206 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
03207 {
03208     int err, kbyte=0, min=0, flags=0;
03209 
03210     if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
03211         return NULL;
03212     CHECK_ENV_NOT_CLOSED(self);
03213 
03214     MYDB_BEGIN_ALLOW_THREADS;
03215 #if (DBVER >= 40)
03216     err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
03217 #else
03218     err = txn_checkpoint(self->db_env, kbyte, min, flags);
03219 #endif
03220     MYDB_END_ALLOW_THREADS;
03221     RETURN_IF_ERR();
03222     RETURN_NONE();
03223 }
03224 
03225 
03226 static PyObject*
03227 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
03228 {
03229     int err, max;
03230 
03231     if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
03232         return NULL;
03233     CHECK_ENV_NOT_CLOSED(self);
03234 
03235     MYDB_BEGIN_ALLOW_THREADS;
03236     err = self->db_env->set_tx_max(self->db_env, max);
03237     MYDB_END_ALLOW_THREADS;
03238     RETURN_IF_ERR();
03239     RETURN_NONE();
03240 }
03241 
03242 
03243 static PyObject*
03244 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
03245 {
03246     int err, atype, flags=0;
03247     int aborted = 0;
03248 
03249     if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
03250         return NULL;
03251     CHECK_ENV_NOT_CLOSED(self);
03252 
03253     MYDB_BEGIN_ALLOW_THREADS;
03254 #if (DBVER >= 40)
03255     err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
03256 #else
03257     err = lock_detect(self->db_env, flags, atype, &aborted);
03258 #endif
03259     MYDB_END_ALLOW_THREADS;
03260     RETURN_IF_ERR();
03261     return PyInt_FromLong(aborted);
03262 }
03263 
03264 
03265 static PyObject*
03266 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
03267 {
03268     int flags=0;
03269     int locker, lock_mode;
03270     DBT obj;
03271     PyObject* objobj;
03272 
03273     if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
03274         return NULL;
03275 
03276 
03277     if (!make_dbt(objobj, &obj))
03278         return NULL;
03279 
03280     return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
03281 }
03282 
03283 
03284 static PyObject*
03285 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
03286 {
03287     int err;
03288     u_int32_t theID;
03289 
03290     if (!PyArg_ParseTuple(args, ":lock_id"))
03291         return NULL;
03292 
03293     CHECK_ENV_NOT_CLOSED(self);
03294     MYDB_BEGIN_ALLOW_THREADS;
03295 #if (DBVER >= 40)
03296     err = self->db_env->lock_id(self->db_env, &theID);
03297 #else
03298     err = lock_id(self->db_env, &theID);
03299 #endif
03300     MYDB_END_ALLOW_THREADS;
03301     RETURN_IF_ERR();
03302 
03303     return PyInt_FromLong((long)theID);
03304 }
03305 
03306 
03307 static PyObject*
03308 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
03309 {
03310     int err;
03311     DBLockObject* dblockobj;
03312 
03313     if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
03314         return NULL;
03315 
03316     CHECK_ENV_NOT_CLOSED(self);
03317     MYDB_BEGIN_ALLOW_THREADS;
03318 #if (DBVER >= 40)
03319     err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
03320 #else
03321     err = lock_put(self->db_env, &dblockobj->lock);
03322 #endif
03323     MYDB_END_ALLOW_THREADS;
03324     RETURN_IF_ERR();
03325     RETURN_NONE();
03326 }
03327 
03328 
03329 static PyObject*
03330 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
03331 {
03332     int err;
03333     DB_LOCK_STAT* sp;
03334     PyObject* d = NULL;
03335     u_int32_t flags = 0;
03336 
03337     if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
03338         return NULL;
03339     CHECK_ENV_NOT_CLOSED(self);
03340 
03341     MYDB_BEGIN_ALLOW_THREADS;
03342 #if (DBVER >= 40)
03343     err = self->db_env->lock_stat(self->db_env, &sp, flags);
03344 #else
03345 #if (DBVER >= 33)
03346     err = lock_stat(self->db_env, &sp);
03347 #else
03348     err = lock_stat(self->db_env, &sp, NULL);
03349 #endif
03350 #endif
03351     MYDB_END_ALLOW_THREADS;
03352     RETURN_IF_ERR();
03353 
03354     /* Turn the stat structure into a dictionary */
03355     d = PyDict_New();
03356     if (d == NULL) {
03357         free(sp);
03358         return NULL;
03359     }
03360 
03361 #define MAKE_ENTRY(name)  _addIntToDict(d, #name, sp->st_##name)
03362 
03363 #if (DBVER < 41)
03364     MAKE_ENTRY(lastid);
03365 #endif
03366     MAKE_ENTRY(nmodes);
03367 #if (DBVER >= 32)
03368     MAKE_ENTRY(maxlocks);
03369     MAKE_ENTRY(maxlockers);
03370     MAKE_ENTRY(maxobjects);
03371     MAKE_ENTRY(nlocks);
03372     MAKE_ENTRY(maxnlocks);
03373 #endif
03374     MAKE_ENTRY(nlockers);
03375     MAKE_ENTRY(maxnlockers);
03376 #if (DBVER >= 32)
03377     MAKE_ENTRY(nobjects);
03378     MAKE_ENTRY(maxnobjects);
03379 #endif
03380     MAKE_ENTRY(nrequests);
03381     MAKE_ENTRY(nreleases);
03382     MAKE_ENTRY(nnowaits);
03383     MAKE_ENTRY(nconflicts);
03384     MAKE_ENTRY(ndeadlocks);
03385     MAKE_ENTRY(regsize);
03386     MAKE_ENTRY(region_wait);
03387     MAKE_ENTRY(region_nowait);
03388 
03389 #undef MAKE_ENTRY
03390     free(sp);
03391     return d;
03392 }
03393 
03394 
03395 static PyObject*
03396 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
03397 {
03398     int flags=0;
03399     int err;
03400     char **log_list_start, **log_list;
03401     PyObject* list;
03402     PyObject* item = NULL;
03403 
03404     if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
03405         return NULL;
03406 
03407     CHECK_ENV_NOT_CLOSED(self);
03408     MYDB_BEGIN_ALLOW_THREADS;
03409 #if (DBVER >= 40)
03410     err = self->db_env->log_archive(self->db_env, &log_list, flags);
03411 #elif (DBVER == 33)
03412     err = log_archive(self->db_env, &log_list, flags);
03413 #else
03414     err = log_archive(self->db_env, &log_list, flags, NULL);
03415 #endif
03416     MYDB_END_ALLOW_THREADS;
03417     RETURN_IF_ERR();
03418 
03419     list = PyList_New(0);
03420     if (list == NULL) {
03421         PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
03422         return NULL;
03423     }
03424 
03425     if (log_list) {
03426         for (log_list_start = log_list; *log_list != NULL; ++log_list) {
03427             item = PyString_FromString (*log_list);
03428             if (item == NULL) {
03429                 Py_DECREF(list);
03430                 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
03431                 list = NULL;
03432                 break;
03433             }
03434             PyList_Append(list, item);
03435             Py_DECREF(item);
03436         }
03437         free(log_list_start);
03438     }
03439     return list;
03440 }
03441 
03442 
03443 static PyObject*
03444 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
03445 {
03446     int err;
03447     DB_TXN_STAT* sp;
03448     PyObject* d = NULL;
03449     u_int32_t flags=0;
03450 
03451     if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
03452         return NULL;
03453     CHECK_ENV_NOT_CLOSED(self);
03454 
03455     MYDB_BEGIN_ALLOW_THREADS;
03456 #if (DBVER >= 40)
03457     err = self->db_env->txn_stat(self->db_env, &sp, flags);
03458 #elif (DBVER == 33)
03459     err = txn_stat(self->db_env, &sp);
03460 #else
03461     err = txn_stat(self->db_env, &sp, NULL);
03462 #endif
03463     MYDB_END_ALLOW_THREADS;
03464     RETURN_IF_ERR();
03465 
03466     /* Turn the stat structure into a dictionary */
03467     d = PyDict_New();
03468     if (d == NULL) {
03469         free(sp);
03470         return NULL;
03471     }
03472 
03473 #define MAKE_ENTRY(name)  _addIntToDict(d, #name, sp->st_##name)
03474 
03475     MAKE_ENTRY(time_ckp);
03476     MAKE_ENTRY(last_txnid);
03477     MAKE_ENTRY(maxtxns);
03478     MAKE_ENTRY(nactive);
03479     MAKE_ENTRY(maxnactive);
03480     MAKE_ENTRY(nbegins);
03481     MAKE_ENTRY(naborts);
03482     MAKE_ENTRY(ncommits);
03483     MAKE_ENTRY(regsize);
03484     MAKE_ENTRY(region_wait);
03485     MAKE_ENTRY(region_nowait);
03486 
03487 #undef MAKE_ENTRY
03488     free(sp);
03489     return d;
03490 }
03491 
03492 
03493 static PyObject*
03494 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
03495 {
03496     int flags=0;
03497     int oldValue;
03498 
03499     if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
03500         return NULL;
03501     CHECK_ENV_NOT_CLOSED(self);
03502 
03503     oldValue = self->getReturnsNone;
03504     self->getReturnsNone = flags;
03505     return PyInt_FromLong(oldValue);
03506 }
03507 
03508 
03509 /* --------------------------------------------------------------------- */
03510 /* DBTxn methods */
03511 
03512 
03513 static PyObject*
03514 DBTxn_commit(DBTxnObject* self, PyObject* args)
03515 {
03516     int flags=0, err;
03517 
03518     if (!PyArg_ParseTuple(args, "|i:commit", &flags))
03519         return NULL;
03520 
03521     MYDB_BEGIN_ALLOW_THREADS;
03522 #if (DBVER >= 40)
03523     err = self->txn->commit(self->txn, flags);
03524 #else
03525     err = txn_commit(self->txn, flags);
03526 #endif
03527     MYDB_END_ALLOW_THREADS;
03528     RETURN_IF_ERR();
03529     RETURN_NONE();
03530 }
03531 
03532 static PyObject*
03533 DBTxn_prepare(DBTxnObject* self, PyObject* args)
03534 {
03535 #if (DBVER >= 33)
03536     int err;
03537     char* gid=NULL;
03538     int   gid_size=0;
03539 
03540     if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
03541         return NULL;
03542 
03543     if (gid_size != DB_XIDDATASIZE) {
03544         PyErr_SetString(PyExc_TypeError,
03545                         "gid must be DB_XIDDATASIZE bytes long");
03546         return NULL;
03547     }
03548 
03549     MYDB_BEGIN_ALLOW_THREADS;
03550 #if (DBVER >= 40)
03551     err = self->txn->prepare(self->txn, (u_int8_t*)gid);
03552 #else
03553     err = txn_prepare(self->txn, (u_int8_t*)gid);
03554 #endif
03555     MYDB_END_ALLOW_THREADS;
03556     RETURN_IF_ERR();
03557     RETURN_NONE();
03558 #else
03559     int err;
03560 
03561     if (!PyArg_ParseTuple(args, ":prepare"))
03562         return NULL;
03563 
03564     MYDB_BEGIN_ALLOW_THREADS;
03565     err = txn_prepare(self->txn);
03566     MYDB_END_ALLOW_THREADS;
03567     RETURN_IF_ERR();
03568     RETURN_NONE();
03569 #endif
03570 }
03571 
03572 
03573 static PyObject*
03574 DBTxn_abort(DBTxnObject* self, PyObject* args)
03575 {
03576     int err;
03577 
03578     if (!PyArg_ParseTuple(args, ":abort"))
03579         return NULL;
03580 
03581     MYDB_BEGIN_ALLOW_THREADS;
03582 #if (DBVER >= 40)
03583     err = self->txn->abort(self->txn);
03584 #else
03585     err = txn_abort(self->txn);
03586 #endif
03587     MYDB_END_ALLOW_THREADS;
03588     RETURN_IF_ERR();
03589     RETURN_NONE();
03590 }
03591 
03592 
03593 static PyObject*
03594 DBTxn_id(DBTxnObject* self, PyObject* args)
03595 {
03596     int id;
03597 
03598     if (!PyArg_ParseTuple(args, ":id"))
03599         return NULL;
03600 
03601     MYDB_BEGIN_ALLOW_THREADS;
03602 #if (DBVER >= 40)
03603     id = self->txn->id(self->txn);
03604 #else
03605     id = txn_id(self->txn);
03606 #endif
03607     MYDB_END_ALLOW_THREADS;
03608     return PyInt_FromLong(id);
03609 }
03610 
03611 /* --------------------------------------------------------------------- */
03612 /* Method definition tables and type objects */
03613 
03614 static PyMethodDef DB_methods[] = {
03615     {"append",          (PyCFunction)DB_append,         METH_VARARGS},
03616 #if (DBVER >= 33)
03617     {"associate",       (PyCFunction)DB_associate,      METH_VARARGS|METH_KEYWORDS},
03618 #endif
03619     {"close",           (PyCFunction)DB_close,          METH_VARARGS},
03620 #if (DBVER >= 32)
03621     {"consume",         (PyCFunction)DB_consume,        METH_VARARGS|METH_KEYWORDS},
03622     {"consume_wait",    (PyCFunction)DB_consume_wait,   METH_VARARGS|METH_KEYWORDS},
03623 #endif
03624     {"cursor",          (PyCFunction)DB_cursor,         METH_VARARGS|METH_KEYWORDS},
03625     {"delete",          (PyCFunction)DB_delete,         METH_VARARGS|METH_KEYWORDS},
03626     {"fd",              (PyCFunction)DB_fd,             METH_VARARGS},
03627     {"get",             (PyCFunction)DB_get,            METH_VARARGS|METH_KEYWORDS},
03628     {"get_both",        (PyCFunction)DB_get_both,       METH_VARARGS|METH_KEYWORDS},
03629     {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
03630     {"get_size",        (PyCFunction)DB_get_size,       METH_VARARGS|METH_KEYWORDS},
03631     {"get_type",        (PyCFunction)DB_get_type,       METH_VARARGS},
03632     {"join",            (PyCFunction)DB_join,           METH_VARARGS},
03633     {"key_range",       (PyCFunction)DB_key_range,      METH_VARARGS|METH_KEYWORDS},
03634     {"has_key",         (PyCFunction)DB_has_key,        METH_VARARGS},
03635     {"items",           (PyCFunction)DB_items,          METH_VARARGS},
03636     {"keys",            (PyCFunction)DB_keys,           METH_VARARGS},
03637     {"open",            (PyCFunction)DB_open,           METH_VARARGS|METH_KEYWORDS},
03638     {"put",             (PyCFunction)DB_put,            METH_VARARGS|METH_KEYWORDS},
03639     {"remove",          (PyCFunction)DB_remove,         METH_VARARGS|METH_KEYWORDS},
03640     {"rename",          (PyCFunction)DB_rename,         METH_VARARGS},
03641     {"set_bt_minkey",   (PyCFunction)DB_set_bt_minkey,  METH_VARARGS},
03642     {"set_cachesize",   (PyCFunction)DB_set_cachesize,  METH_VARARGS},
03643     {"set_flags",       (PyCFunction)DB_set_flags,      METH_VARARGS},
03644     {"set_h_ffactor",   (PyCFunction)DB_set_h_ffactor,  METH_VARARGS},
03645     {"set_h_nelem",     (PyCFunction)DB_set_h_nelem,    METH_VARARGS},
03646     {"set_lorder",      (PyCFunction)DB_set_lorder,     METH_VARARGS},
03647     {"set_pagesize",    (PyCFunction)DB_set_pagesize,   METH_VARARGS},
03648     {"set_re_delim",    (PyCFunction)DB_set_re_delim,   METH_VARARGS},
03649     {"set_re_len",      (PyCFunction)DB_set_re_len,     METH_VARARGS},
03650     {"set_re_pad",      (PyCFunction)DB_set_re_pad,     METH_VARARGS},
03651     {"set_re_source",   (PyCFunction)DB_set_re_source,  METH_VARARGS},
03652 #if (DBVER >= 32)
03653     {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
03654 #endif
03655     {"stat",            (PyCFunction)DB_stat,           METH_VARARGS},
03656     {"sync",            (PyCFunction)DB_sync,           METH_VARARGS},
03657 #if (DBVER >= 33)
03658     {"truncate",        (PyCFunction)DB_truncate,       METH_VARARGS|METH_KEYWORDS},
03659 #endif
03660     {"type",            (PyCFunction)DB_get_type,       METH_VARARGS},
03661     {"upgrade",         (PyCFunction)DB_upgrade,        METH_VARARGS},
03662     {"values",          (PyCFunction)DB_values,         METH_VARARGS},
03663     {"verify",          (PyCFunction)DB_verify,         METH_VARARGS|METH_KEYWORDS},
03664     {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none,      METH_VARARGS},
03665     {NULL,      NULL}       /* sentinel */
03666 };
03667 
03668 
03669 static PyMappingMethods DB_mapping = {
03670         (inquiry)DB_length,          /*mp_length*/
03671         (binaryfunc)DB_subscript,    /*mp_subscript*/
03672         (objobjargproc)DB_ass_sub,   /*mp_ass_subscript*/
03673 };
03674 
03675 
03676 static PyMethodDef DBCursor_methods[] = {
03677     {"close",           (PyCFunction)DBC_close,         METH_VARARGS},
03678     {"count",           (PyCFunction)DBC_count,         METH_VARARGS},
03679     {"current",         (PyCFunction)DBC_current,       METH_VARARGS|METH_KEYWORDS},
03680     {"delete",          (PyCFunction)DBC_delete,        METH_VARARGS},
03681     {"dup",             (PyCFunction)DBC_dup,           METH_VARARGS},
03682     {"first",           (PyCFunction)DBC_first,         METH_VARARGS|METH_KEYWORDS},
03683     {"get",             (PyCFunction)DBC_get,           METH_VARARGS|METH_KEYWORDS},
03684     {"get_recno",       (PyCFunction)DBC_get_recno,     METH_VARARGS},
03685     {"last",            (PyCFunction)DBC_last,          METH_VARARGS|METH_KEYWORDS},
03686     {"next",            (PyCFunction)DBC_next,          METH_VARARGS|METH_KEYWORDS},
03687     {"prev",            (PyCFunction)DBC_prev,          METH_VARARGS|METH_KEYWORDS},
03688     {"put",             (PyCFunction)DBC_put,           METH_VARARGS|METH_KEYWORDS},
03689     {"set",             (PyCFunction)DBC_set,           METH_VARARGS|METH_KEYWORDS},
03690     {"set_range",       (PyCFunction)DBC_set_range,     METH_VARARGS|METH_KEYWORDS},
03691     {"get_both",        (PyCFunction)DBC_get_both,      METH_VARARGS},
03692     {"set_both",        (PyCFunction)DBC_get_both,      METH_VARARGS},
03693     {"set_recno",       (PyCFunction)DBC_set_recno,     METH_VARARGS|METH_KEYWORDS},
03694     {"consume",         (PyCFunction)DBC_consume,       METH_VARARGS|METH_KEYWORDS},
03695     {"next_dup",        (PyCFunction)DBC_next_dup,      METH_VARARGS|METH_KEYWORDS},
03696     {"next_nodup",      (PyCFunction)DBC_next_nodup,    METH_VARARGS|METH_KEYWORDS},
03697     {"prev_nodup",      (PyCFunction)DBC_prev_nodup,    METH_VARARGS|METH_KEYWORDS},
03698     {"join_item",       (PyCFunction)DBC_join_item,     METH_VARARGS},
03699     {NULL,      NULL}       /* sentinel */
03700 };
03701 
03702 
03703 static PyMethodDef DBEnv_methods[] = {
03704     {"close",           (PyCFunction)DBEnv_close,            METH_VARARGS},
03705     {"open",            (PyCFunction)DBEnv_open,             METH_VARARGS},
03706     {"remove",          (PyCFunction)DBEnv_remove,           METH_VARARGS},
03707     {"set_cachesize",   (PyCFunction)DBEnv_set_cachesize,    METH_VARARGS},
03708     {"set_data_dir",    (PyCFunction)DBEnv_set_data_dir,     METH_VARARGS},
03709 #if (DBVER >= 32)
03710     {"set_flags",       (PyCFunction)DBEnv_set_flags,        METH_VARARGS},
03711 #endif
03712     {"set_lg_bsize",    (PyCFunction)DBEnv_set_lg_bsize,     METH_VARARGS},
03713     {"set_lg_dir",      (PyCFunction)DBEnv_set_lg_dir,       METH_VARARGS},
03714     {"set_lg_max",      (PyCFunction)DBEnv_set_lg_max,       METH_VARARGS},
03715     {"set_lk_detect",   (PyCFunction)DBEnv_set_lk_detect,    METH_VARARGS},
03716     {"set_lk_max",      (PyCFunction)DBEnv_set_lk_max,       METH_VARARGS},
03717 #if (DBVER >= 32)
03718     {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
03719     {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
03720     {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
03721 #endif
03722     {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize,  METH_VARARGS},
03723     {"set_tmp_dir",     (PyCFunction)DBEnv_set_tmp_dir,      METH_VARARGS},
03724     {"txn_begin",       (PyCFunction)DBEnv_txn_begin,        METH_VARARGS|METH_KEYWORDS},
03725     {"txn_checkpoint",  (PyCFunction)DBEnv_txn_checkpoint,   METH_VARARGS},
03726     {"txn_stat",        (PyCFunction)DBEnv_txn_stat,         METH_VARARGS},
03727     {"set_tx_max",      (PyCFunction)DBEnv_set_tx_max,       METH_VARARGS},
03728     {"lock_detect",     (PyCFunction)DBEnv_lock_detect,      METH_VARARGS},
03729     {"lock_get",        (PyCFunction)DBEnv_lock_get,         METH_VARARGS},
03730     {"lock_id",         (PyCFunction)DBEnv_lock_id,          METH_VARARGS},
03731     {"lock_put",        (PyCFunction)DBEnv_lock_put,         METH_VARARGS},
03732     {"lock_stat",       (PyCFunction)DBEnv_lock_stat,        METH_VARARGS},
03733     {"log_archive",     (PyCFunction)DBEnv_log_archive,      METH_VARARGS},
03734     {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
03735     {NULL,      NULL}       /* sentinel */
03736 };
03737 
03738 
03739 static PyMethodDef DBTxn_methods[] = {
03740     {"commit",          (PyCFunction)DBTxn_commit,      METH_VARARGS},
03741     {"prepare",         (PyCFunction)DBTxn_prepare,     METH_VARARGS},
03742     {"abort",           (PyCFunction)DBTxn_abort,       METH_VARARGS},
03743     {"id",              (PyCFunction)DBTxn_id,          METH_VARARGS},
03744     {NULL,      NULL}       /* sentinel */
03745 };
03746 
03747 
03748 static PyObject*
03749 DB_getattr(DBObject* self, char *name)
03750 {
03751     return Py_FindMethod(DB_methods, (PyObject* )self, name);
03752 }
03753 
03754 
03755 static PyObject*
03756 DBEnv_getattr(DBEnvObject* self, char *name)
03757 {
03758     if (!strcmp(name, "db_home")) {
03759         CHECK_ENV_NOT_CLOSED(self);
03760         if (self->db_env->db_home == NULL) {
03761             RETURN_NONE();
03762         }
03763         return PyString_FromString(self->db_env->db_home);
03764     }
03765 
03766     return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
03767 }
03768 
03769 
03770 static PyObject*
03771 DBCursor_getattr(DBCursorObject* self, char *name)
03772 {
03773     return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
03774 }
03775 
03776 static PyObject*
03777 DBTxn_getattr(DBTxnObject* self, char *name)
03778 {
03779     return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
03780 }
03781 
03782 static PyObject*
03783 DBLock_getattr(DBLockObject* self, char *name)
03784 {
03785     return NULL;
03786 }
03787 
03788 statichere PyTypeObject DB_Type = {
03789     PyObject_HEAD_INIT(NULL)
03790     0,                  /*ob_size*/
03791     "DB",               /*tp_name*/
03792     sizeof(DBObject),   /*tp_basicsize*/
03793     0,                  /*tp_itemsize*/
03794     /* methods */
03795     (destructor)DB_dealloc, /*tp_dealloc*/
03796     0,                  /*tp_print*/
03797     (getattrfunc)DB_getattr, /*tp_getattr*/
03798     0,                      /*tp_setattr*/
03799     0,          /*tp_compare*/
03800     0,          /*tp_repr*/
03801     0,          /*tp_as_number*/
03802     0,          /*tp_as_sequence*/
03803     &DB_mapping,/*tp_as_mapping*/
03804     0,          /*tp_hash*/
03805 };
03806 
03807 
03808 statichere PyTypeObject DBCursor_Type = {
03809     PyObject_HEAD_INIT(NULL)
03810     0,                  /*ob_size*/
03811     "DBCursor",         /*tp_name*/
03812     sizeof(DBCursorObject),  /*tp_basicsize*/
03813     0,                  /*tp_itemsize*/
03814     /* methods */
03815     (destructor)DBCursor_dealloc,/*tp_dealloc*/
03816     0,                  /*tp_print*/
03817     (getattrfunc)DBCursor_getattr, /*tp_getattr*/
03818     0,                  /*tp_setattr*/
03819     0,                  /*tp_compare*/
03820     0,                  /*tp_repr*/
03821     0,                  /*tp_as_number*/
03822     0,                  /*tp_as_sequence*/
03823     0,                  /*tp_as_mapping*/
03824     0,                  /*tp_hash*/
03825 };
03826 
03827 
03828 statichere PyTypeObject DBEnv_Type = {
03829     PyObject_HEAD_INIT(NULL)
03830     0,          /*ob_size*/
03831     "DBEnv",            /*tp_name*/
03832     sizeof(DBEnvObject),    /*tp_basicsize*/
03833     0,          /*tp_itemsize*/
03834     /* methods */
03835     (destructor)DBEnv_dealloc, /*tp_dealloc*/
03836     0,          /*tp_print*/
03837     (getattrfunc)DBEnv_getattr, /*tp_getattr*/
03838     0,          /*tp_setattr*/
03839     0,          /*tp_compare*/
03840     0,          /*tp_repr*/
03841     0,          /*tp_as_number*/
03842     0,          /*tp_as_sequence*/
03843     0,          /*tp_as_mapping*/
03844     0,          /*tp_hash*/
03845 };
03846 
03847 statichere PyTypeObject DBTxn_Type = {
03848     PyObject_HEAD_INIT(NULL)
03849     0,          /*ob_size*/
03850     "DBTxn",    /*tp_name*/
03851     sizeof(DBTxnObject),  /*tp_basicsize*/
03852     0,          /*tp_itemsize*/
03853     /* methods */
03854     (destructor)DBTxn_dealloc, /*tp_dealloc*/
03855     0,          /*tp_print*/
03856     (getattrfunc)DBTxn_getattr, /*tp_getattr*/
03857     0,                      /*tp_setattr*/
03858     0,          /*tp_compare*/
03859     0,          /*tp_repr*/
03860     0,          /*tp_as_number*/
03861     0,          /*tp_as_sequence*/
03862     0,          /*tp_as_mapping*/
03863     0,          /*tp_hash*/
03864 };
03865 
03866 
03867 statichere PyTypeObject DBLock_Type = {
03868     PyObject_HEAD_INIT(NULL)
03869     0,          /*ob_size*/
03870     "DBLock",   /*tp_name*/
03871     sizeof(DBLockObject),  /*tp_basicsize*/
03872     0,          /*tp_itemsize*/
03873     /* methods */
03874     (destructor)DBLock_dealloc, /*tp_dealloc*/
03875     0,          /*tp_print*/
03876     (getattrfunc)DBLock_getattr, /*tp_getattr*/
03877     0,                      /*tp_setattr*/
03878     0,          /*tp_compare*/
03879     0,          /*tp_repr*/
03880     0,          /*tp_as_number*/
03881     0,          /*tp_as_sequence*/
03882     0,          /*tp_as_mapping*/
03883     0,          /*tp_hash*/
03884 };
03885 
03886 
03887 /* --------------------------------------------------------------------- */
03888 /* Module-level functions */
03889 
03890 static PyObject*
03891 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
03892 {
03893     PyObject* dbenvobj = NULL;
03894     int flags = 0;
03895     char* kwnames[] = { "dbEnv", "flags", NULL};
03896 
03897     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames, &dbenvobj, &flags))
03898         return NULL;
03899     if (dbenvobj == Py_None)
03900         dbenvobj = NULL;
03901     else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
03902         makeTypeError("DBEnv", dbenvobj);
03903         return NULL;
03904     }
03905 
03906     return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
03907 }
03908 
03909 
03910 static PyObject*
03911 DBEnv_construct(PyObject* self, PyObject* args)
03912 {
03913     int flags = 0;
03914     if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
03915     return (PyObject* )newDBEnvObject(flags);
03916 }
03917 
03918 
03919 static char bsddb_version_doc[] =
03920 "Returns a tuple of major, minor, and patch release numbers of the\n\
03921 underlying DB library.";
03922 
03923 static PyObject*
03924 bsddb_version(PyObject* self, PyObject* args)
03925 {
03926     int major, minor, patch;
03927 
03928         if (!PyArg_ParseTuple(args, ":version"))
03929         return NULL;
03930         db_version(&major, &minor, &patch);
03931         return Py_BuildValue("(iii)", major, minor, patch);
03932 }
03933 
03934 
03935 /* List of functions defined in the module */
03936 
03937 static PyMethodDef bsddb_methods[] = {
03938     {"DB",      (PyCFunction)DB_construct,      METH_VARARGS | METH_KEYWORDS },
03939     {"DBEnv",   (PyCFunction)DBEnv_construct,   METH_VARARGS},
03940     {"version", (PyCFunction)bsddb_version,     METH_VARARGS, bsddb_version_doc},
03941     {NULL,      NULL}       /* sentinel */
03942 };
03943 
03944 
03945 /* --------------------------------------------------------------------- */
03946 /* Module initialization */
03947 
03948 
03949 /* Convenience routine to export an integer value.
03950  * Errors are silently ignored, for better or for worse...
03951  */
03952 #define ADD_INT(dict, NAME)         _addIntToDict(dict, #NAME, NAME)
03953 
03954 
03955 
03956 void init_rpmdb(void);          /* XXX remove compiler warning */
03957 
03958 DL_EXPORT(void) init_rpmdb(void)
03959 {
03960     PyObject* m;
03961     PyObject* d;
03962     PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
03963     PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
03964     PyObject* cvsid_s = PyString_FromString( rcs_id );
03965 
03966     /* Initialize the type of the new type objects here; doing it here
03967        is required for portability to Windows without requiring C++. */
03968     DB_Type.ob_type = &PyType_Type;
03969     DBCursor_Type.ob_type = &PyType_Type;
03970     DBEnv_Type.ob_type = &PyType_Type;
03971     DBTxn_Type.ob_type = &PyType_Type;
03972     DBLock_Type.ob_type = &PyType_Type;
03973 
03974 
03975 #ifdef WITH_THREAD
03976     /* Save the current interpreter, so callbacks can do the right thing. */
03977     _db_interpreterState = PyThreadState_Get()->interp;
03978 #endif
03979 
03980     /* Create the module and add the functions */
03981     m = Py_InitModule("_rpmdb", bsddb_methods);
03982 
03983     /* Add some symbolic constants to the module */
03984     d = PyModule_GetDict(m);
03985     PyDict_SetItemString(d, "__version__", pybsddb_version_s);
03986     PyDict_SetItemString(d, "cvsid", cvsid_s);
03987     PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
03988     Py_DECREF(pybsddb_version_s);
03989     pybsddb_version_s = NULL;
03990     Py_DECREF(cvsid_s);
03991     cvsid_s = NULL;
03992     Py_DECREF(db_version_s);
03993     db_version_s = NULL;
03994 
03995     ADD_INT(d, DB_VERSION_MAJOR);
03996     ADD_INT(d, DB_VERSION_MINOR);
03997     ADD_INT(d, DB_VERSION_PATCH);
03998 
03999     ADD_INT(d, DB_MAX_PAGES);
04000     ADD_INT(d, DB_MAX_RECORDS);
04001 
04002     ADD_INT(d, DB_CLIENT);
04003     ADD_INT(d, DB_XA_CREATE);
04004 
04005     ADD_INT(d, DB_CREATE);
04006     ADD_INT(d, DB_NOMMAP);
04007     ADD_INT(d, DB_THREAD);
04008 
04009     ADD_INT(d, DB_FORCE);
04010     ADD_INT(d, DB_INIT_CDB);
04011     ADD_INT(d, DB_INIT_LOCK);
04012     ADD_INT(d, DB_INIT_LOG);
04013     ADD_INT(d, DB_INIT_MPOOL);
04014     ADD_INT(d, DB_INIT_TXN);
04015 #if (DBVER >= 32)
04016     ADD_INT(d, DB_JOINENV);
04017 #endif
04018 
04019     ADD_INT(d, DB_RECOVER);
04020     ADD_INT(d, DB_RECOVER_FATAL);
04021     ADD_INT(d, DB_TXN_NOSYNC);
04022     ADD_INT(d, DB_USE_ENVIRON);
04023     ADD_INT(d, DB_USE_ENVIRON_ROOT);
04024 
04025     ADD_INT(d, DB_LOCKDOWN);
04026     ADD_INT(d, DB_PRIVATE);
04027     ADD_INT(d, DB_SYSTEM_MEM);
04028 
04029     ADD_INT(d, DB_TXN_SYNC);
04030     ADD_INT(d, DB_TXN_NOWAIT);
04031 
04032     ADD_INT(d, DB_EXCL);
04033     ADD_INT(d, DB_FCNTL_LOCKING);
04034     ADD_INT(d, DB_ODDFILESIZE);
04035     ADD_INT(d, DB_RDWRMASTER);
04036     ADD_INT(d, DB_RDONLY);
04037     ADD_INT(d, DB_TRUNCATE);
04038 #if (DBVER >= 32)
04039     ADD_INT(d, DB_EXTENT);
04040     ADD_INT(d, DB_CDB_ALLDB);
04041     ADD_INT(d, DB_VERIFY);
04042 #endif
04043     ADD_INT(d, DB_UPGRADE);
04044 
04045     ADD_INT(d, DB_AGGRESSIVE);
04046     ADD_INT(d, DB_NOORDERCHK);
04047     ADD_INT(d, DB_ORDERCHKONLY);
04048     ADD_INT(d, DB_PR_PAGE);
04049 #if ! (DBVER >= 33)
04050     ADD_INT(d, DB_VRFY_FLAGMASK);
04051     ADD_INT(d, DB_PR_HEADERS);
04052 #endif
04053     ADD_INT(d, DB_PR_RECOVERYTEST);
04054     ADD_INT(d, DB_SALVAGE);
04055 
04056     ADD_INT(d, DB_LOCK_NORUN);
04057     ADD_INT(d, DB_LOCK_DEFAULT);
04058     ADD_INT(d, DB_LOCK_OLDEST);
04059     ADD_INT(d, DB_LOCK_RANDOM);
04060     ADD_INT(d, DB_LOCK_YOUNGEST);
04061 #if (DBVER >= 33)
04062     ADD_INT(d, DB_LOCK_MAXLOCKS);
04063     ADD_INT(d, DB_LOCK_MINLOCKS);
04064     ADD_INT(d, DB_LOCK_MINWRITE);
04065 #endif
04066 
04067 
04068 #if (DBVER >= 33)
04069     _addIntToDict(d, "DB_LOCK_CONFLICT", 0);   /* docs say to use zero instead */
04070 #else
04071     ADD_INT(d, DB_LOCK_CONFLICT);
04072 #endif
04073 
04074     ADD_INT(d, DB_LOCK_DUMP);
04075     ADD_INT(d, DB_LOCK_GET);
04076     ADD_INT(d, DB_LOCK_INHERIT);
04077     ADD_INT(d, DB_LOCK_PUT);
04078     ADD_INT(d, DB_LOCK_PUT_ALL);
04079     ADD_INT(d, DB_LOCK_PUT_OBJ);
04080 
04081     ADD_INT(d, DB_LOCK_NG);
04082     ADD_INT(d, DB_LOCK_READ);
04083     ADD_INT(d, DB_LOCK_WRITE);
04084     ADD_INT(d, DB_LOCK_NOWAIT);
04085 #if (DBVER >= 32)
04086     ADD_INT(d, DB_LOCK_WAIT);
04087 #endif
04088     ADD_INT(d, DB_LOCK_IWRITE);
04089     ADD_INT(d, DB_LOCK_IREAD);
04090     ADD_INT(d, DB_LOCK_IWR);
04091 #if (DBVER >= 33)
04092     ADD_INT(d, DB_LOCK_DIRTY);
04093     ADD_INT(d, DB_LOCK_WWRITE);
04094 #endif
04095 
04096     ADD_INT(d, DB_LOCK_RECORD);
04097     ADD_INT(d, DB_LOCK_UPGRADE);
04098 #if (DBVER >= 32)
04099     ADD_INT(d, DB_LOCK_SWITCH);
04100 #endif
04101 #if (DBVER >= 33)
04102     ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
04103 #endif
04104 
04105     ADD_INT(d, DB_LOCK_NOWAIT);
04106     ADD_INT(d, DB_LOCK_RECORD);
04107     ADD_INT(d, DB_LOCK_UPGRADE);
04108 
04109 #if (DBVER >= 33)
04110     ADD_INT(d, DB_LSTAT_ABORTED);
04111     ADD_INT(d, DB_LSTAT_ERR);
04112     ADD_INT(d, DB_LSTAT_FREE);
04113     ADD_INT(d, DB_LSTAT_HELD);
04114 #if (DBVER == 33)
04115     ADD_INT(d, DB_LSTAT_NOGRANT);
04116 #endif
04117     ADD_INT(d, DB_LSTAT_PENDING);
04118     ADD_INT(d, DB_LSTAT_WAITING);
04119 #endif
04120 
04121     ADD_INT(d, DB_ARCH_ABS);
04122     ADD_INT(d, DB_ARCH_DATA);
04123     ADD_INT(d, DB_ARCH_LOG);
04124 
04125     ADD_INT(d, DB_BTREE);
04126     ADD_INT(d, DB_HASH);
04127     ADD_INT(d, DB_RECNO);
04128     ADD_INT(d, DB_QUEUE);
04129     ADD_INT(d, DB_UNKNOWN);
04130 
04131     ADD_INT(d, DB_DUP);
04132     ADD_INT(d, DB_DUPSORT);
04133     ADD_INT(d, DB_RECNUM);
04134     ADD_INT(d, DB_RENUMBER);
04135     ADD_INT(d, DB_REVSPLITOFF);
04136     ADD_INT(d, DB_SNAPSHOT);
04137 
04138     ADD_INT(d, DB_JOIN_NOSORT);
04139 
04140     ADD_INT(d, DB_AFTER);
04141     ADD_INT(d, DB_APPEND);
04142     ADD_INT(d, DB_BEFORE);
04143     ADD_INT(d, DB_CACHED_COUNTS);
04144 #if (DBVER < 41)
04145     ADD_INT(d, DB_CHECKPOINT);
04146 #endif
04147 #if (DBVER >= 33)
04148     ADD_INT(d, DB_COMMIT);
04149 #endif
04150     ADD_INT(d, DB_CONSUME);
04151 #if (DBVER >= 32)
04152     ADD_INT(d, DB_CONSUME_WAIT);
04153 #endif
04154 #if (DBVER < 41)
04155     ADD_INT(d, DB_CURLSN);
04156 #endif
04157     ADD_INT(d, DB_CURRENT);
04158 #if (DBVER >= 33)
04159     ADD_INT(d, DB_FAST_STAT);
04160 #endif
04161     ADD_INT(d, DB_FIRST);
04162     ADD_INT(d, DB_FLUSH);
04163     ADD_INT(d, DB_GET_BOTH);
04164     ADD_INT(d, DB_GET_RECNO);
04165     ADD_INT(d, DB_JOIN_ITEM);
04166     ADD_INT(d, DB_KEYFIRST);
04167     ADD_INT(d, DB_KEYLAST);
04168     ADD_INT(d, DB_LAST);
04169     ADD_INT(d, DB_NEXT);
04170     ADD_INT(d, DB_NEXT_DUP);
04171     ADD_INT(d, DB_NEXT_NODUP);
04172     ADD_INT(d, DB_NODUPDATA);
04173     ADD_INT(d, DB_NOOVERWRITE);
04174     ADD_INT(d, DB_NOSYNC);
04175     ADD_INT(d, DB_POSITION);
04176     ADD_INT(d, DB_PREV);
04177     ADD_INT(d, DB_PREV_NODUP);
04178     ADD_INT(d, DB_RECORDCOUNT);
04179     ADD_INT(d, DB_SET);
04180     ADD_INT(d, DB_SET_RANGE);
04181     ADD_INT(d, DB_SET_RECNO);
04182     ADD_INT(d, DB_WRITECURSOR);
04183 
04184     ADD_INT(d, DB_OPFLAGS_MASK);
04185     ADD_INT(d, DB_RMW);
04186 #if (DBVER >= 33)
04187     ADD_INT(d, DB_DIRTY_READ);
04188     ADD_INT(d, DB_MULTIPLE);
04189     ADD_INT(d, DB_MULTIPLE_KEY);
04190 #endif
04191 
04192 #if (DBVER >= 33)
04193     ADD_INT(d, DB_DONOTINDEX);
04194 #endif
04195 
04196 #if (DBVER < 41)
04197     ADD_INT(d, DB_INCOMPLETE);
04198 #endif
04199     ADD_INT(d, DB_KEYEMPTY);
04200     ADD_INT(d, DB_KEYEXIST);
04201     ADD_INT(d, DB_LOCK_DEADLOCK);
04202     ADD_INT(d, DB_LOCK_NOTGRANTED);
04203     ADD_INT(d, DB_NOSERVER);
04204     ADD_INT(d, DB_NOSERVER_HOME);
04205     ADD_INT(d, DB_NOSERVER_ID);
04206     ADD_INT(d, DB_NOTFOUND);
04207     ADD_INT(d, DB_OLD_VERSION);
04208     ADD_INT(d, DB_RUNRECOVERY);
04209     ADD_INT(d, DB_VERIFY_BAD);
04210 #if (DBVER >= 33)
04211     ADD_INT(d, DB_PAGE_NOTFOUND);
04212     ADD_INT(d, DB_SECONDARY_BAD);
04213 #endif
04214 #if (DBVER >= 40)
04215     ADD_INT(d, DB_STAT_CLEAR);
04216     ADD_INT(d, DB_REGION_INIT);
04217     ADD_INT(d, DB_NOLOCKING);
04218     ADD_INT(d, DB_YIELDCPU);
04219     ADD_INT(d, DB_PANIC_ENVIRONMENT);
04220     ADD_INT(d, DB_NOPANIC);
04221 #endif
04222 
04223     ADD_INT(d, EINVAL);
04224     ADD_INT(d, EACCES);
04225     ADD_INT(d, ENOSPC);
04226     ADD_INT(d, ENOMEM);
04227     ADD_INT(d, EAGAIN);
04228     ADD_INT(d, EBUSY);
04229     ADD_INT(d, EEXIST);
04230     ADD_INT(d, ENOENT);
04231     ADD_INT(d, EPERM);
04232 
04233 
04234 
04235     /* The base exception class is DBError */
04236     DBError = PyErr_NewException("rpmdb._rpmdb.DBError", NULL, NULL);
04237     PyDict_SetItemString(d, "DBError", DBError);
04238 
04239     /* Some magic to make DBNotFoundError derive from both DBError and
04240        KeyError, since the API only supports using one base class. */
04241     PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
04242     PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
04243                  Py_file_input, d, d);
04244     DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
04245     PyDict_DelItemString(d, "KeyError");
04246 
04247 
04248     /* All the rest of the exceptions derive only from DBError */
04249 #define MAKE_EX(name)   name = PyErr_NewException("rpmdb._rpmdb." #name, DBError, NULL); \
04250                         PyDict_SetItemString(d, #name, name)
04251 
04252 #if !INCOMPLETE_IS_WARNING
04253     MAKE_EX(DBIncompleteError);
04254 #endif
04255     MAKE_EX(DBKeyEmptyError);
04256     MAKE_EX(DBKeyExistError);
04257     MAKE_EX(DBLockDeadlockError);
04258     MAKE_EX(DBLockNotGrantedError);
04259     MAKE_EX(DBOldVersionError);
04260     MAKE_EX(DBRunRecoveryError);
04261     MAKE_EX(DBVerifyBadError);
04262     MAKE_EX(DBNoServerError);
04263     MAKE_EX(DBNoServerHomeError);
04264     MAKE_EX(DBNoServerIDError);
04265 #if (DBVER >= 33)
04266     MAKE_EX(DBPageNotFoundError);
04267     MAKE_EX(DBSecondaryBadError);
04268 #endif
04269 
04270     MAKE_EX(DBInvalidArgError);
04271     MAKE_EX(DBAccessError);
04272     MAKE_EX(DBNoSpaceError);
04273     MAKE_EX(DBNoMemoryError);
04274     MAKE_EX(DBAgainError);
04275     MAKE_EX(DBBusyError);
04276     MAKE_EX(DBFileExistsError);
04277     MAKE_EX(DBNoSuchFileError);
04278     MAKE_EX(DBPermissionsError);
04279 
04280 #undef MAKE_EX
04281 
04282     /* Check for errors */
04283     if (PyErr_Occurred()) {
04284         PyErr_Print();
04285         Py_FatalError("can't initialize module _rpmdb");
04286     }
04287 }

Generated on Sun Oct 26 13:02:02 2003 for rpm by doxygen1.2.18