Mercurial > dovecot > original-hg > dovecot-1.2
changeset 5106:81394e71f92a HEAD
Added istream->blocking setting. It's now used to assert-crash early if a
blocking stream unexpectedly returns "need more data".
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 06 Feb 2007 12:40:15 +0200 |
parents | 342429974bf5 |
children | ddbc89221c26 |
files | src/lib-mail/istream-header-filter.c src/lib-storage/index/mbox/istream-raw-mbox.c src/lib/istream-data.c src/lib/istream-file.c src/lib/istream-limit.c src/lib/istream-mmap.c src/lib/istream.c src/lib/istream.h src/plugins/zlib/istream-zlib.c |
diffstat | 9 files changed, 58 insertions(+), 30 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-mail/istream-header-filter.c Tue Feb 06 11:49:46 2007 +0200 +++ b/src/lib-mail/istream-header-filter.c Tue Feb 06 12:40:15 2007 +0200 @@ -351,6 +351,7 @@ mstream->istream.sync = _sync; mstream->istream.stat = _stat; + mstream->istream.istream.blocking = input->blocking; mstream->istream.istream.seekable = input->seekable; return _i_stream_create(&mstream->istream, pool, -1, 0); }
--- a/src/lib-storage/index/mbox/istream-raw-mbox.c Tue Feb 06 11:49:46 2007 +0200 +++ b/src/lib-storage/index/mbox/istream-raw-mbox.c Tue Feb 06 12:40:15 2007 +0200 @@ -367,6 +367,8 @@ rstream->istream.sync = _sync; rstream->istream.stat = _stat; + rstream->istream.istream.blocking = input->blocking; + rstream->istream.istream.seekable = input->seekable; return _i_stream_create(&rstream->istream, pool, -1, input->real_stream->abs_start_offset); }
--- a/src/lib/istream-data.c Tue Feb 06 11:49:46 2007 +0200 +++ b/src/lib/istream-data.c Tue Feb 06 12:40:15 2007 +0200 @@ -53,6 +53,7 @@ stream->seek = _seek; stream->stat = _stat; + stream->istream.blocking = TRUE; stream->istream.seekable = TRUE; return _i_stream_create(stream, pool, -1, 0); }
--- a/src/lib/istream-file.c Tue Feb 06 11:49:46 2007 +0200 +++ b/src/lib/istream-file.c Tue Feb 06 12:40:15 2007 +0200 @@ -114,15 +114,17 @@ ret = -1; - if (fstream->file) { - do { + do { + if (fstream->file) { ret = pread(stream->fd, stream->w_buffer + stream->pos, size, stream->istream.v_offset + (stream->pos - stream->skip)); - } while (ret < 0 && errno == EINTR); - } else { - ret = read(stream->fd, stream->w_buffer + stream->pos, size); - } + } else { + ret = read(stream->fd, stream->w_buffer + stream->pos, + size); + } + } while (ret < 0 && errno == EINTR && stream->istream.blocking); + if (ret == 0) { /* EOF */ stream->istream.eof = TRUE; @@ -130,9 +132,10 @@ } if (ret < 0) { - if (errno == EINTR || errno == EAGAIN) + if (errno == EINTR || errno == EAGAIN) { + i_assert(!stream->istream.blocking); ret = 0; - else { + } else { stream->istream.eof = TRUE; stream->istream.stream_errno = errno; return -1; @@ -238,9 +241,10 @@ fstream->istream.sync = _sync; fstream->istream.stat = _stat; - /* get size of fd if it's a file */ + /* if it's a file, set the flags properly */ if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) { fstream->file = TRUE; + fstream->istream.istream.blocking = TRUE; fstream->istream.istream.seekable = TRUE; }
--- a/src/lib/istream-limit.c Tue Feb 06 11:49:46 2007 +0200 +++ b/src/lib/istream-limit.c Tue Feb 06 12:40:15 2007 +0200 @@ -132,6 +132,7 @@ lstream->istream.seek = _seek; lstream->istream.stat = _stat; + lstream->istream.istream.blocking = input->blocking; lstream->istream.istream.seekable = input->seekable; return _i_stream_create(&lstream->istream, pool, i_stream_get_fd(input), input->real_stream->abs_start_offset +
--- a/src/lib/istream-mmap.c Tue Feb 06 11:49:46 2007 +0200 +++ b/src/lib/istream-mmap.c Tue Feb 06 12:40:15 2007 +0200 @@ -234,6 +234,7 @@ istream = _i_stream_create(&mstream->istream, pool, fd, start_offset); istream->mmaped = TRUE; + istream->blocking = TRUE; istream->seekable = TRUE; return istream; }
--- a/src/lib/istream.c Tue Feb 06 11:49:46 2007 +0200 +++ b/src/lib/istream.c Tue Feb 06 12:40:15 2007 +0200 @@ -208,42 +208,42 @@ return line; } -const unsigned char *i_stream_get_data(struct istream *stream, size_t *size) +const unsigned char *i_stream_get_data(struct istream *stream, size_t *size_r) { struct _istream *_stream = stream->real_stream; if (_stream->skip >= _stream->pos) { - *size = 0; + *size_r = 0; return NULL; } - *size = _stream->pos - _stream->skip; + *size_r = _stream->pos - _stream->skip; return _stream->buffer + _stream->skip; } unsigned char *i_stream_get_modifiable_data(struct istream *stream, - size_t *size) + size_t *size_r) { struct _istream *_stream = stream->real_stream; if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) { - *size = 0; + *size_r = 0; return NULL; } - *size = _stream->pos - _stream->skip; + *size_r = _stream->pos - _stream->skip; return _stream->w_buffer + _stream->skip; } -int i_stream_read_data(struct istream *stream, const unsigned char **data, - size_t *size, size_t threshold) +int i_stream_read_data(struct istream *stream, const unsigned char **data_r, + size_t *size_r, size_t threshold) { ssize_t ret = 0; bool read_more = FALSE; do { - *data = i_stream_get_data(stream, size); - if (*size > threshold) + *data_r = i_stream_get_data(stream, size_r); + if (*size_r > threshold) return 1; /* we need more data */ @@ -252,9 +252,15 @@ read_more = TRUE; } while (ret > 0); - *data = i_stream_get_data(stream, size); - return ret == -2 ? -2 : - (read_more || ret == 0 ? 0 : -1); + *data_r = i_stream_get_data(stream, size_r); + if (ret == -2) + return -2; + + if (read_more || ret == 0) { + i_assert(!stream->blocking || stream->eof); + return 0; + } + return -1; } struct istream *_i_stream_create(struct _istream *_stream, pool_t pool, int fd,
--- a/src/lib/istream.h Tue Feb 06 11:49:46 2007 +0200 +++ b/src/lib/istream.h Tue Feb 06 12:40:15 2007 +0200 @@ -9,6 +9,7 @@ int stream_errno; unsigned int mmaped:1; /* be careful when copying data */ + unsigned int blocking:1; /* read() shouldn't return 0 */ unsigned int closed:1; unsigned int seekable:1; /* we can seek() backwards */ unsigned int eof:1; /* read() has reached to end of file @@ -85,16 +86,16 @@ /* Returns pointer to beginning of read data, or NULL if there's no data buffered. */ -const unsigned char *i_stream_get_data(struct istream *stream, size_t *size); +const unsigned char *i_stream_get_data(struct istream *stream, size_t *size_r); /* Like i_stream_get_data(), but returns non-const data. This only works with buffered streams (currently only file), others return NULL. */ unsigned char *i_stream_get_modifiable_data(struct istream *stream, - size_t *size); + size_t *size_r); /* Like i_stream_get_data(), but read more when needed. Returns 1 if more than threshold bytes are available, 0 if less, -1 if error or EOF with no bytes read that weren't already in buffer, or -2 if stream's input buffer is full. */ -int i_stream_read_data(struct istream *stream, const unsigned char **data, - size_t *size, size_t threshold); +int i_stream_read_data(struct istream *stream, const unsigned char **data_r, + size_t *size_r, size_t threshold); #endif
--- a/src/plugins/zlib/istream-zlib.c Tue Feb 06 11:49:46 2007 +0200 +++ b/src/plugins/zlib/istream-zlib.c Tue Feb 06 12:40:15 2007 +0200 @@ -124,7 +124,11 @@ i_assert(zstream->seek_offset == stream->istream.v_offset + (stream->pos - stream->skip)); - ret = gzread(zstream->file, stream->w_buffer + stream->pos, size); + do { + ret = gzread(zstream->file, stream->w_buffer + stream->pos, + size); + } while (ret < 0 && errno == EINTR && stream->istream.blocking); + if (ret == 0) { /* EOF */ stream->istream.eof = TRUE; @@ -132,9 +136,10 @@ } if (ret < 0) { - if (errno == EINTR || errno == EAGAIN) + if (errno == EAGAIN) { + i_assert(!stream->istream.blocking); ret = 0; - else { + } else { stream->istream.eof = TRUE; stream->istream.stream_errno = errno; return -1; @@ -236,6 +241,7 @@ struct istream *i_stream_create_zlib(int fd, pool_t pool) { struct zlib_istream *zstream; + struct stat st; zstream = p_new(pool, struct zlib_istream, 1); zstream->fd = fd; @@ -252,6 +258,11 @@ zstream->istream.stat = _stat; zstream->istream.sync = _sync; - zstream->istream.istream.seekable = TRUE; + /* if it's a file, set the flags properly */ + if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) { + zstream->istream.istream.blocking = TRUE; + zstream->istream.istream.seekable = TRUE; + } + return _i_stream_create(&zstream->istream, pool, fd, 0); }