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  }