diff --git a/lib/db/leveldb_transactions.go b/lib/db/leveldb_transactions.go index 8838bc1a..48f07638 100644 --- a/lib/db/leveldb_transactions.go +++ b/lib/db/leveldb_transactions.go @@ -160,22 +160,30 @@ insert: fl.Versions = append(fl.Versions, nv) insertedAt = len(fl.Versions) - 1 } - - if insertedAt == 0 { - // We just inserted a new newest version. Fixup the global size - // calculation. - if !file.Version.Equal(oldFile.Version) || file.Invalid != oldFile.Invalid { + // Fixup the global size calculation. + if hasOldFile { + // We removed the previous newest version + meta.removeFile(globalDeviceID, oldFile) + if insertedAt == 0 { + // inserted a new newest version meta.addFile(globalDeviceID, file) - if hasOldFile { - // We have the old file that was removed at the head of the list. + } else { + // The previous second version is now the first + if newGlobal, ok := t.getFile(folder, fl.Versions[0].Device, name); ok { + // A failure to get the file here is surprising and our + // global size data will be incorrect until a restart... + meta.addFile(globalDeviceID, newGlobal) + } + } + } else if insertedAt == 0 { + // We just inserted a new newest version. + meta.addFile(globalDeviceID, file) + if len(fl.Versions) > 1 { + // The previous newest version is now at index 1, grab it from there. + if oldFile, ok := t.getFile(folder, fl.Versions[1].Device, name); ok { + // A failure to get the file here is surprising and our + // global size data will be incorrect until a restart... meta.removeFile(globalDeviceID, oldFile) - } else if len(fl.Versions) > 1 { - // The previous newest version is now at index 1, grab it from there. - if oldFile, ok := t.getFile(folder, fl.Versions[1].Device, name); ok { - // A failure to get the file here is surprising and our - // global size data will be incorrect until a restart... - meta.removeFile(globalDeviceID, oldFile) - } } } } diff --git a/lib/db/set_test.go b/lib/db/set_test.go index 7f8da0de..6c5afb65 100644 --- a/lib/db/set_test.go +++ b/lib/db/set_test.go @@ -937,6 +937,66 @@ func TestIssue4925(t *testing.T) { } } +func TestMoveGlobalBack(t *testing.T) { + ldb := db.OpenMemory() + + folder := "test" + file := "foo" + s := db.NewFileSet(folder, fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb) + + localHave := fileList{{Name: file, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1}}}, Blocks: genBlocks(1), ModifiedS: 10, Size: 1}} + remote0Have := fileList{{Name: file, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1}, {ID: remoteDevice0.Short(), Value: 1}}}, Blocks: genBlocks(2), ModifiedS: 0, Size: 2}} + + s.Update(protocol.LocalDeviceID, localHave) + s.Update(remoteDevice0, remote0Have) + + if need := needList(s, protocol.LocalDeviceID); len(need) != 1 { + t.Error("Expected 1 local need, got", need) + } else if !need[0].IsEquivalent(remote0Have[0], false, false) { + t.Errorf("Local need incorrect;\n A: %v !=\n E: %v", need[0], remote0Have[0]) + } + + if need := needList(s, remoteDevice0); len(need) != 0 { + t.Error("Expected no need for remote 0, got", need) + } + + ls := s.LocalSize() + if haveBytes := localHave[0].Size; ls.Bytes != haveBytes { + t.Errorf("Incorrect LocalSize bytes; %d != %d", ls.Bytes, haveBytes) + } + + gs := s.GlobalSize() + if globalBytes := remote0Have[0].Size; gs.Bytes != globalBytes { + t.Errorf("Incorrect GlobalSize bytes; %d != %d", gs.Bytes, globalBytes) + } + + // That's what happens when something becomes unignored or something. + // In any case it will be moved back from first spot in the global list + // which is the scenario to be tested here. + remote0Have[0].Version = remote0Have[0].Version.Update(remoteDevice0.Short()).DropOthers(remoteDevice0.Short()) + s.Update(remoteDevice0, remote0Have) + + if need := needList(s, remoteDevice0); len(need) != 1 { + t.Error("Expected 1 need for remote 0, got", need) + } else if !need[0].IsEquivalent(localHave[0], false, false) { + t.Errorf("Need for remote 0 incorrect;\n A: %v !=\n E: %v", need[0], localHave[0]) + } + + if need := needList(s, protocol.LocalDeviceID); len(need) != 0 { + t.Error("Expected no local need, got", need) + } + + ls = s.LocalSize() + if haveBytes := localHave[0].Size; ls.Bytes != haveBytes { + t.Errorf("Incorrect LocalSize bytes; %d != %d", ls.Bytes, haveBytes) + } + + gs = s.GlobalSize() + if globalBytes := localHave[0].Size; gs.Bytes != globalBytes { + t.Errorf("Incorrect GlobalSize bytes; %d != %d", gs.Bytes, globalBytes) + } +} + func replace(fs *db.FileSet, device protocol.DeviceID, files []protocol.FileInfo) { fs.Drop(device) fs.Update(device, files)