mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-08 22:31:04 +00:00
all: Transition to using fs watcher by default (fixes #4552)
This commit is contained in:
parent
d6bb8e6e06
commit
a557d62c4a
@ -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
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
@ -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:",
|
||||
@ -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",
|
||||
@ -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",
|
||||
@ -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",
|
||||
@ -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",
|
||||
|
@ -41,3 +41,31 @@
|
||||
</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> <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> <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> <span translate>Yes</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="dismiss()">
|
||||
<span class="fa fa-times"></span> <span translate>No</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</notification>
|
||||
|
@ -53,6 +53,7 @@ angular.module('syncthing.core')
|
||||
$scope.globalChangeEvents = {};
|
||||
$scope.metricRates = false;
|
||||
$scope.folderPathErrors = {};
|
||||
$scope.currentFolder = {};
|
||||
resetRemoteNeed();
|
||||
|
||||
try {
|
||||
@ -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,
|
||||
@ -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) {
|
||||
@ -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.
|
||||
|
@ -133,37 +133,30 @@
|
||||
<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 form-group" ng-class="{'has-error': folderEditor.rescanIntervalS.$invalid && folderEditor.rescanIntervalS.$dirty}">
|
||||
<div class="col-md-12">
|
||||
<label translate>Scanning</label>
|
||||
<a href="https://docs.syncthing.net/users/syncing.html#scanning" target="_blank"><span class="fa fa-book"></span> <span translate>Help</span></a></br>
|
||||
<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 type="checkbox" ng-model="currentFolder.fsWatcherEnabled" tooltip data-original-title="{{'Use notifications from the filesystem to detect changed items.' | translate }}"> <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"/>
|
||||
<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>
|
||||
</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">
|
||||
<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>
|
||||
<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 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>
|
||||
<div class="row">
|
||||
<!-- Left column -->
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="col-md-6 form-group">
|
||||
<label translate>Folder Type</label>
|
||||
<a href="https://docs.syncthing.net/users/foldertypes.html" target="_blank"><span class="fa fa-book"></span> <span translate>Help</span></a>
|
||||
<select class="form-control" ng-model="currentFolder.type">
|
||||
@ -172,19 +165,7 @@
|
||||
</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">
|
||||
<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>
|
||||
@ -196,6 +177,37 @@
|
||||
</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>
|
||||
</div>
|
||||
|
@ -32,7 +32,7 @@ import (
|
||||
|
||||
const (
|
||||
OldestHandledVersion = 10
|
||||
CurrentVersion = 27
|
||||
CurrentVersion = 28
|
||||
MaxRescanIntervalS = 365 * 24 * 60 * 60
|
||||
)
|
||||
|
||||
@ -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)
|
||||
@ -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]
|
||||
|
@ -207,6 +207,7 @@ func TestOverriddenValues(t *testing.T) {
|
||||
TempIndexMinBlocks: 100,
|
||||
UnackedNotificationIDs: []string{
|
||||
"channelNotification", // added in 17->18 migration
|
||||
"fsWatcherNotification", // added in 27->28 migration
|
||||
},
|
||||
WeakHashSelectionMethod: WeakHashNever,
|
||||
DefaultFolderPath: "/media/syncthing",
|
||||
|
@ -69,7 +69,8 @@ func NewFolderConfiguration(myID protocol.DeviceID, id, label string, fsType fs.
|
||||
f := FolderConfiguration{
|
||||
ID: id,
|
||||
Label: label,
|
||||
RescanIntervalS: 60,
|
||||
RescanIntervalS: 3600,
|
||||
FSWatcherEnabled: true,
|
||||
FSWatcherDelayS: 10,
|
||||
MinDiskFree: Size{Value: 1, Unit: "%"},
|
||||
Devices: []FolderDeviceConfiguration{{DeviceID: myID}},
|
||||
|
2
lib/config/testdata/v25.xml
vendored
2
lib/config/testdata/v25.xml
vendored
@ -1,5 +1,5 @@
|
||||
<configuration version="25">
|
||||
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" fsNotifications="false" notifyDelayS="10" autoNormalize="true">
|
||||
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" fsWatcherEnabled="false" fsWatcherDelayS="10" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
|
||||
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
|
||||
|
2
lib/config/testdata/v26.xml
vendored
2
lib/config/testdata/v26.xml
vendored
@ -1,5 +1,5 @@
|
||||
<configuration version="26">
|
||||
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" fsNotifications="false" notifyDelayS="10" autoNormalize="true">
|
||||
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" fsWatcherEnabled="false" fsWatcherDelayS="10" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
|
||||
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
|
||||
|
2
lib/config/testdata/v27.xml
vendored
2
lib/config/testdata/v27.xml
vendored
@ -1,5 +1,5 @@
|
||||
<configuration version="27">
|
||||
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" fsNotifications="false" notifyDelayS="10" autoNormalize="true">
|
||||
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" fsWatcherEnabled="false" fsWatcherDelayS="10" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
|
||||
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
|
||||
|
16
lib/config/testdata/v28.xml
vendored
Normal file
16
lib/config/testdata/v28.xml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<configuration version="28">
|
||||
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" fsWatcherEnabled="false" fsWatcherDelayS="10" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
|
||||
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
|
||||
<minDiskFree unit="%">1</minDiskFree>
|
||||
<maxConflicts>-1</maxConflicts>
|
||||
<fsync>true</fsync>
|
||||
</folder>
|
||||
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" name="node one" compression="metadata">
|
||||
<address>tcp://a</address>
|
||||
</device>
|
||||
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" name="node two" compression="metadata">
|
||||
<address>tcp://b</address>
|
||||
</device>
|
||||
</configuration>
|
Loading…
Reference in New Issue
Block a user