lib/model: Fix accounting error in rescan with multiple subs (fixes #3028)
When doing prefix scans in the database, "foo" should not be considered a prefix of "foo2". Instead, it should match "foo" exactly and also strings with the prefix "foo/". This is more restrictive than what the standard leveldb prefix scan does so we add some code to enforce it. Also exposes the initialScanCompleted on the rwfolder for testing, and change it to be a channel (so we can wait for it from another goroutine). Otherwise we can't be sure when the initial scan has completed, and we need to wait for that or it might pick up changes we're doing at an unexpected time. GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3067
This commit is contained in:
committed by
Audrius Butkevicius
parent
8b7b0a03eb
commit
1a703efa78
@@ -262,7 +262,17 @@ func (db *Instance) withHave(folder, device, prefix []byte, truncate bool, fn It
|
||||
dbi := t.NewIterator(util.BytesPrefix(db.deviceKey(folder, device, prefix)[:keyPrefixLen+keyFolderLen+keyDeviceLen+len(prefix)]), nil)
|
||||
defer dbi.Release()
|
||||
|
||||
slashedPrefix := prefix
|
||||
if !bytes.HasSuffix(prefix, []byte{'/'}) {
|
||||
slashedPrefix = append(slashedPrefix, '/')
|
||||
}
|
||||
|
||||
for dbi.Next() {
|
||||
name := db.deviceKeyName(dbi.Key())
|
||||
if len(prefix) > 0 && !bytes.Equal(name, prefix) && !bytes.HasPrefix(name, slashedPrefix) {
|
||||
return
|
||||
}
|
||||
|
||||
// The iterator function may keep a reference to the unmarshalled
|
||||
// struct, which in turn references the buffer it was unmarshalled
|
||||
// from. dbi.Value() just returns an internal slice that it reuses, so
|
||||
@@ -359,6 +369,11 @@ func (db *Instance) withGlobal(folder, prefix []byte, truncate bool, fn Iterator
|
||||
dbi := t.NewIterator(util.BytesPrefix(db.globalKey(folder, prefix)), nil)
|
||||
defer dbi.Release()
|
||||
|
||||
slashedPrefix := prefix
|
||||
if !bytes.HasSuffix(prefix, []byte{'/'}) {
|
||||
slashedPrefix = append(slashedPrefix, '/')
|
||||
}
|
||||
|
||||
var fk []byte
|
||||
for dbi.Next() {
|
||||
var vl versionList
|
||||
@@ -370,7 +385,12 @@ func (db *Instance) withGlobal(folder, prefix []byte, truncate bool, fn Iterator
|
||||
l.Debugln(dbi.Key())
|
||||
panic("no versions?")
|
||||
}
|
||||
|
||||
name := db.globalKeyName(dbi.Key())
|
||||
if len(prefix) > 0 && !bytes.Equal(name, prefix) && !bytes.HasPrefix(name, slashedPrefix) {
|
||||
return
|
||||
}
|
||||
|
||||
fk = db.deviceKeyInto(fk[:cap(fk)], folder, vl.versions[0].device, name)
|
||||
bs, err := t.Get(fk, nil)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user