2018-02-01 13:13:24 +00:00
|
|
|
package accounting
|
|
|
|
|
|
|
|
import (
|
2019-01-14 16:12:39 +00:00
|
|
|
"fmt"
|
2018-02-01 13:13:24 +00:00
|
|
|
"sort"
|
|
|
|
"strings"
|
2018-05-02 16:01:39 +00:00
|
|
|
"sync"
|
2019-01-14 16:12:39 +00:00
|
|
|
|
2019-07-28 17:47:38 +00:00
|
|
|
"github.com/rclone/rclone/fs"
|
2018-02-01 13:13:24 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// stringSet holds a set of strings
|
2018-05-02 16:01:39 +00:00
|
|
|
type stringSet struct {
|
|
|
|
mu sync.RWMutex
|
|
|
|
items map[string]struct{}
|
2019-01-14 16:12:39 +00:00
|
|
|
name string
|
2018-05-02 16:01:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// newStringSet creates a new empty string set of capacity size
|
2019-01-14 16:12:39 +00:00
|
|
|
func newStringSet(size int, name string) *stringSet {
|
2018-05-02 16:01:39 +00:00
|
|
|
return &stringSet{
|
|
|
|
items: make(map[string]struct{}, size),
|
2019-01-14 16:12:39 +00:00
|
|
|
name: name,
|
2018-05-02 16:01:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add adds remote to the set
|
|
|
|
func (ss *stringSet) add(remote string) {
|
|
|
|
ss.mu.Lock()
|
|
|
|
ss.items[remote] = struct{}{}
|
|
|
|
ss.mu.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
// del removes remote from the set
|
|
|
|
func (ss *stringSet) del(remote string) {
|
|
|
|
ss.mu.Lock()
|
|
|
|
delete(ss.items, remote)
|
|
|
|
ss.mu.Unlock()
|
|
|
|
}
|
|
|
|
|
2019-07-18 10:13:54 +00:00
|
|
|
// merge adds items from another set
|
|
|
|
func (ss *stringSet) merge(m *stringSet) {
|
|
|
|
ss.mu.Lock()
|
|
|
|
m.mu.Lock()
|
|
|
|
for item := range m.items {
|
|
|
|
ss.items[item] = struct{}{}
|
|
|
|
}
|
|
|
|
m.mu.Unlock()
|
|
|
|
ss.mu.Unlock()
|
|
|
|
}
|
|
|
|
|
2018-05-02 16:01:39 +00:00
|
|
|
// empty returns whether the set has any items
|
|
|
|
func (ss *stringSet) empty() bool {
|
|
|
|
ss.mu.RLock()
|
|
|
|
defer ss.mu.RUnlock()
|
|
|
|
return len(ss.items) == 0
|
|
|
|
}
|
2018-02-01 13:13:24 +00:00
|
|
|
|
2018-08-28 10:17:05 +00:00
|
|
|
// count returns the number of items in the set
|
|
|
|
func (ss *stringSet) count() int {
|
|
|
|
ss.mu.RLock()
|
|
|
|
defer ss.mu.RUnlock()
|
|
|
|
return len(ss.items)
|
|
|
|
}
|
|
|
|
|
2019-07-18 10:13:54 +00:00
|
|
|
// String returns string representation of set items.
|
|
|
|
func (ss *stringSet) String(progress *inProgress) string {
|
2018-05-02 16:01:39 +00:00
|
|
|
ss.mu.RLock()
|
|
|
|
defer ss.mu.RUnlock()
|
2019-07-18 10:13:54 +00:00
|
|
|
strngs := make([]string, 0, len(ss.items))
|
2018-05-02 16:01:39 +00:00
|
|
|
for name := range ss.items {
|
2018-02-01 13:13:24 +00:00
|
|
|
var out string
|
2019-07-18 10:13:54 +00:00
|
|
|
if acc := progress.get(name); acc != nil {
|
2018-02-01 13:13:24 +00:00
|
|
|
out = acc.String()
|
|
|
|
} else {
|
2019-01-14 16:12:39 +00:00
|
|
|
out = fmt.Sprintf("%*s: %s",
|
|
|
|
fs.Config.StatsFileNameLength,
|
|
|
|
shortenName(name, fs.Config.StatsFileNameLength),
|
|
|
|
ss.name,
|
|
|
|
)
|
2018-02-01 13:13:24 +00:00
|
|
|
}
|
2019-07-18 10:13:54 +00:00
|
|
|
strngs = append(strngs, " * "+out)
|
2018-02-01 13:13:24 +00:00
|
|
|
}
|
2019-07-18 10:13:54 +00:00
|
|
|
sorted := sort.StringSlice(strngs)
|
2018-02-01 13:13:24 +00:00
|
|
|
sorted.Sort()
|
2019-07-18 10:13:54 +00:00
|
|
|
return strings.Join(sorted, "\n")
|
2018-02-01 13:13:24 +00:00
|
|
|
}
|
2018-08-28 10:17:05 +00:00
|
|
|
|
|
|
|
// progress returns total bytes read as well as the size.
|
2019-07-18 10:13:54 +00:00
|
|
|
func (ss *stringSet) progress(stats *StatsInfo) (totalBytes, totalSize int64) {
|
2018-08-28 10:17:05 +00:00
|
|
|
ss.mu.RLock()
|
|
|
|
defer ss.mu.RUnlock()
|
|
|
|
for name := range ss.items {
|
2019-07-18 10:13:54 +00:00
|
|
|
if acc := stats.inProgress.get(name); acc != nil {
|
2018-08-28 10:17:05 +00:00
|
|
|
bytes, size := acc.progress()
|
|
|
|
if size >= 0 && bytes >= 0 {
|
|
|
|
totalBytes += bytes
|
|
|
|
totalSize += size
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return totalBytes, totalSize
|
|
|
|
}
|