зеркало из https://github.com/nextcloud/desktop.git
File watcher: Reduce touch ignore duration
On Linux and Windows the file watcher can't distinguish between changes that were caused by the process itself, like during a sync operation, and external changes. To work around that the client keeps a list of files it has touched and blocks notifications on these files for a bit. The duration of this block was originally and arbitrarily set at 15 seconds. During manual tests I regularly thought there was a bug when syncs didn't trigger, when the only problem was that my changes happened too close to a previous sync operation. This change reduces the duration to three seconds. I imagine that this is still enough. Also use std::chrono while at it.
This commit is contained in:
Родитель
539cef345e
Коммит
4d58208676
|
@ -497,7 +497,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
// much lower age than the default since this utility is usually made to be run right after a change in the tests
|
||||
SyncEngine::minimumFileAgeForUpload = 0;
|
||||
SyncEngine::minimumFileAgeForUpload = std::chrono::milliseconds(0);
|
||||
|
||||
int restartCount = 0;
|
||||
restart_sync:
|
||||
|
|
|
@ -61,7 +61,7 @@ static bool fileIsStillChanging(const SyncFileItem &item)
|
|||
const QDateTime modtime = Utility::qDateTimeFromTime_t(item._modtime);
|
||||
const qint64 msSinceMod = modtime.msecsTo(QDateTime::currentDateTimeUtc());
|
||||
|
||||
return msSinceMod < SyncEngine::minimumFileAgeForUpload
|
||||
return std::chrono::milliseconds(msSinceMod) < SyncEngine::minimumFileAgeForUpload
|
||||
// if the mtime is too much in the future we *do* upload the file
|
||||
&& msSinceMod > -10000;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include <climits>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QSslSocket>
|
||||
|
@ -58,10 +59,25 @@ namespace OCC {
|
|||
|
||||
Q_LOGGING_CATEGORY(lcEngine, "nextcloud.sync.engine", QtInfoMsg)
|
||||
|
||||
static const int s_touchedFilesMaxAgeMs = 15 * 1000;
|
||||
bool SyncEngine::s_anySyncRunning = false;
|
||||
|
||||
qint64 SyncEngine::minimumFileAgeForUpload = 2000;
|
||||
/** When the client touches a file, block change notifications for this duration (ms)
|
||||
*
|
||||
* On Linux and Windows the file watcher can't distinguish a change that originates
|
||||
* from the client (like a download during a sync operation) and an external change.
|
||||
* To work around that, all files the client touches are recorded and file change
|
||||
* notifications for these are blocked for some time. This value controls for how
|
||||
* long.
|
||||
*
|
||||
* Reasons this delay can't be very small:
|
||||
* - it takes time for the change notification to arrive and to be processed by the client
|
||||
* - some time could pass between the client recording that a file will be touched
|
||||
* and its filesystem operation finishing, triggering the notification
|
||||
*/
|
||||
static const std::chrono::milliseconds s_touchedFilesMaxAgeMs(3 * 1000);
|
||||
|
||||
// doc in header
|
||||
std::chrono::milliseconds SyncEngine::minimumFileAgeForUpload(2000);
|
||||
|
||||
SyncEngine::SyncEngine(AccountPtr account, const QString &localPath,
|
||||
const QString &remotePath, OCC::SyncJournalDb *journal)
|
||||
|
@ -911,8 +927,9 @@ void SyncEngine::slotAddTouchedFile(const QString &fn)
|
|||
break;
|
||||
// Compare to our new QElapsedTimer instead of using elapsed().
|
||||
// This avoids querying the current time from the OS for every loop.
|
||||
if (now.msecsSinceReference() - first.key().msecsSinceReference() <= s_touchedFilesMaxAgeMs) {
|
||||
// We found the first path younger than 15 second, keep the rest.
|
||||
auto elapsed = std::chrono::milliseconds(now.msecsSinceReference() - first.key().msecsSinceReference());
|
||||
if (elapsed <= s_touchedFilesMaxAgeMs) {
|
||||
// We found the first path younger than the maximum age, keep the rest.
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -934,7 +951,7 @@ bool SyncEngine::wasFileTouched(const QString &fn) const
|
|||
auto begin = _touchedFiles.constBegin();
|
||||
for (auto it = _touchedFiles.constEnd(); it != begin; --it) {
|
||||
if ((it-1).value() == fn)
|
||||
return (it-1).key().elapsed() <= s_touchedFilesMaxAgeMs;
|
||||
return std::chrono::milliseconds((it-1).key().elapsed()) <= s_touchedFilesMaxAgeMs;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -87,12 +87,17 @@ public:
|
|||
SyncJournalDb *journal() const { return _journal; }
|
||||
QString localPath() const { return _localPath; }
|
||||
|
||||
/**
|
||||
* Minimum age, in milisecond, of a file that can be uploaded.
|
||||
* Files more recent than that are not going to be uploaeded as they are considered
|
||||
* too young and possibly still changing
|
||||
/** Duration in ms that uploads should be delayed after a file change
|
||||
*
|
||||
* In certain situations a file can be written to very regularly over a large
|
||||
* amount of time. Copying a large file could take a while. A logfile could be
|
||||
* updated every second.
|
||||
*
|
||||
* In these cases it isn't desirable to attempt to upload the "unfinished" file.
|
||||
* To avoid that, uploads of files where the distance between the mtime and the
|
||||
* current time is less than this duration are skipped.
|
||||
*/
|
||||
static qint64 minimumFileAgeForUpload; // in ms
|
||||
static std::chrono::milliseconds minimumFileAgeForUpload;
|
||||
|
||||
/**
|
||||
* Control whether local discovery should read from filesystem or db.
|
||||
|
|
|
@ -906,7 +906,7 @@ public:
|
|||
: _localModifier(_tempDir.path())
|
||||
{
|
||||
// Needs to be done once
|
||||
OCC::SyncEngine::minimumFileAgeForUpload = 0;
|
||||
OCC::SyncEngine::minimumFileAgeForUpload = std::chrono::milliseconds(0);
|
||||
OCC::Logger::instance()->setLogFile("-");
|
||||
|
||||
QDir rootDir{_tempDir.path()};
|
||||
|
|
Загрузка…
Ссылка в новой задаче