summaryrefslogtreecommitdiffstats
path: root/Modules/_hotshot.c
diff options
context:
space:
mode:
authorNeil Schemenauer <nascheme@enme.ucalgary.ca>2002-05-29 18:19:14 (GMT)
committerNeil Schemenauer <nascheme@enme.ucalgary.ca>2002-05-29 18:19:14 (GMT)
commit8b6b491ed7b8dd0020e1d0155e2199c2cee5e383 (patch)
tree69ecd40949e5a466a1839ae235afa4808afd16dc /Modules/_hotshot.c
parentd7abe2a0fb80866cc305bf71c34e21239adad19f (diff)
downloadcpython-8b6b491ed7b8dd0020e1d0155e2199c2cee5e383.zip
cpython-8b6b491ed7b8dd0020e1d0155e2199c2cee5e383.tar.gz
cpython-8b6b491ed7b8dd0020e1d0155e2199c2cee5e383.tar.bz2
The logreader object did not always refill the input buffer correctly
and got confused by certain log files. Remove logreader_refill and the associated logic and replace with fgetc.
Diffstat (limited to 'Modules/_hotshot.c')
-rw-r--r--Modules/_hotshot.c161
1 files changed, 56 insertions, 105 deletions
diff --git a/Modules/_hotshot.c b/Modules/_hotshot.c
index 2eb7bdb..4399525 100644
--- a/Modules/_hotshot.c
+++ b/Modules/_hotshot.c
@@ -83,11 +83,8 @@ typedef struct {
PyObject_HEAD
PyObject *info;
FILE *logfp;
- int filled;
- int index;
int linetimings;
int frametimings;
- unsigned char buffer[BUFFERSIZE];
} LogReaderObject;
static PyObject * ProfilerError = NULL;
@@ -272,25 +269,21 @@ logreader_tp_iter(LogReaderObject *self)
static int
unpack_packed_int(LogReaderObject *self, int *pvalue, int discard)
{
+ int c;
int accum = 0;
int bits = 0;
- int index = self->index;
int cont;
do {
- if (index >= self->filled)
- return ERR_EOF;
/* read byte */
- accum |= ((self->buffer[index] & 0x7F) >> discard) << bits;
+ if ((c = fgetc(self->logfp)) == EOF)
+ return ERR_EOF;
+ accum |= ((c & 0x7F) >> discard) << bits;
bits += (7 - discard);
- cont = self->buffer[index] & 0x80;
- /* move to next */
+ cont = c & 0x80;
discard = 0;
- index++;
} while (cont);
- /* save state */
- self->index = index;
*pvalue = accum;
return 0;
@@ -302,43 +295,37 @@ unpack_packed_int(LogReaderObject *self, int *pvalue, int discard)
static int
unpack_string(LogReaderObject *self, PyObject **pvalue)
{
+ int i;
int len;
- int oldindex = self->index;
- int err = unpack_packed_int(self, &len, 0);
-
- if (!err) {
- /* need at least len bytes in buffer */
- if (len > (self->filled - self->index)) {
- self->index = oldindex;
- err = ERR_EOF;
- }
- else {
- *pvalue = PyString_FromStringAndSize((char *)self->buffer + self->index,
- len);
- if (*pvalue == NULL) {
- self->index = oldindex;
- err = ERR_EXCEPTION;
- }
- else
- self->index += len;
+ int err;
+ char *buf;
+
+ if ((err = unpack_packed_int(self, &len, 0)))
+ return err;
+
+ buf = malloc(len);
+ for (i=0; i < len; i++) {
+ if ((buf[i] = fgetc(self->logfp)) == EOF) {
+ free(buf);
+ return ERR_EOF;
}
}
- return err;
+ *pvalue = PyString_FromStringAndSize(buf, len);
+ free(buf);
+ if (*pvalue == NULL) {
+ return ERR_EXCEPTION;
+ }
+ return 0;
}
static int
-unpack_add_info(LogReaderObject *self, int skip_opcode)
+unpack_add_info(LogReaderObject *self)
{
PyObject *key;
PyObject *value = NULL;
int err;
- if (skip_opcode) {
- if (self->buffer[self->index] != WHAT_ADD_INFO)
- return ERR_BAD_RECTYPE;
- self->index++;
- }
err = unpack_string(self, &key);
if (!err) {
err = unpack_string(self, &value);
@@ -369,25 +356,6 @@ unpack_add_info(LogReaderObject *self, int skip_opcode)
static void
-logreader_refill(LogReaderObject *self)
-{
- int needed;
- size_t res;
-
- if (self->index) {
- memmove(self->buffer, &self->buffer[self->index],
- self->filled - self->index);
- self->filled = self->filled - self->index;
- self->index = 0;
- }
- needed = BUFFERSIZE - self->filled;
- if (needed > 0) {
- res = fread(&self->buffer[self->filled], 1, needed, self->logfp);
- self->filled += res;
- }
-}
-
-static void
eof_error(void)
{
PyErr_SetString(PyExc_EOFError,
@@ -397,7 +365,8 @@ eof_error(void)
static PyObject *
logreader_tp_iternext(LogReaderObject *self)
{
- int what, oldindex;
+ int c;
+ int what;
int err = ERR_NONE;
int lineno = -1;
int fileno = -1;
@@ -413,22 +382,18 @@ logreader_tp_iternext(LogReaderObject *self)
"cannot iterate over closed LogReader object");
return NULL;
}
- restart:
- if ((self->filled - self->index) < MAXEVENTSIZE)
- logreader_refill(self);
- /* end of input */
- if (self->filled == 0)
+restart:
+ /* decode the record type */
+ if ((c = fgetc(self->logfp)) == EOF)
return NULL;
- oldindex = self->index;
+ what = c & WHAT_OTHER;
+ if (what == WHAT_OTHER)
+ what = c; /* need all the bits for type */
+ else
+ ungetc(c, self->logfp); /* type byte includes packed int */
- /* decode the record type */
- what = self->buffer[self->index] & WHAT_OTHER;
- if (what == WHAT_OTHER) {
- what = self->buffer[self->index];
- self->index++;
- }
switch (what) {
case WHAT_ENTER:
err = unpack_packed_int(self, &fileno, 2);
@@ -447,7 +412,7 @@ logreader_tp_iternext(LogReaderObject *self)
err = unpack_packed_int(self, &tdelta, 0);
break;
case WHAT_ADD_INFO:
- err = unpack_add_info(self, 0);
+ err = unpack_add_info(self);
break;
case WHAT_DEFINE_FILE:
err = unpack_packed_int(self, &fileno, 0);
@@ -468,40 +433,29 @@ logreader_tp_iternext(LogReaderObject *self)
}
break;
case WHAT_LINE_TIMES:
- if (self->index >= self->filled)
+ if ((c = fgetc(self->logfp)) == EOF)
err = ERR_EOF;
else {
- self->linetimings = self->buffer[self->index] ? 1 : 0;
- self->index++;
- goto restart;
- }
+ self->linetimings = c ? 1 : 0;
+ goto restart;
+ }
break;
case WHAT_FRAME_TIMES:
- if (self->index >= self->filled)
+ if ((c = fgetc(self->logfp)) == EOF)
err = ERR_EOF;
else {
- self->frametimings = self->buffer[self->index] ? 1 : 0;
- self->index++;
- goto restart;
- }
+ self->frametimings = c ? 1 : 0;
+ goto restart;
+ }
break;
default:
err = ERR_BAD_RECTYPE;
}
- if (err == ERR_EOF && oldindex != 0) {
- /* It looks like we ran out of data before we had it all; this
- * could easily happen with large packed integers or string
- * data. Try forcing the buffer to be re-filled before failing.
- */
- err = ERR_NONE;
- logreader_refill(self);
- }
if (err == ERR_BAD_RECTYPE) {
PyErr_SetString(PyExc_ValueError,
"unknown record type in log file");
}
else if (err == ERR_EOF) {
- /* Could not avoid end-of-buffer error. */
eof_error();
}
else if (!err) {
@@ -1389,12 +1343,12 @@ hotshot_logreader(PyObject *unused, PyObject *args)
{
LogReaderObject *self = NULL;
char *filename;
+ int c;
+ int err = 0;
if (PyArg_ParseTuple(args, "s:logreader", &filename)) {
self = PyObject_New(LogReaderObject, &LogReaderType);
if (self != NULL) {
- self->filled = 0;
- self->index = 0;
self->frametimings = 1;
self->linetimings = 0;
self->info = NULL;
@@ -1410,14 +1364,17 @@ hotshot_logreader(PyObject *unused, PyObject *args)
Py_DECREF(self);
goto finally;
}
- /* Aggressively attempt to load all preliminary ADD_INFO
- * records from the log so the info records are available
- * from a fresh logreader object.
- */
- logreader_refill(self);
- while (self->filled > self->index
- && self->buffer[self->index] == WHAT_ADD_INFO) {
- int err = unpack_add_info(self, 1);
+ /* read initial info */
+ for (;;) {
+ if ((c = fgetc(self->logfp)) == EOF) {
+ eof_error();
+ break;
+ }
+ if (c != WHAT_ADD_INFO) {
+ ungetc(c, self->logfp);
+ break;
+ }
+ err = unpack_add_info(self);
if (err) {
if (err == ERR_EOF)
eof_error();
@@ -1426,12 +1383,6 @@ hotshot_logreader(PyObject *unused, PyObject *args)
"unexpected error");
break;
}
- /* Refill agressively so we can avoid EOF during
- * initialization unless there's a real EOF condition
- * (the tp_iternext handler loops attempts to refill
- * and try again).
- */
- logreader_refill(self);
}
}
}