1.13.6
by Marco Nenciarini
Import upstream version 1.2.13 |
1 |
Mailbox Searching |
2 |
================= |
|
3 |
||
4 |
'mailbox_search_*()' functions should be used always when you're iterating |
|
5 |
through multiple messages. The search queries can be complex or as simple as |
|
6 |
"all messages". Without searching there's also a way to directly switch to a |
|
7 |
specific message by its sequence number or UID, but this should be avoided |
|
8 |
usually. |
|
9 |
||
10 |
Initializing |
|
11 |
------------ |
|
12 |
||
13 |
Search is initialized with 'mailbox_search_init()' on top of a <transaction> |
|
14 |
[Design.Storage.Mailbox.Transaction.txt]. Although it would appear that a |
|
15 |
search is a read-only operation, it can actually write data to Dovecot's cache |
|
16 |
file. For example if you search for a specific header not yet in cache file, |
|
17 |
the results are saved to cache file so the next search will be fast. This is |
|
18 |
why you should always commit search transactions, even if the rest of your |
|
19 |
operation fails (you should use separate transactions for search and for |
|
20 |
updates if necessary). |
|
21 |
||
22 |
You'll need a search query. 'src/lib-storage/mail-search.h' and |
|
23 |
'mail-search-build.h' contain all the functions and structures related to it. |
|
24 |
Usually you should start with 'mail_search_build_init()' and then start adding |
|
25 |
the search parameters, either manually or with one of the existing |
|
26 |
'mail_search_build_add_*()' helper functions. The same search query structures |
|
27 |
can be saved and used for other searches later, but because search state is |
|
28 |
stored inside the structs you need to be careful that multiple searches aren't |
|
29 |
using them at the same time. This is usually more trouble than worth, so avoid |
|
30 |
doing it. |
|
31 |
||
32 |
Search results can be sorted by giving a sort program. Dovecot optimizes this |
|
33 |
by keeping sort indexes in the index files. |
|
34 |
||
35 |
Reading search results |
|
36 |
---------------------- |
|
37 |
||
38 |
While 'mailbox_search_next()' returns TRUE, a new search result is found and it |
|
39 |
changes the given <mail> [Design.Storage.Mail.txt] to point to the search |
|
40 |
result. The mail's "wanted fields/headers" parameters don't need to include |
|
41 |
anything needed by the search query, Dovecot optimizes them internally. |
|
42 |
||
43 |
If the search needs to parse message bodies and the mailbox is large, this call |
|
44 |
can take a long time. If you want to do other things while searching, you can |
|
45 |
use 'mailbox_search_next_nonblock()' that does only a bit of work and then |
|
46 |
returns either with a result or "try again later" status. Dovecot attempts to |
|
47 |
keep each non-matching call to this function between 200 and 250 milliseconds, |
|
48 |
although the upper bound can't be guaranteed. |
|
49 |
||
50 |
It's possible that messages are being expunged while Dovecot is searching them, |
|
51 |
so it can't determine if they would have matched the search rule or not. In |
|
52 |
this case it skips over them, but if you want to know if this has happened, you |
|
53 |
can see if 'mailbox_search_seen_lost_data()' returns TRUE. |
|
54 |
||
55 |
Deinitializing |
|
56 |
-------------- |
|
57 |
||
58 |
'mailbox_search_deinit()' finishes the search. If it returns -1, some error |
|
59 |
occurred and some search results might not have been returned. |
|
60 |
||
61 |
Example |
|
62 |
------- |
|
63 |
||
64 |
Iterating through all messages in a mailbox goes like: |
|
65 |
||
66 |
---%<------------------------------------------------------------------------- |
|
67 |
/* build search query */ |
|
68 |
search_args = mail_search_build_init(); |
|
69 |
mail_search_build_add_all(search_args); |
|
70 |
||
71 |
search_ctx = mailbox_search_init(trans, search_args, NULL); |
|
72 |
/* search context keeps args referenced */ |
|
73 |
mail_search_args_unref(&search_args); |
|
74 |
||
75 |
mail = mail_alloc(trans, 0, NULL); |
|
76 |
while (mailbox_search_next(ctx, mail)) { |
|
77 |
printf("matched uid %u\n", mail->uid); |
|
78 |
} |
|
79 |
mail_free(&mail); |
|
80 |
if (mailbox_search_deinit(&search_ctx) < 0) |
|
81 |
i_error("search failed"); |
|
82 |
---%<------------------------------------------------------------------------- |
|
83 |
||
84 |
Saving search results |
|
85 |
--------------------- |
|
86 |
||
87 |
Search results can be saved for future use by calling |
|
88 |
'mailbox_search_result_save()' just after initializing the search. The results |
|
89 |
as returned as UIDs with 'mailbox_search_result_get()' and may contain UIDs |
|
90 |
that are already expunged. Once you're done with the saved result, free it with |
|
91 |
'mailbox_search_result_free()'. |
|
92 |
||
93 |
The search result can also be automatically updated whenever mailbox is synced |
|
94 |
if 'MAILBOX_SEARCH_RESULT_FLAG_UPDATE' is set. The update is optimized, so |
|
95 |
Dovecot doesn't do a full re-search, but matches only new and changed messages. |
|
96 |
If 'MAILBOX_SEARCH_RESULT_FLAG_QUEUE_SYNC' is also set, search result additions |
|
97 |
and removals are also tracked and can be retrieved with |
|
98 |
'mailbox_search_result_sync()', i.e. with this you can implement "what changed |
|
99 |
in search results since last time I checked". |
|
100 |
||
1.16.1
by Jaldhar H. Vyas
Import upstream version 2.2.9 |
101 |
(This file was created from the wiki on 2013-11-24 04:42) |