예제 #1
0
static int index_list_update_mail_index(struct index_mailbox_list *ilist,
					struct mailbox *box)
{
	struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
	struct mail_index_sync_ctx *mail_sync_ctx;
	struct mail_index_view *view;
	struct mail_index_transaction *trans;
	struct mail_index_sync_rec sync_rec;
	int ret;

	if (ibox->log_seq == 0)
		return 0;

	ret = mail_index_sync_begin_to(ilist->mail_index,
				       &mail_sync_ctx, &view, &trans,
				       ibox->log_seq, ibox->log_offset, 0);
	if (ret <= 0)
		return ret;

	/* we should have only external transactions in here, for which we
	   don't need to do anything but write them to the index */
	while (mail_index_sync_next(mail_sync_ctx, &sync_rec))
		;

	return mail_index_sync_commit(&mail_sync_ctx);
}
예제 #2
0
static int mdbox_sync_index(struct mdbox_sync_context *ctx)
{
	struct mailbox *box = &ctx->mbox->box;
	const struct mail_index_header *hdr;
	struct mail_index_sync_rec sync_rec;
	uint32_t seq1, seq2;
	int ret = 0;

	hdr = mail_index_get_header(ctx->sync_view);
	if (hdr->uid_validity == 0) {
		/* newly created index file */
		mail_storage_set_critical(box->storage,
			"Mailbox %s: Corrupted index, uidvalidity=0",
			box->vname);
		return 0;
	}

	/* mark the newly seen messages as recent */
	if (mail_index_lookup_seq_range(ctx->sync_view, hdr->first_recent_uid,
					hdr->next_uid, &seq1, &seq2)) {
		index_mailbox_set_recent_seq(&ctx->mbox->box, ctx->sync_view,
					     seq1, seq2);
	}

	/* handle syncing records without map being locked. */
	if (mdbox_map_atomic_is_locked(ctx->atomic)) {
		ctx->map_trans = mdbox_map_transaction_begin(ctx->atomic, FALSE);
		i_array_init(&ctx->expunged_seqs, 64);
	}
	while (mail_index_sync_next(ctx->index_sync_ctx, &sync_rec)) {
		if ((ret = mdbox_sync_rec(ctx, &sync_rec)) < 0)
			break;
	}

	/* write refcount changes to map index. transaction commit updates the
	   log head, while tail is left behind. */
	if (mdbox_map_atomic_is_locked(ctx->atomic)) {
		if (ret == 0)
			ret = mdbox_map_transaction_commit(ctx->map_trans);
		/* write changes to mailbox index */
		if (ret == 0)
			ret = dbox_sync_mark_expunges(ctx);

		/* finish the map changes and unlock the map. this also updates
		   map's tail -> head. */
		if (ret < 0)
			mdbox_map_atomic_set_failed(ctx->atomic);
		mdbox_map_transaction_free(&ctx->map_trans);
		array_free(&ctx->expunged_seqs);
	}

	if (box->v.sync_notify != NULL)
		box->v.sync_notify(box, 0, 0);

	return ret == 0 ? 1 :
		(ctx->mbox->storage->corrupted ? 0 : -1);
}
예제 #3
0
static void cydir_sync_index(struct cydir_sync_context *ctx)
{
	struct mailbox *box = &ctx->mbox->box;
	const struct mail_index_header *hdr;
	struct mail_index_sync_rec sync_rec;
	uint32_t seq1, seq2;

	hdr = mail_index_get_header(ctx->sync_view);
	if (hdr->uid_validity != 0)
		ctx->uid_validity = hdr->uid_validity;
	else
		cydir_sync_set_uidvalidity(ctx);

	/* mark the newly seen messages as recent */
	if (mail_index_lookup_seq_range(ctx->sync_view, hdr->first_recent_uid,
					hdr->next_uid, &seq1, &seq2)) {
		mailbox_recent_flags_set_seqs(&ctx->mbox->box, ctx->sync_view,
					      seq1, seq2);
	}

	while (mail_index_sync_next(ctx->index_sync_ctx, &sync_rec)) {
		if (!mail_index_lookup_seq_range(ctx->sync_view,
						 sync_rec.uid1, sync_rec.uid2,
						 &seq1, &seq2)) {
			/* already expunged, nothing to do. */
			continue;
		}

		switch (sync_rec.type) {
		case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
			cydir_sync_expunge(ctx, seq1, seq2);
			break;
		case MAIL_INDEX_SYNC_TYPE_FLAGS:
		case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
		case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
			/* FIXME: should be bother calling sync_notify()? */
			break;
		}
	}

	if (box->v.sync_notify != NULL)
		box->v.sync_notify(box, 0, 0);
}
예제 #4
0
void index_sync_changes_read(struct index_sync_changes_context *ctx,
			     uint32_t uid, bool *sync_expunge_r,
			     guid_128_t expunged_guid_128_r)
{
	struct mail_index_sync_rec *sync_rec = &ctx->sync_rec;
	uint32_t seq1, seq2;
	unsigned int orig_count;

	*sync_expunge_r = FALSE;

	index_sync_changes_delete_to(ctx, uid);
	orig_count = array_count(&ctx->syncs);

	while (uid >= sync_rec->uid1) {
		if (uid <= sync_rec->uid2) {
			array_append(&ctx->syncs, sync_rec, 1);

			if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_EXPUNGE) {
				*sync_expunge_r = TRUE;
				memcpy(expunged_guid_128_r, sync_rec->guid_128,
				       GUID_128_SIZE);
			}
		}

		if (!mail_index_sync_next(ctx->index_sync_ctx, sync_rec)) {
			memset(sync_rec, 0, sizeof(*sync_rec));
			break;
		}

		switch (sync_rec->type) {
		case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
			break;
		case MAIL_INDEX_SYNC_TYPE_FLAGS:
		case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
		case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
			if (!ctx->dirty_flag_updates)
				break;

			/* mark the changes as dirty */
			(void)mail_index_lookup_seq_range(ctx->sync_view,
							  sync_rec->uid1,
							  sync_rec->uid2,
							  &seq1, &seq2);
			memset(sync_rec, 0, sizeof(*sync_rec));

			if (seq1 == 0)
				break;

			mail_index_update_flags_range(ctx->sync_trans,
				seq1, seq2, MODIFY_ADD,
				(enum mail_flags)MAIL_INDEX_MAIL_FLAG_DIRTY);
			break;
		}
	}

	if (!*sync_expunge_r && orig_count > 0) {
		*sync_expunge_r =
			index_sync_changes_have_expunges(ctx, orig_count,
							 expunged_guid_128_r);
	}
}