summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-08-11 16:23:34 +0300
committerSergey Poznyakoff <gray@gnu.org>2020-08-11 16:23:34 +0300
commitf9cc3bbee99bb4392942052efafced724568e5c8 (patch)
treea03759d4c177eb4bfe3b8a0ba5426794af173a5d
parent0f1a6e4109a7f174bb127281e15579fbb576128d (diff)
downloadmailutils-f9cc3bbee99bb4392942052efafced724568e5c8.tar.gz
mailutils-f9cc3bbee99bb4392942052efafced724568e5c8.tar.bz2
decodemail: use append mode to reduce memory requirements.
* decodemail/decodemail.c (main): Open output mailbox in append mode. If truncate is requested, open it rw for truncating, then close and reopen for appending. This speeds up operation considerably. * libproto/mbox/mbox.c (mbox_open): Change rules for selecting mmap vs file open. (mbox_close): Destroy the stream. (append_message_to_stream): Minor fix. (mbox_append_message): Unlock the stream on failure as well as on success.
-rw-r--r--decodemail/decodemail.c84
-rw-r--r--libproto/mbox/mbox.c37
2 files changed, 86 insertions, 35 deletions
diff --git a/decodemail/decodemail.c b/decodemail/decodemail.c
index b263e1dc1..420309749 100644
--- a/decodemail/decodemail.c
+++ b/decodemail/decodemail.c
@@ -121,6 +121,47 @@ abend (int code)
exit (code);
}
+static void
+mailbox_truncate (mu_mailbox_t mbox)
+{
+ int rc;
+ mu_iterator_t itr;
+
+ mu_mailbox_get_iterator (mbox, &itr);
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+ mu_iterator_next (itr))
+ {
+ mu_message_t m;
+ mu_attribute_t a;
+
+ if ((rc = mu_iterator_current (itr, (void **)&m)) != 0)
+ {
+ mu_error (_("can't get current message while truncating the mailbox: %s"),
+ mu_strerror (rc));
+ exit (EX_OSERR);
+ }
+ mu_message_get_attribute (m, &a);
+ mu_attribute_set_deleted (a);
+ }
+ mu_iterator_destroy (&itr);
+ if ((rc = mu_mailbox_expunge (mbox)) != 0)
+ {
+ mu_error (_("error expunging destination mailbox: %s"),
+ mu_strerror (rc));
+ exit (EX_OSERR);
+ }
+}
+
+static void
+output_mbox_cleanup (void *arg)
+{
+ if (arg)
+ {
+ mu_mailbox_t mbox = arg;
+ mu_mailbox_unlock (mbox);
+ }
+}
+
int
main (int argc, char **argv)
{
@@ -201,7 +242,31 @@ main (int argc, char **argv)
mu_strerror (rc));
abend (EX_OSERR);
}
- rc = mu_mailbox_open (ombox, MU_STREAM_RDWR|MU_STREAM_CREAT);
+
+ mu_onexit (output_mbox_cleanup, ombox);
+
+ if (truncate_opt)
+ {
+ rc = mu_mailbox_open (ombox, MU_STREAM_RDWR);
+ switch (rc)
+ {
+ case 0:
+ mailbox_truncate (ombox);
+ mu_mailbox_close (ombox);
+ break;
+
+ case ENOENT:
+ case MU_ERR_NOENT:
+ break;
+
+ default:
+ mu_error (_("could not open mailbox `%s': %s"),
+ ombox_name, mu_strerror (rc));
+ abend (EX_OSERR);
+ }
+ }
+
+ rc = mu_mailbox_open (ombox, MU_STREAM_APPEND|MU_STREAM_CREAT);
if (rc)
{
mu_error (_("could not open mailbox `%s': %s"),
@@ -214,21 +279,6 @@ main (int argc, char **argv)
strcmp (type, "MBOX") == 0)
from_filter = 1;
- if (truncate_opt)
- {
- mu_mailbox_get_iterator (ombox, &itr);
- for (mu_iterator_first (itr), i = 1; !mu_iterator_is_done (itr);
- mu_iterator_next (itr), i++)
- {
- mu_message_t m;
- mu_attribute_t a;
-
- rc = mu_iterator_current (itr, (void **)&m);
- mu_message_get_attribute (m, &a);
- mu_attribute_set_deleted (a);
- }
- mu_iterator_destroy (&itr);
- }
message_store = message_store_mbox;
}
else
@@ -272,7 +322,7 @@ main (int argc, char **argv)
enable_log_prefix (0);
mu_mailbox_destroy (&imbox);
- (truncate_opt ? mu_mailbox_expunge : mu_mailbox_sync) (ombox);
+ mu_mailbox_sync (ombox);
mu_mailbox_destroy (&ombox);
if (err)
diff --git a/libproto/mbox/mbox.c b/libproto/mbox/mbox.c
index dad348ce7..d05482ce3 100644
--- a/libproto/mbox/mbox.c
+++ b/libproto/mbox/mbox.c
@@ -83,11 +83,11 @@ mbox_open (mu_mailbox_t mailbox, int flags)
/* Get a stream. */
if (mailbox->stream == NULL)
{
- /* We do not try to mmap for CREAT or APPEND, it is not supported. */
- status = (flags & MU_STREAM_CREAT)
- || (mailbox->flags & MU_STREAM_APPEND);
-
- /* Try to mmap () the file first. */
+ /* Prefer mmap, unless the mailbox file does not exist and CREAT is
+ requested or the mailbox is being opened for appending */
+ status = (((flags & MU_STREAM_CREAT) && access (mud->name, F_OK)) ||
+ (mailbox->flags & MU_STREAM_APPEND));
+
if (status == 0)
{
status = mu_mapfile_stream_create (&mailbox->stream, mud->name,
@@ -119,7 +119,8 @@ mbox_close (mu_mailbox_t mailbox)
{
mbox_data_t mud = mailbox->data;
size_t i;
-
+ int rc;
+
if (mud == NULL)
return EINVAL;
@@ -160,7 +161,10 @@ mbox_close (mu_mailbox_t mailbox)
mud->uidnext = 0;
mu_monitor_unlock (mailbox->monitor);
- return mu_stream_close (mailbox->stream);
+ rc = mu_stream_close (mailbox->stream);
+ if (rc == 0)
+ mu_stream_destroy (&mailbox->stream);
+ return rc;
}
static int
@@ -1068,14 +1072,12 @@ append_message_to_stream (mu_stream_t ostr, mu_message_t msg,
if (flags & MBOX_FIRSTMSG)
{
- /* FIXME: Perhaps printf should return error code,
- like the rest of stream functions. */
- mu_stream_printf (ostr, "%s: %lu %u\n",
- MU_HEADER_X_IMAPBASE,
- (unsigned long) mud->uidvalidity,
- (unsigned) mud->uidnext);
- if (mu_stream_err (ostr))
- return mu_stream_last_error (ostr);
+ status = mu_stream_printf (ostr, "%s: %lu %u\n",
+ MU_HEADER_X_IMAPBASE,
+ (unsigned long) mud->uidvalidity,
+ (unsigned) mud->uidnext);
+ if (status)
+ return status;
}
status = msg_attr_to_stream (ostr, msg);
@@ -1140,9 +1142,8 @@ mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg)
}
status = mu_stream_seek (mailbox->stream, 0, MU_SEEK_END, &size);
- if (status)
- return status;
- status = append_message_to_stream (mailbox->stream, msg, mud, 0);
+ if (status == 0)
+ status = append_message_to_stream (mailbox->stream, msg, mud, 0);
if (mailbox->locker)
mu_locker_unlock (mailbox->locker);

Return to:

Send suggestions and report system problems to the System administrator.