-
Notifications
You must be signed in to change notification settings - Fork 669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Speed up local discovery by not doing it #6087
Conversation
This seemed to work in simple tests but clearly needs a lot more testing. I also broke the unittests - they still need fixing. |
2a8ee00
to
863a00d
Compare
The existing unittests work again now. Next steps: Add new unittests that verify it works. |
863a00d
to
428e637
Compare
src/common/syncjournaldb.cpp
Outdated
@@ -550,7 +550,7 @@ bool SyncJournalDb::checkConnect() | |||
_getFilesBelowPathQuery.reset(new SqlQuery(_db)); | |||
if (_getFilesBelowPathQuery->prepare( | |||
GET_FILE_RECORD_QUERY | |||
" WHERE path > (?1||'/') AND path < (?1||'0') ORDER BY path||'/' ASC")) { | |||
" WHERE ?1 == '' OR (path > (?1||'/') AND path < (?1||'0')) ORDER BY path||'/' ASC")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering: does the query uses the index?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, adding that term does indeed break index use (checked with EXPLAIN QUERY PLAN
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that our database doesn't keep paths with a initial /, so path > (''||'/') AND path < (''||'0'')
matches nothing. Something like path > '' AND path < 'last-unicode-character'
would work, but I think we just need a different query for clarity.
src/csync/csync_update.cpp
Outdated
auto rowCallback = [ctx, &count, &skipbase, &files](const OCC::SyncJournalFileRecord &rec) { | ||
if (ctx->current == REMOTE_REPLICA) { | ||
/* When selective sync is used, the database may have subtrees with a parent | ||
* whose etag (md5) is _invalid_. These are ignored and shall not appear in the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(unrelated: we could remove the reference to md5 here. It was there before because the _etag was called _md5, but it has gotten renamed)
src/gui/folder.cpp
Outdated
return; | ||
} | ||
|
||
auto relativePath = path.mid(this->path().size()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/mid/midRef/
@@ -783,6 +824,21 @@ void Folder::slotSyncFinished(bool success) | |||
journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList, QStringList()); | |||
} | |||
|
|||
// bug: This function uses many different criteria for "sync was successful" - investigate! | |||
if ((_syncResult.status() == SyncResult::Success | |||
|| _syncResult.status() == SyncResult::Problem) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it is problem even for soft errors?
src/gui/folder.cpp
Outdated
// on 100% successful sync. ('Problem' syncs could have the touched | ||
// file trigger a soft-error-and-retry scenario and wiping this list | ||
// would mean the file isn't retried) | ||
_locallyModifiedDirs.clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if there were change hapenning during the sync!
Maybe we should clear it as we start the sync, and if the sync fails for any problem, we add them back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ogoffart Yes, great catch! That means we really need to remove files from this list as the individual jobs report success even in the initial version. At least that also solves the problem with 'Problem' syncs due to soft errors at the same time.
src/gui/folder.h
Outdated
* | ||
* Created by registerFolderWatcher(), triggers slotWatchedPathChanged() | ||
*/ | ||
FolderWatcher *_folderWatcher = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ohoh! you are putting the FolderWatcher back in the Folder itself :-) cc/ @dragotin
src/gui/folder.h
Outdated
* | ||
* Created by registerFolderWatcher(), triggers slotWatchedPathChanged() | ||
*/ | ||
FolderWatcher *_folderWatcher = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using QScopedPointer. Otherwise, nullptr instead of 0.
428e637
to
bd4f4c9
Compare
This makes it unnecessary for FolderMan to manage the list and removes the need for some forwarders. This is done in preparation for follow-up commits that want to add diagnostics to FolderWatcher that shall be available from within Folder.
Add state and signal to catch the following two known problems: * Linux: inotify user watch pool is exhausted. Folder watcher becomes unreliable. * Windows: buffer is too small, some notifications are lost but watching stays reliable.
bd4f4c9
to
6563e40
Compare
@ogoffart Significantly updated! The local-discovery-path list now has pretty elaborate sync-error handling. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
7d6487e approved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, but please see the comments.
_getAllFilesQuery.reset(new SqlQuery(_db)); | ||
if (_getAllFilesQuery->prepare( | ||
GET_FILE_RECORD_QUERY | ||
" ORDER BY path||'/' ASC")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we concatenate '/' to the path while ordering?
src/csync/csync_update.cpp
Outdated
// and we want to check whether we should read from the db. Assume "d/foo a" is | ||
// in locally_touched_dirs. Then this check will say no, don't read from the db! | ||
// (because "d/foo" < "d/foo a" < "d/foo/bar") | ||
auto it = ctx->locally_touched_dirs.lower_bound(QByteArray(local_uri)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The QByteArray allocation could be avoided in C++14, there is an overload of lower_bound that can work for types for which the comparator is transparent.
But that would imply a change to the makefile to enable C++14.
Maybe it is not needed as it should not happen so often anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add a note about this for C++14, but won't enable it in this PR.
src/gui/folder.cpp
Outdated
|
||
if (lcFolder().isDebugEnabled()) { | ||
QByteArrayList paths; | ||
for (auto &path : _localDiscoveryPaths) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(minor: could be done with std::copy)
src/gui/folder.cpp
Outdated
for (auto &path : _localDiscoveryPaths) { | ||
paths.append(path); | ||
} | ||
qCDebug(lcFolder) << "local discovery paths: " << qUtf8Printable(paths.join(", ")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you not just qCDebug << paths? why do we need to convert it to a QByteArray first?
Also , qUtf8Priontable is for QString. When you have a QByteArray you can just use constData().
src/libsync/configfile.h
Outdated
@@ -72,6 +72,9 @@ class OWNCLOUDSYNC_EXPORT ConfigFile | |||
/* Force sync interval, in milliseconds */ | |||
quint64 forceSyncInterval(const QString &connection = QString()) const; | |||
|
|||
/** Interval within which full local discovery is required, -1 to disable */ | |||
qint64 fullLocalDiscoveryInterval() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the unit?
I know this is not yet your coding style. But in the future it would be nice to use things like std::chrono::milliseconds as a return type to make it explicit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed!
6563e40
to
2c69d9b
Compare
@ogoffart Resolved remaining issues |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
src/csync/csync_update.cpp
Outdated
// and we want to check whether we should read from the db. Assume "d/foo a" is | ||
// in locally_touched_dirs. Then this check will say no, don't read from the db! | ||
// (because "d/foo" < "d/foo a" < "d/foo/bar") | ||
// C++17: Could skip the conversion to QByteArray here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
c++14
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes...
We mostly trust the file watchers meaning that we don't re-scan the local tree if we have done that recently and no file watcher events have arrived. If the file watchers invalidate a subtree, we rescan only that subtree. Since we're not entirely sure the file watchers are reliable, we still do full local discoveries regularly (1h by default). There is a config file setting as well as an environment variable to control the interval.
2c69d9b
to
2b3a31a
Compare
Use the data from the db instead and only check the file system when a file watcher event suggests it's necessary.
Since we're not confident that file watcher events are good enough, we still do a full local discovery every hour for now. This also doesn't get rid of the initial sync after client startup. But incremental syncs should be sped up significantly.
See #2297