Archived
Add scan percentages (fixes #1030)
This commit is contained in:
1 parent
875de4f637
commit
94c52e3a77
17 files changed
+202
-72
No files matched your search
Generated
+1
-1
@@ -39,7 +39,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/syncthing/protocol",
|
||||
"Rev": "388a29bbe21d8772ee4c29f4520aa8040309607d"
|
||||
"Rev": "68c5dcd83d9be8f28ae59e951a87cdcf01c6f5cb"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/syncthing/relaysrv/client",
|
||||
|
||||
+1
@@ -20,6 +20,7 @@ type FileInfo struct {
|
||||
Modified int64
|
||||
Version Vector
|
||||
LocalVersion int64
|
||||
CachedSize int64 // noencode (cache only)
|
||||
Blocks []BlockInfo // max:1000000
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ func main() {
|
||||
if *standardBlocks || blockSize < protocol.BlockSize {
|
||||
blockSize = protocol.BlockSize
|
||||
}
|
||||
bs, err := scanner.Blocks(fd, blockSize, fi.Size())
|
||||
bs, err := scanner.Blocks(fd, blockSize, fi.Size(), nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
+9
-2
@@ -195,13 +195,20 @@
|
||||
<div class="panel panel-default" ng-repeat="folder in folderList()">
|
||||
<div class="panel-heading" data-toggle="collapse" data-parent="#folders" href="#folder-{{$index}}" style="cursor: pointer">
|
||||
<div class="panel-progress" ng-show="folderStatus(folder) == 'syncing'" ng-attr-style="width: {{syncPercentage(folder.id)}}%"></div>
|
||||
<div class="panel-progress" ng-show="folderStatus(folder) == 'scanning' && scanProgress[folder.id] != undefined" ng-attr-style="width: {{scanPercentage(folder.id)}}%"></div>
|
||||
<h3 class="panel-title">
|
||||
<span class="fa fa-folder hidden-xs"></span>{{folder.id}}
|
||||
<span class="pull-right text-{{folderClass(folder)}}" ng-switch="folderStatus(folder)">
|
||||
<span ng-switch-when="unknown"><span class="hidden-xs" translate>Unknown</span><span class="visible-xs">◼</span></span>
|
||||
<span ng-switch-when="unshared"><span class="hidden-xs" translate>Unshared</span><span class="visible-xs">◼</span></span>
|
||||
<span ng-switch-when="stopped"><span class="hidden-xs" translate>Stopped</span><span class="visible-xs">◼</span></span>
|
||||
<span ng-switch-when="scanning"><span class="hidden-xs" translate>Scanning</span><span class="visible-xs">◼</span></span>
|
||||
<span ng-switch-when="scanning">
|
||||
<span class="hidden-xs" translate>Scanning</span>
|
||||
<span class="hidden-xs" ng-if="scanPercentage(folder.id) != undefined">
|
||||
({{scanPercentage(folder.id)}}%)
|
||||
</span>
|
||||
<span class="visible-xs">◼</span>
|
||||
</span>
|
||||
<span ng-switch-when="idle"><span class="hidden-xs" translate>Up to Date</span><span class="visible-xs">◼</span></span>
|
||||
<span ng-switch-when="syncing">
|
||||
<span class="hidden-xs" translate>Syncing</span>
|
||||
@@ -445,7 +452,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<span class="fa fa-fw fa-link"></span>
|
||||
<span class="fa fa-fw fa-link"></span>
|
||||
<span translate ng-if="connections[deviceCfg.deviceID].type.indexOf('direct') == 0" >Address</span>
|
||||
<span translate ng-if="connections[deviceCfg.deviceID].type.indexOf('relay') == 0" >Relayed via</span>
|
||||
</th>
|
||||
|
||||
@@ -78,6 +78,7 @@ angular.module('syncthing.core')
|
||||
STARTUP_COMPLETED: 'StartupCompleted', // Emitted exactly once, when initialization is complete and Syncthing is ready to start exchanging data with other devices
|
||||
STATE_CHANGED: 'StateChanged', // Emitted when a folder changes state
|
||||
FOLDER_ERRORS: 'FolderErrors', // Emitted when a folder has errors preventing a full sync
|
||||
FOLDER_SCAN_PROGRESS: 'FolderScanProgress', // Emitted every ScanProgressIntervalS seconds, indicating how far into the scan it is at.
|
||||
|
||||
start: function() {
|
||||
$http.get(urlbase + '/events?limit=1')
|
||||
|
||||
@@ -48,6 +48,7 @@ angular.module('syncthing.core')
|
||||
$scope.failedCurrentPage = 1;
|
||||
$scope.failedCurrentFolder = undefined;
|
||||
$scope.failedPageSize = 10;
|
||||
$scope.scanProgress = {};
|
||||
|
||||
$scope.localStateTotal = {
|
||||
bytes: 0,
|
||||
@@ -163,6 +164,12 @@ angular.module('syncthing.core')
|
||||
if (data.to === 'syncing') {
|
||||
$scope.failed[data.folder] = [];
|
||||
}
|
||||
|
||||
// If a folder has started scanning, then any scan progress is
|
||||
// also obsolete.
|
||||
if (data.to === 'scanning') {
|
||||
delete $scope.scanProgress[data.folder];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -310,6 +317,15 @@ angular.module('syncthing.core')
|
||||
$scope.failed[data.folder] = data.errors;
|
||||
});
|
||||
|
||||
$scope.$on(Events.FOLDER_SCAN_PROGRESS, function (event, arg) {
|
||||
var data = arg.data;
|
||||
$scope.scanProgress[data.folder] = {
|
||||
current: data.current,
|
||||
total: data.total
|
||||
};
|
||||
console.log("FolderScanProgress", data);
|
||||
});
|
||||
|
||||
$scope.emitHTTPError = function (data, status, headers, config) {
|
||||
$scope.$emit('HTTPError', {data: data, status: status, headers: headers, config: config});
|
||||
};
|
||||
@@ -634,6 +650,14 @@ angular.module('syncthing.core')
|
||||
return Math.floor(pct);
|
||||
};
|
||||
|
||||
$scope.scanPercentage = function (folder) {
|
||||
if (!$scope.scanProgress[folder]) {
|
||||
return undefined;
|
||||
}
|
||||
var pct = 100 * $scope.scanProgress[folder].current / $scope.scanProgress[folder].total;
|
||||
return Math.floor(pct);
|
||||
}
|
||||
|
||||
$scope.deviceStatus = function (deviceCfg) {
|
||||
if ($scope.deviceFolders(deviceCfg).length === 0) {
|
||||
return 'unused';
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
AssetsBuildDate = "Tue, 25 Aug 2015 13:40:21 GMT"
|
||||
AssetsBuildDate = "Thu, 27 Aug 2015 18:20:39 GMT"
|
||||
)
|
||||
|
||||
func Assets() map[string][]byte {
|
||||
@@ -50,7 +50,7 @@ func Assets() map[string][]byte {
|
||||
assets["assets/lang/lang-zh-TW.json"], _ = base64.StdEncoding.DecodeString("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 truncated
|
||||
assets["assets/lang/prettyprint.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/1xSUY7TMBD95xRWvrISuQASEiQsCxSVKpuF79nGm5g442hst9oijsNJuBgzdtSW/eq892bGb15zAFIWcNiRDuF5IYNBvVW/iseheFPU0Q5ABrB4XeyBiQYC2BW+O4DVuDdXvCq/rxzeSI8X6aT3I4NeM7jTNKdxbQWR1pMAZHCLgzV+TLC6qy+MKh/QBN2rjcGhd7Ns1rL5fgFcJ3x1e39hVMmFSRaeDNMfDa6NTySQ2GJGVfP+TKiyAYQeZGyMTH+KeL7eBCY+85EZ/pSjvwA/p71mPLlq0zK1caQlhvQri6zMfTVhjOwsjeIjM1tHRz0woWo3zX//WBEkkg8xJGuI/3Vtn9GRl6wW6dq5NaolVHWbCApxiGxGlTXBydibrO66F2quIenkqvYb662bkztVrlUSJYI2ep9t+4Pke9R9fjhIkF2kKcM4MXyYiFPP7aexarby748G07tSpL2sdD+ulQ7MUb6X36/+AQAA//8BAAD//5YJ/N+MAgAA")
|
||||
assets["assets/lang/valid-langs.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/yTMvQ6CMBTF8d2nIJ29j2CiEOOgUVNJHIxDgQqVppC2dPDpvacsv38/kpOUL5Kyprso14diV7xE04utaFVmz3/atSbfAtNpRlvgMnQq0ZCh44P7McBnqDpwh4UxkfliaZzoLLkWL64BWHRYnHGaI5Vy7b3m+onkDcVOSEzE/DIyv4Gq69r6Kd6bPwAAAP//AQAA//8bXi5E0gAAAA==")
|
||||
assets["index.html"], _ = base64.StdEncoding.DecodeString("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 truncated
|
||||
assets["index.html"], _ = base64.StdEncoding.DecodeString("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 truncated
|
||||
assets["modal.html"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/3RST0/cPhC9/z7F/HLogkQ2gDjRXaoWqVIlKiHBpceJPUlcHDuyJ9BtlO/eibNNYbUcEv97783Mm9lo8wzKYozbrPUaLVSoKQPG0jhNv7ZZfpGBq3NkDrlGxrxE9aSD77bZMAjVR4JPwKEnuIZVZGSjVjCOB6wn2pUeg06sL95bQneS2KcT+OY/gM3/eS5LUcCt73bB1A3Dye0pXJ5fXMFjQ/Cwc4ob42r43HPjQ1wn+Mx5bEyEB98HRcLXBF99aEHuYl/+JMXAHlhEmEIbwVfp8N3/NtYi3PelNWoWujOKXKQzeF7D5fp8Dd8qQFCS0sK6v4MXjOA8gzaRgyl7Jg0vhhsBSMzKWDqb5X74HhQ68CWjkcURIEPD3F0XRTvHX/tQF6JaSLxiKirPkyGHzcm1QevrZO3+fljNL7ZeXYPFUNNs5jG28o7J8f79GKIh6X4AtBR4/ufDMPW0j+O48ITZXL0lsmFLrwACiZ1ULYmaapsZCZ39ZVQoQya60+Wkuikm6GvuMCS9cfwXsGiulrQLyfv9Gkqvd8khDuiisr2m95n7/NIgZm91Ku9lVl4XLV1m74B3HW2z+bBwSnYgX66pwt5y2sc2gzT8MiStWZSP2PTGGTYtxcWWD66M3ccZliqyyHRzOyV8aNymmJM6Uu6y3W/2yx8AAAD//wEAAP//qvxG6f8DAAA=")
|
||||
assets["syncthing/app.js"], _ = base64.StdEncoding.DecodeString("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")
|
||||
assets["syncthing/core/aboutModalDirective.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/1SOMQ7CMAxF954im1upSnc6cQBG2ENqWktOglwHhFDvTgpSgT/+/yw/F8fMTmxIQ2asYX5ErxPF0fokCE1lSuxAgl7pVgB3TlkPaXAMrbnkQlOKpm7M842uEdQs8af4lLMKed0Z2EP7NymGKzvFo3BZN4NuNei+/06EdztpYNiul75amr56AQAA//8BAAD//xLf4CHFAAAA")
|
||||
@@ -59,7 +59,7 @@ func Assets() map[string][]byte {
|
||||
assets["syncthing/core/basenameFilter.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/2yOTU7DMBCF9z3F0I1tCRx1XXySpgvTjBNLziTyDxIiuTuJg4QNvNVI75tvRlOfnPZynLrkkLPwQY84WOrlY/LIxAm2SGNdRM/Zmw5IekT2DCZtoJ0IuIDPTO3xGJOnorQ0p1gSe6z5LkApBYk6NJawExVU6M7na1W9aw+z9jGAguyRYXY28ubWNm17b8T1z7mng1+WY1E6pD4O8AqX388Vd7O7dq2nf7isvFXiF7jcfzbXY1y3x74AAAD//wEAAP//1ZQ6AXEBAAA=")
|
||||
assets["syncthing/core/binaryFilter.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/6SSTU7DMBCF9z3F7GxDZUrFLjJLWKAewsTjdiR3jFxbokK5O0lTJIMa/jKbRJrvPX+LsbwtwSa9j64ElOJw5DbviLe6jQmFWkA/2lPImKR4JrbpKJbgS49RZJAK3k7MMAlzSVwtiV9KrolhyJ8XYIyBwg49MbqvWFUoViCaT8tuovEeblfrO7iqP5eKR/rGXMCbKYtTRuf4QK/opMOW9jYcxoeXsFYKrkHAI/1H9beOM+U2f5P70WqmztP3Oueujc07nWJ/KB/3NGSrZDf+dqpZvAMAAP//AQAA///Yhw40zwIAAA==")
|
||||
assets["syncthing/core/durationFilter.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/3RUTW/aQBS8+1dMV6rsAAE7iVBlQnpoOeTQ5JBjFFUbvMYuthftB21K/N/7FnAwBS+S9TDzZmbnPTHq9TCX1VooA15KWxnIFFrQu0TDSGij8mqBVKqSG7AEGUpoht+5yaQ1+CuUxJoXVmgPPayUmOc6lxVKqw1eBWQlHKWf+AP4mXuU7qH9IBEpt4W5cH2zP7xcFSJ29WYTXUXhVRiG1++JVdwQXV3DncvLO0Q3YZggGme4CUtc666WmJWM2k5auvHZCX6P/R/THIe9jTKv1xt5vFrYgqthKRNbiMDXb9XcZJTdcC6V8OmWdIZpXhihAr8hpChSS0CXWHCBjddQ+1aLbfhz40+8j9drrvA0+/b48P3p5/0DptiwhMX4MibHA5C7GNfjbVlSOaYCTFMV1ZMPDiWMVVVLN69W1gwOs2v7aESV0DQrEmRscvRjniL41NnqzmEnps7McXt9TOacEGzFlRb3lWmsReHFcRvtIwLna0k9rUTO6TuYI92RjQ7g5+UL3kHUGI3wg5tsmBZSKu+Ewd3R4I6gZ+h3kW7T6dMF6dMnuT6WkxNofZ66FdAUy26N7dj2Ul+bIga7jViHHkRBa3Seb5f15ymOAjlnuvvb3hN7niklVUyctOx0GwOr+UIMuv8PnOPH118EHS7Fmw7aI+yDvbTWZL+6Na3APwAAAP//AQAA///R6NJhrwQAAA==")
|
||||
assets["syncthing/core/eventService.js"], _ = base64.StdEncoding.DecodeString("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")
|
||||
assets["syncthing/core/eventService.js"], _ = base64.StdEncoding.DecodeString("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")
|
||||
assets["syncthing/core/httpErrorDialogDirective.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/1yOwcrCMBCE732K3LaFkt7/nn7QR9B7SNd2YZOU7UYR6bubKhR1jjOzO5+LY2YnNqQhM9aw3KPXieJofRKEpjJFdiBBr3QthUl1PookOZDjNEJrLrmcUIqmbszj1d8kqFnih/E2FxXy+mfgH9qvSDHM7BRPwiXdMboNo/sZPRPe7KSBYX+x9tXa9NUTAAD//wEAAP//F1ZQpc8AAAA=")
|
||||
assets["syncthing/core/httpErrorDialogView.html"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/0yQsW7DMAxE5/orCC2ZmvyA7aXoXqBfwMgXW4AsqSQNJEjz75VcFM0kvLvDiWS/5okjhWlwi1l5F8niSI1t08FNnGZUDj6nweHqI69sIadXH8RHOLJgEYO73w9vOSX4ZtLecqBvMuGkkQ2Phxu7l778KxWJPm/J2xLSTAqsSpbpDMK1QAKSbwZTkXyOWNvrodrEW96EBF8b1I70EcGKyheBLmQLqPAMyi1TVxF7+ihcfgN/pRANanqs053K2PWn/SBj9wMAAP//AQAA//+4f+ClGQEAAA==")
|
||||
assets["syncthing/core/identiconDirective.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/5xVTVPbMBC951dsZwp2GkcOdHpJ6s4wDMxwgENz6IEyHVdWYk0VKSPLcSnkv3clJ8F2FL50wUj79r2V3m5SOS9FqslCZaVgYVDcS2pyLueEKs2Cfg9wkYxrRg1fYQDPmDScKhlEcBt8rLjMVIXfsxKBXEkIN3t9eHBgu1aphmI1v5lCAkFuzHIcx1VVkeozUXoen45GoxjPg0lvB9nlu9oShqtUlCyCgv9jzeQNAkyfKVouEEGoZqlhF4LZ/26moeOPILA8/ck+OlelyC65EN+x1DODqZ5K0qqKgCrRpbVLM1NqCR+2dZNlqgt2JU2tl9A81ecqY2fGpoGBzQOf6ioiOBn14QhOO4LWh/Rdc62Vfq9Cy2nZ4PjYqUiSBBY8ywQ7R+RLChaOGyMvlW5xP0/rSIeObwgnL9Y5e/sLWJj152te38bZ5/eopYYUDHmN5r9Lg1b/i7YO69eyp1PnuwEER13/HMDfW7x983fiK56ZHHNswW/B5ozPc+MD76Hxaki6XDKZnedcZKFFvOxHG+XZVdX+Jl6hz00b3/lTW8kdrVZnu0gq0qLAGhtDqSPcmS+p/zw+wpf26e5uEuzDEcQurh2yk4kx16nJCWVc1I0UY9vWlm4h+AzqzvdbFQ8wVT0ajJpiLXIe9olmS5FSFsa3P3/8uos5FuV9rBn2nvNUAqOJvW74WquGwUC3h+4ezLV84+JdT36D4ckEhsMDvdWsqjsin5ryOaSj92A8xfkJmzPv9ZQ+2uYEc1PL00vNtT546j/Z323vrHsd+9UDcjV/ktEI2Rw/dDAFWoaaMQQXQdT2OlVLNj5kOgQkQVtNGy64/DNuTFyXLgJWj9AI0m3fFb6r34RtBkkoWdX44XapSN0U3cnSa3+t7zDgPwAAAP//AQAA//9afsjulQgAAA==")
|
||||
@@ -79,7 +79,7 @@ func Assets() map[string][]byte {
|
||||
assets["syncthing/core/selectOnClickDirective.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/3SQQWvEIBCF7/srPBRiIEjPXXooe2+hPZYeRKeprJkpo2YpJf+9atLdJWzeSZ/z+Z5q7JPXrAayyYNswg+a+OWwV4YYmnYnspR1DCa6sQyAz8sXPHhnjk0nPlMGHKGQdyeHlk6t+K1QEUNMjFdGkXd4fLjigqFv6ES+dwCMndAxcmhXUNEyoQhlY1bx8hZQNGoWc+cS9iiWlqqH+PZvy3a/yXL+IcicJZNqumHQEV6LvcVVRs2pz2ThQBgzGuTygvf7jw3y3FQxDDTCk/c1KWxFXQBt7Vyqpt8Yn1bedN5N+105/AMAAP//AQAA//+SF+4JDAIAAA==")
|
||||
assets["syncthing/core/shutdownDialogDirective.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/1SOwQqDQAxE737F3qIg672eCv2F9r6sqQZitsRspRT/vdqC1DnOTDIvSJ85qB9TlxlLmF4SbSDpfUyKUBVule9IMRo9t8KQrUuzXChw6qF297xeUBJXVu79rW9StKzyZ/zMyZSinRycoT5EhuODg+FVeU13imajaI6bN8LZDzYy7B+WtliqtvgAAAD//wEAAP//3qFOo80AAAA=")
|
||||
assets["syncthing/core/shutdownDialogView.html"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/0TOTaqDMBAH8PXzFMNsXL16gZhNj+AJ0jjWQJwJzgQp1ru3lkK3P/h/uEXGkCGNPepcbZSNEdSCVX1LjZFUEVIU7rHIRuu/TBOCJcvU4763wzcFV1lKJqMWnmBrYM3B6DjQN3+u/MQPD442J77DHBRuRAznMpwlF9cV37juc8o3LwAAAP//AQAA//99X8KxnQAAAA==")
|
||||
assets["syncthing/core/syncthingController.js"], _ = base64.StdEncoding.DecodeString("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 truncated
|
||||
assets["syncthing/core/syncthingController.js"], _ = base64.StdEncoding.DecodeString("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 truncated
|
||||
assets["syncthing/core/uniqueFolderDirective.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/7SSwW4yMQyE7zyFD7+0IK3CHc5/b1V74h5tvKzVkIDtQFHFuzdhUaGwtJWqzgVp4vkYW2vDMnnLZhVd8jiuZB8a7SgsTRMZq8kIsowjxkZpmwdSoE3Ch+gdclVDm/I8xQDjCbwdh4sYNXG4MHpzkzJnBlVYPkaHvqo/vXsKL7MLoDRxjTWgX9VgVVlqaJT95ApbVHzzb21ZkMWkIB21Oj6jtoS7hfUJh8JF1J7+z6Ajzev/fyUpv/cCRdMp7BCki8m7UClsrSdnFe8G+pqCuiiTpPubcyrnjvNBwCFfQvCiaXsMiemsPO3CM2ePM/K86zfdtUPoGYBlWwHrGa3b/6J/a3PHrxf4aScS6OF/dM5B9/ThftzwNnu44p05h/moPL4DAAD//wEAAP//r65WJ1IDAAA=")
|
||||
assets["syncthing/core/upgradingDialogDirective.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/1yOwQrCMBBE7/2K3LaFkt7tSfAX9B7SNV3YJmW7UUT676YKRZ3jzNudcTFkdmKnNGTGGpZH9DpSDNYnQWgqU2QHEvRKtwLkOYgbCnAixylAa665nFCKpm7M881vEtQs8cv4mIsKeT0YOEL7EylOMzvFs3BJ9xndNqP7K70Q3u2oE8P+Yu2rtemrFwAAAP//AQAA//99zQ2GzwAAAA==")
|
||||
assets["syncthing/core/upgradingDialogView.html"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/1zOTarDMAwE4PXLKYQ2WSW5gO0zPCg9gHDcVODaxlIIJc3dm5b+QLfDN8yYSx4pAo8W5zJVGjlNCKKks1jkdMoI7HOySLXmpfNcfQzdXBCUNQaL69oe380WbqCVkkTSsG3omj9TnJFC6Zu7wzV5Pe8cWOCz2pvh4Rz88v8YSAIsxPoifb/j4hozPN+75g4AAP//AQAA///kaeW6xgAAAA==")
|
||||
|
||||
+15
-14
@@ -68,20 +68,21 @@ func (cfg Configuration) Copy() Configuration {
|
||||
}
|
||||
|
||||
type FolderConfiguration struct {
|
||||
ID string `xml:"id,attr" json:"id"`
|
||||
RawPath string `xml:"path,attr" json:"path"`
|
||||
Devices []FolderDeviceConfiguration `xml:"device" json:"devices"`
|
||||
ReadOnly bool `xml:"ro,attr" json:"readOnly"`
|
||||
RescanIntervalS int `xml:"rescanIntervalS,attr" json:"rescanIntervalS"`
|
||||
IgnorePerms bool `xml:"ignorePerms,attr" json:"ignorePerms"`
|
||||
AutoNormalize bool `xml:"autoNormalize,attr" json:"autoNormalize"`
|
||||
MinDiskFreePct int `xml:"minDiskFreePct" json:"minDiskFreePct"`
|
||||
Versioning VersioningConfiguration `xml:"versioning" json:"versioning"`
|
||||
Copiers int `xml:"copiers" json:"copiers"` // This defines how many files are handled concurrently.
|
||||
Pullers int `xml:"pullers" json:"pullers"` // Defines how many blocks are fetched at the same time, possibly between separate copier routines.
|
||||
Hashers int `xml:"hashers" json:"hashers"` // Less than one sets the value to the number of cores. These are CPU bound due to hashing.
|
||||
Order PullOrder `xml:"order" json:"order"`
|
||||
IgnoreDelete bool `xml:"ignoreDelete" json:"ignoreDelete"`
|
||||
ID string `xml:"id,attr" json:"id"`
|
||||
RawPath string `xml:"path,attr" json:"path"`
|
||||
Devices []FolderDeviceConfiguration `xml:"device" json:"devices"`
|
||||
ReadOnly bool `xml:"ro,attr" json:"readOnly"`
|
||||
RescanIntervalS int `xml:"rescanIntervalS,attr" json:"rescanIntervalS"`
|
||||
IgnorePerms bool `xml:"ignorePerms,attr" json:"ignorePerms"`
|
||||
AutoNormalize bool `xml:"autoNormalize,attr" json:"autoNormalize"`
|
||||
MinDiskFreePct int `xml:"minDiskFreePct" json:"minDiskFreePct"`
|
||||
Versioning VersioningConfiguration `xml:"versioning" json:"versioning"`
|
||||
Copiers int `xml:"copiers" json:"copiers"` // This defines how many files are handled concurrently.
|
||||
Pullers int `xml:"pullers" json:"pullers"` // Defines how many blocks are fetched at the same time, possibly between separate copier routines.
|
||||
Hashers int `xml:"hashers" json:"hashers"` // Less than one sets the value to the number of cores. These are CPU bound due to hashing.
|
||||
Order PullOrder `xml:"order" json:"order"`
|
||||
IgnoreDelete bool `xml:"ignoreDelete" json:"ignoreDelete"`
|
||||
ScanProgressIntervalS int `xml:"scanProgressInterval" json:"scanProgressInterval"` // Set to a negative value to disable. Value of 0 will get replaced with value of 2 (default value)
|
||||
|
||||
Invalid string `xml:"-" json:"invalid"` // Set at runtime when there is an error, not saved
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ const (
|
||||
FolderSummary
|
||||
FolderCompletion
|
||||
FolderErrors
|
||||
FolderScanProgress
|
||||
|
||||
AllEvents = (1 << iota) - 1
|
||||
)
|
||||
@@ -84,6 +85,8 @@ func (t EventType) String() string {
|
||||
return "DevicePaused"
|
||||
case DeviceResumed:
|
||||
return "DeviceResumed"
|
||||
case FolderScanProgress:
|
||||
return "FolderScanProgress"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
+14
-12
@@ -1297,18 +1297,20 @@ nextSub:
|
||||
subs = unifySubs
|
||||
|
||||
w := &scanner.Walker{
|
||||
Dir: folderCfg.Path(),
|
||||
Subs: subs,
|
||||
Matcher: ignores,
|
||||
BlockSize: protocol.BlockSize,
|
||||
TempNamer: defTempNamer,
|
||||
TempLifetime: time.Duration(m.cfg.Options().KeepTemporariesH) * time.Hour,
|
||||
CurrentFiler: cFiler{m, folder},
|
||||
MtimeRepo: db.NewVirtualMtimeRepo(m.db, folderCfg.ID),
|
||||
IgnorePerms: folderCfg.IgnorePerms,
|
||||
AutoNormalize: folderCfg.AutoNormalize,
|
||||
Hashers: m.numHashers(folder),
|
||||
ShortID: m.shortID,
|
||||
Folder: folderCfg.ID,
|
||||
Dir: folderCfg.Path(),
|
||||
Subs: subs,
|
||||
Matcher: ignores,
|
||||
BlockSize: protocol.BlockSize,
|
||||
TempNamer: defTempNamer,
|
||||
TempLifetime: time.Duration(m.cfg.Options().KeepTemporariesH) * time.Hour,
|
||||
CurrentFiler: cFiler{m, folder},
|
||||
MtimeRepo: db.NewVirtualMtimeRepo(m.db, folderCfg.ID),
|
||||
IgnorePerms: folderCfg.IgnorePerms,
|
||||
AutoNormalize: folderCfg.AutoNormalize,
|
||||
Hashers: m.numHashers(folder),
|
||||
ShortID: m.shortID,
|
||||
ProgressTickIntervalS: folderCfg.ScanProgressIntervalS,
|
||||
}
|
||||
|
||||
runner.setState(FolderScanning)
|
||||
|
||||
@@ -989,7 +989,7 @@ func (p *rwFolder) handleFile(file protocol.FileInfo, copyChan chan<- copyBlocks
|
||||
|
||||
// Check for an old temporary file which might have some blocks we could
|
||||
// reuse.
|
||||
tempBlocks, err := scanner.HashFile(tempName, protocol.BlockSize)
|
||||
tempBlocks, err := scanner.HashFile(tempName, protocol.BlockSize, 0, nil)
|
||||
if err == nil {
|
||||
// Check for any reusable blocks in the temp file
|
||||
tempCopyBlocks, _ := scanner.BlockDiff(tempBlocks, file.Blocks)
|
||||
|
||||
@@ -241,7 +241,7 @@ func TestCopierFinder(t *testing.T) {
|
||||
}
|
||||
|
||||
// Verify that the fetched blocks have actually been written to the temp file
|
||||
blks, err := scanner.HashFile(tempFile, protocol.BlockSize)
|
||||
blks, err := scanner.HashFile(tempFile, protocol.BlockSize, 0, nil)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
|
||||
+23
-18
@@ -19,24 +19,27 @@ import (
|
||||
// workers are used in parallel. The outbox will become closed when the inbox
|
||||
// is closed and all items handled.
|
||||
|
||||
func newParallelHasher(dir string, blockSize, workers int, outbox, inbox chan protocol.FileInfo) {
|
||||
func newParallelHasher(dir string, blockSize, workers int, outbox, inbox chan protocol.FileInfo, counter *uint64, done chan struct{}) {
|
||||
wg := sync.NewWaitGroup()
|
||||
wg.Add(workers)
|
||||
|
||||
for i := 0; i < workers; i++ {
|
||||
go func() {
|
||||
hashFiles(dir, blockSize, outbox, inbox)
|
||||
hashFiles(dir, blockSize, outbox, inbox, counter)
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
if done != nil {
|
||||
close(done)
|
||||
}
|
||||
close(outbox)
|
||||
}()
|
||||
}
|
||||
|
||||
func HashFile(path string, blockSize int) ([]protocol.BlockInfo, error) {
|
||||
func HashFile(path string, blockSize int, sizeHint int64, counter *uint64) ([]protocol.BlockInfo, error) {
|
||||
fd, err := os.Open(path)
|
||||
if err != nil {
|
||||
if debug {
|
||||
@@ -44,27 +47,29 @@ func HashFile(path string, blockSize int) ([]protocol.BlockInfo, error) {
|
||||
}
|
||||
return []protocol.BlockInfo{}, err
|
||||
}
|
||||
|
||||
fi, err := fd.Stat()
|
||||
if err != nil {
|
||||
fd.Close()
|
||||
if debug {
|
||||
l.Debugln("stat:", err)
|
||||
}
|
||||
return []protocol.BlockInfo{}, err
|
||||
}
|
||||
defer fd.Close()
|
||||
return Blocks(fd, blockSize, fi.Size())
|
||||
|
||||
if sizeHint == 0 {
|
||||
fi, err := fd.Stat()
|
||||
if err != nil {
|
||||
if debug {
|
||||
l.Debugln("stat:", err)
|
||||
}
|
||||
return []protocol.BlockInfo{}, err
|
||||
}
|
||||
sizeHint = fi.Size()
|
||||
}
|
||||
|
||||
return Blocks(fd, blockSize, sizeHint, counter)
|
||||
}
|
||||
|
||||
func hashFiles(dir string, blockSize int, outbox, inbox chan protocol.FileInfo) {
|
||||
func hashFiles(dir string, blockSize int, outbox, inbox chan protocol.FileInfo, counter *uint64) {
|
||||
for f := range inbox {
|
||||
if f.IsDirectory() || f.IsDeleted() || f.IsSymlink() {
|
||||
outbox <- f
|
||||
continue
|
||||
if f.IsDirectory() || f.IsDeleted() {
|
||||
panic("Bug. Asked to hash a directory or a deleted file.")
|
||||
}
|
||||
|
||||
blocks, err := HashFile(filepath.Join(dir, f.Name), blockSize)
|
||||
blocks, err := HashFile(filepath.Join(dir, f.Name), blockSize, f.CachedSize, counter)
|
||||
if err != nil {
|
||||
if debug {
|
||||
l.Debugln("hash error:", f.Name, err)
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/syncthing/protocol"
|
||||
)
|
||||
@@ -18,7 +19,7 @@ import (
|
||||
var SHA256OfNothing = []uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}
|
||||
|
||||
// Blocks returns the blockwise hash of the reader.
|
||||
func Blocks(r io.Reader, blocksize int, sizehint int64) ([]protocol.BlockInfo, error) {
|
||||
func Blocks(r io.Reader, blocksize int, sizehint int64, counter *uint64) ([]protocol.BlockInfo, error) {
|
||||
var blocks []protocol.BlockInfo
|
||||
if sizehint > 0 {
|
||||
blocks = make([]protocol.BlockInfo, 0, int(sizehint/int64(blocksize)))
|
||||
@@ -36,6 +37,10 @@ func Blocks(r io.Reader, blocksize int, sizehint int64) ([]protocol.BlockInfo, e
|
||||
break
|
||||
}
|
||||
|
||||
if counter != nil {
|
||||
atomic.AddUint64(counter, uint64(n))
|
||||
}
|
||||
|
||||
b := protocol.BlockInfo{
|
||||
Size: int32(n),
|
||||
Offset: offset,
|
||||
|
||||
@@ -51,7 +51,7 @@ var blocksTestData = []struct {
|
||||
func TestBlocks(t *testing.T) {
|
||||
for _, test := range blocksTestData {
|
||||
buf := bytes.NewBuffer(test.data)
|
||||
blocks, err := Blocks(buf, test.blocksize, 0)
|
||||
blocks, err := Blocks(buf, test.blocksize, 0, nil)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -105,8 +105,8 @@ var diffTestData = []struct {
|
||||
|
||||
func TestDiff(t *testing.T) {
|
||||
for i, test := range diffTestData {
|
||||
a, _ := Blocks(bytes.NewBufferString(test.a), test.s, 0)
|
||||
b, _ := Blocks(bytes.NewBufferString(test.b), test.s, 0)
|
||||
a, _ := Blocks(bytes.NewBufferString(test.a), test.s, 0, nil)
|
||||
b, _ := Blocks(bytes.NewBufferString(test.b), test.s, 0, nil)
|
||||
_, d := BlockDiff(a, b)
|
||||
if len(d) != len(test.d) {
|
||||
t.Fatalf("Incorrect length for diff %d; %d != %d", i, len(d), len(test.d))
|
||||
|
||||
+89
-13
@@ -12,11 +12,13 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/syncthing/protocol"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/ignore"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/symlinks"
|
||||
@@ -39,6 +41,8 @@ func init() {
|
||||
}
|
||||
|
||||
type Walker struct {
|
||||
// Folder for which the walker has been created
|
||||
Folder string
|
||||
// Dir is the base directory for the walk
|
||||
Dir string
|
||||
// Limit walking to these paths within Dir, or no limit if Sub is empty
|
||||
@@ -66,6 +70,9 @@ type Walker struct {
|
||||
Hashers int
|
||||
// Our vector clock id
|
||||
ShortID uint64
|
||||
// Optional progress tick interval which defines how often FolderScanProgress
|
||||
// events are emitted. Negative number means disabled.
|
||||
ProgressTickIntervalS int
|
||||
}
|
||||
|
||||
type TempNamer interface {
|
||||
@@ -92,12 +99,13 @@ func (w *Walker) Walk() (chan protocol.FileInfo, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
files := make(chan protocol.FileInfo)
|
||||
hashedFiles := make(chan protocol.FileInfo)
|
||||
newParallelHasher(w.Dir, w.BlockSize, w.Hashers, hashedFiles, files)
|
||||
toHashChan := make(chan protocol.FileInfo)
|
||||
finishedChan := make(chan protocol.FileInfo)
|
||||
|
||||
// A routine which walks the filesystem tree, and sends files which have
|
||||
// been modified to the counter routine.
|
||||
go func() {
|
||||
hashFiles := w.walkAndHashFiles(files, hashedFiles)
|
||||
hashFiles := w.walkAndHashFiles(toHashChan, finishedChan)
|
||||
if len(w.Subs) == 0 {
|
||||
filepath.Walk(w.Dir, hashFiles)
|
||||
} else {
|
||||
@@ -105,10 +113,77 @@ func (w *Walker) Walk() (chan protocol.FileInfo, error) {
|
||||
filepath.Walk(filepath.Join(w.Dir, sub), hashFiles)
|
||||
}
|
||||
}
|
||||
close(files)
|
||||
close(toHashChan)
|
||||
}()
|
||||
|
||||
return hashedFiles, nil
|
||||
// We're not required to emit scan progress events, just kick off hashers,
|
||||
// and feed inputs directly from the walker.
|
||||
if w.ProgressTickIntervalS < 0 {
|
||||
newParallelHasher(w.Dir, w.BlockSize, w.Hashers, finishedChan, toHashChan, nil, nil)
|
||||
return finishedChan, nil
|
||||
}
|
||||
|
||||
// Defaults to every 2 seconds.
|
||||
if w.ProgressTickIntervalS == 0 {
|
||||
w.ProgressTickIntervalS = 2
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(time.Duration(w.ProgressTickIntervalS) * time.Second)
|
||||
|
||||
// We need to emit progress events, hence we create a routine which buffers
|
||||
// the list of files to be hashed, counts the total number of
|
||||
// bytes to hash, and once no more files need to be hashed (chan gets closed),
|
||||
// start a routine which periodically emits FolderScanProgress events,
|
||||
// until a stop signal is sent by the parallel hasher.
|
||||
// Parallel hasher is stopped by this routine when we close the channel over
|
||||
// which it receives the files we ask it to hash.
|
||||
go func() {
|
||||
var filesToHash []protocol.FileInfo
|
||||
var total, progress uint64
|
||||
for file := range toHashChan {
|
||||
filesToHash = append(filesToHash, file)
|
||||
total += uint64(file.CachedSize)
|
||||
}
|
||||
|
||||
realToHashChan := make(chan protocol.FileInfo)
|
||||
done := make(chan struct{})
|
||||
newParallelHasher(w.Dir, w.BlockSize, w.Hashers, finishedChan, realToHashChan, &progress, done)
|
||||
|
||||
// A routine which actually emits the FolderScanProgress events
|
||||
// every w.ProgressTicker ticks, until the hasher routines terminate.
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
if debug {
|
||||
l.Debugln("Walk progress done", w.Dir, w.Subs, w.BlockSize, w.Matcher)
|
||||
}
|
||||
ticker.Stop()
|
||||
return
|
||||
case <-ticker.C:
|
||||
current := atomic.LoadUint64(&progress)
|
||||
if debug {
|
||||
l.Debugf("Walk %s %s current progress %d/%d (%d%%)", w.Dir, w.Subs, current, total, current*100/total)
|
||||
}
|
||||
events.Default.Log(events.FolderScanProgress, map[string]interface{}{
|
||||
"folder": w.Folder,
|
||||
"current": current,
|
||||
"total": total,
|
||||
})
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for _, file := range filesToHash {
|
||||
if debug {
|
||||
l.Debugln("real to hash:", file.Name)
|
||||
}
|
||||
realToHashChan <- file
|
||||
}
|
||||
close(realToHashChan)
|
||||
}()
|
||||
|
||||
return finishedChan, nil
|
||||
}
|
||||
|
||||
func (w *Walker) walkAndHashFiles(fchan, dchan chan protocol.FileInfo) filepath.WalkFunc {
|
||||
@@ -241,7 +316,7 @@ func (w *Walker) walkAndHashFiles(fchan, dchan chan protocol.FileInfo) filepath.
|
||||
return skip
|
||||
}
|
||||
|
||||
blocks, err := Blocks(strings.NewReader(target), w.BlockSize, 0)
|
||||
blocks, err := Blocks(strings.NewReader(target), w.BlockSize, 0, nil)
|
||||
if err != nil {
|
||||
if debug {
|
||||
l.Debugln("hash link error:", p, err)
|
||||
@@ -272,10 +347,10 @@ func (w *Walker) walkAndHashFiles(fchan, dchan chan protocol.FileInfo) filepath.
|
||||
}
|
||||
|
||||
if debug {
|
||||
l.Debugln("symlink to hash:", p, f)
|
||||
l.Debugln("symlink changedb:", p, f)
|
||||
}
|
||||
|
||||
fchan <- f
|
||||
dchan <- f
|
||||
|
||||
return skip
|
||||
}
|
||||
@@ -349,10 +424,11 @@ func (w *Walker) walkAndHashFiles(fchan, dchan chan protocol.FileInfo) filepath.
|
||||
}
|
||||
|
||||
f := protocol.FileInfo{
|
||||
Name: rn,
|
||||
Version: cf.Version.Update(w.ShortID),
|
||||
Flags: flags,
|
||||
Modified: mtime.Unix(),
|
||||
Name: rn,
|
||||
Version: cf.Version.Update(w.ShortID),
|
||||
Flags: flags,
|
||||
Modified: mtime.Unix(),
|
||||
CachedSize: info.Size(),
|
||||
}
|
||||
if debug {
|
||||
l.Debugln("to hash:", p, f)
|
||||
|
||||
@@ -149,8 +149,9 @@ func TestVerify(t *testing.T) {
|
||||
// data should be an even multiple of blocksize long
|
||||
data := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut e")
|
||||
buf := bytes.NewBuffer(data)
|
||||
var progress uint64
|
||||
|
||||
blocks, err := Blocks(buf, blocksize, 0)
|
||||
blocks, err := Blocks(buf, blocksize, 0, &progress)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -158,6 +159,10 @@ func TestVerify(t *testing.T) {
|
||||
t.Fatalf("Incorrect number of blocks %d != %d", len(blocks), exp)
|
||||
}
|
||||
|
||||
if uint64(len(data)) != progress {
|
||||
t.Fatalf("Incorrect counter value %d != %d", len(data), progress)
|
||||
}
|
||||
|
||||
buf = bytes.NewBuffer(data)
|
||||
err = Verify(buf, blocksize, blocks)
|
||||
t.Log(err)
|
||||
|
||||
Reference in new issue
Block a user