mail-index-transaction.c revision 460bbc67ac18cb3155708693436b87410000288d
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen/* Inside transaction we keep messages stored in sequences in uid fields.
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen Before they're written to transaction log the sequences are changed to
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen UIDs. This is because we're able to compress sequence ranges better. */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic void mail_index_transaction_add_last(struct mail_index_transaction *t);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenmail_index_transaction_begin(struct mail_index_view *view,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* don't allow syncing view while there's ongoing transactions */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen t->first_new_seq = mail_index_view_get_messages_count(t->view)+1;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* transaction view cannot work if new records are being added
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch in two places. make sure it doesn't happen. */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic void mail_keyword_transaction_free(struct mail_keyword_transaction *kt)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen for (p = &kt->keywords->kt; *p != NULL; p = &(*p)->next) {
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch if (*p == kt) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* no transactions left, free mail_keywords */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic void mail_index_transaction_free(struct mail_index_transaction *t)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen recs = buffer_get_modifyable_data(t->ext_rec_updates, &size);
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch for (i = 0; i < size; i++) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen kt = buffer_get_modifyable_data(t->keyword_updates, &size);
1c75bf24894a3fc0631caa4954e5130e9bb01d8dTimo Sirainen for (i = 0; i < size; i++)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenvoid mail_index_transaction_ref(struct mail_index_transaction *t)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenvoid mail_index_transaction_unref(struct mail_index_transaction *t)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (--t->refcount == 0)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenmail_index_buffer_convert_to_uids(struct mail_index_transaction *t,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen unsigned char *data;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* @UNSAFE */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen data = buffer_get_modifyable_data(buf, &size);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenmail_index_transaction_convert_to_uids(struct mail_index_transaction *t)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen extensions = buffer_get_data(index->extensions, NULL);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen updates = buffer_get_modifyable_data(t->ext_rec_updates, &size);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen for (i = 0; i < size; i++) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen mail_index_buffer_convert_to_uids(t, updates[i],
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen kt = buffer_get_modifyable_data(t->keyword_updates, &size);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen for (i = 0; i < size; i++) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen mail_index_buffer_convert_to_uids(t, kt[i]->messages,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen mail_index_buffer_convert_to_uids(t, t->expunges,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen sizeof(struct mail_transaction_expunge), TRUE);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen mail_index_buffer_convert_to_uids(t, t->updates,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen sizeof(struct mail_transaction_flag_update), TRUE);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenint mail_index_transaction_commit(struct mail_index_transaction *t,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (mail_index_view_is_inconsistent(t->view)) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen mail_cache_transaction_commit(t->cache_trans_ctx);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (mail_index_transaction_convert_to_uids(t) < 0)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ret = mail_transaction_log_append(t, log_file_seq_r,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenvoid mail_index_transaction_rollback(struct mail_index_transaction *t)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen mail_cache_transaction_rollback(t->cache_trans_ctx);
8855b8b57050fe3b6dc3f19283488512fae98648Timo Sirainenmail_index_transaction_lookup(struct mail_index_transaction *t, uint32_t seq)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen i_assert(seq >= t->first_new_seq && seq <= t->last_new_seq);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen pos = (seq - t->first_new_seq) * sizeof(struct mail_index_record);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return buffer_get_space_unsafe(t->appends, pos,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch sizeof(struct mail_index_record));
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschvoid mail_index_append(struct mail_index_transaction *t, uint32_t uid,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch t->appends = buffer_create_dynamic(default_pool, 4096);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* sequence number is visible only inside given view,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen so let it generate it */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch rec = buffer_append_space_unsafe(t->appends, sizeof(*rec));
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschvoid mail_index_append_assign_uids(struct mail_index_transaction *t,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch rec = buffer_get_modifyable_data(t->appends, &size);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* find the first mail with uid = 0 */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschstatic void mail_index_update_seq_range_buffer(buffer_t *buffer, uint32_t seq)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch data = buffer_get_modifyable_data(buffer, &size);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* quick checks */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* grow last range */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* grow down first range */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen buffer_insert(buffer, 0, &value, sizeof(value));
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* somewhere in the middle, array is sorted so find it with
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen binary search */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* it's already expunged */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* idx == size couldn't happen because we already handle it above */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen i_assert(idx < size && data[idx].seq1 >= seq);
sizeof(*data));
sizeof(*data));
switch (modify_type) {
case MODIFY_REPLACE:
case MODIFY_ADD:
case MODIFY_REMOVE:
switch (t->last_update_modify_type) {
case MODIFY_REPLACE:
case MODIFY_ADD:
case MODIFY_REMOVE:
idx++;
size++;
void *data;
if (size == 0)
idx = 0;
return TRUE;
return FALSE;
void *old_record)
return FALSE;
return TRUE;
return FALSE;
size = 0;
sizeof(buffer_t *));
old_data_r)) {
static struct mail_keyword_transaction *
return kt;
static struct mail_keywords *
struct mail_keywords k;
uint8_t *b;
if (count == 0)
t_push();
memset(&k, 0, sizeof(k));
for (i = 0; i < count; i++) {
k.start = j;
k.end = j;
k.count++;
if (missing_count > 0) {
j = size / sizeof(const char *);
k.end = j;
k.count++;
t_pop();
struct mail_keywords *
const char *const keywords[])
struct mail_keywords *k;
(void)mail_keyword_transaction_new(t, k);