mirror of
https://github.com/syncthing/syncthing.git
synced 2024-11-16 18:41:59 -07:00
86ca58e2a9
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3055
116 lines
2.8 KiB
Go
116 lines
2.8 KiB
Go
// Copyright (C) 2015 The Protocol Authors.
|
|
|
|
package protocol
|
|
|
|
// 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
|
|
// new allocated Vector with the modified contents.
|
|
type Vector []Counter
|
|
|
|
// Counter represents a single counter in the version vector.
|
|
type Counter struct {
|
|
ID ShortID
|
|
Value uint64
|
|
}
|
|
|
|
// Update returns a Vector with the index for the specific ID incremented by
|
|
// 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 {
|
|
for i := range v {
|
|
if v[i].ID == id {
|
|
// Update an existing index
|
|
v[i].Value++
|
|
return v
|
|
} else if v[i].ID > id {
|
|
// Insert a new index
|
|
nv := make(Vector, len(v)+1)
|
|
copy(nv, v[:i])
|
|
nv[i].ID = id
|
|
nv[i].Value = 1
|
|
copy(nv[i+1:], v[i:])
|
|
return nv
|
|
}
|
|
}
|
|
// Append a new index
|
|
return append(v, Counter{id, 1})
|
|
}
|
|
|
|
// Merge returns the vector containing the maximum indexes from v and b. 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) Merge(b Vector) Vector {
|
|
var vi, bi int
|
|
for bi < len(b) {
|
|
if vi == len(v) {
|
|
// We've reach the end of v, all that remains are appends
|
|
return append(v, b[bi:]...)
|
|
}
|
|
|
|
if v[vi].ID > b[bi].ID {
|
|
// The index from b should be inserted here
|
|
n := make(Vector, len(v)+1)
|
|
copy(n, v[:vi])
|
|
n[vi] = b[bi]
|
|
copy(n[vi+1:], v[vi:])
|
|
v = n
|
|
}
|
|
|
|
if v[vi].ID == b[bi].ID {
|
|
if val := b[bi].Value; val > v[vi].Value {
|
|
v[vi].Value = val
|
|
}
|
|
}
|
|
|
|
if bi < len(b) && v[vi].ID == b[bi].ID {
|
|
bi++
|
|
}
|
|
vi++
|
|
}
|
|
|
|
return v
|
|
}
|
|
|
|
// Copy returns an identical vector that is not shared with v.
|
|
func (v Vector) Copy() Vector {
|
|
nv := make(Vector, len(v))
|
|
copy(nv, v)
|
|
return nv
|
|
}
|
|
|
|
// Equal returns true when the two vectors are equivalent.
|
|
func (v Vector) Equal(b Vector) bool {
|
|
return v.Compare(b) == Equal
|
|
}
|
|
|
|
// LesserEqual returns true when the two vectors are equivalent or v is Lesser
|
|
// than b.
|
|
func (v Vector) LesserEqual(b Vector) bool {
|
|
comp := v.Compare(b)
|
|
return comp == Lesser || comp == Equal
|
|
}
|
|
|
|
// GreaterEqual returns true when the two vectors are equivalent or v is Greater
|
|
// than b.
|
|
func (v Vector) GreaterEqual(b Vector) bool {
|
|
comp := v.Compare(b)
|
|
return comp == Greater || comp == Equal
|
|
}
|
|
|
|
// Concurrent returns true when the two vectors are concurrent.
|
|
func (v Vector) Concurrent(b Vector) bool {
|
|
comp := v.Compare(b)
|
|
return comp == ConcurrentGreater || comp == ConcurrentLesser
|
|
}
|
|
|
|
// Counter returns the current value of the given counter ID.
|
|
func (v Vector) Counter(id ShortID) uint64 {
|
|
for _, c := range v {
|
|
if c.ID == id {
|
|
return c.Value
|
|
}
|
|
}
|
|
return 0
|
|
}
|