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  }