[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-sync.c, 1.9, 1.10 maildir-uidlist.c, 1.7, 1.8

cras at procontrol.fi cras at procontrol.fi
Mon May 3 16:50:43 EEST 2004


Update of /home/cvs/dovecot/src/lib-storage/index/maildir
In directory talvi:/tmp/cvs-serv15377/lib-storage/index/maildir

Modified Files:
	maildir-sync.c maildir-uidlist.c 
Log Message:
Syncing should be fixed now.



Index: maildir-sync.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-sync.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- maildir-sync.c	2 May 2004 20:32:16 -0000	1.9
+++ maildir-sync.c	3 May 2004 13:50:41 -0000	1.10
@@ -481,7 +481,8 @@
 	}
 
 	if (cur_mtime != ibox->last_cur_mtime ||
-	    ioloop_time - ibox->dirty_cur_time > MAILDIR_SYNC_SECS) {
+	    (ibox->dirty_cur_time != 0 &&
+	     ioloop_time - ibox->dirty_cur_time > MAILDIR_SYNC_SECS)) {
 		/* cur/ changed, or delayed cur/ check */
 		*cur_changed_r = TRUE;
 		ibox->last_cur_mtime = cur_mtime;

Index: maildir-uidlist.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-uidlist.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- maildir-uidlist.c	2 May 2004 21:07:25 -0000	1.7
+++ maildir-uidlist.c	3 May 2004 13:50:41 -0000	1.8
@@ -35,19 +35,22 @@
 
 	time_t last_mtime;
 
-	pool_t filename_pool;
+	pool_t record_pool;
 	buffer_t *record_buf;
 	struct hash_table *files;
 
 	unsigned int version;
 	unsigned int uid_validity, next_uid, last_read_uid;
 	uint32_t first_recent_uid;
+
+	unsigned int initial_read:1;
 };
 
 struct maildir_uidlist_sync_ctx {
 	struct maildir_uidlist *uidlist;
 
-	pool_t filename_pool;
+	pool_t record_pool;
+	buffer_t *record_buf;
 	struct hash_table *files;
 
 	unsigned int first_new_pos;
@@ -59,7 +62,7 @@
 };
 
 struct maildir_uidlist_iter_ctx {
-	const struct maildir_uidlist_rec *next, *end;
+	const struct maildir_uidlist_rec *const *next, *const *end;
 };
 
 int maildir_uidlist_try_lock(struct maildir_uidlist *uidlist)
@@ -127,8 +130,8 @@
 	i_assert(!UIDLIST_IS_LOCKED(uidlist));
 
 	hash_destroy(uidlist->files);
-	if (uidlist->filename_pool != NULL)
-		pool_unref(uidlist->filename_pool);
+	if (uidlist->record_pool != NULL)
+		pool_unref(uidlist->record_pool);
 
 	buffer_free(uidlist->record_buf);
 	i_free(uidlist->fname);
@@ -148,7 +151,6 @@
 {
         struct maildir_uidlist_rec *rec;
 	uint32_t uid, flags;
-	size_t idx;
 
 	uid = flags = 0;
 	while (*line >= '0' && *line <= '9') {
@@ -199,28 +201,26 @@
 		flags |= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR;
 	}
 
-	if (hash_lookup(uidlist->files, line) != NULL) {
+	if (hash_lookup_full(uidlist->files, line, NULL, NULL)) {
                 mail_storage_set_critical(uidlist->ibox->box.storage,
 			"Duplicate file in uidlist file %s: %s",
 			uidlist->fname, line);
 		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 = p_new(uidlist->record_pool, struct maildir_uidlist_rec, 1);
 	rec->uid = uid;
 	rec->flags = flags;
-	rec->filename = p_strdup(uidlist->filename_pool, line);
-	hash_insert(uidlist->files, rec->filename, POINTER_CAST(idx));
+	rec->filename = p_strdup(uidlist->record_pool, line);
+	hash_insert(uidlist->files, rec->filename, rec);
+	buffer_append(uidlist->record_buf, &rec, sizeof(rec));
 	return 1;
 }
 
 int maildir_uidlist_update(struct maildir_uidlist *uidlist)
 {
 	struct mail_storage *storage = uidlist->ibox->box.storage;
-	const struct maildir_uidlist_rec *rec;
+	const struct maildir_uidlist_rec *const *rec_p;
 	const char *line;
 	struct istream *input;
 	struct stat st;
@@ -251,6 +251,7 @@
 				"open(%s) failed: %m", uidlist->fname);
 			return -1;
 		}
+		uidlist->initial_read = TRUE;
 		return 0;
 	}
 
@@ -260,15 +261,15 @@
 		return -1;
 	}
 
-	if (uidlist->filename_pool == NULL) {
-		uidlist->filename_pool =
-			pool_alloconly_create("uidlist filename_pool",
+	if (uidlist->record_pool == NULL) {
+		uidlist->record_pool =
+			pool_alloconly_create("uidlist record_pool",
 					      nearest_power(st.st_size -
 							    st.st_size/8));
 	}
 
-	rec = buffer_get_data(uidlist->record_buf, &size);
-	last_uid = size == 0 ? 0 : rec[(size / sizeof(*rec))-1].uid;
+	rec_p = buffer_get_data(uidlist->record_buf, &size);
+	last_uid = size == 0 ? 0 : rec_p[(size / sizeof(*rec_p))-1]->uid;
 
 	uidlist->version = 0;
 
@@ -303,6 +304,7 @@
 	}
 
 	i_stream_unref(input);
+	uidlist->initial_read = TRUE;
 	return ret;
 }
 
@@ -310,18 +312,18 @@
 maildir_uidlist_lookup_rec(struct maildir_uidlist *uidlist, uint32_t uid,
 			   unsigned int *idx_r)
 {
-	const struct maildir_uidlist_rec *rec;
+	const struct maildir_uidlist_rec *const *rec_p;
 	unsigned int idx, left_idx, right_idx;
 	size_t size;
 
-	if (uidlist->last_mtime == 0) {
+	if (!uidlist->initial_read) {
 		/* first time we need to read uidlist */
 		if (maildir_uidlist_update(uidlist) < 0)
 			return NULL;
 	}
 
-	rec = buffer_get_data(uidlist->record_buf, &size);
-	size /= sizeof(*rec);
+	rec_p = buffer_get_data(uidlist->record_buf, &size);
+	size /= sizeof(*rec_p);
 
 	idx = 0;
 	left_idx = 0;
@@ -330,13 +332,13 @@
 	while (left_idx < right_idx) {
 		idx = (left_idx + right_idx) / 2;
 
-		if (rec[idx].uid < uid)
+		if (rec_p[idx]->uid < uid)
 			left_idx = idx+1;
-		else if (rec[idx].uid > uid)
+		else if (rec_p[idx]->uid > uid)
 			right_idx = idx;
 		else {
 			*idx_r = idx;
-			return &rec[idx];
+			return rec_p[idx];
 		}
 	}
 
@@ -377,7 +379,7 @@
 
 uint32_t maildir_uidlist_get_recent_count(struct maildir_uidlist *uidlist)
 {
-	const struct maildir_uidlist_rec *rec;
+	const struct maildir_uidlist_rec *const *rec_p;
 	unsigned int idx;
 	size_t size;
 	uint32_t count;
@@ -385,12 +387,12 @@
 	if (uidlist->first_recent_uid == 0)
 		return 0;
 
-	rec = buffer_get_data(uidlist->record_buf, &size);
-	size /= sizeof(*rec);
+	rec_p = buffer_get_data(uidlist->record_buf, &size);
+	size /= sizeof(*rec_p);
 
 	maildir_uidlist_lookup_rec(uidlist, uidlist->first_recent_uid, &idx);
 	for (count = 0; idx < size; idx++) {
-		if ((rec[idx].flags & MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0)
+		if ((rec_p[idx]->flags & MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0)
 			count++;
 	}
 	return count;
@@ -499,18 +501,18 @@
 static void maildir_uidlist_mark_all(struct maildir_uidlist *uidlist,
 				     int nonsynced)
 {
-	struct maildir_uidlist_rec *rec;
+	struct maildir_uidlist_rec **rec_p;
 	size_t i, size;
 
-	rec = buffer_get_modifyable_data(uidlist->record_buf, &size);
-	size /= sizeof(*rec);
+	rec_p = buffer_get_modifyable_data(uidlist->record_buf, &size);
+	size /= sizeof(*rec_p);
 
 	if (nonsynced) {
 		for (i = 0; i < size; i++)
-			rec[i].flags |= MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
+			rec_p[i]->flags |= MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
 	} else {
 		for (i = 0; i < size; i++)
-			rec[i].flags &= ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
+			rec_p[i]->flags &= ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
 	}
 }
 
@@ -518,6 +520,7 @@
 maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, int partial)
 {
 	struct maildir_uidlist_sync_ctx *ctx;
+	size_t size;
 
 	ctx = i_new(struct maildir_uidlist_sync_ctx, 1);
 	ctx->uidlist = uidlist;
@@ -529,10 +532,13 @@
 		return ctx;
 	}
 
-	ctx->filename_pool =
+	ctx->record_pool =
 		pool_alloconly_create("maildir_uidlist_sync", 16384);
-	ctx->files = hash_create(default_pool, ctx->filename_pool, 4096,
+	ctx->files = hash_create(default_pool, ctx->record_pool, 4096,
 				 maildir_hash, maildir_cmp);
+
+	size = buffer_get_used_size(uidlist->record_buf);
+	ctx->record_buf = buffer_create_dynamic(default_pool, size, (size_t)-1);
 	return ctx;
 }
 
@@ -540,7 +546,7 @@
 {
 	int ret;
 
-	if (ctx->uidlist->last_mtime == 0) {
+	if (!ctx->uidlist->initial_read) {
 		/* first time reading the uidlist,
 		   no locking yet */
 		if (maildir_uidlist_update(ctx->uidlist) < 0) {
@@ -574,17 +580,11 @@
 {
 	struct maildir_uidlist *uidlist = ctx->uidlist;
 	struct maildir_uidlist_rec *rec;
-	void *value;
-	size_t idx;
 	int ret;
 
 	/* we'll update uidlist directly */
-	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) {
+	rec = hash_lookup(uidlist->files, filename);
+	if (rec == NULL && !ctx->synced) {
 		ret = maildir_uidlist_sync_uidlist(ctx);
 		if (ret < 0)
 			return -1;
@@ -593,28 +593,25 @@
 								 flags);
 		}
 
-		if (!hash_lookup_full(uidlist->files, filename, NULL, &value))
-			idx = (size_t)-1;
-		else
-			idx = POINTER_CAST_TO(value, size_t);
+		rec = hash_lookup(uidlist->files, filename);
 	}
 
-	if (idx == (size_t)-1) {
-		ctx->new_files = TRUE;
-		idx = buffer_get_used_size(uidlist->record_buf) / sizeof(*rec);
-		ctx->first_new_pos = idx;
+	if (rec == NULL) {
+		if (!ctx->new_files) {
+			ctx->new_files = TRUE;
+			ctx->first_new_pos =
+				buffer_get_used_size(uidlist->record_buf) /
+				sizeof(rec);
+		}
 
-		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 = p_new(uidlist->record_pool,
+			    struct maildir_uidlist_rec, 1);
+		buffer_append(uidlist->record_buf, &rec, sizeof(rec));
 	}
 
 	rec->flags = (rec->flags | flags) & ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
-	rec->filename = p_strdup(uidlist->filename_pool, filename);
-	hash_insert(uidlist->files, rec->filename, POINTER_CAST(idx));
+	rec->filename = p_strdup(uidlist->record_pool, filename);
+	hash_insert(uidlist->files, rec->filename, rec);
 	return 1;
 }
 
@@ -623,9 +620,7 @@
 			      enum maildir_uidlist_rec_flag flags)
 {
 	struct maildir_uidlist *uidlist = ctx->uidlist;
-	struct maildir_uidlist_rec *rec;
-	void *value;
-	size_t idx;
+	struct maildir_uidlist_rec *rec, *old_rec;
 	int ret;
 
 	if (ctx->failed)
@@ -634,15 +629,8 @@
 	if (ctx->partial)
 		return maildir_uidlist_sync_next_partial(ctx, filename, flags);
 
-	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;
-
+	rec = hash_lookup(ctx->files, filename);
+	if (rec != NULL) {
 		if ((rec->flags & (MAILDIR_UIDLIST_REC_FLAG_NEW_DIR |
 				   MAILDIR_UIDLIST_REC_FLAG_MOVED)) == 0) {
 			/* possibly duplicate */
@@ -652,12 +640,8 @@
 		rec->flags &= ~(MAILDIR_UIDLIST_REC_FLAG_NEW_DIR |
 				MAILDIR_UIDLIST_REC_FLAG_MOVED);
 	} else {
-		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) {
+		old_rec = hash_lookup(uidlist->files, filename);
+		if (old_rec == NULL && !ctx->synced) {
 			ret = maildir_uidlist_sync_uidlist(ctx);
 			if (ret < 0)
 				return -1;
@@ -665,39 +649,35 @@
 				return maildir_uidlist_sync_next(ctx, filename,
 								 flags);
 			}
-			if (!hash_lookup_full(uidlist->files, filename,
-					      NULL, &value))
-				idx = (size_t)-1;
-			else
-				idx = POINTER_CAST_TO(value, size_t);
+			old_rec = hash_lookup(uidlist->files, filename);
 		}
 
-		if (idx == (size_t)-1) {
+		rec = p_new(ctx->record_pool, struct maildir_uidlist_rec, 1);
+		buffer_append(ctx->record_buf, &rec, sizeof(rec));
+
+		if (old_rec != NULL)
+			*rec = *old_rec;
+		else if (!ctx->new_files) {
 			ctx->new_files = TRUE;
-			idx = buffer_get_used_size(uidlist->record_buf) /
+			ctx->first_new_pos =
+				buffer_get_used_size(ctx->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;
 		}
 	}
 
+	if ((flags & MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0 && rec->uid != 0)
+		maildir_uidlist_mark_recent(uidlist, rec->uid);
+
 	rec->flags |= flags;
-	rec->filename = p_strdup(ctx->filename_pool, filename);
-	hash_insert(ctx->files, rec->filename, POINTER_CAST(idx));
+	rec->filename = p_strdup(ctx->record_pool, filename);
+	hash_insert(ctx->files, rec->filename, rec);
 	return 1;
 }
 
 static int maildir_time_cmp(const void *p1, const void *p2)
 {
-	const struct maildir_uidlist_rec *rec1 = p1, *rec2 = p2;
-	const char *s1 = rec1->filename, *s2 = rec2->filename;
+	const struct maildir_uidlist_rec *const *rec1 = p1, *const *rec2 = p2;
+	const char *s1 = (*rec1)->filename, *s2 = (*rec2)->filename;
 	time_t t1 = 0, t2 = 0;
 
 	/* we have to do numeric comparision, strcmp() will break when
@@ -718,115 +698,92 @@
 static void maildir_uidlist_assign_uids(struct maildir_uidlist *uidlist,
 					unsigned int first_new_pos)
 {
-	struct maildir_uidlist_rec *rec;
+	struct maildir_uidlist_rec **rec_p;
 	unsigned int dest;
 	size_t size;
 
-	rec = buffer_get_modifyable_data(uidlist->record_buf, &size);
-	size /= sizeof(*rec);
+	rec_p = buffer_get_modifyable_data(uidlist->record_buf, &size);
+	size /= sizeof(*rec_p);
 
 	/* sort new files and assign UIDs for them */
-	qsort(rec + first_new_pos, size - first_new_pos,
-	      sizeof(*rec), maildir_time_cmp);
+	qsort(rec_p + first_new_pos, size - first_new_pos,
+	      sizeof(*rec_p), maildir_time_cmp);
 	for (dest = first_new_pos; dest < size; dest++) {
-		i_assert(rec[dest].uid == 0);
-		rec[dest].uid = uidlist->next_uid++;
-		rec[dest].flags &= ~MAILDIR_UIDLIST_REC_FLAG_MOVED;
+		i_assert(rec_p[dest]->uid == 0);
+		rec_p[dest]->uid = uidlist->next_uid++;
+		rec_p[dest]->flags &= ~MAILDIR_UIDLIST_REC_FLAG_MOVED;
 
-		if ((rec[dest].flags & MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0) {
-			maildir_uidlist_mark_recent(uidlist,
-						    rec[dest].uid);
-		}
+		if ((rec_p[dest]->flags &
+		     MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0)
+			maildir_uidlist_mark_recent(uidlist, rec_p[dest]->uid);
 	}
 }
 
+static int maildir_uid_cmp(const void *p1, const void *p2)
+{
+	const struct maildir_uidlist_rec *const *rec1 = p1, *const *rec2 = p2;
+
+	return (*rec1)->uid < (*rec2)->uid ? -1 :
+		(*rec1)->uid > (*rec2)->uid ? 1 : 0;
+}
+
 static void maildir_uidlist_swap(struct maildir_uidlist_sync_ctx *ctx)
 {
 	struct maildir_uidlist *uidlist = ctx->uidlist;
-	struct maildir_uidlist_rec *rec;
-	void *key, *value;
+	struct maildir_uidlist_rec **rec_p;
 	size_t size;
-	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;
+	/* buffer is unsorted, sort it by UID up to beginning of new messages */
+	rec_p = buffer_get_modifyable_data(ctx->record_buf, &size);
+	size /= sizeof(*rec_p);
+	if (ctx->new_files)
 		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,
-				      &key, &value))
-			continue;
-
-		rec[dest].uid = rec[src].uid;
-		rec[dest].flags =
-			rec[src].flags & ~MAILDIR_UIDLIST_REC_FLAG_MOVED;
-		rec[dest].filename = key;
-		if ((rec[dest].flags & MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0) {
-			maildir_uidlist_mark_recent(ctx->uidlist,
-						    rec[dest].uid);
-		}
-		dest++;
-	}
+	qsort(rec_p, size, sizeof(*rec_p), maildir_uid_cmp);
 
-	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);
+	buffer_free(uidlist->record_buf);
+	uidlist->record_buf = ctx->record_buf;
+	ctx->record_buf = NULL;
 
 	hash_destroy(uidlist->files);
 	uidlist->files = ctx->files;
 	ctx->files = NULL;
 
-	if (uidlist->filename_pool != NULL)
-		pool_unref(uidlist->filename_pool);
-	uidlist->filename_pool = ctx->filename_pool;
-	ctx->filename_pool = NULL;
+	if (uidlist->record_pool != NULL)
+		pool_unref(uidlist->record_pool);
+	uidlist->record_pool = ctx->record_pool;
+	ctx->record_pool = NULL;
+
+	if (ctx->new_files)
+		maildir_uidlist_assign_uids(uidlist, ctx->first_new_pos);
 }
 
 int maildir_uidlist_sync_deinit(struct maildir_uidlist_sync_ctx *ctx)
 {
-	int ret;
+	int ret = ctx->failed ? -1 : 0;
 
-	if (ctx->failed)
-		ret = -1;
+	// FIXME: we most likely don't handle ctx->failed well enough
+	if (!ctx->partial)
+		maildir_uidlist_swap(ctx);
 	else {
-		if (!ctx->partial)
-			maildir_uidlist_swap(ctx);
-		else {
-			if (ctx->new_files) {
-				maildir_uidlist_assign_uids(ctx->uidlist,
-							    ctx->first_new_pos);
-			}
-			maildir_uidlist_mark_all(ctx->uidlist, FALSE);
+		if (ctx->new_files) {
+			maildir_uidlist_assign_uids(ctx->uidlist,
+						    ctx->first_new_pos);
 		}
-
-		if (!ctx->new_files)
-			ret = 0;
-		else
-			ret = maildir_uidlist_rewrite(ctx->uidlist);
+		maildir_uidlist_mark_all(ctx->uidlist, FALSE);
 	}
 
+	if (ctx->new_files && ret == 0)
+		ret = maildir_uidlist_rewrite(ctx->uidlist);
+
 	if (UIDLIST_IS_LOCKED(ctx->uidlist))
 		maildir_uidlist_unlock(ctx->uidlist);
 
 	if (ctx->files != NULL)
 		hash_destroy(ctx->files);
-	if (ctx->filename_pool != NULL)
-		pool_unref(ctx->filename_pool);
+	if (ctx->record_pool != NULL)
+		pool_unref(ctx->record_pool);
+	if (ctx->record_buf != NULL)
+		buffer_free(ctx->record_buf);
 	i_free(ctx);
 	return ret;
 }
@@ -852,9 +809,9 @@
 	if (ctx->next == ctx->end)
 		return 0;
 
-	*uid_r = ctx->next->uid;
-	*flags_r = ctx->next->flags;
-	*filename_r = ctx->next->filename;
+	*uid_r = (*ctx->next)->uid;
+	*flags_r = (*ctx->next)->flags;
+	*filename_r = (*ctx->next)->filename;
 	ctx->next++;
 	return 1;
 }



More information about the dovecot-cvs mailing list