Преглед на файлове

lib/model: Return index from deviceActivity.leastBusy

This way, we don't need a second loop over the Availabilities to remove
the selected item.
greatroar преди 4 години
родител
ревизия
6a9716e8a1
променени са 3 файла, в които са добавени 26 реда и са изтрити 35 реда
  1. 7 8
      lib/model/deviceactivity.go
  2. 14 14
      lib/model/deviceactivity_test.go
  3. 5 13
      lib/model/folder_sendrecv.go

+ 7 - 8
lib/model/deviceactivity.go

@@ -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) {

+ 14 - 14
lib/model/deviceactivity_test.go

@@ -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)
 	}
 }

+ 5 - 13
lib/model/folder_sendrecv.go

@@ -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.")