mail-index-sync-keywords.c revision bf045aa2e9c3846ecde84db303db6588b173bbae
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi/* Copyright (C) 2004 Timo Sirainen */
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi#include "lib.h"
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi#include "array.h"
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi#include "buffer.h"
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi#include "mail-index-view-private.h"
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi#include "mail-index-sync-private.h"
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi#include "mail-transaction-log.h"
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumistatic int
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumikeyword_lookup(struct mail_index_sync_map_ctx *ctx,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi const char *keyword_name, unsigned int *idx_r)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi{
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi struct mail_index_map *map = ctx->view->map;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi const unsigned int *idx_map;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi unsigned int i, count, keyword_idx;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (!ctx->keywords_read) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (mail_index_map_read_keywords(ctx->view->index, map) < 0)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return -1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ctx->keywords_read = TRUE;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (mail_index_keyword_lookup(ctx->view->index, keyword_name,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi FALSE, &keyword_idx) &&
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi array_is_created(&map->keyword_idx_map)) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi /* FIXME: slow. maybe create index -> file mapping as well */
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi idx_map = array_get(&map->keyword_idx_map, &count);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi for (i = 0; i < count; i++) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (idx_map[i] == keyword_idx) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi *idx_r = i;
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber return 1;
c63c04fcaf1c3a78c70500eae253d72fa9c8358aTAMUKI Shoichi }
96283b546081e7ff709968378fca25cb44f1ab6cStéphane Graber }
96283b546081e7ff709968378fca25cb44f1ab6cStéphane Graber }
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber *idx_r = (unsigned int)-1;
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber return 0;
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber}
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graberstatic buffer_t *
207bf0e475f1dc6e9a2dac2cee3a209b56427855Stéphane Graberkeywords_get_header_buf(struct mail_index_map *map,
207bf0e475f1dc6e9a2dac2cee3a209b56427855Stéphane Graber const struct mail_index_ext *ext,
207bf0e475f1dc6e9a2dac2cee3a209b56427855Stéphane Graber unsigned int new_count, unsigned int *keywords_count_r,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi size_t *rec_offset_r, size_t *name_offset_root_r,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi size_t *name_offset_r)
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi{
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi buffer_t *buf;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi const struct mail_index_keyword_header *kw_hdr;
8c3a756ed4cf22f9fdab5f95d067321e6ddcc425KATOH Yasufumi const struct mail_index_keyword_header_rec *kw_rec;
8c3a756ed4cf22f9fdab5f95d067321e6ddcc425KATOH Yasufumi const char *name;
8c3a756ed4cf22f9fdab5f95d067321e6ddcc425KATOH Yasufumi struct mail_index_keyword_header new_kw_hdr;
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi uint32_t offset;
8c3a756ed4cf22f9fdab5f95d067321e6ddcc425KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi kw_hdr = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi kw_rec = (const void *)(kw_hdr + 1);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi name = (const char *)(kw_rec + kw_hdr->keywords_count);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (kw_hdr->keywords_count == 0)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return NULL;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi new_kw_hdr = *kw_hdr;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi new_kw_hdr.keywords_count += new_count;
8adef7614d4340b4ee44a4441fadd530f48515edKATOH Yasufumi *keywords_count_r = new_kw_hdr.keywords_count;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi offset = kw_rec[kw_hdr->keywords_count-1].name_offset;
8c3a756ed4cf22f9fdab5f95d067321e6ddcc425KATOH Yasufumi offset += strlen(name + offset) + 1;
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi buf = buffer_create_dynamic(pool_datastack_create(), 512);
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi buffer_append(buf, &new_kw_hdr, sizeof(new_kw_hdr));
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi buffer_append(buf, kw_rec, sizeof(*kw_rec) * kw_hdr->keywords_count);
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi *rec_offset_r = buf->used;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi buffer_write(buf, buf->used + sizeof(*kw_rec) * new_count,
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi name, offset);
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi *name_offset_root_r = buf->used;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi *name_offset_r = offset;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi return buf;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi}
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumistatic int keywords_ext_register(struct mail_index_sync_map_ctx *ctx,
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi uint32_t ext_id, uint32_t reset_id,
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi uint32_t hdr_size, uint32_t keywords_count)
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi{
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi buffer_t *ext_intro_buf;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi struct mail_transaction_ext_intro *u;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi
8adef7614d4340b4ee44a4441fadd530f48515edKATOH Yasufumi ext_intro_buf =
8adef7614d4340b4ee44a4441fadd530f48515edKATOH Yasufumi buffer_create_static_hard(pool_datastack_create(),
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi sizeof(*u) + sizeof("keywords")-1);
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi u = buffer_append_space_unsafe(ext_intro_buf, sizeof(*u));
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi u->ext_id = ext_id;
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi u->reset_id = reset_id;
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi u->hdr_size = hdr_size;
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi u->record_size = (keywords_count + CHAR_BIT - 1) / CHAR_BIT;
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi if ((u->record_size % 4) != 0) {
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi /* since we aren't properly aligned anyway,
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi reserve one extra byte for future */
adf4b4083369a8bb7ed3c2ce3dd85dcaed7323c4KATOH Yasufumi u->record_size++;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi u->record_align = 1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (ext_id == (uint32_t)-1) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi u->name_size = strlen("keywords");
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi buffer_append(ext_intro_buf, "keywords", u->name_size);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return mail_index_sync_ext_intro(ctx, u);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi}
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumistatic int
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumikeywords_header_add(struct mail_index_sync_map_ctx *ctx,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi const char *keyword_name, unsigned int *keyword_idx_r)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi{
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi struct mail_index_map *map = ctx->view->map;
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi const struct mail_index_ext *ext = NULL;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi struct mail_index_keyword_header *kw_hdr;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi struct mail_index_keyword_header_rec kw_rec;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi uint32_t ext_id;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi buffer_t *buf = NULL;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi size_t keyword_len, rec_offset, name_offset, name_offset_root;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi unsigned int keywords_count;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi int ret;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ext_id = mail_index_map_lookup_ext(map, "keywords");
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (ext_id != (uint32_t)-1) {
d0348408b5fa226bf7f8031c6abf2d5d2a28ba33TAMUKI Shoichi /* update existing header */
d0348408b5fa226bf7f8031c6abf2d5d2a28ba33TAMUKI Shoichi ext = array_idx(&map->extensions, ext_id);
d0348408b5fa226bf7f8031c6abf2d5d2a28ba33TAMUKI Shoichi buf = keywords_get_header_buf(map, ext, 1, &keywords_count,
d0348408b5fa226bf7f8031c6abf2d5d2a28ba33TAMUKI Shoichi &rec_offset, &name_offset_root,
d0348408b5fa226bf7f8031c6abf2d5d2a28ba33TAMUKI Shoichi &name_offset);
d0348408b5fa226bf7f8031c6abf2d5d2a28ba33TAMUKI Shoichi }
d0348408b5fa226bf7f8031c6abf2d5d2a28ba33TAMUKI Shoichi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (buf == NULL) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi /* create new / replace broken header */
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi buf = buffer_create_dynamic(pool_datastack_create(), 512);
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi kw_hdr = buffer_append_space_unsafe(buf, sizeof(*kw_hdr));
8adef7614d4340b4ee44a4441fadd530f48515edKATOH Yasufumi kw_hdr->keywords_count = 1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi keywords_count = kw_hdr->keywords_count;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi rec_offset = buf->used;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi name_offset_root = rec_offset +
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi kw_hdr->keywords_count * sizeof(kw_rec);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi name_offset = 0;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi /* add the keyword */
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi memset(&kw_rec, 0, sizeof(kw_rec));
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi kw_rec.name_offset = name_offset;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi keyword_len = strlen(keyword_name) + 1;
ea00a202cde59a23daba00b64ec92fb9a748327aTAMUKI Shoichi buffer_write(buf, rec_offset, &kw_rec, sizeof(kw_rec));
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi buffer_write(buf, name_offset_root, keyword_name, keyword_len);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi rec_offset += sizeof(kw_rec);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi kw_rec.name_offset += keyword_len;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi name_offset_root += keyword_len;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if ((buf->used % 4) != 0)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi buffer_append_zero(buf, 4 - (buf->used % 4));
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (ext == NULL || buf->used > ext->hdr_size ||
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi (uint32_t)ext->record_size * CHAR_BIT < keywords_count) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi /* if we need to grow the buffer, add some padding */
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi buffer_append_zero(buf, 128);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ret = keywords_ext_register(ctx, ext_id,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ext == NULL ? 0 : ext->reset_id,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi buf->used, keywords_count);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (ret <= 0)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return ret;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi /* map may have changed */
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi map = ctx->view->map;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (ext == NULL) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ext_id = mail_index_map_lookup_ext(map, "keywords");
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi i_assert(ext_id != (uint32_t)-1);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ext = array_idx(&map->extensions, ext_id);
db821c3a4168c9c1072a433340e6009892e26cf2KATOH Yasufumi
db821c3a4168c9c1072a433340e6009892e26cf2KATOH Yasufumi i_assert(ext->hdr_size == buf->used);
db821c3a4168c9c1072a433340e6009892e26cf2KATOH Yasufumi }
db821c3a4168c9c1072a433340e6009892e26cf2KATOH Yasufumi
db821c3a4168c9c1072a433340e6009892e26cf2KATOH Yasufumi buffer_copy(map->hdr_copy_buf, ext->hdr_offset,
db821c3a4168c9c1072a433340e6009892e26cf2KATOH Yasufumi buf, 0, buf->used);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi map->hdr_base = map->hdr_copy_buf->data;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi *keyword_idx_r = keywords_count - 1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ctx->keywords_read = FALSE;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return 1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi}
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumistatic int
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumikeywords_update_records(struct mail_index_view *view,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi const struct mail_index_ext *ext,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi unsigned int keyword_idx,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi enum modify_type type,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi uint32_t uid1, uint32_t uid2)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi{
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi struct mail_index_record *rec;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi unsigned char *data, data_mask;
a1e4c206d5373b8ecd7906bff37f2601d65f022cKATOH Yasufumi unsigned int data_offset;
0dc296145715c36795ad0ad561f115afdd758223KATOH Yasufumi uint32_t seq1, seq2;
a1e4c206d5373b8ecd7906bff37f2601d65f022cKATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi i_assert(keyword_idx != (unsigned int)-1);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (mail_index_lookup_uid_range(view, uid1, uid2, &seq1, &seq2) < 0)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return -1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (seq1 == 0)
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi return 1;
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi data_offset = keyword_idx / CHAR_BIT;
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi data_mask = 1 << (keyword_idx % CHAR_BIT);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi i_assert(data_offset < ext->record_size);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi data_offset += ext->record_offset;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi switch (type) {
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi case MODIFY_ADD:
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi for (seq1--; seq1 < seq2; seq1++) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi rec = MAIL_INDEX_MAP_IDX(view->map, seq1);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi data = PTR_OFFSET(rec, data_offset);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi *data |= data_mask;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi break;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi case MODIFY_REMOVE:
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi data_mask = ~data_mask;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi for (seq1--; seq1 < seq2; seq1++) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi rec = MAIL_INDEX_MAP_IDX(view->map, seq1);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi data = PTR_OFFSET(rec, data_offset);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi *data &= data_mask;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi break;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi default:
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi i_unreached();
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return 1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi}
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
d0348408b5fa226bf7f8031c6abf2d5d2a28ba33TAMUKI Shoichiint mail_index_sync_keywords(struct mail_index_sync_map_ctx *ctx,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi const struct mail_transaction_header *hdr,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi const struct mail_transaction_keyword_update *rec)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi{
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi const char *keyword_name;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi const struct mail_index_ext *ext;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi const uint32_t *uid, *end;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi uint32_t seqset_offset, ext_id;
bf3e09c00eab82850782ad6ec74e4403d84ae866KATOH Yasufumi unsigned int keyword_idx;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi int ret;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi seqset_offset = sizeof(*rec) + rec->name_size;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi if ((seqset_offset % 4) != 0)
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi seqset_offset += 4 - (seqset_offset % 4);
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi if (seqset_offset > hdr->size) {
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi mail_transaction_log_view_set_corrupted(ctx->view->log_view,
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi "Keyword header ended unexpectedly");
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi return -1;
7a49a081dd1d4f92e3c82df344709e3206457e46KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi uid = CONST_PTR_OFFSET(rec, seqset_offset);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi end = CONST_PTR_OFFSET(rec, hdr->size);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (uid == end) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi mail_transaction_log_view_set_corrupted(ctx->view->log_view,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi "Keyword sequence list empty");
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return -1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi keyword_name = t_strndup(rec + 1, rec->name_size);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (keyword_lookup(ctx, keyword_name, &keyword_idx) < 0)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return -1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (keyword_idx == (unsigned int)-1) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ret = keywords_header_add(ctx, keyword_name, &keyword_idx);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (ret <= 0)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return ret;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ext_id = mail_index_map_lookup_ext(ctx->view->map, "keywords");
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (ext_id == (uint32_t)-1) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi /* nothing to do */
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi i_assert(rec->modify_type == MODIFY_REMOVE);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return 1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ext = array_idx(&ctx->view->map->extensions, ext_id);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (ext->record_size == 0) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi /* nothing to do */
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi i_assert(rec->modify_type == MODIFY_REMOVE);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return 1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (!ctx->keywords_read) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (mail_index_map_read_keywords(ctx->view->index,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ctx->view->map) < 0)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return -1;
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi ctx->keywords_read = TRUE;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi while (uid+2 <= end) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (uid[0] > uid[1] || uid[0] == 0) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi mail_transaction_log_view_set_corrupted(
ea00a202cde59a23daba00b64ec92fb9a748327aTAMUKI Shoichi ctx->view->log_view,
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi "Keyword record UIDs are broken");
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return -1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ret = keywords_update_records(ctx->view, ext, keyword_idx,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi rec->modify_type,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi uid[0], uid[1]);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (ret <= 0)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return ret;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi uid += 2;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi return 1;
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi}
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumiint
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumimail_index_sync_keywords_reset(struct mail_index_sync_map_ctx *ctx,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi const struct mail_transaction_header *hdr,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi const struct mail_transaction_keyword_reset *r)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi{
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi struct mail_index_map *map = ctx->view->map;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi struct mail_index_record *rec;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi const struct mail_index_ext *ext;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi const struct mail_transaction_keyword_reset *end;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi uint32_t ext_id, seq1, seq2;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ext_id = mail_index_map_lookup_ext(map, "keywords");
ffeb76b4607be4b241db01ab65989d37b4529c97TAMUKI Shoichi if (ext_id == (uint32_t)-1) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi /* nothing to do */
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return 1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi ext = array_idx(&map->extensions, ext_id);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi end = CONST_PTR_OFFSET(r, hdr->size);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi for (; r != end; r++) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (mail_index_lookup_uid_range(ctx->view, r->uid1, r->uid2,
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi &seq1, &seq2) < 0)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return -1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi if (seq1 == 0)
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi continue;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi for (seq1--; seq1 < seq2; seq1++) {
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi rec = MAIL_INDEX_MAP_IDX(map, seq1);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi memset(PTR_OFFSET(rec, ext->record_offset),
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi 0, ext->record_size);
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi }
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi return 1;
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi}
cab79123082bef9ba265c9c8b9176b8b8afedd64KATOH Yasufumi