all: Rename LocalVersion to Sequence (fixes #3461)

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3462
This commit is contained in:
Jakob Borg 2016-07-29 19:54:24 +00:00 committed by Audrius Butkevicius
parent a022b0cfff
commit 297240facf
14 changed files with 312 additions and 312 deletions

View File

@ -90,8 +90,8 @@ type modelIntf interface {
ConnectedTo(deviceID protocol.DeviceID) bool
GlobalSize(folder string) (nfiles, deleted int, bytes int64)
LocalSize(folder string) (nfiles, deleted int, bytes int64)
CurrentLocalVersion(folder string) (int64, bool)
RemoteLocalVersion(folder string) (int64, bool)
CurrentSequence(folder string) (int64, bool)
RemoteSequence(folder string) (int64, bool)
State(folder string) (string, time.Time, error)
}
@ -596,10 +596,11 @@ func folderSummary(cfg configIntf, m modelIntf, folder string) map[string]interf
res["error"] = err.Error()
}
lv, _ := m.CurrentLocalVersion(folder)
rv, _ := m.RemoteLocalVersion(folder)
ourSeq, _ := m.CurrentSequence(folder)
remoteSeq, _ := m.RemoteSequence(folder)
res["version"] = lv + rv
res["version"] = ourSeq + remoteSeq // legacy
res["sequence"] = ourSeq + remoteSeq // new name
ignorePatterns, _, _ := m.GetIgnores(folder)
res["ignorePatterns"] = false
@ -1187,7 +1188,7 @@ func (f jsonFileInfo) MarshalJSON() ([]byte, error) {
"invalid": f.Invalid,
"noPermissions": f.NoPermissions,
"modified": time.Unix(f.Modified, 0),
"localVersion": f.LocalVersion,
"sequence": f.Sequence,
"numBlocks": len(f.Blocks),
"version": jsonVersionVector(f.Version),
})
@ -1205,7 +1206,7 @@ func (f jsonDBFileInfo) MarshalJSON() ([]byte, error) {
"invalid": f.Invalid,
"noPermissions": f.NoPermissions,
"modified": time.Unix(f.Modified, 0),
"localVersion": f.LocalVersion,
"sequence": f.Sequence,
})
}

View File

@ -103,11 +103,11 @@ func (m *mockedModel) LocalSize(folder string) (nfiles, deleted int, bytes int64
return 0, 0, 0
}
func (m *mockedModel) CurrentLocalVersion(folder string) (int64, bool) {
func (m *mockedModel) CurrentSequence(folder string) (int64, bool) {
return 0, false
}
func (m *mockedModel) RemoteLocalVersion(folder string) (int64, bool) {
func (m *mockedModel) RemoteSequence(folder string) (int64, bool) {
return 0, false
}

View File

@ -22,15 +22,15 @@ import (
)
type FileSet struct {
localVersion int64 // Our local version counter
sequence int64 // Our local sequence number
folder string
db *Instance
blockmap *BlockMap
localSize sizeTracker
globalSize sizeTracker
remoteLocalVersion map[protocol.DeviceID]int64 // Highest seen local versions for other devices
updateMutex sync.Mutex // protects remoteLocalVersion and database updates
remoteSequence map[protocol.DeviceID]int64 // Highest seen sequence numbers for other devices
updateMutex sync.Mutex // protects remoteSequence and database updates
}
// FileIntf is the set of methods implemented by both protocol.FileInfo and
@ -98,7 +98,7 @@ func (s *sizeTracker) Size() (files, deleted int, bytes int64) {
func NewFileSet(folder string, db *Instance) *FileSet {
var s = FileSet{
remoteLocalVersion: make(map[protocol.DeviceID]int64),
remoteSequence: make(map[protocol.DeviceID]int64),
folder: folder,
db: db,
blockmap: NewBlockMap(db, db.folderIdx.ID([]byte(folder))),
@ -111,16 +111,16 @@ func NewFileSet(folder string, db *Instance) *FileSet {
s.db.withAllFolderTruncated([]byte(folder), func(device []byte, f FileInfoTruncated) bool {
copy(deviceID[:], device)
if deviceID == protocol.LocalDeviceID {
if f.LocalVersion > s.localVersion {
s.localVersion = f.LocalVersion
if f.Sequence > s.sequence {
s.sequence = f.Sequence
}
s.localSize.addFile(f)
} else if f.LocalVersion > s.remoteLocalVersion[deviceID] {
s.remoteLocalVersion[deviceID] = f.LocalVersion
} else if f.Sequence > s.remoteSequence[deviceID] {
s.remoteSequence[deviceID] = f.Sequence
}
return true
})
l.Debugf("loaded localVersion for %q: %#v", folder, s.localVersion)
l.Debugf("loaded sequence for %q: %#v", folder, s.sequence)
return &s
}
@ -134,17 +134,17 @@ func (s *FileSet) Replace(device protocol.DeviceID, fs []protocol.FileInfo) {
if device == protocol.LocalDeviceID {
if len(fs) == 0 {
s.localVersion = 0
s.sequence = 0
} else {
// Always overwrite LocalVersion on updated files to ensure
// Always overwrite Sequence on updated files to ensure
// correct ordering. The caller is supposed to leave it set to
// zero anyhow.
for i := range fs {
fs[i].LocalVersion = atomic.AddInt64(&s.localVersion, 1)
fs[i].Sequence = atomic.AddInt64(&s.sequence, 1)
}
}
} else {
s.remoteLocalVersion[device] = maxLocalVersion(fs)
s.remoteSequence[device] = maxSequence(fs)
}
s.db.replace([]byte(s.folder), device[:], fs, &s.localSize, &s.globalSize)
if device == protocol.LocalDeviceID {
@ -164,7 +164,7 @@ func (s *FileSet) Update(device protocol.DeviceID, fs []protocol.FileInfo) {
discards := make([]protocol.FileInfo, 0, len(fs))
updates := make([]protocol.FileInfo, 0, len(fs))
for i, newFile := range fs {
fs[i].LocalVersion = atomic.AddInt64(&s.localVersion, 1)
fs[i].Sequence = atomic.AddInt64(&s.sequence, 1)
existingFile, ok := s.db.getFile([]byte(s.folder), device[:], []byte(newFile.Name))
if !ok || !existingFile.Version.Equal(newFile.Version) {
discards = append(discards, existingFile)
@ -174,7 +174,7 @@ func (s *FileSet) Update(device protocol.DeviceID, fs []protocol.FileInfo) {
s.blockmap.Discard(discards)
s.blockmap.Update(updates)
} else {
s.remoteLocalVersion[device] = maxLocalVersion(fs)
s.remoteSequence[device] = maxSequence(fs)
}
s.db.updateFiles([]byte(s.folder), device[:], fs, &s.localSize, &s.globalSize)
}
@ -248,14 +248,14 @@ func (s *FileSet) Availability(file string) []protocol.DeviceID {
return s.db.availability([]byte(s.folder), []byte(osutil.NormalizedFilename(file)))
}
func (s *FileSet) LocalVersion(device protocol.DeviceID) int64 {
func (s *FileSet) Sequence(device protocol.DeviceID) int64 {
if device == protocol.LocalDeviceID {
return atomic.LoadInt64(&s.localVersion)
return atomic.LoadInt64(&s.sequence)
}
s.updateMutex.Lock()
defer s.updateMutex.Unlock()
return s.remoteLocalVersion[device]
return s.remoteSequence[device]
}
func (s *FileSet) LocalSize() (files, deleted int, bytes int64) {
@ -283,15 +283,15 @@ func (s *FileSet) SetIndexID(device protocol.DeviceID, id protocol.IndexID) {
s.db.setIndexID(device[:], []byte(s.folder), id)
}
// maxLocalVersion returns the highest of the LocalVersion numbers found in
// the given slice of FileInfos. This should really be the LocalVersion of
// maxSequence returns the highest of the Sequence numbers found in
// the given slice of FileInfos. This should really be the Sequence of
// the last item, but Syncthing v0.14.0 and other implementations may not
// implement update sorting....
func maxLocalVersion(fs []protocol.FileInfo) int64 {
func maxSequence(fs []protocol.FileInfo) int64 {
var max int64
for _, f := range fs {
if f.LocalVersion > max {
max = f.LocalVersion
if f.Sequence > max {
max = f.Sequence
}
}
return max

View File

@ -100,11 +100,11 @@ func TestGlobalSet(t *testing.T) {
m := db.NewFileSet("test", ldb)
local0 := fileList{
protocol.FileInfo{Name: "a", LocalVersion: 1, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
protocol.FileInfo{Name: "b", LocalVersion: 2, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(2)},
protocol.FileInfo{Name: "c", LocalVersion: 3, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(3)},
protocol.FileInfo{Name: "d", LocalVersion: 4, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(4)},
protocol.FileInfo{Name: "z", LocalVersion: 5, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(8)},
protocol.FileInfo{Name: "a", Sequence: 1, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
protocol.FileInfo{Name: "b", Sequence: 2, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(2)},
protocol.FileInfo{Name: "c", Sequence: 3, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(3)},
protocol.FileInfo{Name: "d", Sequence: 4, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(4)},
protocol.FileInfo{Name: "z", Sequence: 5, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(8)},
}
local1 := fileList{
protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
@ -480,7 +480,7 @@ func TestNeed(t *testing.T) {
}
}
func TestLocalVersion(t *testing.T) {
func TestSequence(t *testing.T) {
ldb := db.OpenMemory()
m := db.NewFileSet("test", ldb)
@ -501,10 +501,10 @@ func TestLocalVersion(t *testing.T) {
}
m.Replace(protocol.LocalDeviceID, local1)
c0 := m.LocalVersion(protocol.LocalDeviceID)
c0 := m.Sequence(protocol.LocalDeviceID)
m.Replace(protocol.LocalDeviceID, local2)
c1 := m.LocalVersion(protocol.LocalDeviceID)
c1 := m.Sequence(protocol.LocalDeviceID)
if !(c1 > c0) {
t.Fatal("Local version number should have incremented")
}

View File

@ -61,7 +61,7 @@ type FileInfoTruncated struct {
Invalid bool `protobuf:"varint,7,opt,name=invalid,proto3" json:"invalid,omitempty"`
NoPermissions bool `protobuf:"varint,8,opt,name=no_permissions,json=noPermissions,proto3" json:"no_permissions,omitempty"`
Version protocol.Vector `protobuf:"bytes,9,opt,name=version" json:"version"`
LocalVersion int64 `protobuf:"varint,10,opt,name=local_version,json=localVersion,proto3" json:"local_version,omitempty"`
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
}
func (m *FileInfoTruncated) Reset() { *m = FileInfoTruncated{} }
@ -214,10 +214,10 @@ func (m *FileInfoTruncated) MarshalTo(data []byte) (int, error) {
return 0, err
}
i += n2
if m.LocalVersion != 0 {
if m.Sequence != 0 {
data[i] = 0x50
i++
i = encodeVarintStructs(data, i, uint64(m.LocalVersion))
i = encodeVarintStructs(data, i, uint64(m.Sequence))
}
return i, nil
}
@ -303,8 +303,8 @@ func (m *FileInfoTruncated) ProtoSize() (n int) {
}
l = m.Version.ProtoSize()
n += 1 + l + sovStructs(uint64(l))
if m.LocalVersion != 0 {
n += 1 + sovStructs(uint64(m.LocalVersion))
if m.Sequence != 0 {
n += 1 + sovStructs(uint64(m.Sequence))
}
return n
}
@ -740,9 +740,9 @@ func (m *FileInfoTruncated) Unmarshal(data []byte) error {
iNdEx = postIndex
case 10:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field LocalVersion", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType)
}
m.LocalVersion = 0
m.Sequence = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStructs
@ -752,7 +752,7 @@ func (m *FileInfoTruncated) Unmarshal(data []byte) error {
}
b := data[iNdEx]
iNdEx++
m.LocalVersion |= (int64(b) & 0x7F) << shift
m.Sequence |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
@ -884,31 +884,30 @@ var (
)
var fileDescriptorStructs = []byte{
// 401 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x51, 0x4f, 0xcb, 0xd3, 0x30,
0x1c, 0x6e, 0xb7, 0xba, 0xf5, 0x4d, 0xdf, 0x4e, 0x0d, 0x32, 0xca, 0x0e, 0xdd, 0x98, 0x08, 0x22,
0xd8, 0xe9, 0xc4, 0x8b, 0xc7, 0x1d, 0x06, 0x82, 0x07, 0x29, 0x32, 0x8f, 0xa3, 0x4d, 0xb2, 0x2e,
0xd0, 0x26, 0xa5, 0x49, 0x07, 0xf3, 0x93, 0x78, 0xdc, 0xc7, 0xd9, 0xd1, 0x2f, 0xa0, 0xe8, 0xfc,
0x22, 0x66, 0x49, 0x3b, 0x7b, 0x7c, 0x0f, 0x81, 0xdf, 0x93, 0xe7, 0xcf, 0xef, 0x21, 0x01, 0xbe,
0x90, 0x55, 0x8d, 0xa4, 0x88, 0xca, 0x8a, 0x4b, 0x0e, 0x7b, 0x38, 0x9d, 0xbc, 0xce, 0xa8, 0xdc,
0xd7, 0x69, 0x84, 0x78, 0xb1, 0xc8, 0x78, 0xc6, 0x17, 0x9a, 0x4a, 0xeb, 0x9d, 0x46, 0x1a, 0xe8,
0xc9, 0x58, 0x26, 0xef, 0x3b, 0x72, 0x71, 0x64, 0x48, 0xee, 0x29, 0xcb, 0x3a, 0x53, 0x4e, 0x53,
0x93, 0x80, 0x78, 0xbe, 0x48, 0x49, 0x69, 0x6c, 0xf3, 0xaf, 0xc0, 0x5b, 0xd3, 0x9c, 0x6c, 0x48,
0x25, 0x28, 0x67, 0xf0, 0x0d, 0x18, 0x1e, 0xcc, 0x18, 0xd8, 0x33, 0xfb, 0xa5, 0xb7, 0x7c, 0x12,
0xb5, 0xa6, 0x68, 0x43, 0x90, 0xe4, 0xd5, 0xca, 0x39, 0xff, 0x9a, 0x5a, 0x71, 0x2b, 0x83, 0x63,
0x30, 0xc0, 0xe4, 0x40, 0x11, 0x09, 0x7a, 0xca, 0x70, 0x1f, 0x37, 0x68, 0xbe, 0x06, 0x5e, 0x13,
0xfa, 0x89, 0x0a, 0x09, 0xdf, 0x02, 0xb7, 0x71, 0x08, 0x95, 0xdc, 0x57, 0xc9, 0x8f, 0x23, 0x9c,
0x46, 0x9d, 0xdd, 0x4d, 0xf0, 0x4d, 0xf6, 0xc1, 0xf9, 0x7e, 0x9a, 0x5a, 0xf3, 0x9f, 0x3d, 0xf0,
0xf4, 0xaa, 0xfa, 0xc8, 0x76, 0xfc, 0x4b, 0x55, 0x33, 0x94, 0x48, 0x82, 0x21, 0x04, 0x0e, 0x4b,
0x0a, 0xa2, 0x4b, 0xde, 0xc5, 0x7a, 0x86, 0xaf, 0x80, 0x23, 0x8f, 0xa5, 0xe9, 0x31, 0x5a, 0x8e,
0xff, 0x17, 0xbf, 0xd9, 0x15, 0x1b, 0x6b, 0xcd, 0xd5, 0x2f, 0xe8, 0x37, 0x12, 0xf4, 0x95, 0xb6,
0x1f, 0xeb, 0x19, 0xce, 0x80, 0x57, 0x92, 0xaa, 0xa0, 0xc2, 0xb4, 0x74, 0x14, 0xe5, 0xc7, 0xdd,
0x2b, 0x38, 0x01, 0x6e, 0xc1, 0x31, 0xdd, 0x51, 0x82, 0x83, 0x47, 0xda, 0x79, 0xc3, 0x30, 0x00,
0x43, 0x4c, 0x72, 0xa2, 0xca, 0x05, 0x03, 0x45, 0xb9, 0x71, 0x0b, 0xaf, 0x0c, 0x65, 0x87, 0x24,
0xa7, 0x38, 0x18, 0x1a, 0xa6, 0x81, 0xf0, 0x05, 0x18, 0x31, 0xbe, 0xed, 0x2e, 0x75, 0xb5, 0xc0,
0x67, 0xfc, 0x73, 0x67, 0x6d, 0xe7, 0x53, 0xee, 0x1e, 0xf6, 0x29, 0xcf, 0x81, 0x9f, 0x73, 0x94,
0xe4, 0xdb, 0xd6, 0x07, 0x74, 0xdb, 0x7b, 0x7d, 0xd9, 0xbc, 0xb7, 0x79, 0xdf, 0xd5, 0xb3, 0xf3,
0x9f, 0xd0, 0x3a, 0x5f, 0x42, 0xfb, 0x87, 0x3a, 0xbf, 0x2f, 0xa1, 0x75, 0xfa, 0x1b, 0xda, 0xe9,
0x40, 0x2f, 0x78, 0xf7, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xe4, 0xb1, 0x7f, 0x07, 0x98, 0x02, 0x00,
0x00,
// 400 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x51, 0x4d, 0x6b, 0xe2, 0x40,
0x18, 0x4e, 0x34, 0xab, 0x71, 0xb2, 0xba, 0xbb, 0xc3, 0x22, 0xc1, 0x43, 0x14, 0x61, 0x61, 0x59,
0xd8, 0xb8, 0xeb, 0xb2, 0x97, 0x1e, 0x3d, 0x08, 0x85, 0x1e, 0x4a, 0x28, 0xf6, 0x58, 0x4c, 0x66,
0x8c, 0x03, 0xc9, 0x4c, 0x9a, 0x99, 0x08, 0xf6, 0x97, 0xf4, 0xe8, 0xcf, 0xf1, 0xd8, 0x43, 0xcf,
0xa5, 0xb5, 0x7f, 0xa4, 0xe3, 0x4c, 0x62, 0x73, 0xec, 0x21, 0xf0, 0x3e, 0x79, 0x3e, 0xde, 0x87,
0x79, 0x41, 0x97, 0x8b, 0xbc, 0x88, 0x04, 0xf7, 0xb3, 0x9c, 0x09, 0x06, 0x1b, 0x28, 0x1c, 0xfc,
0x8e, 0x89, 0x58, 0x17, 0xa1, 0x1f, 0xb1, 0x74, 0x12, 0xb3, 0x98, 0x4d, 0x14, 0x15, 0x16, 0x2b,
0x85, 0x14, 0x50, 0x93, 0xb6, 0x0c, 0xfe, 0xd7, 0xe4, 0x7c, 0x4b, 0x23, 0xb1, 0x26, 0x34, 0xae,
0x4d, 0x09, 0x09, 0x75, 0x42, 0xc4, 0x92, 0x49, 0x88, 0x33, 0x6d, 0x1b, 0x5f, 0x03, 0x67, 0x4e,
0x12, 0xbc, 0xc0, 0x39, 0x27, 0x8c, 0xc2, 0x3f, 0xa0, 0xbd, 0xd1, 0xa3, 0x6b, 0x8e, 0xcc, 0x9f,
0xce, 0xf4, 0xab, 0x5f, 0x99, 0xfc, 0x05, 0x8e, 0x04, 0xcb, 0x67, 0xd6, 0xfe, 0x69, 0x68, 0x04,
0x95, 0x0c, 0xf6, 0x41, 0x0b, 0xe1, 0x0d, 0x89, 0xb0, 0xdb, 0x90, 0x86, 0xcf, 0x41, 0x89, 0xc6,
0x73, 0xe0, 0x94, 0xa1, 0x17, 0x84, 0x0b, 0xf8, 0x17, 0xd8, 0xa5, 0x83, 0xcb, 0xe4, 0xa6, 0x4c,
0xfe, 0xe2, 0xa3, 0xd0, 0xaf, 0xed, 0x2e, 0x83, 0x4f, 0xb2, 0x33, 0xeb, 0x7e, 0x37, 0x34, 0xc6,
0x8f, 0x0d, 0xf0, 0xed, 0xa8, 0x3a, 0xa7, 0x2b, 0x76, 0x95, 0x17, 0x34, 0x5a, 0x0a, 0x8c, 0x20,
0x04, 0x16, 0x5d, 0xa6, 0x58, 0x95, 0xec, 0x04, 0x6a, 0x86, 0xbf, 0x80, 0x25, 0xb6, 0x99, 0xee,
0xd1, 0x9b, 0xf6, 0xdf, 0x8b, 0x9f, 0xec, 0x92, 0x0d, 0x94, 0xe6, 0xe8, 0xe7, 0xe4, 0x0e, 0xbb,
0x4d, 0xa9, 0x6d, 0x06, 0x6a, 0x86, 0x23, 0xe0, 0x64, 0x38, 0x4f, 0x09, 0xd7, 0x2d, 0x2d, 0x49,
0x75, 0x83, 0xfa, 0x2f, 0x38, 0x00, 0x76, 0xca, 0x10, 0x59, 0x11, 0x8c, 0xdc, 0x4f, 0xca, 0x79,
0xc2, 0xd0, 0x05, 0x6d, 0x84, 0x13, 0x2c, 0xcb, 0xb9, 0x2d, 0x49, 0xd9, 0x41, 0x05, 0x8f, 0x0c,
0xa1, 0x9b, 0x65, 0x42, 0x90, 0xdb, 0xd6, 0x4c, 0x09, 0xe1, 0x0f, 0xd0, 0xa3, 0xec, 0xa6, 0xbe,
0xd4, 0x56, 0x82, 0x2e, 0x65, 0x97, 0xb5, 0xb5, 0xb5, 0xa3, 0x74, 0x3e, 0x76, 0x14, 0x59, 0x94,
0xe3, 0xdb, 0x02, 0x53, 0x79, 0x16, 0xa0, 0x8b, 0x56, 0x58, 0x3f, 0xeb, 0xec, 0xfb, 0xfe, 0xc5,
0x33, 0xf6, 0x07, 0xcf, 0x7c, 0x90, 0xdf, 0xf3, 0xc1, 0x33, 0x76, 0xaf, 0x9e, 0x19, 0xb6, 0x54,
0xee, 0xbf, 0xb7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xb3, 0x6f, 0x36, 0x8f, 0x02, 0x00, 0x00,
}

View File

@ -31,5 +31,5 @@ message FileInfoTruncated {
bool invalid = 7;
bool no_permissions = 8;
protocol.Vector version = 9 [(gogoproto.nullable) = false];
int64 local_version = 10;
int64 sequence = 10;
}

View File

@ -189,7 +189,7 @@ func (m *Model) StartFolder(folder string) {
}
fs := m.folderFiles[folder]
v, ok := fs.LocalVersion(protocol.LocalDeviceID), true
v, ok := fs.Sequence(protocol.LocalDeviceID), true
indexHasFiles := ok && v > 0
if !indexHasFiles {
// It's a blank folder, so this may the first time we're looking at
@ -583,7 +583,7 @@ func (m *Model) Index(deviceID protocol.DeviceID, folder string, fs []protocol.F
"device": deviceID.String(),
"folder": folder,
"items": len(fs),
"version": files.LocalVersion(deviceID),
"version": files.Sequence(deviceID),
})
}
@ -619,7 +619,7 @@ func (m *Model) IndexUpdate(deviceID protocol.DeviceID, folder string, fs []prot
"device": deviceID.String(),
"folder": folder,
"items": len(fs),
"version": files.LocalVersion(deviceID),
"version": files.Sequence(deviceID),
})
runner.IndexUpdated()
@ -674,8 +674,8 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
fs := m.folderFiles[folder.ID]
myIndexID := fs.IndexID(protocol.LocalDeviceID)
myLocalVersion := fs.LocalVersion(protocol.LocalDeviceID)
var startLocalVersion int64
mySequence := fs.Sequence(protocol.LocalDeviceID)
var startSequence int64
for _, dev := range folder.Devices {
if bytes.Equal(dev.ID, m.id[:]) {
@ -687,7 +687,7 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
// They say they've seen our index ID before, so we can
// send a delta update only.
if dev.MaxLocalVersion > myLocalVersion {
if dev.MaxSequence > mySequence {
// Safety check. They claim to have more or newer
// index data than we have - either we have lost
// index data, or reset the index without resetting
@ -695,19 +695,19 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
// happened. We send a full index to reset the
// situation.
l.Infof("Device %v folder %q is delta index compatible, but seems out of sync with reality", deviceID, folder.ID)
startLocalVersion = 0
startSequence = 0
continue
}
l.Infof("Device %v folder %q is delta index compatible (mlv=%d)", deviceID, folder.ID, dev.MaxLocalVersion)
startLocalVersion = dev.MaxLocalVersion
l.Infof("Device %v folder %q is delta index compatible (mlv=%d)", deviceID, folder.ID, dev.MaxSequence)
startSequence = dev.MaxSequence
} else if dev.IndexID != 0 {
// They say they've seen an index ID from us, but it's
// not the right one. Either they are confused or we
// must have reset our database since last talking to
// them. We'll start with a full index transfer.
l.Infof("Device %v folder %q has mismatching index ID for us (%v != %v)", deviceID, folder.ID, dev.IndexID, myIndexID)
startLocalVersion = 0
startSequence = 0
}
} else if bytes.Equal(dev.ID, deviceID[:]) && dev.IndexID != 0 {
// This is the other side's description of themselves. We
@ -743,7 +743,7 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
}
}
go sendIndexes(conn, folder.ID, fs, m.folderIgnores[folder.ID], startLocalVersion, dbLocation)
go sendIndexes(conn, folder.ID, fs, m.folderIgnores[folder.ID], startSequence, dbLocation)
}
m.fmut.Unlock()
@ -1216,15 +1216,15 @@ func (m *Model) receivedFile(folder string, file protocol.FileInfo) {
m.folderStatRef(folder).ReceivedFile(file.Name, file.IsDeleted())
}
func sendIndexes(conn protocol.Connection, folder string, fs *db.FileSet, ignores *ignore.Matcher, startLocalVersion int64, dbLocation string) {
func sendIndexes(conn protocol.Connection, folder string, fs *db.FileSet, ignores *ignore.Matcher, startSequence int64, dbLocation string) {
deviceID := conn.ID()
name := conn.Name()
var err error
l.Debugf("sendIndexes for %s-%s/%q starting (slv=%d)", deviceID, name, folder, startLocalVersion)
l.Debugf("sendIndexes for %s-%s/%q starting (slv=%d)", deviceID, name, folder, startSequence)
defer l.Debugf("sendIndexes for %s-%s/%q exiting: %v", deviceID, name, folder, err)
minLocalVer, err := sendIndexTo(startLocalVersion, conn, folder, fs, ignores, dbLocation)
minSequence, err := sendIndexTo(startSequence, conn, folder, fs, ignores, dbLocation)
// Subscribe to LocalIndexUpdated (we have new information to send) and
// DeviceDisconnected (it might be us who disconnected, so we should
@ -1238,16 +1238,16 @@ func sendIndexes(conn protocol.Connection, folder string, fs *db.FileSet, ignore
return
}
// While we have sent a localVersion at least equal to the one
// While we have sent a sequence at least equal to the one
// currently in the database, wait for the local index to update. The
// local index may update for other folders than the one we are
// sending for.
if fs.LocalVersion(protocol.LocalDeviceID) <= minLocalVer {
if fs.Sequence(protocol.LocalDeviceID) <= minSequence {
sub.Poll(time.Minute)
continue
}
minLocalVer, err = sendIndexTo(minLocalVer, conn, folder, fs, ignores, dbLocation)
minSequence, err = sendIndexTo(minSequence, conn, folder, fs, ignores, dbLocation)
// Wait a short amount of time before entering the next loop. If there
// are continuous changes happening to the local index, this gives us
@ -1256,13 +1256,13 @@ func sendIndexes(conn protocol.Connection, folder string, fs *db.FileSet, ignore
}
}
func sendIndexTo(minLocalVer int64, conn protocol.Connection, folder string, fs *db.FileSet, ignores *ignore.Matcher, dbLocation string) (int64, error) {
func sendIndexTo(minSequence int64, conn protocol.Connection, folder string, fs *db.FileSet, ignores *ignore.Matcher, dbLocation string) (int64, error) {
deviceID := conn.ID()
name := conn.Name()
batch := make([]protocol.FileInfo, 0, indexBatchSize)
currentBatchSize := 0
initial := minLocalVer == 0
maxLocalVer := minLocalVer
initial := minSequence == 0
maxSequence := minSequence
var err error
sorter := NewIndexSorter(dbLocation)
@ -1270,12 +1270,12 @@ func sendIndexTo(minLocalVer int64, conn protocol.Connection, folder string, fs
fs.WithHave(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
f := fi.(protocol.FileInfo)
if f.LocalVersion <= minLocalVer {
if f.Sequence <= minSequence {
return true
}
if f.LocalVersion > maxLocalVer {
maxLocalVer = f.LocalVersion
if f.Sequence > maxSequence {
maxSequence = f.Sequence
}
if ignores.Match(f.Name).IsIgnored() || symlinkInvalid(folder, f) {
@ -1323,7 +1323,7 @@ func sendIndexTo(minLocalVer int64, conn protocol.Connection, folder string, fs
}
}
return maxLocalVer, err
return maxSequence, err
}
func (m *Model) updateLocalsFromScanning(folder string, fs []protocol.FileInfo) {
@ -1360,7 +1360,7 @@ func (m *Model) updateLocals(folder string, fs []protocol.FileInfo) {
"folder": folder,
"items": len(fs),
"filenames": filenames,
"version": files.LocalVersion(protocol.LocalDeviceID),
"version": files.Sequence(protocol.LocalDeviceID),
})
}
@ -1751,13 +1751,13 @@ func (m *Model) generateClusterConfig(device protocol.DeviceID) protocol.Cluster
deviceCfg := m.cfg.Devices()[device]
var indexID protocol.IndexID
var maxLocalVersion int64
var maxSequence int64
if device == m.id {
indexID = fs.IndexID(protocol.LocalDeviceID)
maxLocalVersion = fs.LocalVersion(protocol.LocalDeviceID)
maxSequence = fs.Sequence(protocol.LocalDeviceID)
} else {
indexID = fs.IndexID(device)
maxLocalVersion = fs.LocalVersion(device)
maxSequence = fs.Sequence(device)
}
protocolDevice := protocol.Device{
@ -1768,7 +1768,7 @@ func (m *Model) generateClusterConfig(device protocol.DeviceID) protocol.Cluster
CertName: deviceCfg.CertName,
Introducer: deviceCfg.Introducer,
IndexID: indexID,
MaxLocalVersion: maxLocalVersion,
MaxSequence: maxSequence,
}
protocolFolder.Devices = append(protocolFolder.Devices, protocolDevice)
@ -1823,7 +1823,7 @@ func (m *Model) Override(folder string) {
have.Version = have.Version.Merge(need.Version).Update(m.shortID)
need = have
}
need.LocalVersion = 0
need.Sequence = 0
batch = append(batch, need)
return true
})
@ -1833,10 +1833,10 @@ func (m *Model) Override(folder string) {
runner.setState(FolderIdle)
}
// CurrentLocalVersion returns the change version for the given folder.
// CurrentSequence returns the change version for the given folder.
// This is guaranteed to increment if the contents of the local folder has
// changed.
func (m *Model) CurrentLocalVersion(folder string) (int64, bool) {
func (m *Model) CurrentSequence(folder string) (int64, bool) {
m.fmut.RLock()
fs, ok := m.folderFiles[folder]
m.fmut.RUnlock()
@ -1846,13 +1846,13 @@ func (m *Model) CurrentLocalVersion(folder string) (int64, bool) {
return 0, false
}
return fs.LocalVersion(protocol.LocalDeviceID), true
return fs.Sequence(protocol.LocalDeviceID), true
}
// RemoteLocalVersion returns the change version for the given folder, as
// RemoteSequence returns the change version for the given folder, as
// sent by remote peers. This is guaranteed to increment if the contents of
// the remote or global folder has changed.
func (m *Model) RemoteLocalVersion(folder string) (int64, bool) {
func (m *Model) RemoteSequence(folder string) (int64, bool) {
m.fmut.RLock()
defer m.fmut.RUnlock()
@ -1865,7 +1865,7 @@ func (m *Model) RemoteLocalVersion(folder string) (int64, bool) {
var ver int64
for _, n := range m.folderDevices[folder] {
ver += fs.LocalVersion(n)
ver += fs.Sequence(n)
}
return ver, true

View File

@ -179,7 +179,7 @@ func (f *rwFolder) Serve() {
f.setState(FolderIdle)
}()
var prevVer int64
var prevSec int64
var prevIgnoreHash string
for {
@ -188,7 +188,7 @@ func (f *rwFolder) Serve() {
return
case <-f.remoteIndex:
prevVer = 0
prevSec = 0
f.pullTimer.Reset(0)
l.Debugln(f, "remote index updated, rescheduling pull")
@ -210,14 +210,14 @@ func (f *rwFolder) Serve() {
// The ignore patterns have changed. We need to re-evaluate if
// there are files we need now that were ignored before.
l.Debugln(f, "ignore patterns have changed, resetting prevVer")
prevVer = 0
prevSec = 0
prevIgnoreHash = newHash
}
// RemoteLocalVersion() is a fast call, doesn't touch the database.
curVer, ok := f.model.RemoteLocalVersion(f.folderID)
if !ok || curVer == prevVer {
l.Debugln(f, "skip (curVer == prevVer)", prevVer, ok)
// RemoteSequence() is a fast call, doesn't touch the database.
curSeq, ok := f.model.RemoteSequence(f.folderID)
if !ok || curSeq == prevSec {
l.Debugln(f, "skip (curSeq == prevSeq)", prevSec, ok)
f.pullTimer.Reset(f.sleep)
continue
}
@ -228,7 +228,7 @@ func (f *rwFolder) Serve() {
continue
}
l.Debugln(f, "pulling", prevVer, curVer)
l.Debugln(f, "pulling", prevSec, curSeq)
f.setState(FolderSyncing)
f.clearErrors()
@ -245,19 +245,19 @@ func (f *rwFolder) Serve() {
// sync. Remember the local version number and
// schedule a resync a little bit into the future.
if lv, ok := f.model.RemoteLocalVersion(f.folderID); ok && lv < curVer {
if lv, ok := f.model.RemoteSequence(f.folderID); ok && lv < curSeq {
// There's a corner case where the device we needed
// files from disconnected during the puller
// iteration. The files will have been removed from
// the index, so we've concluded that we don't need
// them, but at the same time we have the local
// version that includes those files in curVer. So we
// catch the case that localVersion might have
// catch the case that sequence might have
// decreased here.
l.Debugln(f, "adjusting curVer", lv)
curVer = lv
curSeq = lv
}
prevVer = curVer
prevSec = curSeq
l.Debugln(f, "next pull in", f.sleep)
f.pullTimer.Reset(f.sleep)
break
@ -1422,7 +1422,7 @@ loop:
break loop
}
job.file.LocalVersion = 0
job.file.Sequence = 0
batch = append(batch, job)
if len(batch) == maxBatchSize {

View File

@ -21,7 +21,7 @@ const (
maxBytesInMemory = 512 << 10
)
// The IndexSorter sorts FileInfos based on their LocalVersion. You use it
// The IndexSorter sorts FileInfos based on their Sequence. You use it
// by first Append()ing all entries to be sorted, then calling Sorted()
// which will iterate over all the items in correctly sorted order.
type IndexSorter interface {
@ -88,7 +88,7 @@ func (s *inMemoryIndexSorter) Append(f protocol.FileInfo) {
}
func (s *inMemoryIndexSorter) Sorted(fn func(protocol.FileInfo) bool) {
sort.Sort(byLocalVersion(s.files))
sort.Sort(bySequence(s.files))
for _, f := range s.files {
if !fn(f) {
break
@ -109,22 +109,22 @@ func (s *inMemoryIndexSorter) copyTo(dst IndexSorter) {
}
}
// byLocalVersion sorts FileInfos by LocalVersion
type byLocalVersion []protocol.FileInfo
// bySequence sorts FileInfos by Sequence
type bySequence []protocol.FileInfo
func (l byLocalVersion) Len() int {
func (l bySequence) Len() int {
return len(l)
}
func (l byLocalVersion) Swap(a, b int) {
func (l bySequence) Swap(a, b int) {
l[a], l[b] = l[b], l[a]
}
func (l byLocalVersion) Less(a, b int) bool {
return l[a].LocalVersion < l[b].LocalVersion
func (l bySequence) Less(a, b int) bool {
return l[a].Sequence < l[b].Sequence
}
// An onDiskIndexSorter is backed by a LevelDB database in the temporary
// directory. It relies on the fact that iterating over the database is done
// in key order and uses the LocalVersion as key. When done with an
// in key order and uses the Sequence as key. When done with an
// onDiskIndexSorter you must call Close() to remove the temporary database.
type onDiskIndexSorter struct {
db *leveldb.DB
@ -158,7 +158,7 @@ func newOnDiskIndexSorter(location string) *onDiskIndexSorter {
func (s *onDiskIndexSorter) Append(f protocol.FileInfo) {
key := make([]byte, 8)
binary.BigEndian.PutUint64(key[:], uint64(f.LocalVersion))
binary.BigEndian.PutUint64(key[:], uint64(f.Sequence))
data, err := f.Marshal()
if err != nil {
panic("bug: marshalling FileInfo should never fail: " + err.Error())

View File

@ -95,7 +95,7 @@ func TestIndexSorter(t *testing.T) {
verifySorted(t, s, nFiles+1)
}
// addFiles adds files with random LocalVersion to the Sorter.
// addFiles adds files with random Sequence to the Sorter.
func addFiles(n int, s IndexSorter) {
for i := 0; i < n; i++ {
rnd := rand.Int63()
@ -104,7 +104,7 @@ func addFiles(n int, s IndexSorter) {
Size: rand.Int63(),
Permissions: uint32(rand.Intn(0777)),
Modified: rand.Int63(),
LocalVersion: rnd,
Sequence: rnd,
Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: uint64(rand.Int63())}}},
Blocks: []protocol.BlockInfo{{
Size: int32(rand.Intn(128 << 10)),
@ -115,15 +115,15 @@ func addFiles(n int, s IndexSorter) {
}
}
// verifySorted checks that the files are returned sorted by LocalVersion.
// verifySorted checks that the files are returned sorted by Sequence.
func verifySorted(t *testing.T, s IndexSorter, expected int) {
prevLocalVer := int64(-1)
prevSequence := int64(-1)
seen := 0
s.Sorted(func(f protocol.FileInfo) bool {
if f.LocalVersion <= prevLocalVer {
t.Fatalf("Unsorted LocalVer, %d <= %d", f.LocalVersion, prevLocalVer)
if f.Sequence <= prevSequence {
t.Fatalf("Unsorted Sequence, %d <= %d", f.Sequence, prevSequence)
}
prevLocalVer = f.LocalVersion
prevSequence = f.Sequence
seen++
return true
})
@ -134,11 +134,11 @@ func verifySorted(t *testing.T, s IndexSorter, expected int) {
// verifyBreak checks that the Sorter stops iteration once we return false.
func verifyBreak(t *testing.T, s IndexSorter, expected int) {
prevLocalVer := int64(-1)
prevSequence := int64(-1)
seen := 0
s.Sorted(func(f protocol.FileInfo) bool {
if f.LocalVersion <= prevLocalVer {
t.Fatalf("Unsorted LocalVer, %d <= %d", f.LocalVersion, prevLocalVer)
if f.Sequence <= prevSequence {
t.Fatalf("Unsorted Sequence, %d <= %d", f.Sequence, prevSequence)
}
if len(f.Blocks) != 1 {
t.Fatalf("incorrect number of blocks %d != 1", len(f.Blocks))
@ -146,7 +146,7 @@ func verifyBreak(t *testing.T, s IndexSorter, expected int) {
if len(f.Version.Counters) != 1 {
t.Fatalf("incorrect number of version counters %d != 1", len(f.Version.Counters))
}
prevLocalVer = f.LocalVersion
prevSequence = f.Sequence
seen++
return seen < expected/2
})

View File

@ -260,7 +260,7 @@ type Device struct {
Addresses []string `protobuf:"bytes,3,rep,name=addresses" json:"addresses,omitempty"`
Compression Compression `protobuf:"varint,4,opt,name=compression,proto3,enum=protocol.Compression" json:"compression,omitempty"`
CertName string `protobuf:"bytes,5,opt,name=cert_name,json=certName,proto3" json:"cert_name,omitempty"`
MaxLocalVersion int64 `protobuf:"varint,6,opt,name=max_local_version,json=maxLocalVersion,proto3" json:"max_local_version,omitempty"`
MaxSequence int64 `protobuf:"varint,6,opt,name=max_sequence,json=maxSequence,proto3" json:"max_sequence,omitempty"`
Introducer bool `protobuf:"varint,7,opt,name=introducer,proto3" json:"introducer,omitempty"`
IndexID IndexID `protobuf:"varint,8,opt,name=index_id,json=indexId,proto3,customtype=IndexID" json:"index_id"`
}
@ -300,7 +300,7 @@ type FileInfo struct {
Invalid bool `protobuf:"varint,7,opt,name=invalid,proto3" json:"invalid,omitempty"`
NoPermissions bool `protobuf:"varint,8,opt,name=no_permissions,json=noPermissions,proto3" json:"no_permissions,omitempty"`
Version Vector `protobuf:"bytes,9,opt,name=version" json:"version"`
LocalVersion int64 `protobuf:"varint,10,opt,name=local_version,json=localVersion,proto3" json:"local_version,omitempty"`
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
Blocks []BlockInfo `protobuf:"bytes,16,rep,name=Blocks,json=blocks" json:"Blocks"`
}
@ -658,10 +658,10 @@ func (m *Device) MarshalTo(data []byte) (int, error) {
i = encodeVarintBep(data, i, uint64(len(m.CertName)))
i += copy(data[i:], m.CertName)
}
if m.MaxLocalVersion != 0 {
if m.MaxSequence != 0 {
data[i] = 0x30
i++
i = encodeVarintBep(data, i, uint64(m.MaxLocalVersion))
i = encodeVarintBep(data, i, uint64(m.MaxSequence))
}
if m.Introducer {
data[i] = 0x38
@ -832,10 +832,10 @@ func (m *FileInfo) MarshalTo(data []byte) (int, error) {
return 0, err
}
i += n1
if m.LocalVersion != 0 {
if m.Sequence != 0 {
data[i] = 0x50
i++
i = encodeVarintBep(data, i, uint64(m.LocalVersion))
i = encodeVarintBep(data, i, uint64(m.Sequence))
}
if len(m.Blocks) > 0 {
for _, msg := range m.Blocks {
@ -1288,8 +1288,8 @@ func (m *Device) ProtoSize() (n int) {
if l > 0 {
n += 1 + l + sovBep(uint64(l))
}
if m.MaxLocalVersion != 0 {
n += 1 + sovBep(uint64(m.MaxLocalVersion))
if m.MaxSequence != 0 {
n += 1 + sovBep(uint64(m.MaxSequence))
}
if m.Introducer {
n += 2
@ -1362,8 +1362,8 @@ func (m *FileInfo) ProtoSize() (n int) {
}
l = m.Version.ProtoSize()
n += 1 + l + sovBep(uint64(l))
if m.LocalVersion != 0 {
n += 1 + sovBep(uint64(m.LocalVersion))
if m.Sequence != 0 {
n += 1 + sovBep(uint64(m.Sequence))
}
if len(m.Blocks) > 0 {
for _, e := range m.Blocks {
@ -2218,9 +2218,9 @@ func (m *Device) Unmarshal(data []byte) error {
iNdEx = postIndex
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field MaxLocalVersion", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field MaxSequence", wireType)
}
m.MaxLocalVersion = 0
m.MaxSequence = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowBep
@ -2230,7 +2230,7 @@ func (m *Device) Unmarshal(data []byte) error {
}
b := data[iNdEx]
iNdEx++
m.MaxLocalVersion |= (int64(b) & 0x7F) << shift
m.MaxSequence |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
@ -2741,9 +2741,9 @@ func (m *FileInfo) Unmarshal(data []byte) error {
iNdEx = postIndex
case 10:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field LocalVersion", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType)
}
m.LocalVersion = 0
m.Sequence = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowBep
@ -2753,7 +2753,7 @@ func (m *FileInfo) Unmarshal(data []byte) error {
}
b := data[iNdEx]
iNdEx++
m.LocalVersion |= (int64(b) & 0x7F) << shift
m.Sequence |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
@ -3927,103 +3927,103 @@ var (
var fileDescriptorBep = []byte{
// 1569 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x6f, 0x1b, 0x45,
0x14, 0x8f, 0xed, 0xf5, 0xbf, 0x89, 0x93, 0x3a, 0xd3, 0x34, 0x35, 0xdb, 0x90, 0x84, 0x6d, 0x2b,
0x82, 0x45, 0x53, 0x68, 0x81, 0x4a, 0x48, 0x20, 0x39, 0xf6, 0x26, 0xb5, 0xea, 0xac, 0xdd, 0xb5,
0x9d, 0x52, 0x0e, 0x58, 0x6b, 0xef, 0xd8, 0x59, 0x75, 0xbd, 0x63, 0x76, 0xd7, 0x6d, 0xc3, 0x17,
0x40, 0x82, 0x2f, 0xc0, 0x05, 0xa9, 0x57, 0xc4, 0x95, 0x0f, 0xd1, 0x63, 0xd5, 0x23, 0x87, 0x0a,
0xc2, 0x85, 0x2f, 0xc0, 0x9d, 0x37, 0x33, 0xbb, 0xde, 0x75, 0xfe, 0xa0, 0x1e, 0x38, 0x58, 0x9e,
0x79, 0xef, 0x37, 0x6f, 0x66, 0x7e, 0xef, 0xf7, 0xde, 0x2c, 0xca, 0xf7, 0xc9, 0x64, 0x67, 0xe2,
0x52, 0x9f, 0xe2, 0x1c, 0xff, 0x1b, 0x50, 0x5b, 0xbe, 0x35, 0xb2, 0xfc, 0xa3, 0x69, 0x7f, 0x67,
0x40, 0xc7, 0xb7, 0x47, 0x74, 0x44, 0x6f, 0x73, 0x4f, 0x7f, 0x3a, 0xe4, 0x33, 0x3e, 0xe1, 0x23,
0xb1, 0x50, 0x99, 0xa0, 0xf4, 0x7d, 0x62, 0xdb, 0x14, 0x6f, 0xa2, 0x45, 0x93, 0x3c, 0xb5, 0x06,
0xa4, 0xe7, 0x18, 0x63, 0x52, 0x4a, 0x6c, 0x25, 0xb6, 0xf3, 0x3a, 0x12, 0x26, 0x0d, 0x2c, 0x0c,
0x30, 0xb0, 0x2d, 0xe2, 0xf8, 0x02, 0x90, 0x14, 0x00, 0x61, 0xe2, 0x80, 0x9b, 0x68, 0x39, 0x00,
0x3c, 0x25, 0xae, 0x67, 0x51, 0xa7, 0x94, 0xe2, 0x98, 0x25, 0x61, 0x3d, 0x14, 0x46, 0xc5, 0x43,
0x99, 0xfb, 0xc4, 0x30, 0x89, 0x8b, 0x3f, 0x40, 0x92, 0x7f, 0x3c, 0x11, 0x7b, 0x2d, 0xdf, 0xb9,
0xb2, 0x13, 0xde, 0x61, 0xe7, 0x80, 0x78, 0x9e, 0x31, 0x22, 0x1d, 0x70, 0xea, 0x1c, 0x82, 0xbf,
0x84, 0xcd, 0xe9, 0x78, 0xe2, 0x82, 0x83, 0x05, 0x4e, 0xf2, 0x15, 0xeb, 0x67, 0x56, 0x54, 0x23,
0x8c, 0x1e, 0x5f, 0xa0, 0x54, 0xd0, 0x52, 0xd5, 0x9e, 0x7a, 0x3e, 0x71, 0xab, 0xd4, 0x19, 0x5a,
0x23, 0xfc, 0x11, 0xca, 0x0e, 0xa9, 0x0d, 0xa7, 0xf0, 0x60, 0xfb, 0xd4, 0xf6, 0xe2, 0x9d, 0x62,
0x14, 0x6c, 0x8f, 0x3b, 0x76, 0xa5, 0x97, 0x6f, 0x36, 0x17, 0xf4, 0x10, 0xa6, 0xfc, 0x98, 0x44,
0x19, 0xe1, 0xc1, 0x6b, 0x28, 0x69, 0x99, 0x82, 0xa2, 0xdd, 0xcc, 0xc9, 0x9b, 0xcd, 0x64, 0xbd,
0xa6, 0x83, 0x05, 0xaf, 0xa2, 0xb4, 0x6d, 0xf4, 0x89, 0x1d, 0x90, 0x23, 0x26, 0xf8, 0x1a, 0xca,
0xbb, 0x70, 0xe1, 0x1e, 0x75, 0xec, 0x63, 0x4e, 0x49, 0x4e, 0xcf, 0x31, 0x43, 0x13, 0xe6, 0xf8,
0x16, 0xc2, 0xd6, 0xc8, 0xa1, 0x2e, 0xe9, 0x4d, 0x88, 0x3b, 0xb6, 0xf8, 0x69, 0xbd, 0x92, 0xc4,
0x51, 0x2b, 0xc2, 0xd3, 0x8a, 0x1c, 0xf8, 0x3a, 0x5a, 0x0a, 0xe0, 0x26, 0xb1, 0x89, 0x4f, 0x4a,
0x69, 0x8e, 0x2c, 0x08, 0x63, 0x8d, 0xdb, 0xe0, 0x6e, 0xab, 0xa6, 0xe5, 0x19, 0x7d, 0x9b, 0xf4,
0x7c, 0x32, 0x9e, 0xf4, 0x2c, 0xc7, 0x24, 0xcf, 0x89, 0x57, 0xca, 0x70, 0x2c, 0x0e, 0x7c, 0x1d,
0x70, 0xd5, 0x85, 0x87, 0xb1, 0x21, 0x32, 0xed, 0x95, 0x8a, 0xa7, 0xd9, 0xa8, 0x71, 0x47, 0xc8,
0x46, 0x00, 0x53, 0x7e, 0x05, 0x36, 0x84, 0x27, 0xc6, 0x46, 0x61, 0x8e, 0x0d, 0x8c, 0xa4, 0x98,
0x52, 0xf8, 0x18, 0xaf, 0xa3, 0xbc, 0x61, 0x9a, 0x2c, 0x2b, 0xb0, 0x55, 0x0a, 0xb6, 0xca, 0xeb,
0x91, 0x01, 0xdf, 0x9b, 0xcf, 0xb2, 0x74, 0x5a, 0x17, 0x17, 0xa5, 0x97, 0x51, 0x3c, 0x20, 0x6e,
0xa0, 0xcc, 0x34, 0xdf, 0x2f, 0xc7, 0x0c, 0x5c, 0x97, 0x65, 0xb4, 0x32, 0x36, 0x9e, 0xf7, 0x6c,
0x3a, 0x30, 0xec, 0x99, 0x34, 0x19, 0x17, 0x29, 0xfd, 0x12, 0x38, 0x1a, 0xcc, 0x1e, 0x88, 0x13,
0x6f, 0x20, 0x64, 0x39, 0xbe, 0x4b, 0xcd, 0x29, 0x2c, 0x2f, 0x65, 0x39, 0x61, 0x31, 0x0b, 0xfe,
0x14, 0xe5, 0x38, 0x9b, 0x3d, 0xb8, 0x71, 0x0e, 0xbc, 0xd2, 0xae, 0xcc, 0x78, 0xf9, 0xfd, 0xcd,
0x66, 0x96, 0x73, 0x59, 0xaf, 0x9d, 0x44, 0x43, 0x3d, 0xcb, 0xb1, 0x75, 0x53, 0x69, 0xa2, 0x34,
0xb7, 0x01, 0x57, 0x19, 0xa1, 0xa7, 0xa0, 0xc0, 0x82, 0x19, 0xde, 0x41, 0xe9, 0xa1, 0x65, 0x03,
0x27, 0x49, 0x4e, 0x3f, 0x8e, 0x89, 0x11, 0xcc, 0x75, 0x67, 0x48, 0x83, 0x04, 0x08, 0x98, 0xd2,
0x45, 0x8b, 0x3c, 0x60, 0x77, 0x62, 0x1a, 0x3e, 0xf9, 0xdf, 0xc2, 0x7e, 0x9f, 0x42, 0xb9, 0xd0,
0x33, 0xcb, 0x5f, 0x22, 0x96, 0xbf, 0x72, 0x50, 0xb2, 0xa2, 0x00, 0xd7, 0xce, 0xc6, 0x8b, 0xd5,
0x2c, 0xac, 0xf7, 0xac, 0xef, 0x08, 0x97, 0x7c, 0x4a, 0xe7, 0x63, 0xbc, 0x85, 0x16, 0x4f, 0xeb,
0x7c, 0x49, 0x8f, 0x9b, 0xb0, 0x8c, 0x72, 0x63, 0x6a, 0x5a, 0x43, 0x8b, 0x98, 0x3c, 0x93, 0x29,
0x7d, 0x36, 0xc7, 0x25, 0x26, 0x53, 0x26, 0x71, 0x33, 0xd0, 0x72, 0x38, 0x65, 0x1e, 0xcb, 0x79,
0x6a, 0xd8, 0x90, 0x16, 0x91, 0xb4, 0x70, 0xca, 0xba, 0x92, 0x43, 0xe7, 0x8a, 0x2b, 0xc7, 0x01,
0x4b, 0x0e, 0x8d, 0x17, 0x16, 0x54, 0x40, 0x28, 0x8d, 0x3c, 0xf8, 0xe7, 0x2a, 0xe0, 0x90, 0x0c,
0x7c, 0x3a, 0xeb, 0x07, 0x01, 0x8c, 0x95, 0xe2, 0xbc, 0xa4, 0x10, 0x3f, 0x6d, 0xc1, 0x8e, 0xeb,
0xe9, 0x63, 0x94, 0xd9, 0x05, 0xc3, 0x93, 0xb0, 0xae, 0x2e, 0x47, 0x51, 0xb9, 0x3d, 0x96, 0x82,
0x4c, 0x9f, 0x03, 0x3f, 0x97, 0x7e, 0x7a, 0xb1, 0xb9, 0xa0, 0x3c, 0x44, 0xf9, 0x19, 0x80, 0xa5,
0x97, 0x0e, 0x87, 0x1e, 0xf1, 0x79, 0x2e, 0x52, 0x7a, 0x30, 0x9b, 0x31, 0xcc, 0xb2, 0x91, 0x0e,
0x18, 0x06, 0xdb, 0x91, 0xe1, 0x1d, 0x71, 0xd6, 0x0b, 0x3a, 0x1f, 0x07, 0x21, 0xbf, 0x40, 0x19,
0x71, 0x13, 0x7c, 0x17, 0xe5, 0x06, 0x74, 0xea, 0xf8, 0x51, 0xf7, 0x5b, 0x89, 0x17, 0x19, 0xf7,
0x04, 0xa7, 0x9a, 0x01, 0x95, 0x3d, 0x94, 0x0d, 0x5c, 0xc0, 0x69, 0x58, 0xf1, 0xd2, 0xee, 0x95,
0x50, 0xff, 0xed, 0x23, 0xea, 0xfa, 0x5c, 0xff, 0xb1, 0x76, 0x08, 0x39, 0x98, 0x8a, 0xf3, 0x49,
0xba, 0x98, 0x28, 0xbf, 0x25, 0x50, 0x56, 0x27, 0xdf, 0x4e, 0x89, 0xe7, 0xc7, 0x5a, 0x47, 0x7a,
0xae, 0x75, 0x44, 0x7a, 0x4e, 0xce, 0xe9, 0x39, 0x94, 0x64, 0x2a, 0x26, 0xc9, 0x88, 0x1c, 0xe9,
0x5c, 0x72, 0xd2, 0xe7, 0x90, 0x93, 0x89, 0xc8, 0x61, 0x02, 0x19, 0xba, 0x74, 0xcc, 0x5b, 0x25,
0x75, 0x0d, 0xf7, 0x38, 0x50, 0xd0, 0x12, 0xb3, 0x76, 0x42, 0xa3, 0xd2, 0x43, 0x39, 0x9d, 0x78,
0x13, 0xd0, 0x0a, 0xb9, 0xf0, 0xd8, 0x10, 0x1e, 0xca, 0xd1, 0xe0, 0x87, 0x86, 0xf0, 0x6c, 0x8c,
0xdf, 0x47, 0xd2, 0x80, 0x9a, 0xe2, 0xc8, 0xcb, 0xf1, 0xfc, 0xab, 0xae, 0x4b, 0xe1, 0x35, 0x32,
0xa1, 0x5c, 0x18, 0x00, 0x5e, 0xe2, 0x62, 0x8d, 0x3e, 0x73, 0x6c, 0x6a, 0x98, 0x2d, 0x97, 0x8e,
0x58, 0x6b, 0xbb, 0xb0, 0xae, 0x6b, 0x28, 0x3b, 0xe5, 0x95, 0x1f, 0x56, 0xf6, 0x8d, 0xf9, 0x4a,
0x3c, 0x1d, 0x48, 0xb4, 0x89, 0x50, 0xc1, 0xc1, 0x52, 0xe5, 0x75, 0x02, 0xc9, 0x17, 0xa3, 0x71,
0x1d, 0x2d, 0x0a, 0x64, 0x2f, 0xf6, 0x4a, 0x6f, 0xbf, 0xcd, 0x46, 0xbc, 0x09, 0xa0, 0xe9, 0x6c,
0x7c, 0xee, 0x53, 0x10, 0xab, 0xb8, 0xd4, 0x5b, 0x57, 0x1c, 0xaf, 0x91, 0xd9, 0x83, 0x26, 0xc1,
0xdd, 0xd3, 0x7a, 0xa1, 0x2f, 0x0a, 0x85, 0xdb, 0x94, 0x0c, 0x92, 0x5a, 0x96, 0x33, 0x52, 0x36,
0x51, 0xba, 0x6a, 0x53, 0x9e, 0xac, 0x0c, 0xbc, 0xb6, 0x1e, 0x6c, 0x13, 0x70, 0x28, 0x66, 0xe5,
0xd7, 0x49, 0xb4, 0x18, 0xfb, 0xd0, 0x80, 0xf3, 0x2c, 0x57, 0x1b, 0xdd, 0x76, 0x47, 0xd5, 0x7b,
0xd5, 0xa6, 0xb6, 0x57, 0xdf, 0x2f, 0x2e, 0xc8, 0xeb, 0x3f, 0xfc, 0xbc, 0x55, 0x1a, 0x47, 0xa0,
0xf9, 0x6f, 0x08, 0xd8, 0xa2, 0xae, 0xd5, 0xd4, 0xaf, 0x8a, 0x09, 0x79, 0x15, 0x80, 0xc5, 0x18,
0x50, 0x74, 0xfb, 0x0f, 0x51, 0x81, 0x03, 0x7a, 0xdd, 0x56, 0xad, 0xd2, 0x51, 0x8b, 0x49, 0x59,
0x06, 0xdc, 0xda, 0x69, 0x5c, 0xc0, 0xf7, 0x75, 0xa8, 0x0b, 0xf5, 0x61, 0x57, 0x6d, 0x77, 0x8a,
0x29, 0x79, 0x0d, 0x80, 0x38, 0x06, 0x0c, 0x2b, 0xe6, 0x26, 0xc8, 0x50, 0x6d, 0xb7, 0x9a, 0x5a,
0x5b, 0x2d, 0x4a, 0xf2, 0x55, 0x40, 0x5d, 0x9e, 0x43, 0x05, 0x0a, 0xfd, 0x0c, 0xad, 0xd4, 0x9a,
0x8f, 0xb4, 0x46, 0xb3, 0x52, 0xeb, 0xb5, 0xf4, 0xe6, 0x3e, 0xac, 0x69, 0x17, 0xd3, 0xf2, 0x26,
0xe0, 0xaf, 0xc5, 0xf0, 0x67, 0x04, 0xf7, 0x2e, 0xb0, 0x57, 0xd7, 0xf6, 0x8b, 0x19, 0xf9, 0x32,
0x40, 0x2f, 0xc5, 0xa0, 0x8c, 0x54, 0x76, 0xe3, 0x6a, 0xa3, 0x09, 0x5b, 0x67, 0xcf, 0xdc, 0x98,
0x93, 0x5d, 0xfe, 0x06, 0xe1, 0xb3, 0x9f, 0x62, 0xf8, 0x06, 0x92, 0xb4, 0xa6, 0xa6, 0x02, 0xa1,
0xfc, 0xfe, 0x67, 0x11, 0x1a, 0x75, 0x08, 0x56, 0x50, 0xaa, 0xf1, 0xf5, 0x27, 0x40, 0xe6, 0x3b,
0x00, 0xba, 0x72, 0x16, 0x04, 0xce, 0x32, 0x45, 0x8b, 0xf1, 0xc0, 0x0a, 0xca, 0x1d, 0xa8, 0x9d,
0x0a, 0x90, 0x5b, 0x81, 0xe0, 0xfc, 0x48, 0xa1, 0xfb, 0x80, 0xf8, 0x06, 0x2f, 0xc0, 0x75, 0x94,
0xd6, 0xd4, 0x43, 0x55, 0x87, 0xc0, 0x2b, 0x00, 0x58, 0x0a, 0x01, 0x1a, 0x01, 0x5d, 0xc1, 0x83,
0x9f, 0xa9, 0x34, 0x1e, 0x55, 0x1e, 0xb7, 0x21, 0x39, 0x18, 0xdc, 0xcb, 0xa1, 0xbb, 0x62, 0x3f,
0x33, 0x8e, 0xbd, 0xf2, 0x3f, 0x09, 0x54, 0x88, 0xbf, 0x6d, 0xb0, 0x40, 0xda, 0xab, 0x37, 0xd4,
0x70, 0xbb, 0xb8, 0x8f, 0x8d, 0xf1, 0x36, 0xca, 0xd7, 0xea, 0xba, 0x5a, 0xed, 0x34, 0xf5, 0xc7,
0xe1, 0x5d, 0xe2, 0xa0, 0x9a, 0xe5, 0x72, 0x71, 0xb3, 0x4f, 0xbf, 0x42, 0xfb, 0xf1, 0x41, 0xa3,
0xae, 0x3d, 0xe8, 0xf1, 0x88, 0x49, 0xf9, 0x1a, 0x80, 0xaf, 0xc6, 0xc1, 0xed, 0xe3, 0xb1, 0x6d,
0x39, 0x4f, 0x78, 0xe0, 0x7b, 0x68, 0x25, 0x84, 0x47, 0x1b, 0xa4, 0xe4, 0x2d, 0x58, 0xb3, 0x7e,
0xce, 0x9a, 0x68, 0x9f, 0xbb, 0xe8, 0x52, 0xb8, 0xb0, 0xab, 0x3d, 0xd0, 0x40, 0x16, 0xa0, 0x9c,
0x0d, 0x58, 0x26, 0x9f, 0xb3, 0xac, 0xeb, 0x3c, 0x71, 0x40, 0x14, 0xe5, 0x5f, 0x12, 0x28, 0x3f,
0xeb, 0x50, 0x8c, 0x67, 0xad, 0xd9, 0x53, 0x75, 0xbd, 0xa9, 0x87, 0x17, 0x9f, 0x39, 0x35, 0xca,
0x87, 0xf8, 0x3d, 0x94, 0xdd, 0x57, 0x35, 0x55, 0xaf, 0x57, 0xc3, 0x7a, 0x98, 0x41, 0xf6, 0x89,
0x43, 0x5c, 0x6b, 0x00, 0x1f, 0xfc, 0x05, 0x08, 0xd3, 0xee, 0x56, 0xef, 0x87, 0x37, 0xe6, 0x02,
0x8e, 0x85, 0x6a, 0x4f, 0x07, 0x47, 0xfc, 0xb6, 0x65, 0x56, 0x3a, 0x87, 0x95, 0x46, 0xbd, 0x26,
0xa0, 0x29, 0xb9, 0x04, 0xd0, 0xd5, 0x19, 0xb4, 0x2e, 0x9e, 0x77, 0x86, 0x2d, 0x9b, 0x68, 0xe3,
0xbf, 0x7b, 0x11, 0x7c, 0x76, 0x64, 0x2a, 0xad, 0x96, 0xaa, 0xd5, 0xc2, 0xd3, 0x47, 0xbe, 0xca,
0x64, 0x42, 0x1c, 0x93, 0x21, 0xf6, 0x9a, 0xfa, 0xbe, 0xda, 0x09, 0x0f, 0x1f, 0x21, 0xf6, 0xa8,
0x3b, 0x22, 0xfe, 0xee, 0xfa, 0xcb, 0x3f, 0x37, 0x16, 0x5e, 0xc1, 0xef, 0xe5, 0xc9, 0x46, 0xe2,
0x15, 0xfc, 0xfe, 0x38, 0xd9, 0x58, 0xf8, 0x1b, 0xfe, 0x5f, 0xfc, 0xb5, 0x91, 0xe8, 0x67, 0x78,
0xef, 0xba, 0xfb, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5f, 0x7a, 0x46, 0xf6, 0x94, 0x0d, 0x00,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x6f, 0xdb, 0x46,
0x16, 0xb7, 0x24, 0x8a, 0x92, 0x46, 0xb2, 0x23, 0x4f, 0x1c, 0x47, 0xcb, 0x78, 0x6d, 0x2f, 0x93,
0x60, 0xbd, 0xc2, 0xc6, 0xd9, 0x4d, 0xda, 0x06, 0x28, 0xd0, 0x02, 0xb2, 0x44, 0x3b, 0x44, 0x64,
0x4a, 0xa1, 0x24, 0xa7, 0xe9, 0xa1, 0x02, 0x25, 0x8e, 0x64, 0x22, 0x14, 0x47, 0x25, 0xa9, 0x24,
0xee, 0x47, 0x68, 0xbf, 0x40, 0x2f, 0x05, 0x82, 0xde, 0x7a, 0xef, 0x87, 0xc8, 0x31, 0xc8, 0xb1,
0x87, 0xa0, 0x75, 0x2f, 0xfd, 0x02, 0xbd, 0x16, 0x7d, 0x9c, 0x21, 0x45, 0xca, 0x7f, 0x8a, 0x1c,
0x7a, 0x10, 0x34, 0xf3, 0xde, 0x6f, 0xde, 0xcc, 0xfc, 0xde, 0xef, 0xbd, 0x21, 0x2a, 0x0c, 0xc8,
0x74, 0x77, 0xea, 0x52, 0x9f, 0xe2, 0x3c, 0xfb, 0x1b, 0x52, 0x5b, 0xba, 0x33, 0xb6, 0xfc, 0xe3,
0xd9, 0x60, 0x77, 0x48, 0x27, 0x77, 0xc7, 0x74, 0x4c, 0xef, 0x32, 0xcf, 0x60, 0x36, 0x62, 0x33,
0x36, 0x61, 0x23, 0xbe, 0x50, 0x9e, 0xa2, 0xec, 0x43, 0x62, 0xdb, 0x14, 0x6f, 0xa1, 0xa2, 0x49,
0x9e, 0x5b, 0x43, 0xd2, 0x77, 0x8c, 0x09, 0xa9, 0xa4, 0xb6, 0x53, 0x3b, 0x05, 0x1d, 0x71, 0x93,
0x06, 0x96, 0x00, 0x30, 0xb4, 0x2d, 0xe2, 0xf8, 0x1c, 0x90, 0xe6, 0x00, 0x6e, 0x62, 0x80, 0xdb,
0x68, 0x25, 0x04, 0x3c, 0x27, 0xae, 0x67, 0x51, 0xa7, 0x92, 0x61, 0x98, 0x65, 0x6e, 0x3d, 0xe2,
0x46, 0xd9, 0x43, 0xe2, 0x43, 0x62, 0x98, 0xc4, 0xc5, 0xff, 0x41, 0x82, 0x7f, 0x32, 0xe5, 0x7b,
0xad, 0xdc, 0xbb, 0xb6, 0x1b, 0xdd, 0x61, 0xf7, 0x90, 0x78, 0x9e, 0x31, 0x26, 0x5d, 0x70, 0xea,
0x0c, 0x82, 0x3f, 0x85, 0xcd, 0xe9, 0x64, 0xea, 0x82, 0x23, 0x08, 0x9c, 0x66, 0x2b, 0x36, 0xce,
0xad, 0xa8, 0xc7, 0x18, 0x3d, 0xb9, 0x40, 0xae, 0xa1, 0xe5, 0xba, 0x3d, 0xf3, 0x7c, 0xe2, 0xd6,
0xa9, 0x33, 0xb2, 0xc6, 0xf8, 0x7f, 0x28, 0x37, 0xa2, 0x36, 0x9c, 0xc2, 0x83, 0xed, 0x33, 0x3b,
0xc5, 0x7b, 0xe5, 0x38, 0xd8, 0x3e, 0x73, 0xec, 0x09, 0xaf, 0xdf, 0x6d, 0x2d, 0xe9, 0x11, 0x4c,
0xfe, 0x26, 0x8d, 0x44, 0xee, 0xc1, 0xeb, 0x28, 0x6d, 0x99, 0x9c, 0xa2, 0x3d, 0xf1, 0xf4, 0xdd,
0x56, 0x5a, 0x6d, 0xe8, 0x60, 0xc1, 0x6b, 0x28, 0x6b, 0x1b, 0x03, 0x62, 0x87, 0xe4, 0xf0, 0x09,
0xbe, 0x81, 0x0a, 0x2e, 0x5c, 0xb8, 0x4f, 0x1d, 0xfb, 0x84, 0x51, 0x92, 0xd7, 0xf3, 0x81, 0xa1,
0x05, 0x73, 0x7c, 0x07, 0x61, 0x6b, 0xec, 0x50, 0x97, 0xf4, 0xa7, 0xc4, 0x9d, 0x58, 0xec, 0xb4,
0x5e, 0x45, 0x60, 0xa8, 0x55, 0xee, 0x69, 0xc7, 0x0e, 0x7c, 0x13, 0x2d, 0x87, 0x70, 0x93, 0xd8,
0xc4, 0x27, 0x95, 0x2c, 0x43, 0x96, 0xb8, 0xb1, 0xc1, 0x6c, 0x70, 0xb7, 0x35, 0xd3, 0xf2, 0x8c,
0x81, 0x4d, 0xfa, 0x3e, 0x99, 0x4c, 0xfb, 0x96, 0x63, 0x92, 0x97, 0xc4, 0xab, 0x88, 0x0c, 0x8b,
0x43, 0x5f, 0x17, 0x5c, 0x2a, 0xf7, 0x04, 0x6c, 0xf0, 0x4c, 0x7b, 0x95, 0xf2, 0x59, 0x36, 0x1a,
0xcc, 0x11, 0xb1, 0x11, 0xc2, 0xe4, 0xef, 0x81, 0x0d, 0xee, 0x49, 0xb0, 0x51, 0x5a, 0x60, 0x03,
0x23, 0x21, 0xa1, 0x14, 0x36, 0xc6, 0x1b, 0xa8, 0x60, 0x98, 0x66, 0x90, 0x15, 0xd8, 0x2a, 0x03,
0x5b, 0x15, 0xf4, 0xd8, 0x80, 0x1f, 0x2c, 0x66, 0x59, 0x38, 0xab, 0x8b, 0xcb, 0xd2, 0x1b, 0x50,
0x3c, 0x24, 0x6e, 0xa8, 0xcc, 0x2c, 0xdb, 0x2f, 0x1f, 0x18, 0x98, 0x2e, 0xff, 0x85, 0x4a, 0x13,
0xe3, 0x65, 0xdf, 0x23, 0x5f, 0xce, 0x88, 0x33, 0x24, 0x8c, 0x86, 0x8c, 0x5e, 0x04, 0x5b, 0x27,
0x34, 0xe1, 0x4d, 0x84, 0x2c, 0xc7, 0x77, 0xa9, 0x39, 0x83, 0x55, 0x95, 0x1c, 0xe3, 0x29, 0x61,
0xc1, 0x1f, 0xa2, 0x3c, 0x23, 0xb1, 0x0f, 0x17, 0xcd, 0x83, 0x57, 0xd8, 0x93, 0x02, 0x3a, 0x7e,
0x7a, 0xb7, 0x95, 0x63, 0x14, 0xaa, 0x8d, 0xd3, 0x78, 0xa8, 0xe7, 0x18, 0x56, 0x35, 0xe5, 0x16,
0xca, 0x32, 0x1b, 0x50, 0x24, 0x72, 0x19, 0x85, 0x75, 0x15, 0xce, 0xf0, 0x2e, 0xca, 0x8e, 0x2c,
0x1b, 0xa8, 0x48, 0x33, 0xd6, 0x71, 0x42, 0x83, 0x60, 0x56, 0x9d, 0x11, 0x0d, 0x79, 0xe7, 0x30,
0xb9, 0x87, 0x8a, 0x2c, 0x60, 0x6f, 0x6a, 0x1a, 0x3e, 0xf9, 0xdb, 0xc2, 0xfe, 0x91, 0x46, 0xf9,
0xc8, 0x33, 0x4f, 0x5b, 0x2a, 0x91, 0xb6, 0x6a, 0x58, 0xa9, 0xbc, 0xee, 0xd6, 0xcf, 0xc7, 0x4b,
0x94, 0x2a, 0xac, 0xf7, 0xac, 0xaf, 0x08, 0x53, 0x7a, 0x46, 0x67, 0x63, 0xbc, 0x8d, 0x8a, 0x67,
0xe5, 0xbd, 0xac, 0x27, 0x4d, 0x58, 0x42, 0xf9, 0x09, 0x35, 0xad, 0x91, 0x45, 0x4c, 0x96, 0xc0,
0x8c, 0x3e, 0x9f, 0xe3, 0x4a, 0xa0, 0xce, 0x40, 0xd9, 0x66, 0x28, 0xe1, 0x68, 0x1a, 0x78, 0x2c,
0xe7, 0xb9, 0x61, 0x43, 0x5a, 0x78, 0xd2, 0xa2, 0x69, 0xd0, 0x8c, 0x1c, 0xba, 0x50, 0x53, 0x79,
0x06, 0x58, 0x76, 0x68, 0xb2, 0x9e, 0x40, 0xf8, 0x51, 0xb3, 0x2a, 0x80, 0x7f, 0x41, 0xf8, 0x47,
0x64, 0xe8, 0xd3, 0x79, 0x1b, 0x08, 0x61, 0xc1, 0x41, 0xe7, 0x4a, 0x42, 0xfc, 0xa0, 0xd1, 0x1c,
0xff, 0x1f, 0x89, 0x7b, 0x36, 0x1d, 0x3e, 0x8b, 0xaa, 0xe8, 0x6a, 0x1c, 0x8c, 0xd9, 0x13, 0xcc,
0x8b, 0x03, 0x06, 0xfc, 0x58, 0xf8, 0xf6, 0xd5, 0xd6, 0x92, 0xfc, 0x18, 0x15, 0xe6, 0x80, 0x20,
0xab, 0x74, 0x34, 0xf2, 0x88, 0xcf, 0x52, 0x90, 0xd1, 0xc3, 0xd9, 0x9c, 0xd8, 0x20, 0x09, 0xd9,
0x90, 0x58, 0xb0, 0x1d, 0x1b, 0xde, 0x31, 0x23, 0xbb, 0xa4, 0xb3, 0x71, 0x18, 0xf2, 0x13, 0x24,
0xf2, 0x0b, 0xe0, 0xfb, 0x28, 0x3f, 0xa4, 0x33, 0xc7, 0x8f, 0x7b, 0xdd, 0x6a, 0xb2, 0xa4, 0x98,
0x27, 0x3c, 0xd5, 0x1c, 0x28, 0xef, 0xa3, 0x5c, 0xe8, 0x02, 0x2a, 0xa3, 0xfa, 0x16, 0xf6, 0xae,
0x45, 0xb2, 0xef, 0x1c, 0x53, 0xd7, 0x67, 0xb2, 0x4f, 0x34, 0x3f, 0xa0, 0x7e, 0xc6, 0xcf, 0x27,
0xe8, 0x7c, 0x22, 0xff, 0x98, 0x42, 0x39, 0x3d, 0xe0, 0xc7, 0xf3, 0x13, 0x8d, 0x22, 0xbb, 0xd0,
0x28, 0x62, 0x19, 0xa7, 0x17, 0x64, 0x1c, 0x29, 0x31, 0x93, 0x50, 0x62, 0x4c, 0x8e, 0x70, 0x21,
0x39, 0xd9, 0x0b, 0xc8, 0x11, 0x63, 0x72, 0x02, 0x5d, 0x8c, 0x5c, 0x3a, 0x61, 0x8d, 0x91, 0xba,
0x86, 0x7b, 0x12, 0x0a, 0x67, 0x39, 0xb0, 0x76, 0x23, 0xa3, 0xdc, 0x47, 0x79, 0x9d, 0x78, 0x53,
0x90, 0x08, 0xb9, 0xf4, 0xd8, 0x10, 0x1e, 0xaa, 0xd0, 0x60, 0x87, 0x86, 0xf0, 0xc1, 0x18, 0xff,
0x1b, 0x09, 0x43, 0x6a, 0xf2, 0x23, 0xaf, 0x24, 0xf3, 0xaf, 0xb8, 0x2e, 0x85, 0xb7, 0xc7, 0x84,
0x2a, 0x09, 0x00, 0xf0, 0xee, 0x96, 0x1b, 0xf4, 0x85, 0x63, 0x53, 0xc3, 0x6c, 0xbb, 0x74, 0x1c,
0x34, 0xb2, 0x4b, 0xcb, 0xb9, 0x81, 0x72, 0x33, 0x56, 0xf0, 0x51, 0x41, 0xdf, 0x5a, 0x2c, 0xc0,
0xb3, 0x81, 0x78, 0x77, 0x88, 0x84, 0x1b, 0x2e, 0x95, 0xdf, 0xa6, 0x90, 0x74, 0x39, 0x1a, 0xab,
0xa8, 0xc8, 0x91, 0xfd, 0xc4, 0x9b, 0xbc, 0xf3, 0x3e, 0x1b, 0xb1, 0xda, 0x47, 0xb3, 0xf9, 0xf8,
0xc2, 0xc6, 0x9f, 0x28, 0xb4, 0xcc, 0xfb, 0x15, 0x1a, 0x3c, 0x75, 0xac, 0x46, 0xe6, 0xcf, 0x97,
0x00, 0x77, 0xcf, 0xea, 0xa5, 0x01, 0x2f, 0x14, 0x66, 0x93, 0x45, 0x24, 0xb4, 0x2d, 0x67, 0x2c,
0x6f, 0xa1, 0x6c, 0xdd, 0xa6, 0x2c, 0x59, 0x22, 0xbc, 0xad, 0x1e, 0x6c, 0x13, 0x72, 0xc8, 0x67,
0xd5, 0xb7, 0x69, 0x54, 0x4c, 0x7c, 0x56, 0xc0, 0x79, 0x56, 0xea, 0xcd, 0x5e, 0xa7, 0xab, 0xe8,
0xfd, 0x7a, 0x4b, 0xdb, 0x57, 0x0f, 0xca, 0x4b, 0xd2, 0xc6, 0xd7, 0xdf, 0x6d, 0x57, 0x26, 0x31,
0x68, 0xf1, 0x8b, 0x01, 0xb6, 0x50, 0xb5, 0x86, 0xf2, 0x59, 0x39, 0x25, 0xad, 0x01, 0xb0, 0x9c,
0x00, 0xf2, 0x26, 0xff, 0x5f, 0x54, 0x62, 0x80, 0x7e, 0xaf, 0xdd, 0xa8, 0x75, 0x95, 0x72, 0x5a,
0x92, 0x00, 0xb7, 0x7e, 0x16, 0x17, 0xf2, 0x7d, 0x13, 0xea, 0x42, 0x79, 0xdc, 0x53, 0x3a, 0xdd,
0x72, 0x46, 0x5a, 0x07, 0x20, 0x4e, 0x00, 0xa3, 0x8a, 0xb9, 0x0d, 0x32, 0x54, 0x3a, 0xed, 0x96,
0xd6, 0x51, 0xca, 0x82, 0x74, 0x1d, 0x50, 0x57, 0x17, 0x50, 0xa1, 0x42, 0x3f, 0x42, 0xab, 0x8d,
0xd6, 0x13, 0xad, 0xd9, 0xaa, 0x35, 0xfa, 0x6d, 0xbd, 0x75, 0x00, 0x6b, 0x3a, 0xe5, 0xac, 0xb4,
0x05, 0xf8, 0x1b, 0x09, 0xfc, 0x39, 0xc1, 0xfd, 0x13, 0xd8, 0x53, 0xb5, 0x83, 0xb2, 0x28, 0x5d,
0x05, 0xe8, 0x95, 0x04, 0x34, 0x20, 0x35, 0xb8, 0x71, 0xbd, 0xd9, 0x82, 0xad, 0x73, 0xe7, 0x6e,
0xcc, 0xc8, 0xae, 0x7e, 0x81, 0xf0, 0xf9, 0x0f, 0x2f, 0x7c, 0x0b, 0x09, 0x5a, 0x4b, 0x53, 0x80,
0x50, 0x76, 0xff, 0xf3, 0x08, 0x8d, 0x3a, 0x04, 0xcb, 0x28, 0xd3, 0xfc, 0xfc, 0x03, 0x20, 0xf3,
0x1f, 0x00, 0xba, 0x76, 0x1e, 0x04, 0xce, 0x2a, 0x45, 0xc5, 0x64, 0x60, 0x19, 0xe5, 0x0f, 0x95,
0x6e, 0x0d, 0xc8, 0xad, 0x41, 0x70, 0x76, 0xa4, 0xc8, 0x7d, 0x48, 0x7c, 0x83, 0x15, 0xe0, 0x06,
0xca, 0x6a, 0xca, 0x91, 0xa2, 0x43, 0xe0, 0x55, 0x00, 0x2c, 0x47, 0x00, 0x8d, 0x80, 0xae, 0xe0,
0x9d, 0x17, 0x6b, 0xcd, 0x27, 0xb5, 0xa7, 0x1d, 0x48, 0x0e, 0x06, 0xf7, 0x4a, 0xe4, 0xae, 0xd9,
0x2f, 0x8c, 0x13, 0xaf, 0xfa, 0x7b, 0x0a, 0x95, 0x92, 0x4f, 0x1a, 0x2c, 0x10, 0xf6, 0xd5, 0xa6,
0x12, 0x6d, 0x97, 0xf4, 0x05, 0x63, 0xbc, 0x83, 0x0a, 0x0d, 0x55, 0x57, 0xea, 0xdd, 0x96, 0xfe,
0x34, 0xba, 0x4b, 0x12, 0xd4, 0xb0, 0x5c, 0x26, 0xee, 0xe0, 0x43, 0xaf, 0xd4, 0x79, 0x7a, 0xd8,
0x54, 0xb5, 0x47, 0x7d, 0x16, 0x31, 0x2d, 0xdd, 0x00, 0xf0, 0xf5, 0x24, 0xb8, 0x73, 0x32, 0xb1,
0x2d, 0xe7, 0x19, 0x0b, 0xfc, 0x00, 0xad, 0x46, 0xf0, 0x78, 0x83, 0x8c, 0xb4, 0x0d, 0x6b, 0x36,
0x2e, 0x58, 0x13, 0xef, 0x73, 0x1f, 0x5d, 0x89, 0x16, 0xf6, 0xb4, 0x47, 0x1a, 0xc8, 0x02, 0x94,
0xb3, 0x09, 0xcb, 0xa4, 0x0b, 0x96, 0xf5, 0x9c, 0x67, 0x0e, 0x88, 0xa2, 0xfa, 0x43, 0x0a, 0x15,
0xe6, 0x1d, 0x2a, 0xe0, 0x59, 0x6b, 0xf5, 0x15, 0x5d, 0x6f, 0xe9, 0xd1, 0xc5, 0xe7, 0x4e, 0x8d,
0xb2, 0x21, 0x7c, 0x54, 0xe5, 0x0e, 0x14, 0x4d, 0xd1, 0xd5, 0x7a, 0x54, 0x0f, 0x73, 0xc8, 0x01,
0x71, 0x88, 0x6b, 0x0d, 0xe1, 0xf3, 0xbe, 0x04, 0x61, 0x3a, 0xbd, 0xfa, 0xc3, 0xe8, 0xc6, 0x4c,
0xc0, 0x89, 0x50, 0x9d, 0xd9, 0xf0, 0x98, 0xdd, 0xb6, 0x1a, 0x94, 0xce, 0x51, 0xad, 0xa9, 0x36,
0x38, 0x34, 0x23, 0x55, 0x00, 0xba, 0x36, 0x87, 0xaa, 0xfc, 0x55, 0x0f, 0xb0, 0x55, 0x13, 0x6d,
0xfe, 0x75, 0x2f, 0x82, 0xaf, 0x0d, 0xb1, 0xd6, 0x6e, 0x2b, 0x5a, 0x23, 0x3a, 0x7d, 0xec, 0xab,
0x4d, 0xa7, 0xc4, 0x31, 0x03, 0xc4, 0x7e, 0x4b, 0x3f, 0x50, 0xba, 0xd1, 0xe1, 0x63, 0xc4, 0x3e,
0x75, 0xc7, 0xc4, 0xdf, 0xdb, 0x78, 0xfd, 0xcb, 0xe6, 0xd2, 0x1b, 0xf8, 0xbd, 0x3e, 0xdd, 0x4c,
0xbd, 0x81, 0xdf, 0xcf, 0xa7, 0x9b, 0x4b, 0xbf, 0xc1, 0xff, 0xab, 0x5f, 0x37, 0x53, 0x03, 0x91,
0xf5, 0xae, 0xfb, 0x7f, 0x06, 0x00, 0x00, 0xff, 0xff, 0xcc, 0x49, 0x51, 0xc5, 0x82, 0x0d, 0x00,
0x00,
}

View File

@ -68,7 +68,7 @@ message Device {
repeated string addresses = 3;
Compression compression = 4;
string cert_name = 5;
int64 max_local_version = 6;
int64 max_sequence = 6;
bool introducer = 7;
uint64 index_id = 8 [(gogoproto.customname) = "IndexID", (gogoproto.customtype) = "IndexID", (gogoproto.nullable) = false];
}
@ -102,7 +102,7 @@ message FileInfo {
bool invalid = 7;
bool no_permissions = 8;
Vector version = 9 [(gogoproto.nullable) = false];
int64 local_version = 10;
int64 sequence = 10;
repeated BlockInfo Blocks = 16 [(gogoproto.nullable) = false];
}

View File

@ -25,8 +25,8 @@ func (m Hello) Magic() uint32 {
}
func (f FileInfo) String() string {
return fmt.Sprintf("File{Name:%q, Type:%v, LocalVersion:%d, Permissions:0%o, Modified:%d, Version:%v, Length:%d, Deleted:%v, Invalid:%v, NoPermissions:%v, Blocks:%v}",
f.Name, f.Type, f.LocalVersion, f.Permissions, f.Modified, f.Version, f.Size, f.Deleted, f.Invalid, f.NoPermissions, f.Blocks)
return fmt.Sprintf("File{Name:%q, Type:%v, Sequence:%d, Permissions:0%o, Modified:%d, Version:%v, Length:%d, Deleted:%v, Invalid:%v, NoPermissions:%v, Blocks:%v}",
f.Name, f.Type, f.Sequence, f.Permissions, f.Modified, f.Version, f.Size, f.Deleted, f.Invalid, f.NoPermissions, f.Blocks)
}
func (f FileInfo) IsDeleted() bool {

View File

@ -46,7 +46,7 @@ type Process struct {
startComplete bool
startCompleteCond *stdsync.Cond
stop bool
localVersion map[string]map[string]int64 // Folder ID => Device ID => LocalVersion
sequence map[string]map[string]int64 // Folder ID => Device ID => Sequence
done map[string]bool // Folder ID => 100%
cmd *exec.Cmd
@ -58,7 +58,7 @@ type Process struct {
func NewProcess(addr string) *Process {
p := &Process{
addr: addr,
localVersion: make(map[string]map[string]int64),
sequence: make(map[string]map[string]int64),
done: make(map[string]bool),
eventMut: sync.NewMutex(),
}
@ -308,16 +308,16 @@ func InSync(folder string, ps ...*Process) bool {
return false
}
// Check LocalVersion for each device. The local version seen by remote
// Check Sequence for each device. The local version seen by remote
// devices should be the same as what it has locally, or the index
// hasn't been sent yet.
sourceID := ps[i].id.String()
sourceVersion := ps[i].localVersion[folder][sourceID]
sourceSeq := ps[i].sequence[folder][sourceID]
for j := range ps {
if i != j {
remoteVersion := ps[j].localVersion[folder][sourceID]
if remoteVersion != sourceVersion {
remoteSeq := ps[j].sequence[folder][sourceID]
if remoteSeq != sourceSeq {
return false
}
}
@ -510,12 +510,12 @@ func (p *Process) eventLoop() {
folder := data["folder"].(string)
version, _ := data["version"].(json.Number).Int64()
p.eventMut.Lock()
m := p.localVersion[folder]
m := p.sequence[folder]
if m == nil {
m = make(map[string]int64)
}
m[p.id.String()] = version
p.localVersion[folder] = m
p.sequence[folder] = m
p.done[folder] = false
l.Debugf("LocalIndexUpdated %v %v done=false\n\t%+v", p.id, folder, m)
p.eventMut.Unlock()
@ -526,12 +526,12 @@ func (p *Process) eventLoop() {
folder := data["folder"].(string)
version, _ := data["version"].(json.Number).Int64()
p.eventMut.Lock()
m := p.localVersion[folder]
m := p.sequence[folder]
if m == nil {
m = make(map[string]int64)
}
m[device] = version
p.localVersion[folder] = m
p.sequence[folder] = m
p.done[folder] = false
l.Debugf("RemoteIndexUpdated %v %v done=false\n\t%+v", p.id, folder, m)
p.eventMut.Unlock()