diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-08-11 16:23:34 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-08-11 16:23:34 +0300 |
commit | f9cc3bbee99bb4392942052efafced724568e5c8 (patch) | |
tree | a03759d4c177eb4bfe3b8a0ba5426794af173a5d | |
parent | 0f1a6e4109a7f174bb127281e15579fbb576128d (diff) | |
download | mailutils-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.c | 84 | ||||
-rw-r--r-- | libproto/mbox/mbox.c | 37 |
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); |