Re: v4 of DB_RETRY_LOCK patches
[notmuch-archives.git] / 99 / 8c061de710ae8d7d6073816cfe8b8774531867
1 Return-Path: <bremner@tethera.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 1C79C431FBD\r
6         for <notmuch@notmuchmail.org>; Sat, 29 Mar 2014 06:46:46 -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: 0\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]\r
12         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 hglS1tXUu2UB for <notmuch@notmuchmail.org>;\r
16         Sat, 29 Mar 2014 06:46:38 -0700 (PDT)\r
17 Received: from yantan.tethera.net (yantan.tethera.net [199.188.72.155])\r
18         (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits))\r
19         (No client certificate requested)\r
20         by olra.theworths.org (Postfix) with ESMTPS id 7AC74431FBC\r
21         for <notmuch@notmuchmail.org>; Sat, 29 Mar 2014 06:46:38 -0700 (PDT)\r
22 Received: from remotemail by yantan.tethera.net with local (Exim 4.80)\r
23         (envelope-from <bremner@tethera.net>)\r
24         id 1WTtag-0006uK-Rs; Sat, 29 Mar 2014 10:46:30 -0300\r
25 Received: (nullmailer pid 8942 invoked by uid 1000); Sat, 29 Mar 2014\r
26         13:46:27 -0000\r
27 From: David Bremner <david@tethera.net>\r
28 To: notmuch@notmuchmail.org\r
29 Subject: [PATCH] dump: support gzipped output\r
30 Date: Sat, 29 Mar 2014 10:46:25 -0300\r
31 Message-Id: <1396100785-8744-1-git-send-email-david@tethera.net>\r
32 X-Mailer: git-send-email 1.9.0\r
33 In-Reply-To: <1396056046-2247-1-git-send-email-david@tethera.net>\r
34 References: <1396056046-2247-1-git-send-email-david@tethera.net>\r
35 X-BeenThere: notmuch@notmuchmail.org\r
36 X-Mailman-Version: 2.1.13\r
37 Precedence: list\r
38 List-Id: "Use and development of the notmuch mail system."\r
39         <notmuch.notmuchmail.org>\r
40 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
41         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
42 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
43 List-Post: <mailto:notmuch@notmuchmail.org>\r
44 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
45 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
46         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
47 X-List-Received-Date: Sat, 29 Mar 2014 13:46:46 -0000\r
48 \r
49 The main goal is to support gzipped output for future internal\r
50 calls (e.g. from notmuch-new) to notmuch_database_dump.\r
51 \r
52 The additional dependency is not very heavy since xapian already pulls\r
53 in zlib.\r
54 ---\r
55 \r
56 I had a quick look at supporting gzipped input for restore; I think it\r
57 just requires an implementation of getline that uses gzgetc or gzgets;\r
58 the decompression can be completely transparent to the user based on\r
59 magic number.\r
60 \r
61  INSTALL                   | 17 ++++++++++----\r
62  Makefile.local            |  2 +-\r
63  configure                 | 23 ++++++++++++++++---\r
64  doc/man1/notmuch-dump.rst |  3 +++\r
65  notmuch-client.h          |  4 +++-\r
66  notmuch-dump.c            | 57 ++++++++++++++++++++++++++++++-----------------\r
67  test/T240-dump-restore.sh | 12 ++++++++++\r
68  7 files changed, 89 insertions(+), 29 deletions(-)\r
69 \r
70 diff --git a/INSTALL b/INSTALL\r
71 index 690b0ef..2754e52 100644\r
72 --- a/INSTALL\r
73 +++ b/INSTALL\r
74 @@ -20,8 +20,8 @@ configure stage.\r
75  \r
76  Dependencies\r
77  ------------\r
78 -Notmuch depends on three libraries: Xapian, GMime 2.4 or 2.6, and\r
79 -Talloc which are each described below:\r
80 +Notmuch depends on four libraries: Xapian, GMime 2.4 or 2.6,\r
81 +Talloc, and zlib which are each described below:\r
82  \r
83         Xapian\r
84         ------\r
85 @@ -60,6 +60,15 @@ Talloc which are each described below:\r
86  \r
87         Talloc is available from http://talloc.samba.org/\r
88  \r
89 +       zlib\r
90 +       ----\r
91 +\r
92 +       zlib is an extremely popular compression library. It is used\r
93 +       by Xapian, so if you installed that you will already have\r
94 +       zlib. You may need to install the zlib headers seperately.\r
95 +\r
96 +       zlib is available from http://zlib.net\r
97 +\r
98  Building Documentation\r
99  ----------------------\r
100  \r
101 @@ -79,11 +88,11 @@ dependencies with a simple simple command line. For example:\r
102  \r
103    For Debian and similar:\r
104  \r
105 -        sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev python-sphinx\r
106 +        sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev python-sphinx\r
107  \r
108    For Fedora and similar:\r
109  \r
110 -       sudo yum install xapian-core-devel gmime-devel libtalloc-devel python-sphinx\r
111 +       sudo yum install xapian-core-devel gmime-devel libtalloc-devel zlib-devel python-sphinx\r
112  \r
113  On other systems, a similar command can be used, but the details of\r
114  the package names may be different.\r
115 diff --git a/Makefile.local b/Makefile.local\r
116 index cb7b106..e5a20a7 100644\r
117 --- a/Makefile.local\r
118 +++ b/Makefile.local\r
119 @@ -41,7 +41,7 @@ PV_FILE=bindings/python/notmuch/version.py\r
120  # Smash together user's values with our extra values\r
121  FINAL_CFLAGS = -DNOTMUCH_VERSION=$(VERSION) $(CPPFLAGS) $(CFLAGS) $(WARN_CFLAGS) $(extra_cflags) $(CONFIGURE_CFLAGS)\r
122  FINAL_CXXFLAGS = $(CPPFLAGS) $(CXXFLAGS) $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) $(CONFIGURE_CXXFLAGS)\r
123 -FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lutil -Llib -lnotmuch $(AS_NEEDED_LDFLAGS) $(GMIME_LDFLAGS) $(TALLOC_LDFLAGS)\r
124 +FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lutil -Llib -lnotmuch $(AS_NEEDED_LDFLAGS) $(GMIME_LDFLAGS) $(TALLOC_LDFLAGS) $(ZLIB_LDFLAGS)\r
125  FINAL_NOTMUCH_LINKER = CC\r
126  ifneq ($(LINKER_RESOLVES_LIBRARY_DEPENDENCIES),1)\r
127  FINAL_NOTMUCH_LDFLAGS += $(CONFIGURE_LDFLAGS)\r
128 diff --git a/configure b/configure\r
129 index 1d430b9..89bb3f3 100755\r
130 --- a/configure\r
131 +++ b/configure\r
132 @@ -340,6 +340,18 @@ else\r
133      errors=$((errors + 1))\r
134  fi\r
135  \r
136 +printf "Checking for zlib development files... "\r
137 +have_zlib=0\r
138 +if pkg-config --exists zlib; then\r
139 +    printf "Yes.\n"\r
140 +    have_zlib=1\r
141 +    zlib_cflags=$(pkg-config --cflags zlib)\r
142 +    zlib_ldflags=$(pkg-config --libs zlib)\r
143 +else\r
144 +    printf "No.\n"\r
145 +    errors=$((errors + 1))\r
146 +fi\r
147 +\r
148  printf "Checking for talloc development files... "\r
149  if pkg-config --exists talloc; then\r
150      printf "Yes.\n"\r
151 @@ -519,11 +531,11 @@ case a simple command will install everything you need. For example:\r
152  \r
153  On Debian and similar systems:\r
154  \r
155 -       sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev\r
156 +       sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev\r
157  \r
158  Or on Fedora and similar systems:\r
159  \r
160 -       sudo yum install xapian-core-devel gmime-devel libtalloc-devel\r
161 +       sudo yum install xapian-core-devel gmime-devel libtalloc-devel zlib-devel\r
162  \r
163  On other systems, similar commands can be used, but the details of the\r
164  package names may be different.\r
165 @@ -844,6 +856,10 @@ XAPIAN_LDFLAGS = ${xapian_ldflags}\r
166  GMIME_CFLAGS = ${gmime_cflags}\r
167  GMIME_LDFLAGS = ${gmime_ldflags}\r
168  \r
169 +# Flags needed to compile and link against zlib\r
170 +ZLIB_CFLAGS = ${zlib_cflags}\r
171 +ZLIB_LDFLAGS = ${zlib_ldflags}\r
172 +\r
173  # Flags needed to compile and link against talloc\r
174  TALLOC_CFLAGS = ${talloc_cflags}\r
175  TALLOC_LDFLAGS = ${talloc_ldflags}\r
176 @@ -882,6 +898,7 @@ CONFIGURE_CFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)      \\\r
177                    -DUTIL_BYTE_ORDER=\$(UTIL_BYTE_ORDER)\r
178  \r
179  CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)    \\\r
180 +                    \$(ZLIB_CFLAGS)                                     \\\r
181                      \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\\r
182                      \$(VALGRIND_CFLAGS) \$(XAPIAN_CXXFLAGS)             \\\r
183                      -DHAVE_STRCASESTR=\$(HAVE_STRCASESTR)               \\\r
184 @@ -892,5 +909,5 @@ CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)    \\\r
185                      -DHAVE_XAPIAN_COMPACT=\$(HAVE_XAPIAN_COMPACT)       \\\r
186                      -DUTIL_BYTE_ORDER=\$(UTIL_BYTE_ORDER)\r
187  \r
188 -CONFIGURE_LDFLAGS =  \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS)\r
189 +CONFIGURE_LDFLAGS =  \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(ZLIB_LDFLAGS) \$(XAPIAN_LDFLAGS)\r
190  EOF\r
191 diff --git a/doc/man1/notmuch-dump.rst b/doc/man1/notmuch-dump.rst\r
192 index 17d1da5..d94cb4f 100644\r
193 --- a/doc/man1/notmuch-dump.rst\r
194 +++ b/doc/man1/notmuch-dump.rst\r
195 @@ -19,6 +19,9 @@ recreated from the messages themselves. The output of notmuch dump is\r
196  therefore the only critical thing to backup (and much more friendly to\r
197  incremental backup than the native database files.)\r
198  \r
199 +``--gzip``\r
200 +    Compress the output in a format compatible with **gzip(1)**.\r
201 +\r
202  ``--format=(sup|batch-tag)``\r
203      Notmuch restore supports two plain text dump formats, both with one\r
204      message-id per line, followed by a list of tags.\r
205 diff --git a/notmuch-client.h b/notmuch-client.h\r
206 index d110648..e1efbe0 100644\r
207 --- a/notmuch-client.h\r
208 +++ b/notmuch-client.h\r
209 @@ -450,7 +450,9 @@ typedef enum dump_formats {\r
210  int\r
211  notmuch_database_dump (notmuch_database_t *notmuch,\r
212                        const char *output_file_name,\r
213 -                      const char *query_str, dump_format_t output_format);\r
214 +                      const char *query_str,\r
215 +                      dump_format_t output_format,\r
216 +                      notmuch_bool_t gzip_output);\r
217  \r
218  #include "command-line-arguments.h"\r
219  #endif\r
220 diff --git a/notmuch-dump.c b/notmuch-dump.c\r
221 index 21702d7..128a37d 100644\r
222 --- a/notmuch-dump.c\r
223 +++ b/notmuch-dump.c\r
224 @@ -21,10 +21,12 @@\r
225  #include "notmuch-client.h"\r
226  #include "hex-escape.h"\r
227  #include "string-util.h"\r
228 +#include <zlib.h>\r
229 +\r
230  \r
231  static int\r
232 -database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
233 -                   const char *query_str, int output_format)\r
234 +database_dump_file (notmuch_database_t *notmuch, gzFile output,\r
235 +                       const char *query_str, int output_format)\r
236  {\r
237      notmuch_query_t *query;\r
238      notmuch_messages_t *messages;\r
239 @@ -69,7 +71,7 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
240         }\r
241  \r
242         if (output_format == DUMP_FORMAT_SUP) {\r
243 -           fprintf (output, "%s (", message_id);\r
244 +           gzprintf (output, "%s (", message_id);\r
245         }\r
246  \r
247         for (tags = notmuch_message_get_tags (message);\r
248 @@ -78,12 +80,12 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
249             const char *tag_str = notmuch_tags_get (tags);\r
250  \r
251             if (! first)\r
252 -               fputs (" ", output);\r
253 +               gzputs (output, " ");\r
254  \r
255             first = 0;\r
256  \r
257             if (output_format == DUMP_FORMAT_SUP) {\r
258 -               fputs (tag_str, output);\r
259 +               gzputs (output, tag_str);\r
260             } else {\r
261                 if (hex_encode (notmuch, tag_str,\r
262                                 &buffer, &buffer_size) != HEX_SUCCESS) {\r
263 @@ -91,12 +93,12 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
264                              tag_str);\r
265                     return EXIT_FAILURE;\r
266                 }\r
267 -               fprintf (output, "+%s", buffer);\r
268 +               gzprintf (output, "+%s", buffer);\r
269             }\r
270         }\r
271  \r
272         if (output_format == DUMP_FORMAT_SUP) {\r
273 -           fputs (")\n", output);\r
274 +           gzputs (output, ")\n");\r
275         } else {\r
276             if (make_boolean_term (notmuch, "id", message_id,\r
277                                    &buffer, &buffer_size)) {\r
278 @@ -104,7 +106,7 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
279                              message_id, strerror (errno));\r
280                     return EXIT_FAILURE;\r
281             }\r
282 -           fprintf (output, " -- %s\n", buffer);\r
283 +           gzprintf (output, " -- %s\n", buffer);\r
284         }\r
285  \r
286         notmuch_message_destroy (message);\r
287 @@ -121,24 +123,37 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
288  int\r
289  notmuch_database_dump (notmuch_database_t *notmuch,\r
290                        const char *output_file_name,\r
291 -                      const char *query_str, dump_format_t output_format)\r
292 +                      const char *query_str,\r
293 +                      dump_format_t output_format,\r
294 +                      notmuch_bool_t gzip_output)\r
295  {\r
296 -    FILE *output = stdout;\r
297 +    gzFile output;\r
298 +    const char *mode = gzip_output ? "w9" : "wT";\r
299 +\r
300      int ret;\r
301  \r
302 -    if (output_file_name) {\r
303 -       output = fopen (output_file_name, "w");\r
304 -       if (output == NULL) {\r
305 -           fprintf (stderr, "Error opening %s for writing: %s\n",\r
306 -                    output_file_name, strerror (errno));\r
307 -           return EXIT_FAILURE;\r
308 -       }\r
309 +    if (output_file_name)\r
310 +       output = gzopen (output_file_name, mode);\r
311 +    else\r
312 +       output = gzdopen (fileno (stdout), mode);\r
313 +\r
314 +    if (output == NULL) {\r
315 +       fprintf (stderr, "Error opening %s for (gzip) writing: %s\n",\r
316 +                output_file_name || "stdout", strerror (errno));\r
317 +       return EXIT_FAILURE;\r
318      }\r
319  \r
320      ret = database_dump_file (notmuch, output, query_str, output_format);\r
321  \r
322 -    if (output != stdout)\r
323 -       fclose (output);\r
324 +    /* unlike stdio, zlib needs explicit flushing */\r
325 +    if (gzflush (output, Z_FINISH)) {\r
326 +       fprintf (stderr, "Error flushing output: %s\n",\r
327 +                gzerror (output, NULL));\r
328 +       return EXIT_FAILURE;\r
329 +    }\r
330 +\r
331 +    if (output_file_name)\r
332 +       gzclose_w (output);\r
333  \r
334      return ret;\r
335  }\r
336 @@ -158,6 +173,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])\r
337      int opt_index;\r
338  \r
339      int output_format = DUMP_FORMAT_BATCH_TAG;\r
340 +    notmuch_bool_t gzip_output = 0;\r
341  \r
342      notmuch_opt_desc_t options[] = {\r
343         { NOTMUCH_OPT_KEYWORD, &output_format, "format", 'f',\r
344 @@ -165,6 +181,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])\r
345                                   { "batch-tag", DUMP_FORMAT_BATCH_TAG },\r
346                                   { 0, 0 } } },\r
347         { NOTMUCH_OPT_STRING, &output_file_name, "output", 'o', 0  },\r
348 +       { NOTMUCH_OPT_BOOLEAN, &gzip_output, "gzip", 'z', 0 },\r
349         { 0, 0, 0, 0, 0 }\r
350      };\r
351  \r
352 @@ -181,7 +198,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])\r
353      }\r
354  \r
355      ret = notmuch_database_dump (notmuch, output_file_name, query_str,\r
356 -                                output_format);\r
357 +                                output_format, gzip_output);\r
358  \r
359      notmuch_database_destroy (notmuch);\r
360  \r
361 diff --git a/test/T240-dump-restore.sh b/test/T240-dump-restore.sh\r
362 index 0004438..d79aca8 100755\r
363 --- a/test/T240-dump-restore.sh\r
364 +++ b/test/T240-dump-restore.sh\r
365 @@ -68,6 +68,18 @@ test_begin_subtest "dump --output=outfile --"\r
366  notmuch dump --output=dump-1-arg-dash.actual --\r
367  test_expect_equal_file dump.expected dump-1-arg-dash.actual\r
368  \r
369 +# gzipped output\r
370 +\r
371 +test_begin_subtest "dump --gzip"\r
372 +notmuch dump --gzip > dump-gzip.gz\r
373 +gunzip dump-gzip.gz\r
374 +test_expect_equal_file dump.expected dump-gzip\r
375 +\r
376 +test_begin_subtest "dump --gzip --output=outfile"\r
377 +notmuch dump --gzip --output=dump-gzip-outfile.gz\r
378 +gunzip dump-gzip-outfile.gz\r
379 +test_expect_equal_file dump.expected dump-gzip-outfile\r
380 +\r
381  # Note, we assume all messages from cworth have a message-id\r
382  # containing cworth.org\r
383  \r
384 -- \r
385 1.9.0\r
386 \r