github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/fs/accounting/stringset.go (about) 1 package accounting 2 3 import ( 4 "fmt" 5 "sort" 6 "strings" 7 "sync" 8 9 "github.com/ncw/rclone/fs" 10 ) 11 12 // stringSet holds a set of strings 13 type stringSet struct { 14 mu sync.RWMutex 15 items map[string]struct{} 16 name string 17 } 18 19 // newStringSet creates a new empty string set of capacity size 20 func newStringSet(size int, name string) *stringSet { 21 return &stringSet{ 22 items: make(map[string]struct{}, size), 23 name: name, 24 } 25 } 26 27 // add adds remote to the set 28 func (ss *stringSet) add(remote string) { 29 ss.mu.Lock() 30 ss.items[remote] = struct{}{} 31 ss.mu.Unlock() 32 } 33 34 // del removes remote from the set 35 func (ss *stringSet) del(remote string) { 36 ss.mu.Lock() 37 delete(ss.items, remote) 38 ss.mu.Unlock() 39 } 40 41 // empty returns whether the set has any items 42 func (ss *stringSet) empty() bool { 43 ss.mu.RLock() 44 defer ss.mu.RUnlock() 45 return len(ss.items) == 0 46 } 47 48 // count returns the number of items in the set 49 func (ss *stringSet) count() int { 50 ss.mu.RLock() 51 defer ss.mu.RUnlock() 52 return len(ss.items) 53 } 54 55 // Strings returns all the strings in the stringSet 56 func (ss *stringSet) Strings() []string { 57 ss.mu.RLock() 58 defer ss.mu.RUnlock() 59 strings := make([]string, 0, len(ss.items)) 60 for name := range ss.items { 61 var out string 62 if acc := Stats.inProgress.get(name); acc != nil { 63 out = acc.String() 64 } else { 65 out = fmt.Sprintf("%*s: %s", 66 fs.Config.StatsFileNameLength, 67 shortenName(name, fs.Config.StatsFileNameLength), 68 ss.name, 69 ) 70 } 71 strings = append(strings, " * "+out) 72 } 73 sorted := sort.StringSlice(strings) 74 sorted.Sort() 75 return sorted 76 } 77 78 // String returns all the file names in the stringSet joined by newline 79 func (ss *stringSet) String() string { 80 return strings.Join(ss.Strings(), "\n") 81 } 82 83 // progress returns total bytes read as well as the size. 84 func (ss *stringSet) progress() (totalBytes, totalSize int64) { 85 ss.mu.RLock() 86 defer ss.mu.RUnlock() 87 for name := range ss.items { 88 if acc := Stats.inProgress.get(name); acc != nil { 89 bytes, size := acc.progress() 90 if size >= 0 && bytes >= 0 { 91 totalBytes += bytes 92 totalSize += size 93 } 94 } 95 } 96 return totalBytes, totalSize 97 }