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