Re: [PATCH] emacs: poll: return useful errors when poll fails.
[notmuch-archives.git] / 48 / bc7c21b34b82a36f767d4dffe4eeedc37c1983
1 Return-Path: <schnouki@schnouki.net>\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 F405E429E25\r
6         for <notmuch@notmuchmail.org>; Tue, 20 Dec 2011 17:00:56 -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.1\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.1 tagged_above=-999 required=5\r
12         tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1]\r
13         autolearn=disabled\r
14 Received: from olra.theworths.org ([127.0.0.1])\r
15         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
16         with ESMTP id pQGlbAVjCLTH for <notmuch@notmuchmail.org>;\r
17         Tue, 20 Dec 2011 17:00:55 -0800 (PST)\r
18 Received: from ks3536.kimsufi.com (schnouki.net [87.98.217.222])\r
19         by olra.theworths.org (Postfix) with ESMTP id B3647431FB6\r
20         for <notmuch@notmuchmail.org>; Tue, 20 Dec 2011 17:00:55 -0800 (PST)\r
21 Received: from odin.local (nancy.schnouki.net [78.238.0.45])\r
22         by ks3536.kimsufi.com (Postfix) with ESMTPSA id 650566A0026;\r
23         Wed, 21 Dec 2011 02:00:54 +0100 (CET)\r
24 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=schnouki.net;\r
25         s=key-schnouki; t=1324429254;\r
26         bh=ehG+Gitxjap0IVnzIv/mX02SMfPgOZYy+gPVqA3o9IU=;\r
27         h=From:To:Cc:Subject:In-Reply-To:References:Date:Message-ID:\r
28         MIME-Version:Content-Type;\r
29         b=eUHEzu+kZbqwwtZqrgQfP7XyaUf8Tg+oEkW9Awij7E7x3DWw+UNUPKruayxb5u+7g\r
30         hfwjNBtbzFv0BhgGnJG5N73PDCPClUfURYQHErfq8lrDtFCQz949KEz50TH7rFuL78\r
31         RN8WRpYMXt0XW7x3vfxodiu09+7BSwzzxMKNz9PQ=\r
32 From: Thomas Jost <schnouki@schnouki.net>\r
33 To: Austin Clements <amdragon@MIT.EDU>\r
34 Subject: Re: [PATCH 2/5] lib: Add a MTIME value to every mail document\r
35 In-Reply-To: <20111215004507.GF2760@mit.edu>\r
36 References: <1323796305-28789-1-git-send-email-schnouki@schnouki.net>\r
37         <1323796305-28789-3-git-send-email-schnouki@schnouki.net>\r
38         <20111215004507.GF2760@mit.edu>\r
39 User-Agent: Notmuch/0.10.2+122~g1d81c5e (http://notmuchmail.org)\r
40         Emacs/24.0.92.1 (x86_64-unknown-linux-gnu)\r
41 Date: Wed, 21 Dec 2011 02:00:53 +0100\r
42 Message-ID: <878vm6agca.fsf@schnouki.net>\r
43 MIME-Version: 1.0\r
44 Content-Type: multipart/signed; boundary="=-=-=";\r
45         micalg=pgp-sha1; protocol="application/pgp-signature"\r
46 Cc: notmuch@notmuchmail.org\r
47 X-BeenThere: notmuch@notmuchmail.org\r
48 X-Mailman-Version: 2.1.13\r
49 Precedence: list\r
50 List-Id: "Use and development of the notmuch mail system."\r
51         <notmuch.notmuchmail.org>\r
52 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
53         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
54 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
55 List-Post: <mailto:notmuch@notmuchmail.org>\r
56 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
57 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
58         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
59 X-List-Received-Date: Wed, 21 Dec 2011 01:00:57 -0000\r
60 \r
61 --=-=-=\r
62 Content-Type: text/plain\r
63 Content-Transfer-Encoding: quoted-printable\r
64 \r
65 On Wed, 14 Dec 2011 19:45:07 -0500, Austin Clements <amdragon@MIT.EDU> wrot=\r
66 e:\r
67 > A few minor comments below.\r
68 >=20\r
69 > At a higher level, I'm curious what the tag synchronization protocol\r
70 > you're building on top of this is.  I can't think of one that doesn't\r
71 > have race conditions, but maybe I'm not thinking about it right.\r
72 \r
73 The approach I've used is quite different from what you described in\r
74 id:"20111219194821.GA10376@mit.edu". I don't directly sync host A to\r
75 host B but I use a server in the middle. (A is my laptop --> not always\r
76 on, B is my work PC --> turned off when I'm out of office, so a direct\r
77 sync would be harder to do).\r
78 \r
79 My nm-sync script is written in Python 2 (2.7, may work with 2.6) and is\r
80 present on both my PCs and on my server. It can operate in two modes :\r
81 client (when run from one of my PCs) or server (called *from the client*\r
82 through ssh, running on my server).\r
83 \r
84 When running in server mode, the script manipulates a small DB stored as\r
85 a Python dictionary (and stored on disk with the pickle module). It does\r
86 not even need notmuch to be installed on the server. Here is what this\r
87 DB looks like:\r
88   {\r
89     "lastseen": {\r
90       "pc_A": 1324428029,\r
91       "pc_B": 1323952028\r
92     },\r
93     "messages": {\r
94       "msgid_001": (mtime, tag1, tag2, ..., tagN),\r
95       "msgid_002": (mtime, tag1, tag2, ..., tagM),\r
96       ...\r
97     }\r
98   }\r
99 \r
100 So when running the client, here is what happens:\r
101 1. client starts a subprocess: "ssh myserver ~/nm-sync server"\r
102 2. client and server check that their sha1sum match (to avoid version\r
103    mismatch)\r
104 3. client identifies itself with its hostname ("pc_A" in the example\r
105    above), server replies with its "lastseen" value and updates its in\r
106    the DB\r
107 4. server sends to client messages with mtime > lastseen (msgid + mtime\r
108    + tags), client updates the notmuch DB with these values\r
109 5. client queries the notmuch DB for messages with mtime > lastseen and\r
110    sends them (msgid + mtime + tags) to the server, which stores them in\r
111    the DB\r
112 6. cleanup: server removes messages with mtime < min(lastseen) from its\r
113    DB\r
114 \r
115 So basically this approach assumes that all clocks are synchronized\r
116 (everyone uses ntp, right?...) and does not even try to detect\r
117 conflicts: if a message has been modified both locally and remotely,\r
118 then the local version will be overwritten by the remote one, period. It\r
119 should also work with more than 2 hosts (but not tested yet). No sync\r
120 data is kept in the notmuch DB.\r
121 \r
122 Right now all of this fits in about 250 lines of Python (could be made\r
123 shorter) and works quite well for me. I'll put it online after doing\r
124 some cleanup.\r
125 \r
126 \r
127 > Quoth Thomas Jost on Dec 13 at  6:11 pm:\r
128 > > This is a time_t value, similar to the message date (TIMESTAMP). It is =\r
129 first set\r
130 > > when the message is added to the database, and is then updated every ti=\r
131 me a tag\r
132 > > is added or removed. It can thus be used for doing incremental dumps of=\r
133  the\r
134 > > database or for synchronizing it between several computers.\r
135 > >=20\r
136 > > This value can be read freely (with notmuch_message_get_mtime()) but fo=\r
137 r now it\r
138 > > can't be set to an arbitrary value: it can only be set to "now" when up=\r
139 dated.\r
140 > > There's no specific reason for this except that I don't really see a re=\r
141 al use\r
142 > > case for setting it to an arbitrary value.\r
143 > > ---\r
144 > >  lib/database.cc       |    7 ++++++-\r
145 > >  lib/message.cc        |   32 ++++++++++++++++++++++++++++++++\r
146 > >  lib/notmuch-private.h |    6 +++++-\r
147 > >  lib/notmuch.h         |    4 ++++\r
148 > >  4 files changed, 47 insertions(+), 2 deletions(-)\r
149 > >=20\r
150 > > diff --git a/lib/database.cc b/lib/database.cc\r
151 > > index 2025189..6dc6f73 100644\r
152 > > --- a/lib/database.cc\r
153 > > +++ b/lib/database.cc\r
154 > > @@ -81,7 +81,7 @@ typedef struct {\r
155 > >   *                 STRING is the name of a file within that\r
156 > >   *                 directory for this mail message.\r
157 > >   *\r
158 > > - *    A mail document also has four values:\r
159 > > + *    A mail document also has five values:\r
160 > >   *\r
161 > >   * TIMESTAMP:      The time_t value corresponding to the message's\r
162 > >   *                 Date header.\r
163 > > @@ -92,6 +92,9 @@ typedef struct {\r
164 > >   *\r
165 > >   * SUBJECT:        The value of the "Subject" header\r
166 > >   *\r
167 > > + * MTIME:          The time_t value corresponding to the last time\r
168 > > + *                 a tag was added or removed on the message.\r
169 > > + *\r
170 > >   * In addition, terms from the content of the message are added with\r
171 > >   * "from", "to", "attachment", and "subject" prefixes for use by the\r
172 > >   * user in searching. Similarly, terms from the path of the mail\r
173 > > @@ -1735,6 +1738,8 @@ notmuch_database_add_message (notmuch_database_t =\r
174 *notmuch,\r
175 > >         date =3D notmuch_message_file_get_header (message_file, "date");\r
176 > >         _notmuch_message_set_header_values (message, date, from, subject);\r
177 > >=20=20\r
178 > > +            _notmuch_message_update_mtime (message);\r
179 >=20\r
180 > Indentation.\r
181 \r
182 Fixed, thanks.\r
183 \r
184 >=20\r
185 > > +\r
186 > >         _notmuch_message_index_file (message, filename);\r
187 > >     } else {\r
188 > >         ret =3D NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;\r
189 > > diff --git a/lib/message.cc b/lib/message.cc\r
190 > > index 0075425..0c98589 100644\r
191 > > --- a/lib/message.cc\r
192 > > +++ b/lib/message.cc\r
193 > > @@ -830,6 +830,34 @@ _notmuch_message_set_header_values (notmuch_messag=\r
194 e_t *message,\r
195 > >      message->doc.add_value (NOTMUCH_VALUE_SUBJECT, subject);\r
196 > >  }\r
197 > >=20=20\r
198 > > +/* Get the message mtime, i.e. when it was added or the last time a ta=\r
199 g was\r
200 > > + * added/removed. */\r
201 > > +time_t\r
202 > > +notmuch_message_get_mtime (notmuch_message_t *message)\r
203 > > +{\r
204 > > +    std::string value;\r
205 > > +\r
206 > > +    try {\r
207 > > +   value =3D message->doc.get_value (NOTMUCH_VALUE_MTIME);\r
208 > > +    } catch (Xapian::Error &error) {\r
209 > > +   INTERNAL_ERROR ("Failed to read mtime value from document.");\r
210 > > +   return 0;\r
211 > > +    }\r
212 >=20\r
213 > For compatibility, this should handle the case when\r
214 > NOTMUCH_VALUE_MTIME is missing, probably by just returning 0.  As it\r
215 > is, value will be an empty string and sortable_unserialise is\r
216 > undefined on strings that weren't produced by sortable_serialise.\r
217 \r
218 Right. I think I rebuilt my DB just after implementing this, which\r
219 explains why I did not notice that myself. Thanks!\r
220 \r
221 > > +\r
222 > > +    return Xapian::sortable_unserialise (value);\r
223 > > +}\r
224 > > +\r
225 > > +/* Set the message mtime to "now". */\r
226 > > +void\r
227 > > +_notmuch_message_update_mtime (notmuch_message_t *message)\r
228 > > +{\r
229 > > +    time_t time_value;\r
230 > > +\r
231 > > +    time_value =3D time (NULL);\r
232 > > +    message->doc.add_value (NOTMUCH_VALUE_MTIME,\r
233 > > +                            Xapian::sortable_serialise (time_value));\r
234 >=20\r
235 > Indentation.\r
236 \r
237 Noted too. It's really time I start using dtrt-indent.\r
238 \r
239 >=20\r
240 > > +}\r
241 > > +\r
242 > >  /* Synchronize changes made to message->doc out into the database. */\r
243 > >  void\r
244 > >  _notmuch_message_sync (notmuch_message_t *message)\r
245 > > @@ -994,6 +1022,8 @@ notmuch_message_add_tag (notmuch_message_t *messag=\r
246 e, const char *tag)\r
247 > >                     private_status);\r
248 > >      }\r
249 > >=20=20\r
250 > > +    _notmuch_message_update_mtime (message);\r
251 > > +\r
252 > >      if (! message->frozen)\r
253 > >     _notmuch_message_sync (message);\r
254 > >=20=20\r
255 > > @@ -1022,6 +1052,8 @@ notmuch_message_remove_tag (notmuch_message_t *me=\r
256 ssage, const char *tag)\r
257 > >                     private_status);\r
258 > >      }\r
259 > >=20=20\r
260 > > +    _notmuch_message_update_mtime (message);\r
261 > > +\r
262 > >      if (! message->frozen)\r
263 > >     _notmuch_message_sync (message);\r
264 > >=20=20\r
265 > > diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h\r
266 > > index 60a932f..9859872 100644\r
267 > > --- a/lib/notmuch-private.h\r
268 > > +++ b/lib/notmuch-private.h\r
269 > > @@ -95,7 +95,8 @@ typedef enum {\r
270 > >      NOTMUCH_VALUE_TIMESTAMP =3D 0,\r
271 > >      NOTMUCH_VALUE_MESSAGE_ID,\r
272 > >      NOTMUCH_VALUE_FROM,\r
273 > > -    NOTMUCH_VALUE_SUBJECT\r
274 > > +    NOTMUCH_VALUE_SUBJECT,\r
275 > > +    NOTMUCH_VALUE_MTIME\r
276 > >  } notmuch_value_t;\r
277 > >=20=20\r
278 > >  /* Xapian (with flint backend) complains if we provide a term longer\r
279 > > @@ -276,6 +277,9 @@ _notmuch_message_set_header_values (notmuch_message=\r
280 _t *message,\r
281 > >                                 const char *from,\r
282 > >                                 const char *subject);\r
283 > >  void\r
284 > > +_notmuch_message_update_mtime (notmuch_message_t *message);\r
285 > > +\r
286 > > +void\r
287 > >  _notmuch_message_sync (notmuch_message_t *message);\r
288 > >=20=20\r
289 > >  notmuch_status_t\r
290 > > diff --git a/lib/notmuch.h b/lib/notmuch.h\r
291 > > index 9f23a10..643ebce 100644\r
292 > > --- a/lib/notmuch.h\r
293 > > +++ b/lib/notmuch.h\r
294 > > @@ -910,6 +910,10 @@ notmuch_message_set_flag (notmuch_message_t *messa=\r
295 ge,\r
296 > >  time_t\r
297 > >  notmuch_message_get_date  (notmuch_message_t *message);\r
298 > >=20=20\r
299 > > +/* Get the mtime of 'message' as a time_t value. */\r
300 > > +time_t\r
301 > > +notmuch_message_get_mtime (notmuch_message_t *message);\r
302 > > +\r
303 > >  /* Get the value of the specified header from 'message'.\r
304 > >   *\r
305 > >   * The value will be read from the actual message file, not from the\r
306 \r
307 =2D-=20\r
308 Thomas/Schnouki\r
309 \r
310 --=-=-=\r
311 Content-Type: application/pgp-signature\r
312 \r
313 -----BEGIN PGP SIGNATURE-----\r
314 Version: GnuPG v1.4.11 (GNU/Linux)\r
315 \r
316 iQEcBAEBAgAGBQJO8S/FAAoJEMPdciX+bh5ILyoH/0H/94+LglcGxWTx8YN7uRfw\r
317 6IeK8fPHm+ykKVSTEYrvsREi+FvkjOeLAuoMp1kOH2g1Z7O7dCTLrsYgjJcMrlMW\r
318 b1lbZam6Vo5bd5455p9DY+SzSq2J29hRpyxp0yqM3u7Awbqi/eGWsfQXW1FUNSmg\r
319 fQ2ra3wsP6d1o3oG09sAft9nkBpajcWimfG5bMaXy32srlSQXZU1uUjxAh7NyI+a\r
320 tGiKYKE5Q9tCNmhv0EuToh7PoBNLH18RWYxtTicfp6Kcz2dtE+U3xfrSiieMu6PD\r
321 +YSyTyEqu755yqZuZPVXmajsbvsgvGWHus5Bm1KMS2882MFJ2q6PjRFcgllI1YI=\r
322 =w5vf\r
323 -----END PGP SIGNATURE-----\r
324 --=-=-=--\r