github.com/xhghs/rclone@v1.51.1-0.20200430155106-e186a28cced8/fs/accounting/stringset.go (about) 1 package accounting 2 3 import ( 4 "fmt" 5 "sort" 6 "strings" 7 "sync" 8 9 "github.com/rclone/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 // merge adds items from another set 42 func (ss *stringSet) merge(m *stringSet) { 43 ss.mu.Lock() 44 m.mu.Lock() 45 for item := range m.items { 46 ss.items[item] = struct{}{} 47 } 48 m.mu.Unlock() 49 ss.mu.Unlock() 50 } 51 52 // empty returns whether the set has any items 53 func (ss *stringSet) empty() bool { 54 ss.mu.RLock() 55 defer ss.mu.RUnlock() 56 return len(ss.items) == 0 57 } 58 59 // count returns the number of items in the set 60 func (ss *stringSet) count() int { 61 ss.mu.RLock() 62 defer ss.mu.RUnlock() 63 return len(ss.items) 64 } 65 66 // String returns string representation of set items excluding any in 67 // exclude (if set). 68 func (ss *stringSet) String(progress *inProgress, exclude *stringSet) string { 69 ss.mu.RLock() 70 defer ss.mu.RUnlock() 71 strngs := make([]string, 0, len(ss.items)) 72 for name := range ss.items { 73 if exclude != nil { 74 exclude.mu.RLock() 75 _, found := exclude.items[name] 76 exclude.mu.RUnlock() 77 if found { 78 continue 79 } 80 } 81 var out string 82 if acc := progress.get(name); acc != nil { 83 out = acc.String() 84 } else { 85 out = fmt.Sprintf("%*s: %s", 86 fs.Config.StatsFileNameLength, 87 shortenName(name, fs.Config.StatsFileNameLength), 88 ss.name, 89 ) 90 } 91 strngs = append(strngs, " * "+out) 92 } 93 sorted := sort.StringSlice(strngs) 94 sorted.Sort() 95 return strings.Join(sorted, "\n") 96 } 97 98 // progress returns total bytes read as well as the size. 99 func (ss *stringSet) progress(stats *StatsInfo) (totalBytes, totalSize int64) { 100 ss.mu.RLock() 101 defer ss.mu.RUnlock() 102 for name := range ss.items { 103 if acc := stats.inProgress.get(name); acc != nil { 104 bytes, size := acc.progress() 105 if size >= 0 && bytes >= 0 { 106 totalBytes += bytes 107 totalSize += size 108 } 109 } 110 } 111 return totalBytes, totalSize 112 }