diff --git a/lib/model/folder_sendrecv.go b/lib/model/folder_sendrecv.go index 6ff984f23..7834ee7c7 100644 --- a/lib/model/folder_sendrecv.go +++ b/lib/model/folder_sendrecv.go @@ -505,13 +505,10 @@ nextFile: continue nextFile } - devices := snap.Availability(fileName) - for _, dev := range devices { - if f.model.ConnectedTo(dev) { - // Handle the file normally, by copying and pulling, etc. - f.handleFile(fi, snap, copyChan) - continue nextFile - } + devices := f.model.fileAvailability(f.FolderConfiguration, snap, fi) + if len(devices) > 0 { + f.handleFile(fi, snap, copyChan) + continue } f.newPullError(fileName, errNotAvailable) f.queue.Done(fileName) @@ -1547,7 +1544,7 @@ func (f *sendReceiveFolder) pullBlock(state pullBlockState, snap *db.Snapshot, o } var lastError error - candidates := f.model.availabilityInSnapshot(f.FolderConfiguration, snap, state.file, state.block) + candidates := f.model.blockAvailability(f.FolderConfiguration, snap, state.file, state.block) loop: for { select { diff --git a/lib/model/model.go b/lib/model/model.go index b4ee3925e..3615eca16 100644 --- a/lib/model/model.go +++ b/lib/model/model.go @@ -2882,16 +2882,31 @@ func (m *model) Availability(folder string, file protocol.FileInfo, block protoc } defer snap.Release() - return m.availabilityInSnapshotRLocked(cfg, snap, file, block), nil + return m.blockAvailabilityRLocked(cfg, snap, file, block), nil } -func (m *model) availabilityInSnapshot(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo, block protocol.BlockInfo) []Availability { +func (m *model) blockAvailability(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo, block protocol.BlockInfo) []Availability { m.mut.RLock() defer m.mut.RUnlock() - return m.availabilityInSnapshotRLocked(cfg, snap, file, block) + return m.blockAvailabilityRLocked(cfg, snap, file, block) } -func (m *model) availabilityInSnapshotRLocked(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo, block protocol.BlockInfo) []Availability { +func (m *model) blockAvailabilityRLocked(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo, block protocol.BlockInfo) []Availability { + var candidates []Availability + + candidates = append(candidates, m.fileAvailabilityRLocked(cfg, snap, file)...) + candidates = append(candidates, m.blockAvailabilityFromTemporaryRLocked(cfg, file, block)...) + + return candidates +} + +func (m *model) fileAvailability(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo) []Availability { + m.mut.RLock() + defer m.mut.RUnlock() + return m.fileAvailabilityRLocked(cfg, snap, file) +} + +func (m *model) fileAvailabilityRLocked(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo) []Availability { var availabilities []Availability for _, device := range snap.Availability(file.Name) { if _, ok := m.remoteFolderStates[device]; !ok { @@ -2905,13 +2920,16 @@ func (m *model) availabilityInSnapshotRLocked(cfg config.FolderConfiguration, sn availabilities = append(availabilities, Availability{ID: device, FromTemporary: false}) } } + return availabilities +} +func (m *model) blockAvailabilityFromTemporaryRLocked(cfg config.FolderConfiguration, file protocol.FileInfo, block protocol.BlockInfo) []Availability { + var availabilities []Availability for _, device := range cfg.Devices { if m.deviceDownloads[device.DeviceID].Has(cfg.ID, file.Name, file.Version, int(block.Offset/int64(file.BlockSize()))) { availabilities = append(availabilities, Availability{ID: device.DeviceID, FromTemporary: true}) } } - return availabilities }