Re: notmuch-mutt: Use of uninitialized value.
[notmuch-archives.git] / b7 / edf951c27d141015c04bb407d04034635493ef
1 Return-Path: <amthrax@drake.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 28D41429E4A\r
6         for <notmuch@notmuchmail.org>; Thu, 17 Feb 2011 23:59:38 -0800 (PST)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: 0\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=0 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_NONE=-0.0001] 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 ZT6zN79RrO8j for <notmuch@notmuchmail.org>;\r
16         Thu, 17 Feb 2011 23:59:36 -0800 (PST)\r
17 Received: from dmz-mailsec-scanner-7.mit.edu (DMZ-MAILSEC-SCANNER-7.MIT.EDU\r
18         [18.7.68.36])\r
19         by olra.theworths.org (Postfix) with ESMTP id 33F61429E38\r
20         for <notmuch@notmuchmail.org>; Thu, 17 Feb 2011 23:59:29 -0800 (PST)\r
21 X-AuditID: 12074424-b7b0bae000000a05-6d-4d5e26e04bad\r
22 Received: from mailhub-auth-3.mit.edu ( [18.9.21.43])\r
23         by dmz-mailsec-scanner-7.mit.edu (Symantec Brightmail Gateway) with\r
24         SMTP id 8D.70.02565.0E62E5D4; Fri, 18 Feb 2011 02:59:28 -0500 (EST)\r
25 Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103])\r
26         by mailhub-auth-3.mit.edu (8.13.8/8.9.2) with ESMTP id p1I7xRwj029792; \r
27         Fri, 18 Feb 2011 02:59:27 -0500\r
28 Received: from drake.mit.edu\r
29         (209-6-116-242.c3-0.arl-ubr1.sbo-arl.ma.cable.rcn.com\r
30         [209.6.116.242]) (authenticated bits=0)\r
31         (User authenticated as amdragon@ATHENA.MIT.EDU)\r
32         by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id p1I7xQp1001544\r
33         (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
34         Fri, 18 Feb 2011 02:59:27 -0500 (EST)\r
35 Received: from amthrax by drake.mit.edu with local (Exim 4.72)\r
36         (envelope-from <amthrax@drake.mit.edu>)\r
37         id 1PqLFO-0008LK-Jg; Fri, 18 Feb 2011 02:59:26 -0500\r
38 From: Austin Clements <amdragon@MIT.EDU>\r
39 To: notmuch@notmuchmail.org\r
40 Subject: [PATCH 06/10] lib: Add API's to find by filename and remove a\r
41         filename from a message.\r
42 Date: Fri, 18 Feb 2011 02:58:56 -0500\r
43 Message-Id: <1298015940-31986-7-git-send-email-amdragon@mit.edu>\r
44 X-Mailer: git-send-email 1.7.2.3\r
45 In-Reply-To: <1298015940-31986-1-git-send-email-amdragon@mit.edu>\r
46 References: <1298015940-31986-1-git-send-email-amdragon@mit.edu>\r
47 X-Brightmail-Tracker: AAAAAA==\r
48 Cc: amdragon@mit.edu\r
49 X-BeenThere: notmuch@notmuchmail.org\r
50 X-Mailman-Version: 2.1.13\r
51 Precedence: list\r
52 List-Id: "Use and development of the notmuch mail system."\r
53         <notmuch.notmuchmail.org>\r
54 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
55         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
56 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
57 List-Post: <mailto:notmuch@notmuchmail.org>\r
58 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
59 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
60         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
61 X-List-Received-Date: Fri, 18 Feb 2011 07:59:38 -0000\r
62 \r
63 The two new API functions, notmuch_database_find_message_by_filename\r
64 and notmuch_message_remove_filename give library users more control\r
65 over the filename removal process.  notmuch_database_remove_message\r
66 has been reimplemented in terms of these new functions.\r
67 \r
68 notmuch_message_remove_filename acts much like\r
69 notmuch_message_remove_tag in that it does not synchronize with the\r
70 database if the message is frozen.  Thus, callers can freeze a message\r
71 to remove a filename and perform tag synchronization in one atomic\r
72 operation.\r
73 \r
74 This new approach also naturally eliminates an atomicity violation in\r
75 the old code.  Previously, notmuch_database_remove_message would first\r
76 update the database document to remove the filename and only then\r
77 remove the document if it had no more filenames left.  An interruption\r
78 between these two steps resulted in a permanently un-removable zombie\r
79 message that would produce errors and odd results in searches.  Since\r
80 this new approach delegates document deletion to\r
81 _notmuch_message_sync, the document will be deleted without first\r
82 being updated, eliminating this window.\r
83 ---\r
84  lib/database.cc |   58 +++++++++++++++++++-----------------------------------\r
85  lib/message.cc  |   21 +++++++++++++++++++\r
86  lib/notmuch.h   |   43 ++++++++++++++++++++++++++++++++++++++-\r
87  3 files changed, 83 insertions(+), 39 deletions(-)\r
88 \r
89 diff --git a/lib/database.cc b/lib/database.cc\r
90 index d88b168..bee1e96 100644\r
91 --- a/lib/database.cc\r
92 +++ b/lib/database.cc\r
93 @@ -1689,72 +1689,56 @@ notmuch_status_t\r
94  notmuch_database_remove_message (notmuch_database_t *notmuch,\r
95                                  const char *filename)\r
96  {\r
97 -    Xapian::WritableDatabase *db;\r
98 +    notmuch_message_t *message;\r
99 +    notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;\r
100 +    message = notmuch_database_find_message_by_filename (notmuch, filename);\r
101 +    if (message) {\r
102 +       status = notmuch_message_remove_filename (message, filename);\r
103 +       notmuch_message_destroy (message);\r
104 +    }\r
105 +    return status;\r
106 +}\r
107 +\r
108 +notmuch_message_t *\r
109 +notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,\r
110 +                                          const char *filename)\r
111 +{\r
112      void *local;\r
113      const char *prefix = _find_prefix ("file-direntry");\r
114      char *direntry, *term;\r
115      Xapian::PostingIterator i, end;\r
116 -    Xapian::Document document;\r
117 +    notmuch_message_t *message = NULL;\r
118      notmuch_status_t status;\r
119  \r
120 -    status = _notmuch_database_ensure_writable (notmuch);\r
121 -    if (status)\r
122 -       return status;\r
123 -\r
124      local = talloc_new (notmuch);\r
125  \r
126 -    db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);\r
127 -\r
128      try {\r
129  \r
130         status = _notmuch_database_filename_to_direntry (local, notmuch,\r
131                                                          filename, &direntry);\r
132         if (status)\r
133 -           return status;\r
134 +           return NULL;\r
135  \r
136         term = talloc_asprintf (local, "%s%s", prefix, direntry);\r
137  \r
138         find_doc_ids_for_term (notmuch, term, &i, &end);\r
139  \r
140 -       for ( ; i != end; i++) {\r
141 -           Xapian::TermIterator j;\r
142 -           notmuch_message_t *message;\r
143 +       if (i != end) {\r
144             notmuch_private_status_t private_status;\r
145  \r
146 -           message = _notmuch_message_create (local, notmuch,\r
147 +           message = _notmuch_message_create (notmuch, notmuch,\r
148                                                *i, &private_status);\r
149 -           if (message == NULL)\r
150 -               return COERCE_STATUS (private_status,\r
151 -                                     "Inconsistent document ID in datbase.");\r
152 -\r
153 -           _notmuch_message_remove_filename (message, filename);\r
154 -           _notmuch_message_sync (message);\r
155 -\r
156 -           /* Take care to find document after sync'ing filename removal. */\r
157 -           document = find_document_for_doc_id (notmuch, *i);\r
158 -           j = document.termlist_begin ();\r
159 -           j.skip_to (prefix);\r
160 -\r
161 -           /* Was this the last file-direntry in the message? */\r
162 -           if (j == document.termlist_end () ||\r
163 -               strncmp ((*j).c_str (), prefix, strlen (prefix)))\r
164 -           {\r
165 -               db->delete_document (document.get_docid ());\r
166 -               status = NOTMUCH_STATUS_SUCCESS;\r
167 -           } else {\r
168 -               status = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;\r
169 -           }\r
170         }\r
171      } catch (const Xapian::Error &error) {\r
172 -       fprintf (stderr, "Error: A Xapian exception occurred removing message: %s\n",\r
173 +       fprintf (stderr, "Error: A Xapian exception occurred finding message by filename: %s\n",\r
174                  error.get_msg().c_str());\r
175         notmuch->exception_reported = TRUE;\r
176 -       status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;\r
177 +       message = NULL;\r
178      }\r
179  \r
180      talloc_free (local);\r
181  \r
182 -    return status;\r
183 +    return message;\r
184  }\r
185  \r
186  notmuch_tags_t *\r
187 diff --git a/lib/message.cc b/lib/message.cc\r
188 index 635f5cf..b4adb5c 100644\r
189 --- a/lib/message.cc\r
190 +++ b/lib/message.cc\r
191 @@ -1300,6 +1300,27 @@ notmuch_message_remove_all_tags (notmuch_message_t *message)\r
192  }\r
193  \r
194  notmuch_status_t\r
195 +notmuch_message_remove_filename (notmuch_message_t *message,\r
196 +                                const char *filename)\r
197 +{\r
198 +    notmuch_status_t status;\r
199 +\r
200 +    status = _notmuch_database_ensure_writable (message->notmuch);\r
201 +    if (status)\r
202 +       return status;\r
203 +\r
204 +    status = _notmuch_message_remove_filename (message, filename);\r
205 +    /* Was this the last file-direntry in the message? */\r
206 +    if (status == NOTMUCH_STATUS_SUCCESS)\r
207 +       message->deleted = TRUE;\r
208 +\r
209 +    if (! message->frozen)\r
210 +       _notmuch_message_sync (message);\r
211 +\r
212 +    return status;\r
213 +}\r
214 +\r
215 +notmuch_status_t\r
216  notmuch_message_freeze (notmuch_message_t *message)\r
217  {\r
218      notmuch_status_t status;\r
219 diff --git a/lib/notmuch.h b/lib/notmuch.h\r
220 index e508309..61030cb 100644\r
221 --- a/lib/notmuch.h\r
222 +++ b/lib/notmuch.h\r
223 @@ -316,6 +316,22 @@ notmuch_message_t *\r
224  notmuch_database_find_message (notmuch_database_t *database,\r
225                                const char *message_id);\r
226  \r
227 +/* Find a message with the given filename.\r
228 + *\r
229 + * If the database contains a message with the given filename, then a\r
230 + * new notmuch_message_t object is returned.  The caller should call \r
231 + * notmuch_message_destroy when done with the message.\r
232 + *\r
233 + * This function returns NULL in the following situations:\r
234 + *\r
235 + *     * No message is found with the given filename\r
236 + *     * An out-of-memory situation occurs\r
237 + *     * A Xapian exception occurs\r
238 + */\r
239 +notmuch_message_t *\r
240 +notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,\r
241 +                                          const char *filename);\r
242 +\r
243  /* Return a list of all tags found in the database.\r
244   *\r
245   * This function creates a list of all tags found in the database. The\r
246 @@ -979,11 +995,34 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message);\r
247  notmuch_status_t\r
248  notmuch_message_tags_to_maildir_flags (notmuch_message_t *message);\r
249  \r
250 +/* Remove a filename from a message.  If this is the last copy of this\r
251 + * message, also delete it from the database.\r
252 + *\r
253 + * Much like notmuch_message_remove_tag, if message is frozen, it will\r
254 + * not be removed from or updated in the database until thawed.\r
255 + *\r
256 + * Return value:\r
257 + *\r
258 + * NOTMUCH_STATUS_SUCCESS: The last filename was removed and the\r
259 + *     message was removed from the database.\r
260 + *\r
261 + * NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: This filename was removed but\r
262 + *     the message persists in the database with at least one other\r
263 + *     filename.\r
264 + *\r
265 + * NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only\r
266 + *     mode so no message can be removed.\r
267 + */\r
268 +notmuch_status_t\r
269 +notmuch_message_remove_filename (notmuch_message_t *message,\r
270 +                                const char *filename);\r
271 +\r
272  /* Freeze the current state of 'message' within the database.\r
273   *\r
274   * This means that changes to the message state, (via\r
275 - * notmuch_message_add_tag, notmuch_message_remove_tag, and\r
276 - * notmuch_message_remove_all_tags), will not be committed to the\r
277 + * notmuch_message_add_tag, notmuch_message_remove_tag,\r
278 + * notmuch_message_remove_all_tags, and\r
279 + * notmuch_message_remove_filename), will not be committed to the\r
280   * database until the message is thawed with notmuch_message_thaw.\r
281   *\r
282   * Multiple calls to freeze/thaw are valid and these calls will\r
283 -- \r
284 1.7.2.3\r
285 \r