mail-index-transaction.c revision 7d9954a0609f942dada5ebf98031f1f1b94c5f35
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen/* Inside transaction we keep messages stored in sequences in uid fields.
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen Before they're written to transaction log the sequences are changed to
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen UIDs. This is because we're able to compress sequence ranges better. */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenvoid mail_index_transaction_reset(struct mail_index_transaction *t)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct mail_index_transaction_ext_hdr_update **ext_hdrs;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen recs = array_get_modifiable(&t->ext_rec_updates, &count);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen for (i = 0; i < count; i++) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen ext_hdrs = array_get_modifiable(&t->ext_hdr_updates, &count);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen for (i = 0; i < count; i++)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct mail_index_transaction_keyword_update *u;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen u = array_get_modifiable(&t->keyword_updates, &count);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen for (i = 0; i < count; i++) {
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen t->first_new_seq = mail_index_view_get_messages_count(t->view)+1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen memset(t->pre_hdr_mask, 0, sizeof(t->pre_hdr_mask));
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen memset(t->post_hdr_mask, 0, sizeof(t->post_hdr_mask));
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen mail_cache_transaction_rollback(t->cache_trans_ctx);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenstatic void mail_index_transaction_free(struct mail_index_transaction *t)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenmail_index_transaction_get_view(struct mail_index_transaction *t)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenbool mail_index_transaction_is_expunged(struct mail_index_transaction *t,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenvoid mail_index_transaction_ref(struct mail_index_transaction *t)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenvoid mail_index_transaction_unref(struct mail_index_transaction **_t)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (--t->refcount == 0)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenbool mail_index_seq_array_lookup(const ARRAY_TYPE(seq_array) *array,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* we're probably appending it, check */
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainenstatic bool mail_index_seq_array_add(ARRAY_TYPE(seq_array) *array, uint32_t seq,
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* records need to be 32bit aligned */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen i_assert(array->arr.element_size == sizeof(seq) + aligned_record_size);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen if (mail_index_seq_array_lookup(array, seq, &idx)) {
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen /* already there, update */
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen /* save the old record before overwriting it */
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen memcpy(old_record, PTR_OFFSET(p, sizeof(seq)),
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen memcpy(PTR_OFFSET(p, sizeof(seq)), record, record_size);
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen memcpy(PTR_OFFSET(p, sizeof(seq)), record, record_size);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenmail_index_buffer_convert_to_uids(struct mail_index_transaction *t,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen for (i = 0; i < count; i++) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, *seq - 1);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* we're using only rec->uid, no need to bother locking
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen the index. */
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen /* FIXME: replace with simple assert once we
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen figure out why this happens.. */
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen "first_new_seq = %u, records = %u",
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstatic void keyword_updates_convert_to_uids(struct mail_index_transaction *t)
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen struct mail_index_transaction_keyword_update *updates;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen unsigned int i, count;
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen updates = array_get_modifiable(&t->keyword_updates, &count);
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen for (i = 0; i < count; i++) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (array_is_created(&updates[i].remove_seq)) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenmail_index_transaction_convert_to_uids(struct mail_index_transaction *t)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen unsigned int i, count;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen updates = array_get_modifiable(&t->ext_rec_updates, &count);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen for (i = 0; i < count; i++) {
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen mail_index_buffer_convert_to_uids(t, &updates[i],
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen mail_index_buffer_convert_to_uids(t, (void *)&t->expunges, TRUE);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen mail_index_buffer_convert_to_uids(t, (void *)&t->updates, TRUE);
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen mail_index_buffer_convert_to_uids(t, (void *)&t->keyword_resets, TRUE);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstatic int uid_map_cmp(const void *p1, const void *p2)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenmail_index_update_day_headers(struct mail_index_transaction *t)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen sizeof(hdr.day_first_uid) / sizeof(hdr.day_first_uid[0]);
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen /* get beginning of today */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* get number of days since last message */
b87daa509bf5b306189282a9df795d094a6d7150Timo Sirainen /* @UNSAFE: move days forward and fill the missing days with old
b87daa509bf5b306189282a9df795d094a6d7150Timo Sirainen day_first_uid[0]. */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen memcpy(hdr.day_first_uid + days, hdr.day_first_uid, max_days - days);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen offsetof(struct mail_index_header, day_stamp),
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen &hdr.day_stamp, sizeof(hdr.day_stamp), FALSE);
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen offsetof(struct mail_index_header, day_first_uid),
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen hdr.day_first_uid, sizeof(hdr.day_first_uid), FALSE);
eca38954bcf972618f6b85932a3690acbd2b673aTimo Sirainenvoid mail_index_transaction_sort_appends(struct mail_index_transaction *t)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen unsigned int i, j, count, ext_rec_array_count;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen /* first make a copy of the UIDs and map them to sequences */
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen recs = array_get_modifiable(&t->appends, &count);
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen for (i = 0; i < count; i++) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* now sort the UID map */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen qsort(new_uid_map, count, sizeof(*new_uid_map), uid_map_cmp);
for (i = 0; i < count; i++)
for (i = 0; i < count; i++)
ext_rec_array_count = 0;
for (j = 0; j < ext_rec_array_count; j++) {
unsigned int ext_count;
for (i = 0; i < ext_count; i++) {
(t->first_new_seq +
return next_uid;
int ret;
if (mail_index_transaction_convert_to_uids(t) < 0)
return ret;
t->v.rollback(t);
struct mail_index_record *
if (t->last_new_seq != 0)
if (uid != 0) {
if (!t->appends_nonsorted &&
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;
idx--;
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 i, count;
for (i = 0; i < count; i++) {
return TRUE;
for (i = 0; i < count; i++) {
return TRUE;
for (i = 0; i < count; i++) {
if (ids[i] != 0)
return TRUE;
for (i = 0; i < count; i++) {
return TRUE;
return FALSE;
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) {
struct mail_index_transaction_keyword_update *u;
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++) {
struct mail_index_transaction *
struct mail_index_transaction *t;
t->v = trans_vfuncs;
t->first_new_seq =