mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-22 19:08:58 +00:00
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:
parent
b84ee4d240
commit
6a9716e8a1
@ -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()
|
m.mut.Lock()
|
||||||
low := 2<<30 - 1
|
low := 2<<30 - 1
|
||||||
found := false
|
best := -1
|
||||||
var selected Availability
|
for i := range availability {
|
||||||
for _, info := range availability {
|
if usage := m.act[availability[i].ID]; usage < low {
|
||||||
if usage := m.act[info.ID]; usage < low {
|
|
||||||
low = usage
|
low = usage
|
||||||
selected = info
|
best = i
|
||||||
found = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.mut.Unlock()
|
m.mut.Unlock()
|
||||||
return selected, found
|
return best
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *deviceActivity) using(availability Availability) {
|
func (m *deviceActivity) using(availability Availability) {
|
||||||
|
@ -19,42 +19,42 @@ func TestDeviceActivity(t *testing.T) {
|
|||||||
devices := []Availability{n0, n1, n2}
|
devices := []Availability{n0, n1, n2}
|
||||||
na := newDeviceActivity()
|
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)
|
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)
|
t.Errorf("Least busy device should still be n0 (%v) not %v", n0, lb)
|
||||||
}
|
}
|
||||||
|
|
||||||
lb, _ := na.leastBusy(devices)
|
lb := na.leastBusy(devices)
|
||||||
na.using(lb)
|
na.using(devices[lb])
|
||||||
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)
|
t.Errorf("Least busy device should be n1 (%v) not %v", n1, lb)
|
||||||
}
|
}
|
||||||
lb, _ = na.leastBusy(devices)
|
lb = na.leastBusy(devices)
|
||||||
na.using(lb)
|
na.using(devices[lb])
|
||||||
if lb, ok := na.leastBusy(devices); !ok || lb != n2 {
|
if lb := na.leastBusy(devices); lb != 2 {
|
||||||
t.Errorf("Least busy device should be n2 (%v) not %v", n2, lb)
|
t.Errorf("Least busy device should be n2 (%v) not %v", n2, lb)
|
||||||
}
|
}
|
||||||
|
|
||||||
lb, _ = na.leastBusy(devices)
|
lb = na.leastBusy(devices)
|
||||||
na.using(lb)
|
na.using(devices[lb])
|
||||||
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)
|
t.Errorf("Least busy device should be n0 (%v) not %v", n0, lb)
|
||||||
}
|
}
|
||||||
|
|
||||||
na.done(n1)
|
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)
|
t.Errorf("Least busy device should be n1 (%v) not %v", n1, lb)
|
||||||
}
|
}
|
||||||
|
|
||||||
na.done(n2)
|
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)
|
t.Errorf("Least busy device should still be n1 (%v) not %v", n1, lb)
|
||||||
}
|
}
|
||||||
|
|
||||||
na.done(n0)
|
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)
|
t.Errorf("Least busy device should be n0 (%v) not %v", n0, lb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1532,8 +1532,8 @@ loop:
|
|||||||
// Select the least busy device to pull the block from. If we found no
|
// 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
|
// feasible device at all, fail the block (and in the long run, the
|
||||||
// file).
|
// file).
|
||||||
selected, found := activity.leastBusy(candidates)
|
found := activity.leastBusy(candidates)
|
||||||
if !found {
|
if found == -1 {
|
||||||
if lastError != nil {
|
if lastError != nil {
|
||||||
state.fail(errors.Wrap(lastError, "pull"))
|
state.fail(errors.Wrap(lastError, "pull"))
|
||||||
} else {
|
} else {
|
||||||
@ -1542,7 +1542,9 @@ loop:
|
|||||||
break
|
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
|
// Fetch the block, while marking the selected device as in use so that
|
||||||
// leastBusy can select another device when someone else asks.
|
// leastBusy can select another device when someone else asks.
|
||||||
@ -1804,16 +1806,6 @@ func (f *sendReceiveFolder) inConflict(current, replacement protocol.Vector) boo
|
|||||||
return false
|
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 {
|
func (f *sendReceiveFolder) moveForConflict(name, lastModBy string, scanChan chan<- string) error {
|
||||||
if isConflict(name) {
|
if isConflict(name) {
|
||||||
l.Infoln("Conflict for", name, "which is already a conflict copy; not copying again.")
|
l.Infoln("Conflict for", name, "which is already a conflict copy; not copying again.")
|
||||||
|
Loading…
Reference in New Issue
Block a user