lib/model: Fix wild completion percentages

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3188
This commit is contained in:
Audrius Butkevicius 2016-05-26 06:53:27 +00:00 committed by Jakob Borg
parent 72154aa668
commit fc173bf679
2 changed files with 36 additions and 28 deletions

View File

@ -25,7 +25,6 @@ type deviceFolderFileDownloadState struct {
type deviceFolderDownloadState struct { type deviceFolderDownloadState struct {
mut sync.RWMutex mut sync.RWMutex
files map[string]deviceFolderFileDownloadState files map[string]deviceFolderFileDownloadState
numberOfBlocksInProgress int
} }
// Has returns whether a block at that specific index, and that specific version of the file // Has returns whether a block at that specific index, and that specific version of the file
@ -57,7 +56,6 @@ func (p *deviceFolderDownloadState) Update(updates []protocol.FileDownloadProgre
for _, update := range updates { for _, update := range updates {
local, ok := p.files[update.Name] local, ok := p.files[update.Name]
if update.UpdateType == protocol.UpdateTypeForget && ok && local.version.Equal(update.Version) { if update.UpdateType == protocol.UpdateTypeForget && ok && local.version.Equal(update.Version) {
p.numberOfBlocksInProgress -= len(local.blockIndexes)
delete(p.files, update.Name) delete(p.files, update.Name)
} else if update.UpdateType == protocol.UpdateTypeAppend { } else if update.UpdateType == protocol.UpdateTypeAppend {
if !ok { if !ok {
@ -66,25 +64,25 @@ func (p *deviceFolderDownloadState) Update(updates []protocol.FileDownloadProgre
version: update.Version, version: update.Version,
} }
} else if !local.version.Equal(update.Version) { } else if !local.version.Equal(update.Version) {
p.numberOfBlocksInProgress -= len(local.blockIndexes)
local.blockIndexes = append(local.blockIndexes[:0], update.BlockIndexes...) local.blockIndexes = append(local.blockIndexes[:0], update.BlockIndexes...)
local.version = update.Version local.version = update.Version
} else { } else {
local.blockIndexes = append(local.blockIndexes, update.BlockIndexes...) local.blockIndexes = append(local.blockIndexes, update.BlockIndexes...)
} }
p.files[update.Name] = local p.files[update.Name] = local
p.numberOfBlocksInProgress += len(update.BlockIndexes)
} }
} }
} }
// NumberOfBlocksInProgress returns the number of blocks the device has downloaded // GetBlockCounts returns a map filename -> number of blocks downloaded.
// for a specific folder. func (p *deviceFolderDownloadState) GetBlockCounts() map[string]int {
func (p *deviceFolderDownloadState) NumberOfBlocksInProgress() int {
p.mut.RLock() p.mut.RLock()
n := p.numberOfBlocksInProgress res := make(map[string]int, len(p.files))
for name, state := range p.files {
res[name] = len(state.blockIndexes)
}
p.mut.RUnlock() p.mut.RUnlock()
return n return res
} }
// deviceDownloadState represents the state of all in progress downloads // deviceDownloadState represents the state of all in progress downloads
@ -134,20 +132,21 @@ func (t *deviceDownloadState) Has(folder, file string, version protocol.Vector,
return f.Has(file, version, index) return f.Has(file, version, index)
} }
// NumberOfBlocksInProgress returns the number of blocks the device has downloaded // GetBlockCounts returns a map filename -> number of blocks downloaded for the
// for all folders. // given folder.
func (t *deviceDownloadState) NumberOfBlocksInProgress() int { func (t *deviceDownloadState) GetBlockCounts(folder string) map[string]int {
if t == nil { if t == nil {
return 0 return nil
} }
n := 0
t.mut.RLock() t.mut.RLock()
for _, folder := range t.folders { for name, state := range t.folders {
n += folder.NumberOfBlocksInProgress() if name == folder {
return state.GetBlockCounts()
}
} }
t.mut.RUnlock() t.mut.RUnlock()
return n return nil
} }
func newDeviceDownloadState() *deviceDownloadState { func newDeviceDownloadState() *deviceDownloadState {

View File

@ -374,16 +374,25 @@ func (m *Model) Completion(device protocol.DeviceID, folder string) float64 {
return 100 // Folder is empty, so we have all of it return 100 // Folder is empty, so we have all of it
} }
var need int64 m.pmut.RLock()
counts := m.deviceDownloads[device].GetBlockCounts(folder)
m.pmut.RUnlock()
var need, fileNeed, downloaded int64
rf.WithNeedTruncated(device, func(f db.FileIntf) bool { rf.WithNeedTruncated(device, func(f db.FileIntf) bool {
need += f.Size() ft := f.(db.FileInfoTruncated)
return true
})
// This might might be more than it really is, because some blocks can be of a smaller size. // This might might be more than it really is, because some blocks can be of a smaller size.
m.pmut.RLock() downloaded = int64(counts[ft.Name] * protocol.BlockSize)
need -= int64(m.deviceDownloads[device].NumberOfBlocksInProgress() * protocol.BlockSize)
m.pmut.RUnlock() fileNeed = ft.Size() - downloaded
if fileNeed < 0 {
fileNeed = 0
}
need += fileNeed
return true
})
needRatio := float64(need) / float64(tot) needRatio := float64(need) / float64(tot)
completionPct := 100 * (1 - needRatio) completionPct := 100 * (1 - needRatio)
@ -1083,13 +1092,13 @@ func (m *Model) DownloadProgress(device protocol.DeviceID, folder string, update
m.pmut.RLock() m.pmut.RLock()
m.deviceDownloads[device].Update(folder, updates) m.deviceDownloads[device].Update(folder, updates)
blocks := m.deviceDownloads[device].NumberOfBlocksInProgress() state := m.deviceDownloads[device].GetBlockCounts(folder)
m.pmut.RUnlock() m.pmut.RUnlock()
events.Default.Log(events.RemoteDownloadProgress, map[string]interface{}{ events.Default.Log(events.RemoteDownloadProgress, map[string]interface{}{
"device": device.String(), "device": device.String(),
"folder": folder, "folder": folder,
"blocks": blocks, "state": state,
}) })
} }