1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 09:37:02 +00:00

file: Use os.Readdirnames to eliminate Lstat calls for #122

- This a speed/syscall optimization, not memory.
This commit is contained in:
James Hillyerd
2018-10-21 09:25:32 -07:00
parent f68f07d896
commit 0640f9fa08

View File

@@ -4,7 +4,6 @@ import (
"bufio" "bufio"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"sync" "sync"
@@ -190,41 +189,33 @@ func (fs *Store) PurgeMessages(mailbox string) error {
// VisitMailboxes accepts a function that will be called with the messages in each mailbox while it // VisitMailboxes accepts a function that will be called with the messages in each mailbox while it
// continues to return true. // continues to return true.
func (fs *Store) VisitMailboxes(f func([]storage.Message) (cont bool)) error { func (fs *Store) VisitMailboxes(f func([]storage.Message) (cont bool)) error {
infos1, err := ioutil.ReadDir(fs.mailPath) names1, err := readDirNames(fs.mailPath)
if err != nil { if err != nil {
return err return err
} }
// Loop over level 1 directories // Loop over level 1 directories
for _, inf1 := range infos1 { for _, name1 := range names1 {
if inf1.IsDir() { names2, err := readDirNames(fs.mailPath, name1)
l1 := inf1.Name() if err != nil {
infos2, err := ioutil.ReadDir(filepath.Join(fs.mailPath, l1)) return err
}
// Loop over level 2 directories
for _, name2 := range names2 {
names3, err := readDirNames(fs.mailPath, name1, name2)
if err != nil { if err != nil {
return err return err
} }
// Loop over level 2 directories // Loop over mailboxes
for _, inf2 := range infos2 { for _, name3 := range names3 {
if inf2.IsDir() { mb := fs.mboxFromHash(name3)
l2 := inf2.Name() mb.RLock()
infos3, err := ioutil.ReadDir(filepath.Join(fs.mailPath, l1, l2)) msgs, err := mb.getMessages()
if err != nil { mb.RUnlock()
return err if err != nil {
} return err
// Loop over mailboxes }
for _, inf3 := range infos3 { if !f(msgs) {
if inf3.IsDir() { return nil
mb := fs.mboxFromHash(inf3.Name())
mb.RLock()
msgs, err := mb.getMessages()
mb.RUnlock()
if err != nil {
return err
}
if !f(msgs) {
return nil
}
}
}
} }
} }
} }
@@ -264,14 +255,14 @@ func (fs *Store) mboxFromHash(hash string) *mbox {
} }
} }
// getPooledReader pulls a buffered reader from the fs.bufReaderPool // getPooledReader pulls a buffered reader from the fs.bufReaderPool.
func (fs *Store) getPooledReader(r io.Reader) *bufio.Reader { func (fs *Store) getPooledReader(r io.Reader) *bufio.Reader {
br := fs.bufReaderPool.Get().(*bufio.Reader) br := fs.bufReaderPool.Get().(*bufio.Reader)
br.Reset(r) br.Reset(r)
return br return br
} }
// putPooledReader returns a buffered reader to the fs.bufReaderPool // putPooledReader returns a buffered reader to the fs.bufReaderPool.
func (fs *Store) putPooledReader(br *bufio.Reader) { func (fs *Store) putPooledReader(br *bufio.Reader) {
fs.bufReaderPool.Put(br) fs.bufReaderPool.Put(br)
} }
@@ -284,7 +275,16 @@ func generatePrefix(date time.Time) string {
} }
// generateId adds a 4-digit unique number onto the end of the string // generateId adds a 4-digit unique number onto the end of the string
// returned by generatePrefix() // returned by generatePrefix().
func generateID(date time.Time) string { func generateID(date time.Time) string {
return generatePrefix(date) + "-" + fmt.Sprintf("%04d", <-countChannel) return generatePrefix(date) + "-" + fmt.Sprintf("%04d", <-countChannel)
} }
// readDirNames returns a slice of filenames in the specified directory or an error.
func readDirNames(elem ...string) ([]string, error) {
f, err := os.Open(filepath.Join(elem...))
if err != nil {
return nil, err
}
return f.Readdirnames(0)
}