Mercurial > dovecot > core-2.2
comparison src/lib-storage/index/index-search.c @ 903:fd8888f6f037 HEAD
Naming style changes, finally got tired of most of the typedefs. Also the
previous enum -> macro change reverted so that we don't use the highest bit
anymore, that's incompatible with old indexes so they will be rebuilt.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 05 Jan 2003 15:09:51 +0200 |
parents | 0d5be52d7131 |
children | 4f697dde0fca |
comparison
equal
deleted
inserted
replaced
902:5043e48c022f | 903:fd8888f6f037 |
---|---|
2 | 2 |
3 #include "lib.h" | 3 #include "lib.h" |
4 #include "istream.h" | 4 #include "istream.h" |
5 #include "ostream.h" | 5 #include "ostream.h" |
6 #include "mmap-util.h" | 6 #include "mmap-util.h" |
7 #include "rfc822-date.h" | 7 #include "message-date.h" |
8 #include "message-size.h" | 8 #include "message-size.h" |
9 #include "message-body-search.h" | 9 #include "message-body-search.h" |
10 #include "message-header-search.h" | 10 #include "message-header-search.h" |
11 #include "imap-date.h" | 11 #include "imap-date.h" |
12 #include "imap-envelope.h" | 12 #include "imap-envelope.h" |
26 } STMT_END | 26 } STMT_END |
27 | 27 |
28 #define TXT_UNKNOWN_CHARSET "[BADCHARSET] Unknown charset" | 28 #define TXT_UNKNOWN_CHARSET "[BADCHARSET] Unknown charset" |
29 #define TXT_INVALID_SEARCH_KEY "Invalid search key" | 29 #define TXT_INVALID_SEARCH_KEY "Invalid search key" |
30 | 30 |
31 typedef struct { | 31 struct search_index_context { |
32 Pool hdr_pool; | 32 pool_t hdr_pool; |
33 IndexMailbox *ibox; | 33 struct index_mailbox *ibox; |
34 MailIndexRecord *rec; | 34 struct mail_index_record *rec; |
35 unsigned int client_seq; | 35 unsigned int client_seq; |
36 int cached; | 36 int cached; |
37 const char *charset; | 37 const char *charset; |
38 const char *error; | 38 const char *error; |
39 } SearchIndexContext; | 39 }; |
40 | 40 |
41 typedef struct { | 41 struct search_header_context { |
42 SearchIndexContext *index_context; | 42 struct search_index_context *index_context; |
43 MailSearchArg *args; | 43 struct mail_search_arg *args; |
44 int custom_header; | 44 int custom_header; |
45 | 45 |
46 const unsigned char *name, *value; | 46 const unsigned char *name, *value; |
47 size_t name_len, value_len; | 47 size_t name_len, value_len; |
48 } SearchHeaderContext; | 48 }; |
49 | 49 |
50 typedef struct { | 50 struct search_body_context { |
51 SearchIndexContext *index_ctx; | 51 struct search_index_context *index_ctx; |
52 IStream *input; | 52 struct istream *input; |
53 MessagePart *part; | 53 struct message_part *part; |
54 } SearchBodyContext; | 54 }; |
55 | 55 |
56 static MailSortType sort_unsorted[] = { MAIL_SORT_END }; | 56 static enum mail_sort_type sort_unsorted[] = { MAIL_SORT_END }; |
57 | 57 |
58 static int msgset_contains(const char *set, unsigned int match_num, | 58 static int msgset_contains(const char *set, unsigned int match_num, |
59 unsigned int max_num) | 59 unsigned int max_num) |
60 { | 60 { |
61 unsigned int num, num2; | 61 unsigned int num, num2; |
120 } | 120 } |
121 | 121 |
122 return num; | 122 return num; |
123 } | 123 } |
124 | 124 |
125 static int search_keyword(MailIndex *index, MailIndexRecord *rec, | 125 static int search_keyword(struct mail_index *index, |
126 const char *value) | 126 struct mail_index_record *rec, const char *value) |
127 { | 127 { |
128 const char **custom_flags; | 128 const char **custom_flags; |
129 int i; | 129 int i; |
130 | 130 |
131 if ((rec->msg_flags & MAIL_CUSTOM_FLAGS_MASK) == 0) | 131 if ((rec->msg_flags & MAIL_CUSTOM_FLAGS_MASK) == 0) |
142 | 142 |
143 return FALSE; | 143 return FALSE; |
144 } | 144 } |
145 | 145 |
146 /* Returns >0 = matched, 0 = not matched, -1 = unknown */ | 146 /* Returns >0 = matched, 0 = not matched, -1 = unknown */ |
147 static int search_arg_match_index(IndexMailbox *ibox, MailIndexRecord *rec, | 147 static int search_arg_match_index(struct index_mailbox *ibox, |
148 struct mail_index_record *rec, | |
148 unsigned int client_seq, | 149 unsigned int client_seq, |
149 MailSearchArgType type, const char *value) | 150 enum mail_search_arg_type type, |
151 const char *value) | |
150 { | 152 { |
151 switch (type) { | 153 switch (type) { |
152 case SEARCH_ALL: | 154 case SEARCH_ALL: |
153 return TRUE; | 155 return TRUE; |
154 case SEARCH_SET: | 156 case SEARCH_SET: |
177 default: | 179 default: |
178 return -1; | 180 return -1; |
179 } | 181 } |
180 } | 182 } |
181 | 183 |
182 static void search_index_arg(MailSearchArg *arg, void *context) | 184 static void search_index_arg(struct mail_search_arg *arg, void *context) |
183 { | 185 { |
184 SearchIndexContext *ctx = context; | 186 struct search_index_context *ctx = context; |
185 | 187 |
186 switch (search_arg_match_index(ctx->ibox, ctx->rec, ctx->client_seq, | 188 switch (search_arg_match_index(ctx->ibox, ctx->rec, ctx->client_seq, |
187 arg->type, arg->value.str)) { | 189 arg->type, arg->value.str)) { |
188 case -1: | 190 case -1: |
189 /* unknown */ | 191 /* unknown */ |
195 ARG_SET_RESULT(arg, 1); | 197 ARG_SET_RESULT(arg, 1); |
196 break; | 198 break; |
197 } | 199 } |
198 } | 200 } |
199 | 201 |
200 static ImapMessageCache *search_open_cache(SearchIndexContext *ctx) | 202 static struct imap_message_cache * |
203 search_open_cache(struct search_index_context *ctx) | |
201 { | 204 { |
202 if (!ctx->cached) { | 205 if (!ctx->cached) { |
203 (void)index_msgcache_open(ctx->ibox->cache, | 206 (void)index_msgcache_open(ctx->ibox->cache, |
204 ctx->ibox->index, ctx->rec, 0); | 207 ctx->ibox->index, ctx->rec, 0); |
205 ctx->cached = TRUE; | 208 ctx->cached = TRUE; |
206 } | 209 } |
207 return ctx->ibox->cache; | 210 return ctx->ibox->cache; |
208 } | 211 } |
209 | 212 |
210 /* Returns >0 = matched, 0 = not matched, -1 = unknown */ | 213 /* Returns >0 = matched, 0 = not matched, -1 = unknown */ |
211 static int search_arg_match_cached(SearchIndexContext *ctx, | 214 static int search_arg_match_cached(struct search_index_context *ctx, |
212 MailSearchArgType type, const char *value) | 215 enum mail_search_arg_type type, |
216 const char *value) | |
213 { | 217 { |
214 time_t internal_date, search_time; | 218 time_t internal_date, search_time; |
215 uoff_t virtual_size, search_size; | 219 uoff_t virtual_size, search_size; |
216 | 220 |
217 switch (type) { | 221 switch (type) { |
257 default: | 261 default: |
258 return -1; | 262 return -1; |
259 } | 263 } |
260 } | 264 } |
261 | 265 |
262 static void search_cached_arg(MailSearchArg *arg, void *context) | 266 static void search_cached_arg(struct mail_search_arg *arg, void *context) |
263 { | 267 { |
264 SearchIndexContext *ctx = context; | 268 struct search_index_context *ctx = context; |
265 | 269 |
266 switch (search_arg_match_cached(ctx, arg->type, | 270 switch (search_arg_match_cached(ctx, arg->type, |
267 arg->value.str)) { | 271 arg->value.str)) { |
268 case -1: | 272 case -1: |
269 /* unknown */ | 273 /* unknown */ |
275 ARG_SET_RESULT(arg, 1); | 279 ARG_SET_RESULT(arg, 1); |
276 break; | 280 break; |
277 } | 281 } |
278 } | 282 } |
279 | 283 |
280 static int search_sent(MailSearchArgType type, const char *search_value, | 284 static int search_sent(enum mail_search_arg_type type, const char *search_value, |
281 const char *sent_value) | 285 const char *sent_value) |
282 { | 286 { |
283 time_t search_time, sent_time; | 287 time_t search_time, sent_time; |
284 int timezone_offset; | 288 int timezone_offset; |
285 | 289 |
289 if (!imap_parse_date(search_value, &search_time)) | 293 if (!imap_parse_date(search_value, &search_time)) |
290 return 0; | 294 return 0; |
291 | 295 |
292 /* NOTE: Latest IMAP4rev1 draft specifies that timezone is ignored | 296 /* NOTE: Latest IMAP4rev1 draft specifies that timezone is ignored |
293 in searches. */ | 297 in searches. */ |
294 if (!rfc822_parse_date(sent_value, &sent_time, &timezone_offset)) | 298 if (!message_date_parse(sent_value, &sent_time, &timezone_offset)) |
295 return 0; | 299 return 0; |
296 | 300 |
297 switch (type) { | 301 switch (type) { |
298 case SEARCH_SENTBEFORE: | 302 case SEARCH_SENTBEFORE: |
299 return sent_time < search_time; | 303 return sent_time < search_time; |
305 default: | 309 default: |
306 i_unreached(); | 310 i_unreached(); |
307 } | 311 } |
308 } | 312 } |
309 | 313 |
310 static HeaderSearchContext *search_header_context(SearchIndexContext *ctx, | 314 static struct header_search_context * |
311 MailSearchArg *arg) | 315 search_header_context(struct search_index_context *ctx, |
316 struct mail_search_arg *arg) | |
312 { | 317 { |
313 int unknown_charset; | 318 int unknown_charset; |
314 | 319 |
315 if (arg->context != NULL) { | 320 if (arg->context != NULL) { |
316 message_header_search_reset(arg->context); | 321 message_header_search_reset(arg->context); |
332 | 337 |
333 return arg->context; | 338 return arg->context; |
334 } | 339 } |
335 | 340 |
336 /* Returns >0 = matched, 0 = not matched, -1 = unknown */ | 341 /* Returns >0 = matched, 0 = not matched, -1 = unknown */ |
337 static int search_arg_match_envelope(SearchIndexContext *ctx, | 342 static int search_arg_match_envelope(struct search_index_context *ctx, |
338 MailSearchArg *arg) | 343 struct mail_search_arg *arg) |
339 { | 344 { |
340 MailIndex *index = ctx->ibox->index; | 345 struct mail_index *index = ctx->ibox->index; |
341 ImapEnvelopeField env_field; | 346 enum imap_envelope_field env_field; |
342 HeaderSearchContext *hdr_search_ctx; | 347 struct header_search_context *hdr_search_ctx; |
343 const char *envelope, *field; | 348 const char *envelope, *field; |
344 int ret; | 349 int ret; |
345 | 350 |
346 switch (arg->type) { | 351 switch (arg->type) { |
347 case SEARCH_SENTBEFORE: | 352 case SEARCH_SENTBEFORE: |
380 | 385 |
381 /* get field from hopefully cached envelope */ | 386 /* get field from hopefully cached envelope */ |
382 envelope = index->lookup_field(index, ctx->rec, DATA_FIELD_ENVELOPE); | 387 envelope = index->lookup_field(index, ctx->rec, DATA_FIELD_ENVELOPE); |
383 if (envelope != NULL) { | 388 if (envelope != NULL) { |
384 ret = imap_envelope_parse(envelope, env_field, | 389 ret = imap_envelope_parse(envelope, env_field, |
385 IMAP_ENVELOPE_RESULT_STRING, | 390 IMAP_ENVELOPE_RESULT_TYPE_STRING, |
386 &field) ? 1 : -1; | 391 &field) ? 1 : -1; |
387 } else { | 392 } else { |
388 index->cache_fields_later(index, DATA_FIELD_ENVELOPE); | 393 index->cache_fields_later(index, DATA_FIELD_ENVELOPE); |
389 field = NULL; | 394 field = NULL; |
390 ret = -1; | 395 ret = -1; |
424 } | 429 } |
425 t_pop(); | 430 t_pop(); |
426 return ret; | 431 return ret; |
427 } | 432 } |
428 | 433 |
429 static void search_envelope_arg(MailSearchArg *arg, void *context) | 434 static void search_envelope_arg(struct mail_search_arg *arg, void *context) |
430 { | 435 { |
431 SearchIndexContext *ctx = context; | 436 struct search_index_context *ctx = context; |
432 | 437 |
433 switch (search_arg_match_envelope(ctx, arg)) { | 438 switch (search_arg_match_envelope(ctx, arg)) { |
434 case -1: | 439 case -1: |
435 /* unknown */ | 440 /* unknown */ |
436 break; | 441 break; |
441 ARG_SET_RESULT(arg, 1); | 446 ARG_SET_RESULT(arg, 1); |
442 break; | 447 break; |
443 } | 448 } |
444 } | 449 } |
445 | 450 |
446 static void search_header_arg(MailSearchArg *arg, void *context) | 451 static void search_header_arg(struct mail_search_arg *arg, void *context) |
447 { | 452 { |
448 SearchHeaderContext *ctx = context; | 453 struct search_header_context *ctx = context; |
449 HeaderSearchContext *hdr_search_ctx; | 454 struct header_search_context *hdr_search_ctx; |
450 size_t len; | 455 size_t len; |
451 int ret; | 456 int ret; |
452 | 457 |
453 /* first check that the field name matches to argument. */ | 458 /* first check that the field name matches to argument. */ |
454 switch (arg->type) { | 459 switch (arg->type) { |
518 } | 523 } |
519 | 524 |
520 ARG_SET_RESULT(arg, ret); | 525 ARG_SET_RESULT(arg, ret); |
521 } | 526 } |
522 | 527 |
523 static void search_header(MessagePart *part __attr_unused__, | 528 static void search_header(struct message_part *part __attr_unused__, |
524 const unsigned char *name, size_t name_len, | 529 const unsigned char *name, size_t name_len, |
525 const unsigned char *value, size_t value_len, | 530 const unsigned char *value, size_t value_len, |
526 void *context) | 531 void *context) |
527 { | 532 { |
528 SearchHeaderContext *ctx = context; | 533 struct search_header_context *ctx = context; |
529 | 534 |
530 if ((name_len > 0 && ctx->custom_header) || | 535 if ((name_len > 0 && ctx->custom_header) || |
531 (name_len == 4 && memcasecmp(name, "Date", 4) == 0) || | 536 (name_len == 4 && memcasecmp(name, "Date", 4) == 0) || |
532 (name_len == 4 && memcasecmp(name, "From", 4) == 0) || | 537 (name_len == 4 && memcasecmp(name, "From", 4) == 0) || |
533 (name_len == 2 && memcasecmp(name, "To", 2) == 0) || | 538 (name_len == 2 && memcasecmp(name, "To", 2) == 0) || |
542 ctx->custom_header = FALSE; | 547 ctx->custom_header = FALSE; |
543 mail_search_args_foreach(ctx->args, search_header_arg, ctx); | 548 mail_search_args_foreach(ctx->args, search_header_arg, ctx); |
544 } | 549 } |
545 } | 550 } |
546 | 551 |
547 static void search_body(MailSearchArg *arg, void *context) | 552 static void search_body(struct mail_search_arg *arg, void *context) |
548 { | 553 { |
549 SearchBodyContext *ctx = context; | 554 struct search_body_context *ctx = context; |
550 int ret, unknown_charset; | 555 int ret, unknown_charset; |
551 | 556 |
552 if (ctx->index_ctx->error != NULL) | 557 if (ctx->index_ctx->error != NULL) |
553 return; | 558 return; |
554 | 559 |
566 | 571 |
567 ARG_SET_RESULT(arg, ret > 0); | 572 ARG_SET_RESULT(arg, ret > 0); |
568 } | 573 } |
569 } | 574 } |
570 | 575 |
571 static int search_arg_match_text(MailSearchArg *args, SearchIndexContext *ctx) | 576 static int search_arg_match_text(struct mail_search_arg *args, |
572 { | 577 struct search_index_context *ctx) |
573 IStream *input; | 578 { |
579 struct istream *input; | |
574 int have_headers, have_body, have_text; | 580 int have_headers, have_body, have_text; |
575 | 581 |
576 /* first check what we need to use */ | 582 /* first check what we need to use */ |
577 mail_search_args_analyze(args, &have_headers, &have_body, &have_text); | 583 mail_search_args_analyze(args, &have_headers, &have_body, &have_text); |
578 if (!have_headers && !have_body && !have_text) | 584 if (!have_headers && !have_body && !have_text) |
579 return TRUE; | 585 return TRUE; |
580 | 586 |
581 if (have_headers || have_text) { | 587 if (have_headers || have_text) { |
582 SearchHeaderContext hdr_ctx; | 588 struct search_header_context hdr_ctx; |
583 | 589 |
584 if (!imap_msgcache_get_data(search_open_cache(ctx), &input)) | 590 if (!imap_msgcache_get_data(search_open_cache(ctx), &input)) |
585 return FALSE; | 591 return FALSE; |
586 | 592 |
587 memset(&hdr_ctx, 0, sizeof(hdr_ctx)); | 593 memset(&hdr_ctx, 0, sizeof(hdr_ctx)); |
596 NULL, NULL)) | 602 NULL, NULL)) |
597 return FALSE; | 603 return FALSE; |
598 } | 604 } |
599 | 605 |
600 if (have_text || have_body) { | 606 if (have_text || have_body) { |
601 SearchBodyContext body_ctx; | 607 struct search_body_context body_ctx; |
602 | 608 |
603 memset(&body_ctx, 0, sizeof(body_ctx)); | 609 memset(&body_ctx, 0, sizeof(body_ctx)); |
604 body_ctx.index_ctx = ctx; | 610 body_ctx.index_ctx = ctx; |
605 body_ctx.input = input; | 611 body_ctx.input = input; |
606 body_ctx.part = imap_msgcache_get_parts(search_open_cache(ctx)); | 612 body_ctx.part = imap_msgcache_get_parts(search_open_cache(ctx)); |
636 | 642 |
637 set++; | 643 set++; |
638 } | 644 } |
639 } | 645 } |
640 | 646 |
641 static void search_get_sequid(IndexMailbox *ibox, MailSearchArg *args, | 647 static void search_get_sequid(struct index_mailbox *ibox, |
648 struct mail_search_arg *args, | |
642 unsigned int *first_seq, unsigned int *last_seq, | 649 unsigned int *first_seq, unsigned int *last_seq, |
643 unsigned int *first_uid, unsigned int *last_uid) | 650 unsigned int *first_uid, unsigned int *last_uid) |
644 { | 651 { |
645 for (; args != NULL; args = args->next) { | 652 for (; args != NULL; args = args->next) { |
646 if (args->type == SEARCH_OR || args->type == SEARCH_SUB) { | 653 if (args->type == SEARCH_OR || args->type == SEARCH_SUB) { |
660 return; | 667 return; |
661 } | 668 } |
662 } | 669 } |
663 } | 670 } |
664 | 671 |
665 static int search_limit_by_flags(IndexMailbox *ibox, MailSearchArg *args, | 672 static int search_limit_by_flags(struct index_mailbox *ibox, |
673 struct mail_search_arg *args, | |
666 unsigned int *first_uid, | 674 unsigned int *first_uid, |
667 unsigned int *last_uid) | 675 unsigned int *last_uid) |
668 { | 676 { |
669 MailIndexHeader *hdr; | 677 struct mail_index_header *hdr; |
670 unsigned int uid; | 678 unsigned int uid; |
671 | 679 |
672 hdr = ibox->index->header; | 680 hdr = ibox->index->header; |
673 for (; args != NULL; args = args->next) { | 681 for (; args != NULL; args = args->next) { |
674 if (args->type == SEARCH_SEEN) { | 682 if (args->type == SEARCH_SEEN) { |
713 } | 721 } |
714 | 722 |
715 return *first_uid <= *last_uid; | 723 return *first_uid <= *last_uid; |
716 } | 724 } |
717 | 725 |
718 static unsigned int client_seq_to_uid(MailIndex *index, unsigned int seq) | 726 static unsigned int client_seq_to_uid(struct mail_index *index, |
719 { | 727 unsigned int seq) |
720 MailIndexRecord *rec; | 728 { |
729 struct mail_index_record *rec; | |
721 unsigned int expunges_before; | 730 unsigned int expunges_before; |
722 | 731 |
723 (void)mail_modifylog_seq_get_expunges(index->modifylog, seq, seq, | 732 (void)mail_modifylog_seq_get_expunges(index->modifylog, seq, seq, |
724 &expunges_before); | 733 &expunges_before); |
725 seq -= expunges_before; | 734 seq -= expunges_before; |
726 | 735 |
727 rec = index->lookup(index, seq); | 736 rec = index->lookup(index, seq); |
728 return rec == NULL ? 0 : rec->uid; | 737 return rec == NULL ? 0 : rec->uid; |
729 } | 738 } |
730 | 739 |
731 static int search_get_uid_range(IndexMailbox *ibox, MailSearchArg *args, | 740 static int search_get_uid_range(struct index_mailbox *ibox, |
741 struct mail_search_arg *args, | |
732 unsigned int *first_uid, | 742 unsigned int *first_uid, |
733 unsigned int *last_uid) | 743 unsigned int *last_uid) |
734 { | 744 { |
735 unsigned int first_seq, last_seq, uid; | 745 unsigned int first_seq, last_seq, uid; |
736 | 746 |
773 | 783 |
774 i_assert(*first_uid <= *last_uid); | 784 i_assert(*first_uid <= *last_uid); |
775 return TRUE; | 785 return TRUE; |
776 } | 786 } |
777 | 787 |
778 static int search_messages(IndexMailbox *ibox, const char *charset, | 788 static int search_messages(struct index_mailbox *ibox, const char *charset, |
779 MailSearchArg *args, MailSortContext *sort_ctx, | 789 struct mail_search_arg *args, |
780 OStream *output, int uid_result) | 790 struct mail_sort_context *sort_ctx, |
781 { | 791 struct ostream *output, int uid_result) |
782 SearchIndexContext ctx; | 792 { |
783 MailIndexRecord *rec; | 793 struct search_index_context ctx; |
784 MailSearchArg *arg; | 794 struct mail_index_record *rec; |
785 const ModifyLogExpunge *expunges; | 795 struct mail_search_arg *arg; |
796 const struct modify_log_expunge *expunges; | |
786 unsigned int first_uid, last_uid, client_seq, expunges_before; | 797 unsigned int first_uid, last_uid, client_seq, expunges_before; |
787 const char *str; | 798 const char *str; |
788 int found, failed; | 799 int found, failed; |
789 | 800 |
790 if (ibox->synced_messages_count == 0) | 801 if (ibox->synced_messages_count == 0) |
868 if (ctx.error != NULL) | 879 if (ctx.error != NULL) |
869 mail_storage_set_error(ibox->box.storage, "%s", ctx.error); | 880 mail_storage_set_error(ibox->box.storage, "%s", ctx.error); |
870 return ctx.error == NULL; | 881 return ctx.error == NULL; |
871 } | 882 } |
872 | 883 |
873 int index_storage_search(Mailbox *box, const char *charset, MailSearchArg *args, | 884 int index_storage_search(struct mailbox *box, const char *charset, |
874 MailSortType *sorting, OStream *output, int uid_result) | 885 struct mail_search_arg *args, |
875 { | 886 enum mail_sort_type *sorting, |
876 IndexMailbox *ibox = (IndexMailbox *) box; | 887 struct ostream *output, int uid_result) |
877 MailSortContext *sort_ctx; | 888 { |
878 IndexSortContext index_sort_ctx; | 889 struct index_mailbox *ibox = (struct index_mailbox *) box; |
890 struct mail_sort_context *sort_ctx; | |
891 struct index_sort_context index_sort_ctx; | |
879 int failed; | 892 int failed; |
880 | 893 |
881 if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED)) | 894 if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED)) |
882 return FALSE; | 895 return FALSE; |
883 | 896 |