lib/model: Return index from deviceActivity.leastBusy

This way, we don't need a second loop over the Availabilities to remove
the selected item.
This commit is contained in:
greatroar 2021-11-10 19:56:29 +01:00 committed by Jakob Borg
parent b84ee4d240
commit 6a9716e8a1
3 changed files with 26 additions and 35 deletions

View File

@ -26,20 +26,19 @@ func newDeviceActivity() *deviceActivity {
}
}
func (m *deviceActivity) leastBusy(availability []Availability) (Availability, bool) {
// Returns the index of the least busy device, or -1 if all are too busy.
func (m *deviceActivity) leastBusy(availability []Availability) int {
m.mut.Lock()
low := 2<<30 - 1
found := false
var selected Availability
for _, info := range availability {
if usage := m.act[info.ID]; usage < low {
best := -1
for i := range availability {
if usage := m.act[availability[i].ID]; usage < low {
low = usage
selected = info
found = true
best = i
}
}
m.mut.Unlock()
return selected, found
return best
}
func (m *deviceActivity) using(availability Availability) {

View File

@ -19,42 +19,42 @@ func TestDeviceActivity(t *testing.T) {
devices := []Availability{n0, n1, n2}
na := newDeviceActivity()
if lb, ok := na.leastBusy(devices); !ok || lb != n0 {
if lb := na.leastBusy(devices); lb != 0 {
t.Errorf("Least busy device should be n0 (%v) not %v", n0, lb)
}
if lb, ok := na.leastBusy(devices); !ok || lb != n0 {
if lb := na.leastBusy(devices); lb != 0 {
t.Errorf("Least busy device should still be n0 (%v) not %v", n0, lb)
}
lb, _ := na.leastBusy(devices)
na.using(lb)
if lb, ok := na.leastBusy(devices); !ok || lb != n1 {
lb := na.leastBusy(devices)
na.using(devices[lb])
if lb := na.leastBusy(devices); lb != 1 {
t.Errorf("Least busy device should be n1 (%v) not %v", n1, lb)
}
lb, _ = na.leastBusy(devices)
na.using(lb)
if lb, ok := na.leastBusy(devices); !ok || lb != n2 {
lb = na.leastBusy(devices)
na.using(devices[lb])
if lb := na.leastBusy(devices); lb != 2 {
t.Errorf("Least busy device should be n2 (%v) not %v", n2, lb)
}
lb, _ = na.leastBusy(devices)
na.using(lb)
if lb, ok := na.leastBusy(devices); !ok || lb != n0 {
lb = na.leastBusy(devices)
na.using(devices[lb])
if lb := na.leastBusy(devices); lb != 0 {
t.Errorf("Least busy device should be n0 (%v) not %v", n0, lb)
}
na.done(n1)
if lb, ok := na.leastBusy(devices); !ok || lb != n1 {
if lb := na.leastBusy(devices); lb != 1 {
t.Errorf("Least busy device should be n1 (%v) not %v", n1, lb)
}
na.done(n2)
if lb, ok := na.leastBusy(devices); !ok || lb != n1 {
if lb := na.leastBusy(devices); lb != 1 {
t.Errorf("Least busy device should still be n1 (%v) not %v", n1, lb)
}
na.done(n0)
if lb, ok := na.leastBusy(devices); !ok || lb != n0 {
if lb := na.leastBusy(devices); lb != 0 {
t.Errorf("Least busy device should be n0 (%v) not %v", n0, lb)
}
}

View File

@ -1532,8 +1532,8 @@ loop:
// Select the least busy device to pull the block from. If we found no
// feasible device at all, fail the block (and in the long run, the
// file).
selected, found := activity.leastBusy(candidates)
if !found {
found := activity.leastBusy(candidates)
if found == -1 {
if lastError != nil {
state.fail(errors.Wrap(lastError, "pull"))
} else {
@ -1542,7 +1542,9 @@ loop:
break
}
candidates = removeAvailability(candidates, selected)
selected := candidates[found]
candidates[found] = candidates[len(candidates)-1]
candidates = candidates[:len(candidates)-1]
// Fetch the block, while marking the selected device as in use so that
// leastBusy can select another device when someone else asks.
@ -1804,16 +1806,6 @@ func (f *sendReceiveFolder) inConflict(current, replacement protocol.Vector) boo
return false
}
func removeAvailability(availabilities []Availability, availability Availability) []Availability {
for i := range availabilities {
if availabilities[i] == availability {
availabilities[i] = availabilities[len(availabilities)-1]
return availabilities[:len(availabilities)-1]
}
}
return availabilities
}
func (f *sendReceiveFolder) moveForConflict(name, lastModBy string, scanChan chan<- string) error {
if isConflict(name) {
l.Infoln("Conflict for", name, "which is already a conflict copy; not copying again.")