mail-index-transaction.c revision a1248a194946f2429f1cb0da7cf22bf73e8a11be
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen/* Inside transaction we keep messages stored in sequences in uid fields.
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen Before they're written to transaction log the sequences are changed to
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen UIDs. This is because we're able to compress sequence ranges better. */
503a863a317acba125a4e46435694e35fad769e4Timo Sirainenmail_index_transaction_begin(struct mail_index_view *view,
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen /* don't allow syncing view while there's ongoing transactions */
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen t->first_new_seq = mail_index_view_get_messages_count(t->view)+1;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen /* transaction view cannot work if new records are being added
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen in two places. make sure it doesn't happen. */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenstatic void mail_index_transaction_free(struct mail_index_transaction *t)
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen recs = array_get_modifyable(&t->ext_rec_updates, &count);
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen for (i = 0; i < count; i++) {
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen struct mail_index_transaction_keyword_update *u;
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen u = array_get_modifyable(&t->keyword_updates, &count);
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen for (i = 0; i < count; i++) {
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainenvoid mail_index_transaction_ref(struct mail_index_transaction *t)
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainenvoid mail_index_transaction_unref(struct mail_index_transaction **_t)
c991d8c2c0d5d6c025e24fc00cb06dd61c42456dTimo Sirainen if (--t->refcount == 0)
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainenbool mail_index_seq_array_lookup(const array_t *array, uint32_t seq,
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen unsigned int *idx_r)
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen /* we're probably appending it, check */
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainenstatic bool mail_index_seq_array_add(array_t *array, uint32_t seq,
605eca549c08af753e05c25937bcccd66079c321Timo Sirainen unsigned int idx;
6646bd844c85d5b27451199d8868b6d2357cd293Timo Sirainen i_assert(array->element_size == sizeof(seq) + record_size);
6646bd844c85d5b27451199d8868b6d2357cd293Timo Sirainen if (mail_index_seq_array_lookup(array, seq, &idx)) {
6646bd844c85d5b27451199d8868b6d2357cd293Timo Sirainen /* already there, update */
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen /* save the old record before overwriting it */
6646bd844c85d5b27451199d8868b6d2357cd293Timo Sirainen memcpy(old_record, PTR_OFFSET(p, sizeof(seq)),
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen memcpy(PTR_OFFSET(p, sizeof(seq)), record, record_size);
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen memcpy(PTR_OFFSET(p, sizeof(seq)), record, record_size);
503a863a317acba125a4e46435694e35fad769e4Timo Sirainenmail_index_buffer_convert_to_uids(struct mail_index_transaction *t,
e262f3aa3429dbc74f668bc8bd501cf08b955778Timo Sirainen for (i = 0; i < count; i++) {
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, *seq - 1);
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen /* FIXME: replace with simple assert once we
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen figure out why this happens.. */
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen "first_new_seq = %u, records = %u",
503a863a317acba125a4e46435694e35fad769e4Timo Sirainenstatic void arrays_convert_to_uids(struct mail_index_transaction *t,
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen unsigned int i, count;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen updates = array_get_modifyable(array, &count);
4c9a72e0988d462df49810984dc93b3fd4a24c23Timo Sirainen for (i = 0; i < count; i++) {
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen mail_index_buffer_convert_to_uids(t, &updates[i],
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainenstatic void keyword_updates_convert_to_uids(struct mail_index_transaction *t)
ba14267101444b8f144091cefd437e1ea44d3e32Timo Sirainen struct mail_index_transaction_keyword_update *updates;
ba14267101444b8f144091cefd437e1ea44d3e32Timo Sirainen unsigned int i, count;
ba14267101444b8f144091cefd437e1ea44d3e32Timo Sirainen updates = array_get_modifyable(&t->keyword_updates, &count);
ba14267101444b8f144091cefd437e1ea44d3e32Timo Sirainen for (i = 0; i < count; i++) {
ef174bf5299348e8c0662d235341869f319cfe54Timo Sirainen if (array_is_created(&updates[i].remove_seq)) {
ba14267101444b8f144091cefd437e1ea44d3e32Timo Sirainenmail_index_transaction_convert_to_uids(struct mail_index_transaction *t)
ef174bf5299348e8c0662d235341869f319cfe54Timo Sirainen arrays_convert_to_uids(t, &t->ext_rec_updates, FALSE);
ba14267101444b8f144091cefd437e1ea44d3e32Timo Sirainen mail_index_buffer_convert_to_uids(t, &t->expunges, TRUE);
ba14267101444b8f144091cefd437e1ea44d3e32Timo Sirainen mail_index_buffer_convert_to_uids(t, &t->updates, TRUE);
ba14267101444b8f144091cefd437e1ea44d3e32Timo Sirainen mail_index_buffer_convert_to_uids(t, &t->keyword_resets, TRUE);
c47e837a127c533e67debafde8ccf9691041be16Timo Sirainenstatic int uid_map_cmp(const void *p1, const void *p2)
c47e837a127c533e67debafde8ccf9691041be16Timo Sirainenmail_index_transaction_sort_appends(struct mail_index_transaction *t)
c47e837a127c533e67debafde8ccf9691041be16Timo Sirainen unsigned int i, j, count, ext_rec_array_count;
c47e837a127c533e67debafde8ccf9691041be16Timo Sirainen /* first make a copy of the UIDs and map them to sequences */
c47e837a127c533e67debafde8ccf9691041be16Timo Sirainen recs = array_get_modifyable(&t->appends, &count);
c47e837a127c533e67debafde8ccf9691041be16Timo Sirainen for (i = 0; i < count; i++) {
c47e837a127c533e67debafde8ccf9691041be16Timo Sirainen /* now sort the UID map */
c47e837a127c533e67debafde8ccf9691041be16Timo Sirainen qsort(new_uid_map, count, sizeof(*new_uid_map), uid_map_cmp);
c47e837a127c533e67debafde8ccf9691041be16Timo Sirainen for (i = 0; i < count; i++)
c47e837a127c533e67debafde8ccf9691041be16Timo Sirainen /* sort mail records */
eb5ea3f4513ff2999892b8d904551f58b74f65f9Timo Sirainen sorted_recs = i_new(struct mail_index_record, count);
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen for (i = 0; i < count; i++)
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen buffer_write(t->appends.buffer, 0, sorted_recs,
e4cebacdec9c9e5b685dde5f7cbf7a5cf7e1d248Timo Sirainen /* fix the order in extensions */
e4cebacdec9c9e5b685dde5f7cbf7a5cf7e1d248Timo Sirainen ext_rec_arrays = array_get_modifyable(&t->ext_rec_updates,
e4cebacdec9c9e5b685dde5f7cbf7a5cf7e1d248Timo Sirainen for (j = 0; j < ext_rec_array_count; j++) {
e4cebacdec9c9e5b685dde5f7cbf7a5cf7e1d248Timo Sirainen for (i = 0; i < ext_count; i++) {
e4cebacdec9c9e5b685dde5f7cbf7a5cf7e1d248Timo Sirainen seq = *ext_rec < t->first_new_seq ? *ext_rec :
9905ec03fb2011419caeac4cd5a1b6c28ab50a73Timo Sirainen mail_index_seq_array_add(&new_array, seq, ext_rec+1,
90b50df264b57e0f63cd8cc6aea1ce3bb7cf5f64Timo Sirainen /* FIXME: fix the order in keywords */
90b50df264b57e0f63cd8cc6aea1ce3bb7cf5f64Timo Sirainenint mail_index_transaction_commit(struct mail_index_transaction **_t,
90b50df264b57e0f63cd8cc6aea1ce3bb7cf5f64Timo Sirainen if (mail_index_view_is_inconsistent(t->view)) {
90b50df264b57e0f63cd8cc6aea1ce3bb7cf5f64Timo Sirainen mail_cache_transaction_commit(t->cache_trans_ctx);
90b50df264b57e0f63cd8cc6aea1ce3bb7cf5f64Timo Sirainen if (mail_index_transaction_convert_to_uids(t) < 0)
90b50df264b57e0f63cd8cc6aea1ce3bb7cf5f64Timo Sirainen ret = mail_transaction_log_append(t, log_file_seq_r,
90b50df264b57e0f63cd8cc6aea1ce3bb7cf5f64Timo Sirainenvoid mail_index_transaction_rollback(struct mail_index_transaction **_t)
90b50df264b57e0f63cd8cc6aea1ce3bb7cf5f64Timo Sirainen mail_cache_transaction_rollback(t->cache_trans_ctx);
5fdeff082e329e4a85bb7e74aaec2c35e2288557Timo Sirainenmail_index_transaction_lookup(struct mail_index_transaction *t, uint32_t seq)
5fdeff082e329e4a85bb7e74aaec2c35e2288557Timo Sirainen i_assert(seq >= t->first_new_seq && seq <= t->last_new_seq);
5fdeff082e329e4a85bb7e74aaec2c35e2288557Timo Sirainen return array_idx_modifyable(&t->appends, seq - t->first_new_seq);
5fdeff082e329e4a85bb7e74aaec2c35e2288557Timo Sirainenvoid mail_index_append(struct mail_index_transaction *t, uint32_t uid,
5fdeff082e329e4a85bb7e74aaec2c35e2288557Timo Sirainen /* sequence number is visible only inside given view,
5fdeff082e329e4a85bb7e74aaec2c35e2288557Timo Sirainen so let it generate it */
5fdeff082e329e4a85bb7e74aaec2c35e2288557Timo Sirainen /* if previous record's UID is larger than this one,
unsigned int i, count;
for (i = 0; i < count; i++) {
for (; i < count; i++) {
struct mail_transaction_flag_update u,
unsigned int count;
idx++;
tmp_update = u;
move = 0;
~u.remove_flags;
~u.add_flags;
switch (modify_type) {
case MODIFY_REPLACE:
case MODIFY_ADD:
case MODIFY_REMOVE:
unsigned int count;
memset(&u, 0, sizeof(u));
switch (modify_type) {
case MODIFY_REPLACE:
case MODIFY_ADD:
case MODIFY_REMOVE:
t->last_update_idx++;
last_update++;
count);
bool prepend)
if (prepend) {
unsigned int count;
count = 0;
old_data_r)) {
struct mail_keywords *
const char *const keywords[])
struct mail_keywords *k;
unsigned int i, count;
if (count == 0) {
for (i = 0; i < count; i++) {
struct mail_keywords *
struct mail_keywords *k;
unsigned int count;
if (count == 0) {
unsigned int i, ku_count;
switch (modify_type) {
case MODIFY_ADD:
case MODIFY_REMOVE:
case MODIFY_REPLACE:
&ku_count);
for (i = 0; i < ku_count; i++) {