github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/shell/autocomplete/paths_cache.go (about) 1 package autocomplete 2 3 import ( 4 "crypto/md5" 5 "sync" 6 "time" 7 ) 8 9 type pathsCacheT struct { 10 hash map[string]pathsCacheItemT 11 gcSleep int 12 mutex sync.Mutex 13 } 14 15 type pathsCacheItemT struct { 16 time time.Time 17 paths []string 18 } 19 20 var pathsCache = NewPathsCache() 21 22 func NewPathsCache() *pathsCacheT { 23 pc := new(pathsCacheT) 24 pc.hash = make(map[string]pathsCacheItemT) 25 pc.gcSleep = 5 // minutes 26 go pc.garbageCollection() 27 return pc 28 } 29 30 var ( 31 t = []byte{':', 't'} 32 f = []byte{':', 'f'} 33 ) 34 35 func (pc *pathsCacheT) CreateHash(exe string, filesToo bool, regexp bool) []byte { 36 h := md5.New() 37 38 _, err := h.Write([]byte(exe)) 39 if err != nil { 40 return nil 41 } 42 43 if filesToo { 44 _, err = h.Write(t) 45 } else { 46 _, err = h.Write(f) 47 } 48 if err != nil { 49 return nil 50 } 51 52 if regexp { 53 _, err = h.Write(t) 54 } else { 55 _, err = h.Write(f) 56 } 57 if err != nil { 58 return nil 59 } 60 61 hash := h.Sum(nil) 62 return hash 63 } 64 65 func (pc *pathsCacheT) Get(hash []byte) []string { 66 s := string(hash) 67 68 pc.mutex.Lock() 69 70 cache := pc.hash[s] 71 if cache.time.After(time.Now()) { 72 s := cache.paths 73 pc.mutex.Unlock() 74 return s 75 } 76 77 pc.mutex.Unlock() 78 return nil 79 } 80 81 func (pc *pathsCacheT) Set(hash []byte, paths []string) { 82 pc.mutex.Lock() 83 84 pc.hash[string(hash)] = pathsCacheItemT{ 85 time: time.Now().Add(time.Duration(30) * time.Second), 86 paths: paths, 87 } 88 89 pc.mutex.Unlock() 90 } 91 92 func (pc *pathsCacheT) garbageCollection() { 93 for { 94 pc.mutex.Lock() 95 sleep := pc.gcSleep 96 pc.mutex.Unlock() 97 time.Sleep(time.Duration(sleep) * time.Minute) 98 99 pc.mutex.Lock() 100 for hash := range pc.hash { 101 if pc.hash[hash].time.Before(time.Now()) { 102 delete(pc.hash, hash) 103 } 104 } 105 pc.mutex.Unlock() 106 } 107 }