2020-06-13 20:37:42 +02:00
|
|
|
package accounting
|
|
|
|
|
|
|
|
import (
|
2020-11-05 17:59:59 +01:00
|
|
|
"context"
|
2020-06-13 20:37:42 +02:00
|
|
|
"fmt"
|
build: modernize Go usage
This commit modernizes Go usage. This was done with:
go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix -test ./...
Then files needed to be `go fmt`ed and a few comments needed to be
restored.
The modernizations include replacing
- if/else conditional assignment by a call to the built-in min or max functions added in go1.21
- sort.Slice(x, func(i, j int) bool) { return s[i] < s[j] } by a call to slices.Sort(s), added in go1.21
- interface{} by the 'any' type added in go1.18
- append([]T(nil), s...) by slices.Clone(s) or slices.Concat(s), added in go1.21
- loop around an m[k]=v map update by a call to one of the Collect, Copy, Clone, or Insert functions from the maps package, added in go1.21
- []byte(fmt.Sprintf...) by fmt.Appendf(nil, ...), added in go1.19
- append(s[:i], s[i+1]...) by slices.Delete(s, i, i+1), added in go1.21
- a 3-clause for i := 0; i < n; i++ {} loop by for i := range n {}, added in go1.22
2025-02-26 22:08:12 +01:00
|
|
|
"maps"
|
2020-06-13 20:37:42 +02:00
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/rclone/rclone/fs"
|
2020-08-05 17:59:44 +02:00
|
|
|
"github.com/rclone/rclone/fs/rc"
|
2020-06-13 20:37:42 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// transferMap holds name to transfer map
|
|
|
|
type transferMap struct {
|
|
|
|
mu sync.RWMutex
|
|
|
|
items map[string]*Transfer
|
|
|
|
name string
|
|
|
|
}
|
|
|
|
|
|
|
|
// newTransferMap creates a new empty transfer map of capacity size
|
|
|
|
func newTransferMap(size int, name string) *transferMap {
|
|
|
|
return &transferMap{
|
|
|
|
items: make(map[string]*Transfer, size),
|
|
|
|
name: name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add adds a new transfer to the map
|
|
|
|
func (tm *transferMap) add(tr *Transfer) {
|
|
|
|
tm.mu.Lock()
|
|
|
|
tm.items[tr.remote] = tr
|
|
|
|
tm.mu.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
// del removes a transfer from the map by name
|
2022-06-27 18:56:03 +02:00
|
|
|
func (tm *transferMap) del(remote string) bool {
|
2020-06-13 20:37:42 +02:00
|
|
|
tm.mu.Lock()
|
2022-06-27 18:56:03 +02:00
|
|
|
_, exists := tm.items[remote]
|
2020-06-13 20:37:42 +02:00
|
|
|
delete(tm.items, remote)
|
|
|
|
tm.mu.Unlock()
|
2022-06-27 18:56:03 +02:00
|
|
|
|
|
|
|
return exists
|
2020-06-13 20:37:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// merge adds items from another map
|
|
|
|
func (tm *transferMap) merge(m *transferMap) {
|
|
|
|
tm.mu.Lock()
|
|
|
|
m.mu.Lock()
|
build: modernize Go usage
This commit modernizes Go usage. This was done with:
go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix -test ./...
Then files needed to be `go fmt`ed and a few comments needed to be
restored.
The modernizations include replacing
- if/else conditional assignment by a call to the built-in min or max functions added in go1.21
- sort.Slice(x, func(i, j int) bool) { return s[i] < s[j] } by a call to slices.Sort(s), added in go1.21
- interface{} by the 'any' type added in go1.18
- append([]T(nil), s...) by slices.Clone(s) or slices.Concat(s), added in go1.21
- loop around an m[k]=v map update by a call to one of the Collect, Copy, Clone, or Insert functions from the maps package, added in go1.21
- []byte(fmt.Sprintf...) by fmt.Appendf(nil, ...), added in go1.19
- append(s[:i], s[i+1]...) by slices.Delete(s, i, i+1), added in go1.21
- a 3-clause for i := 0; i < n; i++ {} loop by for i := range n {}, added in go1.22
2025-02-26 22:08:12 +01:00
|
|
|
maps.Copy(tm.items, m.items)
|
2020-06-13 20:37:42 +02:00
|
|
|
m.mu.Unlock()
|
|
|
|
tm.mu.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
// empty returns whether the map has any items
|
|
|
|
func (tm *transferMap) empty() bool {
|
|
|
|
tm.mu.RLock()
|
|
|
|
defer tm.mu.RUnlock()
|
|
|
|
return len(tm.items) == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
// count returns the number of items in the map
|
|
|
|
func (tm *transferMap) count() int {
|
|
|
|
tm.mu.RLock()
|
|
|
|
defer tm.mu.RUnlock()
|
|
|
|
return len(tm.items)
|
|
|
|
}
|
|
|
|
|
2020-08-05 17:59:44 +02:00
|
|
|
// _sortedSlice returns all transfers sorted by start time
|
|
|
|
//
|
|
|
|
// Call with mu.Rlock held
|
|
|
|
func (tm *transferMap) _sortedSlice() []*Transfer {
|
2020-06-16 17:18:32 +02:00
|
|
|
s := make([]*Transfer, 0, len(tm.items))
|
|
|
|
for _, tr := range tm.items {
|
|
|
|
s = append(s, tr)
|
|
|
|
}
|
2020-09-18 13:30:01 +02:00
|
|
|
// sort by time first and if equal by name. Note that the relatively
|
|
|
|
// low time resolution on Windows can cause equal times.
|
2020-06-16 17:18:32 +02:00
|
|
|
sort.Slice(s, func(i, j int) bool {
|
2020-09-18 13:30:01 +02:00
|
|
|
a, b := s[i], s[j]
|
|
|
|
if a.startedAt.Before(b.startedAt) {
|
|
|
|
return true
|
|
|
|
} else if !a.startedAt.Equal(b.startedAt) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return a.remote < b.remote
|
2020-06-16 17:18:32 +02:00
|
|
|
})
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2020-06-13 20:37:42 +02:00
|
|
|
// String returns string representation of map items excluding any in
|
|
|
|
// exclude (if set).
|
2020-11-05 17:59:59 +01:00
|
|
|
func (tm *transferMap) String(ctx context.Context, progress *inProgress, exclude *transferMap) string {
|
2020-06-13 20:37:42 +02:00
|
|
|
tm.mu.RLock()
|
|
|
|
defer tm.mu.RUnlock()
|
2020-11-05 12:33:32 +01:00
|
|
|
ci := fs.GetConfig(ctx)
|
Spelling fixes
Fix spelling of: above, already, anonymous, associated,
authentication, bandwidth, because, between, blocks, calculate,
candidates, cautious, changelog, cleaner, clipboard, command,
completely, concurrently, considered, constructs, corrupt, current,
daemon, dependencies, deprecated, directory, dispatcher, download,
eligible, ellipsis, encrypter, endpoint, entrieslist, essentially,
existing writers, existing, expires, filesystem, flushing, frequently,
hierarchy, however, implementation, implements, inaccurate,
individually, insensitive, longer, maximum, metadata, modified,
multipart, namedirfirst, nextcloud, obscured, opened, optional,
owncloud, pacific, passphrase, password, permanently, persimmon,
positive, potato, protocol, quota, receiving, recommends, referring,
requires, revisited, satisfied, satisfies, satisfy, semver,
serialized, session, storage, strategies, stringlist, successful,
supported, surprise, temporarily, temporary, transactions, unneeded,
update, uploads, wrapped
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2020-10-09 02:17:24 +02:00
|
|
|
stringList := make([]string, 0, len(tm.items))
|
2020-08-05 17:59:44 +02:00
|
|
|
for _, tr := range tm._sortedSlice() {
|
2023-02-27 17:46:12 +01:00
|
|
|
var what = tr.what
|
2020-06-13 20:37:42 +02:00
|
|
|
if exclude != nil {
|
|
|
|
exclude.mu.RLock()
|
2020-06-16 17:18:32 +02:00
|
|
|
_, found := exclude.items[tr.remote]
|
2020-06-13 20:37:42 +02:00
|
|
|
exclude.mu.RUnlock()
|
|
|
|
if found {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var out string
|
2020-06-16 17:18:32 +02:00
|
|
|
if acc := progress.get(tr.remote); acc != nil {
|
2020-06-13 20:37:42 +02:00
|
|
|
out = acc.String()
|
2023-02-27 17:46:12 +01:00
|
|
|
if what != "" {
|
|
|
|
out += ", " + what
|
|
|
|
}
|
2020-06-13 20:37:42 +02:00
|
|
|
} else {
|
2023-02-06 11:30:22 +01:00
|
|
|
if what == "" {
|
|
|
|
what = tm.name
|
|
|
|
}
|
2020-06-13 20:37:42 +02:00
|
|
|
out = fmt.Sprintf("%*s: %s",
|
2020-11-05 12:33:32 +01:00
|
|
|
ci.StatsFileNameLength,
|
|
|
|
shortenName(tr.remote, ci.StatsFileNameLength),
|
2023-02-06 11:30:22 +01:00
|
|
|
what,
|
2020-06-13 20:37:42 +02:00
|
|
|
)
|
|
|
|
}
|
Spelling fixes
Fix spelling of: above, already, anonymous, associated,
authentication, bandwidth, because, between, blocks, calculate,
candidates, cautious, changelog, cleaner, clipboard, command,
completely, concurrently, considered, constructs, corrupt, current,
daemon, dependencies, deprecated, directory, dispatcher, download,
eligible, ellipsis, encrypter, endpoint, entrieslist, essentially,
existing writers, existing, expires, filesystem, flushing, frequently,
hierarchy, however, implementation, implements, inaccurate,
individually, insensitive, longer, maximum, metadata, modified,
multipart, namedirfirst, nextcloud, obscured, opened, optional,
owncloud, pacific, passphrase, password, permanently, persimmon,
positive, potato, protocol, quota, receiving, recommends, referring,
requires, revisited, satisfied, satisfies, satisfy, semver,
serialized, session, storage, strategies, stringlist, successful,
supported, surprise, temporarily, temporary, transactions, unneeded,
update, uploads, wrapped
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2020-10-09 02:17:24 +02:00
|
|
|
stringList = append(stringList, " * "+out)
|
2020-06-13 20:37:42 +02:00
|
|
|
}
|
Spelling fixes
Fix spelling of: above, already, anonymous, associated,
authentication, bandwidth, because, between, blocks, calculate,
candidates, cautious, changelog, cleaner, clipboard, command,
completely, concurrently, considered, constructs, corrupt, current,
daemon, dependencies, deprecated, directory, dispatcher, download,
eligible, ellipsis, encrypter, endpoint, entrieslist, essentially,
existing writers, existing, expires, filesystem, flushing, frequently,
hierarchy, however, implementation, implements, inaccurate,
individually, insensitive, longer, maximum, metadata, modified,
multipart, namedirfirst, nextcloud, obscured, opened, optional,
owncloud, pacific, passphrase, password, permanently, persimmon,
positive, potato, protocol, quota, receiving, recommends, referring,
requires, revisited, satisfied, satisfies, satisfy, semver,
serialized, session, storage, strategies, stringlist, successful,
supported, surprise, temporarily, temporary, transactions, unneeded,
update, uploads, wrapped
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2020-10-09 02:17:24 +02:00
|
|
|
return strings.Join(stringList, "\n")
|
2020-06-13 20:37:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// progress returns total bytes read as well as the size.
|
|
|
|
func (tm *transferMap) progress(stats *StatsInfo) (totalBytes, totalSize int64) {
|
|
|
|
tm.mu.RLock()
|
|
|
|
defer tm.mu.RUnlock()
|
|
|
|
for name := range tm.items {
|
|
|
|
if acc := stats.inProgress.get(name); acc != nil {
|
|
|
|
bytes, size := acc.progress()
|
|
|
|
if size >= 0 && bytes >= 0 {
|
|
|
|
totalBytes += bytes
|
|
|
|
totalSize += size
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return totalBytes, totalSize
|
|
|
|
}
|
2020-08-05 17:59:44 +02:00
|
|
|
|
|
|
|
// remotes returns a []string of the remote names for the transferMap
|
|
|
|
func (tm *transferMap) remotes() (c []string) {
|
|
|
|
tm.mu.RLock()
|
|
|
|
defer tm.mu.RUnlock()
|
|
|
|
for _, tr := range tm._sortedSlice() {
|
|
|
|
c = append(c, tr.remote)
|
|
|
|
}
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
// rcStats returns a []rc.Params of the stats for the transferMap
|
|
|
|
func (tm *transferMap) rcStats(progress *inProgress) (t []rc.Params) {
|
|
|
|
tm.mu.RLock()
|
|
|
|
defer tm.mu.RUnlock()
|
|
|
|
for _, tr := range tm._sortedSlice() {
|
2024-01-18 17:44:13 +01:00
|
|
|
out := tr.rcStats() // basic stats
|
2020-08-05 17:59:44 +02:00
|
|
|
if acc := progress.get(tr.remote); acc != nil {
|
2024-01-18 17:44:13 +01:00
|
|
|
acc.rcStats(out) // add extended stats if have acc
|
2020-08-05 17:59:44 +02:00
|
|
|
}
|
2024-01-18 17:44:13 +01:00
|
|
|
t = append(t, out)
|
2020-08-05 17:59:44 +02:00
|
|
|
}
|
|
|
|
return t
|
|
|
|
}
|