mail-index-transaction.c revision ae6c13635a316a0c6069a462d5a52f249089785a
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* Inside transaction we keep messages stored in sequences in uid fields.
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen Before they're written to transaction log the sequences are changed to
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen UIDs. This is because we're able to compress sequence ranges better. */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "lib.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "buffer.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-index-view-private.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-transaction-log.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-cache-private.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-index-transaction-private.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <stddef.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <stdlib.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenstruct mail_index_transaction *
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenmail_index_transaction_begin(struct mail_index_view *view,
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen int hide, int external)
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen{
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen struct mail_index_transaction *t;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen /* don't allow syncing view while there's ongoing transactions */
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen mail_index_view_transaction_ref(view);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen mail_index_view_ref(view);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen t = i_new(struct mail_index_transaction, 1);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen t->refcount = 1;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen t->view = view;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen t->hide_transaction = hide;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen t->external = external;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen t->first_new_seq = mail_index_view_get_messages_count(t->view)+1;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen if (view->syncing) {
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen /* transaction view cannot work if new records are being added
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen in two places. make sure it doesn't happen. */
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen t->no_appends = TRUE;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen }
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen return t;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void mail_keyword_transaction_free(struct mail_keyword_transaction *kt)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_keyword_transaction **p;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen for (p = &kt->keywords->kt; *p != NULL; p = &(*p)->next) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (*p == kt) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen *p = kt->next;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen break;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (*p == NULL) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* no transactions left, free mail_keywords */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(kt->keywords->kt == NULL);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen i_free(kt->keywords);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen }
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen if (kt->messages != NULL)
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen buffer_free(kt->messages);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen i_free(kt);
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen}
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainenstatic void mail_index_transaction_free(struct mail_index_transaction *t)
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen{
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen buffer_t **recs;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen size_t i, size;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen if (t->ext_rec_updates != NULL) {
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen recs = buffer_get_modifyable_data(t->ext_rec_updates, &size);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen size /= sizeof(*recs);
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen for (i = 0; i < size; i++) {
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen if (recs[i] != NULL)
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen buffer_free(recs[i]);
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen }
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen buffer_free(t->ext_rec_updates);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen }
df831edaa3b3aa22e03bc5fd416a0553c5600a69Phil Carmody
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen if (t->keyword_updates != NULL) {
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen struct mail_keyword_transaction **kt;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen kt = buffer_get_modifyable_data(t->keyword_updates, &size);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen size /= sizeof(*kt);
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen for (i = 0; i < size; i++)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen mail_keyword_transaction_free(kt[i]);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen buffer_free(t->keyword_updates);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (t->appends != NULL)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen buffer_free(t->appends);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (t->expunges != NULL)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen buffer_free(t->expunges);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (t->updates != NULL)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen buffer_free(t->updates);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (t->ext_resizes != NULL)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen buffer_free(t->ext_resizes);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (t->ext_resets != NULL)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen buffer_free(t->ext_resets);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen mail_index_view_transaction_unref(t->view);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen mail_index_view_close(t->view);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen i_free(t);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen}
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenvoid mail_index_transaction_ref(struct mail_index_transaction *t)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen{
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen t->refcount++;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen}
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid mail_index_transaction_unref(struct mail_index_transaction *t)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if (--t->refcount == 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_index_transaction_free(t);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainenstatic void
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainenmail_index_buffer_convert_to_uids(struct mail_index_transaction *t,
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen buffer_t *buf, size_t record_size, int range)
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct mail_index_view *view = t->view;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const struct mail_index_record *rec;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen unsigned char *data;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_t size, i;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen uint32_t *seq;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen int j;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen if (buf == NULL)
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen return;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen /* @UNSAFE */
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen data = buffer_get_modifyable_data(buf, &size);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen for (i = 0; i < size; i += record_size) {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen seq = (uint32_t *)&data[i];
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen for (j = 0; j <= range; j++, seq++) {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen if (*seq >= t->first_new_seq) {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen rec = mail_index_transaction_lookup(t, *seq);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen *seq = rec->uid;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen } else {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen i_assert(*seq <= view->map->records_count);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen *seq = MAIL_INDEX_MAP_IDX(view->map,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen *seq - 1)->uid;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen i_assert(*seq != 0);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen }
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainenstatic int
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainenmail_index_transaction_convert_to_uids(struct mail_index_transaction *t)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
a2738cdb6d2733fb3e186331d68009421a19ea00Timo Sirainen struct mail_index *index = t->view->index;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen const struct mail_index_ext *extensions;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen buffer_t **updates;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen size_t i, size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen if (mail_index_view_lock(t->view) < 0)
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen return -1;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen if (t->ext_rec_updates != NULL) {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen extensions = buffer_get_data(index->extensions, NULL);
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen updates = buffer_get_modifyable_data(t->ext_rec_updates, &size);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen size /= sizeof(*updates);
7af4788b402346c94496095dd819f95ce03fe431Timo Sirainen
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen for (i = 0; i < size; i++) {
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen if (updates[i] == NULL)
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen continue;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen mail_index_buffer_convert_to_uids(t, updates[i],
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen sizeof(uint32_t) + extensions[i].record_size,
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen FALSE);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen }
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen }
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (t->keyword_updates != NULL) {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen struct mail_keyword_transaction **kt;
c24ef531ca58abad996482f5c2e8992be9ae8981Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen kt = buffer_get_modifyable_data(t->keyword_updates, &size);
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen size /= sizeof(*kt);
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen for (i = 0; i < size; i++) {
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen if (kt[i]->messages == NULL)
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen continue;
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen
2524ef7b34965a1b1895d6140fd8296bf57c78d2Timo Sirainen mail_index_buffer_convert_to_uids(t, kt[i]->messages,
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen sizeof(uint32_t) * 2, TRUE);
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen }
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen mail_index_buffer_convert_to_uids(t, t->expunges,
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen sizeof(struct mail_transaction_expunge), TRUE);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_index_buffer_convert_to_uids(t, t->updates,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen sizeof(struct mail_transaction_flag_update), TRUE);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return 0;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen}
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenint mail_index_transaction_commit(struct mail_index_transaction *t,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen uint32_t *log_file_seq_r,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen uoff_t *log_file_offset_r)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen{
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen int ret;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (mail_index_view_is_inconsistent(t->view)) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen mail_index_transaction_rollback(t);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return -1;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen }
66dc739bb67d678770e1b7a7bc75f4f6f9523d2aTimo Sirainen
66dc739bb67d678770e1b7a7bc75f4f6f9523d2aTimo Sirainen if (t->cache_trans_ctx != NULL) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen mail_cache_transaction_commit(t->cache_trans_ctx);
66dc739bb67d678770e1b7a7bc75f4f6f9523d2aTimo Sirainen t->cache_trans_ctx = NULL;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen }
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (mail_index_transaction_convert_to_uids(t) < 0)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen ret = -1;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen else {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen ret = mail_transaction_log_append(t, log_file_seq_r,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen log_file_offset_r);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen }
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen mail_index_transaction_unref(t);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return ret;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen}
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenvoid mail_index_transaction_rollback(struct mail_index_transaction *t)
c6b6ac7819931dfa92c0182ffaa7db07ac6ab0daTimo Sirainen{
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (t->cache_trans_ctx != NULL) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen mail_cache_transaction_rollback(t->cache_trans_ctx);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen t->cache_trans_ctx = NULL;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_index_transaction_unref(t);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstruct mail_index_record *
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainenmail_index_transaction_lookup(struct mail_index_transaction *t, uint32_t seq)
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen size_t pos;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(seq >= t->first_new_seq && seq <= t->last_new_seq);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen pos = (seq - t->first_new_seq) * sizeof(struct mail_index_record);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return buffer_get_space_unsafe(t->appends, pos,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen sizeof(struct mail_index_record));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvoid mail_index_append(struct mail_index_transaction *t, uint32_t uid,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen uint32_t *seq_r)
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct mail_index_record *rec;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_assert(!t->no_appends);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen t->log_updates = TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen if (t->appends == NULL)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen t->appends = buffer_create_dynamic(default_pool, 4096);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen /* sequence number is visible only inside given view,
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen so let it generate it */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen if (t->last_new_seq != 0)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen *seq_r = ++t->last_new_seq;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen else
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen *seq_r = t->last_new_seq = t->first_new_seq;
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen rec = buffer_append_space_unsafe(t->appends, sizeof(*rec));
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen memset(rec, 0, sizeof(*rec));
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen rec->uid = uid;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenvoid mail_index_append_assign_uids(struct mail_index_transaction *t,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen uint32_t first_uid, uint32_t *next_uid_r)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen{
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen struct mail_index_record *rec, *end;
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen size_t size;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen if (t->appends == NULL)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen return;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen rec = buffer_get_modifyable_data(t->appends, &size);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen end = PTR_OFFSET(rec, size);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen /* find the first mail with uid = 0 */
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen for (; rec != end; rec++) {
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen if (rec->uid == 0)
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen break;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen for (; rec != end; rec++) {
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen i_assert(rec->uid == 0);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen rec->uid = first_uid++;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen }
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen *next_uid_r = first_uid;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstruct seq_range {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen uint32_t seq1, seq2;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen};
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstatic void mail_index_update_seq_range_buffer(buffer_t *buffer, uint32_t seq)
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen{
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen struct seq_range *data, value;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen unsigned int idx, left_idx, right_idx;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen size_t size;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen value.seq1 = value.seq2 = seq;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen data = buffer_get_modifyable_data(buffer, &size);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen size /= sizeof(*data);
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen i_assert(size > 0);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen /* quick checks */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (data[size-1].seq2 == seq-1) {
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen /* grow last range */
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen data[size-1].seq2 = seq;
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen return;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen }
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen if (data[size-1].seq2 < seq) {
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen buffer_append(buffer, &value, sizeof(value));
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen return;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (data[0].seq1 == seq+1) {
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen /* grow down first range */
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen data[0].seq1 = seq;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (data[0].seq1 > seq) {
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen buffer_insert(buffer, 0, &value, sizeof(value));
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen /* somewhere in the middle, array is sorted so find it with
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen binary search */
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen idx = 0; left_idx = 0; right_idx = size;
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen while (left_idx < right_idx) {
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen idx = (left_idx + right_idx) / 2;
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen if (data[idx].seq1 <= seq) {
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen if (data[idx].seq2 >= seq) {
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen /* it's already expunged */
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen return;
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen }
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen left_idx = idx+1;
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen } else {
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen right_idx = idx;
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen }
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen }
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen if (data[idx].seq2 < seq)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen idx++;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* idx == size couldn't happen because we already handle it above */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_assert(idx < size && data[idx].seq1 >= seq);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_assert(data[idx].seq1 > seq || data[idx].seq2 < seq);
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (data[idx].seq1 == seq+1) {
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen data[idx].seq1 = seq;
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen if (idx > 0 && data[idx-1].seq2 == seq-1) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* merge */
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen data[idx-1].seq2 = data[idx].seq2;
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen buffer_delete(buffer, idx * sizeof(*data),
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen sizeof(*data));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen } else if (data[idx].seq2 == seq-1) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_assert(idx+1 < size); /* already handled above */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen data[idx].seq2 = seq;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (data[idx+1].seq1 == seq+1) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* merge */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen data[idx+1].seq1 = data[idx].seq1;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen buffer_delete(buffer, idx * sizeof(*data),
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen sizeof(*data));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen } else {
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen buffer_insert(buffer, idx * sizeof(*data),
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen &value, sizeof(value));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen}
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenvoid mail_index_expunge(struct mail_index_transaction *t, uint32_t seq)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen{
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(t->view));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen t->log_updates = TRUE;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen /* expunges is a sorted array of {seq1, seq2, ..}, .. */
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (t->expunges == NULL) {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen t->expunges = buffer_create_dynamic(default_pool, 1024);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen buffer_append(t->expunges, &seq, sizeof(seq));
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen buffer_append(t->expunges, &seq, sizeof(seq));
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen }
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen mail_index_update_seq_range_buffer(t->expunges, seq);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic void
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainenmail_index_insert_flag_update(struct mail_index_transaction *t,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_transaction_flag_update u,
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen uint32_t left_idx, uint32_t right_idx)
df16c7e87511fed827e6890a2a47d13ca48716deTimo Sirainen{
df16c7e87511fed827e6890a2a47d13ca48716deTimo Sirainen struct mail_transaction_flag_update *updates, tmp_update;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_t size;
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen uint32_t idx;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen updates = buffer_get_modifyable_data(t->updates, &size);
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen size /= sizeof(*updates);
b7651d283ca261015ef3c445f1f27f340f0864e2Timo Sirainen
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen i_assert(left_idx <= right_idx && right_idx <= size);
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen /* find the first update with either overlapping range,
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen or the update which will come after our insert */
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen idx = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen while (left_idx < right_idx) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen idx = (left_idx + right_idx) / 2;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen if (updates[idx].uid1 < u.uid1)
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen left_idx = idx+1;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen else if (updates[idx].uid1 > u.uid1)
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen right_idx = idx;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen else
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen break;
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen }
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen if (idx < size && updates[idx].uid2 < u.uid1)
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen idx++;
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen
89c8d5f336e44cca091a1f588d51ba26e5145ad2Timo Sirainen /* overlapping ranges, split/merge them */
89c8d5f336e44cca091a1f588d51ba26e5145ad2Timo Sirainen i_assert(idx == 0 || updates[idx-1].uid2 < u.uid1);
89c8d5f336e44cca091a1f588d51ba26e5145ad2Timo Sirainen
89c8d5f336e44cca091a1f588d51ba26e5145ad2Timo Sirainen for (; idx < size && u.uid2 >= updates[idx].uid1; idx++) {
f20e7fbdc9bdbe8fecb9c661c9b8175f3bb78c69Timo Sirainen if (u.uid1 != updates[idx].uid1 &&
c0b1543512bc3e0a3a9f526056a3678a07ce32f5Timo Sirainen (updates[idx].add_flags != u.add_flags ||
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen updates[idx].remove_flags != u.remove_flags)) {
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen /* split existing update from beginning */
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen tmp_update = updates[idx];
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen tmp_update.uid2 = u.uid1 - 1;
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen updates[idx].uid1 = u.uid1;
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen i_assert(tmp_update.uid1 <= tmp_update.uid2);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen i_assert(updates[idx].uid1 <= updates[idx].uid2);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen buffer_insert(t->updates, idx * sizeof(tmp_update),
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen &tmp_update, sizeof(tmp_update));
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen updates = buffer_get_modifyable_data(t->updates, NULL);
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen size++; idx++;
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen }
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen if (u.uid2 < updates[idx].uid2 &&
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen (updates[idx].add_flags != u.add_flags ||
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen updates[idx].remove_flags != u.remove_flags)) {
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen /* split existing update from end */
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen tmp_update = updates[idx];
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen tmp_update.uid2 = u.uid2;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen updates[idx].uid1 = u.uid2 + 1;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen i_assert(tmp_update.uid1 <= tmp_update.uid2);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen i_assert(updates[idx].uid1 <= updates[idx].uid2);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen buffer_insert(t->updates, idx * sizeof(tmp_update),
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen &tmp_update, sizeof(tmp_update));
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen updates = buffer_get_modifyable_data(t->updates, NULL);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen size++;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen }
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen updates[idx].add_flags =
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen (updates[idx].add_flags | u.add_flags) &
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen ~u.remove_flags;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen updates[idx].remove_flags =
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen (updates[idx].remove_flags | u.remove_flags) &
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen ~u.add_flags;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen u.uid1 = updates[idx].uid2 + 1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (u.uid1 > u.uid2) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* break here before idx++ so last_update_idx is set
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen correctly */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen i_assert(idx <= size);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen if (u.uid1 <= u.uid2) {
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen i_assert(idx == 0 || updates[idx-1].uid2 < u.uid1);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen i_assert(idx == size || updates[idx].uid1 > u.uid2);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen buffer_insert(t->updates, idx * sizeof(u), &u, sizeof(u));
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen }
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen t->last_update_idx = idx;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen}
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainenstatic void mail_index_record_modify_flags(struct mail_index_record *rec,
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen enum modify_type modify_type,
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen enum mail_flags flags)
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen{
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen switch (modify_type) {
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen case MODIFY_REPLACE:
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen rec->flags = flags;
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen break;
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen case MODIFY_ADD:
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen rec->flags |= flags;
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen break;
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen case MODIFY_REMOVE:
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen rec->flags &= ~flags;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen break;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen }
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvoid mail_index_update_flags_range(struct mail_index_transaction *t,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen uint32_t seq1, uint32_t seq2,
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen enum modify_type modify_type,
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen enum mail_flags flags)
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen{
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen struct mail_index_record *rec;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen struct mail_transaction_flag_update u, *last_update;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen size_t size;
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen t->log_updates = TRUE;
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (seq2 >= t->first_new_seq) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* updates for appended messages, modify them directly */
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen uint32_t seq;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for (seq = I_MAX(t->first_new_seq, seq1); seq <= seq2; seq++) {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen rec = mail_index_transaction_lookup(t, seq);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_index_record_modify_flags(rec, modify_type, flags);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (seq1 >= t->first_new_seq)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen return;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* range contains also existing messages. update them next. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen seq2 = t->first_new_seq - 1;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(seq1 <= seq2 && seq1 > 0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(seq2 <= mail_index_view_get_messages_count(t->view));
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen memset(&u, 0, sizeof(u));
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen u.uid1 = seq1;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen u.uid2 = seq2;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen switch (modify_type) {
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen case MODIFY_REPLACE:
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen u.add_flags = flags;
f4bbeadda12fbd7c219063db68f3e78646d83c2cTimo Sirainen u.remove_flags = ~flags & MAIL_INDEX_FLAGS_MASK;
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen break;
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen case MODIFY_ADD:
abe8754852e70763e92f74caabbcc13d0917714cTimo Sirainen u.add_flags = flags;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen break;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen case MODIFY_REMOVE:
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen u.remove_flags = flags;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen break;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen if (t->updates == NULL) {
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen t->updates = buffer_create_dynamic(default_pool, 4096);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen buffer_append(t->updates, &u, sizeof(u));
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen return;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen }
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen last_update = buffer_get_modifyable_data(t->updates, &size);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen size /= sizeof(*last_update);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (t->last_update_idx < size) {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen /* fast path - hopefully we're updating the next message,
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen or a message that is to be appended as last update */
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen last_update += t->last_update_idx;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (seq1 - 1 == last_update->uid2) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (u.add_flags == last_update->add_flags &&
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen u.remove_flags == last_update->remove_flags &&
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen (t->last_update_idx + 1 == size ||
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen last_update[1].uid1 > seq2)) {
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen /* we can just update the UID range */
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen last_update->uid2 = seq2;
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen return;
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen }
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen } else if (seq1 > last_update->uid2) {
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen /* hopefully we can just append it */
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen t->last_update_idx++;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen last_update++;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen }
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen }
97e62b2b36dda0acb3215667042f5c80cdee8155Timo Sirainen
97e62b2b36dda0acb3215667042f5c80cdee8155Timo Sirainen if (t->last_update_idx == size) {
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen buffer_append(t->updates, &u, sizeof(u));
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen return;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen }
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen /* slow path */
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen if (seq1 > last_update->uid2) {
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen /* added after this */
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen mail_index_insert_flag_update(t, u, t->last_update_idx + 1,
97e62b2b36dda0acb3215667042f5c80cdee8155Timo Sirainen size);
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen } else {
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen /* added before this or on top of this */
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen mail_index_insert_flag_update(t, u, 0, t->last_update_idx);
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen }
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen}
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainenvoid mail_index_update_flags(struct mail_index_transaction *t, uint32_t seq,
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen enum modify_type modify_type,
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen enum mail_flags flags)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen{
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen mail_index_update_flags_range(t, seq, seq, modify_type, flags);
dd2df6a67f10792ce31a3666197c0b6885893a3aTimo Sirainen}
dd2df6a67f10792ce31a3666197c0b6885893a3aTimo Sirainen
14175321ddb88619015866978c05a27786ca4814Timo Sirainenint mail_index_seq_buffer_lookup(buffer_t *buffer, uint32_t seq,
14175321ddb88619015866978c05a27786ca4814Timo Sirainen size_t record_size, size_t *pos_r)
14175321ddb88619015866978c05a27786ca4814Timo Sirainen{
14175321ddb88619015866978c05a27786ca4814Timo Sirainen unsigned int idx, left_idx, right_idx;
14175321ddb88619015866978c05a27786ca4814Timo Sirainen void *data;
14175321ddb88619015866978c05a27786ca4814Timo Sirainen uint32_t full_record_size, *seq_p;
14175321ddb88619015866978c05a27786ca4814Timo Sirainen size_t size;
14175321ddb88619015866978c05a27786ca4814Timo Sirainen
14175321ddb88619015866978c05a27786ca4814Timo Sirainen full_record_size = record_size + sizeof(seq);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen
14175321ddb88619015866978c05a27786ca4814Timo Sirainen data = buffer_get_modifyable_data(buffer, &size);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen
14175321ddb88619015866978c05a27786ca4814Timo Sirainen /* we're probably appending it, check */
14175321ddb88619015866978c05a27786ca4814Timo Sirainen if (size == 0)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen idx = 0;
439dd06aec3301e65d650f6dc1d4a1a00b356b4fTimo Sirainen else if (*((uint32_t *)PTR_OFFSET(data, size-full_record_size)) < seq)
439dd06aec3301e65d650f6dc1d4a1a00b356b4fTimo Sirainen idx = size / full_record_size;
439dd06aec3301e65d650f6dc1d4a1a00b356b4fTimo Sirainen else {
439dd06aec3301e65d650f6dc1d4a1a00b356b4fTimo Sirainen idx = 0; left_idx = 0; right_idx = size / full_record_size;
14175321ddb88619015866978c05a27786ca4814Timo Sirainen while (left_idx < right_idx) {
14175321ddb88619015866978c05a27786ca4814Timo Sirainen idx = (left_idx + right_idx) / 2;
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen seq_p = PTR_OFFSET(data, idx * full_record_size);
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen if (*seq_p < seq)
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen left_idx = idx+1;
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen else if (*seq_p > seq)
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen right_idx = idx;
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen else {
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen *pos_r = idx * full_record_size;
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen return TRUE;
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen }
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen }
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen }
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen *pos_r = idx * full_record_size;
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen return FALSE;
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen}
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainenstatic int mail_index_update_seq_buffer(buffer_t **buffer, uint32_t seq,
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen const void *record, size_t record_size,
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen void *old_record)
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen{
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen void *p;
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen size_t pos;
dd2df6a67f10792ce31a3666197c0b6885893a3aTimo Sirainen
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen if (*buffer == NULL) {
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen *buffer = buffer_create_dynamic(default_pool, 1024);
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen buffer_append(*buffer, &seq, sizeof(seq));
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen buffer_append(*buffer, record, record_size);
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen return FALSE;
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen }
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen if (mail_index_seq_buffer_lookup(*buffer, seq, record_size, &pos)) {
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen /* already there, update */
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen p = buffer_get_space_unsafe(*buffer, pos + sizeof(seq),
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen record_size);
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen if (old_record != NULL)
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen memcpy(old_record, p, record_size);
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen memcpy(p, record, record_size);
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen return TRUE;
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen } else {
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen /* insert */
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen buffer_copy(*buffer, pos + sizeof(seq) + record_size,
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen *buffer, pos, (size_t)-1);
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen buffer_write(*buffer, pos, &seq, sizeof(seq));
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen buffer_write(*buffer, pos + sizeof(seq), record, record_size);
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen return FALSE;
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen }
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen}
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainenvoid mail_index_update_header(struct mail_index_transaction *t,
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen size_t offset, const void *data, size_t size)
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen{
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen i_assert(offset < sizeof(t->hdr_change));
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen i_assert(size <= sizeof(t->hdr_change) - offset);
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen t->hdr_changed = TRUE;
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen t->log_updates = TRUE;
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen memcpy(t->hdr_change + offset, data, size);
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen for (; size > 0; size--)
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen t->hdr_mask[offset++] = 1;
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen}
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainenvoid mail_index_ext_resize(struct mail_index_transaction *t, uint32_t ext_id,
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen uint32_t hdr_size, uint16_t record_size,
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen uint16_t record_align)
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen{
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen struct mail_transaction_ext_intro intro;
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen const struct mail_index_ext *ext;
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen memset(&intro, 0, sizeof(intro));
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen if (!mail_index_map_get_ext_idx(t->view->map, ext_id, &intro.ext_id)) {
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen intro.ext_id = (uint32_t)-1;
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen ext = t->view->index->extensions->data;
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen ext += ext_id;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen } else {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen ext = t->view->map->extensions->data;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen ext += ext_id;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen /* allow only header size changes if something was already written */
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen i_assert(t->ext_rec_updates == NULL ||
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen (ext->record_size == record_size &&
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen ext->record_align == record_align));
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen t->log_updates = TRUE;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if (t->ext_resizes == NULL)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen t->ext_resizes = buffer_create_dynamic(default_pool, 128);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen intro.hdr_size = hdr_size;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen intro.record_size = record_size;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen intro.record_align = record_align;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen intro.name_size = 1;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen buffer_write(t->ext_resizes, ext_id * sizeof(intro),
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen &intro, sizeof(intro));
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen}
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainenvoid mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id,
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen uint32_t reset_id)
4aa7fe81503a20bc972ae625da4dd9e6996fbdbfTimo Sirainen{
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen size_t pos;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen i_assert(reset_id != 0);
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen t->log_updates = TRUE;
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen if (t->ext_rec_updates != NULL &&
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen ext_id < t->ext_rec_updates->used / sizeof(buffer_t *)) {
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen buffer_t *const *buf = t->ext_rec_updates->data;
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen buf += ext_id;
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen if (*buf != NULL)
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen buffer_set_used_size(*buf, 0);
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen }
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen pos = ext_id * sizeof(uint32_t);
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen if (t->ext_resets == NULL) {
66d84e6f0ae34a3cf5b8fa8e009d6caf025b6a2aTimo Sirainen t->ext_resets = buffer_create_dynamic(default_pool,
66d84e6f0ae34a3cf5b8fa8e009d6caf025b6a2aTimo Sirainen pos + sizeof(uint32_t));
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen }
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen buffer_write(t->ext_resets, pos, &reset_id, sizeof(reset_id));
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen}
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainenvoid mail_index_update_header_ext(struct mail_index_transaction *t,
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen uint32_t ext_id, size_t offset,
b80c329a25b5b07f5e68cd44ef0fef9db6613486Timo Sirainen const void *data, size_t size)
b80c329a25b5b07f5e68cd44ef0fef9db6613486Timo Sirainen{
b80c329a25b5b07f5e68cd44ef0fef9db6613486Timo Sirainen // FIXME
b80c329a25b5b07f5e68cd44ef0fef9db6613486Timo Sirainen}
73b9c241e7fb6abdccda88e88fbd32e844dbc185Timo Sirainen
73b9c241e7fb6abdccda88e88fbd32e844dbc185Timo Sirainenvoid mail_index_update_ext(struct mail_index_transaction *t, uint32_t seq,
73b9c241e7fb6abdccda88e88fbd32e844dbc185Timo Sirainen uint32_t ext_id, const void *data, void *old_data_r)
73b9c241e7fb6abdccda88e88fbd32e844dbc185Timo Sirainen{
73b9c241e7fb6abdccda88e88fbd32e844dbc185Timo Sirainen struct mail_index *index = t->view->index;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen const struct mail_index_ext *ext;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen const struct mail_transaction_ext_intro *intro;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen buffer_t **buf;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen uint16_t record_size;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen size_t size;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen i_assert(seq > 0 &&
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen (seq <= mail_index_view_get_messages_count(t->view) ||
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen seq <= t->last_new_seq));
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen i_assert(ext_id < index->extensions->used / sizeof(*ext));
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen
d9ab8a13b51c9d8f4e13e1bf785eeadce6702b3bTimo Sirainen t->log_updates = TRUE;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen
5df8396a7cbad0b38b83a86667fb3d4c223f6f7cTimo Sirainen if (t->ext_resizes == NULL) {
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen intro = NULL;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen size = 0;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen } else {
5df8396a7cbad0b38b83a86667fb3d4c223f6f7cTimo Sirainen intro = buffer_get_data(t->ext_resizes, &size);
d5b3f66491101aba8667369586c95c615cb26ae6Timo Sirainen }
5df8396a7cbad0b38b83a86667fb3d4c223f6f7cTimo Sirainen if (ext_id < size / sizeof(*intro) && intro[ext_id].name_size != 0) {
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen /* resized record */
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen record_size = intro[ext_id].record_size;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen } else {
9db5ade1c16c7f67c51004f28c28ea335755d3f0Timo Sirainen ext = index->extensions->data;
9db5ade1c16c7f67c51004f28c28ea335755d3f0Timo Sirainen record_size = ext[ext_id].record_size;
9db5ade1c16c7f67c51004f28c28ea335755d3f0Timo Sirainen }
9db5ade1c16c7f67c51004f28c28ea335755d3f0Timo Sirainen
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen if (t->ext_rec_updates == NULL)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen t->ext_rec_updates = buffer_create_dynamic(default_pool, 128);
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen buf = buffer_get_space_unsafe(t->ext_rec_updates,
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen ext_id * sizeof(buffer_t *),
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen sizeof(buffer_t *));
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen /* @UNSAFE */
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen if (!mail_index_update_seq_buffer(buf, seq, data, record_size,
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen old_data_r)) {
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen if (old_data_r != NULL)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen memset(old_data_r, 0, record_size);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen}
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenstatic struct mail_keyword_transaction *
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenmail_keyword_transaction_new(struct mail_index_transaction *t,
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen struct mail_keywords *keywords)
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen{
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen struct mail_keyword_transaction *kt;
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen if (t->keyword_updates == NULL)
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen t->keyword_updates = buffer_create_dynamic(default_pool, 512);
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen kt = i_new(struct mail_keyword_transaction, 1);
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen kt->transaction = t;
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen kt->keywords = keywords;
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen kt->next = keywords->kt;
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen keywords->kt = kt;
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen buffer_append(t->keyword_updates, &kt, sizeof(kt));
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen return kt;
9511a40d933181045343110c8101b75887062aaeTimo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic struct mail_keywords *
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainenmail_index_keywords_build(struct mail_index *index,
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen const char *const keywords[], unsigned int count)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_keywords k;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen const char **missing_keywords, *keyword;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen buffer_t *keyword_buf;
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen unsigned int i, j, bitmask_offset, missing_count = 0;
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen size_t size;
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen uint8_t *b;
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen if (count == 0)
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainen return i_new(struct mail_keywords, 1);
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen /* @UNSAFE */
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen t_push();
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen missing_keywords = t_new(const char *, count + 1);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen memset(&k, 0, sizeof(k));
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen /* keywords are sorted in index. look up the existing ones and add
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen new ones. build a bitmap pointing to them. keywords are never
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen removed from index's keyword list. */
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen bitmask_offset = sizeof(k) - sizeof(k.bitmask);
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen keyword_buf = buffer_create_dynamic(default_pool, bitmask_offset +
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen (count + 7) / 8 + 8);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen for (i = 0; i < count; i++) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen for (j = 0; index->keywords[j] != NULL; j++) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (strcasecmp(keywords[i], index->keywords[j]) == 0)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen break;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (index->keywords[j] != NULL) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (keyword_buf->used == 0) {
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen /* first one */
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen k.start = j;
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen } else if (j < k.start) {
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen buffer_copy(keyword_buf,
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen bitmask_offset + k.start - j,
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen keyword_buf, bitmask_offset,
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen (size_t)-1);
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen k.start = j;
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen }
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen b = buffer_get_space_unsafe(keyword_buf,
d14e62b7b37dc78fcc940aca25042eceb358b156Timo Sirainen bitmask_offset +
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen (j - k.start) / 8, 1);
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen *b |= 1 << ((j - k.start) % 8);
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen k.end = j;
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen k.count++;
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen } else {
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen /* arrays are sorted, can't match anymore */
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen missing_keywords[missing_count++] = keywords[i];
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen }
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen }
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen if (missing_count > 0) {
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen /* add missing keywords. first drop the trailing NULL. */
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen size = index->keywords_buf->used - sizeof(const char *);
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen buffer_set_used_size(index->keywords_buf, size);
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen j = size / sizeof(const char *);
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen for (; *missing_keywords != NULL; missing_keywords++, j++) {
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Sirainen keyword = p_strdup(index->keywords_pool,
*missing_keywords);
buffer_append(index->keywords_buf,
&keyword, sizeof(keyword));
b = buffer_get_space_unsafe(keyword_buf,
bitmask_offset +
(j - k.start) / 8, 1);
*b |= 1 << ((j - k.start) % 8);
k.end = j;
k.count++;
}
buffer_append_zero(index->keywords_buf, sizeof(const char *));
index->keywords = index->keywords_buf->data;
}
buffer_write(keyword_buf, 0, &k, bitmask_offset);
t_pop();
return buffer_free_without_data(keyword_buf);
}
struct mail_keywords *
mail_index_keywords_create(struct mail_index_transaction *t,
const char *const keywords[])
{
struct mail_keywords *k;
const char *const null_keywords[] = { NULL };
if (keywords == NULL)
keywords = null_keywords;
k = mail_index_keywords_build(t->view->index, keywords,
strarray_length(keywords));
(void)mail_keyword_transaction_new(t, k);
return k;
}
void mail_index_update_keywords(struct mail_index_transaction *t, uint32_t seq,
enum modify_type modify_type,
struct mail_keywords *keywords)
{
struct mail_keyword_transaction *kt;
i_assert(seq > 0 &&
(seq <= mail_index_view_get_messages_count(t->view) ||
seq <= t->last_new_seq));
i_assert(keywords->count > 0 || modify_type == MODIFY_REPLACE);
i_assert(keywords->kt->transaction->view->index == t->view->index);
for (kt = keywords->kt; kt != NULL; kt = kt->next) {
if (kt->transaction == t &&
(kt->modify_type == modify_type || kt->messages == NULL))
break;
}
if (kt == NULL)
kt = mail_keyword_transaction_new(t, keywords);
if (kt->messages == NULL) {
kt->messages = buffer_create_dynamic(default_pool, 32);
kt->modify_type = modify_type;
buffer_append(kt->messages, &seq, sizeof(seq));
buffer_append(kt->messages, &seq, sizeof(seq));
} else {
mail_index_update_seq_range_buffer(kt->messages, seq);
}
t->log_updates = TRUE;
}