Vfs: Switch on/off only when sync isn't running #6936
authorChristian Kamm <mail@ckamm.de>
Mon, 14 Jan 2019 14:48:08 +0000 (15:48 +0100)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:58:34 +0000 (10:58 +0100)
Avoids some situations that might cause data loss.

src/gui/accountsettings.cpp
src/gui/wizard/owncloudwizard.cpp

index cfe3a1c8efa21c0509875ba4dceed015c8eb030d..da939cf8df2ce3995312f38d1b923d91829af1ae 100644 (file)
@@ -457,7 +457,8 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
 
     if (Theme::instance()->showVirtualFilesOption()
         && !folder->supportsVirtualFiles()
-        && bestAvailableVfsMode() != Vfs::Off) {
+        && bestAvailableVfsMode() != Vfs::Off
+        && !folder->isVfsOnOffSwitchPending()) {
         ac = menu->addAction(tr("Enable virtual file support (experimental)..."));
         connect(ac, &QAction::triggered, this, &AccountSettings::slotEnableVfsCurrentFolder);
     }
@@ -648,27 +649,43 @@ void AccountSettings::slotEnableVfsCurrentFolder()
         if (!enable || !folder)
             return;
 
-        qCInfo(lcAccountSettings) << "Enabling vfs support for folder" << folder->path();
+        // It is unsafe to switch on vfs while a sync is running - wait if necessary.
+        auto connection = std::make_shared<QMetaObject::Connection>();
+        auto switchVfsOn = [folder, connection, this]() {
+            if (*connection)
+                QObject::disconnect(*connection);
 
-        // Wipe selective sync blacklist
-        bool ok = false;
-        auto oldBlacklist = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
-        folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, {});
-        for (const auto &entry : oldBlacklist) {
-            folder->journalDb()->avoidReadFromDbOnNextSync(entry);
-        }
+            qCInfo(lcAccountSettings) << "Enabling vfs support for folder" << folder->path();
+
+            // Wipe selective sync blacklist
+            bool ok = false;
+            auto oldBlacklist = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
+            folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, {});
+            for (const auto &entry : oldBlacklist) {
+                folder->journalDb()->avoidReadFromDbOnNextSync(entry);
+            }
+
+            // Change the folder vfs mode and load the plugin
+            folder->setSupportsVirtualFiles(true);
+            folder->setVfsOnOffSwitchPending(false);
 
-        // Change the folder vfs mode and load the plugin
-        folder->setSupportsVirtualFiles(true);
+            // Wipe pin states to be sure
+            folder->journalDb()->wipePinStateForPathAndBelow("");
+            folder->journalDb()->setPinStateForPath("", PinState::OnlineOnly);
 
-        // Wipe pin states to be sure
-        folder->journalDb()->wipePinStateForPathAndBelow("");
-        folder->journalDb()->setPinStateForPath("", PinState::OnlineOnly);
+            FolderMan::instance()->scheduleFolder(folder);
 
-        FolderMan::instance()->scheduleFolder(folder);
+            _ui->_folderList->doItemsLayout();
+        };
 
-        // Update the ui: no selective sync, vfs indicator; size changed
-        _ui->_folderList->doItemsLayout();
+        if (folder->isSyncRunning()) {
+            *connection = connect(folder, &Folder::syncFinished, this, switchVfsOn);
+            folder->setVfsOnOffSwitchPending(true);
+            folder->slotTerminateSync();
+            _ui->_folderList->doItemsLayout();
+        } else {
+            switchVfsOn();
+        }
     });
 }
 
@@ -687,7 +704,9 @@ void AccountSettings::slotDisableVfsCurrentFolder()
            "are currently marked as 'available online only' will be downloaded."
            "\n\n"
            "The only advantage of disabling virtual file support is that the selective sync feature "
-           "will become available again."));
+           "will become available again."
+           "\n\n"
+           "This action will abort any currently running synchronization."));
     msgBox->addButton(tr("Disable support"), QMessageBox::AcceptRole);
     msgBox->addButton(tr("Cancel"), QMessageBox::RejectRole);
     connect(msgBox, &QMessageBox::finished, msgBox, [this, msgBox, folder](int result) {
@@ -695,20 +714,36 @@ void AccountSettings::slotDisableVfsCurrentFolder()
         if (result != QMessageBox::AcceptRole || !folder)
             return;
 
-        qCInfo(lcAccountSettings) << "Disabling vfs support for folder" << folder->path();
+        // It is unsafe to switch off vfs while a sync is running - wait if necessary.
+        auto connection = std::make_shared<QMetaObject::Connection>();
+        auto switchVfsOff = [folder, connection, this]() {
+            if (*connection)
+                QObject::disconnect(*connection);
+
+            qCInfo(lcAccountSettings) << "Disabling vfs support for folder" << folder->path();
 
-        // Also wipes virtual files, schedules remote discovery
-        folder->setSupportsVirtualFiles(false);
+            // Also wipes virtual files, schedules remote discovery
+            folder->setSupportsVirtualFiles(false);
+            folder->setVfsOnOffSwitchPending(false);
 
-        // Wipe pin states and selective sync db
-        folder->journalDb()->wipePinStateForPathAndBelow("");
-        folder->journalDb()->setPinStateForPath("", PinState::AlwaysLocal);
-        folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, {});
+            // Wipe pin states and selective sync db
+            folder->journalDb()->wipePinStateForPathAndBelow("");
+            folder->journalDb()->setPinStateForPath("", PinState::AlwaysLocal);
+            folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, {});
 
-        FolderMan::instance()->scheduleFolder(folder);
+            FolderMan::instance()->scheduleFolder(folder);
 
-        // Update the ui: no selective sync, vfs indicator; size changed
-        _ui->_folderList->doItemsLayout();
+            _ui->_folderList->doItemsLayout();
+        };
+
+        if (folder->isSyncRunning()) {
+            *connection = connect(folder, &Folder::syncFinished, this, switchVfsOff);
+            folder->setVfsOnOffSwitchPending(true);
+            folder->slotTerminateSync();
+            _ui->_folderList->doItemsLayout();
+        } else {
+            switchVfsOff();
+        }
     });
     msgBox->open();
 }
index 7079f2fc1629e3952f60b4416461d3fe17712565..b9c33957d2628005760637c8b396ad286acfba94 100644 (file)
@@ -341,6 +341,8 @@ void OwncloudWizard::askExperimentalVirtualFilesFeature(const std::function<void
                "When a file is opened its contents will be downloaded automatically. "
                "Alternatively files can be downloaded manually by using their context menu."
                "\n\n"
+               "Switching to this mode will abort any currently running synchronization."
+               "\n\n"
                "This is a new, experimental mode. If you decide to use it, please report any "
                "issues that come up."));
     } else {
@@ -352,6 +354,8 @@ void OwncloudWizard::askExperimentalVirtualFilesFeature(const std::function<void
                "Instead, a tiny \"%1\" file will be created for each file that exists on the server. "
                "The contents can be downloaded by running these files or by using their context menu."
                "\n\n"
+               "Switching to this mode will abort any currently running synchronization."
+               "\n\n"
                "This is a new, experimental mode. If you decide to use it, please report any "
                "issues that come up.")
                 .arg(APPLICATION_DOTVIRTUALFILE_SUFFIX));