Skip to content

Commit

Permalink
all: Transition to using fs watcher by default (fixes syncthing#4552)
Browse files Browse the repository at this point in the history
  • Loading branch information
imsodin authored and AudriusButkevicius committed Mar 25, 2018
1 parent d6bb8e6 commit a557d62
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 68 deletions.
1 change: 0 additions & 1 deletion etc/linux-systemd/system/syncthing@.service
Expand Up @@ -2,7 +2,6 @@
Description=Syncthing - Open Source Continuous File Synchronization for %I
Documentation=man:syncthing(1)
After=network.target
Wants=syncthing-inotify@.service

[Service]
User=%i
Expand Down
1 change: 0 additions & 1 deletion etc/linux-systemd/user/syncthing.service
@@ -1,7 +1,6 @@
[Unit]
Description=Syncthing - Open Source Continuous File Synchronization
Documentation=man:syncthing(1)
Wants=syncthing-inotify.service

[Service]
ExecStart=/usr/bin/syncthing -no-browser -no-restart -logflags=0
Expand Down
8 changes: 8 additions & 0 deletions gui/default/assets/lang/lang-en.json
Expand Up @@ -12,6 +12,7 @@
"Add Remote Device": "Add Remote Device",
"Add devices from the introducer to our device list, for mutually shared folders.": "Add devices from the introducer to our device list, for mutually shared folders.",
"Add new folder?": "Add new folder?",
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.",
"Address": "Address",
"Addresses": "Addresses",
"Advanced": "Advanced",
Expand Down Expand Up @@ -49,6 +50,7 @@
"Connection Error": "Connection Error",
"Connection Type": "Connection Type",
"Connections": "Connections",
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.",
"Copied from elsewhere": "Copied from elsewhere",
"Copied from original": "Copied from original",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 the following Contributors:",
Expand All @@ -75,6 +77,7 @@
"Discovery Failures": "Discovery Failures",
"Do not restore": "Do not restore",
"Do not restore all": "Do not restore all",
"Do you want to enable watching for changes for all your folders?": "Do you want to enable watching for changes for all your folders?",
"Documentation": "Documentation",
"Download Rate": "Download Rate",
"Downloaded": "Downloaded",
Expand Down Expand Up @@ -114,6 +117,7 @@
"Folder Path": "Folder Path",
"Folder Type": "Folder Type",
"Folders": "Folders",
"Full Rescan Interval (s)": "Full Rescan Interval (s)",
"GUI": "GUI",
"GUI Authentication Password": "GUI Authentication Password",
"GUI Authentication User": "GUI Authentication User",
Expand Down Expand Up @@ -193,6 +197,7 @@
"Periodic scanning at given interval and disabled watching for changes": "Periodic scanning at given interval and disabled watching for changes",
"Periodic scanning at given interval and enabled watching for changes": "Periodic scanning at given interval and enabled watching for changes",
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:",
"Permissions": "Permissions",
"Please consult the release notes before performing a major upgrade.": "Please consult the release notes before performing a major upgrade.",
"Please set a GUI Authentication User and Password in the Settings dialog.": "Please set a GUI Authentication User and Password in the Settings dialog.",
"Please wait": "Please wait",
Expand Down Expand Up @@ -328,6 +333,9 @@
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a parent directory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a subdirectory of an existing folder \"{{otherFolder}}\".",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a subdirectory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Warning: If you are using an external watcher like {{syncthingInotify}}, you should make sure it is deactivated.",
"Watch for Changes": "Watch for Changes",
"Watching for Changes": "Watching for Changes",
"When adding a new device, keep in mind that this device must be added on the other side too.": "When adding a new device, keep in mind that this device must be added on the other side too.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.",
"Yes": "Yes",
Expand Down
28 changes: 28 additions & 0 deletions gui/default/syncthing/core/notifications.html
Expand Up @@ -41,3 +41,31 @@ <h3 class="panel-title"><span class="fa fa-flash"></span>&nbsp;<span translate>A
</div>
</div>
</notification>

<notification id="fsWatcherNotification">
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title"><span class="fa fa-flash"></span>&ensp;<span translate>Watching for Changes</span></h3>
</div>
<div class="panel-body">
<p translate>Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.</p>
<p><a href="https://docs.syncthing.net/users/syncing.html#scanning"><span class="fa fa-fw fa-book"></span>&nbsp;<span translate>Learn more</span></a></p>
<p>
<span translate>Do you want to enable watching for changes for all your folders?</span><br/>
<span translate>Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.</span>
</p>
<p translate translate-value-syncthing-inotify="syncthing-inotify">Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.</p>
</div>
<div class="panel-footer clearfix">
<div class="pull-right">
<button type="button" class="btn btn-primary btn-sm" ng-click="activateAllFsWatchers(); dismiss()">
<span class="fa fa-check"></span>&nbsp;<span translate>Yes</span>
</button>
<button type="button" class="btn btn-default btn-sm" ng-click="dismiss()">
<span class="fa fa-times"></span>&nbsp;<span translate>No</span>
</button>
</div>
<div class="clearfix"></div>
</div>
</div>
</notification>
34 changes: 33 additions & 1 deletion gui/default/syncthing/core/syncthingController.js
Expand Up @@ -53,6 +53,7 @@ angular.module('syncthing.core')
$scope.globalChangeEvents = {};
$scope.metricRates = false;
$scope.folderPathErrors = {};
$scope.currentFolder = {};
resetRemoteNeed();

try {
Expand All @@ -62,8 +63,9 @@ angular.module('syncthing.core')
$scope.folderDefaults = {
selectedDevices: {},
type: "readwrite",
rescanIntervalS: 60,
rescanIntervalS: 3600,
fsWatcherDelayS: 10,
fsWatcherEnabled: true,
minDiskFree: {value: 1, unit: "%"},
maxConflicts: 10,
fsync: true,
Expand Down Expand Up @@ -1504,6 +1506,14 @@ angular.module('syncthing.core')
$scope.currentFolder.path = pathJoin($scope.config.options.defaultFolderPath, newvalue);
});

$scope.$watch('currentFolder.fsWatcherEnabled', function (newvalue) {
if (newvalue) {
$scope.currentFolder.rescanIntervalS = 3600;
} else {
$scope.currentFolder.rescanIntervalS = 60;
}
});

$scope.loadFormIntoScope = function (form) {
console.log('loadFormIntoScope',form.$name);
switch (form.$name) {
Expand Down Expand Up @@ -2126,6 +2136,28 @@ angular.module('syncthing.core')
return false;
};

$scope.activateAllFsWatchers = function() {
var folders = $scope.folderList();

$.each(folders, function(i) {
if (folders[i].fsWatcherEnabled) {
return;
}
folders[i].fsWatcherEnabled = true;
if (folders[i].rescanIntervalS === 0) {
return;
}
// Delay full scans, but scan at least once per day
folders[i].rescanIntervalS *= 60;
if (folders[i].rescanIntervalS > 86400) {
folders[i].rescanIntervalS = 86400;
}
});

$scope.config.folders = folders;
$scope.saveConfig();
};

$scope.bumpFile = function (folder, file) {
var url = urlbase + "/db/prio?folder=" + encodeURIComponent(folder) + "&file=" + encodeURIComponent(file);
// In order to get the right view of data in the response.
Expand Down
112 changes: 62 additions & 50 deletions gui/default/syncthing/folder/editFolderModalView.html
Expand Up @@ -133,70 +133,82 @@
<div class="pull-left" ng-show="!editingExisting"><span translate translate-value-path="{{currentFolder.path}}{{system.pathSeparator}}.stignore">Creating ignore patterns, overwriting an existing file at {%path%}.</span></div>
</div>
<div id="folder-advanced" class="tab-pane">
<div class="row">
<div class="col-md-6">
<div class="form-group" ng-class="{'has-error': folderEditor.rescanIntervalS.$invalid && folderEditor.rescanIntervalS.$dirty}">
<label for="rescanIntervalS"><span translate>Rescan Interval</span> (s)</label><br/>
<input name="rescanIntervalS" id="rescanIntervalS" class="form-control" type="number" ng-model="currentFolder.rescanIntervalS" required="" aria-required="true" min="0"/>
<p class="help-block">
<span translate ng-if="!folderEditor.rescanIntervalS.$valid && folderEditor.rescanIntervalS.$dirty">The rescan interval must be a non-negative number of seconds.</span>
</p>
<div class="row form-group" ng-class="{'has-error': folderEditor.rescanIntervalS.$invalid && folderEditor.rescanIntervalS.$dirty}">
<div class="col-md-12">
<label translate>Scanning</label>
&nbsp;<a href="https://docs.syncthing.net/users/syncing.html#scanning" target="_blank"><span class="fa fa-book"></span>&nbsp;<span translate>Help</span></a></br>
<div class="row">
<div class="col-md-6">
<input type="checkbox" ng-model="currentFolder.fsWatcherEnabled" tooltip data-original-title="{{'Use notifications from the filesystem to detect changed items.' | translate }}">&nbsp;<span translate>Watch for Changes</span>
</div>
<div class="col-md-6">
<div class="row">
<span class="col-md-8" translate>Full Rescan Interval (s)</span>
<div class="col-md-4">
<input name="rescanIntervalS" id="rescanIntervalS" class="form-control" type="number" ng-model="currentFolder.rescanIntervalS" required="" aria-required="true" min="0"/>
</div>
</div>
<p class="help-block" ng-if="!folderEditor.rescanIntervalS.$valid && folderEditor.rescanIntervalS.$dirty" translate>
The rescan interval must be a non-negative number of seconds.
</p>
</div>
</div>
</div>
<div class="col-md-6 form-horizontal">
<div class="form-group" ng-class="{'has-error': folderEditor.minDiskFree.$invalid && folderEditor.minDiskFree.$dirty}">
<label class="col-xs-12" for="minDiskFree"><span translate>Minimum Free Disk Space</span></label><br/>
<div class="col-xs-9"><input name="minDiskFree" id="minDiskFree" class="form-control" type="number" ng-model="currentFolder.minDiskFree.value" required="" aria-required="true" min="0" step="0.01"/></div>
<div class="col-xs-3"><select class="col-sm-3 form-control" ng-model="currentFolder.minDiskFree.unit">
</div>
<div class="row">
<div class="col-md-6 form-group">
<label translate>Folder Type</label>
&nbsp;<a href="https://docs.syncthing.net/users/foldertypes.html" target="_blank"><span class="fa fa-book"></span>&nbsp;<span translate>Help</span></a>
<select class="form-control" ng-model="currentFolder.type">
<option value="readwrite" translate>Send &amp; Receive</option>
<option value="readonly" translate>Send Only</option>
</select>
<p ng-if="currentFolder.type == 'readonly'" translate class="help-block">Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.</p>
</div>
<div class="col-md-6 form-group">
<label translate>File Pull Order</label>
<select class="form-control" ng-model="currentFolder.order">
<option value="random" translate>Random</option>
<option value="alphabetic" translate>Alphabetic</option>
<option value="smallestFirst" translate>Smallest First</option>
<option value="largestFirst" translate>Largest First</option>
<option value="oldestFirst" translate>Oldest First</option>
<option value="newestFirst" translate>Newest First</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-6 form-horizontal form-group" ng-class="{'has-error': folderEditor.minDiskFree.$invalid && folderEditor.minDiskFree.$dirty}">
<label for="minDiskFree" translate>Minimum Free Disk Space</label><br/>
<div class="row">
<div class="col-md-9">
<input name="minDiskFree" id="minDiskFree" class="form-control" type="number" ng-model="currentFolder.minDiskFree.value" required="" aria-required="true" min="0" step="0.01"/>
</div>
<div class="col-md-3">
<select class="form-control" ng-model="currentFolder.minDiskFree.unit">
<option value="%">%</option>
<option value="kB">kB</option>
<option value="MB">MB</option>
<option value="GB">GB</option>
<option value="TB">TB</option>
</select>
</div>
</div>
<p class="help-block" ng-show="folderEditor.minDiskFree.$invalid" translate>
Enter a non-negative number (e.g., "2.35") and select a unit. Percentages are as part of the total disk size.
</p>
</div>
<div class="col-md-6 form-group">
<label translate>Permissions</label><br/>
<input type="checkbox" ng-model="currentFolder.ignorePerms"/> <span translate>Ignore</span>
<p translate class="help-block">File permission bits are ignored when looking for changes. Use on FAT file systems.</p>
</select></div>
<p class="col-xs-12 help-block" ng-show="folderEditor.minDiskFree.$invalid">
<span translate>Enter a non-negative number (e.g., "2.35") and select a unit. Percentages are as part of the total disk size.</span>
</p>
</div>
</div>
</div>
<div class="row">
<!-- Left column -->
<div class="col-md-6">
<div class="form-group">
<label translate>Folder Type</label>
&nbsp;<a href="https://docs.syncthing.net/users/foldertypes.html" target="_blank"><span class="fa fa-book"></span>&nbsp;<span translate>Help</span></a>
<select class="form-control" ng-model="currentFolder.type">
<option value="readwrite" translate>Send &amp; Receive</option>
<option value="readonly" translate>Send Only</option>
</select>
<p ng-if="currentFolder.type == 'readonly'" translate class="help-block">Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.</p>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="currentFolder.ignorePerms"/> <span translate>Ignore Permissions</span>
</label>
</div>
<p translate class="help-block">File permission bits are ignored when looking for changes. Use on FAT file systems.</p>
</div>
</div>

<!-- Right column-->
<div class="col-md-6">
<div class="form-group">
<label translate>File Pull Order</label>
<select class="form-control" ng-model="currentFolder.order">
<option value="random" translate>Random</option>
<option value="alphabetic" translate>Alphabetic</option>
<option value="smallestFirst" translate>Smallest First</option>
<option value="largestFirst" translate>Largest First</option>
<option value="oldestFirst" translate>Oldest First</option>
<option value="newestFirst" translate>Newest First</option>
</select>
</div>
</div>
</div>
</div>
</div>
</form>
Expand Down
11 changes: 10 additions & 1 deletion lib/config/config.go
Expand Up @@ -32,7 +32,7 @@ import (

const (
OldestHandledVersion = 10
CurrentVersion = 27
CurrentVersion = 28
MaxRescanIntervalS = 365 * 24 * 60 * 60
)

Expand Down Expand Up @@ -315,6 +315,9 @@ func (cfg *Configuration) clean() error {
if cfg.Version == 26 {
convertV26V27(cfg)
}
if cfg.Version == 27 {
convertV27V28(cfg)
}

// Build a list of available devices
existingDevices := make(map[protocol.DeviceID]bool)
Expand Down Expand Up @@ -374,6 +377,12 @@ func (cfg *Configuration) clean() error {
return nil
}

func convertV27V28(cfg *Configuration) {
// Show a notification about enabling filesystem watching
cfg.Options.UnackedNotificationIDs = append(cfg.Options.UnackedNotificationIDs, "fsWatcherNotification")
cfg.Version = 28
}

func convertV26V27(cfg *Configuration) {
for i := range cfg.Folders {
f := &cfg.Folders[i]
Expand Down
3 changes: 2 additions & 1 deletion lib/config/config_test.go
Expand Up @@ -206,7 +206,8 @@ func TestOverriddenValues(t *testing.T) {
OverwriteRemoteDevNames: true,
TempIndexMinBlocks: 100,
UnackedNotificationIDs: []string{
"channelNotification", // added in 17->18 migration
"channelNotification", // added in 17->18 migration
"fsWatcherNotification", // added in 27->28 migration
},
WeakHashSelectionMethod: WeakHashNever,
DefaultFolderPath: "/media/syncthing",
Expand Down

0 comments on commit a557d62

Please sign in to comment.