[dovecot-cvs] dovecot/src/lib-storage/index/maildir
maildir-uidlist.c, 1.6, 1.7
cras at procontrol.fi
cras at procontrol.fi
Mon May 3 00:07:27 EEST 2004
Update of /home/cvs/dovecot/src/lib-storage/index/maildir
In directory talvi:/tmp/cvs-serv4049/lib-storage/index/maildir
Modified Files:
maildir-uidlist.c
Log Message:
crashfix
Index: maildir-uidlist.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-uidlist.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- maildir-uidlist.c 2 May 2004 18:07:25 -0000 1.6
+++ maildir-uidlist.c 2 May 2004 21:07:25 -0000 1.7
@@ -49,9 +49,8 @@
pool_t filename_pool;
struct hash_table *files;
- buffer_t *new_record_buf;
- unsigned int partial_new_pos;
+ unsigned int first_new_pos;
unsigned int partial:1;
unsigned int new_files:1;
@@ -149,6 +148,7 @@
{
struct maildir_uidlist_rec *rec;
uint32_t uid, flags;
+ size_t idx;
uid = flags = 0;
while (*line >= '0' && *line <= '9') {
@@ -206,12 +206,14 @@
return 0;
}
+ idx = buffer_get_used_size(uidlist->record_buf) / sizeof(*rec);
rec = buffer_append_space_unsafe(uidlist->record_buf, sizeof(*rec));
+
memset(rec, 0, sizeof(*rec));
rec->uid = uid;
rec->flags = flags;
rec->filename = p_strdup(uidlist->filename_pool, line);
- hash_insert(uidlist->files, rec->filename, rec);
+ hash_insert(uidlist->files, rec->filename, POINTER_CAST(idx));
return 1;
}
@@ -529,8 +531,6 @@
ctx->filename_pool =
pool_alloconly_create("maildir_uidlist_sync", 16384);
- ctx->new_record_buf =
- buffer_create_dynamic(default_pool, 512, (size_t)-1);
ctx->files = hash_create(default_pool, ctx->filename_pool, 4096,
maildir_hash, maildir_cmp);
return ctx;
@@ -574,11 +574,17 @@
{
struct maildir_uidlist *uidlist = ctx->uidlist;
struct maildir_uidlist_rec *rec;
+ void *value;
+ size_t idx;
int ret;
/* we'll update uidlist directly */
- rec = hash_lookup(uidlist->files, filename);
- if (rec == NULL && !ctx->synced) {
+ if (!hash_lookup_full(uidlist->files, filename, NULL, &value))
+ idx = (size_t)-1;
+ else
+ idx = POINTER_CAST_TO(value, size_t);
+
+ if (idx == (size_t)-1 && !ctx->synced) {
ret = maildir_uidlist_sync_uidlist(ctx);
if (ret < 0)
return -1;
@@ -586,22 +592,29 @@
return maildir_uidlist_sync_next_partial(ctx, filename,
flags);
}
- rec = hash_lookup(uidlist->files, filename);
+
+ if (!hash_lookup_full(uidlist->files, filename, NULL, &value))
+ idx = (size_t)-1;
+ else
+ idx = POINTER_CAST_TO(value, size_t);
}
- if (rec == NULL) {
+ if (idx == (size_t)-1) {
ctx->new_files = TRUE;
- ctx->partial_new_pos =
- buffer_get_used_size(uidlist->record_buf) /
- sizeof(*rec);
+ idx = buffer_get_used_size(uidlist->record_buf) / sizeof(*rec);
+ ctx->first_new_pos = idx;
+
rec = buffer_append_space_unsafe(uidlist->record_buf,
sizeof(*rec));
memset(rec, 0, sizeof(*rec));
+ } else {
+ rec = buffer_get_modifyable_data(uidlist->record_buf, NULL);
+ rec += idx;
}
rec->flags = (rec->flags | flags) & ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
rec->filename = p_strdup(uidlist->filename_pool, filename);
- hash_insert(uidlist->files, rec->filename, rec);
+ hash_insert(uidlist->files, rec->filename, POINTER_CAST(idx));
return 1;
}
@@ -609,7 +622,10 @@
const char *filename,
enum maildir_uidlist_rec_flag flags)
{
+ struct maildir_uidlist *uidlist = ctx->uidlist;
struct maildir_uidlist_rec *rec;
+ void *value;
+ size_t idx;
int ret;
if (ctx->failed)
@@ -618,8 +634,15 @@
if (ctx->partial)
return maildir_uidlist_sync_next_partial(ctx, filename, flags);
- rec = hash_lookup(ctx->files, filename);
- if (rec != NULL) {
+ if (!hash_lookup_full(ctx->files, filename, NULL, &value))
+ idx = (size_t)-1;
+ else
+ idx = POINTER_CAST_TO(value, size_t);
+
+ if (idx != (size_t)-1) {
+ rec = buffer_get_modifyable_data(uidlist->record_buf, NULL);
+ rec += idx;
+
if ((rec->flags & (MAILDIR_UIDLIST_REC_FLAG_NEW_DIR |
MAILDIR_UIDLIST_REC_FLAG_MOVED)) == 0) {
/* possibly duplicate */
@@ -629,8 +652,12 @@
rec->flags &= ~(MAILDIR_UIDLIST_REC_FLAG_NEW_DIR |
MAILDIR_UIDLIST_REC_FLAG_MOVED);
} else {
- rec = hash_lookup(ctx->uidlist->files, filename);
- if (rec == NULL && !ctx->synced) {
+ if (!hash_lookup_full(uidlist->files, filename,
+ NULL, &value))
+ idx = (size_t)-1;
+ else
+ idx = POINTER_CAST_TO(value, size_t);
+ if (idx == (size_t)-1 && !ctx->synced) {
ret = maildir_uidlist_sync_uidlist(ctx);
if (ret < 0)
return -1;
@@ -638,20 +665,32 @@
return maildir_uidlist_sync_next(ctx, filename,
flags);
}
- rec = hash_lookup(ctx->uidlist->files, filename);
+ if (!hash_lookup_full(uidlist->files, filename,
+ NULL, &value))
+ idx = (size_t)-1;
+ else
+ idx = POINTER_CAST_TO(value, size_t);
}
- if (rec == NULL) {
+ if (idx == (size_t)-1) {
ctx->new_files = TRUE;
- rec = buffer_append_space_unsafe(ctx->new_record_buf,
+ idx = buffer_get_used_size(uidlist->record_buf) /
+ sizeof(*rec);
+ ctx->first_new_pos = idx;
+
+ rec = buffer_append_space_unsafe(uidlist->record_buf,
sizeof(*rec));
memset(rec, 0, sizeof(*rec));
+ } else {
+ rec = buffer_get_modifyable_data(uidlist->record_buf,
+ NULL);
+ rec += idx;
}
}
rec->flags |= flags;
rec->filename = p_strdup(ctx->filename_pool, filename);
- hash_insert(ctx->files, rec->filename, rec);
+ hash_insert(ctx->files, rec->filename, POINTER_CAST(idx));
return 1;
}
@@ -707,13 +746,20 @@
struct maildir_uidlist_rec *rec;
void *key, *value;
size_t size;
- unsigned int src, dest;
+ unsigned int src, dest, new_files_count;
/* @UNSAFE */
rec = buffer_get_modifyable_data(uidlist->record_buf, &size);
size /= sizeof(*rec);
+ if (ctx->new_files) {
+ new_files_count = size - ctx->first_new_pos;
+ size = ctx->first_new_pos;
+ } else {
+ new_files_count = 0;
+ }
+
/* update filename pointers, skip deleted messages */
for (dest = src = 0; src < size; src++) {
if (!hash_lookup_full(ctx->files, rec[src].filename,
@@ -730,11 +776,16 @@
}
dest++;
}
- buffer_set_used_size(uidlist->record_buf, dest * sizeof(*rec));
- buffer_append_buf(uidlist->record_buf, ctx->new_record_buf,
- 0, (size_t)-1);
- maildir_uidlist_assign_uids(uidlist, dest);
+ if (ctx->new_files) {
+ buffer_copy(uidlist->record_buf, dest * sizeof(*rec),
+ uidlist->record_buf, src * sizeof(*rec),
+ (size_t)-1);
+ dest += new_files_count;
+ }
+ buffer_set_used_size(uidlist->record_buf, dest * sizeof(*rec));
+ if (ctx->new_files)
+ maildir_uidlist_assign_uids(uidlist, src);
hash_destroy(uidlist->files);
uidlist->files = ctx->files;
@@ -758,7 +809,7 @@
else {
if (ctx->new_files) {
maildir_uidlist_assign_uids(ctx->uidlist,
- ctx->partial_new_pos);
+ ctx->first_new_pos);
}
maildir_uidlist_mark_all(ctx->uidlist, FALSE);
}
@@ -776,8 +827,6 @@
hash_destroy(ctx->files);
if (ctx->filename_pool != NULL)
pool_unref(ctx->filename_pool);
- if (ctx->new_record_buf != NULL)
- buffer_free(ctx->new_record_buf);
i_free(ctx);
return ret;
}
More information about the dovecot-cvs
mailing list