mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-17 17:47:03 +00:00
file: Use os.Readdirnames to eliminate Lstat calls for #122
- This a speed/syscall optimization, not memory.
This commit is contained in:
@@ -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)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user