Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / 01 / bdb16594f6b01c74c999198b7edc00af539c78
1 Return-Path: <aclements@csail.mit.edu>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id 20DEF431FB6\r
6         for <notmuch@notmuchmail.org>; Tue, 21 Oct 2014 18:49:22 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -2.3\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-2.3 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_MED=-2.3] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id pjKGcSE-sYOv for <notmuch@notmuchmail.org>;\r
16         Tue, 21 Oct 2014 18:49:14 -0700 (PDT)\r
17 Received: from outgoing.csail.mit.edu (outgoing.csail.mit.edu [128.30.2.149])\r
18         by olra.theworths.org (Postfix) with ESMTP id 6733A431FAE\r
19         for <notmuch@notmuchmail.org>; Tue, 21 Oct 2014 18:49:14 -0700 (PDT)\r
20 Received: from [104.131.20.129] (helo=awakeningjr)\r
21         by outgoing.csail.mit.edu with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16)\r
22         (Exim 4.72) (envelope-from <aclements@csail.mit.edu>)\r
23         id 1Xgl33-0005Gj-S9; Tue, 21 Oct 2014 21:49:13 -0400\r
24 Received: from amthrax by awakeningjr with local (Exim 4.84)\r
25         (envelope-from <aclements@csail.mit.edu>)\r
26         id 1Xgl33-0000Ge-JH; Tue, 21 Oct 2014 21:49:13 -0400\r
27 Date: Tue, 21 Oct 2014 21:49:13 -0400\r
28 From: Austin Clements <aclements@csail.mit.edu>\r
29 To: Mark Walters <markwalters1009@gmail.com>\r
30 Subject: Re: [PATCH v2 08/12] lib: Implement ghost-based thread linking\r
31 Message-ID: <20141022014913.GE7970@csail.mit.edu>\r
32 References: <1412637438-4821-1-git-send-email-aclements@csail.mit.edu>\r
33         <1412637438-4821-9-git-send-email-aclements@csail.mit.edu>\r
34         <87zjcphvdu.fsf@qmul.ac.uk>\r
35 MIME-Version: 1.0\r
36 Content-Type: text/plain; charset=us-ascii\r
37 Content-Disposition: inline\r
38 In-Reply-To: <87zjcphvdu.fsf@qmul.ac.uk>\r
39 User-Agent: Mutt/1.5.23 (2014-03-12)\r
40 Cc: notmuch@notmuchmail.org\r
41 X-BeenThere: notmuch@notmuchmail.org\r
42 X-Mailman-Version: 2.1.13\r
43 Precedence: list\r
44 List-Id: "Use and development of the notmuch mail system."\r
45         <notmuch.notmuchmail.org>\r
46 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
47         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
48 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
49 List-Post: <mailto:notmuch@notmuchmail.org>\r
50 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
51 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
52         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
53 X-List-Received-Date: Wed, 22 Oct 2014 01:49:22 -0000\r
54 \r
55 Quoth Mark Walters on Oct 22 at 12:10 am:\r
56 > On Tue, 07 Oct 2014, Austin Clements <aclements@csail.mit.edu> wrote:\r
57 > > From: Austin Clements <amdragon@mit.edu>\r
58 > >\r
59 > > This updates the thread linking code to use ghost messages instead of\r
60 > > user metadata to link messages into threads.\r
61 > >\r
62 > > In contrast with the old approach, this is actually correct.\r
63 > > Previously, thread merging updated only the thread IDs of message\r
64 > > documents, not thread IDs stored in user metadata.  As originally\r
65 > > diagnosed by Mark Walters [1] and as demonstrated by the broken\r
66 > > T260-thread-order test, this can cause notmuch to fail to link\r
67 > > messages even though they're in the same thread.  In principle the old\r
68 > > approach could have been fixed by updating the user metadata thread\r
69 > > IDs as well, but these are not indexed and hence this would have\r
70 > > required a full scan of all stored thread IDs.  Ghost messages solve\r
71 > > this problem naturally by reusing the exact same thread ID and message\r
72 > > ID representation and indexing as regular messages.\r
73 > >\r
74 > > Furthermore, thanks to this greater symmetry, ghost messages are also\r
75 > > algorithmically simpler.  We continue to support the old user metadata\r
76 > > format, so this patch can't delete any code, but when we do remove\r
77 > > support for the old format, several functions can simply be deleted.\r
78 > >\r
79 > > [1] id:8738h7kv2q.fsf@qmul.ac.uk\r
80 > > ---\r
81 > >  lib/database.cc | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--------\r
82 > >  1 file changed, 75 insertions(+), 11 deletions(-)\r
83 > >\r
84 > > diff --git a/lib/database.cc b/lib/database.cc\r
85 > > index c641bcd..fdcc526 100644\r
86 > > --- a/lib/database.cc\r
87 > > +++ b/lib/database.cc\r
88 > > @@ -1752,6 +1752,12 @@ _get_metadata_thread_id_key (void *ctx, const char *message_id)\r
89 > >                         message_id);\r
90 > >  }\r
91 > >  \r
92 > > +static notmuch_status_t\r
93 > > +_resolve_message_id_to_thread_id_old (notmuch_database_t *notmuch,\r
94 > > +                                 void *ctx,\r
95 > > +                                 const char *message_id,\r
96 > > +                                 const char **thread_id_ret);\r
97 > > +\r
98 > >  /* Find the thread ID to which the message with 'message_id' belongs.\r
99 > >   *\r
100 > >   * Note: 'thread_id_ret' must not be NULL!\r
101 > > @@ -1760,9 +1766,9 @@ _get_metadata_thread_id_key (void *ctx, const char *message_id)\r
102 > >   *\r
103 > >   * Note: If there is no message in the database with the given\r
104 > >   * 'message_id' then a new thread_id will be allocated for this\r
105 > > - * message and stored in the database metadata, (where this same\r
106 > > + * message ID and stored in the database metadata so that the\r
107 > >   * thread ID can be looked up if the message is added to the database\r
108 > > - * later).\r
109 > > + * later.\r
110 > >   */\r
111 > >  static notmuch_status_t\r
112 > >  _resolve_message_id_to_thread_id (notmuch_database_t *notmuch,\r
113 > > @@ -1770,6 +1776,49 @@ _resolve_message_id_to_thread_id (notmuch_database_t *notmuch,\r
114 > >                               const char *message_id,\r
115 > >                               const char **thread_id_ret)\r
116 > >  {\r
117 > > +    notmuch_private_status_t status;\r
118 > > +    notmuch_message_t *message;\r
119 > > +\r
120 > > +    if (! (notmuch->features & NOTMUCH_FEATURE_GHOSTS))\r
121 > > +   return _resolve_message_id_to_thread_id_old (notmuch, ctx, message_id,\r
122 > > +                                                thread_id_ret);\r
123 > > +\r
124 > > +    /* Look for this message (regular or ghost) */\r
125 > > +    message = _notmuch_message_create_for_message_id (\r
126 > > +   notmuch, message_id, &status);\r
127 > > +    if (status == NOTMUCH_PRIVATE_STATUS_SUCCESS) {\r
128 > > +   /* Message exists */\r
129 > > +   *thread_id_ret = talloc_steal (\r
130 > > +       ctx, notmuch_message_get_thread_id (message));\r
131 > > +    } else if (status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {\r
132 > > +   /* Message did not exist.  Give it a fresh thread ID and\r
133 > > +    * populate this message as a ghost message. */\r
134 > > +   *thread_id_ret = talloc_strdup (\r
135 > > +       ctx, _notmuch_database_generate_thread_id (notmuch));\r
136 > > +   if (! *thread_id_ret) {\r
137 > > +       status = NOTMUCH_PRIVATE_STATUS_OUT_OF_MEMORY;\r
138 > > +   } else {\r
139 > > +       status = _notmuch_message_initialize_ghost (message, *thread_id_ret);\r
140 > > +       if (status == 0)\r
141 > > +           /* Commit the new ghost message */\r
142 > > +           _notmuch_message_sync (message);\r
143 > > +   }\r
144 > > +    } else {\r
145 > > +   /* Create failed. Fall through. */\r
146 > > +    }\r
147 > > +\r
148 > > +    notmuch_message_destroy (message);\r
149 > > +\r
150 > > +    return COERCE_STATUS (status, "Error creating ghost message");\r
151 > > +}\r
152 > > +\r
153 > > +/* Pre-ghost messages _resolve_message_id_to_thread_id */\r
154 > > +static notmuch_status_t\r
155 > > +_resolve_message_id_to_thread_id_old (notmuch_database_t *notmuch,\r
156 > > +                                 void *ctx,\r
157 > > +                                 const char *message_id,\r
158 > > +                                 const char **thread_id_ret)\r
159 > > +{\r
160 > >      notmuch_status_t status;\r
161 > >      notmuch_message_t *message;\r
162 > >      string thread_id_string;\r
163 > > @@ -2007,7 +2056,7 @@ _consume_metadata_thread_id (void *ctx, notmuch_database_t *notmuch,\r
164 > >      }\r
165 > >  }\r
166 > >  \r
167 > > -/* Given a (mostly empty) 'message' and its corresponding\r
168 > > +/* Given a blank or ghost 'message' and its corresponding\r
169 > >   * 'message_file' link it to existing threads in the database.\r
170 > >   *\r
171 > >   * The first check is in the metadata of the database to see if we\r
172\r
173 > There is quite a lot of comment below this and it is not clear to me how\r
174 > much of it applies to the is_ghost case. In particular does the \r
175\r
176 >   * Finally, we look in the database for existing message that\r
177 >   * reference 'message'.\r
178\r
179 > still apply? I would have thought that we would already have done that\r
180 > in the is_ghost case. \r
181 \r
182 Good point.  The comment isn't really wrong, but it isn't right\r
183 either.  How about\r
184 \r
185 diff --git a/lib/database.cc b/lib/database.cc\r
186 index 6e51a72..d063ec8 100644\r
187 --- a/lib/database.cc\r
188 +++ b/lib/database.cc\r
189 @@ -2121,10 +2121,13 @@ _consume_metadata_thread_id (void *ctx, notmuch_database_t *notmuch,\r
190  /* Given a blank or ghost 'message' and its corresponding\r
191   * 'message_file' link it to existing threads in the database.\r
192   *\r
193 - * The first check is in the metadata of the database to see if we\r
194 - * have pre-allocated a thread_id in advance for this message, (which\r
195 - * would have happened if a message was previously added that\r
196 - * referenced this one).\r
197 + * First, if is_ghost, this retrieves the thread ID already stored in\r
198 + * the message (which will be the case if a message was previously\r
199 + * added that referenced this one).  If the message is blank\r
200 + * (!is_ghost), it doesn't have a thread ID yet (we'll generate one\r
201 + * later in this function).  If the database does not support ghost\r
202 + * messages, this checks for a thread ID stored in database metadata\r
203 + * for this message ID.\r
204   *\r
205   * Second, we look at 'message_file' and its link-relevant headers\r
206   * (References and In-Reply-To) for message IDs.\r
207 @@ -2132,7 +2135,7 @@ _consume_metadata_thread_id (void *ctx, notmuch_database_t *notmuch,\r
208   * Finally, we look in the database for existing message that\r
209   * reference 'message'.\r
210   *\r
211 - * In all cases, we assign to the current message the first thread_id\r
212 + * In all cases, we assign to the current message the first thread ID\r
213   * found (through either parent or child). We will also merge any\r
214   * existing, distinct threads where this message belongs to both,\r
215   * (which is not uncommon when messages are processed out of order).\r
216 \r
217 ?\r
218 \r
219 > Of course this also applies to the actual code which seems to call\r
220 > _notmuch_database_link_message_to_children unconditionally. It might be\r
221 > worth a comment in any case.\r
222\r
223 > Best wishes\r
224\r
225 > Mark\r
226\r
227\r
228 > > @@ -2035,16 +2084,22 @@ _consume_metadata_thread_id (void *ctx, notmuch_database_t *notmuch,\r
229 > >  static notmuch_status_t\r
230 > >  _notmuch_database_link_message (notmuch_database_t *notmuch,\r
231 > >                             notmuch_message_t *message,\r
232 > > -                           notmuch_message_file_t *message_file)\r
233 > > +                           notmuch_message_file_t *message_file,\r
234 > > +                           notmuch_bool_t is_ghost)\r
235 > >  {\r
236 > >      void *local = talloc_new (NULL);\r
237 > >      notmuch_status_t status;\r
238 > > -    const char *thread_id;\r
239 > > +    const char *thread_id = NULL;\r
240 > >  \r
241 > >      /* Check if the message already had a thread ID */\r
242 > > -    thread_id = _consume_metadata_thread_id (local, notmuch, message);\r
243 > > -    if (thread_id)\r
244 > > -   _notmuch_message_add_term (message, "thread", thread_id);\r
245 > > +    if (notmuch->features & NOTMUCH_FEATURE_GHOSTS) {\r
246 > > +   if (is_ghost)\r
247 > > +       thread_id = notmuch_message_get_thread_id (message);\r
248 > > +    } else {\r
249 > > +   thread_id = _consume_metadata_thread_id (local, notmuch, message);\r
250 > > +   if (thread_id)\r
251 > > +       _notmuch_message_add_term (message, "thread", thread_id);\r
252 > > +    }\r
253 > >  \r
254 > >      status = _notmuch_database_link_message_to_parents (notmuch, message,\r
255 > >                                                     message_file,\r
256 > > @@ -2079,6 +2134,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
257 > >      notmuch_message_t *message = NULL;\r
258 > >      notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS, ret2;\r
259 > >      notmuch_private_status_t private_status;\r
260 > > +    notmuch_bool_t is_ghost = false;\r
261 > >  \r
262 > >      const char *date, *header;\r
263 > >      const char *from, *to, *subject;\r
264 > > @@ -2171,12 +2227,20 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
265 > >  \r
266 > >     _notmuch_message_add_filename (message, filename);\r
267 > >  \r
268 > > -   /* Is this a newly created message object? */\r
269 > > -   if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {\r
270 > > +   /* Is this a newly created message object or a ghost\r
271 > > +    * message?  We have to be slightly careful: if this is a\r
272 > > +    * blank message, it's not safe to call\r
273 > > +    * notmuch_message_get_flag yet. */\r
274 > > +   if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND ||\r
275 > > +       (is_ghost = notmuch_message_get_flag (\r
276 > > +           message, NOTMUCH_MESSAGE_FLAG_GHOST))) {\r
277 > >         _notmuch_message_add_term (message, "type", "mail");\r
278 > > +       if (is_ghost)\r
279 > > +           /* Convert ghost message to a regular message */\r
280 > > +           _notmuch_message_remove_term (message, "type", "ghost");\r
281 > >  \r
282 > >         ret = _notmuch_database_link_message (notmuch, message,\r
283 > > -                                             message_file);\r
284 > > +                                             message_file, is_ghost);\r
285 > >         if (ret)\r
286 > >             goto DONE;\r
287 > >  \r
288 > >\r
289 > > _______________________________________________\r
290 > > notmuch mailing list\r
291 > > notmuch@notmuchmail.org\r
292 > > http://notmuchmail.org/mailman/listinfo/notmuch\r