73 lines
1.7 KiB
Go
73 lines
1.7 KiB
Go
|
package accounting
|
||
|
|
||
|
import (
|
||
|
"io"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"github.com/ncw/rclone/fs"
|
||
|
)
|
||
|
|
||
|
// Transfer keeps track of initiated transfers and provides access to
|
||
|
// accounting functions.
|
||
|
// Transfer needs to be closed on completion.
|
||
|
type Transfer struct {
|
||
|
stats *StatsInfo
|
||
|
acc *Account
|
||
|
remote string
|
||
|
size int64
|
||
|
|
||
|
mu sync.Mutex
|
||
|
startedAt time.Time
|
||
|
completedAt time.Time
|
||
|
}
|
||
|
|
||
|
// newTransfer instantiates new transfer
|
||
|
func newTransfer(stats *StatsInfo, obj fs.Object) *Transfer {
|
||
|
return newTransferRemoteSize(stats, obj.Remote(), obj.Size())
|
||
|
}
|
||
|
|
||
|
func newTransferRemoteSize(stats *StatsInfo, remote string, size int64) *Transfer {
|
||
|
tr := &Transfer{
|
||
|
stats: stats,
|
||
|
remote: remote,
|
||
|
size: size,
|
||
|
startedAt: time.Now(),
|
||
|
}
|
||
|
stats.AddTransfer(tr)
|
||
|
return tr
|
||
|
}
|
||
|
|
||
|
// Done ends the transfer.
|
||
|
// Must be called after transfer is finished to run proper cleanups.
|
||
|
func (tr *Transfer) Done(err error) {
|
||
|
if err != nil {
|
||
|
tr.stats.Error(err)
|
||
|
}
|
||
|
if tr.acc != nil {
|
||
|
if err := tr.acc.Close(); err != nil {
|
||
|
fs.LogLevelPrintf(fs.Config.StatsLogLevel, nil, "can't close account: %+v\n", err)
|
||
|
}
|
||
|
}
|
||
|
tr.stats.DoneTransferring(tr.remote, err == nil)
|
||
|
tr.mu.Lock()
|
||
|
tr.completedAt = time.Now()
|
||
|
tr.mu.Unlock()
|
||
|
}
|
||
|
|
||
|
// Account returns reader that knows how to keep track of transfer progress.
|
||
|
func (tr *Transfer) Account(in io.ReadCloser) *Account {
|
||
|
if tr.acc != nil {
|
||
|
return tr.acc
|
||
|
}
|
||
|
return newAccountSizeName(tr.stats, in, tr.size, tr.remote)
|
||
|
}
|
||
|
|
||
|
// TimeRange returns the time transfer started and ended at. If not completed
|
||
|
// it will return zero time for end time.
|
||
|
func (tr *Transfer) TimeRange() (time.Time, time.Time) {
|
||
|
tr.mu.Lock()
|
||
|
defer tr.mu.Unlock()
|
||
|
return tr.startedAt, tr.completedAt
|
||
|
}
|