Mercurial > dovecot > original-hg > dovecot-1.2
changeset 4828:7cc1b8fec8ab HEAD
Reference counting fixes. Fixes an assert crash when closing the index.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 18 Nov 2006 23:01:10 +0200 |
parents | 966f7b3fb03c |
children | 830cb3af6623 |
files | src/lib-index/mail-transaction-log-private.h src/lib-index/mail-transaction-log-view.c src/lib-index/mail-transaction-log.c |
diffstat | 3 files changed, 39 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-transaction-log-private.h Sat Nov 18 22:27:14 2006 +0200 +++ b/src/lib-index/mail-transaction-log-private.h Sat Nov 18 23:01:10 2006 +0200 @@ -13,6 +13,8 @@ struct mail_transaction_log *log; struct mail_transaction_log_file *next; + /* refcount=0 is a valid state. files start that way, and they're + freed only when mail_transaction_logs_clean() is called. */ int refcount; char *filepath;
--- a/src/lib-index/mail-transaction-log-view.c Sat Nov 18 22:27:14 2006 +0200 +++ b/src/lib-index/mail-transaction-log-view.c Sat Nov 18 23:01:10 2006 +0200 @@ -1,7 +1,7 @@ /* Copyright (C) 2003-2004 Timo Sirainen */ #include "lib.h" -#include "buffer.h" +#include "array.h" #include "mail-index-private.h" #include "mail-transaction-log-private.h" #include "mail-transaction-util.h" @@ -16,6 +16,10 @@ enum mail_transaction_type type_mask; struct mail_transaction_header tmp_hdr; + /* a list of log files we've referenced. we have to keep this list + explicitly because more files may be added into the linked list + at any time. */ + array_t ARRAY_DEFINE(file_refs, struct mail_transaction_log_file *); struct mail_transaction_log_file *cur, *head, *tail; uoff_t cur_offset; @@ -36,17 +40,32 @@ view->head = view->tail = view->log->head; view->head->refcount++; + ARRAY_CREATE(&view->file_refs, default_pool, + struct mail_transaction_log_file *, 8); + array_append(&view->file_refs, &view->head, 1); view->next = log->views; log->views = view; return view; } +static void +mail_transaction_log_view_unref_all(struct mail_transaction_log_view *view) +{ + struct mail_transaction_log_file *const *files; + unsigned int i, count; + + files = array_get(&view->file_refs, &count); + for (i = 0; i < count; i++) + files[i]->refcount--; + + array_clear(&view->file_refs); +} + void mail_transaction_log_view_close(struct mail_transaction_log_view **_view) { struct mail_transaction_log_view *view = *_view; struct mail_transaction_log_view **p; - struct mail_transaction_log_file *file; *_view = NULL; @@ -57,11 +76,10 @@ } } - for (file = view->tail; file != view->head; file = file->next) - file->refcount--; - view->head->refcount--; + mail_transaction_log_view_unref_all(view); + mail_transaction_logs_clean(view->log); - mail_transaction_logs_clean(view->log); + array_free(&view->file_refs); i_free(view); } @@ -184,21 +202,16 @@ max_file_offset <= file->sync_offset); /* we have all of them. update refcounts. */ - if (view->tail->hdr.file_seq < first->hdr.file_seq) { - /* unref old files */ - for (file = view->tail; file != first; file = file->next) - file->refcount--; - } else { - /* going backwards, reference them */ - for (file = first; file != view->tail; file = file->next) - file->refcount++; + mail_transaction_log_view_unref_all(view); + + view->tail = first; + view->head = view->log->head; + + /* reference all used files */ + for (file = view->tail; file != NULL; file = file->next) { + array_append(&view->file_refs, &file, 1); + file->refcount++; } - view->tail = first; - - /* reference all new files */ - for (file = view->head->next; file != NULL; file = file->next) - file->refcount++; - view->head = view->log->head; view->prev_file_seq = 0; view->prev_file_offset = 0;
--- a/src/lib-index/mail-transaction-log.c Sat Nov 18 22:27:14 2006 +0200 +++ b/src/lib-index/mail-transaction-log.c Sat Nov 18 23:01:10 2006 +0200 @@ -247,6 +247,7 @@ log->head = mail_transaction_log_file_open_or_create(log, path); i_assert(log->head != NULL); } + log->head->refcount++; if (index->fd != -1 && INDEX_HAS_MISSING_LOGS(index, log->head)) { @@ -683,7 +684,6 @@ } file = i_new(struct mail_transaction_log_file, 1); - file->refcount = 1; file->log = log; file->filepath = i_strdup(path); file->fd = fd; @@ -766,7 +766,6 @@ struct mail_transaction_log_file *file; file = i_new(struct mail_transaction_log_file, 1); - file->refcount = 1; file->log = log; file->filepath = i_strdup("(in-memory transaction log file)"); file->fd = -1; @@ -866,6 +865,7 @@ for (file = log->files; file != NULL; file = next) { next = file->next; + i_assert(file->refcount >= 0); if (file->refcount == 0) mail_transaction_log_file_free(file); } @@ -908,7 +908,6 @@ if (lock) { if (mail_transaction_log_file_lock(file) < 0) { - file->refcount--; mail_transaction_logs_clean(log); return -1; } @@ -922,6 +921,7 @@ i_assert(log->head != file); log->head = file; + log->head->refcount++; return 0; } @@ -967,6 +967,7 @@ } log->head = file; + log->head->refcount++; return 0; }