mail-index-transaction.c revision 5b1980a4dd8baad683578351d7f154b87c5f35e0
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2003-2004 Timo Sirainen */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic void mail_index_transaction_add_last(struct mail_index_transaction *t);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenmail_index_transaction_begin(struct mail_index_view *view, int hide)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen /* don't allow syncing view while there's ongoing transactions */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic void mail_index_transaction_free(struct mail_index_transaction *t)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenint mail_index_transaction_commit(struct mail_index_transaction *t,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if (mail_index_view_is_inconsistent(t->view)) {
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen ret = mail_transaction_log_append(t, log_file_seq_r, log_file_offset_r);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenvoid mail_index_transaction_rollback(struct mail_index_transaction *t)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenvoid mail_index_append(struct mail_index_transaction *t, uint32_t uid,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen t->appends = buffer_create_dynamic(default_pool,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* sequence number is visible only inside given view,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen so let it generate it */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen rec = buffer_append_space_unsafe(t->appends, sizeof(*rec));
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenvoid mail_index_expunge(struct mail_index_transaction *t, uint32_t seq)
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_message_count(t->view));
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen /* expunges is a sorted array of {seq1, seq2, ..}, .. */
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen t->expunges = buffer_create_dynamic(default_pool,
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen buffer_append(t->expunges, &exp, sizeof(exp));
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen data = buffer_get_modifyable_data(t->expunges, &size);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen /* quick checks */
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen /* grow last range */
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen buffer_append(t->expunges, &exp, sizeof(exp));
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen /* grow down first range */
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen buffer_insert(t->expunges, 0, &exp, sizeof(exp));
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen /* somewhere in the middle, array is sorted so find it with
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen binary search */
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen /* idx == size couldn't happen because we already handle it above */
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen i_assert(idx < size && data[idx].seq1 >= seq);
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen if (data[idx].seq1 <= seq && data[idx].seq2 >= seq) {
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen /* already expunged */
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen buffer_delete(t->expunges, idx * sizeof(*data),
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen i_assert(idx+1 < size); /* already handled above */
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen buffer_delete(t->expunges, idx * sizeof(*data),
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen buffer_insert(t->expunges, idx * sizeof(*data),
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenstatic void mail_index_record_modify_flags(struct mail_index_record *rec,
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen memcpy(rec->keywords, keywords, INDEX_KEYWORDS_BYTE_COUNT);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen#define IS_COMPATIBLE_UPDATE(t, modify_type, flags, keywords) \
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen ((t)->last_update_modify_type == (modify_type) && \
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen memcmp((t)->last_update.add_keywords, keywords, \
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenvoid mail_index_update_flags(struct mail_index_transaction *t, uint32_t seq,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen enum mail_flags flags, keywords_mask_t keywords)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (t->first_new_seq != 0 && seq >= t->first_new_seq) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* just appended message, modify it directly */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen pos = (seq - t->first_new_seq) * sizeof(*rec);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen rec = buffer_get_space_unsafe(t->appends, pos, sizeof(*rec));
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen mail_index_record_modify_flags(rec, modify_type,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_message_count(t->view));
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* first get group updates into same structure. this allows faster
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen updates if same mails have multiple flag updates during same
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen transaction (eg. 1:10 +seen, 1:10 +deleted) */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen IS_COMPATIBLE_UPDATE(t, modify_type, flags, keywords)) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen IS_COMPATIBLE_UPDATE(t, modify_type, flags, keywords)) {
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen t->last_update.seq1 = t->last_update.seq2 = seq;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainenmail_index_transaction_get_last(struct mail_index_transaction *t,
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* remove_flags = ~add_flags */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++)
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen update->remove_keywords[i] = ~update->add_keywords[i];
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* already in add_flags */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* add_flags -> remove_flags */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen memcpy(&update->remove_keywords, &update->add_keywords,
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen memset(&update->add_keywords, 0, INDEX_KEYWORDS_BYTE_COUNT);
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainenstatic void mail_index_transaction_add_last(struct mail_index_transaction *t)
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen struct mail_transaction_flag_update update, *data;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen t->updates = buffer_create_dynamic(default_pool,
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen data = buffer_get_modifyable_data(t->updates, &size);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen /* find the nearest sequence from existing updates */
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen if (idx < size && data[idx].seq2 < update.seq1)
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen i_assert(idx == size || data[idx].seq1 < update.seq1);
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen /* insert it into buffer, split it in multiple parts if needed
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen to make sure the ordering stays the same */
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen /* partial */
632018810af689442569cbb0139c55868923ccfeTimo Sirainen buffer_insert(t->updates, idx * sizeof(update),
632018810af689442569cbb0139c55868923ccfeTimo Sirainen data = buffer_get_modifyable_data(t->updates, NULL);
632018810af689442569cbb0139c55868923ccfeTimo Sirainen buffer_insert(t->updates, idx * sizeof(update),
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainenvoid mail_index_update_cache(struct mail_index_transaction *t,
632018810af689442569cbb0139c55868923ccfeTimo Sirainen struct mail_transaction_cache_update *data, update;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen t->cache_updates = buffer_create_dynamic(default_pool,
632018810af689442569cbb0139c55868923ccfeTimo Sirainen data = buffer_get_modifyable_data(t->cache_updates, &size);
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* we're probably appending it, check */
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen /* already there, update */