[dovecot-cvs] dovecot/src/lib istream-data.c, 1.11, 1.12 istream-file.c, 1.22, 1.23 istream-internal.h, 1.6, 1.7 istream-limit.c, 1.12, 1.13 istream-mmap.c, 1.15, 1.16 istream.c, 1.27, 1.28 istream.h, 1.16, 1.17 ostream-file.c, 1.45, 1.46

cras at dovecot.org cras at dovecot.org
Tue Mar 29 13:28:09 EEST 2005


Update of /var/lib/cvs/dovecot/src/lib
In directory talvi:/tmp/cvs-serv331/lib

Modified Files:
	istream-data.c istream-file.c istream-internal.h 
	istream-limit.c istream-mmap.c istream.c istream.h 
	ostream-file.c 
Log Message:
Replaced i_stream_get_size() with i_stream_stat(). Added i_stream_sync().



Index: istream-data.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/istream-data.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- istream-data.c	28 Mar 2005 13:06:43 -0000	1.11
+++ istream-data.c	29 Mar 2005 10:28:06 -0000	1.12
@@ -28,9 +28,10 @@
 	stream->istream.v_offset = v_offset;
 }
 
-static uoff_t _get_size(struct _istream *stream)
+static const struct stat *_stat(struct _istream *stream)
 {
-	return stream->pos;
+	stream->statbuf.st_size = stream->pos;
+	return &stream->statbuf;
 }
 
 struct istream *i_stream_create_from_data(pool_t pool, const void *data,
@@ -48,7 +49,7 @@
 
 	stream->read = _read;
 	stream->seek = _seek;
-	stream->get_size = _get_size;
+	stream->stat = _stat;
 
 	stream->istream.seekable = TRUE;
 	return _i_stream_create(stream, pool, -1, 0);

Index: istream-file.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/istream-file.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- istream-file.c	28 Mar 2005 13:06:43 -0000	1.22
+++ istream-file.c	29 Mar 2005 10:28:06 -0000	1.23
@@ -3,6 +3,7 @@
 /* @UNSAFE: whole file */
 
 #include "lib.h"
+#include "ioloop.h"
 #include "istream-internal.h"
 #include "network.h"
 
@@ -15,6 +16,8 @@
 struct file_istream {
 	struct _istream istream;
 
+        struct timeval fstat_cache_stamp;
+
 	size_t max_buffer_size;
 	uoff_t skip_left;
 
@@ -173,15 +176,45 @@
 	stream->skip = stream->pos = 0;
 }
 
-static uoff_t _get_size(struct _istream *stream)
+static void _sync(struct _istream *stream)
 {
 	struct file_istream *fstream = (struct file_istream *) stream;
-	struct stat st;
 
-	if (fstream->file && fstat(stream->fd, &st) == 0 && S_ISREG(st.st_mode))
-		return (uoff_t)st.st_size;
-	else
-		return (uoff_t)-1;
+	fstream->fstat_cache_stamp.tv_sec = 0;
+
+	if (!stream->istream.seekable) {
+		/* can't do anything or data would be lost */
+		return;
+	}
+
+	stream->skip = stream->pos = 0;
+}
+
+static int fstat_cached(struct file_istream *fstream)
+{
+	if (fstream->fstat_cache_stamp.tv_sec == ioloop_timeval.tv_sec &&
+	    fstream->fstat_cache_stamp.tv_usec == ioloop_timeval.tv_usec)
+		return 0;
+
+	if (fstat(fstream->istream.fd, &fstream->istream.statbuf) < 0) {
+		i_error("file_istream.fstat() failed: %m");
+		return -1;
+	}
+
+	fstream->fstat_cache_stamp = ioloop_timeval;
+	return 0;
+}
+
+static const struct stat *_stat(struct _istream *stream)
+{
+	struct file_istream *fstream = (struct file_istream *) stream;
+
+	if (fstream->file) {
+		if (fstat_cached(fstream) < 0)
+			return NULL;
+	}
+
+	return &stream->statbuf;
 }
 
 struct istream *i_stream_create_file(int fd, pool_t pool,
@@ -200,7 +233,8 @@
 
 	fstream->istream.read = _read;
 	fstream->istream.seek = _seek;
-	fstream->istream.get_size = _get_size;
+	fstream->istream.sync = _sync;
+	fstream->istream.stat = _stat;
 
 	/* get size of fd if it's a file */
 	if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {

Index: istream-internal.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/istream-internal.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- istream-internal.h	28 Mar 2005 22:35:12 -0000	1.6
+++ istream-internal.h	29 Mar 2005 10:28:06 -0000	1.7
@@ -1,6 +1,8 @@
 #ifndef __ISTREAM_INTERNAL_H
 #define __ISTREAM_INTERNAL_H
 
+#include <sys/stat.h>
+
 #include "istream.h"
 #include "iostream-internal.h"
 
@@ -11,7 +13,8 @@
 /* methods: */
 	ssize_t (*read)(struct _istream *stream);
 	void (*seek)(struct _istream *stream, uoff_t v_offset);
-	uoff_t (*get_size)(struct _istream *stream);
+	void (*sync)(struct _istream *stream);
+	const struct stat *(*stat)(struct _istream *stream);
 
 /* data: */
 	struct istream istream;
@@ -22,6 +25,7 @@
 	string_t *line_str; /* for i_stream_next_line() if w_buffer == NULL */
 	size_t buffer_size;
 	uoff_t abs_start_offset;
+	struct stat statbuf;
 
 	size_t skip, pos;
 };

Index: istream-limit.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/istream-limit.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- istream-limit.c	28 Mar 2005 13:06:43 -0000	1.12
+++ istream-limit.c	29 Mar 2005 10:28:06 -0000	1.13
@@ -89,12 +89,19 @@
 	stream->skip = stream->pos = 0;
 }
 
-static uoff_t _get_size(struct _istream *stream)
+static const struct stat *_stat(struct _istream *stream)
 {
 	struct limit_istream *lstream = (struct limit_istream *) stream;
+	const struct stat *st;
 
-	return lstream->v_size != (uoff_t)-1 ? lstream->v_size :
-		i_stream_get_size(lstream->input);
+	st = i_stream_stat(lstream->input);
+	if (st == NULL)
+		return NULL;
+
+	stream->statbuf = *st;
+	if (lstream->v_size != (uoff_t)-1)
+		stream->statbuf.st_size = lstream->v_size;
+	return &stream->statbuf;
 }
 
 struct istream *i_stream_create_limit(pool_t pool, struct istream *input,
@@ -120,7 +127,7 @@
 
 	lstream->istream.read = _read;
 	lstream->istream.seek = _seek;
-	lstream->istream.get_size = _get_size;
+	lstream->istream.stat = _stat;
 
 	lstream->istream.istream.seekable = input->seekable;
 	return _i_stream_create(&lstream->istream, pool, i_stream_get_fd(input),

Index: istream-mmap.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/istream-mmap.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- istream-mmap.c	28 Mar 2005 13:06:43 -0000	1.15
+++ istream-mmap.c	29 Mar 2005 10:28:06 -0000	1.16
@@ -1,6 +1,7 @@
 /* Copyright (c) 2002-2003 Timo Sirainen */
 
 #include "lib.h"
+#include "ioloop.h"
 #include "mmap-util.h"
 #include "istream-internal.h"
 
@@ -10,7 +11,8 @@
 struct mmap_istream {
 	struct _istream istream;
 
-	int fd;
+        struct timeval fstat_cache_stamp;
+
 	void *mmap_base;
 	off_t mmap_offset;
 	size_t mmap_block_size;
@@ -25,10 +27,10 @@
 {
 	struct mmap_istream *mstream = (struct mmap_istream *) stream;
 
-	if (mstream->autoclose_fd && mstream->fd != -1) {
-		if (close(mstream->fd) < 0)
+	if (mstream->autoclose_fd && mstream->istream.fd != -1) {
+		if (close(mstream->istream.fd) < 0)
 			i_error("mmap_istream.close() failed: %m");
-		mstream->fd = -1;
+		mstream->istream.fd = -1;
 	}
 }
 
@@ -115,7 +117,7 @@
 	} else {
 		mstream->mmap_base =
 			mmap(NULL, stream->buffer_size, PROT_READ, MAP_PRIVATE,
-			     mstream->fd, mstream->mmap_offset);
+			     stream->fd, mstream->mmap_offset);
 		if (mstream->mmap_base == MAP_FAILED) {
 			stream->istream.stream_errno = errno;
 			mstream->mmap_base = NULL;
@@ -157,11 +159,39 @@
 	stream->istream.v_offset = v_offset;
 }
 
-static uoff_t _get_size(struct _istream *stream)
+static void _sync(struct _istream *stream)
 {
 	struct mmap_istream *mstream = (struct mmap_istream *) stream;
 
-	return mstream->v_size;
+	i_stream_munmap(mstream);
+	stream->skip = stream->pos = stream->istream.v_offset;
+
+	mstream->fstat_cache_stamp.tv_sec = 0;
+}
+
+static int fstat_cached(struct mmap_istream *mstream)
+{
+	if (mstream->fstat_cache_stamp.tv_sec == ioloop_timeval.tv_sec &&
+	    mstream->fstat_cache_stamp.tv_usec == ioloop_timeval.tv_usec)
+		return 0;
+
+	if (fstat(mstream->istream.fd, &mstream->istream.statbuf) < 0) {
+		i_error("mmap_istream.fstat() failed: %m");
+		return -1;
+	}
+
+	mstream->fstat_cache_stamp = ioloop_timeval;
+	return 0;
+}
+
+static const struct stat *_stat(struct _istream *stream)
+{
+	struct mmap_istream *mstream = (struct mmap_istream *) stream;
+
+	if (fstat_cached(mstream) < 0)
+		return NULL;
+
+	return &stream->statbuf;
 }
 
 struct istream *i_stream_create_mmap(int fd, pool_t pool, size_t block_size,
@@ -187,7 +217,6 @@
 	}
 
 	mstream = p_new(pool, struct mmap_istream, 1);
-	mstream->fd = fd;
         _set_max_buffer_size(&mstream->istream.iostream, block_size);
 	mstream->autoclose_fd = autoclose_fd;
 	mstream->v_size = v_size;
@@ -198,7 +227,8 @@
 
 	mstream->istream.read = _read;
 	mstream->istream.seek = _seek;
-	mstream->istream.get_size = _get_size;
+	mstream->istream.sync = _sync;
+	mstream->istream.stat = _stat;
 
 	istream = _i_stream_create(&mstream->istream, pool, fd, start_offset);
 	istream->mmaped = TRUE;

Index: istream.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/istream.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- istream.c	28 Mar 2005 22:35:12 -0000	1.27
+++ istream.c	29 Mar 2005 10:28:07 -0000	1.28
@@ -1,6 +1,7 @@
 /* Copyright (c) 2002-2003 Timo Sirainen */
 
 #include "lib.h"
+#include "ioloop.h"
 #include "str.h"
 #include "istream-internal.h"
 
@@ -90,11 +91,19 @@
 	_stream->seek(_stream, v_offset);
 }
 
-uoff_t i_stream_get_size(struct istream *stream)
+void i_stream_sync(struct istream *stream)
 {
 	struct _istream *_stream = stream->real_stream;
 
-	return _stream->get_size(_stream);
+	if (!stream->closed && _stream->sync != NULL)
+		_stream->sync(_stream);
+}
+
+const struct stat *i_stream_stat(struct istream *stream)
+{
+	struct _istream *_stream = stream->real_stream;
+
+	return _stream->stat(_stream);
 }
 
 int i_stream_have_bytes_left(struct istream *stream)
@@ -234,6 +243,12 @@
 	_stream->abs_start_offset = abs_start_offset;
 	_stream->istream.real_stream = _stream;
 
+	memset(&_stream->statbuf, 0, sizeof(_stream->statbuf));
+	_stream->statbuf.st_size = -1;
+	_stream->statbuf.st_atime =
+		_stream->statbuf.st_mtime =
+		_stream->statbuf.st_ctime = ioloop_time;
+
 	_io_stream_init(pool, &_stream->iostream);
 	return &_stream->istream;
 }

Index: istream.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/istream.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- istream.h	28 Mar 2005 22:35:12 -0000	1.16
+++ istream.h	29 Mar 2005 10:28:07 -0000	1.17
@@ -35,6 +35,9 @@
 /* Mark the stream closed. Any reads after this will return -1. The data
    already read can still be used. */
 void i_stream_close(struct istream *stream);
+/* Sync the stream with the underlying backend, ie. if a file has been
+   modified, flush any cached data. */
+void i_stream_sync(struct istream *stream);
 
 /* Change the maximum size for stream's input buffer to grow. Useful only
    for buffered streams (currently only file). */
@@ -49,8 +52,10 @@
 /* Seek to specified position from beginning of file. Never fails, the next
    read tells if it was successful. This works only for files. */
 void i_stream_seek(struct istream *stream, uoff_t v_offset);
-/* Returns size of the stream, or (uoff_t)-1 if unknown */
-uoff_t i_stream_get_size(struct istream *stream);
+/* Returns struct stat, or NULL if error. As the underlying stream may not be
+   a file, only some of the fields might be set, others would be zero.
+   st_size is always set, and if it's not known, it's -1. */
+const struct stat *i_stream_stat(struct istream *stream);
 /* Returns TRUE if there are any bytes left to be read or in buffer. */
 int i_stream_have_bytes_left(struct istream *stream);
 

Index: ostream-file.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ostream-file.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- ostream-file.c	27 Mar 2005 13:51:54 -0000	1.45
+++ ostream-file.c	29 Mar 2005 10:28:07 -0000	1.46
@@ -636,12 +636,19 @@
 static off_t _send_istream(struct _ostream *outstream, struct istream *instream)
 {
 	struct file_ostream *foutstream = (struct file_ostream *)outstream;
+	const struct stat *st;
 	uoff_t in_size;
 	off_t ret;
 	int in_fd, overlapping;
 
+	st = i_stream_stat(instream);
+	if (st == NULL) {
+		outstream->ostream.stream_errno = instream->stream_errno;
+		return -1;
+	}
+
 	in_fd = i_stream_get_fd(instream);
-	in_size = i_stream_get_size(instream);
+	in_size = st->st_size;
 	i_assert(instream->v_offset <= in_size);
 
 	outstream->ostream.stream_errno = 0;



More information about the dovecot-cvs mailing list