Vfs: Make files that end up in db placeholders
authorChristian Kamm <mail@ckamm.de>
Mon, 21 Jan 2019 10:22:40 +0000 (11:22 +0100)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:58:37 +0000 (10:58 +0100)
Since 'placeholder' just means that it's an item of the special type
that the vfs plugin can deal with - no matter whether hydrated or
dehydrated - all done items should become placeholders. Even
directories.

Now every file that passes through updateMetadata() will be converted to
a placeholder if necessary.

src/common/vfs.h
src/libsync/owncloudpropagator.cpp
src/libsync/owncloudpropagator.h
src/libsync/propagatedownload.cpp
src/libsync/syncengine.cpp
src/libsync/vfs/suffix/vfs_suffix.cpp
src/libsync/vfs/suffix/vfs_suffix.h

index 727c062731adc1b09ceaafb9850234af8d36f095..a358619cbd329b1514020bc2a2b1eb2fbc162fcb 100644 (file)
@@ -31,7 +31,6 @@ typedef QSharedPointer<Account> AccountPtr;
 class SyncJournalDb;
 class VfsPrivate;
 class SyncFileItem;
-typedef QSharedPointer<SyncFileItem> SyncFileItemPtr;
 
 /** Collection of parameters for initializing a Vfs instance. */
 struct OCSYNC_EXPORT VfsSetupParams
@@ -129,15 +128,18 @@ public:
     virtual bool updateMetadata(const QString &filePath, time_t modtime, quint64 size, const QByteArray &fileId, QString *error) = 0;
 
     /// Create a new dehydrated placeholder. Called from PropagateDownload.
-    virtual void createPlaceholder(const QString &syncFolder, const SyncFileItemPtr &item) = 0;
+    virtual void createPlaceholder(const QString &syncFolder, const SyncFileItem &item) = 0;
 
     /** Convert a new file to a hydrated placeholder.
      *
      * Some VFS integrations expect that every file, including those that have all
      * the remote data, are "placeholders". This function is called by PropagateDownload
      * to convert newly downloaded, fully hydrated files into placeholders.
+     *
+     * Implementations must make sure that calling this function on a file that already
+     * is a placeholder is acceptable.
      */
-    virtual void convertToPlaceholder(const QString &filename, const SyncFileItemPtr &item) = 0;
+    virtual void convertToPlaceholder(const QString &filename, const SyncFileItem &item) = 0;
 
     /// Determine whether the file at the given absolute path is a dehydrated placeholder.
     virtual bool isDehydratedPlaceholder(const QString &filePath) = 0;
@@ -180,8 +182,8 @@ public:
     bool isHydrating() const override { return false; }
 
     bool updateMetadata(const QString &, time_t, quint64, const QByteArray &, QString *) override { return true; }
-    void createPlaceholder(const QString &, const SyncFileItemPtr &) override {}
-    void convertToPlaceholder(const QString &, const SyncFileItemPtr &) override {}
+    void createPlaceholder(const QString &, const SyncFileItem &) override {}
+    void convertToPlaceholder(const QString &, const SyncFileItem &) override {}
 
     bool isDehydratedPlaceholder(const QString &) override { return false; }
     bool statTypeVirtualFile(csync_file_stat_t *, void *) override { return false; }
index b6813c4d85bf637c1541fe3d665e8b894150bc24..673fa173798bff97e6b135679f2f466782de9232 100644 (file)
@@ -724,11 +724,17 @@ QString OwncloudPropagator::adjustRenamedPath(const QString &original) const
     return OCC::adjustRenamedPath(_renamedDirectories, original);
 }
 
-bool OwncloudPropagator::updateMetadata(const SyncFileItem &item)
+bool OwncloudPropagator::updateMetadata(const SyncFileItem &item, const QString &localFolderPath, SyncJournalDb &journal, Vfs &vfs)
 {
-    QString fsPath = getFilePath(item.destination());
+    QString fsPath = localFolderPath + item.destination();
+    vfs.convertToPlaceholder(fsPath, item);
     auto record = item.toSyncJournalFileRecordWithInode(fsPath);
-    return _journal->setFileRecord(record);
+    return journal.setFileRecord(record);
+}
+
+bool OwncloudPropagator::updateMetadata(const SyncFileItem &item)
+{
+    return updateMetadata(item, _localDir, *_journal, *syncOptions()._vfs);
 }
 
 // ================================================================================
@@ -1019,9 +1025,7 @@ void CleanupPollsJob::slotPollFinished()
     } else if (job->_item->_status != SyncFileItem::Success) {
         qCWarning(lcCleanupPolls) << "There was an error with file " << job->_item->_file << job->_item->_errorString;
     } else {
-        // want to do Propagator::updateMetadata()
-        QString filesystemPath = _localPath + job->_item->_file;
-        if (!_journal->setFileRecord(job->_item->toSyncJournalFileRecordWithInode(filesystemPath))) {
+        if (!OwncloudPropagator::updateMetadata(*job->_item, _localPath, *_journal, *_vfs)) {
             qCWarning(lcCleanupPolls) << "database error";
             job->_item->_status = SyncFileItem::FatalError;
             job->_item->_errorString = tr("Error writing metadata to the database");
index a6b64de2daf95265f87a4b96ee2f24489188f8b6..211bed5a40286765b183477eb809d3882703bebe 100644 (file)
@@ -511,8 +511,11 @@ public:
      *
      * Typically after a sync operation succeeded. Updates the inode from
      * the filesystem.
+     *
+     * Will also trigger a Vfs::convertToPlaceholder.
      */
-    bool updateMetadata(const SyncFileItem &item);
+    static bool updateMetadata(const SyncFileItem &item, const QString &localFolderPath, SyncJournalDb &journal, Vfs &vfs);
+    bool updateMetadata(const SyncFileItem &item); // convenience for the above
 
 private slots:
 
@@ -570,15 +573,17 @@ class CleanupPollsJob : public QObject
     AccountPtr _account;
     SyncJournalDb *_journal;
     QString _localPath;
+    QSharedPointer<Vfs> _vfs;
 
 public:
     explicit CleanupPollsJob(const QVector<SyncJournalDb::PollInfo> &pollInfos, AccountPtr account,
-        SyncJournalDb *journal, const QString &localPath, QObject *parent = nullptr)
+        SyncJournalDb *journal, const QString &localPath, const QSharedPointer<Vfs> &vfs, QObject *parent = nullptr)
         : QObject(parent)
         , _pollInfos(pollInfos)
         , _account(account)
         , _journal(journal)
         , _localPath(localPath)
+        , _vfs(vfs)
     {
     }
 
index 97592d465b72976c02ed559a2de1bab8002f8ce2..fe0cceac72c2b61bb281ea145ba8ddd844fa8096 100644 (file)
@@ -440,7 +440,7 @@ void PropagateDownloadFile::startAfterIsEncryptedIsChecked()
         auto fn = propagator()->getFilePath(_item->_file);
         qCDebug(lcPropagateDownload) << "creating virtual file" << fn;
 
-        vfs->createPlaceholder(propagator()->_localDir, _item);
+        vfs->createPlaceholder(propagator()->_localDir, *_item);
         updateMetadata(false);
         return;
     }
@@ -1005,7 +1005,7 @@ void PropagateDownloadFile::downloadFinished()
     }
 
     // Make the file a hydrated placeholder if possible
-    propagator()->syncOptions()._vfs->convertToPlaceholder(fn, _item);
+    propagator()->syncOptions()._vfs->convertToPlaceholder(fn, *_item);
 
     FileSystem::setFileHidden(fn, false);
 
index a10edb7b29b84c9dcfbb7f1f3dd2c3a0c15f936a..fc2c30ce386e1411c537d3b288bd378407db0079 100644 (file)
@@ -411,7 +411,7 @@ void SyncEngine::startSync()
         if (!pollInfos.isEmpty()) {
             qCInfo(lcEngine) << "Finish Poll jobs before starting a sync";
             auto *job = new CleanupPollsJob(pollInfos, _account,
-                _journal, _localPath, this);
+                _journal, _localPath, _syncOptions._vfs, this);
             connect(job, &CleanupPollsJob::finished, this, &SyncEngine::startSync);
             connect(job, &CleanupPollsJob::aborted, this, &SyncEngine::slotCleanPollsJobAborted);
             job->start();
index b99f4f2e5de4e9171a47149ebb585b35fd97c1ff..60d753a1b0b790387a512e174009c4e12edfb4d4 100644 (file)
@@ -67,18 +67,18 @@ bool VfsSuffix::updateMetadata(const QString &filePath, time_t modtime, quint64,
     return true;
 }
 
-void VfsSuffix::createPlaceholder(const QString &syncFolder, const SyncFileItemPtr &item)
+void VfsSuffix::createPlaceholder(const QString &syncFolder, const SyncFileItem &item)
 {
     // The concrete shape of the placeholder is also used in isDehydratedPlaceholder() below
-    QString fn = syncFolder + item->_file;
+    QString fn = syncFolder + item._file;
     QFile file(fn);
     file.open(QFile::ReadWrite | QFile::Truncate);
     file.write(" ");
     file.close();
-    FileSystem::setModTime(fn, item->_modtime);
+    FileSystem::setModTime(fn, item._modtime);
 }
 
-void VfsSuffix::convertToPlaceholder(const QString &, const SyncFileItemPtr &)
+void VfsSuffix::convertToPlaceholder(const QString &, const SyncFileItem &)
 {
     // Nothing necessary
 }
index 6d45fc75cbc7151c6bbdc8787587f47844235bdb..6c60c530abf992a9f32cb6c131d43596f1d2c2aa 100644 (file)
@@ -41,8 +41,8 @@ public:
 
     bool updateMetadata(const QString &filePath, time_t modtime, quint64 size, const QByteArray &fileId, QString *error) override;
 
-    void createPlaceholder(const QString &syncFolder, const SyncFileItemPtr &item) override;
-    void convertToPlaceholder(const QString &filename, const SyncFileItemPtr &item) override;
+    void createPlaceholder(const QString &syncFolder, const SyncFileItem &item) override;
+    void convertToPlaceholder(const QString &filename, const SyncFileItem &item) override;
 
     bool isDehydratedPlaceholder(const QString &filePath) override;
     bool statTypeVirtualFile(csync_file_stat_t *stat, void *stat_data) override;