diff --git a/node.go b/node.go index b29f2fe45..5c9a5768c 100644 --- a/node.go +++ b/node.go @@ -6,6 +6,7 @@ import ( "os" "os/user" "strconv" + "sync" "syscall" "time" @@ -339,15 +340,41 @@ func (node *Node) fillUser(stat *syscall.Stat_t) error { node.UID = stat.Uid node.GID = stat.Gid - u, err := user.LookupId(strconv.Itoa(int(stat.Uid))) + username, err := lookupUsername(strconv.Itoa(int(stat.Uid))) if err != nil { return err } - node.User = u.Username + node.User = username return nil } +var ( + uidLookupCache = make(map[string]string) + uidLookupCacheMutex = sync.RWMutex{} +) + +func lookupUsername(uid string) (string, error) { + uidLookupCacheMutex.RLock() + value, ok := uidLookupCache[uid] + uidLookupCacheMutex.RUnlock() + + if ok { + return value, nil + } + + u, err := user.LookupId(uid) + if err != nil { + return "", err + } + + uidLookupCacheMutex.Lock() + uidLookupCache[uid] = u.Username + uidLookupCacheMutex.Unlock() + + return u.Username, nil +} + func (node *Node) fillExtra(path string, fi os.FileInfo) error { stat, ok := fi.Sys().(*syscall.Stat_t) if !ok { @@ -356,11 +383,14 @@ func (node *Node) fillExtra(path string, fi os.FileInfo) error { node.Inode = stat.Ino - node.fillUser(stat) node.fillTimes(stat) var err error + if err = node.fillUser(stat); err != nil { + return err + } + switch node.Type { case "file": node.Size = uint64(stat.Size)