Browse Source

lib/model: Prevent duplicate need count on recalculating metadata (#6964)

Simon Frei 5 years ago
parent
commit
ecc24428ac
2 changed files with 40 additions and 4 deletions
  1. 30 0
      lib/db/db_test.go
  2. 10 4
      lib/db/meta.go

+ 30 - 0
lib/db/db_test.go

@@ -918,6 +918,36 @@ func TestCheckLocalNeed(t *testing.T) {
 	checkNeed()
 }
 
+func TestDuplicateNeedCount(t *testing.T) {
+	db := NewLowlevel(backend.OpenMemory())
+	defer db.Close()
+
+	folder := "test"
+	testFs := fs.NewFilesystem(fs.FilesystemTypeFake, "")
+
+	fs := NewFileSet(folder, testFs, db)
+	files := []protocol.FileInfo{{Name: "foo", Version: protocol.Vector{}.Update(myID), Sequence: 1}}
+	fs.Update(protocol.LocalDeviceID, files)
+	files[0].Version = files[0].Version.Update(remoteDevice0.Short())
+	fs.Update(remoteDevice0, files)
+
+	db.CheckRepair()
+
+	fs = NewFileSet(folder, testFs, db)
+	found := false
+	for _, c := range fs.meta.counts.Counts {
+		if bytes.Equal(protocol.LocalDeviceID[:], c.DeviceID) && c.LocalFlags == needFlag {
+			if found {
+				t.Fatal("second need count for local device encountered")
+			}
+			found = true
+		}
+	}
+	if !found {
+		t.Fatal("no need count for local device encountered")
+	}
+}
+
 func numBlockLists(db *Lowlevel) (int, error) {
 	it, err := db.Backend.NewPrefixIterator([]byte{KeyTypeBlockList})
 	if err != nil {

+ 10 - 4
lib/db/meta.go

@@ -198,18 +198,24 @@ func (m *metadataTracker) updateFileLocked(dev protocol.DeviceID, f protocol.Fil
 	}
 }
 
-// emptyNeeded makes sure there is a zero counts in case the device needs nothing.
+// emptyNeeded ensures that there is a need count for the given device and that it is empty.
 func (m *metadataTracker) emptyNeeded(dev protocol.DeviceID) {
 	m.mut.Lock()
 	defer m.mut.Unlock()
 
 	m.dirty = true
 
-	m.indexes[metaKey{dev, needFlag}] = len(m.counts.Counts)
-	m.counts.Counts = append(m.counts.Counts, Counts{
+	empty := Counts{
 		DeviceID:   dev[:],
 		LocalFlags: needFlag,
-	})
+	}
+	key := metaKey{dev, needFlag}
+	if idx, ok := m.indexes[key]; ok {
+		m.counts.Counts[idx] = empty
+		return
+	}
+	m.indexes[key] = len(m.counts.Counts)
+	m.counts.Counts = append(m.counts.Counts, empty)
 }
 
 // addNeeded adds a file to the needed counts