all: Rename LocalVersion to Sequence (fixes #3461)
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3462
This commit is contained in:
committed by
Audrius Butkevicius
parent
a022b0cfff
commit
297240facf
@@ -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,24 +1751,24 @@ 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{
|
||||
ID: device[:],
|
||||
Name: deviceCfg.Name,
|
||||
Addresses: deviceCfg.Addresses,
|
||||
Compression: deviceCfg.Compression,
|
||||
CertName: deviceCfg.CertName,
|
||||
Introducer: deviceCfg.Introducer,
|
||||
IndexID: indexID,
|
||||
MaxLocalVersion: maxLocalVersion,
|
||||
ID: device[:],
|
||||
Name: deviceCfg.Name,
|
||||
Addresses: deviceCfg.Addresses,
|
||||
Compression: deviceCfg.Compression,
|
||||
CertName: deviceCfg.CertName,
|
||||
Introducer: deviceCfg.Introducer,
|
||||
IndexID: indexID,
|
||||
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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -95,17 +95,17 @@ 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()
|
||||
f := protocol.FileInfo{
|
||||
Name: fmt.Sprintf("file-%d", rnd),
|
||||
Size: rand.Int63(),
|
||||
Permissions: uint32(rand.Intn(0777)),
|
||||
Modified: rand.Int63(),
|
||||
LocalVersion: rnd,
|
||||
Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: uint64(rand.Int63())}}},
|
||||
Name: fmt.Sprintf("file-%d", rnd),
|
||||
Size: rand.Int63(),
|
||||
Permissions: uint32(rand.Intn(0777)),
|
||||
Modified: rand.Int63(),
|
||||
Sequence: rnd,
|
||||
Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: uint64(rand.Int63())}}},
|
||||
Blocks: []protocol.BlockInfo{{
|
||||
Size: int32(rand.Intn(128 << 10)),
|
||||
Hash: []byte(rand.String(32)),
|
||||
@@ -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
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user