Skip to content

Commit 9516fc9

Browse files
erikjvmodSpike
andauthored
[DC-193] Make CfAPi locking more granular and always groups siblings together (#12386)
* Make CfApi locks more granular Also lock when disconnecting/unregistering. * Always group in the sidebar when that is available And remove all traces of `groupInSidebar`. * Only unregister syncroot when it was actually registered before. --------- Co-authored-by: modSpike <lisa.reese@kiteworks.com>
1 parent 92e15f2 commit 9516fc9

File tree

8 files changed

+36
-62
lines changed

8 files changed

+36
-62
lines changed

src/common/vfs.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,9 @@ const VfsPluginManager &VfsPluginManager::instance()
276276
return *_instance;
277277
}
278278

279-
VfsSetupParams::VfsSetupParams(Account *account, const QUrl &baseUrl, bool groupInSidebar, SyncEngine *syncEngine)
279+
VfsSetupParams::VfsSetupParams(Account *account, const QUrl &baseUrl, SyncEngine *syncEngine)
280280
: account(account)
281281
, _baseUrl(baseUrl)
282-
, _groupInSidebar(groupInSidebar)
283282
, _syncEngine(syncEngine)
284283
{
285284
}

src/common/vfs.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class SyncEngine;
4444
/** Collection of parameters for initializing a Vfs instance. */
4545
struct OCSYNC_EXPORT VfsSetupParams
4646
{
47-
explicit VfsSetupParams(Account *account, const QUrl &baseUrl, bool groupInSidebar, SyncEngine *syncEngine);
47+
explicit VfsSetupParams(Account *account, const QUrl &baseUrl, SyncEngine *syncEngine);
4848
/** The full path to the folder on the local filesystem
4949
*
5050
* Always ends with /.
@@ -81,16 +81,10 @@ struct OCSYNC_EXPORT VfsSetupParams
8181
return _baseUrl;
8282
}
8383

84-
bool groupInSidebar() const
85-
{
86-
return _groupInSidebar;
87-
}
88-
8984
SyncEngine *syncEngine() const;
9085

9186
private:
9287
QUrl _baseUrl;
93-
bool _groupInSidebar = false;
9488
SyncEngine *_syncEngine;
9589
};
9690

src/gui/folder.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ void Folder::startVfs()
520520
return;
521521
}
522522

523-
VfsSetupParams vfsParams(_accountState->account(), webDavUrl(), groupInSidebar(), _engine.get());
523+
VfsSetupParams vfsParams(_accountState->account(), webDavUrl(), _engine.get());
524524
vfsParams.filesystemPath = path();
525525
vfsParams.remotePath = remotePathTrailingSlash();
526526
vfsParams.journal = &_journal;
@@ -1246,15 +1246,4 @@ QString FolderDefinition::displayName() const
12461246
return _displayName;
12471247
}
12481248

1249-
bool Folder::groupInSidebar() const
1250-
{
1251-
if (_accountState && _accountState->account() && _accountState->account()->hasDefaultSyncRoot()) {
1252-
// QFileInfo is horrible and "/foo/" is treated different to "/foo"
1253-
const QString parentDir = QFileInfo(Utility::stripTrailingSlash(path())).dir().path();
1254-
// If parentDir == home, we would add the home dir to the sidebar.
1255-
return QFileInfo(parentDir) != QFileInfo(QDir::homePath()) && FileSystem::isChildPathOf(parentDir, _accountState->account()->defaultSyncRoot());
1256-
}
1257-
return false;
1258-
}
1259-
12601249
} // namespace OCC

src/gui/folder.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -344,14 +344,6 @@ class OWNCLOUDGUI_EXPORT Folder : public QObject
344344
/** Whether this folder should show selective sync ui */
345345
bool supportsSelectiveSync() const;
346346

347-
/**
348-
* Whether to register the parent folder of our sync root in the explorer
349-
* The default behaviour is to register alls spaces in a common dir in the home folder
350-
* in that case we only display that common dir in the Windows sidebar.
351-
* With the legacy behaviour we only have one dir which we will register with Windows
352-
*/
353-
bool groupInSidebar() const;
354-
355347
/**
356348
* The folder is deployed by an admin
357349
* We will hide the remove option and the disable/enable vfs option.

src/gui/folderman.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,8 +1150,7 @@ Folder *FolderMan::addFolderFromScratch(AccountState *accountState, FolderDefini
11501150
auto newFolder = addFolder(accountState, folderDefinition);
11511151

11521152
if (newFolder) {
1153-
// With spaces we only handle the main folder
1154-
if (!newFolder->groupInSidebar()) {
1153+
if (newFolder->vfs().mode() != Vfs::WindowsCfApi) {
11551154
Utility::setupFavLink(folderDefinition.localPath());
11561155
}
11571156
qCDebug(lcFolderMan) << "Local sync folder" << folderDefinition.localPath() << "successfully created!";

src/plugins/vfs/win/vfs_win.cpp

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,8 @@ QString VfsWinPrivate::syncRootPath() const
517517
return QDir::toNativeSeparators(Utility::stripTrailingSlash(q->params().filesystemPath));
518518
}
519519

520+
QMutex VfsWinPrivate::registrationMutex;
521+
520522
// Register as a sync provider with cfapi as well as with the explorer integration
521523
void VfsWinPrivate::registerFolder(const VfsSetupParams &params)
522524
{
@@ -607,7 +609,7 @@ void VfsWinPrivate::registerFolder(const VfsSetupParams &params)
607609
// A Uri to a cloud storage recycle bin.
608610
//providerInfo.RecycleBinUri(L"recycle bin");
609611

610-
providerInfo.ShowSiblingsAsGroup(params.groupInSidebar());
612+
providerInfo.ShowSiblingsAsGroup(true);
611613

612614
// Prepage the key from the shell property store we'll use to determine
613615
// availability.
@@ -642,14 +644,6 @@ void VfsWinPrivate::registerFolder(const VfsSetupParams &params)
642644
return;
643645
}
644646

645-
// Code below this point cannot run in parallel: the calls below will first search for existing sync root
646-
// information, and as a second step it will register the new provider for the folder. If multiple
647-
// sync connections are being created in short order (e.g. when setting up a new account), it is possible
648-
// that a second call to `registerFolder` will start running this registration. This can result in
649-
// multiple side-bar entries in the windows explorer.
650-
static QMutex registrationMutex;
651-
QMutexLocker registrationLock(&registrationMutex);
652-
653647
try {
654648
auto previousInfo = StorageProviderSyncRootManager::GetSyncRootInformationForFolder(f);
655649
const QString oldId = hstringToQString(previousInfo.Id());
@@ -699,6 +693,7 @@ void VfsWinPrivate::registerFolder(const VfsSetupParams &params)
699693
}
700694

701695
try {
696+
QMutexLocker registrationLock(&registrationMutex);
702697
StorageProviderSyncRootManager::Register(providerInfo);
703698
} catch (winrt::hresult_error const& ex) {
704699
qCWarning(lcVfs) << "Error registering StorageProvider for" << params.filesystemPath << QString::number(ex.code()) << hstringToQString(ex.message());
@@ -727,13 +722,15 @@ void VfsWinPrivate::registerFolder(const VfsSetupParams &params)
727722
};
728723
// clang-format on
729724

730-
HRESULT ok = CfConnectSyncRoot(
731-
syncRootW.c_str(),
732-
callbacks,
733-
this, // use VfsWinPrivate as callback context
734-
CF_CONNECT_FLAG_BLOCK_SELF_IMPLICIT_HYDRATION // don't let antivirus implicitly hydrate (or something, a bit unclear)
735-
| CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH, // request that callbacks get the full path
736-
&_connectionKey);
725+
HRESULT ok;
726+
{
727+
QMutexLocker registrationLock(&registrationMutex);
728+
ok = CfConnectSyncRoot(syncRootW.c_str(), callbacks,
729+
this, // use VfsWinPrivate as callback context
730+
CF_CONNECT_FLAG_BLOCK_SELF_IMPLICIT_HYDRATION // don't let antivirus implicitly hydrate (or something, a bit unclear)
731+
| CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH, // request that callbacks get the full path
732+
&_connectionKey);
733+
}
737734
if (FAILED(ok)) {
738735
Q_EMIT q->error(tr("Unable to connect sync root: %1 error: %2").arg(syncRoot, Utility::formatWinError(ok)));
739736
return;
@@ -809,20 +806,18 @@ void VfsWin::stop()
809806
wait.processEvents(QEventLoop::AllEvents, 100);
810807
}
811808

809+
QMutexLocker registrationLock(&d->registrationMutex);
812810
CfDisconnectSyncRoot(d->_connectionKey);
813811
}
814812

815813
void VfsWin::unregisterFolder()
816814
{
817815
Q_D(VfsWin);
818-
using SyncRootManager = winrt::Windows::Storage::Provider::StorageProviderSyncRootManager;
819-
try {
820-
SyncRootManager::Unregister(d->_registrationId);
821-
} catch (winrt::hresult_error const &ex) {
822-
qCWarning(lcVfs) << "Could not Unregister() sync root:" << hstringToQString(ex.message());
823-
}
824816

825-
// Remove the folder from the search index
817+
if (d->_registrationState == VfsWinPrivate::Unregistered)
818+
return;
819+
820+
// First step: remove the folder from the search index
826821
const std::wstring url(convertFullNativePathToFullyDecodedUrlW(d->syncRootPath()));
827822
winrt::com_ptr<ISearchCrawlScopeManager> searchCrawlScopeManager = getSearchCrawlScopeManager();
828823

@@ -835,6 +830,15 @@ void VfsWin::unregisterFolder()
835830
} else {
836831
qCWarning(lcVfs) << "Unable to get the SearchCrawlScopeManager to remove the path" << url;
837832
}
833+
834+
// Final step: unregister the path. We're now completely done with it.
835+
using SyncRootManager = winrt::Windows::Storage::Provider::StorageProviderSyncRootManager;
836+
try {
837+
QMutexLocker registrationLock(&d->registrationMutex);
838+
SyncRootManager::Unregister(d->_registrationId);
839+
} catch (winrt::hresult_error const &ex) {
840+
qCWarning(lcVfs) << "Could not Unregister() sync root:" << hstringToQString(ex.message());
841+
}
838842
}
839843

840844
OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> VfsWin::updateMetadata(const SyncFileItem &item, const QString &filePath, const QString &replacesFile)

src/plugins/vfs/win/vfs_win_p.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ class VfsWinPrivate : public QObject
8989
VfsWin *q;
9090
QAtomicInt _registrationState;
9191
CF_CONNECTION_KEY _connectionKey;
92+
static QMutex registrationMutex;
9293

9394
// System.StorageProviderState key
9495
std::unique_ptr<PROPERTYKEY> storageProviderStateKey;

test/testutils/syncenginetestutils.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -914,32 +914,28 @@ FakeFolder::FakeFolder(const FileInfo &fileTemplate, OCC::Vfs::Mode vfsMode, boo
914914
OC_ENFORCE(syncOnce())
915915
}
916916

917-
FakeFolder::~FakeFolder()
918-
{
919-
auto opts = _syncEngine->syncOptions();
920-
opts._vfs->stop();
921-
opts._vfs->unregisterFolder(); // Important! This removes the side-bar entry in Windows Explorer!
922-
}
917+
FakeFolder::~FakeFolder() { }
923918

924919
void FakeFolder::switchToVfs(QSharedPointer<OCC::Vfs> vfs)
925920
{
926921
auto opts = _syncEngine->syncOptions();
927922

928923
opts._vfs->stop();
924+
opts._vfs->unregisterFolder();
929925
QObject::disconnect(_syncEngine.get(), nullptr, opts._vfs.data(), nullptr);
930926

931927
opts._vfs = vfs;
932928
_syncEngine->setSyncOptions(opts);
933929

934-
OCC::VfsSetupParams vfsParams(account(), account()->davUrl(), false, &syncEngine());
930+
OCC::VfsSetupParams vfsParams(account(), account()->davUrl(), &syncEngine());
935931
vfsParams.filesystemPath = localPath();
936932
vfsParams.remotePath = QLatin1Char('/');
937933
vfsParams.journal = _journalDb.get();
938934
vfsParams.providerName = QStringLiteral("OC-TEST");
939935
vfsParams.providerDisplayName = QStringLiteral("OC-TEST");
940936
vfsParams.providerVersion = QVersionNumber(0, 1, 0);
941937
vfsParams.multipleAccountsRegistered = false;
942-
QObject::connect(_syncEngine.get(), &QObject::destroyed, vfs.data(), [vfs]() {
938+
QObject::connect(_syncEngine.get(), &QObject::destroyed, this, [vfs]() {
943939
vfs->stop();
944940
vfs->unregisterFolder();
945941
});

0 commit comments

Comments
 (0)