Humanize serialization of version vectors (again)

This commit is contained in:
Jakob Borg 2016-01-20 11:10:22 -08:00
parent e267bf3e09
commit 11d4986517
9 changed files with 38 additions and 17 deletions

View File

@ -1220,7 +1220,7 @@ type jsonVersionVector protocol.Vector
func (v jsonVersionVector) MarshalJSON() ([]byte, error) { func (v jsonVersionVector) MarshalJSON() ([]byte, error) {
res := make([]string, len(v)) res := make([]string, len(v))
for i, c := range v { for i, c := range v {
res[i] = fmt.Sprintf("%d:%d", c.ID, c.Value) res[i] = fmt.Sprintf("%v:%d", c.ID, c.Value)
} }
return json.Marshal(res) return json.Marshal(res)
} }

View File

@ -1208,7 +1208,7 @@ func cleanConfigDirectory() {
// short ID:s; that is, that the devices in the cluster all have unique // short ID:s; that is, that the devices in the cluster all have unique
// initial 64 bits. // initial 64 bits.
func checkShortIDs(cfg *config.Wrapper) error { func checkShortIDs(cfg *config.Wrapper) error {
exists := make(map[uint64]protocol.DeviceID) exists := make(map[protocol.ShortID]protocol.DeviceID)
for deviceID := range cfg.Devices() { for deviceID := range cfg.Devices() {
shortID := deviceID.Short() shortID := deviceID.Short()
if otherID, ok := exists[shortID]; ok { if otherID, ok := exists[shortID]; ok {

View File

@ -67,7 +67,7 @@ type Model struct {
finder *db.BlockFinder finder *db.BlockFinder
progressEmitter *ProgressEmitter progressEmitter *ProgressEmitter
id protocol.DeviceID id protocol.DeviceID
shortID uint64 shortID protocol.ShortID
cacheIgnoredFiles bool cacheIgnoredFiles bool
protectedFiles []string protectedFiles []string

View File

@ -87,7 +87,7 @@ type rwFolder struct {
ignorePerms bool ignorePerms bool
copiers int copiers int
pullers int pullers int
shortID uint64 shortID protocol.ShortID
order config.PullOrder order config.PullOrder
maxConflicts int maxConflicts int
sleep time.Duration sleep time.Duration
@ -108,7 +108,7 @@ type rwFolder struct {
errorsMut sync.Mutex errorsMut sync.Mutex
} }
func newRWFolder(m *Model, shortID uint64, cfg config.FolderConfiguration) *rwFolder { func newRWFolder(m *Model, shortID protocol.ShortID, cfg config.FolderConfiguration) *rwFolder {
p := &rwFolder{ p := &rwFolder{
stateTracker: stateTracker{ stateTracker: stateTracker{
folder: cfg.ID, folder: cfg.ID,

View File

@ -16,6 +16,7 @@ import (
) )
type DeviceID [32]byte type DeviceID [32]byte
type ShortID uint64
var LocalDeviceID = DeviceID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} var LocalDeviceID = DeviceID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
@ -69,14 +70,20 @@ func (n DeviceID) Equals(other DeviceID) bool {
} }
// Short returns an integer representing bits 0-63 of the device ID. // Short returns an integer representing bits 0-63 of the device ID.
func (n DeviceID) Short() uint64 { func (n DeviceID) Short() ShortID {
return binary.BigEndian.Uint64(n[:]) return ShortID(binary.BigEndian.Uint64(n[:]))
} }
func (n *DeviceID) MarshalText() ([]byte, error) { func (n *DeviceID) MarshalText() ([]byte, error) {
return []byte(n.String()), nil return []byte(n.String()), nil
} }
func (s ShortID) String() string {
var bs [8]byte
binary.BigEndian.PutUint64(bs[:], uint64(s))
return base32.StdEncoding.EncodeToString(bs[:])[:7]
}
func (n *DeviceID) UnmarshalText(bs []byte) error { func (n *DeviceID) UnmarshalText(bs []byte) error {
id := string(bs) id := string(bs)
id = strings.Trim(id, "=") id = strings.Trim(id, "=")

View File

@ -74,3 +74,17 @@ func TestMarshallingDeviceID(t *testing.T) {
t.Error("Compare error") t.Error("Compare error")
} }
} }
func TestShortIDString(t *testing.T) {
id, _ := DeviceIDFromString(formatted)
sid := id.Short().String()
if len(sid) != 7 {
t.Errorf("Wrong length for short ID: got %d, want 7", len(sid))
}
want := formatted[:len(sid)]
if sid != want {
t.Errorf("Wrong short ID: got %q, want %q", sid, want)
}
}

View File

@ -10,31 +10,31 @@ type Vector []Counter
// Counter represents a single counter in the version vector. // Counter represents a single counter in the version vector.
type Counter struct { type Counter struct {
ID uint64 ID ShortID
Value uint64 Value uint64
} }
// Update returns a Vector with the index for the specific ID incremented by // 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, // one. If it is possible, the vector v is updated and returned. If it is not,
// a copy will be created, updated and returned. // a copy will be created, updated and returned.
func (v Vector) Update(ID uint64) Vector { func (v Vector) Update(id ShortID) Vector {
for i := range v { for i := range v {
if v[i].ID == ID { if v[i].ID == id {
// Update an existing index // Update an existing index
v[i].Value++ v[i].Value++
return v return v
} else if v[i].ID > ID { } else if v[i].ID > id {
// Insert a new index // Insert a new index
nv := make(Vector, len(v)+1) nv := make(Vector, len(v)+1)
copy(nv, v[:i]) copy(nv, v[:i])
nv[i].ID = ID nv[i].ID = id
nv[i].Value = 1 nv[i].Value = 1
copy(nv[i+1:], v[i:]) copy(nv[i+1:], v[i:])
return nv return nv
} }
} }
// Append a new index // Append a new index
return append(v, Counter{ID, 1}) return append(v, Counter{id, 1})
} }
// Merge returns the vector containing the maximum indexes from v and b. If it // Merge returns the vector containing the maximum indexes from v and b. If it
@ -105,7 +105,7 @@ func (v Vector) Concurrent(b Vector) bool {
} }
// Counter returns the current value of the given counter ID. // Counter returns the current value of the given counter ID.
func (v Vector) Counter(id uint64) uint64 { func (v Vector) Counter(id ShortID) uint64 {
for _, c := range v { for _, c := range v {
if c.ID == id { if c.ID == id {
return c.Value return c.Value

View File

@ -21,7 +21,7 @@ type xdrReader interface {
func (v Vector) EncodeXDRInto(w xdrWriter) (int, error) { func (v Vector) EncodeXDRInto(w xdrWriter) (int, error) {
w.WriteUint32(uint32(len(v))) w.WriteUint32(uint32(len(v)))
for i := range v { for i := range v {
w.WriteUint64(v[i].ID) w.WriteUint64(uint64(v[i].ID))
w.WriteUint64(v[i].Value) w.WriteUint64(v[i].Value)
} }
return 4 + 16*len(v), nil return 4 + 16*len(v), nil
@ -35,7 +35,7 @@ func (v *Vector) DecodeXDRFrom(r xdrReader) error {
} }
n := make(Vector, l) n := make(Vector, l)
for i := range n { for i := range n {
n[i].ID = r.ReadUint64() n[i].ID = ShortID(r.ReadUint64())
n[i].Value = r.ReadUint64() n[i].Value = r.ReadUint64()
} }
*v = n *v = n

View File

@ -69,7 +69,7 @@ type Walker struct {
// Number of routines to use for hashing // Number of routines to use for hashing
Hashers int Hashers int
// Our vector clock id // Our vector clock id
ShortID uint64 ShortID protocol.ShortID
// Optional progress tick interval which defines how often FolderScanProgress // Optional progress tick interval which defines how often FolderScanProgress
// events are emitted. Negative number means disabled. // events are emitted. Negative number means disabled.
ProgressTickIntervalS int ProgressTickIntervalS int