]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
mdbox: Removed mdbox_max_open_files setting.
authorTimo Sirainen <tss@iki.fi>
Mon, 8 Mar 2010 18:28:08 +0000 (20:28 +0200)
committerTimo Sirainen <tss@iki.fi>
Mon, 8 Mar 2010 18:28:08 +0000 (20:28 +0200)
It's now hard coded to 2, and the files are closed after 30 seconds of being
unused.

--HG--
branch : HEAD

src/lib-storage/index/dbox-multi/mdbox-file.c
src/lib-storage/index/dbox-multi/mdbox-file.h
src/lib-storage/index/dbox-multi/mdbox-settings.c
src/lib-storage/index/dbox-multi/mdbox-settings.h
src/lib-storage/index/dbox-multi/mdbox-storage.c
src/lib-storage/index/dbox-multi/mdbox-storage.h

index d897d5502409b1900b3585dca40a16739a8c97f7..f91d616373ccc6ad719b528a31d0efa224cfd133 100644 (file)
 static struct mdbox_file *
 mdbox_find_and_move_open_file(struct mdbox_storage *storage, uint32_t file_id)
 {
-       struct mdbox_file *const *files, *file;
+       struct mdbox_file *const *files;
        unsigned int i, count;
 
        files = array_get(&storage->open_files, &count);
        for (i = 0; i < count; i++) {
-               if (files[i]->file_id == file_id) {
-                       /* move to last in the array */
-                       file = files[i];
-                       array_delete(&storage->open_files, i, 1);
-                       array_append(&storage->open_files, &file, 1);
-                       return file;
-               }
+               if (files[i]->file_id == file_id)
+                       return files[i];
        }
        return NULL;
 }
@@ -127,9 +122,9 @@ mdbox_file_init_full(struct mdbox_storage *storage,
        }
 
        count = array_count(&storage->open_files);
-       if (count > storage->set->mdbox_max_open_files) {
-               mdbox_close_open_files(storage, count -
-                                      storage->set->mdbox_max_open_files);
+       if (count > MDBOX_MAX_OPEN_UNUSED_FILES) {
+               mdbox_close_open_files(storage,
+                                      count - MDBOX_MAX_OPEN_UNUSED_FILES);
        }
 
        file = i_new(struct mdbox_file, 1);
@@ -187,6 +182,53 @@ int mdbox_file_assign_file_id(struct mdbox_file *file, uint32_t file_id)
        return 0;
 }
 
+static struct mdbox_file *
+mdbox_find_oldest_unused_file(struct mdbox_storage *storage,
+                             unsigned int *idx_r)
+{
+       struct mdbox_file *const *files, *oldest_file = NULL;
+       unsigned int i, count;
+
+       files = array_get(&storage->open_files, &count);
+       *idx_r = count;
+       for (i = 0; i < count; i++) {
+               if (files[i]->file.refcount == 0) {
+                       if (oldest_file == NULL ||
+                           files[i]->close_time < oldest_file->close_time) {
+                               oldest_file = files[i];
+                               *idx_r = i;
+                       }
+               }
+       }
+       return oldest_file;
+}
+
+static void mdbox_file_close_timeout(struct mdbox_storage *storage)
+{
+       struct mdbox_file *oldest;
+       unsigned int i;
+       time_t close_time = ioloop_time - MDBOX_CLOSE_UNUSED_FILES_TIMEOUT_SECS;
+
+       while ((oldest = mdbox_find_oldest_unused_file(storage, &i)) != NULL) {
+               if (oldest->close_time > close_time)
+                       break;
+               array_delete(&storage->open_files, i, 1);
+               dbox_file_free(&oldest->file);
+       }
+
+       if (oldest == NULL)
+               timeout_remove(&storage->to_close_unused_files);
+}
+
+static void mdbox_file_close_later(struct mdbox_file *mfile)
+{
+       if (mfile->storage->to_close_unused_files == NULL) {
+               mfile->storage->to_close_unused_files =
+                       timeout_add(MDBOX_CLOSE_UNUSED_FILES_TIMEOUT_SECS*1000,
+                                   mdbox_file_close_timeout, mfile->storage);
+       }
+}
+
 void mdbox_file_unrefed(struct dbox_file *file)
 {
        struct mdbox_file *mfile = (struct mdbox_file *)file;
@@ -195,24 +237,23 @@ void mdbox_file_unrefed(struct dbox_file *file)
 
        /* don't cache metadata seeks while file isn't being referenced */
        file->metadata_read_offset = (uoff_t)-1;
+       mfile->close_time = ioloop_time;
 
        if (mfile->file_id != 0) {
                files = array_get(&mfile->storage->open_files, &count);
-               if (!file->deleted &&
-                   count <= mfile->storage->set->mdbox_max_open_files) {
+               if (!file->deleted && count <= MDBOX_MAX_OPEN_UNUSED_FILES) {
                        /* we can leave this file open for now */
+                       mdbox_file_close_later(mfile);
                        return;
                }
 
                /* close the oldest file with refcount=0 */
-               for (i = 0; i < count; i++) {
-                       if (files[i]->file.refcount == 0)
-                               break;
-               }
-               oldest_file = files[i];
+               oldest_file = mdbox_find_oldest_unused_file(mfile->storage, &i);
+               i_assert(oldest_file != NULL);
                array_delete(&mfile->storage->open_files, i, 1);
                if (oldest_file != mfile) {
                        dbox_file_free(&oldest_file->file);
+                       mdbox_file_close_later(mfile);
                        return;
                }
                /* have to close ourself */
index 9548b726e720774034c71922c9eec1b2e7e4c32c..4505364c6797373f9a490b1397d8a8969f2cda08 100644 (file)
@@ -8,6 +8,7 @@ struct mdbox_file {
        struct mdbox_storage *storage;
 
        uint32_t file_id;
+       time_t close_time;
 };
 
 struct dbox_file *
index 7bee02e054e5860ad752b7fbd0bb6eadb6c80537..de5624e6407c4c0a8f76d61449173f8c7867c9c2 100644 (file)
 #define DEF(type, name) \
        { type, #name, offsetof(struct mdbox_settings, name), NULL }
 
-static bool mdbox_settings_verify(void *_set, pool_t pool ATTR_UNUSED,
-                                 const char **error_r);
-
 static const struct setting_define mdbox_setting_defines[] = {
        DEF(SET_SIZE, mdbox_rotate_size),
        DEF(SET_TIME, mdbox_rotate_interval),
        DEF(SET_TIME, mdbox_altmove),
-       DEF(SET_UINT, mdbox_max_open_files),
 
        SETTING_DEFINE_LIST_END
 };
@@ -26,8 +22,7 @@ static const struct setting_define mdbox_setting_defines[] = {
 static const struct mdbox_settings mdbox_default_settings = {
        .mdbox_rotate_size = 2*1024*1024,
        .mdbox_rotate_interval = 0,
-       .mdbox_altmove = 3600*24*7,
-       .mdbox_max_open_files = 64
+       .mdbox_altmove = 3600*24*7
 };
 
 static const struct setting_parser_info mdbox_setting_parser_info = {
@@ -39,25 +34,9 @@ static const struct setting_parser_info mdbox_setting_parser_info = {
        .struct_size = sizeof(struct mdbox_settings),
 
        .parent_offset = (size_t)-1,
-       .parent = &mail_user_setting_parser_info,
-
-       .check_func = mdbox_settings_verify
+       .parent = &mail_user_setting_parser_info
 };
 
-/* <settings checks> */
-static bool mdbox_settings_verify(void *_set, pool_t pool ATTR_UNUSED,
-                                 const char **error_r)
-{
-       const struct mdbox_settings *set = _set;
-
-       if (set->mdbox_max_open_files < 2) {
-               *error_r = "mdbox_max_open_files must be at least 2";
-               return FALSE;
-       }
-       return TRUE;
-}
-/* </settings checks> */
-
 const struct setting_parser_info *mdbox_get_setting_parser_info(void)
 {
        return &mdbox_setting_parser_info;
index b1fdcc0ec79924f9d119218ebe3707a88e1be067..a0ef7782d5514c866fe07e994aaaab058d33e56e 100644 (file)
@@ -5,7 +5,6 @@ struct mdbox_settings {
        uoff_t mdbox_rotate_size;
        unsigned int mdbox_rotate_interval;
        unsigned int mdbox_altmove;
-       unsigned int mdbox_max_open_files;
 };
 
 const struct setting_parser_info *mdbox_get_setting_parser_info(void);
index d19e46ec5a8e3e622403239c439ef10048f49e92..adb5f950601c7767ff94908856afb9f24cbd09b2 100644 (file)
@@ -39,7 +39,6 @@ mdbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
        const char *dir;
 
        storage->set = mail_storage_get_driver_settings(_storage);
-       i_assert(storage->set->mdbox_max_open_files >= 2);
 
        if (*ns->list->set.mailbox_dir_name == '\0') {
                *error_r = "dbox: MAILBOXDIR must not be empty";
@@ -55,8 +54,7 @@ mdbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
        storage->alt_storage_dir = p_strconcat(_storage->pool,
                                               ns->list->set.alt_dir,
                                               "/"MDBOX_GLOBAL_DIR_NAME, NULL);
-       i_array_init(&storage->open_files,
-                    I_MIN(storage->set->mdbox_max_open_files, 128));
+       i_array_init(&storage->open_files, 64);
 
        storage->map = dbox_map_init(storage, ns->list, storage->storage_dir);
        return 0;
@@ -73,6 +71,8 @@ static void mdbox_storage_destroy(struct mail_storage *_storage)
 
        mdbox_files_free(storage);
        dbox_map_deinit(&storage->map);
+       if (storage->to_close_unused_files != NULL)
+               timeout_remove(&storage->to_close_unused_files);
        array_free(&storage->open_files);
 }
 
index ce21077bbe4215e45637cb9595f5f708a5eb907e..340e4abe4f4bceea0e39b207c1871ee0a41c41fc 100644 (file)
@@ -11,6 +11,8 @@
 #define MDBOX_GLOBAL_DIR_NAME "storage"
 #define MDBOX_MAIL_FILE_PREFIX "m."
 #define MDBOX_MAIL_FILE_FORMAT MDBOX_MAIL_FILE_PREFIX"%u"
+#define MDBOX_MAX_OPEN_UNUSED_FILES 2
+#define MDBOX_CLOSE_UNUSED_FILES_TIMEOUT_SECS 30
 
 #define MDBOX_INDEX_HEADER_MIN_SIZE (sizeof(uint32_t))
 struct mdbox_index_header {
@@ -28,6 +30,7 @@ struct mdbox_storage {
        struct dbox_map *map;
 
        ARRAY_DEFINE(open_files, struct mdbox_file *);
+       struct timeout *to_close_unused_files;
 };
 
 struct mdbox_mail_index_record {