Potential race between folder being added and scan (potentially fixes #1986)

This commit is contained in:
Audrius Butkevicius 2015-06-24 08:52:38 +01:00
parent 986f8dfb2e
commit 31cd0b943c
3 changed files with 15 additions and 12 deletions

View File

@ -428,7 +428,10 @@ func folderSummary(m *model.Model, folder string) map[string]interface{} {
res["error"] = err.Error() res["error"] = err.Error()
} }
res["version"] = m.CurrentLocalVersion(folder) + m.RemoteLocalVersion(folder) lv, _ := m.CurrentLocalVersion(folder)
rv, _ := m.RemoteLocalVersion(folder)
res["version"] = lv + rv
ignorePatterns, _, _ := m.GetIgnores(folder) ignorePatterns, _, _ := m.GetIgnores(folder)
res["ignorePatterns"] = false res["ignorePatterns"] = false

View File

@ -1554,23 +1554,23 @@ func (m *Model) Override(folder string) {
// CurrentLocalVersion returns the change version for the given folder. // CurrentLocalVersion returns the change version for the given folder.
// This is guaranteed to increment if the contents of the local folder has // This is guaranteed to increment if the contents of the local folder has
// changed. // changed.
func (m *Model) CurrentLocalVersion(folder string) int64 { func (m *Model) CurrentLocalVersion(folder string) (int64, bool) {
m.fmut.RLock() m.fmut.RLock()
fs, ok := m.folderFiles[folder] fs, ok := m.folderFiles[folder]
m.fmut.RUnlock() m.fmut.RUnlock()
if !ok { if !ok {
// The folder might not exist, since this can be called with a user // The folder might not exist, since this can be called with a user
// specified folder name from the REST interface. // specified folder name from the REST interface.
return 0 return 0, false
} }
return fs.LocalVersion(protocol.LocalDeviceID) return fs.LocalVersion(protocol.LocalDeviceID), true
} }
// RemoteLocalVersion returns the change version for the given folder, as // RemoteLocalVersion returns the change version for the given folder, as
// sent by remote peers. This is guaranteed to increment if the contents of // sent by remote peers. This is guaranteed to increment if the contents of
// the remote or global folder has changed. // the remote or global folder has changed.
func (m *Model) RemoteLocalVersion(folder string) int64 { func (m *Model) RemoteLocalVersion(folder string) (int64, bool) {
m.fmut.RLock() m.fmut.RLock()
defer m.fmut.RUnlock() defer m.fmut.RUnlock()
@ -1578,7 +1578,7 @@ func (m *Model) RemoteLocalVersion(folder string) int64 {
if !ok { if !ok {
// The folder might not exist, since this can be called with a user // The folder might not exist, since this can be called with a user
// specified folder name from the REST interface. // specified folder name from the REST interface.
return 0 return 0, false
} }
var ver int64 var ver int64
@ -1586,7 +1586,7 @@ func (m *Model) RemoteLocalVersion(folder string) int64 {
ver += fs.LocalVersion(n) ver += fs.LocalVersion(n)
} }
return ver return ver, true
} }
func (m *Model) GlobalDirectoryTree(folder, prefix string, levels int, dirsonly bool) map[string]interface{} { func (m *Model) GlobalDirectoryTree(folder, prefix string, levels int, dirsonly bool) map[string]interface{} {
@ -1695,7 +1695,7 @@ func (m *Model) CheckFolderHealth(id string) error {
} }
fi, err := os.Stat(folder.Path()) fi, err := os.Stat(folder.Path())
if m.CurrentLocalVersion(id) > 0 { if v, ok := m.CurrentLocalVersion(id); ok && v > 0 {
// Safety check. If the cached index contains files but the // Safety check. If the cached index contains files but the
// folder doesn't exist, we have a problem. We would assume // folder doesn't exist, we have a problem. We would assume
// that all files have been deleted which might not be the case, // that all files have been deleted which might not be the case,

View File

@ -204,10 +204,10 @@ func (p *rwFolder) Serve() {
} }
// RemoteLocalVersion() is a fast call, doesn't touch the database. // RemoteLocalVersion() is a fast call, doesn't touch the database.
curVer := p.model.RemoteLocalVersion(p.folder) curVer, ok := p.model.RemoteLocalVersion(p.folder)
if curVer == prevVer { if !ok || curVer == prevVer {
if debug { if debug {
l.Debugln(p, "skip (curVer == prevVer)", prevVer) l.Debugln(p, "skip (curVer == prevVer)", prevVer, ok)
} }
p.pullTimer.Reset(nextPullIntv) p.pullTimer.Reset(nextPullIntv)
continue continue
@ -231,7 +231,7 @@ func (p *rwFolder) Serve() {
// sync. Remember the local version number and // sync. Remember the local version number and
// schedule a resync a little bit into the future. // schedule a resync a little bit into the future.
if lv := p.model.RemoteLocalVersion(p.folder); lv < curVer { if lv, ok := p.model.RemoteLocalVersion(p.folder); ok && lv < curVer {
// There's a corner case where the device we needed // There's a corner case where the device we needed
// files from disconnected during the puller // files from disconnected during the puller
// iteration. The files will have been removed from // iteration. The files will have been removed from