changeset 5849:a9df50952600 HEAD

Added support for resetting index.
author Timo Sirainen <tss@iki.fi>
date Sun, 01 Jul 2007 01:05:26 +0300
parents 064aa8ff69c2
children f8caf3c6a5a7
files src/lib-index/mail-index-sync-update.c src/lib-index/mail-index-sync.c src/lib-index/mail-index-transaction-private.h src/lib-index/mail-index-transaction.c src/lib-index/mail-index-view-sync.c src/lib-index/mail-index-write.c src/lib-index/mail-index.h src/lib-index/mail-transaction-log-append.c src/lib-index/mail-transaction-log-file.c src/lib-index/mail-transaction-log-private.h src/lib-index/mail-transaction-log-view.c src/lib-index/mail-transaction-log.c src/lib-index/mail-transaction-log.h
diffstat 13 files changed, 196 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-index-sync-update.c	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-index-sync-update.c	Sun Jul 01 01:05:26 2007 +0300
@@ -697,7 +697,7 @@
 	uint32_t prev_seq;
 	uoff_t start_offset, prev_offset;
 	int ret;
-	bool had_dirty;
+	bool had_dirty, reset;
 
 	i_assert(index->map == map || type == MAIL_INDEX_SYNC_HANDLER_VIEW);
 
@@ -725,7 +725,7 @@
 	view = mail_index_view_open_with_map(index, map);
 	ret = mail_transaction_log_view_set(view->log_view,
 					    map->hdr.log_file_seq, start_offset,
-					    (uint32_t)-1, (uoff_t)-1);
+					    (uint32_t)-1, (uoff_t)-1, &reset);
 	if (ret <= 0) {
 		if (force && ret == 0) {
 			/* the seq/offset is probably broken */
@@ -758,6 +758,15 @@
 	}
 
 	mail_index_sync_map_init(&sync_map_ctx, view, type);
+	if (reset) {
+		/* Reset the entire index. Leave only indexid and
+		   log_file_seq. */
+		mail_transaction_log_view_get_prev_pos(view->log_view,
+						       &prev_seq, &prev_offset);
+		map = mail_index_map_alloc(index);
+		map->hdr.log_file_seq = prev_seq;
+		mail_index_sync_replace_map(&sync_map_ctx, map);
+	}
 	map = NULL;
 
 	/* FIXME: when transaction sync lock is removed, we'll need to handle
--- a/src/lib-index/mail-index-sync.c	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-index-sync.c	Sun Jul 01 01:05:26 2007 +0300
@@ -308,13 +308,14 @@
 {
 	uint32_t log_seq;
 	uoff_t log_offset;
+	bool reset;
 	int ret;
 
 	mail_transaction_log_get_head(view->index->log, &log_seq, &log_offset);
 
 	ret = mail_transaction_log_view_set(view->log_view,
                                             start_file_seq, start_file_offset,
-					    log_seq, log_offset);
+					    log_seq, log_offset, &reset);
 	if (ret <= 0) {
 		/* either corrupted or the file was deleted for
 		   some reason. either way, we can't go forward */
--- a/src/lib-index/mail-index-transaction-private.h	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-index-transaction-private.h	Sun Jul 01 01:05:26 2007 +0300
@@ -25,6 +25,8 @@
 	struct mail_index_transaction_vfuncs v;
 	struct mail_index_view *view;
 
+	/* NOTE: If you add anything new, remember to update
+	   mail_index_transaction_reset() to reset it. */
         ARRAY_DEFINE(appends, struct mail_index_record);
 	uint32_t first_new_seq, last_new_seq;
 
@@ -55,10 +57,12 @@
 	unsigned int sync_transaction:1;
 	unsigned int hide_transaction:1;
 	unsigned int no_appends:1;
+	unsigned int external:1;
+
 	unsigned int appends_nonsorted:1;
-	unsigned int external:1;
 	unsigned int pre_hdr_changed:1;
 	unsigned int post_hdr_changed:1;
+	unsigned int reset:1;
 	unsigned int log_updates:1;
 };
 
--- a/src/lib-index/mail-index-transaction.c	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-index-transaction.c	Sun Jul 01 01:05:26 2007 +0300
@@ -77,6 +77,7 @@
 	t->appends_nonsorted = FALSE;
 	t->pre_hdr_changed = FALSE;
 	t->post_hdr_changed = FALSE;
+	t->reset = FALSE;
 	t->log_updates = FALSE;
 }
 
@@ -1039,6 +1040,14 @@
 	t->log_updates = TRUE;
 }
 
+void mail_index_reset(struct mail_index_transaction *t)
+{
+	mail_index_transaction_reset(t);
+
+	t->reset = TRUE;
+	t->log_updates = TRUE;
+}
+
 struct mail_index_transaction_vfuncs trans_vfuncs = {
 	_mail_index_transaction_commit,
 	_mail_index_transaction_rollback
--- a/src/lib-index/mail-index-view-sync.c	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-index-view-sync.c	Sun Jul 01 01:05:26 2007 +0300
@@ -87,27 +87,53 @@
 	return 0;
 }
 
-static int view_sync_set_log_view_range(struct mail_index_view *view)
+static int
+view_sync_set_log_view_range(struct mail_index_view *view, bool sync_expunges)
 {
 	const struct mail_index_header *hdr = &view->index->map->hdr;
+	uint32_t start_seq, end_seq;
+	uoff_t start_offset, end_offset;
+	bool reset;
 	int ret;
 
-	/* the view begins from the first non-synced transaction */
-	ret = mail_transaction_log_view_set(view->log_view,
-					    view->log_file_expunge_seq,
-					    view->log_file_expunge_offset,
-					    hdr->log_file_seq,
-					    hdr->log_file_head_offset);
-	if (ret <= 0) {
-		if (ret == 0) {
-			/* FIXME: use the new index to get needed changes */
+	start_seq = view->log_file_expunge_seq;
+	start_offset = view->log_file_expunge_offset;
+	end_seq = hdr->log_file_seq;
+	end_offset = hdr->log_file_head_offset;
+
+	for (;;) {
+		/* the view begins from the first non-synced transaction */
+		ret = mail_transaction_log_view_set(view->log_view,
+						    start_seq, start_offset,
+						    end_seq, end_offset,
+						    &reset);
+		if (ret <= 0) {
+			if (ret < 0)
+				return -1;
+
+			/* FIXME: use the new index to get needed
+			   changes */
 			mail_index_set_error(view->index,
 				"Transaction log got desynced for index %s",
 				view->index->filepath);
 			view->inconsistent = TRUE;
+			return -1;
 		}
-		return -1;
+
+		if (!reset || sync_expunges)
+			break;
+
+		/* we can't do this. sync only up to reset. */
+		mail_transaction_log_view_get_prev_pos(view->log_view,
+						       &end_seq, &end_offset);
+		end_seq--; end_offset = (uoff_t)-1;
+		if (end_seq < start_seq) {
+			/* we have only this reset log */
+			mail_transaction_log_view_clear(view->log_view);
+			break;
+		}
 	}
+
 	return 0;
 }
 
@@ -121,7 +147,7 @@
 	unsigned int count;
 	int ret;
 
-	if (view_sync_set_log_view_range(view) < 0)
+	if (view_sync_set_log_view_range(view, TRUE) < 0)
 		return -1;
 
 	/* get a list of expunge transactions. there may be some that we have
@@ -196,6 +222,7 @@
 	struct mail_index_view_sync_ctx *ctx;
 	struct mail_index_map *map;
 	ARRAY_TYPE(seq_range) expunges = ARRAY_INIT;
+	bool sync_expunges;
 
 	i_assert(!view->syncing);
 	i_assert(view->transactions == 0);
@@ -203,13 +230,14 @@
 	if (mail_index_view_lock_head(view) < 0)
 		return -1;
 
-	if ((flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) == 0) {
+	sync_expunges = (flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) == 0;
+	if (sync_expunges) {
 		/* get list of all expunges first */
 		if (view_sync_get_expunges(view, &expunges) < 0)
 			return -1;
 	}
 
-	if (view_sync_set_log_view_range(view) < 0) {
+	if (view_sync_set_log_view_range(view, sync_expunges) < 0) {
 		if (array_is_created(&expunges))
 			array_free(&expunges);
 		return -1;
@@ -222,7 +250,7 @@
 	mail_index_sync_map_init(&ctx->sync_map_ctx, view,
 				 MAIL_INDEX_SYNC_HANDLER_VIEW);
 
-	if ((flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) == 0) {
+	if (sync_expunges) {
 		view->sync_new_map = view->index->map;
 		view->sync_new_map->refcount++;
 
@@ -590,11 +618,7 @@
 #endif
 
 	/* set log view to empty range so unneeded memory gets freed */
-	(void)mail_transaction_log_view_set(view->log_view,
-					    view->log_file_head_seq,
-					    view->log_file_head_offset,
-					    view->log_file_head_seq,
-					    view->log_file_head_offset);
+	mail_transaction_log_view_clear(view->log_view);
 
 	if (array_is_created(&ctx->expunges))
 		array_free(&ctx->expunges);
--- a/src/lib-index/mail-index-write.c	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-index-write.c	Sun Jul 01 01:05:26 2007 +0300
@@ -214,5 +214,5 @@
 	if (want_rotate &&
 	    hdr->log_file_seq == index->log->head->hdr.file_seq &&
 	    hdr->log_file_tail_offset == hdr->log_file_head_offset)
-		(void)mail_transaction_log_rotate(index->log);
+		(void)mail_transaction_log_rotate(index->log, FALSE);
 }
--- a/src/lib-index/mail-index.h	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-index.h	Sun Jul 01 01:05:26 2007 +0300
@@ -323,6 +323,9 @@
 				   uint32_t seq1, uint32_t seq2,
 				   enum modify_type modify_type,
 				   enum mail_flags flags);
+/* Reset the index before committing this transaction. This is usually done
+   only when UIDVALIDITY changes. */
+void mail_index_reset(struct mail_index_transaction *t);
 
 /* Lookup a keyword, returns TRUE if found, FALSE if not. If autocreate is
    TRUE, the keyword is automatically created and TRUE is always returned. */
--- a/src/lib-index/mail-transaction-log-append.c	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-transaction-log-append.c	Sun Jul 01 01:05:26 2007 +0300
@@ -173,7 +173,8 @@
 	uint32_t idx;
 	unsigned int count;
 
-	if (!mail_index_map_get_ext_idx(t->view->map, ext_id, &idx)) {
+	if (t->reset ||
+	    !mail_index_map_get_ext_idx(t->view->map, ext_id, &idx)) {
 		/* new extension */
 		idx = (uint32_t)-1;
 	}
@@ -410,6 +411,14 @@
 	index = mail_index_view_get_index(view);
 	log = index->log;
 
+	if (t->reset) {
+		/* Reset the whole index, preserving only indexid. Begin by
+		   rotating the log. We don't care if we skip some non-synced
+		   transactions. */
+		if (mail_transaction_log_rotate(log, TRUE) < 0)
+			return -1;
+	}
+
 	if (!index->log_locked) {
 		/* update sync_offset */
 		if (mail_transaction_log_file_map(log->head,
--- a/src/lib-index/mail-transaction-log-file.c	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-transaction-log-file.c	Sun Jul 01 01:05:26 2007 +0300
@@ -429,7 +429,8 @@
 
 static int
 mail_transaction_log_file_create2(struct mail_transaction_log_file *file,
-				  int new_fd, struct dotlock **dotlock)
+				  int new_fd, bool reset,
+				  struct dotlock **dotlock)
 {
 	struct mail_index *index = file->log->index;
 	struct stat st;
@@ -443,7 +444,9 @@
 	   if we go and open()+close() the file and we had it already opened,
 	   its locks are lost. so we use stat() to check if the file has been
 	   recreated, although it almost never is. */
-	if (nfs_safe_stat(file->filepath, &st) < 0) {
+	if (reset)
+		rename_existing = FALSE;
+	else if (nfs_safe_stat(file->filepath, &st) < 0) {
 		if (errno != ENOENT) {
 			mail_index_file_set_syscall_error(index, file->filepath,
 							  "stat()");
@@ -487,6 +490,11 @@
 	if (mail_transaction_log_init_hdr(file->log, &file->hdr) < 0)
 		return -1;
 
+	if (reset) {
+		file->hdr.prev_file_seq = 0;
+		file->hdr.prev_file_offset = 0;
+	}
+
 	if (write_full(new_fd, &file->hdr, sizeof(file->hdr)) < 0) {
 		mail_index_file_set_syscall_error(index, file->filepath,
 						  "write_full()");
@@ -533,7 +541,8 @@
 	return 0;
 }
 
-int mail_transaction_log_file_create(struct mail_transaction_log_file *file)
+int mail_transaction_log_file_create(struct mail_transaction_log_file *file,
+				     bool reset)
 {
 	struct mail_index *index = file->log->index;
 	struct dotlock *dotlock;
@@ -565,7 +574,7 @@
 
         /* either fd gets used or the dotlock gets deleted and returned fd
            is for the existing file */
-        if (mail_transaction_log_file_create2(file, fd, &dotlock) < 0) {
+        if (mail_transaction_log_file_create2(file, fd, reset, &dotlock) < 0) {
 		if (dotlock != NULL)
 			(void)file_dotlock_delete(&dotlock);
 		return -1;
--- a/src/lib-index/mail-transaction-log-private.h	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-transaction-log-private.h	Sun Jul 01 01:05:26 2007 +0300
@@ -80,7 +80,8 @@
 
 int mail_transaction_log_file_open(struct mail_transaction_log_file *file,
 				   bool check_existing);
-int mail_transaction_log_file_create(struct mail_transaction_log_file *file);
+int mail_transaction_log_file_create(struct mail_transaction_log_file *file,
+				     bool reset);
 int mail_transaction_log_file_lock(struct mail_transaction_log_file *file);
 
 int mail_transaction_log_find_file(struct mail_transaction_log *log,
@@ -97,7 +98,7 @@
 void mail_transaction_logs_clean(struct mail_transaction_log *log);
 
 bool mail_transaction_log_want_rotate(struct mail_transaction_log *log);
-int mail_transaction_log_rotate(struct mail_transaction_log *log);
+int mail_transaction_log_rotate(struct mail_transaction_log *log, bool reset);
 int mail_transaction_log_lock_head(struct mail_transaction_log *log);
 void mail_transaction_log_file_unlock(struct mail_transaction_log_file *file);
 
--- a/src/lib-index/mail-transaction-log-view.c	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-transaction-log-view.c	Sun Jul 01 01:05:26 2007 +0300
@@ -88,10 +88,10 @@
 		view->log = NULL;
 }
 
-int
-mail_transaction_log_view_set(struct mail_transaction_log_view *view,
-			      uint32_t min_file_seq, uoff_t min_file_offset,
-			      uint32_t max_file_seq, uoff_t max_file_offset)
+int mail_transaction_log_view_set(struct mail_transaction_log_view *view,
+				  uint32_t min_file_seq, uoff_t min_file_offset,
+				  uint32_t max_file_seq, uoff_t max_file_offset,
+				  bool *reset_r)
 {
 	struct mail_transaction_log_file *file, *const *files;
 	uoff_t start_offset, end_offset;
@@ -102,6 +102,8 @@
 	i_assert(view->log != NULL);
 	i_assert(min_file_seq <= max_file_seq);
 
+	*reset_r = FALSE;
+
 	if (view->log == NULL) {
 		/* transaction log is closed already. this log view shouldn't
 		   be used anymore. */
@@ -138,21 +140,6 @@
 		}
 	}
 
-	/* find the oldest log file first. */
-	ret = mail_transaction_log_find_file(view->log, min_file_seq, &file);
-	if (ret <= 0)
-		return ret;
-
-	if (min_file_offset == 0) {
-		/* beginning of the file */
-		min_file_offset = file->hdr.hdr_size;
-		if (max_file_offset == 0 && min_file_seq == max_file_seq) {
-			/* we don't actually want to show anything */
-			max_file_offset = min_file_offset;
-		}
-	}
-	i_assert(min_file_offset >= file->hdr.hdr_size);
-
 	if (min_file_seq == max_file_seq && min_file_offset > max_file_offset) {
 		/* log file offset is probably corrupted in the index file. */
 		mail_transaction_log_view_set_corrupted(view,
@@ -162,11 +149,8 @@
 		return -1;
 	}
 
-	view->tail = file;
-	view->head = file;
-
-	for (seq = min_file_seq+1; seq <= max_file_seq; seq++) {
-		file = file->next;
+	view->tail = view->head = file = NULL;
+	for (seq = min_file_seq; seq <= max_file_seq; seq++) {
 		if (file == NULL || file->hdr.file_seq != seq) {
 			/* see if we could find the missing file */
 			ret = mail_transaction_log_find_file(view->log,
@@ -181,18 +165,50 @@
 		}
 
 		if (file == NULL || file->hdr.file_seq != seq) {
-			if (file == NULL && max_file_seq == (uint32_t)-1) {
+			if (file == NULL && max_file_seq == (uint32_t)-1 &&
+			    view->head == view->log->head) {
 				/* we just wanted to sync everything */
 				i_assert(max_file_offset == (uoff_t)-1);
 				max_file_seq = seq-1;
 				break;
 			}
+			/* if any of the found files reset the index,
+			   ignore any missing files up to it */
+			file = view->tail != NULL ? view->tail :
+				view->log->files;
+			for (;; file = file->next) {
+				if (file == NULL ||
+				    file->hdr.file_seq > max_file_seq) {
+					/* missing files in the middle */
+					return 0;
+				}
 
-			/* missing files in the middle */
-			return 0;
+				if (file->hdr.file_seq >= seq &&
+				    file->hdr.prev_file_seq == 0) {
+					/* we can ignore the missing file */
+					break;
+				}
+			}
+			seq = file->hdr.file_seq;
+			view->tail = NULL;
+		} 
+
+		if (view->tail == NULL)
+			view->tail = file;
+		view->head = file;
+		file = file->next;
+	}
+
+	if (min_file_offset == 0) {
+		/* beginning of the file */
+		min_file_offset = view->tail->hdr.hdr_size;
+		if (min_file_offset > max_file_offset &&
+		    min_file_seq == max_file_seq) {
+			/* we don't actually want to show anything */
+			max_file_offset = min_file_offset;
 		}
-		view->head = file;
 	}
+	i_assert(min_file_offset >= view->tail->hdr.hdr_size);
 
 	/* we have all of them. update refcounts. */
 	mail_transaction_log_view_unref_all(view);
@@ -206,6 +222,10 @@
 			break;
 	}
 
+	view->cur = view->tail;
+	view->cur_offset = view->cur->hdr.file_seq == min_file_seq ?
+		min_file_offset : view->cur->hdr.hdr_size;
+
 	/* Map the files only after we've found them all. Otherwise if we map
 	   one file and then another file just happens to get rotated, we could
 	   include both files in the view but skip the last transactions from
@@ -225,6 +245,19 @@
 						    end_offset);
 		if (ret <= 0)
 			return ret;
+
+		if (file->hdr.prev_file_seq == 0) {
+			/* this file resets the index.
+			   don't bother reading the others. */
+			if (view->cur != file ||
+			    view->cur_offset == file->hdr.hdr_size) {
+				view->cur = file;
+				view->cur_offset = file->hdr.hdr_size;
+				*reset_r = TRUE;
+				break;
+			}
+			i_assert(i == 1);
+		}
 	}
 
 	i_assert(max_file_seq == (uint32_t)-1 ||
@@ -232,11 +265,8 @@
 	i_assert(max_file_offset == (uoff_t)-1 ||
 		 max_file_offset <= view->head->sync_offset);
 
-	view->prev_file_seq = 0;
-	view->prev_file_offset = 0;
-
-	view->cur = view->tail;
-	view->cur_offset = min_file_offset;
+	view->prev_file_seq = view->cur->hdr.file_seq;
+	view->prev_file_offset = view->cur_offset;
 
 	view->min_file_seq = min_file_seq;
 	view->min_file_offset = min_file_offset;
@@ -245,10 +275,23 @@
 	view->broken = FALSE;
 
 	i_assert(view->cur_offset <= view->cur->sync_offset);
-	i_assert(view->cur->hdr.file_seq == min_file_seq);
 	return 1;
 }
 
+void mail_transaction_log_view_clear(struct mail_transaction_log_view *view)
+{
+	mail_transaction_log_view_unref_all(view);
+
+	view->cur = view->head = view->tail = NULL;
+
+	view->min_file_seq = view->max_file_seq = 0;
+	view->min_file_offset = view->max_file_offset = 0;
+	view->cur_offset = 0;
+
+	view->prev_file_seq = 0;
+	view->prev_file_offset = 0;
+}
+
 void
 mail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view,
 				       uint32_t *file_seq_r,
--- a/src/lib-index/mail-transaction-log.c	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-transaction-log.c	Sun Jul 01 01:05:26 2007 +0300
@@ -101,7 +101,7 @@
 		mail_transaction_log_file_free(&log->open_file);
 	}
 
-	if (mail_transaction_log_file_create(file) < 0)
+	if (mail_transaction_log_file_create(file, FALSE) < 0)
 		mail_transaction_log_file_free(&file);
 
 	mail_transaction_log_set_head(log, file);
@@ -183,7 +183,7 @@
 	return LOG_WANT_ROTATE(log->head);
 }
 
-int mail_transaction_log_rotate(struct mail_transaction_log *log)
+int mail_transaction_log_rotate(struct mail_transaction_log *log, bool reset)
 {
 	struct mail_transaction_log_file *file;
 	const char *path = log->head->filepath;
@@ -191,9 +191,13 @@
 
 	i_assert(log->head->locked);
 
-	if (MAIL_INDEX_IS_IN_MEMORY(log->index))
+	if (MAIL_INDEX_IS_IN_MEMORY(log->index)) {
 		file = mail_transaction_log_file_alloc_in_memory(log);
-	else {
+		if (reset) {
+			file->hdr.prev_file_seq = 0;
+			file->hdr.prev_file_offset = 0;
+		}
+	} else {
                 /* we're locked, we shouldn't need to worry about ESTALE
                    problems in here. */
 		if (fstat(log->head->fd, &st) < 0) {
@@ -209,7 +213,7 @@
 		file->last_mtime = st.st_mtime;
 		file->last_size = st.st_size;
 
-		if (mail_transaction_log_file_create(file) < 0) {
+		if (mail_transaction_log_file_create(file, reset) < 0) {
 			mail_transaction_log_file_free(&file);
 			return -1;
 		}
--- a/src/lib-index/mail-transaction-log.h	Sun Jul 01 01:04:57 2007 +0300
+++ b/src/lib-index/mail-transaction-log.h	Sun Jul 01 01:05:26 2007 +0300
@@ -146,11 +146,15 @@
 mail_transaction_log_view_open(struct mail_transaction_log *log);
 void mail_transaction_log_view_close(struct mail_transaction_log_view **view);
 
-/* Set view boundaries. Returns -1 if error, 0 if files are lost, 1 if ok. */
-int
-mail_transaction_log_view_set(struct mail_transaction_log_view *view,
-			      uint32_t min_file_seq, uoff_t min_file_offset,
-			      uint32_t max_file_seq, uoff_t max_file_offset);
+/* Set view boundaries. Returns -1 if error, 0 if files are lost, 1 if ok.
+   reset_r=TRUE if the whole index should be reset before applying any
+   changes. */
+int mail_transaction_log_view_set(struct mail_transaction_log_view *view,
+				  uint32_t min_file_seq, uoff_t min_file_offset,
+				  uint32_t max_file_seq, uoff_t max_file_offset,
+				  bool *reset_r);
+/* Clear the view. */
+void mail_transaction_log_view_clear(struct mail_transaction_log_view *view);
 
 /* Read next transaction record from current position. The position is updated.
    Returns -1 if error, 0 if we're at end of the view, 1 if ok. */