dovecot: Created a new struct mail_index_record_map which can be...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Aug 3 03:45:25 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/6418139447fa
changeset: 6165:6418139447fa
user: Timo Sirainen <tss at iki.fi>
date: Fri Aug 03 03:22:04 2007 +0300
description:
Created a new struct mail_index_record_map which can be shared by multiple
mail_index_maps. This avoids having to copy records when appending new
messages.
diffstat:
11 files changed, 295 insertions(+), 183 deletions(-)
src/lib-index/mail-cache.c | 4
src/lib-index/mail-index-fsck.c | 4
src/lib-index/mail-index-map.c | 252 +++++++++++++++++++-------------
src/lib-index/mail-index-private.h | 54 ++++--
src/lib-index/mail-index-sync-ext.c | 20 +-
src/lib-index/mail-index-sync-update.c | 103 ++++++++-----
src/lib-index/mail-index-transaction.c | 6
src/lib-index/mail-index-view-sync.c | 3
src/lib-index/mail-index-view.c | 8 -
src/lib-index/mail-index-write.c | 22 +-
src/lib-index/mail-index.c | 2
diffs (truncated from 961 to 300 lines):
diff -r 22398d619cac -r 6418139447fa src/lib-index/mail-cache.c
--- a/src/lib-index/mail-cache.c Thu Aug 02 19:06:34 2007 +0300
+++ b/src/lib-index/mail-cache.c Fri Aug 03 03:22:04 2007 +0300
@@ -527,8 +527,8 @@ static void mail_cache_update_need_compr
uoff_t max_del_space;
cont_percentage = hdr->continued_record_count * 100 /
- (cache->index->map->records_count == 0 ? 1 :
- cache->index->map->records_count);
+ (cache->index->map->rec_map->records_count == 0 ? 1 :
+ cache->index->map->rec_map->records_count);
if (cont_percentage >= MAIL_CACHE_COMPRESS_CONTINUED_PERCENTAGE &&
hdr->used_file_size >= MAIL_CACHE_COMPRESS_MIN_SIZE) {
/* too many continued rows, compress */
diff -r 22398d619cac -r 6418139447fa src/lib-index/mail-index-fsck.c
--- a/src/lib-index/mail-index-fsck.c Thu Aug 02 19:06:34 2007 +0300
+++ b/src/lib-index/mail-index-fsck.c Fri Aug 03 03:22:04 2007 +0300
@@ -78,8 +78,8 @@ mail_index_fsck_map(struct mail_index *i
hdr.first_unseen_uid_lowwater = 0;
hdr.first_deleted_uid_lowwater = 0;
- rec = map->records; last_uid = 0;
- for (i = 0; i < map->records_count; i++) {
+ rec = map->rec_map->records; last_uid = 0;
+ for (i = 0; i < map->rec_map->records_count; i++) {
if (rec->uid <= last_uid) {
*error_r = "Record UIDs are not ordered";
return 0;
diff -r 22398d619cac -r 6418139447fa src/lib-index/mail-index-map.c
--- a/src/lib-index/mail-index-map.c Thu Aug 02 19:06:34 2007 +0300
+++ b/src/lib-index/mail-index-map.c Fri Aug 03 03:22:04 2007 +0300
@@ -310,39 +310,17 @@ static int mail_index_check_header(struc
hdr->first_deleted_uid_lowwater > hdr->next_uid)
return 0;
- if (map->records_count > 0) {
+ if (hdr->messages_count > 0) {
/* last message's UID must be smaller than next_uid.
also make sure it's not zero. */
const struct mail_index_record *rec;
- rec = MAIL_INDEX_MAP_IDX(map, map->records_count-1);
+ rec = MAIL_INDEX_MAP_IDX(map, hdr->messages_count-1);
if (rec->uid == 0 || rec->uid >= hdr->next_uid)
return 0;
}
return 1;
-}
-
-static void mail_index_map_clear(struct mail_index_map *map)
-{
- if (map->buffer != NULL) {
- i_assert(map->mmap_base == NULL);
- buffer_free(map->buffer);
- map->buffer = NULL;
- } else if (map->mmap_base != NULL) {
- i_assert(map->buffer == NULL);
- if (munmap(map->mmap_base, map->mmap_size) < 0)
- mail_index_set_syscall_error(map->index, "munmap()");
- map->mmap_base = NULL;
- }
-
- if (map->refcount > 0) {
- memset(&map->hdr, 0, sizeof(map->hdr));
- map->mmap_size = 0;
- map->mmap_used_size = 0;
- map->records = NULL;
- map->records_count = 0;
- }
}
static void mail_index_map_copy_hdr(struct mail_index_map *map,
@@ -361,14 +339,14 @@ static int mail_index_mmap(struct mail_i
static int mail_index_mmap(struct mail_index_map *map, uoff_t file_size)
{
struct mail_index *index = map->index;
+ struct mail_index_record_map *rec_map = map->rec_map;
const struct mail_index_header *hdr;
unsigned int records_count;
- if (map->buffer != NULL) {
- /* we had temporarily used a buffer, eg. for updating index */
- buffer_free(map->buffer);
- map->buffer = NULL;
- }
+ i_assert(rec_map->mmap_base == NULL);
+
+ buffer_free(rec_map->buffer);
+ rec_map->buffer = NULL;
if (file_size > SSIZE_T_MAX) {
/* too large file to map into memory */
@@ -377,40 +355,40 @@ static int mail_index_mmap(struct mail_i
return -1;
}
- map->mmap_base = mmap(NULL, file_size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE, index->fd, 0);
- if (map->mmap_base == MAP_FAILED) {
- map->mmap_base = NULL;
+ rec_map->mmap_base = mmap(NULL, file_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, index->fd, 0);
+ if (rec_map->mmap_base == MAP_FAILED) {
+ rec_map->mmap_base = NULL;
mail_index_set_syscall_error(index, "mmap()");
return -1;
}
- map->mmap_size = file_size;
-
- hdr = map->mmap_base;
- if (map->mmap_size >
+ rec_map->mmap_size = file_size;
+
+ hdr = rec_map->mmap_base;
+ if (rec_map->mmap_size >
offsetof(struct mail_index_header, major_version) &&
hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
/* major version change - handle silently */
return 0;
}
- if (map->mmap_size < MAIL_INDEX_HEADER_MIN_SIZE) {
+ if (rec_map->mmap_size < MAIL_INDEX_HEADER_MIN_SIZE) {
mail_index_set_error(index, "Corrupted index file %s: "
"File too small (%"PRIuSIZE_T")",
- index->filepath, map->mmap_size);
- return 0;
- }
-
- if (!mail_index_check_header_compat(index, hdr, map->mmap_size)) {
+ index->filepath, rec_map->mmap_size);
+ return 0;
+ }
+
+ if (!mail_index_check_header_compat(index, hdr, rec_map->mmap_size)) {
/* Can't use this file */
return 0;
}
- map->mmap_used_size = hdr->header_size +
+ rec_map->mmap_used_size = hdr->header_size +
hdr->messages_count * hdr->record_size;
- if (map->mmap_used_size > map->mmap_size) {
- records_count = (map->mmap_size - hdr->header_size) /
+ if (rec_map->mmap_used_size > rec_map->mmap_size) {
+ records_count = (rec_map->mmap_size - hdr->header_size) /
hdr->record_size;
mail_index_set_error(index, "Corrupted index file %s: "
"messages_count too large (%u > %u)",
@@ -421,9 +399,9 @@ static int mail_index_mmap(struct mail_i
mail_index_map_copy_hdr(map, hdr);
- map->hdr_base = map->mmap_base;
- map->records = PTR_OFFSET(map->mmap_base, map->hdr.header_size);
- map->records_count = map->hdr.messages_count;
+ map->hdr_base = rec_map->mmap_base;
+ rec_map->records = PTR_OFFSET(rec_map->mmap_base, map->hdr.header_size);
+ rec_map->records_count = map->hdr.messages_count;
return 1;
}
@@ -464,7 +442,7 @@ mail_index_try_read_map(struct mail_inde
size_t pos, records_size, initial_buf_pos = 0;
unsigned int records_count, extra;
- i_assert(map->mmap_base == NULL);
+ i_assert(map->rec_map->mmap_base == NULL);
*retry_r = FALSE;
ret = mail_index_read_header(index, read_buf, sizeof(read_buf), &pos);
@@ -517,23 +495,24 @@ mail_index_try_read_map(struct mail_inde
return 0;
}
- if (map->buffer == NULL) {
- map->buffer = buffer_create_dynamic(default_pool,
- records_size);
+ if (map->rec_map->buffer == NULL) {
+ map->rec_map->buffer =
+ buffer_create_dynamic(default_pool,
+ records_size);
}
/* @UNSAFE */
- buffer_set_used_size(map->buffer, 0);
+ buffer_set_used_size(map->rec_map->buffer, 0);
if (initial_buf_pos <= hdr->header_size)
extra = 0;
else {
extra = initial_buf_pos - hdr->header_size;
- buffer_append(map->buffer,
+ buffer_append(map->rec_map->buffer,
CONST_PTR_OFFSET(buf, hdr->header_size),
extra);
}
if (records_size > extra) {
- data = buffer_append_space_unsafe(map->buffer,
+ data = buffer_append_space_unsafe(map->rec_map->buffer,
records_size - extra);
ret = pread_full(index->fd, data, records_size - extra,
hdr->header_size + extra);
@@ -556,8 +535,9 @@ mail_index_try_read_map(struct mail_inde
return 0;
}
- map->records = buffer_get_modifiable_data(map->buffer, NULL);
- map->records_count = hdr->messages_count;
+ map->rec_map->records =
+ buffer_get_modifiable_data(map->rec_map->buffer, NULL);
+ map->rec_map->records_count = hdr->messages_count;
mail_index_map_copy_hdr(map, hdr);
map->hdr_base = map->hdr_copy_buf->data;
@@ -700,7 +680,9 @@ static int mail_index_map_latest_file(st
new_map = mail_index_map_alloc(index);
if (use_mmap) {
- new_map->lock_id = lock_id;
+ new_map->rec_map->lock_id = lock_id;
+ new_map->rec_map->lock_count++;
+ new_map->locked = TRUE;
ret = mail_index_mmap(new_map, file_size);
} else {
ret = mail_index_read_map(new_map, file_size);
@@ -718,6 +700,7 @@ static int mail_index_map_latest_file(st
mail_index_unmap(&new_map);
return ret;
}
+ i_assert(new_map->rec_map->records != NULL);
index->last_read_log_file_seq = new_map->hdr.log_file_seq;
index->last_read_log_file_head_offset =
@@ -773,6 +756,40 @@ int mail_index_map(struct mail_index *in
return ret;
}
+static void mail_index_record_map_free(struct mail_index_map *map,
+ struct mail_index_record_map *rec_map)
+{
+ if (rec_map->buffer != NULL) {
+ i_assert(rec_map->mmap_base == NULL);
+ buffer_free(rec_map->buffer);
+ rec_map->buffer = NULL;
+ } else if (rec_map->mmap_base != NULL) {
+ i_assert(rec_map->buffer == NULL);
+ if (munmap(rec_map->mmap_base, rec_map->mmap_size) < 0)
+ mail_index_set_syscall_error(map->index, "munmap()");
+ rec_map->mmap_base = NULL;
+ }
+ array_free(&rec_map->maps);
+ i_free(rec_map);
+}
+
+static void mail_index_record_map_unlink(struct mail_index_map *map)
+{
+ struct mail_index_map *const *maps;
+ unsigned int i, count;
+
+ maps = array_get(&map->rec_map->maps, &count);
+ for (i = 0; i < count; i++) {
+ if (maps[i] == map) {
+ array_delete(&map->rec_map->maps, i, 1);
+ if (i == 0 && count == 1)
+ mail_index_record_map_free(map, map->rec_map);
+ return;
+ }
+ }
+ i_unreached();
+}
+
void mail_index_unmap(struct mail_index_map **_map)
{
struct mail_index_map *map = *_map;
@@ -782,8 +799,8 @@ void mail_index_unmap(struct mail_index_
return;
i_assert(map->refcount == 0);
- mail_index_map_clear(map);
mail_index_map_unlock(map);
+ mail_index_record_map_unlink(map);
if (map->extension_pool != NULL)
pool_unref(map->extension_pool);
@@ -795,35 +812,61 @@ void mail_index_unmap(struct mail_index_
int mail_index_map_lock(struct mail_index_map *map)
{
- if (map->lock_id != 0 || MAIL_INDEX_MAP_IS_IN_MEMORY(map))
- return 0;
-
- if (mail_index_lock_shared(map->index, &map->lock_id) < 0)
+ if (map->locked)
+ return 0;
+
+ if (map->rec_map->lock_id != 0 || MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
+ map->rec_map->lock_count++;
+ map->locked = TRUE;
More information about the dovecot-cvs
mailing list