|
@@ -147,7 +147,6 @@ func (f *sendReceiveFolder) Serve() {
|
|
|
f.setState(FolderIdle)
|
|
f.setState(FolderIdle)
|
|
|
}()
|
|
}()
|
|
|
|
|
|
|
|
- var prevSeq int64
|
|
|
|
|
var prevIgnoreHash string
|
|
var prevIgnoreHash string
|
|
|
var success bool
|
|
var success bool
|
|
|
pullFailTimer := time.NewTimer(time.Duration(0))
|
|
pullFailTimer := time.NewTimer(time.Duration(0))
|
|
@@ -157,6 +156,8 @@ func (f *sendReceiveFolder) Serve() {
|
|
|
f.startWatch()
|
|
f.startWatch()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ initialCompleted := f.initialScanFinished
|
|
|
|
|
+
|
|
|
for {
|
|
for {
|
|
|
select {
|
|
select {
|
|
|
case <-f.ctx.Done():
|
|
case <-f.ctx.Done():
|
|
@@ -169,13 +170,13 @@ func (f *sendReceiveFolder) Serve() {
|
|
|
default:
|
|
default:
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if prevSeq, prevIgnoreHash, success = f.pull(prevSeq, prevIgnoreHash); !success {
|
|
|
|
|
|
|
+ if prevIgnoreHash, success = f.pull(prevIgnoreHash); !success {
|
|
|
// Pulling failed, try again later.
|
|
// Pulling failed, try again later.
|
|
|
pullFailTimer.Reset(f.pause)
|
|
pullFailTimer.Reset(f.pause)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
case <-pullFailTimer.C:
|
|
case <-pullFailTimer.C:
|
|
|
- if prevSeq, prevIgnoreHash, success = f.pull(prevSeq, prevIgnoreHash); !success {
|
|
|
|
|
|
|
+ if prevIgnoreHash, success = f.pull(prevIgnoreHash); !success {
|
|
|
// Pulling failed, try again later.
|
|
// Pulling failed, try again later.
|
|
|
pullFailTimer.Reset(f.pause)
|
|
pullFailTimer.Reset(f.pause)
|
|
|
// Back off from retrying to pull with an upper limit.
|
|
// Back off from retrying to pull with an upper limit.
|
|
@@ -184,6 +185,14 @@ func (f *sendReceiveFolder) Serve() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ case <-initialCompleted:
|
|
|
|
|
+ // Initial scan has completed, we should do a pull
|
|
|
|
|
+ initialCompleted = nil // never hit this case again
|
|
|
|
|
+ if prevIgnoreHash, success = f.pull(prevIgnoreHash); !success {
|
|
|
|
|
+ // Pulling failed, try again later.
|
|
|
|
|
+ pullFailTimer.Reset(f.pause)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// The reason for running the scanner from within the puller is that
|
|
// The reason for running the scanner from within the puller is that
|
|
|
// this is the easiest way to make sure we are not doing both at the
|
|
// this is the easiest way to make sure we are not doing both at the
|
|
|
// same time.
|
|
// same time.
|
|
@@ -222,41 +231,27 @@ func (f *sendReceiveFolder) String() string {
|
|
|
return fmt.Sprintf("sendReceiveFolder/%s@%p", f.folderID, f)
|
|
return fmt.Sprintf("sendReceiveFolder/%s@%p", f.folderID, f)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (f *sendReceiveFolder) pull(prevSeq int64, prevIgnoreHash string) (curSeq int64, curIgnoreHash string, success bool) {
|
|
|
|
|
|
|
+func (f *sendReceiveFolder) pull(prevIgnoreHash string) (curIgnoreHash string, success bool) {
|
|
|
select {
|
|
select {
|
|
|
case <-f.initialScanFinished:
|
|
case <-f.initialScanFinished:
|
|
|
default:
|
|
default:
|
|
|
// Once the initial scan finished, a pull will be scheduled
|
|
// Once the initial scan finished, a pull will be scheduled
|
|
|
- return prevSeq, prevIgnoreHash, true
|
|
|
|
|
|
|
+ return prevIgnoreHash, true
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
f.model.fmut.RLock()
|
|
f.model.fmut.RLock()
|
|
|
curIgnores := f.model.folderIgnores[f.folderID]
|
|
curIgnores := f.model.folderIgnores[f.folderID]
|
|
|
f.model.fmut.RUnlock()
|
|
f.model.fmut.RUnlock()
|
|
|
|
|
|
|
|
- curSeq = prevSeq
|
|
|
|
|
curIgnoreHash = curIgnores.Hash()
|
|
curIgnoreHash = curIgnores.Hash()
|
|
|
ignoresChanged := curIgnoreHash != prevIgnoreHash
|
|
ignoresChanged := curIgnoreHash != prevIgnoreHash
|
|
|
- if ignoresChanged {
|
|
|
|
|
- // 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 curSeq")
|
|
|
|
|
- curSeq = 0
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // RemoteSequence() is a fast call, doesn't touch the database.
|
|
|
|
|
- remoteSeq, ok := f.model.RemoteSequence(f.folderID)
|
|
|
|
|
- if !ok || remoteSeq == curSeq {
|
|
|
|
|
- l.Debugln(f, "skip (remoteSeq == curSeq)", curSeq, ok)
|
|
|
|
|
- return curSeq, curIgnoreHash, true
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
if err := f.CheckHealth(); err != nil {
|
|
if err := f.CheckHealth(); err != nil {
|
|
|
l.Debugln("Skipping pull of", f.Description(), "due to folder error:", err)
|
|
l.Debugln("Skipping pull of", f.Description(), "due to folder error:", err)
|
|
|
- return curSeq, curIgnoreHash, true
|
|
|
|
|
|
|
+ return curIgnoreHash, true
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- l.Debugln(f, "pulling", curSeq, remoteSeq)
|
|
|
|
|
|
|
+ l.Debugln(f, "pulling")
|
|
|
|
|
|
|
|
f.setState(FolderSyncing)
|
|
f.setState(FolderSyncing)
|
|
|
f.clearErrors()
|
|
f.clearErrors()
|
|
@@ -273,20 +268,6 @@ func (f *sendReceiveFolder) pull(prevSeq int64, prevIgnoreHash string) (curSeq i
|
|
|
// No files were changed by the puller, so we are in
|
|
// No files were changed by the puller, so we are in
|
|
|
// sync. Update the local version number.
|
|
// sync. Update the local version number.
|
|
|
|
|
|
|
|
- if lv, ok := f.model.RemoteSequence(f.folderID); ok && lv < remoteSeq {
|
|
|
|
|
- // 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 old remote sequence
|
|
|
|
|
- // that includes those files in remoteSeq. So we
|
|
|
|
|
- // catch the case that this sequence might have
|
|
|
|
|
- // decreased here.
|
|
|
|
|
- l.Debugf("%v adjusting remoteSeq from %d to %d", remoteSeq, lv)
|
|
|
|
|
- remoteSeq = lv
|
|
|
|
|
- }
|
|
|
|
|
- curSeq = remoteSeq
|
|
|
|
|
-
|
|
|
|
|
f.pause = f.basePause()
|
|
f.pause = f.basePause()
|
|
|
|
|
|
|
|
break
|
|
break
|
|
@@ -313,7 +294,7 @@ func (f *sendReceiveFolder) pull(prevSeq int64, prevIgnoreHash string) (curSeq i
|
|
|
|
|
|
|
|
f.setState(FolderIdle)
|
|
f.setState(FolderIdle)
|
|
|
|
|
|
|
|
- return curSeq, curIgnoreHash, changed == 0
|
|
|
|
|
|
|
+ return curIgnoreHash, changed == 0
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// pullerIteration runs a single puller iteration for the given folder and
|
|
// pullerIteration runs a single puller iteration for the given folder and
|