if (fstat(index->fd, &st1) < 0)
return mail_index_set_syscall_error(index, "fstat()");
- if (stat(index->filepath, &st2) < 0)
- return mail_index_set_syscall_error(index, "stat()");
+ if (stat(index->filepath, &st2) < 0) {
+ mail_index_set_syscall_error(index, "stat()");
+ if (errno != ENOENT)
+ return -1;
+
+ /* lost it? recreate */
+ (void)mail_index_reset(index);
+ return -1;
+ }
if (st1.st_ino != st2.st_ino ||
!CMP_DEV_T(st1.st_dev, st2.st_dev)) {
int mail_index_write_header(struct mail_index *index,
const struct mail_index_header *hdr);
-int mail_index_create(struct mail_index *index, struct mail_index_header *hdr);
int mail_index_try_open_only(struct mail_index *index);
int mail_index_try_open(struct mail_index *index, unsigned int *lock_id_r);
int mail_index_create_tmp_file(struct mail_index *index, const char **path_r);
const void *data, size_t *data_offset);
void mail_index_set_inconsistent(struct mail_index *index);
-int mail_index_mark_corrupted(struct mail_index *index);
int mail_index_set_error(struct mail_index *index, const char *fmt, ...)
__attr_format__(2, 3);
#include "mail-index-private.h"
#include "mail-transaction-log.h"
-int mail_index_reset(struct mail_index *index)
+static int mail_index_mark_corrupted(struct mail_index *index)
{
struct mail_index_header hdr;
- if (mail_index_mark_corrupted(index) < 0)
+ if (index->readonly)
+ return 0;
+
+ /* make sure we can write the header */
+ if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
+ if (mprotect(index->map->mmap_base, sizeof(hdr),
+ PROT_READ | PROT_WRITE) < 0) {
+ mail_index_set_syscall_error(index, "mprotect()");
+ return -1;
+ }
+ }
+
+ hdr = *index->hdr;
+ hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
+ if (mail_index_write_header(index, &hdr) < 0)
return -1;
+ if (fsync(index->fd) < 0)
+ return mail_index_set_syscall_error(index, "fsync()");
+
+ mail_index_set_inconsistent(index);
+ return 0;
+}
+
+int mail_index_reset(struct mail_index *index)
+{
+ struct mail_index_header hdr;
+ uint32_t file_seq;
+ uoff_t file_offset;
+ int log_locked;
+
mail_index_header_init(&hdr);
if (hdr.indexid == index->indexid)
hdr.indexid++;
- // FIXME: close it? ..
- if (mail_index_create(index, &hdr) < 0)
+ if (mail_index_mark_corrupted(index) < 0)
return -1;
- /* reopen transaction log - FIXME: doesn't work, we have log views
- open.. */
- mail_transaction_log_close(index->log);
- index->log = mail_transaction_log_open_or_create(index);
- if (index->log == NULL) {
- /* FIXME: creates potential crashes.. */
+ log_locked = index->log_locked;
+ if (log_locked)
+ mail_transaction_log_sync_unlock(index->log);
+ mail_index_close(index);
+
+ if (mail_index_open(index, MAIL_INDEX_OPEN_FLAG_CREATE) < 0)
return -1;
+
+ if (log_locked) {
+ if (mail_transaction_log_sync_lock(index->log,
+ &file_seq, &file_offset) < 0)
+ return -1;
}
return 0;
int mail_index_view_lock(struct mail_index_view *view)
{
- if (view->inconsistent)
+ if (mail_index_view_is_inconsistent(view))
return -1;
if (view->map != view->index->map) {
int mail_index_view_is_inconsistent(struct mail_index_view *view)
{
+ if (view->index->indexid != view->indexid)
+ view->inconsistent = TRUE;
return view->inconsistent;
}
return fd;
}
-int mail_index_create(struct mail_index *index, struct mail_index_header *hdr)
+static int mail_index_create(struct mail_index *index,
+ struct mail_index_header *hdr)
{
const char *path;
uint32_t seq;
return ret;
}
-static int
-mail_index_open2(struct mail_index *index, enum mail_index_open_flags flags)
+static int mail_index_open_files(struct mail_index *index,
+ enum mail_index_open_flags flags)
{
struct mail_index_header hdr;
unsigned int lock_id = 0;
index->filepath = i_strconcat(index->dir, "/",
index->prefix, NULL);
- ret = mail_index_open2(index, flags);
+ ret = mail_index_open_files(index, flags);
if (ret <= 0)
break;
index->indexid = 0;
}
-int mail_index_mark_corrupted(struct mail_index *index)
-{
- struct mail_index_header hdr;
-
- if (index->readonly || index->hdr == NULL ||
- (index->hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0)
- return 0;
-
- /* make sure we can write the header */
- if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
- if (mprotect(index->map->mmap_base, sizeof(hdr),
- PROT_READ | PROT_WRITE) < 0) {
- mail_index_set_syscall_error(index, "mprotect()");
- return -1;
- }
- }
-
- hdr = *index->hdr;
- hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
- if (mail_index_write_header(index, &hdr) < 0)
- return -1;
-
- if (fsync(index->fd) < 0)
- return mail_index_set_syscall_error(index, "fsync()");
-
- mail_index_set_inconsistent(index);
- return 0;
-}
-
int mail_index_set_syscall_error(struct mail_index *index,
const char *function)
{
void mail_transaction_log_view_close(struct mail_transaction_log_view *view)
{
+ struct mail_transaction_log_view **p;
+
+ for (p = &view->log->views; *p != NULL; p = &(*p)->next) {
+ if (*p == view) {
+ *p = view->next;
+ break;
+ }
+ }
+
mail_transaction_log_view_unset(view);
if (view->data_buf != NULL)
buffer_free(view->data_buf);
i_free(view);
}
+void mail_transaction_log_views_close(struct mail_transaction_log *log)
+{
+ struct mail_transaction_log_view *view;
+
+ for (view = log->views; view != NULL; view = view->next)
+ 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,
i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header));
i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header));
+ if (view->log == NULL)
+ return -1;
+
ret = mail_transaction_log_file_find(view->log, min_file_seq, &file);
if (ret <= 0) {
if (ret == 0 &&
void mail_transaction_log_close(struct mail_transaction_log *log)
{
- i_assert(log->views == NULL);
+ mail_transaction_log_views_close(log);
+ log->index->log = NULL;
i_free(log);
}
if (st.st_size == file->hdr.used_size &&
file->buffer_offset <= start_offset && end_offset == (uoff_t)-1) {
/* we've seen the whole file.. do we have all of it mapped? */
- size = buffer_get_used_size(file->buffer);
+ size = file->buffer == NULL ? 0 :
+ buffer_get_used_size(file->buffer);
if (file->buffer_offset + size == file->hdr.used_size)
return 1;
}
if (start_offset < sizeof(file->hdr)) {
mail_transaction_log_file_set_corrupted(file,
- "offset (%"PRIuUOFF_T"u) < header size (%"PRIuSIZE_T")",
+ "offset (%"PRIuUOFF_T") < header size (%"PRIuSIZE_T")",
start_offset, sizeof(file->hdr));
return -1;
}
if (end_offset > file->hdr.used_size) {
mail_transaction_log_file_set_corrupted(file,
- "offset (%"PRIuUOFF_T"u) > used_size (%u)",
+ "offset (%"PRIuUOFF_T") > used_size (%u)",
end_offset, file->hdr.used_size);
return -1;
}
int
mail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view);
+void mail_transaction_log_views_close(struct mail_transaction_log *log);
+
/* Write data to transaction log. This is atomic operation. Sequences in
updates[] and expunges[] are relative to given view, they're modified
to real ones. */