changeset 5285:a09da370923d HEAD

If write to transaction log fails, we may later need to truncate the file so that after the write there won't be garbage after it.
author Timo Sirainen <tss@iki.fi>
date Sun, 11 Mar 2007 19:43:10 +0200
parents 6ba1cd2580ee
children bf90ba82e2db
files src/lib-index/mail-transaction-log-append.c src/lib-index/mail-transaction-log.c
diffstat 2 files changed, 28 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-transaction-log-append.c	Sun Mar 11 19:38:09 2007 +0200
+++ b/src/lib-index/mail-transaction-log-append.c	Sun Mar 11 19:43:10 2007 +0200
@@ -426,6 +426,9 @@
 	file->first_append_size = 0;
 	append_offset = file->sync_offset;
 
+	if (file->sync_offset < file->buffer_offset)
+		file->sync_offset = file->buffer_offset;
+
 	old_hidden_syncs_count = !array_is_created(&view->syncs_hidden) ? 0 :
 		array_count(&view->syncs_hidden);
 
@@ -488,6 +491,20 @@
 					t->external);
 	}
 
+	if (ret == 0 && file->sync_offset < file->last_size) {
+		/* there is some garbage at the end of the transaction log
+		   (eg. previous write failed). remove it so reader doesn't
+		   break because of it. */
+		buffer_set_used_size(file->buffer,
+				     file->sync_offset - file->buffer_offset);
+		if (!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
+			if (ftruncate(file->fd, file->sync_offset) < 0) {
+				mail_index_file_set_syscall_error(index,
+					file->filepath, "ftruncate()");
+			}
+		}
+	}
+
 	if (ret == 0 && file->first_append_size != 0) {
 		if (!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
 			/* synced - rewrite first record's header */
--- a/src/lib-index/mail-transaction-log.c	Sun Mar 11 19:38:09 2007 +0200
+++ b/src/lib-index/mail-transaction-log.c	Sun Mar 11 19:43:10 2007 +0200
@@ -1137,8 +1137,13 @@
 		   memory, it may be just that the memory was updated
 		   after we checked the file size. */
 		if (file->locked || file->mmap_base == NULL) {
-			mail_transaction_log_file_set_corrupted(file,
-				"hdr.size too large (%u)", hdr_size);
+			if (hdr_size != 0) {
+				mail_transaction_log_file_set_corrupted(file,
+					"hdr.size too large (%u)", hdr_size);
+			} else {
+				mail_transaction_log_file_set_corrupted(file,
+					"Unexpected garbage at EOF");
+			}
 			return -1;
 		}
 	}
@@ -1201,6 +1206,8 @@
 		buffer_set_used_size(file->buffer, size);
 	} while (ret > 0 || (ret < 0 && errno == EINTR));
 
+	file->last_size = read_offset;
+
 	if (mail_transaction_log_file_sync(file) < 0)
 		return -1;
 
@@ -1265,6 +1272,8 @@
 							  "fstat()");
 			return -1;
 		}
+		file->last_size = st.st_size;
+
 		if (start_offset > (uoff_t)st.st_size) {
 			mail_transaction_log_file_set_corrupted(file,
 				"start_offset (%"PRIuUOFF_T") > file size "