str_append_c(mail_ctx.header, '\n');
}
- i_assert(mail_ctx.mail.space == mails[idx].space);
+ /* breaks with leftover space:
+ i_assert(mail_ctx.mail.space == mails[idx].space);*/
sync_ctx->prev_msg_uid = old_prev_msg_uid;
/* we're moving next message - update it's from_offset */
uint32_t first_seq, uint32_t last_seq, off_t extra_space)
{
/* FIXME: with mails[0] = expunged and first_seq=1, we leave the
- \n header? */
+ \n header! */
struct mbox_sync_mail *mails;
size_t size;
uoff_t offset, start_offset, end_offset, dest_offset;
data which hasn't yet been copied backwards. to avoid too much
complexity, we just leave all the rest of the extra space to first
mail */
- extra_per_mail = extra_space / (last_seq - first_seq + 1+3);
+ extra_per_mail = extra_space / (last_seq - first_seq + 1);
idx = last_seq - first_seq;
if (mails[idx].uid != 0)
static int mbox_sync_do(struct index_mailbox *ibox,
struct mail_index_sync_ctx *index_sync_ctx,
- struct mail_index_view *sync_view)
+ struct mail_index_view *sync_view,
+ buffer_t *syncs, struct mail_index_sync_rec *sync_rec)
{
struct mbox_sync_context sync_ctx;
struct mbox_sync_mail_context mail_ctx;
- struct mail_index_sync_rec sync_rec;
struct mail_index_transaction *t;
const struct mail_index_header *hdr;
const struct mail_index_record *rec;
uint8_t new_flags;
off_t space_diff, move_diff;
uoff_t offset, extra_space, trailer_size;
- buffer_t *mails, *syncs;
+ buffer_t *mails;
size_t size;
struct stat st;
int sync_expunge, ret = 0;
istream_raw_mbox_seek(input, 0);
mails = buffer_create_dynamic(default_pool, 4096, (size_t)-1);
- syncs = buffer_create_dynamic(default_pool, 256, (size_t)-1);
- memset(&sync_rec, 0, sizeof(sync_rec));
messages_count = mail_index_view_get_message_count(sync_view);
space_diff = 0; need_space_seq = 0; idx_seq = 0; rec = NULL;
/* get all sync records related to this message */
ret = 1; sync_expunge = FALSE;
mbox_sync_buffer_delete_old(syncs, mail_ctx.mail.uid);
- while (mail_ctx.mail.uid >= sync_rec.uid1 && ret > 0) {
- if (sync_rec.uid1 != 0) {
- i_assert(mail_ctx.mail.uid <= sync_rec.uid2);
- buffer_append(syncs, &sync_rec,
- sizeof(sync_rec));
+ while (mail_ctx.mail.uid >= sync_rec->uid1 && ret > 0) {
+ if (sync_rec->uid1 != 0) {
+ i_assert(mail_ctx.mail.uid <= sync_rec->uid2);
+ buffer_append(syncs, sync_rec,
+ sizeof(*sync_rec));
- if (sync_rec.type ==
+ if (sync_rec->type ==
MAIL_INDEX_SYNC_TYPE_EXPUNGE)
sync_expunge = TRUE;
}
- ret = mail_index_sync_next(index_sync_ctx, &sync_rec);
+ ret = mail_index_sync_next(index_sync_ctx, sync_rec);
if (ret == 0)
- memset(&sync_rec, 0, sizeof(sync_rec));
+ memset(sync_rec, 0, sizeof(*sync_rec));
}
if (ret < 0)
break;
hdr->uid_validity;
}
+ if (!sync_expunge && sync_ctx.first_uid == 0)
+ sync_ctx.first_uid = mail_ctx.mail.uid;
+
if ((mail_ctx.need_rewrite || sync_ctx.expunged_space > 0 ||
buffer_get_used_size(syncs) != 0) && !ibox->readonly) {
if (ibox->mbox_lock_type == F_RDLCK) {
space_diff += sync_ctx.expunged_space;
sync_ctx.expunged_space -= -space_diff;
+ if (mail_ctx.have_eoh && !mail_ctx.updated)
+ str_append_c(mail_ctx.header, '\n');
+
if (space_diff < 0 &&
mbox_sync_grow_file(&sync_ctx, &mail_ctx, -space_diff) < 0)
ret = -1;
/* only syncs left should be just appends (and their updates)
which weren't synced yet for some reason (crash). we'll just
ignore them, as we've overwritten them above. */
- while (mail_index_sync_next(index_sync_ctx, &sync_rec) > 0)
+ while (mail_index_sync_next(index_sync_ctx, sync_rec) > 0)
;
}
str_free(sync_ctx.header);
str_free(sync_ctx.from_line);
buffer_free(mails);
- buffer_free(syncs);
return ret < 0 ? ret : 0;
}
unsigned int lock_id;
uint32_t seq;
uoff_t offset;
+ struct mail_index_sync_rec sync_rec;
+ buffer_t *syncs;
int ret, lock_type;
if (last_commit) {
if (ret <= 0)
return ret;
+ memset(&sync_rec, 0, sizeof(sync_rec));
+ syncs = buffer_create_dynamic(default_pool, 256, (size_t)-1);
+
lock_type = mail_index_sync_have_more(index_sync_ctx) ?
F_WRLCK : F_RDLCK;
if (mbox_lock(ibox, lock_type, &lock_id) > 0 &&
mbox_file_open_stream(ibox) == 0) {
- ret = mbox_sync_do(ibox, index_sync_ctx, sync_view);
+ ret = mbox_sync_do(ibox, index_sync_ctx, sync_view,
+ syncs, &sync_rec);
if (ret == -2) {
/* read lock -> write lock. do it again. */
(void)mbox_unlock(ibox, lock_id);
ret = -1;
else {
ret = mbox_sync_do(ibox, index_sync_ctx,
- sync_view);
+ sync_view, syncs, &sync_rec);
}
}
} else {
ret = -1;
}
+ buffer_free(syncs);
return ret;
}