syncthing/lib/protocol/vector.go

116 lines
2.8 KiB
Go
Raw Normal View History

2015-03-20 09:58:32 +01:00
// Copyright (C) 2015 The Protocol Authors.
package protocol
2015-09-22 21:51:05 +02:00
// The Vector type represents a version vector. The zero value is a usable
2015-03-20 09:58:32 +01:00
// version vector. The vector has slice semantics and some operations on it
2015-09-22 20:34:24 +02:00
// are "append-like" in that they may return the same vector modified, or v
2015-03-20 09:58:32 +01:00
// new allocated Vector with the modified contents.
type Vector []Counter
2015-09-22 21:51:05 +02:00
// Counter represents a single counter in the version vector.
2015-03-20 09:58:32 +01:00
type Counter struct {
ID ShortID
2015-03-20 09:58:32 +01:00
Value uint64
}
2015-09-22 21:51:05 +02:00
// Update returns a Vector with the index for the specific ID incremented by
2015-03-20 09:58:32 +01:00
// one. If it is possible, the vector v is updated and returned. If it is not,
2015-09-22 21:51:05 +02:00
// a copy will be created, updated and returned.
func (v Vector) Update(id ShortID) Vector {
2015-03-20 09:58:32 +01:00
for i := range v {
if v[i].ID == id {
2015-03-20 09:58:32 +01:00
// Update an existing index
v[i].Value++
return v
} else if v[i].ID > id {
2015-09-22 21:51:05 +02:00
// Insert a new index
2015-03-20 09:58:32 +01:00
nv := make(Vector, len(v)+1)
copy(nv, v[:i])
nv[i].ID = id
2015-03-20 09:58:32 +01:00
nv[i].Value = 1
copy(nv[i+1:], v[i:])
return nv
}
}
2015-09-22 21:51:05 +02:00
// Append a new index
return append(v, Counter{id, 1})
2015-03-20 09:58:32 +01:00
}
2015-09-22 20:34:24 +02:00
// Merge returns the vector containing the maximum indexes from v and b. If it
2015-09-22 21:51:05 +02:00
// is possible, the vector v is updated and returned. If it is not, a copy
2015-03-20 09:58:32 +01:00
// will be created, updated and returned.
2015-09-22 20:34:24 +02:00
func (v Vector) Merge(b Vector) Vector {
var vi, bi int
2015-03-20 09:58:32 +01:00
for bi < len(b) {
2015-09-22 20:34:24 +02:00
if vi == len(v) {
// We've reach the end of v, all that remains are appends
return append(v, b[bi:]...)
2015-03-20 09:58:32 +01:00
}
2015-09-22 20:34:24 +02:00
if v[vi].ID > b[bi].ID {
2015-03-20 09:58:32 +01:00
// The index from b should be inserted here
2015-09-22 20:34:24 +02:00
n := make(Vector, len(v)+1)
copy(n, v[:vi])
n[vi] = b[bi]
copy(n[vi+1:], v[vi:])
v = n
2015-03-20 09:58:32 +01:00
}
2015-09-22 20:34:24 +02:00
if v[vi].ID == b[bi].ID {
if val := b[bi].Value; val > v[vi].Value {
v[vi].Value = val
2015-03-20 09:58:32 +01:00
}
}
2015-09-22 20:34:24 +02:00
if bi < len(b) && v[vi].ID == b[bi].ID {
2015-03-20 09:58:32 +01:00
bi++
}
2015-09-22 20:34:24 +02:00
vi++
2015-03-20 09:58:32 +01:00
}
2015-09-22 20:34:24 +02:00
return v
2015-03-20 09:58:32 +01:00
}
// 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.
2015-09-22 20:34:24 +02:00
func (v Vector) Equal(b Vector) bool {
return v.Compare(b) == Equal
2015-03-20 09:58:32 +01:00
}
2015-09-22 20:34:24 +02:00
// LesserEqual returns true when the two vectors are equivalent or v is Lesser
2015-03-20 09:58:32 +01:00
// than b.
2015-09-22 20:34:24 +02:00
func (v Vector) LesserEqual(b Vector) bool {
comp := v.Compare(b)
2015-03-20 09:58:32 +01:00
return comp == Lesser || comp == Equal
}
2015-09-22 20:34:24 +02:00
// GreaterEqual returns true when the two vectors are equivalent or v is Greater
2015-03-20 09:58:32 +01:00
// than b.
2015-09-22 20:34:24 +02:00
func (v Vector) GreaterEqual(b Vector) bool {
comp := v.Compare(b)
2015-03-20 09:58:32 +01:00
return comp == Greater || comp == Equal
}
// Concurrent returns true when the two vectors are concurrent.
2015-09-22 20:34:24 +02:00
func (v Vector) Concurrent(b Vector) bool {
comp := v.Compare(b)
2015-03-20 09:58:32 +01:00
return comp == ConcurrentGreater || comp == ConcurrentLesser
}
2015-04-09 12:51:21 +02:00
// Counter returns the current value of the given counter ID.
func (v Vector) Counter(id ShortID) uint64 {
2015-04-09 12:51:21 +02:00
for _, c := range v {
if c.ID == id {
return c.Value
}
}
return 0
}