Show a tray message when a folder watcher becomes unreliable #6119

This commit is contained in:
Christian Kamm 2018-04-24 09:52:15 +02:00 committed by Camila San
parent 028da61824
commit 2844c925eb
No known key found for this signature in database
GPG Key ID: 7A4A6121E88E2AD4
8 changed files with 69 additions and 12 deletions

View File

@ -21,6 +21,25 @@ When a deeply nested directory is excluded from synchronization it will be
listed with other ignored files and directories in the "Not synced" tab of
the "Activity" pane.
There Was A Warning About Changes In Synchronized Folders Not Being Tracked Reliably.
-------------------------------------------------------------------------------------
On linux when the synchronized folder contains very many subfolders the
operating system may not allow for enough inotify watches to monitor the
changes in all of them.
In this case the client will not be able to immediately start the
synchronization process when a file in one of the unmonitored folders changes.
Instead, the client will show the warning and manually scan folders for changes
in a regular interval (two hours by default).
This problem can be solved by setting the fs.inotify.max_user_watches
sysctl to a higher value. This can usually be done either temporarily::
echo 524288 > /proc/sys/fs/inotify/max_user_watches
or permanently by adjusting ``/etc/sysctl.conf``.
I Want To Move My Local Sync Folder
-----------------------------------

View File

@ -202,9 +202,8 @@ Application::Application(int &argc, char **argv)
_theme->setSystrayUseMonoIcons(cfg.monoIcons());
connect(_theme, &Theme::systrayUseMonoIconsChanged, this, &Application::slotUseMonoIconsChanged);
FolderMan::instance()->setupFolders();
_proxy.setupQtProxyFromConfig(); // folders have to be defined first, than we set up the Qt proxy.
// Setting up the gui class will allow tray notifications for the
// setup that follows, like folder setup
_gui = new ownCloudGui(this);
if (_showLogWindow) {
_gui->slotToggleLogBrowser(); // _showLogWindow is set in parseOptions.
@ -213,6 +212,9 @@ Application::Application(int &argc, char **argv)
_gui->setupCloudProviders();
#endif
FolderMan::instance()->setupFolders();
_proxy.setupQtProxyFromConfig(); // folders have to be defined first, than we set up the Qt proxy.
// Enable word wrapping of QInputDialog (#4197)
setStyleSheet("QInputDialog QLabel { qproperty-wordWrap:1; }");

View File

@ -1015,6 +1015,20 @@ void Folder::warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QS
Logger::instance()->postOptionalGuiLog(Theme::instance()->appNameGUI(), message);
}
void Folder::slotWatcherUnreliable(const QString &message)
{
qCWarning(lcFolder) << "Folder watcher for" << path() << "became unreliable:" << message;
auto fullMessage =
tr("Changes in synchronized folders could not be tracked reliably.\n"
"\n"
"This means that the synchronization client might not upload local changes "
"immediately and will instead only scan for local changes and upload them "
"occasionally (every two hours by default).\n"
"\n"
"%1").arg(message);
Logger::instance()->postGuiLog(Theme::instance()->appNameGUI(), fullMessage);
}
void Folder::scheduleThisFolderSoon()
{
if (!_scheduleSelfTimer.isActive()) {
@ -1034,11 +1048,14 @@ void Folder::registerFolderWatcher()
if (!QDir(path()).exists())
return;
_folderWatcher.reset(new FolderWatcher(path(), this));
_folderWatcher.reset(new FolderWatcher(this));
connect(_folderWatcher.data(), &FolderWatcher::pathChanged,
this, &Folder::slotWatchedPathChanged);
connect(_folderWatcher.data(), &FolderWatcher::lostChanges,
this, &Folder::slotNextSyncFullLocalDiscovery);
connect(_folderWatcher.data(), &FolderWatcher::becameUnreliable,
this, &Folder::slotWatcherUnreliable);
_folderWatcher->init(path());
}
void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, bool *cancel)

View File

@ -325,6 +325,9 @@ private slots:
/** Warn users if they create a file or folder that is selective-sync excluded */
void warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QStringRef &path);
/** Warn users about an unreliable folder watcher */
void slotWatcherUnreliable(const QString &message);
private:
bool reloadExcludes();

View File

@ -38,19 +38,22 @@ namespace OCC {
Q_LOGGING_CATEGORY(lcFolderWatcher, "nextcloud.gui.folderwatcher", QtInfoMsg)
FolderWatcher::FolderWatcher(const QString &root, Folder *folder)
FolderWatcher::FolderWatcher(Folder *folder)
: QObject(folder)
, _folder(folder)
{
_d.reset(new FolderWatcherPrivate(this, root));
_timer.start();
}
FolderWatcher::~FolderWatcher()
{
}
void FolderWatcher::init(const QString &root)
{
_d.reset(new FolderWatcherPrivate(this, root));
_timer.start();
}
bool FolderWatcher::pathIsIgnored(const QString &path)
{
if (path.isEmpty())

View File

@ -55,11 +55,14 @@ class FolderWatcher : public QObject
{
Q_OBJECT
public:
// Construct, connect signals, call init()
explicit FolderWatcher(Folder *folder = 0L);
virtual ~FolderWatcher();
/**
* @param root Path of the root of the folder
*/
FolderWatcher(const QString &root, Folder *folder = 0L);
virtual ~FolderWatcher();
void init(const QString &root);
/**
* Not all backends are recursive by default.
@ -96,6 +99,12 @@ signals:
*/
void lostChanges();
/**
* Signals when the watcher became unreliable. The string is a translated
* message that can be shown to users.
*/
void becameUnreliable(const QString &message);
protected slots:
// called from the implementations to indicate a change in path
void changeDetected(const QString &path);

View File

@ -81,8 +81,11 @@ void FolderWatcherPrivate::inotifyRegisterPath(const QString &path)
} else {
// If we're running out of memory or inotify watches, become
// unreliable.
if (errno == ENOMEM || errno == ENOSPC) {
if (_parent->_isReliable && (errno == ENOMEM || errno == ENOSPC)) {
_parent->_isReliable = false;
emit _parent->becameUnreliable(
tr("This problem usually happens when the inotify watches are exhausted. "
"Check the FAQ for details."));
}
}
}

View File

@ -113,7 +113,8 @@ public:
Utility::writeRandomFile( _rootPath+"/a2/renamefile");
Utility::writeRandomFile( _rootPath+"/a1/movefile");
_watcher.reset(new FolderWatcher(_rootPath));
_watcher.reset(new FolderWatcher);
_watcher->init(_rootPath);
_pathChangedSpy.reset(new QSignalSpy(_watcher.data(), SIGNAL(pathChanged(QString))));
}