From d57aa9e582f1644e2ee260c5c18fbf974dcc03ee Mon Sep 17 00:00:00 2001 From: Tim Culverhouse Date: Wed, 6 Sep 2023 07:47:19 -0500 Subject: lib: return a new Header from LimitHeaders The LimitHeaders function is used to optionally reduce memory usage of aerc by only keeping certain headers in memory for the message list. The function properly deletes header keys and values from the underlying object, however the underlying data structure has a map and a slice - which do not get resized after deletion: resulting in no actual memory savings. Create a new header and add only the headers we want to it. Return this value and use in the MessageInfo struct. Signed-off-by: Tim Culverhouse Acked-by: Robin Jarry --- worker/lib/parse.go | 22 ++++++++++------------ worker/maildir/worker.go | 4 ++-- worker/mbox/worker.go | 4 ++-- worker/notmuch/worker.go | 4 ++-- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/worker/lib/parse.go b/worker/lib/parse.go index 2baf13f7..8e20e904 100644 --- a/worker/lib/parse.go +++ b/worker/lib/parse.go @@ -303,7 +303,7 @@ func MessageInfo(raw RawMessage) (*models.MessageInfo, error) { Flags: flags, Labels: labels, InternalDate: recDate, - RFC822Headers: &mail.Header{Header: msg.Header}, + RFC822Headers: h, Size: 0, Uid: raw.UID(), Error: parseErr, @@ -312,26 +312,24 @@ func MessageInfo(raw RawMessage) (*models.MessageInfo, error) { // LimitHeaders returns a new Header with the specified headers included or // excluded -func LimitHeaders(hdr *mail.Header, fields []string, exclude bool) { +func LimitHeaders(hdr *mail.Header, fields []string, exclude bool) *mail.Header { fieldMap := make(map[string]struct{}, len(fields)) for _, f := range fields { fieldMap[strings.ToLower(f)] = struct{}{} } + nh := &mail.Header{} curFields := hdr.Fields() for curFields.Next() { key := strings.ToLower(curFields.Key()) - _, ok := fieldMap[key] - switch { - case exclude && ok: - curFields.Del() - case exclude && !ok: - // No-op: exclude but we didn't find it - case !exclude && ok: - // No-op: include and we found it - case !exclude && !ok: - curFields.Del() + _, present := fieldMap[key] + // XOR exclude and present. When they are equal, it means we + // should not add the header to the new header struct + if exclude == present { + continue } + nh.Add(key, curFields.Value()) } + return nh } // MessageHeaders populates a models.MessageInfo struct for the message. diff --git a/worker/maildir/worker.go b/worker/maildir/worker.go index 620e6c17..0be6137f 100644 --- a/worker/maildir/worker.go +++ b/worker/maildir/worker.go @@ -667,9 +667,9 @@ func (w *Worker) handleFetchMessageHeaders( } switch { case len(w.headersExclude) > 0: - lib.LimitHeaders(info.RFC822Headers, w.headersExclude, true) + info.RFC822Headers = lib.LimitHeaders(info.RFC822Headers, w.headersExclude, true) case len(w.headers) > 0: - lib.LimitHeaders(info.RFC822Headers, w.headers, false) + info.RFC822Headers = lib.LimitHeaders(info.RFC822Headers, w.headers, false) } w.worker.PostMessage(&types.MessageInfo{ Message: types.RespondTo(msg), diff --git a/worker/mbox/worker.go b/worker/mbox/worker.go index eb622e93..ab853b1c 100644 --- a/worker/mbox/worker.go +++ b/worker/mbox/worker.go @@ -174,9 +174,9 @@ func (w *mboxWorker) handleMessage(msg types.WorkerMessage) error { } else { switch { case len(w.headersExclude) > 0: - lib.LimitHeaders(msgInfo.RFC822Headers, w.headersExclude, true) + msgInfo.RFC822Headers = lib.LimitHeaders(msgInfo.RFC822Headers, w.headersExclude, true) case len(w.headers) > 0: - lib.LimitHeaders(msgInfo.RFC822Headers, w.headers, false) + msgInfo.RFC822Headers = lib.LimitHeaders(msgInfo.RFC822Headers, w.headers, false) } w.worker.PostMessage(&types.MessageInfo{ Message: types.RespondTo(msg), diff --git a/worker/notmuch/worker.go b/worker/notmuch/worker.go index aa0d1135..d1eb69d0 100644 --- a/worker/notmuch/worker.go +++ b/worker/notmuch/worker.go @@ -678,9 +678,9 @@ func (w *worker) emitMessageInfo(m *Message, } switch { case len(w.headersExclude) > 0: - lib.LimitHeaders(info.RFC822Headers, w.headersExclude, true) + info.RFC822Headers = lib.LimitHeaders(info.RFC822Headers, w.headersExclude, true) case len(w.headers) > 0: - lib.LimitHeaders(info.RFC822Headers, w.headers, false) + info.RFC822Headers = lib.LimitHeaders(info.RFC822Headers, w.headers, false) } switch parent { case nil: -- cgit v1.2.3-54-g00ecf