mail-index-sync-keywords.c revision 7ded22760598b78ee29f9418eacc0abe3fb51055
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2004 Timo Sirainen */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenkeyword_lookup(struct mail_index_sync_map_ctx *ctx,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *keyword_name, unsigned int *idx_r)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const unsigned int *idx_map;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (array_is_created(&map->keyword_idx_map) &&
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen mail_index_keyword_lookup(ctx->view->index, keyword_name,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* FIXME: slow. maybe create index -> file mapping as well */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen idx_map = array_get(&map->keyword_idx_map, &count);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen for (i = 0; i < count; i++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenkeywords_get_header_buf(struct mail_index_map *map,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen unsigned int new_count, unsigned int *keywords_count_r,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen size_t *rec_offset_r, size_t *name_offset_root_r,
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen const struct mail_index_keyword_header *kw_hdr;
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen const struct mail_index_keyword_header_rec *kw_rec;
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainen kw_hdr = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen name = (const char *)(kw_rec + kw_hdr->keywords_count);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_assert((size_t)(name - (const char *)kw_hdr) < ext->hdr_size);
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen *keywords_count_r = new_kw_hdr.keywords_count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen offset = kw_rec[kw_hdr->keywords_count-1].name_offset;
b57cd9928909b51fa473c3eea81442e296006438Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 512);
b57cd9928909b51fa473c3eea81442e296006438Timo Sirainen buffer_append(buf, &new_kw_hdr, sizeof(new_kw_hdr));
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen buffer_append(buf, kw_rec, sizeof(*kw_rec) * kw_hdr->keywords_count);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen buffer_write(buf, buf->used + sizeof(*kw_rec) * new_count,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstatic int keywords_ext_register(struct mail_index_sync_map_ctx *ctx,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen buffer_create_static_hard(pool_datastack_create(),
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen u = buffer_append_space_unsafe(ext_intro_buf, sizeof(*u));
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen u->record_size = (keywords_count + CHAR_BIT - 1) / CHAR_BIT;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* since we aren't properly aligned anyway,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen reserve one extra byte for future */
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen buffer_append(ext_intro_buf, "keywords", u->name_size);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenkeywords_header_add(struct mail_index_sync_map_ctx *ctx,
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen const char *keyword_name, unsigned int *keyword_idx_r)
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen size_t keyword_len, rec_offset, name_offset, name_offset_root;
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* if we crash in the middle of writing the header, the
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen keywords are more or less corrupted. avoid that by
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen making sure the header is updated atomically. */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen if (!mail_index_map_lookup_ext(map, "keywords", &ext_map_idx))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* update existing header */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ext = array_idx(&map->extensions, ext_map_idx);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen buf = keywords_get_header_buf(map, ext, 1, &keywords_count,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* create new / replace broken header */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 512);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen kw_hdr = buffer_append_space_unsafe(buf, sizeof(*kw_hdr));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* add the keyword */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen buffer_write(buf, rec_offset, &kw_rec, sizeof(kw_rec));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen buffer_write(buf, name_offset_root, keyword_name, keyword_len);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ext == NULL || buf->used > ext->hdr_size ||
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (uint32_t)ext->record_size * CHAR_BIT < keywords_count) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* if we need to grow the buffer, add some padding */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* map may have changed */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!mail_index_map_lookup_ext(map, "keywords", &ext_map_idx))
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen ext = array_idx(&map->extensions, ext_map_idx);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen buffer_copy(map->hdr_copy_buf, ext->hdr_offset,
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainenkeywords_update_records(struct mail_index_sync_map_ctx *ctx,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int keyword_idx, enum modify_type type,
4c9c55e15f35474f53f11659e796c63b1c34e884Timo Sirainen mail_index_lookup_uid_range(view, uid1, uid2, &seq1, &seq2);
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen mail_index_sync_write_seq_update(ctx, seq1, seq2);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen i_assert(data_offset >= sizeof(struct mail_index_record));
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenint mail_index_sync_keywords(struct mail_index_sync_map_ctx *ctx,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen const struct mail_transaction_keyword_update *rec)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen seqset_offset = sizeof(*rec) + rec->name_size;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen keyword_name = t_strndup(rec + 1, rec->name_size);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "Trying to use empty keyword");
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen if (keyword_lookup(ctx, keyword_name, &keyword_idx) < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = keywords_header_add(ctx, keyword_name, &keyword_idx);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (!mail_index_map_lookup_ext(ctx->view->map, "keywords",
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ext = array_idx(&ctx->view->map->extensions, ext_map_idx);
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen /* nothing to do */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen "Keyword ext record missing for added keyword");
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (mail_index_map_parse_keywords(ctx->view->map) < 0)
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen ret = keywords_update_records(ctx, ext, keyword_idx,
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainenmail_index_sync_keywords_reset(struct mail_index_sync_map_ctx *ctx,
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen const struct mail_transaction_keyword_reset *r)
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen const struct mail_transaction_keyword_reset *end;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!mail_index_map_lookup_ext(map, "keywords", &ext_map_idx)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* nothing to do */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ext = array_idx(&map->extensions, ext_map_idx);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen for (; r != end; r++) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen mail_index_lookup_uid_range(ctx->view, r->uid1, r->uid2,