diff --git a/gui/default/index.html b/gui/default/index.html index 655a46fc..9fa5466e 100644 --- a/gui/default/index.html +++ b/gui/default/index.html @@ -323,6 +323,10 @@ + + + + ({{syncPercentage(folder.id) | percent}}, {{model[folder.id].needBytes | binary}}B) diff --git a/gui/default/syncthing/core/syncthingController.js b/gui/default/syncthing/core/syncthingController.js index 611b3d93..1479a1da 100755 --- a/gui/default/syncthing/core/syncthingController.js +++ b/gui/default/syncthing/core/syncthingController.js @@ -803,7 +803,7 @@ angular.module('syncthing.core') if (status == 'paused') { return 'default'; } - if (status === 'syncing' || status === 'scanning') { + if (status === 'syncing' || status === 'sync-preparing' || status === 'scanning') { return 'primary'; } if (status === 'unknown') { @@ -968,6 +968,7 @@ angular.module('syncthing.core') for (var i = 0; i < folderListCache.length; i++) { var status = $scope.folderStatus(folderListCache[i]); switch (status) { + case 'sync-preparing': case 'syncing': syncCount++; break; diff --git a/lib/model/folder_sendrecv.go b/lib/model/folder_sendrecv.go index bbf381a9..a2da02c4 100644 --- a/lib/model/folder_sendrecv.go +++ b/lib/model/folder_sendrecv.go @@ -176,7 +176,6 @@ func (f *sendReceiveFolder) pull() bool { l.Debugf("%v pulling", f) - f.setState(FolderSyncing) f.clearPullErrors() scanChan := make(chan string) @@ -194,6 +193,10 @@ func (f *sendReceiveFolder) pull() bool { default: } + // Needs to be set on every loop, as the puller might have set + // it to FolderSyncing during the last iteration. + f.setState(FolderSyncPreparing) + changed := f.pullerIteration(scanChan) l.Debugln(f, "changed", changed, "on try", tries+1) @@ -1396,6 +1399,8 @@ func (f *sendReceiveFolder) pullerRoutine(in <-chan pullBlockState, out chan<- * continue } + f.setState(FolderSyncing) // Does nothing if already FolderSyncing + // The requestLimiter limits how many pending block requests we have // ongoing at any given time, based on the size of the blocks // themselves. diff --git a/lib/model/folderstate.go b/lib/model/folderstate.go index d11a72ea..d1a4c54c 100644 --- a/lib/model/folderstate.go +++ b/lib/model/folderstate.go @@ -19,6 +19,7 @@ const ( FolderIdle folderState = iota FolderScanning FolderScanWaiting + FolderSyncPreparing FolderSyncing FolderError ) @@ -31,6 +32,8 @@ func (s folderState) String() string { return "scanning" case FolderScanWaiting: return "scan-waiting" + case FolderSyncPreparing: + return "sync-preparing" case FolderSyncing: return "syncing" case FolderError: @@ -65,29 +68,32 @@ func (s *stateTracker) setState(newState folderState) { } s.mut.Lock() - if newState != s.current { - /* This should hold later... - if s.current != FolderIdle && (newState == FolderScanning || newState == FolderSyncing) { - panic("illegal state transition " + s.current.String() + " -> " + newState.String()) - } - */ + defer s.mut.Unlock() - eventData := map[string]interface{}{ - "folder": s.folderID, - "to": newState.String(), - "from": s.current.String(), - } - - if !s.changed.IsZero() { - eventData["duration"] = time.Since(s.changed).Seconds() - } - - s.current = newState - s.changed = time.Now() - - s.evLogger.Log(events.StateChanged, eventData) + if newState == s.current { + return } - s.mut.Unlock() + + /* This should hold later... + if s.current != FolderIdle && (newState == FolderScanning || newState == FolderSyncing) { + panic("illegal state transition " + s.current.String() + " -> " + newState.String()) + } + */ + + eventData := map[string]interface{}{ + "folder": s.folderID, + "to": newState.String(), + "from": s.current.String(), + } + + if !s.changed.IsZero() { + eventData["duration"] = time.Since(s.changed).Seconds() + } + + s.current = newState + s.changed = time.Now() + + s.evLogger.Log(events.StateChanged, eventData) } // getState returns the current state, the time when it last changed, and the