Mercurial > dovecot > original-hg > dovecot-1.2
comparison src/plugins/fts-squat/squat-trie.c @ 7197:bb9304dee6d4 HEAD
uidlist renumbering: changed iteration code to iterate children first. This
will be needed for handling expunges.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 27 Jan 2008 11:49:35 +0200 |
parents | d9b87e3ce6c8 |
children | f5f77a3ae203 |
comparison
equal
deleted
inserted
replaced
7196:4f1527e3d61b | 7197:bb9304dee6d4 |
---|---|
997 trie->hdr.root_uidlist_idx = trie->root.uid_list_idx; | 997 trie->hdr.root_uidlist_idx = trie->root.uid_list_idx; |
998 return 0; | 998 return 0; |
999 } | 999 } |
1000 | 1000 |
1001 static struct squat_trie_iterate_context * | 1001 static struct squat_trie_iterate_context * |
1002 squat_trie_iterate_uidlist_init(struct squat_trie *trie) | 1002 squat_trie_iterate_init(struct squat_trie *trie) |
1003 { | 1003 { |
1004 struct squat_trie_iterate_context *ctx; | 1004 struct squat_trie_iterate_context *ctx; |
1005 | 1005 |
1006 ctx = i_new(struct squat_trie_iterate_context, 1); | 1006 ctx = i_new(struct squat_trie_iterate_context, 1); |
1007 ctx->trie = trie; | 1007 ctx->trie = trie; |
1009 i_array_init(&ctx->parents, trie->hdr.partial_len*2); | 1009 i_array_init(&ctx->parents, trie->hdr.partial_len*2); |
1010 return ctx; | 1010 return ctx; |
1011 } | 1011 } |
1012 | 1012 |
1013 static int | 1013 static int |
1014 squat_trie_iterate_uidlist_deinit(struct squat_trie_iterate_context *ctx) | 1014 squat_trie_iterate_deinit(struct squat_trie_iterate_context *ctx) |
1015 { | 1015 { |
1016 int ret = ctx->failed ? -1 : 0; | 1016 int ret = ctx->failed ? -1 : 0; |
1017 | 1017 |
1018 array_free(&ctx->parents); | 1018 array_free(&ctx->parents); |
1019 i_free(ctx); | 1019 i_free(ctx); |
1020 return ret; | 1020 return ret; |
1021 } | 1021 } |
1022 | 1022 |
1023 static struct squat_node * | 1023 static struct squat_node * |
1024 squat_trie_iterate_uidlist_first(struct squat_trie_iterate_context *ctx) | 1024 squat_trie_iterate_first(struct squat_trie_iterate_context *ctx) |
1025 { | 1025 { |
1026 struct squat_node *node = ctx->cur.node; | 1026 if (ctx->cur.node->children_not_mapped) { |
1027 int level; | 1027 if (node_read_children(ctx->trie, ctx->cur.node, 1) < 0) { |
1028 | |
1029 if (UIDLIST_IS_SINGLETON(node->uid_list_idx)) { | |
1030 /* no uidlists */ | |
1031 i_assert(node == &ctx->trie->root); | |
1032 return NULL; | |
1033 } | |
1034 | |
1035 if (node->children_not_mapped) { | |
1036 level = array_count(&ctx->parents); | |
1037 | |
1038 if (node_read_children(ctx->trie, node, level) < 0) { | |
1039 ctx->failed = TRUE; | 1028 ctx->failed = TRUE; |
1040 return NULL; | 1029 return NULL; |
1041 } | 1030 } |
1042 } | 1031 } |
1043 return node; | 1032 return ctx->cur.node; |
1044 } | 1033 } |
1045 | 1034 |
1046 static struct squat_node * | 1035 static struct squat_node * |
1047 squat_trie_iterate_uidlist_next(struct squat_trie_iterate_context *ctx) | 1036 squat_trie_iterate_next(struct squat_trie_iterate_context *ctx) |
1048 { | 1037 { |
1049 struct squat_trie_iterate_node *iter_nodes; | 1038 struct squat_trie_iterate_node *iter_nodes; |
1050 struct squat_node *node = ctx->cur.node; | |
1051 struct squat_node *children; | 1039 struct squat_node *children; |
1052 unsigned int count; | 1040 unsigned int count; |
1053 | 1041 |
1054 /* return our children first */ | 1042 while (ctx->cur.idx == ctx->cur.node->child_count) { |
1055 children = NODE_CHILDREN_NODES(node); | |
1056 for (; ctx->cur.idx < node->child_count; ctx->cur.idx++) { | |
1057 if (!UIDLIST_IS_SINGLETON(children[ctx->cur.idx].uid_list_idx)) | |
1058 return &children[ctx->cur.idx++]; | |
1059 } | |
1060 | |
1061 ctx->cur.idx = 0; | |
1062 for (;;) { | |
1063 /* next start iterating our childrens' children */ | |
1064 while (ctx->cur.idx < node->child_count) { | |
1065 uint32_t list_idx = | |
1066 children[ctx->cur.idx++].uid_list_idx; | |
1067 | |
1068 if (UIDLIST_IS_SINGLETON(list_idx)) | |
1069 continue; | |
1070 | |
1071 array_append(&ctx->parents, &ctx->cur, 1); | |
1072 ctx->cur.node = &children[ctx->cur.idx-1]; | |
1073 ctx->cur.idx = 0; | |
1074 if (squat_trie_iterate_uidlist_first(ctx) == NULL) | |
1075 return NULL; | |
1076 return squat_trie_iterate_uidlist_next(ctx); | |
1077 } | |
1078 | |
1079 /* no more children. go to next sibling's children */ | |
1080 iter_nodes = array_get_modifiable(&ctx->parents, &count); | 1043 iter_nodes = array_get_modifiable(&ctx->parents, &count); |
1081 if (count == 0) | 1044 if (count == 0) |
1082 return NULL; | 1045 return NULL; |
1083 | |
1084 ctx->cur = iter_nodes[count-1]; | 1046 ctx->cur = iter_nodes[count-1]; |
1085 array_delete(&ctx->parents, count-1, 1); | 1047 array_delete(&ctx->parents, count-1, 1); |
1086 | 1048 } |
1087 node = ctx->cur.node; | 1049 |
1088 children = NODE_CHILDREN_NODES(node); | 1050 ctx->cur.idx++; |
1089 } | 1051 array_append(&ctx->parents, &ctx->cur, 1); |
1052 children = NODE_CHILDREN_NODES(ctx->cur.node); | |
1053 ctx->cur.node = &children[ctx->cur.idx-1]; | |
1054 ctx->cur.idx = 0; | |
1055 return ctx->cur.node; | |
1090 } | 1056 } |
1091 | 1057 |
1092 static int | 1058 static int |
1093 squat_trie_renumber_uidlists(struct squat_trie_build_context *ctx, | 1059 squat_trie_renumber_uidlists(struct squat_trie_build_context *ctx, |
1094 bool compress) | 1060 bool compress) |
1109 now = time(NULL); | 1075 now = time(NULL); |
1110 ctx->trie->hdr.indexid = | 1076 ctx->trie->hdr.indexid = |
1111 I_MAX((unsigned int)now, ctx->trie->hdr.indexid + 1); | 1077 I_MAX((unsigned int)now, ctx->trie->hdr.indexid + 1); |
1112 | 1078 |
1113 i_array_init(&uids, 1024); | 1079 i_array_init(&uids, 1024); |
1114 iter = squat_trie_iterate_uidlist_init(ctx->trie); | 1080 iter = squat_trie_iterate_init(ctx->trie); |
1115 node = squat_trie_iterate_uidlist_first(iter); | 1081 node = squat_trie_iterate_first(iter); |
1116 new_uid_list_idx = 0x100; | 1082 new_uid_list_idx = 0x100; |
1117 while (node != NULL) { | 1083 while (node != NULL) { |
1118 array_clear(&uids); | 1084 if (!UIDLIST_IS_SINGLETON(node->uid_list_idx)) { |
1119 if (squat_uidlist_get(ctx->trie->uidlist, node->uid_list_idx, | 1085 array_clear(&uids); |
1120 &uids) < 0) { | 1086 if (squat_uidlist_get(ctx->trie->uidlist, |
1121 ret = -1; | 1087 node->uid_list_idx, &uids) < 0) { |
1122 break; | 1088 ret = -1; |
1123 } | 1089 break; |
1124 max_count = I_MAX(max_count, array_count(&uids)); | 1090 } |
1125 squat_uidlist_rebuild_next(rebuild_ctx, &uids); | 1091 max_count = I_MAX(max_count, array_count(&uids)); |
1126 node->uid_list_idx = new_uid_list_idx << 1; | 1092 squat_uidlist_rebuild_next(rebuild_ctx, &uids); |
1127 new_uid_list_idx++; | 1093 node->uid_list_idx = new_uid_list_idx << 1; |
1128 | 1094 new_uid_list_idx++; |
1129 node = squat_trie_iterate_uidlist_next(iter); | 1095 } |
1130 } | 1096 node = squat_trie_iterate_next(iter); |
1131 squat_trie_iterate_uidlist_deinit(iter); | 1097 } |
1098 squat_trie_iterate_deinit(iter); | |
1132 array_free(&uids); | 1099 array_free(&uids); |
1133 | 1100 |
1134 /* lock the trie before we rename uidlist */ | 1101 /* lock the trie before we rename uidlist */ |
1135 if (squat_trie_lock(ctx->trie, F_WRLCK, &ctx->file_lock) <= 0) | 1102 if (squat_trie_lock(ctx->trie, F_WRLCK, &ctx->file_lock) <= 0) |
1136 ret = -1; | 1103 ret = -1; |