Gustavo Niemeyer <niemeyer@conectiva.com>:
Fixed recno support (keys are integers rather than strings). Work around DB bug that cause stdin to be closed by rnopen() when the DB file needed to exist but did not (no longer segfaults). This closes SF tracker patch #403445. Also wrapped some long lines and added whitespace around operators -- FLD.
This commit is contained in:
parent
cf9926ca8d
commit
ed5e8234d7
|
@ -2,9 +2,10 @@
|
|||
Author: Michael McLay
|
||||
Hacked: Guido van Rossum
|
||||
Btree and Recno additions plus sequence methods: David Ely
|
||||
Hacked by Gustavo Niemeyer <niemeyer@conectiva.com> fixing recno
|
||||
support.
|
||||
|
||||
XXX To do:
|
||||
- provide interface to the B-tree and record libraries too
|
||||
- provide a way to access the various hash functions
|
||||
- support more open flags
|
||||
|
||||
|
@ -17,6 +18,10 @@
|
|||
#include "pythread.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -32,6 +37,7 @@ typedef struct {
|
|||
PyObject_HEAD
|
||||
DB *di_bsddb;
|
||||
int di_size; /* -1 means recompute */
|
||||
int di_type;
|
||||
#ifdef WITH_THREAD
|
||||
PyThread_type_lock di_lock;
|
||||
#endif
|
||||
|
@ -40,10 +46,10 @@ typedef struct {
|
|||
staticforward PyTypeObject Bsddbtype;
|
||||
|
||||
#define is_bsddbobject(v) ((v)->ob_type == &Bsddbtype)
|
||||
#define check_bsddbobject_open(v) if ((v)->di_bsddb == NULL) \
|
||||
#define check_bsddbobject_open(v, r) if ((v)->di_bsddb == NULL) \
|
||||
{ PyErr_SetString(BsddbError, \
|
||||
"BSDDB object has already been closed"); \
|
||||
return NULL; }
|
||||
return r; }
|
||||
|
||||
static PyObject *BsddbError;
|
||||
|
||||
|
@ -81,6 +87,8 @@ newdbhashobject(char *file, int flags, int mode,
|
|||
}
|
||||
|
||||
dp->di_size = -1;
|
||||
dp->di_type = DB_HASH;
|
||||
|
||||
#ifdef WITH_THREAD
|
||||
dp->di_lock = PyThread_allocate_lock();
|
||||
if (dp->di_lock == NULL) {
|
||||
|
@ -129,6 +137,8 @@ newdbbtobject(char *file, int flags, int mode,
|
|||
}
|
||||
|
||||
dp->di_size = -1;
|
||||
dp->di_type = DB_BTREE;
|
||||
|
||||
#ifdef WITH_THREAD
|
||||
dp->di_lock = PyThread_allocate_lock();
|
||||
if (dp->di_lock == NULL) {
|
||||
|
@ -148,6 +158,7 @@ newdbrnobject(char *file, int flags, int mode,
|
|||
{
|
||||
bsddbobject *dp;
|
||||
RECNOINFO info;
|
||||
int fd;
|
||||
|
||||
if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
|
||||
return NULL;
|
||||
|
@ -163,9 +174,18 @@ newdbrnobject(char *file, int flags, int mode,
|
|||
#ifdef O_BINARY
|
||||
flags |= O_BINARY;
|
||||
#endif
|
||||
/* This is a hack to avoid a dbopen() bug that happens when
|
||||
* it fails. */
|
||||
fd = open(file, flags);
|
||||
if (fd == -1) {
|
||||
dp->di_bsddb = NULL;
|
||||
}
|
||||
else {
|
||||
close(fd);
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info);
|
||||
Py_END_ALLOW_THREADS
|
||||
}
|
||||
if (dp->di_bsddb == NULL) {
|
||||
PyErr_SetFromErrno(BsddbError);
|
||||
#ifdef WITH_THREAD
|
||||
|
@ -176,6 +196,8 @@ newdbrnobject(char *file, int flags, int mode,
|
|||
}
|
||||
|
||||
dp->di_size = -1;
|
||||
dp->di_type = DB_RECNO;
|
||||
|
||||
#ifdef WITH_THREAD
|
||||
dp->di_lock = PyThread_allocate_lock();
|
||||
if (dp->di_lock == NULL) {
|
||||
|
@ -225,11 +247,7 @@ bsddb_dealloc(bsddbobject *dp)
|
|||
static int
|
||||
bsddb_length(bsddbobject *dp)
|
||||
{
|
||||
if (dp->di_bsddb == NULL) {
|
||||
PyErr_SetString(BsddbError,
|
||||
"BSDDB object has already been closed");
|
||||
return -1;
|
||||
}
|
||||
check_bsddbobject_open(dp, -1);
|
||||
if (dp->di_size < 0) {
|
||||
DBT krec, drec;
|
||||
int status;
|
||||
|
@ -259,13 +277,27 @@ bsddb_subscript(bsddbobject *dp, PyObject *key)
|
|||
char *data,buf[4096];
|
||||
int size;
|
||||
PyObject *result;
|
||||
recno_t recno;
|
||||
|
||||
if (!PyArg_Parse(key, "s#", &data, &size))
|
||||
if (dp->di_type == DB_RECNO) {
|
||||
if (!PyArg_Parse(key, "i", &recno)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"key type must be integer");
|
||||
return NULL;
|
||||
check_bsddbobject_open(dp);
|
||||
|
||||
}
|
||||
krec.data = &recno;
|
||||
krec.size = sizeof(recno);
|
||||
}
|
||||
else {
|
||||
if (!PyArg_Parse(key, "s#", &data, &size)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"key type must be string");
|
||||
return NULL;
|
||||
}
|
||||
krec.data = data;
|
||||
krec.size = size;
|
||||
}
|
||||
check_bsddbobject_open(dp, NULL);
|
||||
|
||||
BSDDB_BGN_SAVE(dp)
|
||||
status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
|
||||
|
@ -296,19 +328,27 @@ bsddb_ass_sub(bsddbobject *dp, PyObject *key, PyObject *value)
|
|||
DBT krec, drec;
|
||||
char *data;
|
||||
int size;
|
||||
recno_t recno;
|
||||
|
||||
if (dp->di_type == DB_RECNO) {
|
||||
if (!PyArg_Parse(key, "i", &recno)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"bsddb key type must be integer");
|
||||
return -1;
|
||||
}
|
||||
krec.data = &recno;
|
||||
krec.size = sizeof(recno);
|
||||
}
|
||||
else {
|
||||
if (!PyArg_Parse(key, "s#", &data, &size)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"bsddb key type must be string");
|
||||
return -1;
|
||||
}
|
||||
if (dp->di_bsddb == NULL) {
|
||||
PyErr_SetString(BsddbError,
|
||||
"BSDDB object has already been closed");
|
||||
return -1;
|
||||
}
|
||||
krec.data = data;
|
||||
krec.size = size;
|
||||
}
|
||||
check_bsddbobject_open(dp, -1);
|
||||
dp->di_size = -1;
|
||||
if (value == NULL) {
|
||||
BSDDB_BGN_SAVE(dp)
|
||||
|
@ -323,17 +363,6 @@ bsddb_ass_sub(bsddbobject *dp, PyObject *key, PyObject *value)
|
|||
}
|
||||
drec.data = data;
|
||||
drec.size = size;
|
||||
#if 0
|
||||
/* For RECNO, put fails with 'No space left on device'
|
||||
after a few short records are added?? Looks fine
|
||||
to this point... linked with 1.85 on Solaris Intel
|
||||
Roger E. Masse 1/16/97
|
||||
*/
|
||||
printf("before put data: '%s', size: %d\n",
|
||||
drec.data, drec.size);
|
||||
printf("before put key= '%s', size= %d\n",
|
||||
krec.data, krec.size);
|
||||
#endif
|
||||
BSDDB_BGN_SAVE(dp)
|
||||
status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
|
||||
BSDDB_END_SAVE(dp)
|
||||
|
@ -378,7 +407,7 @@ bsddb_close(bsddbobject *dp, PyObject *args)
|
|||
static PyObject *
|
||||
bsddb_keys(bsddbobject *dp, PyObject *args)
|
||||
{
|
||||
PyObject *list, *item;
|
||||
PyObject *list, *item=NULL;
|
||||
DBT krec, drec;
|
||||
char *data=NULL,buf[4096];
|
||||
int status;
|
||||
|
@ -386,7 +415,7 @@ bsddb_keys(bsddbobject *dp, PyObject *args)
|
|||
|
||||
if (!PyArg_NoArgs(args))
|
||||
return NULL;
|
||||
check_bsddbobject_open(dp);
|
||||
check_bsddbobject_open(dp, NULL);
|
||||
list = PyList_New(0);
|
||||
if (list == NULL)
|
||||
return NULL;
|
||||
|
@ -400,7 +429,11 @@ bsddb_keys(bsddbobject *dp, PyObject *args)
|
|||
BSDDB_END_SAVE(dp)
|
||||
if (data==NULL) return PyErr_NoMemory();
|
||||
while (status == 0) {
|
||||
item = PyString_FromStringAndSize(data, (int)krec.size);
|
||||
if (dp->di_type == DB_RECNO)
|
||||
item = PyInt_FromLong(*((int*)data));
|
||||
else
|
||||
item = PyString_FromStringAndSize(data,
|
||||
(int)krec.size);
|
||||
if (data != buf) free(data);
|
||||
if (item == NULL) {
|
||||
Py_DECREF(list);
|
||||
|
@ -442,12 +475,27 @@ bsddb_has_key(bsddbobject *dp, PyObject *args)
|
|||
int status;
|
||||
char *data;
|
||||
int size;
|
||||
recno_t recno;
|
||||
|
||||
if (!PyArg_Parse(args, "s#", &data, &size))
|
||||
if (dp->di_type == DB_RECNO) {
|
||||
if (!PyArg_Parse(args, "i", &recno)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"key type must be integer");
|
||||
return NULL;
|
||||
check_bsddbobject_open(dp);
|
||||
}
|
||||
krec.data = &recno;
|
||||
krec.size = sizeof(recno);
|
||||
}
|
||||
else {
|
||||
if (!PyArg_Parse(args, "s#", &data, &size)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"key type must be string");
|
||||
return NULL;
|
||||
}
|
||||
krec.data = data;
|
||||
krec.size = size;
|
||||
}
|
||||
check_bsddbobject_open(dp, NULL);
|
||||
|
||||
BSDDB_BGN_SAVE(dp)
|
||||
status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
|
||||
|
@ -468,12 +516,27 @@ bsddb_set_location(bsddbobject *dp, PyObject *key)
|
|||
char *data,buf[4096];
|
||||
int size;
|
||||
PyObject *result;
|
||||
recno_t recno;
|
||||
|
||||
if (!PyArg_Parse(key, "s#", &data, &size))
|
||||
if (dp->di_type == DB_RECNO) {
|
||||
if (!PyArg_Parse(key, "i", &recno)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"key type must be integer");
|
||||
return NULL;
|
||||
check_bsddbobject_open(dp);
|
||||
}
|
||||
krec.data = &recno;
|
||||
krec.size = sizeof(recno);
|
||||
}
|
||||
else {
|
||||
if (!PyArg_Parse(key, "s#", &data, &size)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"key type must be string");
|
||||
return NULL;
|
||||
}
|
||||
krec.data = data;
|
||||
krec.size = size;
|
||||
}
|
||||
check_bsddbobject_open(dp, NULL);
|
||||
|
||||
BSDDB_BGN_SAVE(dp)
|
||||
status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
|
||||
|
@ -492,7 +555,12 @@ bsddb_set_location(bsddbobject *dp, PyObject *key)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
result = Py_BuildValue("s#s#", krec.data, krec.size, data, drec.size);
|
||||
if (dp->di_type == DB_RECNO)
|
||||
result = Py_BuildValue("is#", *((int*)krec.data),
|
||||
data, drec.size);
|
||||
else
|
||||
result = Py_BuildValue("s#s#", krec.data, krec.size,
|
||||
data, drec.size);
|
||||
if (data != buf) free(data);
|
||||
return result;
|
||||
}
|
||||
|
@ -509,7 +577,7 @@ bsddb_seq(bsddbobject *dp, PyObject *args, int sequence_request)
|
|||
if (!PyArg_NoArgs(args))
|
||||
return NULL;
|
||||
|
||||
check_bsddbobject_open(dp);
|
||||
check_bsddbobject_open(dp, NULL);
|
||||
krec.data = 0;
|
||||
krec.size = 0;
|
||||
|
||||
|
@ -538,7 +606,13 @@ bsddb_seq(bsddbobject *dp, PyObject *args, int sequence_request)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
result = Py_BuildValue("s#s#", kdata, krec.size, ddata, drec.size);
|
||||
|
||||
if (dp->di_type == DB_RECNO)
|
||||
result = Py_BuildValue("is#", *((int*)kdata),
|
||||
ddata, drec.size);
|
||||
else
|
||||
result = Py_BuildValue("s#s#", kdata, krec.size,
|
||||
ddata, drec.size);
|
||||
if (kdata != kbuf) free(kdata);
|
||||
if (ddata != dbuf) free(ddata);
|
||||
return result;
|
||||
|
@ -571,7 +645,7 @@ bsddb_sync(bsddbobject *dp, PyObject *args)
|
|||
|
||||
if (!PyArg_NoArgs(args))
|
||||
return NULL;
|
||||
check_bsddbobject_open(dp);
|
||||
check_bsddbobject_open(dp, NULL);
|
||||
BSDDB_BGN_SAVE(dp)
|
||||
status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
|
||||
BSDDB_END_SAVE(dp)
|
||||
|
@ -741,19 +815,6 @@ bsdrnopen(PyObject *self, PyObject *args)
|
|||
&reclen, &bval, &bfname))
|
||||
return NULL;
|
||||
|
||||
# if 0
|
||||
printf("file: %s\n", file);
|
||||
printf("flag: %s\n", flag);
|
||||
printf("mode: %d\n", mode);
|
||||
printf("rnflags: 0x%x\n", rnflags);
|
||||
printf("cachesize: %d\n", cachesize);
|
||||
printf("psize: %d\n", psize);
|
||||
printf("lorder: %d\n", 0);
|
||||
printf("reclen: %d\n", reclen);
|
||||
printf("bval: %c\n", bval[0]);
|
||||
printf("bfname %s\n", bfname);
|
||||
#endif
|
||||
|
||||
if (flag != NULL) {
|
||||
/* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
|
||||
if (flag[0] == 'r')
|
||||
|
|
Loading…
Reference in New Issue