mail-index-sync-keywords.c revision 6825360d446542046757b06064282301c4c6b27c
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenkeyword_lookup(struct mail_index_sync_map_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *keyword_name, unsigned int *idx_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const unsigned int *idx_map;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (array_is_created(&map->keyword_idx_map) &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_keyword_lookup(ctx->view->index, keyword_name,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* FIXME: slow. maybe create index -> file mapping as well */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen idx_map = array_get(&map->keyword_idx_map, &count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < count; i++) {
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainenkeywords_get_header_buf(struct mail_index_map *map,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen unsigned int new_count, unsigned int *keywords_count_r,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen size_t *rec_offset_r, size_t *name_offset_root_r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_index_keyword_header *kw_hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_index_keyword_header_rec *kw_rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen kw_hdr = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen name = (const char *)(kw_rec + kw_hdr->keywords_count);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen i_assert((size_t)(name - (const char *)kw_hdr) < ext->hdr_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *keywords_count_r = new_kw_hdr.keywords_count;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen offset = kw_rec[kw_hdr->keywords_count-1].name_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 512);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_append(buf, &new_kw_hdr, sizeof(new_kw_hdr));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_append(buf, kw_rec, sizeof(*kw_rec) * kw_hdr->keywords_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_write(buf, buf->used + sizeof(*kw_rec) * new_count,
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainenstatic int keywords_ext_register(struct mail_index_sync_map_ctx *ctx,
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen buffer_create_static_hard(pool_datastack_create(),
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen u = buffer_append_space_unsafe(ext_intro_buf, sizeof(*u));
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen u->record_size = (keywords_count + CHAR_BIT - 1) / CHAR_BIT;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen /* since we aren't properly aligned anyway,
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen reserve one extra byte for future */
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen buffer_append(ext_intro_buf, "keywords", u->name_size);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainenkeywords_header_add(struct mail_index_sync_map_ctx *ctx,
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen const char *keyword_name, unsigned int *keyword_idx_r)
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen size_t keyword_len, rec_offset, name_offset, name_offset_root;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen /* if we crash in the middle of writing the header, the
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen keywords are more or less corrupted. avoid that by
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen making sure the header is updated atomically. */
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen ext_id = mail_index_map_lookup_ext(map, "keywords");
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen /* update existing header */
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen buf = keywords_get_header_buf(map, ext, 1, &keywords_count,
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen /* create new / replace broken header */
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 512);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen kw_hdr = buffer_append_space_unsafe(buf, sizeof(*kw_hdr));
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* add the keyword */
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen buffer_write(buf, rec_offset, &kw_rec, sizeof(kw_rec));
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen buffer_write(buf, name_offset_root, keyword_name, keyword_len);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (ext == NULL || buf->used > ext->hdr_size ||
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen (uint32_t)ext->record_size * CHAR_BIT < keywords_count) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* if we need to grow the buffer, add some padding */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* map may have changed */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen ext_id = mail_index_map_lookup_ext(map, "keywords");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_copy(map->hdr_copy_buf, ext->hdr_offset,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenkeywords_update_records(struct mail_index_sync_map_ctx *ctx,
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen unsigned int keyword_idx, enum modify_type type,
c4877db8b6559846f4b58be8e42422dc734c193fTimo Sirainen mail_index_lookup_uid_range(view, uid1, uid2, &seq1, &seq2);
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen mail_index_sync_write_seq_update(ctx, seq1, seq2);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(data_offset >= sizeof(struct mail_index_record));
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenint mail_index_sync_keywords(struct mail_index_sync_map_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_keyword_update *rec)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen seqset_offset = sizeof(*rec) + rec->name_size;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen keyword_name = t_strndup(rec + 1, rec->name_size);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen "Trying to use empty keyword");
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen if (keyword_lookup(ctx, keyword_name, &keyword_idx) < 0)
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen ret = keywords_header_add(ctx, keyword_name, &keyword_idx);
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen ext_id = mail_index_map_lookup_ext(ctx->view->map, "keywords");
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen array_idx(&ctx->view->map->extensions, ext_id);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* nothing to do */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen "Keyword ext record missing for added keyword");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_map_parse_keywords(ctx->view->map) < 0)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen ret = keywords_update_records(ctx, ext, keyword_idx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_index_sync_keywords_reset(struct mail_index_sync_map_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_keyword_reset *r)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen const struct mail_transaction_keyword_reset *end;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen ext_id = mail_index_map_lookup_ext(map, "keywords");
d565eaa943f29a49b97230ced57eec40ee65b4f9Timo Sirainen /* nothing to do */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (; r != end; r++) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen mail_index_lookup_uid_range(ctx->view, r->uid1, r->uid2,