[dovecot-cvs] dovecot/src/lib-index mail-index-private.h, 1.54,
1.55 mail-index-sync-keywords.c, 1.4,
1.5 mail-index-sync-private.h, 1.25, 1.26 mail-index-sync.c,
1.54, 1.55 mail-index-transaction-private.h, 1.23,
1.24 mail-index-transaction.c, 1.57, 1.58 mail-index-view.c,
1.33, 1.34 mail-index.c, 1.196, 1.197 mail-index.h, 1.145,
1.146 mail-transaction-log-append.c, 1.7, 1.8
cras at dovecot.org
cras at dovecot.org
Sun Apr 3 00:09:08 EEST 2005
Update of /var/lib/cvs/dovecot/src/lib-index
In directory talvi:/tmp/cvs-serv14722/lib-index
Modified Files:
mail-index-private.h mail-index-sync-keywords.c
mail-index-sync-private.h mail-index-sync.c
mail-index-transaction-private.h mail-index-transaction.c
mail-index-view.c mail-index.c mail-index.h
mail-transaction-log-append.c
Log Message:
Keywords are now stored in X-Keywords headers in mbox. Did several related
API changes to get better performance.
Index: mail-index-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-private.h,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -d -r1.54 -r1.55
--- mail-index-private.h 29 Mar 2005 12:18:49 -0000 1.54
+++ mail-index-private.h 2 Apr 2005 21:09:03 -0000 1.55
@@ -62,14 +62,6 @@
/* unsigned char name[] */
};
-struct mail_keywords {
- struct mail_index *index;
- unsigned int count;
-
- /* variable sized list of keyword indexes */
- uint32_t idx[1];
-};
-
struct mail_index_keyword_header {
uint32_t keywords_count;
/* struct mail_index_keyword_header_rec[] */
@@ -99,9 +91,7 @@
buffer_t *buffer;
buffer_t *hdr_copy_buf;
- pool_t keywords_pool;
- const char *const *keywords;
- unsigned int keywords_count;
+ array_t ARRAY_DEFINE(keyword_idx_map, unsigned int); /* file -> index */
unsigned int write_to_disk:1;
};
@@ -142,8 +132,8 @@
uoff_t sync_log_file_offset;
pool_t keywords_pool;
- array_t ARRAY_DEFINE(keywords_arr, const char *);
- const char *const *keywords;
+ array_t ARRAY_DEFINE(keywords, const char *);
+ struct hash_table *keywords_hash; /* name -> idx */
uint32_t keywords_ext_id;
unsigned int last_grow_count;
Index: mail-index-sync-keywords.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-sync-keywords.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- mail-index-sync-keywords.c 12 Mar 2005 18:16:29 -0000 1.4
+++ mail-index-sync-keywords.c 2 Apr 2005 21:09:03 -0000 1.5
@@ -11,18 +11,24 @@
const char *keyword_name, unsigned int *idx_r)
{
struct mail_index_map *map = ctx->view->map;
- unsigned int i;
+ const unsigned int *idx_map;
+ unsigned int i, count, keyword_idx;
if (!ctx->keywords_read) {
if (mail_index_map_read_keywords(ctx->view->index, map) < 0)
return -1;
ctx->keywords_read = TRUE;
}
-
- for (i = 0; i < map->keywords_count; i++) {
- if (strcmp(map->keywords[i], keyword_name) == 0) {
- *idx_r = i;
- return 1;
+ if (mail_index_keyword_lookup(ctx->view->index, keyword_name,
+ FALSE, &keyword_idx) &&
+ array_is_created(&map->keyword_idx_map)) {
+ /* FIXME: slow. maybe create index -> file mapping as well */
+ idx_map = array_get(&map->keyword_idx_map, &count);
+ for (i = 0; i < count; i++) {
+ if (idx_map[i] == keyword_idx) {
+ *idx_r = i;
+ return 1;
+ }
}
}
Index: mail-index-sync-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-sync-private.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- mail-index-sync-private.h 2 Apr 2005 19:31:27 -0000 1.25
+++ mail-index-sync-private.h 2 Apr 2005 21:09:03 -0000 1.26
@@ -26,7 +26,8 @@
struct mail_index_sync_list {
const array_t *ARRAY_DEFINE_PTR(array, struct uid_range);
unsigned int idx;
- unsigned int keyword_num;
+ unsigned int keyword_idx:31;
+ unsigned int keyword_remove:1;
};
struct mail_index_expunge_handler {
Index: mail-index-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-sync.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -d -r1.54 -r1.55
--- mail-index-sync.c 29 Mar 2005 12:18:49 -0000 1.54
+++ mail-index-sync.c 2 Apr 2005 21:09:03 -0000 1.55
@@ -185,7 +185,8 @@
mail_index_sync_read_and_sort(struct mail_index_sync_ctx *ctx,
int *seen_external_r)
{
- struct mail_index_sync_list *synclist;
+ struct mail_index_sync_list *synclist;
+ const struct mail_index_transaction_keyword_update *keyword_updates;
unsigned int i, keyword_count;
int ret;
@@ -236,10 +237,20 @@
synclist->array = &ctx->trans->keyword_resets;
}
+ keyword_updates = keyword_count == 0 ? NULL :
+ array_get(&ctx->trans->keyword_updates, NULL);
for (i = 0; i < keyword_count; i++) {
- synclist = array_modifyable_append(&ctx->sync_list);
- synclist->array = array_idx(&ctx->trans->keyword_updates, i);
- synclist->keyword_num = i;
+ if (array_is_created(&keyword_updates[i].add_seq)) {
+ synclist = array_modifyable_append(&ctx->sync_list);
+ synclist->array = &keyword_updates[i].add_seq;
+ synclist->keyword_idx = i;
+ }
+ if (array_is_created(&keyword_updates[i].remove_seq)) {
+ synclist = array_modifyable_append(&ctx->sync_list);
+ synclist->array = &keyword_updates[i].remove_seq;
+ synclist->keyword_idx = i;
+ synclist->keyword_remove = TRUE;
+ }
}
return ret;
@@ -430,16 +441,17 @@
rec->remove_flags = update->remove_flags;
}
-static void mail_index_sync_get_keyword_update(struct mail_index_sync_rec *rec,
- const struct uid_range *range,
- unsigned int num)
+static void
+mail_index_sync_get_keyword_update(struct mail_index_sync_rec *rec,
+ const struct uid_range *range,
+ struct mail_index_sync_list *sync_list)
{
- rec->type = num % 2 == 0 ?
+ rec->type = !sync_list->keyword_remove ?
MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD :
MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE;
rec->uid1 = range->uid1;
rec->uid2 = range->uid2;
- rec->keyword_idx = num / 2;
+ rec->keyword_idx = sync_list->keyword_idx;
}
static void mail_index_sync_get_keyword_reset(struct mail_index_sync_rec *rec,
@@ -530,7 +542,7 @@
mail_index_sync_get_keyword_reset(sync_rec, uid_range);
} else {
mail_index_sync_get_keyword_update(sync_rec, uid_range,
- sync_list[i].keyword_num);
+ &sync_list[i]);
}
sync_list[i].idx++;
@@ -624,12 +636,6 @@
mail_index_sync_end(ctx);
}
-const char *const *const *
-mail_index_sync_get_keywords(struct mail_index_sync_ctx *ctx)
-{
- return &ctx->index->keywords;
-}
-
void mail_index_sync_flags_apply(const struct mail_index_sync_rec *sync_rec,
uint8_t *flags)
{
@@ -637,3 +643,41 @@
*flags = (*flags & ~sync_rec->remove_flags) | sync_rec->add_flags;
}
+
+int mail_index_sync_keywords_apply(const struct mail_index_sync_rec *sync_rec,
+ array_t *keywords)
+{
+ ARRAY_SET_TYPE(keywords, unsigned int);
+ const unsigned int *keyword_indexes;
+ unsigned int idx = sync_rec->keyword_idx;
+ unsigned int i, count;
+
+ keyword_indexes = array_get(keywords, &count);
+ switch (sync_rec->type) {
+ case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
+ for (i = 0; i < count; i++) {
+ if (keyword_indexes[i] == idx)
+ return FALSE;
+ }
+
+ array_append(keywords, &idx, 1);
+ return TRUE;
+ case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
+ for (i = 0; i < count; i++) {
+ if (keyword_indexes[i] == idx) {
+ array_delete(keywords, i, 1);
+ return TRUE;
+ }
+ }
+ return FALSE;
+ case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
+ if (array_count(keywords) == 0)
+ return FALSE;
+
+ array_clear(keywords);
+ return TRUE;
+ default:
+ i_unreached();
+ return FALSE;
+ }
+}
Index: mail-index-transaction-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-transaction-private.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- mail-index-transaction-private.h 12 Mar 2005 18:16:29 -0000 1.23
+++ mail-index-transaction-private.h 2 Apr 2005 21:09:03 -0000 1.24
@@ -3,6 +3,11 @@
#include "mail-transaction-log.h"
+struct mail_index_transaction_keyword_update {
+ array_t ARRAY_DEFINE(add_seq, uint32_t);
+ array_t ARRAY_DEFINE(remove_seq, uint32_t);
+};
+
struct mail_index_transaction {
int refcount;
struct mail_index_view *view;
@@ -21,7 +26,8 @@
array_t ARRAY_DEFINE(ext_resizes, struct mail_transaction_ext_intro);
array_t ARRAY_DEFINE(ext_resets, uint32_t);
- array_t ARRAY_DEFINE(keyword_updates, array_t);
+ array_t ARRAY_DEFINE(keyword_updates,
+ struct mail_index_transaction_keyword_update);
array_t ARRAY_DEFINE(keyword_resets, struct seq_range);
struct mail_cache_transaction_ctx *cache_trans_ctx;
Index: mail-index-transaction.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-transaction.c,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -d -r1.57 -r1.58
--- mail-index-transaction.c 27 Mar 2005 12:22:21 -0000 1.57
+++ mail-index-transaction.c 2 Apr 2005 21:09:03 -0000 1.58
@@ -56,11 +56,15 @@
}
if (array_is_created(&t->keyword_updates)) {
- recs = array_get_modifyable(&t->keyword_updates, &count);
+ struct mail_index_transaction_keyword_update *u;
+
+ u = array_get_modifyable(&t->keyword_updates, &count);
for (i = 0; i < count; i++) {
- if (array_is_created(&recs[i]))
- array_free(&recs[i]);
+ if (array_is_created(&u[i].add_seq))
+ array_free(&u[i].add_seq);
+ if (array_is_created(&u[i].remove_seq))
+ array_free(&u[i].remove_seq);
}
array_free(&t->keyword_updates);
}
@@ -830,11 +834,9 @@
mail_index_keywords_create(struct mail_index_transaction *t,
const char *const keywords[])
{
- /* @UNSAFE */
struct mail_index *index = t->view->index;
struct mail_keywords *k;
- const char **missing_keywords, *keyword;
- unsigned int count, i, j, k_pos = 0, missing_count = 0;
+ unsigned int i, count;
if (keywords == NULL) {
k = i_new(struct mail_keywords, 1);
@@ -843,48 +845,39 @@
}
count = strarray_length(keywords);
+ /* @UNSAFE */
k = i_malloc(sizeof(struct mail_keywords) +
(sizeof(k->idx) * (count-1)));
- k->index = t->view->index;
+ k->index = index;
k->count = count;
- t_push();
- missing_keywords = t_new(const char *, count + 1);
-
/* look up the keywords from index. they're never removed from there
so we can permanently store indexes to them. */
for (i = 0; i < count; i++) {
- for (j = 0; index->keywords[j] != NULL; j++) {
- if (strcasecmp(keywords[i], index->keywords[j]) == 0)
- break;
- }
-
- if (index->keywords[j] != NULL)
- k->idx[k_pos++] = j;
- else
- missing_keywords[missing_count++] = keywords[i];
+ (void)mail_index_keyword_lookup(index, keywords[i],
+ TRUE, &k->idx[i]);
}
+ return k;
+}
- if (missing_count > 0) {
- /* add missing keywords. first drop the trailing NULL. */
- array_delete(&index->keywords_arr,
- array_count(&index->keywords_arr) - 1, 1);
-
- j = array_count(&index->keywords_arr);
- for (; *missing_keywords != NULL; missing_keywords++, j++) {
- keyword = p_strdup(index->keywords_pool,
- *missing_keywords);
- array_append(&index->keywords_arr, &keyword, 1);
+struct mail_keywords *
+mail_index_keywords_create_from_indexes(struct mail_index_transaction *t,
+ const array_t *keyword_indexes)
+{
+ ARRAY_SET_TYPE(keyword_indexes, unsigned int);
+ struct mail_keywords *k;
+ unsigned int count;
- k->idx[k_pos++] = j;
- }
+ count = array_count(keyword_indexes);
- (void)array_modifyable_append(&index->keywords_arr);
- index->keywords = array_idx(&index->keywords_arr, 0);
- }
- i_assert(k_pos == count);
+ /* @UNSAFE */
+ k = i_malloc(sizeof(struct mail_keywords) +
+ (sizeof(k->idx) * (count-1)));
+ k->index = t->view->index;
+ k->count = count;
- t_pop();
+ memcpy(k->idx, array_get(keyword_indexes, NULL),
+ count * sizeof(k->idx[0]));
return k;
}
@@ -897,8 +890,8 @@
enum modify_type modify_type,
struct mail_keywords *keywords)
{
- array_t *arr;
- unsigned int i, idx;
+ struct mail_index_transaction_keyword_update *u;
+ unsigned int i;
i_assert(seq > 0 &&
(seq <= mail_index_view_get_messages_count(t->view) ||
@@ -906,48 +899,40 @@
i_assert(keywords->count > 0 || modify_type == MODIFY_REPLACE);
i_assert(keywords->index == t->view->index);
- /* keyword_updates is an array of
- { buffer_t *add_seq; buffer_t *remove_seq; }
- which is why there's the multiplication by 2.
-
- If t->keyword_resets is set for the sequence, there's no need to
- update remove_seq as it will remove all keywords. */
-
if (!array_is_created(&t->keyword_updates)) {
uint32_t max_idx = keywords->idx[keywords->count-1];
ARRAY_CREATE(&t->keyword_updates, default_pool,
- array_t, max_idx * 2);
+ struct mail_index_transaction_keyword_update,
+ max_idx);
}
switch (modify_type) {
case MODIFY_ADD:
for (i = 0; i < keywords->count; i++) {
- idx = keywords->idx[i] * 2;
- arr = array_modifyable_idx(&t->keyword_updates, idx);
- mail_index_seq_range_array_add(arr, 16, seq);
-
- arr = array_modifyable_idx(&t->keyword_updates, idx+1);
- mail_index_seq_range_array_remove(arr, seq);
+ u = array_modifyable_idx(&t->keyword_updates,
+ keywords->idx[i]);
+ mail_index_seq_range_array_add(&u->add_seq, 16, seq);
+ mail_index_seq_range_array_remove(&u->remove_seq, seq);
}
break;
case MODIFY_REMOVE:
for (i = 0; i < keywords->count; i++) {
- idx = keywords->idx[i] * 2;
- arr = array_modifyable_idx(&t->keyword_updates, idx);
- mail_index_seq_range_array_remove(arr, seq);
-
- arr = array_modifyable_idx(&t->keyword_updates, idx+1);
- mail_index_seq_range_array_add(arr, 16, seq);
+ u = array_modifyable_idx(&t->keyword_updates,
+ keywords->idx[i]);
+ mail_index_seq_range_array_remove(&u->add_seq, seq);
+ mail_index_seq_range_array_add(&u->remove_seq, 16, seq);
}
break;
case MODIFY_REPLACE:
for (i = 0; i < keywords->count; i++) {
- idx = keywords->idx[i] * 2;
- arr = array_modifyable_idx(&t->keyword_updates, idx);
- mail_index_seq_range_array_add(arr, 16, seq);
+ u = array_modifyable_idx(&t->keyword_updates,
+ keywords->idx[i]);
+ mail_index_seq_range_array_add(&u->add_seq, 16, seq);
}
+ /* If t->keyword_resets is set for a sequence, there's no
+ need to update remove_seq as it will remove all keywords. */
mail_index_seq_range_array_add(&t->keyword_resets, 16, seq);
break;
}
Index: mail-index-view.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-view.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- mail-index-view.c 12 Mar 2005 18:16:29 -0000 1.33
+++ mail-index-view.c 2 Apr 2005 21:09:03 -0000 1.34
@@ -458,58 +458,71 @@
}
int mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
- buffer_t *buf, const char *const **keywords_r)
+ array_t *keyword_idx)
{
+ ARRAY_SET_TYPE(keyword_idx, unsigned int);
struct mail_index_map *map;
const struct mail_index_ext *ext;
const void *data;
- unsigned int i, j;
+ const unsigned int *keyword_idx_map;
+ unsigned int i, j, keyword_count, index_idx;
uint32_t ext_id, idx;
int ret;
- *keywords_r = NULL;
- buffer_set_used_size(buf, 0);
+ array_clear(keyword_idx);
ext_id = view->index->keywords_ext_id;
ret = mail_index_lookup_ext_full(view, seq, ext_id, &map, &data);
if (ret < 0)
return -1;
- if (!mail_index_map_get_ext_idx(map, ext_id, &idx)) {
- buffer_append_zero(buf, sizeof(const char *));
- *keywords_r = buf->data;
+ if (!mail_index_map_get_ext_idx(map, ext_id, &idx))
return ret;
- }
ext = array_idx(&map->extensions, idx);
+ if (!array_is_created(&map->keyword_idx_map)) {
+ keyword_idx_map = NULL;
+ keyword_count = 0;
+ } else {
+ keyword_idx_map = array_get(&map->keyword_idx_map,
+ &keyword_count);
+ }
+
for (i = 0, idx = 0; i < ext->record_size; i++) {
- if (((const char *)data)[i] == 0)
+ if (((const unsigned char *)data)[i] == 0)
continue;
+ idx = i * CHAR_BIT;
for (j = 0; j < CHAR_BIT; j++, idx++) {
- if ((((const char *)data)[i] & (1 << j)) == 0)
+ if ((((const unsigned char *)data)[i] & (1 << j)) == 0)
continue;
- if (idx >= map->keywords_count) {
+ if (idx >= keyword_count) {
/* keyword header is updated, re-read
it so we know what this one is
called */
if (mail_index_map_read_keywords(view->index,
map) < 0)
return -1;
- if (idx >= map->keywords_count) {
+
+ if (!array_is_created(&map->keyword_idx_map))
+ return ret;
+
+ keyword_idx_map =
+ array_get(&map->keyword_idx_map,
+ &keyword_count);
+
+ if (idx >= keyword_count) {
/* extra bits set in keyword bytes.
shouldn't happen, but just ignore. */
break;
}
}
- buffer_append(buf, &map->keywords[idx],
- sizeof(const char *));
+
+ index_idx = keyword_idx_map[idx];
+ array_append(keyword_idx, &index_idx, 1);
}
}
- buffer_append_zero(buf, sizeof(const char *));
- *keywords_r = buf->data;
-
return ret;
}
Index: mail-index.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index.c,v
retrieving revision 1.196
retrieving revision 1.197
diff -u -d -r1.196 -r1.197
--- mail-index.c 29 Mar 2005 12:18:49 -0000 1.196
+++ mail-index.c 2 Apr 2005 21:09:05 -0000 1.197
@@ -2,6 +2,7 @@
#include "lib.h"
#include "buffer.h"
+#include "hash.h"
#include "mmap-util.h"
#include "read-full.h"
#include "write-full.h"
@@ -45,23 +46,25 @@
index->keywords_ext_id =
mail_index_ext_register(index, "keywords", 128, 2, 1);
index->keywords_pool = pool_alloconly_create("keywords", 512);
- ARRAY_CREATE(&index->keywords_arr, default_pool,
- const char *, 16);
- (void)array_modifyable_append(&index->keywords_arr);
- index->keywords = array_idx(&index->keywords_arr, 0);
+ ARRAY_CREATE(&index->keywords, default_pool, const char *, 16);
+ index->keywords_hash =
+ hash_create(default_pool, index->keywords_pool, 0,
+ strcase_hash, (hash_cmp_callback_t *)strcasecmp);
return index;
}
void mail_index_free(struct mail_index *index)
{
mail_index_close(index);
+
+ hash_destroy(index->keywords_hash);
pool_unref(index->extension_pool);
pool_unref(index->keywords_pool);
array_free(&index->sync_handlers);
array_free(&index->sync_lost_handlers);
array_free(&index->expunge_handlers);
- array_free(&index->keywords_arr);
+ array_free(&index->keywords);
i_free(index->error);
i_free(index->dir);
@@ -333,20 +336,45 @@
return 1;
}
+int mail_index_keyword_lookup(struct mail_index *index,
+ const char *keyword, int autocreate,
+ unsigned int *idx_r)
+{
+ char *keyword_dup;
+ void *value;
+
+ if (hash_lookup_full(index->keywords_hash, keyword, NULL, &value)) {
+ *idx_r = POINTER_CAST_TO(value, unsigned int);
+ return TRUE;
+ }
+
+ if (!autocreate) {
+ *idx_r = (unsigned int)-1;
+ return FALSE;
+ }
+
+ keyword = keyword_dup = p_strdup(index->keywords_pool, keyword);
+ *idx_r = array_count(&index->keywords);
+
+ hash_insert(index->keywords_hash, keyword_dup, POINTER_CAST(*idx_r));
+ array_append(&index->keywords, &keyword, 1);
+ return TRUE;
+}
+
int mail_index_map_read_keywords(struct mail_index *index,
struct mail_index_map *map)
{
const struct mail_index_ext *ext;
const struct mail_index_keyword_header *kw_hdr;
const struct mail_index_keyword_header_rec *kw_rec;
- const char *name, **keywords_list;
- unsigned int i, name_len;
+ const char *name;
+ unsigned int i, name_len, old_count;
uint32_t ext_id;
ext_id = mail_index_map_lookup_ext(map, "keywords");
if (ext_id == (uint32_t)-1) {
- map->keywords = NULL;
- map->keywords_count = 0;
+ if (array_is_created(&map->keyword_idx_map))
+ array_clear(&map->keyword_idx_map);
return 0;
}
@@ -356,6 +384,23 @@
kw_rec = (const void *)(kw_hdr + 1);
name = (const char *)(kw_rec + kw_hdr->keywords_count);
+ old_count = !array_is_created(&map->keyword_idx_map) ? 0 :
+ array_count(&map->keyword_idx_map);
+
+ /* Keywords can only be added in mapping. */
+ if (kw_hdr->keywords_count == old_count) {
+ /* nothing changed */
+ return 0;
+ }
+
+ /* make sure the header is valid */
+ if (kw_hdr->keywords_count < old_count) {
+ mail_index_set_error(index, "Corrupted index file %s: "
+ "Keywords removed unexpectedly",
+ index->filepath);
+ return -1;
+ }
+
if ((size_t)(name - (const char *)kw_hdr) > ext->hdr_size) {
mail_index_set_error(index, "Corrupted index file %s: "
"keywords_count larger than header size",
@@ -363,7 +408,6 @@
return -1;
}
- /* make sure the header is valid */
name_len = (const char *)kw_hdr + ext->hdr_size - name;
for (i = 0; i < kw_hdr->keywords_count; i++) {
if (kw_rec[i].name_offset > name_len) {
@@ -380,42 +424,43 @@
return -1;
}
- if (map->keywords_pool == NULL)
- map->keywords_pool = pool_alloconly_create("keywords", 1024);
-
- /* Save keywords in memory. Only new keywords should come into the
- mapping, so keep the existing keyword strings in memory to allow
- mail_index_lookup_keywords() to safely return direct pointers
- into them. */
- if (kw_hdr->keywords_count < map->keywords_count) {
- mail_index_set_error(index, "Corrupted index file %s: "
- "Keywords removed unexpectedly",
- index->filepath);
- return -1;
- }
- if (kw_hdr->keywords_count == map->keywords_count) {
- /* nothing changed */
- return 0;
+ /* create file -> index mapping */
+ if (!array_is_created(&map->keyword_idx_map)) {
+ ARRAY_CREATE(&map->keyword_idx_map, default_pool,
+ unsigned int, kw_hdr->keywords_count);
}
- /* @UNSAFE */
- keywords_list = p_new(map->keywords_pool,
- const char *, kw_hdr->keywords_count + 1);
- for (i = 0; i < map->keywords_count; i++)
- keywords_list[i] = map->keywords[i];
+#ifdef DEBUG
+ for (i = 0; i < array_count(&map->keyword_idx_map); i++) {
+ const char *keyword = name + kw_rec[i].name_offset;
+ const unsigned int *old_idx;
+ unsigned int idx;
+
+ old_idx = array_idx(&map->keyword_idx_map, i);
+ if (!mail_index_keyword_lookup(index, keyword, FALSE, &idx) ||
+ idx != *old_idx) {
+ mail_index_set_error(index, "Corrupted index file %s: "
+ "Keywords changed unexpectedly",
+ index->filepath);
+ return -1;
+ }
+ }
+#endif
+ i = array_count(&map->keyword_idx_map);
for (; i < kw_hdr->keywords_count; i++) {
- keywords_list[i] = p_strdup(map->keywords_pool,
- name + kw_rec[i].name_offset);
+ const char *keyword = name + kw_rec[i].name_offset;
+ unsigned int idx;
+
+ (void)mail_index_keyword_lookup(index, keyword, TRUE, &idx);
+ array_append(&map->keyword_idx_map, &idx, 1);
}
- map->keywords = keywords_list;
- map->keywords_count = kw_hdr->keywords_count;
return 0;
}
-const char *const *mail_index_get_keywords(struct mail_index *index)
+const array_t *mail_index_get_keywords(struct mail_index *index)
{
(void)mail_index_map_read_keywords(index, index->map);
- return index->map->keywords;
+ return &index->keywords;
}
static int mail_index_check_header(struct mail_index *index,
@@ -508,8 +553,8 @@
mail_index_map_clear(index, map);
if (map->extension_pool != NULL)
pool_unref(map->extension_pool);
- if (map->keywords_pool != NULL)
- pool_unref(map->keywords_pool);
+ if (array_is_created(&map->keyword_idx_map))
+ array_free(&map->keyword_idx_map);
buffer_free(map->hdr_copy_buf);
i_free(map);
}
Index: mail-index.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index.h,v
retrieving revision 1.145
retrieving revision 1.146
diff -u -d -r1.145 -r1.146
--- mail-index.h 27 Mar 2005 12:22:21 -0000 1.145
+++ mail-index.h 2 Apr 2005 21:09:05 -0000 1.146
@@ -106,6 +106,14 @@
uint8_t flags; /* enum mail_flags | enum mail_index_mail_flags */
};
+struct mail_keywords {
+ struct mail_index *index;
+ unsigned int count;
+
+ /* variable sized list of keyword indexes */
+ unsigned int idx[1];
+};
+
enum mail_index_sync_type {
MAIL_INDEX_SYNC_TYPE_APPEND = 0x01,
MAIL_INDEX_SYNC_TYPE_EXPUNGE = 0x02,
@@ -124,11 +132,10 @@
uint8_t add_flags;
uint8_t remove_flags;
- /* MAIL_INDEX_SYNC_TYPE_KEYWORDS: */
+ /* MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD, .._REMOVE: */
unsigned int keyword_idx;
};
-struct mail_keywords;
struct mail_index;
struct mail_index_map;
struct mail_index_view;
@@ -256,7 +263,7 @@
struct mail_index_map **map_r,
const struct mail_index_record **rec_r);
int mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
- buffer_t *buf, const char *const **keywords_r);
+ array_t *keyword_idx);
/* Returns the UID for given message. May be slightly faster than
mail_index_lookup()->uid. */
int mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
@@ -291,13 +298,24 @@
enum modify_type modify_type,
enum mail_flags flags);
-/* Return a NULL-terminated list of all existing keywords. */
-const char *const *mail_index_get_keywords(struct mail_index *index);
+/* Lookup a keyword, returns TRUE if found, FALSE if not. If autocreate is
+ TRUE, the keyword is automatically created and TRUE is always returned. */
+int mail_index_keyword_lookup(struct mail_index *index,
+ const char *keyword, int autocreate,
+ unsigned int *idx_r);
+/* Return a pointer to array of NULL-terminated list of keywords. Note that
+ the array contents (and thus pointers inside it) may change after calling
+ mail_index_keywords_create() or mail_index_sync_begin(). */
+const array_t *mail_index_get_keywords(struct mail_index *index);
+
/* Create a keyword list structure. It's freed automatically at the end of
the transaction. */
struct mail_keywords *
mail_index_keywords_create(struct mail_index_transaction *t,
const char *const keywords[]);
+struct mail_keywords *
+mail_index_keywords_create_from_indexes(struct mail_index_transaction *t,
+ const array_t *keyword_indexes);
/* Free the keywords. */
void mail_index_keywords_free(struct mail_keywords *keywords);
/* Update keywords for given message. */
@@ -317,15 +335,14 @@
/* Reset the error message. */
void mail_index_reset_error(struct mail_index *index);
-/* Return a pointer to NULL-terminated list of keywords which are referenced
- in mail_index_sync_rec->keyword_idx. Note tat the pointer may change after
- calling mail_index_keywords_create(). */
-const char *const *const *
-mail_index_sync_get_keywords(struct mail_index_sync_ctx *ctx);
/* Apply changes in MAIL_INDEX_SYNC_TYPE_FLAGS typed sync records to given
- flags variables. */
+ flags variable. */
void mail_index_sync_flags_apply(const struct mail_index_sync_rec *sync_rec,
uint8_t *flags);
+/* Apply changes in MAIL_INDEX_SYNC_TYPE_KEYWORD_* typed sync records to given
+ keywords array. Returns TRUE If something was changed. */
+int mail_index_sync_keywords_apply(const struct mail_index_sync_rec *sync_rec,
+ array_t *keywords);
/* register index extension. name is a unique identifier for the extension.
returns unique identifier for the name. */
Index: mail-transaction-log-append.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log-append.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- mail-transaction-log-append.c 29 Mar 2005 12:18:49 -0000 1.7
+++ mail-transaction-log-append.c 2 Apr 2005 21:09:05 -0000 1.8
@@ -272,37 +272,56 @@
return 0;
}
+static int
+log_append_keyword_update(struct mail_transaction_log_file *file,
+ struct mail_index_transaction *t,
+ buffer_t *hdr_buf, enum modify_type modify_type,
+ const char *keyword, const buffer_t *buffer)
+{
+ struct mail_transaction_keyword_update kt_hdr;
+
+ memset(&kt_hdr, 0, sizeof(kt_hdr));
+ kt_hdr.modify_type = modify_type;
+ kt_hdr.name_size = strlen(keyword);
+
+ buffer_set_used_size(hdr_buf, 0);
+ buffer_append(hdr_buf, &kt_hdr, sizeof(kt_hdr));
+ buffer_append(hdr_buf, keyword, kt_hdr.name_size);
+ if ((hdr_buf->used % 4) != 0)
+ buffer_append_zero(hdr_buf, 4 - (hdr_buf->used % 4));
+
+ return log_append_buffer(file, buffer, hdr_buf,
+ MAIL_TRANSACTION_KEYWORD_UPDATE, t->external);
+}
+
static int log_append_keyword_updates(struct mail_transaction_log_file *file,
struct mail_index_transaction *t)
{
- struct mail_index *index = t->view->index;
- struct mail_transaction_keyword_update kt_hdr;
+ const struct mail_index_transaction_keyword_update *updates;
+ const char *const *keywords;
buffer_t *hdr_buf;
- array_t *updates;
- unsigned int i, count;
+ unsigned int i, count, keywords_count;
hdr_buf = buffer_create_dynamic(pool_datastack_create(), 64);
+ keywords = array_get_modifyable(&t->view->index->keywords,
+ &keywords_count);
updates = array_get_modifyable(&t->keyword_updates, &count);
- for (i = 0; i < count; i++) {
- if (!array_is_created(&updates[i]))
- continue;
-
- buffer_set_used_size(hdr_buf, 0);
-
- memset(&kt_hdr, 0, sizeof(kt_hdr));
- kt_hdr.modify_type = (i & 1) == 0 ? MODIFY_ADD : MODIFY_REMOVE;
- kt_hdr.name_size = strlen(index->keywords[i / 2]);
- buffer_append(hdr_buf, &kt_hdr, sizeof(kt_hdr));
- buffer_append(hdr_buf, index->keywords[i / 2],
- kt_hdr.name_size);
- if ((hdr_buf->used % 4) != 0)
- buffer_append_zero(hdr_buf, 4 - (hdr_buf->used % 4));
+ i_assert(count <= keywords_count);
- if (log_append_buffer(file, updates[i].buffer, hdr_buf,
- MAIL_TRANSACTION_KEYWORD_UPDATE,
- t->external) < 0)
- return -1;
+ for (i = 0; i < count; i++) {
+ if (array_is_created(&updates[i].add_seq)) {
+ if (log_append_keyword_update(file, t, hdr_buf,
+ MODIFY_ADD, keywords[i],
+ updates[i].add_seq.buffer) < 0)
+ return -1;
+ }
+ if (array_is_created(&updates[i].remove_seq)) {
+ if (log_append_keyword_update(file, t, hdr_buf,
+ MODIFY_REMOVE, keywords[i],
+ updates[i].remove_seq.buffer) < 0)
+ return -1;
+ }
}
return 0;
More information about the dovecot-cvs
mailing list