diff --git a/cmd/syncthing/gui.go b/cmd/syncthing/gui.go index 02e68a809..8a57d5325 100644 --- a/cmd/syncthing/gui.go +++ b/cmd/syncthing/gui.go @@ -91,6 +91,7 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro router.Get("/", getRoot) router.Get("/rest/version", restGetVersion) router.Get("/rest/model", restGetModel) + router.Get("/rest/model/version", restGetModelVersion) router.Get("/rest/need", restGetNeed) router.Get("/rest/connections", restGetConnections) router.Get("/rest/config", restGetConfig) @@ -144,6 +145,17 @@ func restGetVersion() string { return Version } +func restGetModelVersion(m *model.Model, w http.ResponseWriter, r *http.Request) { + var qs = r.URL.Query() + var repo = qs.Get("repo") + var res = make(map[string]interface{}) + + res["version"] = m.Version(repo) + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(res) +} + func restGetModel(m *model.Model, w http.ResponseWriter, r *http.Request) { var qs = r.URL.Query() var repo = qs.Get("repo") @@ -168,6 +180,7 @@ func restGetModel(m *model.Model, w http.ResponseWriter, r *http.Request) { res["inSyncFiles"], res["inSyncBytes"] = globalFiles-needFiles, globalBytes-needBytes res["state"] = m.State(repo) + res["version"] = m.Version(repo) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(res) diff --git a/gui/app.js b/gui/app.js index 222b9b374..776f5518a 100644 --- a/gui/app.js +++ b/gui/app.js @@ -103,9 +103,20 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) { getFailed(); }); Object.keys($scope.repos).forEach(function (id) { - $http.get(urlbase + '/model?repo=' + encodeURIComponent(id)).success(function (data) { - $scope.model[id] = data; - }); + if (typeof $scope.model[id] === 'undefined') { + // Never fetched before + $http.get(urlbase + '/model?repo=' + encodeURIComponent(id)).success(function (data) { + $scope.model[id] = data; + }); + } else { + $http.get(urlbase + '/model/version?repo=' + encodeURIComponent(id)).success(function (data) { + if (data.version > $scope.model[id].version) { + $http.get(urlbase + '/model?repo=' + encodeURIComponent(id)).success(function (data) { + $scope.model[id] = data; + }); + } + }); + } }); $http.get(urlbase + '/connections').success(function (data) { var now = Date.now(), diff --git a/model/model.go b/model/model.go index 9f581e23a..c87e5c11b 100644 --- a/model/model.go +++ b/model/model.go @@ -872,3 +872,18 @@ func (m *Model) Override(repo string) { r.Update(cid.LocalID, fs) } + +// Version returns the change version for the given repository. This is +// guaranteed to increment if the contents of the local or global repository +// has changed. +func (m *Model) Version(repo string) uint64 { + var ver uint64 + + m.rmut.Lock() + for _, n := range m.repoNodes[repo] { + ver += m.repoFiles[repo].Changes(m.cm.Get(n)) + } + m.rmut.Unlock() + + return ver +} diff --git a/model/puller.go b/model/puller.go index 77eba070a..ecb8c9913 100644 --- a/model/puller.go +++ b/model/puller.go @@ -11,6 +11,7 @@ import ( "path/filepath" "runtime" "time" + "github.com/calmh/syncthing/cid" "github.com/calmh/syncthing/config" "github.com/calmh/syncthing/osutil" @@ -135,6 +136,7 @@ func (p *puller) run() { walkTicker := time.Tick(time.Duration(p.cfg.Options.RescanIntervalS) * time.Second) timeout := time.Tick(5 * time.Second) changed := true + var prevVer uint64 for { // Run the pulling loop as long as there are blocks to fetch @@ -197,8 +199,11 @@ func (p *puller) run() { default: } - // Queue more blocks to fetch, if any - p.queueNeededBlocks() + if v := p.model.Version(p.repoCfg.ID); v > prevVer { + // Queue more blocks to fetch, if any + p.queueNeededBlocks() + prevVer = v + } } }