diff --git a/lib/model/folder.go b/lib/model/folder.go index 15595bac1..bacd58cec 100644 --- a/lib/model/folder.go +++ b/lib/model/folder.go @@ -904,19 +904,8 @@ func (f *folder) emitDiskChangeEvents(fs []protocol.FileInfo, typeOfEvent events objType := "file" action := "modified" - switch { - case file.IsDeleted(): + if file.IsDeleted() { action = "deleted" - - // If our local vector is version 1 AND it is the only version - // vector so far seen for this file then it is a new file. Else if - // it is > 1 it's not new, and if it is 1 but another shortId - // version vector exists then it is new for us but created elsewhere - // so the file is still not new but modified by us. Only if it is - // truly new do we change this to 'added', else we leave it as - // 'modified'. - case len(file.Version.Counters) == 1 && file.Version.Counters[0].Value == 1: - action = "added" } if file.IsSymlink() { diff --git a/lib/protocol/vector.go b/lib/protocol/vector.go index 5b8dad2c4..f4d8662dd 100644 --- a/lib/protocol/vector.go +++ b/lib/protocol/vector.go @@ -2,6 +2,8 @@ package protocol +import "time" + // The Vector type represents a version vector. The zero value is a usable // version vector. The vector has slice semantics and some operations on it // are "append-like" in that they may return the same vector modified, or v @@ -13,23 +15,39 @@ package protocol // one. If it is possible, the vector v is updated and returned. If it is not, // a copy will be created, updated and returned. func (v Vector) Update(id ShortID) Vector { + now := uint64(time.Now().Unix()) + return v.updateWithNow(id, now) +} + +func (v Vector) updateWithNow(id ShortID, now uint64) Vector { for i := range v.Counters { if v.Counters[i].ID == id { // Update an existing index - v.Counters[i].Value++ + v.Counters[i].Value = max(v.Counters[i].Value+1, now) return v } else if v.Counters[i].ID > id { // Insert a new index nv := make([]Counter, len(v.Counters)+1) copy(nv, v.Counters[:i]) nv[i].ID = id - nv[i].Value = 1 + nv[i].Value = max(1, now) copy(nv[i+1:], v.Counters[i:]) return Vector{Counters: nv} } } + // Append a new index - return Vector{Counters: append(v.Counters, Counter{ID: id, Value: 1})} + return Vector{Counters: append(v.Counters, Counter{ + ID: id, + Value: max(1, now), + })} +} + +func max(a, b uint64) uint64 { + if a > b { + return a + } + return b } // Merge returns the vector containing the maximum indexes from v and b. If it diff --git a/lib/protocol/vector_test.go b/lib/protocol/vector_test.go index eb700d400..e1fb691cf 100644 --- a/lib/protocol/vector_test.go +++ b/lib/protocol/vector_test.go @@ -12,8 +12,8 @@ func TestUpdate(t *testing.T) { // Append - v = v.Update(42) - expected := Vector{Counters: []Counter{{ID: 42, Value: 1}}} + v = v.updateWithNow(42, 5) + expected := Vector{Counters: []Counter{{ID: 42, Value: 5}}} if v.Compare(expected) != Equal { t.Errorf("Update error, %+v != %+v", v, expected) @@ -21,17 +21,17 @@ func TestUpdate(t *testing.T) { // Insert at front - v = v.Update(36) - expected = Vector{Counters: []Counter{{ID: 36, Value: 1}, {ID: 42, Value: 1}}} + v = v.updateWithNow(36, 6) + expected = Vector{Counters: []Counter{{ID: 36, Value: 6}, {ID: 42, Value: 5}}} if v.Compare(expected) != Equal { t.Errorf("Update error, %+v != %+v", v, expected) } - // Insert in moddle + // Insert in middle - v = v.Update(37) - expected = Vector{Counters: []Counter{{ID: 36, Value: 1}, {ID: 37, Value: 1}, {ID: 42, Value: 1}}} + v = v.updateWithNow(37, 7) + expected = Vector{Counters: []Counter{{ID: 36, Value: 6}, {ID: 37, Value: 7}, {ID: 42, Value: 5}}} if v.Compare(expected) != Equal { t.Errorf("Update error, %+v != %+v", v, expected) @@ -39,8 +39,26 @@ func TestUpdate(t *testing.T) { // Update existing - v = v.Update(37) - expected = Vector{Counters: []Counter{{ID: 36, Value: 1}, {ID: 37, Value: 2}, {ID: 42, Value: 1}}} + v = v.updateWithNow(37, 1) + expected = Vector{Counters: []Counter{{ID: 36, Value: 6}, {ID: 37, Value: 8}, {ID: 42, Value: 5}}} + + if v.Compare(expected) != Equal { + t.Errorf("Update error, %+v != %+v", v, expected) + } + + // Update existing with higher current time + + v = v.updateWithNow(37, 100) + expected = Vector{Counters: []Counter{{ID: 36, Value: 6}, {ID: 37, Value: 100}, {ID: 42, Value: 5}}} + + if v.Compare(expected) != Equal { + t.Errorf("Update error, %+v != %+v", v, expected) + } + + // Update existing with lower current time + + v = v.updateWithNow(37, 50) + expected = Vector{Counters: []Counter{{ID: 36, Value: 6}, {ID: 37, Value: 101}, {ID: 42, Value: 5}}} if v.Compare(expected) != Equal { t.Errorf("Update error, %+v != %+v", v, expected)