Kaydet (Commit) ed5e8234 authored tarafından Fred Drake's avatar Fred Drake

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.
üst cf9926ca
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
Author: Michael McLay Author: Michael McLay
Hacked: Guido van Rossum Hacked: Guido van Rossum
Btree and Recno additions plus sequence methods: David Ely Btree and Recno additions plus sequence methods: David Ely
Hacked by Gustavo Niemeyer <niemeyer@conectiva.com> fixing recno
support.
XXX To do: XXX To do:
- provide interface to the B-tree and record libraries too
- provide a way to access the various hash functions - provide a way to access the various hash functions
- support more open flags - support more open flags
...@@ -17,6 +18,10 @@ ...@@ -17,6 +18,10 @@
#include "pythread.h" #include "pythread.h"
#endif #endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
...@@ -32,6 +37,7 @@ typedef struct { ...@@ -32,6 +37,7 @@ typedef struct {
PyObject_HEAD PyObject_HEAD
DB *di_bsddb; DB *di_bsddb;
int di_size; /* -1 means recompute */ int di_size; /* -1 means recompute */
int di_type;
#ifdef WITH_THREAD #ifdef WITH_THREAD
PyThread_type_lock di_lock; PyThread_type_lock di_lock;
#endif #endif
...@@ -40,10 +46,10 @@ typedef struct { ...@@ -40,10 +46,10 @@ typedef struct {
staticforward PyTypeObject Bsddbtype; staticforward PyTypeObject Bsddbtype;
#define is_bsddbobject(v) ((v)->ob_type == &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, \ { PyErr_SetString(BsddbError, \
"BSDDB object has already been closed"); \ "BSDDB object has already been closed"); \
return NULL; } return r; }
static PyObject *BsddbError; static PyObject *BsddbError;
...@@ -81,6 +87,8 @@ newdbhashobject(char *file, int flags, int mode, ...@@ -81,6 +87,8 @@ newdbhashobject(char *file, int flags, int mode,
} }
dp->di_size = -1; dp->di_size = -1;
dp->di_type = DB_HASH;
#ifdef WITH_THREAD #ifdef WITH_THREAD
dp->di_lock = PyThread_allocate_lock(); dp->di_lock = PyThread_allocate_lock();
if (dp->di_lock == NULL) { if (dp->di_lock == NULL) {
...@@ -129,6 +137,8 @@ newdbbtobject(char *file, int flags, int mode, ...@@ -129,6 +137,8 @@ newdbbtobject(char *file, int flags, int mode,
} }
dp->di_size = -1; dp->di_size = -1;
dp->di_type = DB_BTREE;
#ifdef WITH_THREAD #ifdef WITH_THREAD
dp->di_lock = PyThread_allocate_lock(); dp->di_lock = PyThread_allocate_lock();
if (dp->di_lock == NULL) { if (dp->di_lock == NULL) {
...@@ -148,6 +158,7 @@ newdbrnobject(char *file, int flags, int mode, ...@@ -148,6 +158,7 @@ newdbrnobject(char *file, int flags, int mode,
{ {
bsddbobject *dp; bsddbobject *dp;
RECNOINFO info; RECNOINFO info;
int fd;
if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL) if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
return NULL; return NULL;
...@@ -163,9 +174,18 @@ newdbrnobject(char *file, int flags, int mode, ...@@ -163,9 +174,18 @@ newdbrnobject(char *file, int flags, int mode,
#ifdef O_BINARY #ifdef O_BINARY
flags |= O_BINARY; flags |= O_BINARY;
#endif #endif
Py_BEGIN_ALLOW_THREADS /* This is a hack to avoid a dbopen() bug that happens when
dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info); * it fails. */
Py_END_ALLOW_THREADS 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) { if (dp->di_bsddb == NULL) {
PyErr_SetFromErrno(BsddbError); PyErr_SetFromErrno(BsddbError);
#ifdef WITH_THREAD #ifdef WITH_THREAD
...@@ -176,6 +196,8 @@ newdbrnobject(char *file, int flags, int mode, ...@@ -176,6 +196,8 @@ newdbrnobject(char *file, int flags, int mode,
} }
dp->di_size = -1; dp->di_size = -1;
dp->di_type = DB_RECNO;
#ifdef WITH_THREAD #ifdef WITH_THREAD
dp->di_lock = PyThread_allocate_lock(); dp->di_lock = PyThread_allocate_lock();
if (dp->di_lock == NULL) { if (dp->di_lock == NULL) {
...@@ -225,11 +247,7 @@ bsddb_dealloc(bsddbobject *dp) ...@@ -225,11 +247,7 @@ bsddb_dealloc(bsddbobject *dp)
static int static int
bsddb_length(bsddbobject *dp) bsddb_length(bsddbobject *dp)
{ {
if (dp->di_bsddb == NULL) { check_bsddbobject_open(dp, -1);
PyErr_SetString(BsddbError,
"BSDDB object has already been closed");
return -1;
}
if (dp->di_size < 0) { if (dp->di_size < 0) {
DBT krec, drec; DBT krec, drec;
int status; int status;
...@@ -259,13 +277,27 @@ bsddb_subscript(bsddbobject *dp, PyObject *key) ...@@ -259,13 +277,27 @@ bsddb_subscript(bsddbobject *dp, PyObject *key)
char *data,buf[4096]; char *data,buf[4096];
int size; int size;
PyObject *result; PyObject *result;
recno_t recno;
if (!PyArg_Parse(key, "s#", &data, &size))
return NULL;
check_bsddbobject_open(dp);
krec.data = data; if (dp->di_type == DB_RECNO) {
krec.size = size; if (!PyArg_Parse(key, "i", &recno)) {
PyErr_SetString(PyExc_TypeError,
"key type must be integer");
return NULL;
}
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) BSDDB_BGN_SAVE(dp)
status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0); status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
...@@ -296,19 +328,27 @@ bsddb_ass_sub(bsddbobject *dp, PyObject *key, PyObject *value) ...@@ -296,19 +328,27 @@ bsddb_ass_sub(bsddbobject *dp, PyObject *key, PyObject *value)
DBT krec, drec; DBT krec, drec;
char *data; char *data;
int size; int size;
recno_t recno;
if (!PyArg_Parse(key, "s#", &data, &size)) { if (dp->di_type == DB_RECNO) {
PyErr_SetString(PyExc_TypeError, if (!PyArg_Parse(key, "i", &recno)) {
"bsddb key type must be string"); PyErr_SetString(PyExc_TypeError,
return -1; "bsddb key type must be integer");
return -1;
}
krec.data = &recno;
krec.size = sizeof(recno);
} }
if (dp->di_bsddb == NULL) { else {
PyErr_SetString(BsddbError, if (!PyArg_Parse(key, "s#", &data, &size)) {
"BSDDB object has already been closed"); PyErr_SetString(PyExc_TypeError,
return -1; "bsddb key type must be string");
} return -1;
krec.data = data; }
krec.size = size; krec.data = data;
krec.size = size;
}
check_bsddbobject_open(dp, -1);
dp->di_size = -1; dp->di_size = -1;
if (value == NULL) { if (value == NULL) {
BSDDB_BGN_SAVE(dp) BSDDB_BGN_SAVE(dp)
...@@ -323,17 +363,6 @@ bsddb_ass_sub(bsddbobject *dp, PyObject *key, PyObject *value) ...@@ -323,17 +363,6 @@ bsddb_ass_sub(bsddbobject *dp, PyObject *key, PyObject *value)
} }
drec.data = data; drec.data = data;
drec.size = size; 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) BSDDB_BGN_SAVE(dp)
status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0); status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
BSDDB_END_SAVE(dp) BSDDB_END_SAVE(dp)
...@@ -378,7 +407,7 @@ bsddb_close(bsddbobject *dp, PyObject *args) ...@@ -378,7 +407,7 @@ bsddb_close(bsddbobject *dp, PyObject *args)
static PyObject * static PyObject *
bsddb_keys(bsddbobject *dp, PyObject *args) bsddb_keys(bsddbobject *dp, PyObject *args)
{ {
PyObject *list, *item; PyObject *list, *item=NULL;
DBT krec, drec; DBT krec, drec;
char *data=NULL,buf[4096]; char *data=NULL,buf[4096];
int status; int status;
...@@ -386,7 +415,7 @@ bsddb_keys(bsddbobject *dp, PyObject *args) ...@@ -386,7 +415,7 @@ bsddb_keys(bsddbobject *dp, PyObject *args)
if (!PyArg_NoArgs(args)) if (!PyArg_NoArgs(args))
return NULL; return NULL;
check_bsddbobject_open(dp); check_bsddbobject_open(dp, NULL);
list = PyList_New(0); list = PyList_New(0);
if (list == NULL) if (list == NULL)
return NULL; return NULL;
...@@ -395,12 +424,16 @@ bsddb_keys(bsddbobject *dp, PyObject *args) ...@@ -395,12 +424,16 @@ bsddb_keys(bsddbobject *dp, PyObject *args)
if (status == 0) { if (status == 0) {
if (krec.size > sizeof(buf)) data = malloc(krec.size); if (krec.size > sizeof(buf)) data = malloc(krec.size);
else data = buf; else data = buf;
if (data!=NULL) memcpy(data,krec.data,krec.size); if (data != NULL) memcpy(data,krec.data,krec.size);
} }
BSDDB_END_SAVE(dp) BSDDB_END_SAVE(dp)
if (data==NULL) return PyErr_NoMemory(); if (data==NULL) return PyErr_NoMemory();
while (status == 0) { 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 (data != buf) free(data);
if (item == NULL) { if (item == NULL) {
Py_DECREF(list); Py_DECREF(list);
...@@ -442,12 +475,27 @@ bsddb_has_key(bsddbobject *dp, PyObject *args) ...@@ -442,12 +475,27 @@ bsddb_has_key(bsddbobject *dp, PyObject *args)
int status; int status;
char *data; char *data;
int size; int size;
recno_t recno;
if (!PyArg_Parse(args, "s#", &data, &size)) if (dp->di_type == DB_RECNO) {
return NULL; if (!PyArg_Parse(args, "i", &recno)) {
check_bsddbobject_open(dp); PyErr_SetString(PyExc_TypeError,
krec.data = data; "key type must be integer");
krec.size = size; return NULL;
}
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) BSDDB_BGN_SAVE(dp)
status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0); status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
...@@ -468,12 +516,27 @@ bsddb_set_location(bsddbobject *dp, PyObject *key) ...@@ -468,12 +516,27 @@ bsddb_set_location(bsddbobject *dp, PyObject *key)
char *data,buf[4096]; char *data,buf[4096];
int size; int size;
PyObject *result; PyObject *result;
recno_t recno;
if (!PyArg_Parse(key, "s#", &data, &size)) if (dp->di_type == DB_RECNO) {
return NULL; if (!PyArg_Parse(key, "i", &recno)) {
check_bsddbobject_open(dp); PyErr_SetString(PyExc_TypeError,
krec.data = data; "key type must be integer");
krec.size = size; return NULL;
}
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) BSDDB_BGN_SAVE(dp)
status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR); status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
...@@ -492,7 +555,12 @@ bsddb_set_location(bsddbobject *dp, PyObject *key) ...@@ -492,7 +555,12 @@ bsddb_set_location(bsddbobject *dp, PyObject *key)
return NULL; 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); if (data != buf) free(data);
return result; return result;
} }
...@@ -509,7 +577,7 @@ bsddb_seq(bsddbobject *dp, PyObject *args, int sequence_request) ...@@ -509,7 +577,7 @@ bsddb_seq(bsddbobject *dp, PyObject *args, int sequence_request)
if (!PyArg_NoArgs(args)) if (!PyArg_NoArgs(args))
return NULL; return NULL;
check_bsddbobject_open(dp); check_bsddbobject_open(dp, NULL);
krec.data = 0; krec.data = 0;
krec.size = 0; krec.size = 0;
...@@ -519,14 +587,14 @@ bsddb_seq(bsddbobject *dp, PyObject *args, int sequence_request) ...@@ -519,14 +587,14 @@ bsddb_seq(bsddbobject *dp, PyObject *args, int sequence_request)
if (status == 0) { if (status == 0) {
if (krec.size > sizeof(kbuf)) kdata = malloc(krec.size); if (krec.size > sizeof(kbuf)) kdata = malloc(krec.size);
else kdata = kbuf; else kdata = kbuf;
if (kdata!=NULL) memcpy(kdata,krec.data,krec.size); if (kdata != NULL) memcpy(kdata,krec.data,krec.size);
if (drec.size > sizeof(dbuf)) ddata = malloc(drec.size); if (drec.size > sizeof(dbuf)) ddata = malloc(drec.size);
else ddata = dbuf; else ddata = dbuf;
if (ddata!=NULL) memcpy(ddata,drec.data,drec.size); if (ddata != NULL) memcpy(ddata,drec.data,drec.size);
} }
BSDDB_END_SAVE(dp) BSDDB_END_SAVE(dp)
if (status == 0) { if (status == 0) {
if ((kdata==NULL) || (ddata==NULL)) if ((kdata == NULL) || (ddata == NULL))
return PyErr_NoMemory(); return PyErr_NoMemory();
} }
else { else {
...@@ -538,7 +606,13 @@ bsddb_seq(bsddbobject *dp, PyObject *args, int sequence_request) ...@@ -538,7 +606,13 @@ bsddb_seq(bsddbobject *dp, PyObject *args, int sequence_request)
return NULL; 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 (kdata != kbuf) free(kdata);
if (ddata != dbuf) free(ddata); if (ddata != dbuf) free(ddata);
return result; return result;
...@@ -571,7 +645,7 @@ bsddb_sync(bsddbobject *dp, PyObject *args) ...@@ -571,7 +645,7 @@ bsddb_sync(bsddbobject *dp, PyObject *args)
if (!PyArg_NoArgs(args)) if (!PyArg_NoArgs(args))
return NULL; return NULL;
check_bsddbobject_open(dp); check_bsddbobject_open(dp, NULL);
BSDDB_BGN_SAVE(dp) BSDDB_BGN_SAVE(dp)
status = (dp->di_bsddb->sync)(dp->di_bsddb, 0); status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
BSDDB_END_SAVE(dp) BSDDB_END_SAVE(dp)
...@@ -741,19 +815,6 @@ bsdrnopen(PyObject *self, PyObject *args) ...@@ -741,19 +815,6 @@ bsdrnopen(PyObject *self, PyObject *args)
&reclen, &bval, &bfname)) &reclen, &bval, &bfname))
return NULL; 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) { if (flag != NULL) {
/* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */ /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
if (flag[0] == 'r') if (flag[0] == 'r')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment