dovecot-1.2: mbox: Don't cache mbox state after it has been unlo...

dovecot at dovecot.org dovecot at dovecot.org
Sat Dec 13 12:41:51 EET 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/e7b0a099c33d
changeset: 8529:e7b0a099c33d
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Dec 13 11:21:21 2008 +0200
description:
mbox: Don't cache mbox state after it has been unlocked.

diffstat:

5 files changed, 74 insertions(+), 23 deletions(-)
src/lib-storage/index/mbox/istream-raw-mbox.c |   49 ++++++++++++++++++++++---
src/lib-storage/index/mbox/istream-raw-mbox.h |    4 ++
src/lib-storage/index/mbox/mbox-file.c        |   34 ++++++++---------
src/lib-storage/index/mbox/mbox-lock.c        |    7 +++
src/lib-storage/index/mbox/mbox-mail.c        |    3 +

diffs (265 lines):

diff -r 1a9e14718bd6 -r e7b0a099c33d src/lib-storage/index/mbox/istream-raw-mbox.c
--- a/src/lib-storage/index/mbox/istream-raw-mbox.c	Sat Dec 13 10:36:13 2008 +0200
+++ b/src/lib-storage/index/mbox/istream-raw-mbox.c	Sat Dec 13 11:21:21 2008 +0200
@@ -15,8 +15,11 @@ struct raw_mbox_istream {
 	uoff_t from_offset, hdr_offset, body_offset, mail_size;
 	uoff_t input_peak_offset;
 
+	unsigned int locked:1;
+	unsigned int seeked:1;
 	unsigned int crlf_ending:1;
 	unsigned int corrupted:1;
+	unsigned int mail_size_forced:1;
 	unsigned int eof:1;
 	unsigned int header_missing_eoh:1;
 };
@@ -144,6 +147,7 @@ static ssize_t i_stream_raw_mbox_read(st
 	int eoh_char, tz;
 	bool crlf_ending = FALSE;
 
+	i_assert(rstream->seeked);
 	i_assert(stream->istream.v_offset >= rstream->from_offset);
 
 	if (stream->istream.eof)
@@ -315,8 +319,9 @@ static ssize_t i_stream_raw_mbox_read(st
 		/* istream_raw_mbox_set_next_offset() used invalid
 		   cached next_offset? */
 		i_error("Next message unexpectedly lost from mbox file "
-			"%s at %"PRIuUOFF_T, rstream->path,
-			rstream->hdr_offset + rstream->mail_size);
+			"%s at %"PRIuUOFF_T" (%s)", rstream->path,
+			rstream->hdr_offset + rstream->mail_size,
+			rstream->mail_size_forced ? "cached" : "noncached");
 		rstream->eof = TRUE;
 		rstream->corrupted = TRUE;
 		rstream->istream.istream.stream_errno = EINVAL;
@@ -455,6 +460,8 @@ uoff_t istream_raw_mbox_get_start_offset
 	struct raw_mbox_istream *rstream =
 		(struct raw_mbox_istream *)stream->real_stream;
 
+	i_assert(rstream->seeked);
+
 	return rstream->from_offset;
 }
 
@@ -462,6 +469,8 @@ uoff_t istream_raw_mbox_get_header_offse
 {
 	struct raw_mbox_istream *rstream =
 		(struct raw_mbox_istream *)stream->real_stream;
+
+	i_assert(rstream->seeked);
 
 	if (rstream->hdr_offset == rstream->from_offset)
 		(void)i_stream_raw_mbox_read(&rstream->istream);
@@ -481,6 +490,8 @@ uoff_t istream_raw_mbox_get_body_offset(
 		(struct raw_mbox_istream *)stream->real_stream;
 	uoff_t offset;
 	size_t pos;
+
+	i_assert(rstream->seeked);
 
 	if (rstream->body_offset != (uoff_t)-1)
 		return rstream->body_offset;
@@ -516,6 +527,7 @@ uoff_t istream_raw_mbox_get_body_size(st
 	size_t size;
 	uoff_t old_offset, body_size, next_body_offset;
 
+	i_assert(rstream->seeked);
 	i_assert(rstream->hdr_offset != (uoff_t)-1);
 	i_assert(rstream->body_offset != (uoff_t)-1);
 
@@ -569,6 +581,8 @@ time_t istream_raw_mbox_get_received_tim
 	struct raw_mbox_istream *rstream =
 		(struct raw_mbox_istream *)stream->real_stream;
 
+	i_assert(rstream->seeked);
+
 	if (rstream->received_time == (time_t)-1)
 		(void)i_stream_raw_mbox_read(&rstream->istream);
 	return rstream->received_time;
@@ -579,6 +593,8 @@ const char *istream_raw_mbox_get_sender(
 	struct raw_mbox_istream *rstream =
 		(struct raw_mbox_istream *)stream->real_stream;
 
+	i_assert(rstream->seeked);
+
 	if (rstream->sender == NULL)
 		(void)i_stream_raw_mbox_read(&rstream->istream);
 	return rstream->sender == NULL ? "" : rstream->sender;
@@ -588,6 +604,8 @@ bool istream_raw_mbox_has_crlf_ending(st
 {
 	struct raw_mbox_istream *rstream =
 		(struct raw_mbox_istream *)stream->real_stream;
+
+	i_assert(rstream->seeked);
 
 	return rstream->crlf_ending;
 }
@@ -627,17 +645,21 @@ int istream_raw_mbox_seek(struct istream
 		(struct raw_mbox_istream *)stream->real_stream;
 	bool check;
 
+	i_assert(rstream->locked);
+
 	rstream->corrupted = FALSE;
 	rstream->eof = FALSE;
 	rstream->istream.istream.eof = FALSE;
 
-	if (rstream->mail_size != (uoff_t)-1 &&
+	/* if seeked is FALSE, we unlocked in the middle. don't try to use
+	   any cached state then. */
+	if (rstream->mail_size != (uoff_t)-1 && rstream->seeked &&
 	    rstream->hdr_offset + rstream->mail_size == offset) {
 		istream_raw_mbox_next(stream, (uoff_t)-1);
 		return 0;
 	}
 
-	if (offset == rstream->from_offset) {
+	if (offset == rstream->from_offset && rstream->seeked) {
 		/* back to beginning of current message */
 		offset = rstream->hdr_offset;
 		check = offset == 0;
@@ -657,6 +679,7 @@ int istream_raw_mbox_seek(struct istream
 		rstream->hdr_offset = offset;
 		check = TRUE;
 	}
+	rstream->seeked = TRUE;
 
 	i_stream_seek_mark(stream, offset);
 	i_stream_seek_mark(rstream->istream.parent, offset);
@@ -673,6 +696,7 @@ void istream_raw_mbox_set_next_offset(st
 
 	i_assert(rstream->hdr_offset != (uoff_t)-1);
 
+	rstream->mail_size_forced = TRUE;
 	rstream->mail_size = offset - rstream->hdr_offset;
 }
 
@@ -691,3 +715,20 @@ bool istream_raw_mbox_is_corrupted(struc
 
 	return rstream->corrupted;
 }
+
+void istream_raw_mbox_set_locked(struct istream *stream)
+{
+	struct raw_mbox_istream *rstream =
+		(struct raw_mbox_istream *)stream->real_stream;
+
+	rstream->locked = TRUE;
+}
+
+void istream_raw_mbox_set_unlocked(struct istream *stream)
+{
+	struct raw_mbox_istream *rstream =
+		(struct raw_mbox_istream *)stream->real_stream;
+
+	rstream->locked = FALSE;
+	rstream->seeked = FALSE;
+}
diff -r 1a9e14718bd6 -r e7b0a099c33d src/lib-storage/index/mbox/istream-raw-mbox.h
--- a/src/lib-storage/index/mbox/istream-raw-mbox.h	Sat Dec 13 10:36:13 2008 +0200
+++ b/src/lib-storage/index/mbox/istream-raw-mbox.h	Sat Dec 13 11:21:21 2008 +0200
@@ -46,5 +46,9 @@ bool istream_raw_mbox_is_eof(struct istr
 bool istream_raw_mbox_is_eof(struct istream *stream);
 /* Returns TRUE if we've noticed corruption in used offsets/sizes. */
 bool istream_raw_mbox_is_corrupted(struct istream *stream);
+/* Change stream's locking state. We'll assert-crash if stream is tried to be
+   read while it's unlocked. */
+void istream_raw_mbox_set_locked(struct istream *stream);
+void istream_raw_mbox_set_unlocked(struct istream *stream);
 
 #endif
diff -r 1a9e14718bd6 -r e7b0a099c33d src/lib-storage/index/mbox/mbox-file.c
--- a/src/lib-storage/index/mbox/mbox-file.c	Sat Dec 13 10:36:13 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-file.c	Sat Dec 13 11:21:21 2008 +0200
@@ -66,28 +66,26 @@ int mbox_file_open_stream(struct mbox_ma
 	if (mbox->mbox_file_stream != NULL) {
 		/* read-only mbox stream */
 		i_assert(mbox->mbox_fd == -1 && mbox->mbox_readonly);
-
-		mbox->mbox_stream =
-			i_stream_create_raw_mbox(mbox->mbox_file_stream,
-						 mbox->path);
-		return 0;
-	}
-
-	if (mbox->mbox_fd == -1) {
-		if (mbox_file_open(mbox) < 0)
-			return -1;
-	}
-
-	if (mbox->mbox_writeonly)
-		mbox->mbox_file_stream = i_stream_create_from_data(NULL, 0);
-	else {
-		mbox->mbox_file_stream =
-			i_stream_create_fd(mbox->mbox_fd,
-					   MAIL_READ_BLOCK_SIZE, FALSE);
+	} else {
+		if (mbox->mbox_fd == -1) {
+			if (mbox_file_open(mbox) < 0)
+				return -1;
+		}
+
+		if (mbox->mbox_writeonly) {
+			mbox->mbox_file_stream =
+				i_stream_create_from_data(NULL, 0);
+		} else {
+			mbox->mbox_file_stream =
+				i_stream_create_fd(mbox->mbox_fd,
+						   MAIL_READ_BLOCK_SIZE, FALSE);
+		}
 	}
 
 	mbox->mbox_stream = i_stream_create_raw_mbox(mbox->mbox_file_stream,
 						     mbox->path);
+	if (mbox->mbox_lock_type != F_UNLCK)
+		istream_raw_mbox_set_locked(mbox->mbox_stream);
 	return 0;
 }
 
diff -r 1a9e14718bd6 -r e7b0a099c33d src/lib-storage/index/mbox/mbox-lock.c
--- a/src/lib-storage/index/mbox/mbox-lock.c	Sat Dec 13 10:36:13 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-lock.c	Sat Dec 13 11:21:21 2008 +0200
@@ -5,6 +5,7 @@
 #include "nfs-workarounds.h"
 #include "mail-index-private.h"
 #include "mbox-storage.h"
+#include "istream-raw-mbox.h"
 #include "mbox-file.h"
 #include "mbox-lock.h"
 
@@ -714,6 +715,8 @@ int mbox_lock(struct mbox_mailbox *mbox,
 		mbox->mbox_excl_locks++;
 		*lock_id_r = mbox->mbox_lock_id + 1;
 	}
+	if (mbox->mbox_stream != NULL)
+		istream_raw_mbox_set_locked(mbox->mbox_stream);
 	return 1;
 }
 
@@ -759,6 +762,10 @@ int mbox_unlock(struct mbox_mailbox *mbo
 	}
 	/* all locks gone */
 
+	/* make sure we don't read the stream while unlocked */
+	if (mbox->mbox_stream != NULL)
+		istream_raw_mbox_set_unlocked(mbox->mbox_stream);
+
 	memset(&ctx, 0, sizeof(ctx));
 	ctx.mbox = mbox;
 
diff -r 1a9e14718bd6 -r e7b0a099c33d src/lib-storage/index/mbox/mbox-mail.c
--- a/src/lib-storage/index/mbox/mbox-mail.c	Sat Dec 13 10:36:13 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-mail.c	Sat Dec 13 11:21:21 2008 +0200
@@ -194,9 +194,10 @@ mbox_mail_get_next_offset(struct index_m
 	}
 
 	/* We can't really trust trans_view. The next message may already be
-	   expunged from it. Also there hdr.messages_count may be incorrect.
+	   expunged from it. Also hdr.messages_count may be incorrect there.
 	   So refresh the index to get the latest changes and get the next
 	   message's offset using a new view. */
+	i_assert(mbox->mbox_lock_type != F_UNLCK);
 	if (mbox_sync_header_refresh(mbox) < 0)
 		return -1;
 


More information about the dovecot-cvs mailing list