diff --git a/src/libcommon/utility/sourcelocation.h b/src/libcommon/utility/sourcelocation.h
new file mode 100644
index 000000000..54eef77c2
--- /dev/null
+++ b/src/libcommon/utility/sourcelocation.h
@@ -0,0 +1,81 @@
+/*
+ * Infomaniak kDrive - Desktop
+ * Copyright (C) 2023-2024 Infomaniak Network SA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#if defined(_WIN32)
+// || defined(__APPLE__) still buggy on macOS
+// https://www.reddit.com/r/cpp/comments/1b1pjii/comment/ksg8efc/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
+#define SRC_LOC_AVALAIBALE
+#endif
+
+#ifdef SRC_LOC_AVALAIBALE
+#include
+#endif // SRC_LOC_AVALAIBALE
+
+#include
+#include
+
+namespace KDC {
+
+class SourceLocation {
+ public:
+ constexpr SourceLocation() = default;
+#ifdef SRC_LOC_AVALAIBALE
+ [[nodiscard]] static consteval SourceLocation currentLoc(
+ const std::source_location& loc = std::source_location::current()) {
+ SourceLocation result;
+ result._line = loc.line();
+ result._fileName = loc.file_name();
+ result._functionName = loc.function_name();
+ return result;
+ }
+#else
+#define currentLoc() \
+ currentLocCompatibility(__LINE__, __FILE__, \
+ "") // Cannot be used as a default argument as it will be evaluated at the definition site.
+ [[nodiscard]] static consteval SourceLocation currentLocCompatibility(uint32_t line, const char* file,
+ const char* function) {
+ SourceLocation result;
+ result._line = line;
+ result._fileName = file;
+ result._functionName = function;
+ return result;
+ }
+#endif // SRC_LOC_AVALAIBALE
+
+ [[nodiscard]] uint32_t line() const { return _line; }
+ [[nodiscard]] std::string fileName() const { return std::filesystem::path(_fileName).filename().string(); }
+ [[nodiscard]] std::string functionName() const {
+ std::string str(_functionName);
+ auto firstParenthesis = str.find_first_of('(');
+ str = firstParenthesis != std::string::npos
+ ? str.substr(0, firstParenthesis)
+ : str; // "namespace::class::function(namespace::args)" -> "namespace::class::function"
+ auto lastColon = str.find_last_of(':');
+ return lastColon != std::string::npos ? str.substr(lastColon + 1) : str; // "namespace::class::function" -> "function"
+ }
+
+ private:
+ uint32_t _line = 0;
+ const char* _fileName = "";
+ const char* _functionName = "";
+};
+
+} // namespace KDC
+// namespace KDC
diff --git a/src/libcommon/utility/types.h b/src/libcommon/utility/types.h
index 7f16bf1d9..f54e3880c 100644
--- a/src/libcommon/utility/types.h
+++ b/src/libcommon/utility/types.h
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
#pragma once
#include
@@ -28,6 +27,7 @@
#include
#include
#include
+#include "sourcelocation.h"
namespace KDC {
@@ -230,25 +230,36 @@ enum class ExitCause {
MoveToTrashFailed,
InvalidName,
LiteSyncNotAllowed,
+ NotPlaceHolder,
NetworkTimeout,
SocketsDefuncted, // macOS: sockets defuncted by kernel
NotFound,
QuotaExceeded,
FullListParsingError,
OperationCanceled,
- ShareLinkAlreadyExists
+ ShareLinkAlreadyExists,
+ InvalidArgument
};
std::string toString(ExitCause e);
struct ExitInfo {
ExitInfo() = default;
- constexpr ExitInfo(const ExitCode &code, const ExitCause &cause) : _code(code), _cause(cause) {}
- ExitInfo(const ExitCode &code) : _code(code) {}
+ constexpr ExitInfo(const ExitCode &code, const ExitCause &cause,
+ const SourceLocation srcLoc = SourceLocation::currentLoc()) :
+ _code(code),
+ _cause(cause), _srcLoc(srcLoc) {}
+
+ ExitInfo(const ExitCode &code, const SourceLocation srcLoc = SourceLocation::currentLoc()) :
+ _code(code), _srcLoc(srcLoc) {}
+
const ExitCode &code() const { return _code; }
const ExitCause &cause() const { return _cause; }
operator ExitCode() const { return _code; }
operator ExitCause() const { return _cause; }
- explicit operator std::string() const { return "ExitInfo{" + toString(code()) + ", " + toString(cause()) + "}"; }
+ explicit operator std::string() const {
+ // Example: "ExitInfo{SystemError-NotFound from (file.cpp:42[functionName])}"
+ return "ExitInfo{" + toString(code()) + "-" + toString(cause()) + srcLocStr() + "}";
+ }
constexpr operator bool() const { return _code == ExitCode::Ok; }
constexpr explicit operator int() const { return toInt(_code) * 100 + toInt(_cause); }
constexpr bool operator==(const ExitInfo &other) const { return _code == other._code && _cause == other._cause; }
@@ -256,6 +267,13 @@ struct ExitInfo {
private:
ExitCode _code{ExitCode::Unknown};
ExitCause _cause{ExitCause::Unknown};
+ SourceLocation _srcLoc;
+
+ std::string srcLocStr() const {
+ if (_code == ExitCode::Ok) return "";
+ return " from (" + _srcLoc.fileName() + ":" + std::to_string(_srcLoc.line()) +
+ (!_srcLoc.functionName().empty() ? "[" + _srcLoc.functionName() + "]" : "");
+ }
};
std::string toString(ExitInfo e);
diff --git a/src/libcommonserver/CMakeLists.txt b/src/libcommonserver/CMakeLists.txt
index 2ffa385b4..77fe4a057 100644
--- a/src/libcommonserver/CMakeLists.txt
+++ b/src/libcommonserver/CMakeLists.txt
@@ -11,6 +11,8 @@ if (UNIX AND CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
endif ()
find_package(libzip 1.10.1 REQUIRED)
+set(CMAKE_AUTOMOC TRUE)
+
add_definitions(-DUNICODE)
add_definitions(-D_UNICODE)
@@ -34,6 +36,9 @@ set(libcommonserver_SRCS
# Io
io/filestat.h
io/iohelper.h io/iohelper.cpp
+ # Vfs
+ vfs.h vfs.cpp
+ plugin.h plugin.cpp
)
if(APPLE)
diff --git a/src/libcommonserver/vfs.cpp b/src/libcommonserver/vfs.cpp
index 3027c1d6c..f7bd779d4 100644
--- a/src/libcommonserver/vfs.cpp
+++ b/src/libcommonserver/vfs.cpp
@@ -32,10 +32,51 @@
using namespace KDC;
-Vfs::Vfs(VfsSetupParams &vfsSetupParams, QObject *parent) :
+Vfs::Vfs(const VfsSetupParams &vfsSetupParams, QObject *parent) :
QObject(parent), _vfsSetupParams(vfsSetupParams), _extendedLog(false), _started(false) {}
-Vfs::~Vfs() {}
+void Vfs::starVfsWorkers() {
+ // Start hydration/dehydration workers
+ // !!! Disabled for testing because no QEventLoop !!!
+ if (qApp) {
+ // Start worker threads
+ for (int i = 0; i < nbWorkers; i++) {
+ for (int j = 0; j < s_nb_threads[i]; j++) {
+ auto *workerThread = new QtLoggingThread();
+ _workerInfo[i]._threadList.append(workerThread);
+ auto *worker = new VfsWorker(this, i, j, logger());
+ worker->moveToThread(workerThread);
+ connect(workerThread, &QThread::started, worker, &VfsWorker::start);
+ connect(workerThread, &QThread::finished, worker, &QObject::deleteLater);
+ connect(workerThread, &QThread::finished, workerThread, &QObject::deleteLater);
+ workerThread->start();
+ }
+ }
+ }
+}
+
+Vfs::~Vfs() {
+ // Ask worker threads to stop
+ for (auto &worker: _workerInfo) {
+ worker._mutex.lock();
+ worker._stop = true;
+ worker._mutex.unlock();
+ worker._queueWC.wakeAll();
+ }
+
+ // Force threads to stop if needed
+ for (auto &worker: _workerInfo) {
+ for (QThread *thread: qAsConst(worker._threadList)) {
+ if (thread) {
+ thread->quit();
+ if (!thread->wait(1000)) {
+ thread->terminate();
+ thread->wait();
+ }
+ }
+ }
+ }
+}
QString Vfs::modeToString(KDC::VirtualFileMode virtualFileMode) {
// Note: Strings are used for config and must be stable
@@ -67,13 +108,13 @@ KDC::VirtualFileMode Vfs::modeFromString(const QString &str) {
return {};
}
-bool Vfs::start(bool &installationDone, bool &activationDone, bool &connectionDone) {
+ExitInfo Vfs::start(bool &installationDone, bool &activationDone, bool &connectionDone) {
if (!_started) {
- _started = startImpl(installationDone, activationDone, connectionDone);
- return _started;
+ ExitInfo exitInfo = startImpl(installationDone, activationDone, connectionDone);
+ _started = exitInfo.code() == ExitCode::Ok;
+ return exitInfo;
}
-
- return true;
+ return ExitCode::Ok;
}
void Vfs::stop(bool unregister) {
@@ -83,34 +124,105 @@ void Vfs::stop(bool unregister) {
}
}
-VfsOff::VfsOff(VfsSetupParams &vfsSetupParams, QObject *parent) : Vfs(vfsSetupParams, parent) {}
-
-VfsOff::~VfsOff() {}
+ExitInfo Vfs::handleVfsError(const SyncPath &itemPath, const SourceLocation location) const {
+ if (ExitInfo exitInfo = checkIfPathExists(itemPath, true, location); !exitInfo) {
+ return exitInfo;
+ }
+ return defaultVfsError(location);
+}
-bool VfsOff::forceStatus(const QString &path, bool isSyncing, int /*progress*/, bool /*isHydrated*/) {
- KDC::SyncPath fullPath(_vfsSetupParams._localPath / QStr2Path(path));
+ExitInfo Vfs::checkIfPathExists(const SyncPath &itemPath, bool shouldExist, const SourceLocation location) const {
+ if (itemPath.empty()) {
+ LOGW_WARN(logger(), L"Empty path");
+ assert(false && "Empty path in a VFS call");
+ return {ExitCode::SystemError, ExitCause::NotFound, location};
+ }
bool exists = false;
- KDC::IoError ioError = KDC::IoError::Success;
- if (!KDC::IoHelper::checkIfPathExists(fullPath, exists, ioError)) {
- LOGW_WARN(logger(), L"Error in IoHelper::checkIfPathExists: " << KDC::Utility::formatIoError(fullPath, ioError).c_str());
- return false;
+ IoError ioError = IoError::Unknown;
+ if (!IoHelper::checkIfPathExists(itemPath, exists, ioError)) {
+ LOGW_WARN(logger(), L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(itemPath, ioError));
+ return {ExitCode::SystemError, location};
+ }
+ if (ioError == IoError::AccessDenied) {
+ LOGW_WARN(logger(), L"File access error: " << Utility::formatIoError(itemPath, ioError));
+ return {ExitCode::SystemError, ExitCause::FileAccessError, location};
}
+ if (exists != shouldExist) {
+ if (shouldExist) {
+ LOGW_DEBUG(logger(), L"File doesn't exist: " << Utility::formatSyncPath(itemPath));
+ return {ExitCode::SystemError, ExitCause::NotFound, location};
+ } else {
+ LOGW_DEBUG(logger(), L"File already exists: " << Utility::formatSyncPath(itemPath));
+ return {ExitCode::SystemError, ExitCause::FileAlreadyExist, location};
+ }
+ }
+ return ExitCode::Ok;
+}
+
+VfsWorker::VfsWorker(Vfs *vfs, int type, int num, log4cplus::Logger logger) :
+ _vfs(vfs), _type(type), _num(num), _logger(logger) {}
- if (!exists) {
- LOGW_DEBUG(logger(), L"Item does not exist anymore - path=" << Path2WStr(fullPath).c_str());
- return true;
+void VfsWorker::start() {
+ LOG_DEBUG(logger(), "Worker with type=" << _type << " and num=" << _num << " started");
+
+ WorkerInfo &workerInfo = _vfs->_workerInfo[_type];
+
+ forever {
+ workerInfo._mutex.lock();
+ while (workerInfo._queue.empty() && !workerInfo._stop) {
+ LOG_DEBUG(logger(), "Worker with type=" << _type << " and num=" << _num << " waiting");
+ workerInfo._queueWC.wait(&workerInfo._mutex);
+ }
+
+ if (workerInfo._stop) {
+ workerInfo._mutex.unlock();
+ break;
+ }
+
+ QString path = workerInfo._queue.back();
+ workerInfo._queue.pop_back();
+ workerInfo._mutex.unlock();
+
+ LOG_DEBUG(logger(), "Worker with type=" << _type << " and num=" << _num << " working");
+
+ switch (_type) {
+ case workerHydration:
+ _vfs->hydrate(path);
+ break;
+ case workerDehydration:
+ _vfs->dehydrate(path);
+ break;
+ default:
+ LOG_ERROR(logger(), "Unknown vfs worker type=" << _type);
+ break;
+ }
}
+ LOG_DEBUG(logger(), "Worker with type=" << _type << " and num=" << _num << " ended");
+}
+
+VfsOff::VfsOff(QObject *parent) : Vfs(VfsSetupParams(), parent) {}
+
+VfsOff::VfsOff(VfsSetupParams &vfsSetupParams, QObject *parent) : Vfs(vfsSetupParams, parent) {}
+
+VfsOff::~VfsOff() {}
+
+ExitInfo VfsOff::forceStatus(const SyncPath &pathStd, bool isSyncing, int /*progress*/, bool /*isHydrated*/) {
+ QString path = SyncName2QStr(pathStd.native());
+ KDC::SyncPath fullPath(_vfsSetupParams._localPath / QStr2Path(path));
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath, true); !exitInfo) {
+ return exitInfo;
+ }
// Update Finder
LOGW_DEBUG(logger(), L"Send status to the Finder extension for file/directory " << Path2WStr(fullPath).c_str());
QString status = isSyncing ? "SYNC" : "OK";
_vfsSetupParams._executeCommand(QString("STATUS:%1:%2").arg(status, path).toStdString().c_str());
- return true;
+ return ExitCode::Ok;
}
-bool VfsOff::startImpl(bool &, bool &, bool &) {
- return true;
+ExitInfo VfsOff::startImpl(bool &, bool &, bool &) {
+ return ExitCode::Ok;
}
static QString modeToPluginName(KDC::VirtualFileMode virtualFileMode) {
diff --git a/src/libcommonserver/vfs.h b/src/libcommonserver/vfs.h
index 985f5ccbf..28a6c0b7a 100644
--- a/src/libcommonserver/vfs.h
+++ b/src/libcommonserver/vfs.h
@@ -18,31 +18,49 @@
#pragma once
+#include "libcommon/utility/utility.h"
#include "libcommon/utility/types.h"
#include "libsyncengine/progress/syncfileitem.h"
+#include "libcommon/utility/sourcelocation.h"
#include
+#include
#include
#include
#include
+#include
+#include
+#include
+#include
#include
#include
-namespace KDC {
+constexpr short nbWorkers = 2;
+constexpr short workerHydration = 0;
+constexpr short workerDehydration = 1;
+namespace KDC {
struct VfsSetupParams {
int _syncDbId;
int _driveId;
int _userId;
- std::filesystem::path _localPath;
- std::filesystem::path _targetPath;
+ SyncPath _localPath;
+ SyncPath _targetPath;
std::string _namespaceCLSID;
KDC::ExecuteCommand _executeCommand;
log4cplus::Logger _logger;
};
+struct WorkerInfo {
+ QMutex _mutex;
+ std::deque _queue;
+ QWaitCondition _queueWC;
+ bool _stop = false;
+ QList _threadList;
+};
+
/** Interface describing how to deal with virtual/placeholder files.
*
* There are different ways of representing files locally that will only
@@ -59,12 +77,13 @@ class Vfs : public QObject {
Q_OBJECT
public:
+ std::array _workerInfo;
static QString modeToString(KDC::VirtualFileMode virtualFileMode);
static KDC::VirtualFileMode modeFromString(const QString &str);
- explicit Vfs(VfsSetupParams &vfsSetupParams, QObject *parent = nullptr);
+ explicit Vfs(const VfsSetupParams &vfsSetupParams, QObject *parent = nullptr);
- virtual ~Vfs();
+ ~Vfs() override;
inline void setSyncFileStatusCallback(void (*syncFileStatus)(int, const KDC::SyncPath &, KDC::SyncFileStatus &)) {
_syncFileStatus = syncFileStatus;
@@ -82,8 +101,11 @@ class Vfs : public QObject {
/** Initializes interaction with the VFS provider.
*
* The plugin-specific work is done in startImpl().
+ * Possible return values are:
+ * - ExitCode::Ok: Everything went fine.
+ * - ExitCode::LiteSyncError, ExitCause::UnableToCreateVfs: The VFS provider could not be started.
*/
- bool start(bool &installationDone, bool &activationDone, bool &connectionDone);
+ ExitInfo start(bool &installationDone, bool &activationDone, bool &connectionDone);
/// Stop interaction with VFS provider. Like when the client application quits.
/// Also deregister the folder with the sync provider, like when a folder is removed.
@@ -96,71 +118,105 @@ class Vfs : public QObject {
*/
virtual bool socketApiPinStateActionsShown() const = 0;
- /** Return true when download of a file's data is currently ongoing.
- *
- * See also the beginHydrating() and doneHydrating() signals.
- */
- virtual bool isHydrating() const = 0;
-
- /** Update placeholder metadata during discovery.
+ /** Update placeholder metadata.
*
* If the remote metadata changes, the local placeholder's metadata should possibly
* change as well.
*
- * Returning false and setting error indicates an error.
+ * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, the metadata was updated.
+ * - ExitCode::LogicError, ExitCause::Unknown: The liteSync connector is not initialized.
+ * - ExitCode::SystemError, ExitCause::Unknown: An unknown error occurred.
+ * - ExitCode::SystemError, ExitCause::NotFoud: The item could not be found.
+ * - ExitCode::SystemError, ExitCause::FileAccessError: Missing permissions on the item ot the item is locked.
*/
- virtual bool updateMetadata(const QString &filePath, time_t creationTime, time_t modtime, qint64 size,
- const QByteArray &fileId, QString *error) = 0;
+ virtual ExitInfo updateMetadata(const SyncPath &filePath, time_t creationTime, time_t modtime, int64_t size,
+ const NodeId &fileId) = 0;
- /// Create a new dehydrated placeholder
- virtual bool createPlaceholder(const KDC::SyncPath &relativeLocalPath, const KDC::SyncFileItem &item) = 0;
+ /** Create a new dehydrated placeholder
+ *
+ * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, the placeholder was created.
+ * - ExitCode::LogicError, ExitCause::InvalidArgument: relativeLocalPath is empty or item.remoteNodeId is not set.
+ * - ExitCode::SystemError, ExitCause::Unknown: An unknown error occurred.
+ * - ExitCode::SystemError, ExitCause::NotFoud: The parent folder does not exist.
+ * - ExitCode::SystemError, ExitCause::FileAccessError: Missing permissions on the destination folder or it is
+ * locked.
+ * - ExitCode::SystemError, ExitCause::FileAlreadyExist: An item with the same name already exists in the destination
+ * folder.
+ */
+ virtual ExitInfo createPlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item) = 0;
/** Convert a hydrated placeholder to a dehydrated one. Called from PropagateDownlaod.
*
* This is different from delete+create because preserving some file metadata
* (like pin states) may be essential for some vfs plugins.
- */
- virtual bool dehydratePlaceholder(const QString &path) = 0;
-
- /** Discovery hook: even unchanged files may need UPDATE_METADATA.
*
- * For instance cfapi vfs wants local hydrated non-placeholder files to
- * become hydrated placeholder files.
+ * * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, the placeholder is dehydrating (async).
+ * - ExitCode::LogicError, ExitCause::InvalidArgument: The provided path is empty.
+ * - ExitCode::SystemError, ExitCause::Unknown: An unknown error occurred.
+ * - ExitCode::SystemError, ExitCause::NotFoud: The item could not be found.
+ * - ExitCode::SystemError, ExitCause::FileAccessError: Missing permissions on the item ot the item is locked.
+ * - ExitCode::SystemError, ExitCause::NotPlaceHolder: The item is not a placeholder.
+ * folder.
*/
- virtual bool needsMetadataUpdate(const KDC::SyncFileItem &item) = 0;
+ virtual ExitInfo dehydratePlaceholder(const SyncPath &path) = 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".
- * 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.
*
- * replacesFile can optionally contain a filesystem path to a placeholder that this
- * new placeholder shall supersede, for rename-replace actions with new downloads,
- * for example.
+ * * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, the file is now a placeholder.
+ * - ExitCode::LogicError, ExitCause::InvalidArgument: item.localNodeId is not set.
+ * - ExitCode::SystemError, ExitCause::Unknown: An unknown error occurred.
+ * - ExitCode::SystemError, ExitCause::NotFoud: The item could not be found.
+ * - ExitCode::SystemError, ExitCause::FileAccessError: Missing permissions on the item ot the item is locked.
+ */
+ virtual ExitInfo convertToPlaceholder(const SyncPath &path, const KDC::SyncFileItem &item) = 0;
+
+ /** Update the fetch status of a file.
+ *
+ * This is used to update the progress of a file download in the OS file UI.
+ *
+ * * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, the fetch status was updated.
+ * - ExitCode::SystemError, ExitCause::Unknown: An unknown error occurred.
+ * - ExitCode::SystemError, ExitCause::NotFoud: The item could not be found.
+ * - ExitCode::SystemError, ExitCause::FileAccessError: Missing permissions on the item ot the item is locked (The item is
+ * the file in the sync folder, any error on the tmpItem will lead to SystemError, Unknown).
*/
- virtual bool convertToPlaceholder(const QString &path, const KDC::SyncFileItem &item) = 0;
+ virtual ExitInfo updateFetchStatus(const SyncPath &tmpPath, const SyncPath &path, int64_t received, bool &canceled,
+ bool &finished) = 0;
- virtual bool updateFetchStatus(const QString &tmpPath, const QString &path, qint64 received, bool &canceled,
- bool &finished) = 0;
+ /** Force the status of a file.
+ *
+ * This is used to force the sync status of a file (isSyncing or not)
+ *
+ * * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, the status was updated.
+ * - ExitCode::SystemError, ExitCause::Unknown: An unknown error occurred.
+ * - ExitCode::SystemError, ExitCause::NotFoud: The item could not be found.
+ * - ExitCode::SystemError, ExitCause::FileAccessError: Missing permissions on the item ot the item is locked.
+ */
+ virtual ExitInfo forceStatus(const SyncPath &path, bool isSyncing, int progress, bool isHydrated = false) = 0;
- virtual bool forceStatus(const QString &path, bool isSyncing, int progress, bool isHydrated = false) = 0;
virtual bool cleanUpStatuses() { return true; };
- /// Determine whether the file at the given absolute path is a dehydrated placeholder.
- virtual bool isDehydratedPlaceholder(const QString &filePath, bool isAbsolutePath = false) = 0;
-
- /** Similar to isDehydratedPlaceholder() but used from sync discovery.
- *
- * This function shall set stat->type if appropriate.
- * It may rely on stat->path and stat_data (platform specific data).
+ /** Determine whether the file at the given path is a dehydrated placeholder.
*
- * Returning true means that type was fully determined.
+ * * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, isDehydrated is set to true if the file is a dehydrated placeholder.
+ * - ExitCode::SystemError, ExitCause::Unknown: An unknown error occurred.
+ * - ExitCode::SystemError, ExitCause::NotFoud: The item could not be found.
+ * - ExitCode::SystemError, ExitCause::FileAccessError: Missing permissions on the item ot the item is locked.
*/
- // virtual bool statTypeVirtualFile(csync_file_stat_t *stat, void *stat_data, const QString &fileDirectory) = 0;
+ virtual ExitInfo isDehydratedPlaceholder(const SyncPath &filePath, bool &isDehydrated, bool isAbsolutePath = false) = 0;
/** Sets the pin state for the item at a path.
*
@@ -170,8 +226,14 @@ class Vfs : public QObject {
* but some vfs plugins will store the pin state in file attributes instead.
*
* fileRelativePath is relative to the sync folder. Can be "" for root folder.
+ *
+ * * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, the pin state was updated.
+ * - ExitCode::SystemError, ExitCause::Unknown: An unknown error occurred.
+ * - ExitCode::SystemError, ExitCause::NotFoud: The item could not be found.
+ * - ExitCode::SystemError, ExitCause::FileAccessError: Missing permissions on the item ot the item is locked.
*/
- virtual bool setPinState(const QString &fileRelativePath, KDC::PinState state) = 0;
+ virtual ExitInfo setPinState(const SyncPath &fileRelativePath, KDC::PinState state) = 0;
/** Returns the pin state of an item at a path.
*
@@ -182,31 +244,64 @@ class Vfs : public QObject {
*
* Returns none on retrieval error.
*/
- virtual KDC::PinState pinState(const QString &fileRelativePath) = 0;
- virtual bool status(const QString &filePath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress) = 0;
+ virtual KDC::PinState pinState(const SyncPath &fileRelativePath) = 0;
- virtual bool setThumbnail(const QString &filePath, const QPixmap &pixmap) = 0;
+ /** Returns the status of a file.
+ *
+ * * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, the status was retrieved.
+ * - ExitCode::SystemError, ExitCause::Unknown: An unknown error occurred.
+ * - ExitCode::SystemError, ExitCause::NotFoud: The item could not be found.
+ * - ExitCode::SystemError, ExitCause::FileAccessError: Missing permissions on the item ot the item is locked.
+ */
+ virtual ExitInfo status(const SyncPath &filePath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing,
+ int &progress) = 0;
- virtual bool setAppExcludeList() = 0;
+ /** Set the thumbnail for a file.
+ *
+ * * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, the status was retrieved.
+ * - ExitCode::SystemError, ExitCause::Unknown: An unknown error occurred.
+ * - ExitCode::SystemError, ExitCause::NotFoud: The item could not be found.
+ * - ExitCode::SystemError, ExitCause::FileAccessError: Missing permissions on the item ot the item is locked.
+ */
+ virtual ExitInfo setThumbnail(const SyncPath &filePath, const QPixmap &pixmap) = 0;
- virtual bool getFetchingAppList(QHash &appTable) = 0;
+ /** Set the list of applications that should not be hydrated.
+ *
+ * * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, the list was set.
+ * - ExitCode::LogicError, ExitCause::Unknown: An unknown error occurred.
+ */
+ virtual ExitInfo setAppExcludeList() = 0;
+
+ /** Set the list of applications that should not be hydrated.
+ *
+ * * Possible return values are:
+ * - ExitCode::Ok: Everything went fine, the list was set.
+ * - ExitCode::LogicError, ExitCause::Unknown: An unknown error occurred.
+ */
+ virtual ExitInfo getFetchingAppList(QHash &appTable) = 0;
- virtual void exclude(const QString &) = 0;
- virtual bool isExcluded(const QString &filePath) = 0;
+ virtual void exclude(const SyncPath &) = 0;
+ virtual bool isExcluded(const SyncPath &filePath) = 0;
- virtual void cancelHydrate(const QString &) {}
+ virtual void cancelHydrate(const SyncPath &) {}
- virtual bool fileStatusChanged(const QString &systemFileName, KDC::SyncFileStatus fileStatus) = 0;
+ virtual bool fileStatusChanged(const SyncPath &systemFileName, KDC::SyncFileStatus fileStatus) = 0;
virtual void convertDirContentToPlaceholder(const QString &, bool) {}
- virtual void clearFileAttributes(const QString &) = 0;
+ virtual void clearFileAttributes(const SyncPath &) = 0;
inline void setExtendedLog(bool extendedLog) { _extendedLog = extendedLog; }
inline const std::string &namespaceCLSID() { return _vfsSetupParams._namespaceCLSID; }
inline void setNamespaceCLSID(const std::string &CLSID) { _vfsSetupParams._namespaceCLSID = CLSID; }
+ virtual void dehydrate(const QString &path) = 0;
+ virtual void hydrate(const QString &path) = 0;
+
signals:
/// Emitted when a user-initiated hydration starts
void beginHydrating();
@@ -215,6 +310,8 @@ class Vfs : public QObject {
protected:
VfsSetupParams _vfsSetupParams;
+ void starVfsWorkers();
+ const std::array s_nb_threads = {5, 5};
// Callbacks
void (*_syncFileStatus)(int syncDbId, const KDC::SyncPath &itemPath, KDC::SyncFileStatus &status) = nullptr;
@@ -233,17 +330,40 @@ class Vfs : public QObject {
* Usually some registration needs to be done with the backend. This function
* should take care of it if necessary.
*/
- virtual bool startImpl(bool &installationDone, bool &activationDone, bool &connectionDone) = 0;
+ virtual ExitInfo startImpl(bool &installationDone, bool &activationDone, bool &connectionDone) = 0;
virtual void stopImpl(bool unregister) = 0;
- inline log4cplus::Logger logger() { return _vfsSetupParams._logger; }
+ inline log4cplus::Logger logger() const { return _vfsSetupParams._logger; }
+
+ ExitInfo handleVfsError(const SyncPath &itemPath, const SourceLocation location = SourceLocation::currentLoc()) const;
+ ExitInfo checkIfPathExists(const SyncPath &itemPath, bool shouldExist,
+ const SourceLocation location = SourceLocation::currentLoc()) const;
+ // By default we will return file access error.
+ inline ExitInfo defaultVfsError(const SourceLocation location = SourceLocation::currentLoc()) const {
+ return {ExitCode::SystemError, ExitCause::FileAccessError, location};
+ }
private:
bool _extendedLog;
bool _started;
};
+class VfsWorker : public QObject {
+ Q_OBJECT
+
+ public:
+ VfsWorker(Vfs *vfs, int type, int num, log4cplus::Logger logger);
+ void start();
+
+ private:
+ Vfs *_vfs;
+ int _type;
+ int _num;
+ log4cplus::Logger _logger;
+
+ inline log4cplus::Logger logger() { return _logger; }
+};
} // namespace KDC
Q_DECLARE_INTERFACE(KDC::Vfs, "Vfs")
@@ -260,40 +380,49 @@ class VfsOff : public Vfs {
Q_INTERFACES(KDC::Vfs)
public:
+ explicit VfsOff(QObject *parent = nullptr);
VfsOff(VfsSetupParams &vfsSetupParams, QObject *parent = nullptr);
- virtual ~VfsOff();
+ ~VfsOff() override;
KDC::VirtualFileMode mode() const override { return KDC::VirtualFileMode::Off; }
bool socketApiPinStateActionsShown() const override { return false; }
- bool isHydrating() const override { return false; }
-
- bool updateMetadata(const QString &, time_t, time_t, qint64, const QByteArray &, QString *) override { return true; }
- bool createPlaceholder(const KDC::SyncPath &, const KDC::SyncFileItem &) override { return true; }
- bool dehydratePlaceholder(const QString &) override { return true; }
- bool convertToPlaceholder(const QString &, const KDC::SyncFileItem &) override { return true; }
- bool updateFetchStatus(const QString &, const QString &, qint64, bool &, bool &) override { return true; }
- bool forceStatus(const QString &path, bool isSyncing, int progress, bool isHydrated = false) override;
-
- bool needsMetadataUpdate(const KDC::SyncFileItem &) override { return false; }
- bool isDehydratedPlaceholder(const QString &, bool) override { return false; }
-
- bool setPinState(const QString &, KDC::PinState) override { return true; }
- KDC::PinState pinState(const QString &) override { return KDC::PinState::AlwaysLocal; }
- bool status(const QString &, bool &, bool &, bool &, int &) override { return true; }
- virtual bool setThumbnail(const QString &, const QPixmap &) override { return true; }
- virtual bool setAppExcludeList() override { return true; }
- virtual bool getFetchingAppList(QHash &) override { return true; }
- virtual void exclude(const QString &) override {}
- virtual bool isExcluded(const QString &) override { return false; }
- virtual bool fileStatusChanged(const QString &, KDC::SyncFileStatus) override { return true; }
-
- virtual void clearFileAttributes(const QString &) override {}
+
+ ExitInfo updateMetadata(const SyncPath &, time_t, time_t, int64_t, const NodeId &) override { return ExitCode::Ok; }
+ ExitInfo createPlaceholder(const KDC::SyncPath &, const KDC::SyncFileItem &) override { return ExitCode::Ok; }
+ ExitInfo dehydratePlaceholder(const SyncPath &) override { return ExitCode::Ok; }
+ ExitInfo convertToPlaceholder(const SyncPath &, const KDC::SyncFileItem &) override { return ExitCode::Ok; }
+ ExitInfo updateFetchStatus(const SyncPath &, const SyncPath &, int64_t, bool &, bool &) override { return ExitCode::Ok; }
+ ExitInfo forceStatus(const SyncPath &path, bool isSyncing, int progress, bool isHydrated = false) override;
+
+ ExitInfo isDehydratedPlaceholder(const SyncPath &, bool &isDehydrated, bool) override {
+ isDehydrated = false;
+ return ExitCode::Ok;
+ }
+
+ ExitInfo setPinState(const SyncPath &, KDC::PinState) override { return ExitCode::Ok; }
+ KDC::PinState pinState(const SyncPath &) override { return KDC::PinState::AlwaysLocal; }
+ ExitInfo status(const SyncPath &, bool &, bool &, bool &, int &) override { return ExitCode::Ok; }
+ ExitInfo setThumbnail(const SyncPath &, const QPixmap &) override { return ExitCode::Ok; }
+ ExitInfo setAppExcludeList() override { return ExitCode::Ok; }
+ ExitInfo getFetchingAppList(QHash &) override { return ExitCode::Ok; }
+ void exclude(const SyncPath &) override { /*VfsOff*/
+ }
+ bool isExcluded(const SyncPath &) override { return false; }
+ bool fileStatusChanged(const SyncPath &, KDC::SyncFileStatus) final { return true; }
+
+ void clearFileAttributes(const SyncPath &) override { /*VfsOff*/
+ }
+ void dehydrate(const QString &) override { /*VfsOff*/
+ }
+ void hydrate(const QString &) override { /*VfsOff*/
+ }
protected:
- bool startImpl(bool &installationDone, bool &activationDone, bool &connectionDone) override;
- void stopImpl(bool /*unregister*/) override {}
+ ExitInfo startImpl(bool &installationDone, bool &activationDone, bool &connectionDone) override;
+ void stopImpl(bool /*unregister*/) override { /*VfsOff*/
+ }
friend class TestWorkers;
};
diff --git a/src/libsyncengine/jobs/abstractjob.h b/src/libsyncengine/jobs/abstractjob.h
index ecaa76535..687f1efee 100644
--- a/src/libsyncengine/jobs/abstractjob.h
+++ b/src/libsyncengine/jobs/abstractjob.h
@@ -73,24 +73,26 @@ class AbstractJob : public Poco::Runnable {
inline bool isRunning() const { return _isRunning; }
inline void setVfsUpdateFetchStatusCallback(
- std::function callback) noexcept {
+ const std::function &callback) noexcept {
_vfsUpdateFetchStatus = callback;
}
- inline void setVfsSetPinStateCallback(std::function callback) noexcept {
+ inline void setVfsSetPinStateCallback(const std::function &callback) noexcept {
_vfsSetPinState = callback;
}
- inline void setVfsForceStatusCallback(std::function callback) noexcept {
+ inline void setVfsForceStatusCallback(
+ const std::function &callback) noexcept {
_vfsForceStatus = callback;
}
- inline void setVfsStatusCallback(std::function callback) noexcept {
+ inline void setVfsStatusCallback(
+ const std::function &callback) noexcept {
_vfsStatus = callback;
}
- inline void setVfsUpdateMetadataCallback(std::function
- callback) noexcept {
+ inline void setVfsUpdateMetadataCallback(
+ const std::function
+ &callback) noexcept {
_vfsUpdateMetadata = callback;
}
- inline void setVfsCancelHydrateCallback(std::function callback) noexcept {
+ inline void setVfsCancelHydrateCallback(const std::function &callback) noexcept {
_vfsCancelHydrate = callback;
}
@@ -107,16 +109,16 @@ class AbstractJob : public Poco::Runnable {
ExitCode _exitCode = ExitCode::Unknown;
ExitCause _exitCause = ExitCause::Unknown;
- std::function
- _vfsUpdateFetchStatus = nullptr;
- std::function _vfsSetPinState = nullptr;
- std::function _vfsForceStatus = nullptr;
- std::function
- _vfsStatus = nullptr;
- std::function
- _vfsUpdateMetadata = nullptr;
- std::function _vfsCancelHydrate = nullptr;
+ std::function
+ _vfsUpdateFetchStatus;
+ std::function _vfsSetPinState;
+ std::function _vfsForceStatus;
+ std::function
+ _vfsStatus;
+ std::function
+ _vfsUpdateMetadata;
+ std::function _vfsCancelHydrate;
private:
virtual void run() final;
diff --git a/src/libsyncengine/jobs/network/API_v2/createdirjob.cpp b/src/libsyncengine/jobs/network/API_v2/createdirjob.cpp
index e9f01024b..e8561bab1 100644
--- a/src/libsyncengine/jobs/network/API_v2/createdirjob.cpp
+++ b/src/libsyncengine/jobs/network/API_v2/createdirjob.cpp
@@ -24,8 +24,8 @@ namespace KDC {
CreateDirJob::CreateDirJob(int driveDbId, const SyncPath &filepath, const NodeId &parentId, const SyncName &name,
const std::string &color /*= ""*/) :
- AbstractTokenNetworkJob(ApiType::Drive, 0, 0, driveDbId, 0), _filePath(filepath), _parentDirId(parentId), _name(name),
- _color(color) {
+ AbstractTokenNetworkJob(ApiType::Drive, 0, 0, driveDbId, 0),
+ _filePath(filepath), _parentDirId(parentId), _name(name), _color(color) {
_httpMethod = Poco::Net::HTTPRequest::HTTP_POST;
}
@@ -33,16 +33,22 @@ CreateDirJob::CreateDirJob(int driveDbId, const NodeId &parentId, const SyncName
CreateDirJob(driveDbId, "", parentId, name) {}
CreateDirJob::~CreateDirJob() {
- if (_vfsSetPinState && _vfsForceStatus && !_filePath.empty()) {
- if (!_vfsSetPinState(_filePath, PinState::AlwaysLocal)) {
- LOGW_WARN(_logger, L"Error in CreateDirJob::vfsSetPinState for " << Utility::formatSyncPath(_filePath).c_str());
- }
- if (!_vfsForceStatus(_filePath, false, 0, true)) {
- LOGW_WARN(_logger, L"Error in CreateDirJob::vfsForceStatus for " << Utility::formatSyncPath(_filePath).c_str());
+ if (_filePath.empty()) return;
+ try {
+ if (_vfsSetPinState && _vfsForceStatus) {
+ if (ExitInfo exitInfo = _vfsSetPinState(_filePath, PinState::AlwaysLocal); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in CreateDirJob::vfsSetPinState for " << Utility::formatSyncPath(_filePath) << L" : "
+ << exitInfo);
+ }
+ if (ExitInfo exitInfo = _vfsForceStatus(_filePath, false, 0, true); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in CreateDirJob::vfsForceStatus for " << Utility::formatSyncPath(_filePath) << L" : "
+ << exitInfo);
+ }
}
+ } catch (const std::bad_function_call &e) {
+ LOG_WARN(_logger, "Error in CreateDirJob::~CreateDirJob: " << e.what());
}
}
-
std::string CreateDirJob::getSpecificUrl() {
std::string str = AbstractTokenNetworkJob::getSpecificUrl();
str += "/files/";
@@ -79,8 +85,11 @@ bool CreateDirJob::handleResponse(std::istream &is) {
}
}
- if (!_filePath.empty() && _vfsForceStatus && !_vfsForceStatus(_filePath, false, 100, true)) {
- LOGW_WARN(_logger, L"Error in CreateDirJob::_vfsForceStatus for " << Utility::formatSyncPath(_filePath).c_str());
+ if (!_filePath.empty() && _vfsForceStatus) {
+ if (ExitInfo exitInfo = _vfsForceStatus(_filePath, false, 100, true); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in CreateDirJob::_vfsForceStatus for " << Utility::formatSyncPath(_filePath) << L" : "
+ << exitInfo);
+ }
}
}
diff --git a/src/libsyncengine/jobs/network/API_v2/downloadjob.cpp b/src/libsyncengine/jobs/network/API_v2/downloadjob.cpp
index 744c7c7cc..674044e5a 100644
--- a/src/libsyncengine/jobs/network/API_v2/downloadjob.cpp
+++ b/src/libsyncengine/jobs/network/API_v2/downloadjob.cpp
@@ -59,24 +59,25 @@ DownloadJob::DownloadJob(int driveDbId, const NodeId &remoteFileId, const SyncPa
}
DownloadJob::~DownloadJob() {
+ try{
// Remove tmp file
// For a remote CREATE operation, the tmp file should no longer exist, but if an error occurred in handleResponse, it must be
// deleted
if (!removeTmpFile() && !_isCreate) {
LOGW_WARN(_logger, L"Failed to remove tmp file: " << Utility::formatSyncPath(_tmpPath));
}
-
+
if (_responseHandlingCanceled) {
if (_vfsSetPinState) {
- if (!_vfsSetPinState(_localpath, PinState::OnlineOnly)) {
- LOGW_WARN(_logger, L"Error in vfsSetPinState: " << Utility::formatSyncPath(_localpath));
+ if (ExitInfo exitInfo = _vfsSetPinState(_localpath, PinState::OnlineOnly); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsSetPinState: " << Utility::formatSyncPath(_localpath) << L" : " << exitInfo);
}
}
// TODO: usefull ?
if (_vfsForceStatus) {
- if (!_vfsForceStatus(_localpath, false, 0, false)) {
- LOGW_WARN(_logger, L"Error in vfsForceStatus: " << Utility::formatSyncPath(_localpath));
+ if (ExitInfo exitInfo = _vfsForceStatus(_localpath, false, 0, false); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsForceStatus: " << Utility::formatSyncPath(_localpath) << L" : " << exitInfo);
}
}
@@ -87,17 +88,22 @@ DownloadJob::~DownloadJob() {
}
} else {
if (_vfsSetPinState) {
- if (!_vfsSetPinState(_localpath, _exitCode == ExitCode::Ok ? PinState::AlwaysLocal : PinState::OnlineOnly)) {
- LOGW_WARN(_logger, L"Error in vfsSetPinState: " << Utility::formatSyncPath(_localpath));
+ if (ExitInfo exitInfo =
+ _vfsSetPinState(_localpath, _exitCode == ExitCode::Ok ? PinState::AlwaysLocal : PinState::OnlineOnly);
+ !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsSetPinState: " << Utility::formatSyncPath(_localpath) << L": " << exitInfo);
}
}
if (_vfsForceStatus) {
- if (!_vfsForceStatus(_localpath, false, 0, _exitCode == ExitCode::Ok)) {
- LOGW_WARN(_logger, L"Error in vfsForceStatus: " << Utility::formatSyncPath(_localpath));
+ if (ExitInfo exitInfo = _vfsForceStatus(_localpath, false, 0, _exitCode == ExitCode::Ok); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsForceStatus: " << Utility::formatSyncPath(_localpath) << L" : " << exitInfo);
}
}
}
+ } catch (const std::bad_function_call &e) {
+ LOG_ERROR(_logger, "Error in DownloadJob::~DownloadJob: " << e.what());
+ }
}
std::string DownloadJob::getSpecificUrl() {
@@ -142,28 +148,37 @@ void DownloadJob::runJob() noexcept {
IoError ioError = IoError::Success;
if (!IoHelper::getFileStat(_localpath, &filestat, ioError)) {
LOGW_WARN(_logger, L"Error in IoHelper::getFileStat: " << Utility::formatIoError(_localpath, ioError));
+ _exitCode = ExitCode::SystemError;
+ _exitCause = ExitCause::Unknown;
return;
}
-
if (ioError == IoError::NoSuchFileOrDirectory) {
LOGW_WARN(_logger, L"Item does not exist anymore: " << Utility::formatSyncPath(_localpath));
+ _exitCode = ExitCode::SystemError;
+ _exitCause = ExitCause::NotFound;
return;
} else if (ioError == IoError::AccessDenied) {
LOGW_WARN(_logger, L"Item misses search permission: " << Utility::formatSyncPath(_localpath));
+ _exitCode = ExitCode::SystemError;
+ _exitCause = ExitCause::FileAccessError;
return;
}
- std::string error;
- if (!_vfsUpdateMetadata(_localpath, filestat.creationTime, filestat.modtime, _expectedSize,
- std::to_string(filestat.inode), error)) {
- LOGW_WARN(_logger, L"Update metadata failed: " << Utility::formatSyncPath(_localpath));
+ if (ExitInfo exitInfo = _vfsUpdateMetadata(_localpath, filestat.creationTime, filestat.modtime, _expectedSize,
+ std::to_string(filestat.inode));
+ !exitInfo) {
+ LOGW_WARN(_logger, L"Update metadata failed " << exitInfo << L" " << Utility::formatSyncPath(_localpath));
+ _exitCode = exitInfo.code();
+ _exitCause = exitInfo.cause();
return;
}
}
if (_vfsForceStatus) {
- if (!_vfsForceStatus(_localpath, true, 0, false)) {
- LOGW_WARN(_logger, L"Error in vfsForceStatus: " << Utility::formatSyncPath(_localpath));
+ if (ExitInfo exitInfo = _vfsForceStatus(_localpath, true, 0, false); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsForceStatus: " << Utility::formatSyncPath(_localpath) << L" : " << exitInfo);
+ _exitCode = exitInfo.code();
+ _exitCause = exitInfo.cause();
return;
}
}
@@ -314,8 +329,11 @@ bool DownloadJob::handleResponse(std::istream &is) {
std::chrono::duration elapsed_seconds = std::chrono::steady_clock::now() - fileProgressTimer;
if (elapsed_seconds.count() > NOTIFICATION_DELAY || done) {
// Update fetch status
- if (!_vfsUpdateFetchStatus(_tmpPath, _localpath, getProgress(), fetchCanceled, fetchFinished)) {
- LOGW_WARN(_logger, L"Error in vfsUpdateFetchStatus: " << Utility::formatSyncPath(_localpath));
+ if (ExitInfo exitInfo =
+ _vfsUpdateFetchStatus(_tmpPath, _localpath, getProgress(), fetchCanceled, fetchFinished);
+ !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsUpdateFetchStatus: " << Utility::formatSyncPath(_localpath) << L": "
+ << exitInfo);
fetchError = true;
break;
} else if (fetchCanceled) {
@@ -351,8 +369,10 @@ bool DownloadJob::handleResponse(std::istream &is) {
if (!_responseHandlingCanceled) {
if (_vfsUpdateFetchStatus && !fetchFinished) {
// Update fetch status
- if (!_vfsUpdateFetchStatus(_tmpPath, _localpath, getProgress(), fetchCanceled, fetchFinished)) {
- LOGW_WARN(_logger, L"Error in vfsUpdateFetchStatus: " << Utility::formatSyncPath(_localpath));
+ if (ExitInfo exitInfo = _vfsUpdateFetchStatus(_tmpPath, _localpath, getProgress(), fetchCanceled, fetchFinished);
+ !exitInfo) {
+ LOGW_WARN(_logger,
+ L"Error in vfsUpdateFetchStatus: " << Utility::formatSyncPath(_localpath) << L" : " << exitInfo);
fetchError = true;
} else if (fetchCanceled) {
LOGW_WARN(_logger, L"Update fetch status canceled: " << Utility::formatSyncPath(_localpath));
diff --git a/src/libsyncengine/jobs/network/API_v2/duplicatejob.cpp b/src/libsyncengine/jobs/network/API_v2/duplicatejob.cpp
index 699d9de5b..cf1304b79 100644
--- a/src/libsyncengine/jobs/network/API_v2/duplicatejob.cpp
+++ b/src/libsyncengine/jobs/network/API_v2/duplicatejob.cpp
@@ -34,12 +34,12 @@ DuplicateJob::~DuplicateJob() {
bool isHydrated = false;
bool isSyncing = false;
int progress = 0;
- if (!_vfsStatus(_absoluteFinalPath, isPlaceholder, isHydrated, isSyncing, progress)) {
- LOGW_WARN(_logger, L"Error in vfsStatus for path=" << Path2WStr(_absoluteFinalPath).c_str());
+ if (ExitInfo exitInfo = _vfsStatus(_absoluteFinalPath, isPlaceholder, isHydrated, isSyncing, progress); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsStatus for path=" << Path2WStr(_absoluteFinalPath) << L" : " << exitInfo);
}
- if (!_vfsForceStatus(_absoluteFinalPath, false, 0, false)) {
- LOGW_WARN(_logger, L"Error in vfsForceStatus for path=" << Path2WStr(_absoluteFinalPath).c_str());
+ if (ExitInfo exitInfo = _vfsForceStatus(_absoluteFinalPath, false, 0, false); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsForceStatus for path=" << Path2WStr(_absoluteFinalPath) << L" : " << exitInfo);
}
}
}
diff --git a/src/libsyncengine/jobs/network/API_v2/movejob.cpp b/src/libsyncengine/jobs/network/API_v2/movejob.cpp
index f6e8fde24..573a39419 100644
--- a/src/libsyncengine/jobs/network/API_v2/movejob.cpp
+++ b/src/libsyncengine/jobs/network/API_v2/movejob.cpp
@@ -25,8 +25,8 @@ namespace KDC {
MoveJob::MoveJob(int driveDbId, const SyncPath &destFilepath, const NodeId &fileId, const NodeId &destDirId,
const SyncName &name /*= ""*/) :
- AbstractTokenNetworkJob(ApiType::Drive, 0, 0, driveDbId, 0), _destFilepath(destFilepath), _fileId(fileId),
- _destDirId(destDirId), _name(name) {
+ AbstractTokenNetworkJob(ApiType::Drive, 0, 0, driveDbId, 0),
+ _destFilepath(destFilepath), _fileId(fileId), _destDirId(destDirId), _name(name) {
_httpMethod = Poco::Net::HTTPRequest::HTTP_POST;
}
@@ -36,13 +36,14 @@ MoveJob::~MoveJob() {
bool isHydrated = false;
bool isSyncing = false;
int progress = 0;
- if (!_vfsStatus(_destFilepath, isPlaceholder, isHydrated, isSyncing, progress)) {
- LOGW_WARN(_logger, L"Error in vfsStatus for path=" << Path2WStr(_destFilepath).c_str());
+ if (ExitInfo exitInfo = _vfsStatus(_destFilepath, isPlaceholder, isHydrated, isSyncing, progress); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsStatus for path=" << Path2WStr(_destFilepath) << L" : " << exitInfo);
}
- if (!_vfsForceStatus(_destFilepath, false, 100,
- isHydrated)) { // TODO : to be refactored, some parameters are used on macOS only
- LOGW_WARN(_logger, L"Error in vfsForceStatus for path=" << Path2WStr(_destFilepath).c_str());
+ if (ExitInfo exitInfo = _vfsForceStatus(_destFilepath, false, 100,
+ isHydrated);
+ !exitInfo) { // TODO : to be refactored, some parameters are used on macOS only
+ LOGW_WARN(_logger, L"Error in vfsForceStatus for path=" << Path2WStr(_destFilepath) << L" : " << exitInfo);
}
}
}
diff --git a/src/libsyncengine/jobs/network/API_v2/renamejob.cpp b/src/libsyncengine/jobs/network/API_v2/renamejob.cpp
index 3cb2007ae..9b16ef302 100644
--- a/src/libsyncengine/jobs/network/API_v2/renamejob.cpp
+++ b/src/libsyncengine/jobs/network/API_v2/renamejob.cpp
@@ -33,12 +33,12 @@ RenameJob::~RenameJob() {
bool isHydrated = false;
bool isSyncing = false;
int progress = 0;
- if (!_vfsStatus(_absoluteFinalPath, isPlaceholder, isHydrated, isSyncing, progress)) {
- LOGW_WARN(_logger, L"Error in vfsStatus for path=" << Path2WStr(_absoluteFinalPath).c_str());
+ if (ExitInfo exitInfo = _vfsStatus(_absoluteFinalPath, isPlaceholder, isHydrated, isSyncing, progress); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsStatus for path=" << Path2WStr(_absoluteFinalPath) << L" : " << exitInfo);
}
- if (!_vfsForceStatus(_absoluteFinalPath, false, 0, isHydrated)) {
- LOGW_WARN(_logger, L"Error in vfsForceStatus for path=" << Path2WStr(_absoluteFinalPath).c_str());
+ if (ExitInfo exitInfo = _vfsForceStatus(_absoluteFinalPath, false, 0, isHydrated); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsForceStatus for path=" << Path2WStr(_absoluteFinalPath) << L" : " << exitInfo);
}
}
}
diff --git a/src/libsyncengine/jobs/network/API_v2/upload_session/abstractuploadsession.cpp b/src/libsyncengine/jobs/network/API_v2/upload_session/abstractuploadsession.cpp
index 87d1787a3..8f0ae3828 100644
--- a/src/libsyncengine/jobs/network/API_v2/upload_session/abstractuploadsession.cpp
+++ b/src/libsyncengine/jobs/network/API_v2/upload_session/abstractuploadsession.cpp
@@ -272,7 +272,7 @@ bool AbstractUploadSession::sendChunks() {
// "file not found" errors.
std::ifstream file;
if (ExitInfo exitInfo = IoHelper::openFile(_filePath, file, 10); !exitInfo) {
- LOGW_WARN(_logger, L"Failed to open file " << Utility::formatSyncPath(_filePath));
+ LOGW_WARN(_logger, L"Failed to open file " << Utility::formatSyncPath(_filePath) << L" " << exitInfo);
return exitInfo;
}
diff --git a/src/libsyncengine/jobs/network/API_v2/upload_session/driveuploadsession.cpp b/src/libsyncengine/jobs/network/API_v2/upload_session/driveuploadsession.cpp
index 42b17daa6..1dfd9fbe7 100644
--- a/src/libsyncengine/jobs/network/API_v2/upload_session/driveuploadsession.cpp
+++ b/src/libsyncengine/jobs/network/API_v2/upload_session/driveuploadsession.cpp
@@ -30,15 +30,17 @@ DriveUploadSession::DriveUploadSession(int driveDbId, std::shared_ptr sy
DriveUploadSession::DriveUploadSession(int driveDbId, std::shared_ptr syncDb, const SyncPath &filepath,
const SyncName &filename, const NodeId &remoteParentDirId, SyncTime modtime,
bool liteSyncActivated, uint64_t nbParalleleThread /*= 1*/) :
- AbstractUploadSession(filepath, filename, nbParalleleThread), _driveDbId(driveDbId), _syncDb(syncDb), _modtimeIn(modtime),
- _remoteParentDirId(remoteParentDirId) {
+ AbstractUploadSession(filepath, filename, nbParalleleThread),
+ _driveDbId(driveDbId), _syncDb(syncDb), _modtimeIn(modtime), _remoteParentDirId(remoteParentDirId) {
(void) liteSyncActivated;
_uploadSessionType = UploadSessionType::Drive;
}
DriveUploadSession::~DriveUploadSession() {
- if (_vfsForceStatus && !_vfsForceStatus(getFilePath(), false, 100, true)) {
- LOGW_WARN(getLogger(), L"Error in vfsForceStatus: " << Utility::formatSyncPath(getFilePath()).c_str());
+ if (_vfsForceStatus) {
+ if (ExitInfo exitInfo = _vfsForceStatus(getFilePath(), false, 100, true); !exitInfo) {
+ LOGW_WARN(getLogger(), L"Error in vfsForceStatus: " << Utility::formatSyncPath(getFilePath()) << L" : " << exitInfo);
+ }
}
}
diff --git a/src/libsyncengine/jobs/network/API_v2/upload_session/uploadsessionfinishjob.cpp b/src/libsyncengine/jobs/network/API_v2/upload_session/uploadsessionfinishjob.cpp
index db2c9ba9c..03419a518 100644
--- a/src/libsyncengine/jobs/network/API_v2/upload_session/uploadsessionfinishjob.cpp
+++ b/src/libsyncengine/jobs/network/API_v2/upload_session/uploadsessionfinishjob.cpp
@@ -37,8 +37,8 @@ UploadSessionFinishJob::UploadSessionFinishJob(UploadSessionType uploadType, con
UploadSessionFinishJob::~UploadSessionFinishJob() {
if (_vfsForceStatus) {
- if (!_vfsForceStatus(_filePath, false, 0, true)) {
- LOGW_WARN(_logger, L"Error in vfsForceStatus for path=" << Path2WStr(_filePath).c_str());
+ if (ExitInfo exitInfo = _vfsForceStatus(_filePath, false, 0, true); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsForceStatus for path=" << Path2WStr(_filePath) << L" : " << exitInfo);
}
}
}
diff --git a/src/libsyncengine/jobs/network/API_v2/uploadjob.cpp b/src/libsyncengine/jobs/network/API_v2/uploadjob.cpp
index fe3fb0fcc..27cd63822 100644
--- a/src/libsyncengine/jobs/network/API_v2/uploadjob.cpp
+++ b/src/libsyncengine/jobs/network/API_v2/uploadjob.cpp
@@ -45,14 +45,14 @@ UploadJob::UploadJob(int driveDbId, const SyncPath &filepath, const NodeId &file
UploadJob::~UploadJob() {
if (_vfsForceStatus) {
- if (!_vfsForceStatus(_filePath, false, 100, true)) {
- LOGW_WARN(_logger, L"Error in vfsForceStatus - path=" << Path2WStr(_filePath).c_str());
+ if (ExitInfo exitInfo = _vfsForceStatus(_filePath, false, 100, true); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsForceStatus - path=" << Path2WStr(_filePath) << L" : " << exitInfo);
}
}
if (_vfsSetPinState) {
- if (!_vfsSetPinState(_filePath, PinState::AlwaysLocal)) {
- LOGW_WARN(_logger, L"Error in vfsSetPinState - path=" << Path2WStr(_filePath).c_str());
+ if (ExitInfo exitInfo = _vfsSetPinState(_filePath, PinState::AlwaysLocal); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsSetPinState - path=" << Path2WStr(_filePath) << L": " << exitInfo);
}
}
}
diff --git a/src/libsyncengine/jobs/network/abstractnetworkjob.cpp b/src/libsyncengine/jobs/network/abstractnetworkjob.cpp
index bfc5dfd92..525f4469a 100644
--- a/src/libsyncengine/jobs/network/abstractnetworkjob.cpp
+++ b/src/libsyncengine/jobs/network/abstractnetworkjob.cpp
@@ -140,7 +140,7 @@ void AbstractNetworkJob::runJob() noexcept {
bool canceled = false;
if (ExitInfo exitInfo = setData(); !exitInfo) { // Must be called before setQueryParameters
- LOG_WARN(_logger, "Job " << jobId() << " is cancelled");
+ LOG_WARN(_logger, "Job " << jobId() << " is cancelled " << exitInfo);
_exitCode = exitInfo.code();
_exitCause = exitInfo.cause();
break;
diff --git a/src/libsyncengine/propagation/executor/executorworker.cpp b/src/libsyncengine/propagation/executor/executorworker.cpp
index 39d085670..f2b07438d 100644
--- a/src/libsyncengine/propagation/executor/executorworker.cpp
+++ b/src/libsyncengine/propagation/executor/executorworker.cpp
@@ -230,8 +230,8 @@ void ExecutorWorker::execute() {
_syncPal->vfsCleanUpStatuses();
setExitCause(executorExitInfo.cause());
- LOG_SYNCPAL_DEBUG(_logger, "Worker stopped: name=" << name().c_str());
setDone(executorExitInfo.code());
+ LOG_SYNCPAL_DEBUG(_logger, "Worker stopped: name=" << name() << " " << executorExitInfo);
}
void ExecutorWorker::initProgressManager() {
@@ -335,7 +335,8 @@ ExitInfo ExecutorWorker::handleCreateOp(SyncOpPtr syncOp, std::shared_ptromit()) {
bool isDehydratedPlaceholder = false;
if (ExitInfo exitInfo = checkLiteSyncInfoForCreate(syncOp, absoluteLocalFilePath, isDehydratedPlaceholder); !exitInfo) {
- LOGW_SYNCPAL_WARN(_logger, L"Error in checkLiteSyncInfoForCreate");
+ LOG_SYNCPAL_WARN(_logger, "Error in checkLiteSyncInfoForCreate"
+ << " " << exitInfo);
return exitInfo;
}
@@ -367,8 +368,8 @@ ExitInfo ExecutorWorker::handleCreateOp(SyncOpPtr syncOp, std::shared_ptrcorrespondingNode()->id().has_value() ? *syncOp->correspondingNode()->id() : std::string(),
syncOp->affectedNode()->lastmodified(), node);
!exitInfo) {
- LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for "
- << Utility::formatSyncName(syncOp->affectedNode()->name()));
+ LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for: "
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" " << exitInfo);
return exitInfo;
}
} else {
@@ -413,6 +414,8 @@ ExitInfo ExecutorWorker::handleCreateOp(SyncOpPtr syncOp, std::shared_ptraffectedNode()->name())
+ << L" " << exitInfo);
return exitInfo;
}
@@ -425,13 +428,14 @@ ExitInfo ExecutorWorker::handleCreateOp(SyncOpPtr syncOp, std::shared_ptrparentDirId());
!exitInfoCheckAlreadyExcluded) {
- LOG_SYNCPAL_WARN(_logger, "Error in ExecutorWorker::checkAlreadyExcluded");
+ LOG_SYNCPAL_WARN(_logger, "Error in ExecutorWorker::checkAlreadyExcluded"
+ << " " << exitInfoCheckAlreadyExcluded);
return exitInfoCheckAlreadyExcluded;
}
if (const ExitInfo exitInfo = handleForbiddenAction(syncOp, relativeLocalFilePath, ignored); !exitInfo) {
LOGW_SYNCPAL_WARN(_logger, L"Error in handleForbiddenAction for item: "
- << Utility::formatSyncPath(relativeLocalFilePath));
+ << Utility::formatSyncPath(relativeLocalFilePath) << L" " << exitInfo);
return exitInfo;
}
return {ExitCode::BackError, ExitCause::FileAccessError};
@@ -442,8 +446,9 @@ ExitInfo ExecutorWorker::handleCreateOp(SyncOpPtr syncOp, std::shared_ptrtargetSide() == ReplicaSide::Remote);
!exitInfo) {
- LOGW_SYNCPAL_WARN(_logger, L"Failed to convert to placeholder for "
- << Utility::formatSyncName(syncOp->affectedNode()->name()));
+ LOGW_SYNCPAL_WARN(_logger, L"Failed to convert to placeholder for: "
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" "
+ << exitInfo);
return exitInfo;
}
@@ -542,8 +547,9 @@ ExitInfo ExecutorWorker::generateCreateJob(SyncOpPtr syncOp, std::shared_ptraffectedNode()->name()));
+ LOGW_SYNCPAL_WARN(_logger, L"Failed to create placeholder for: "
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" "
+ << exitInfo);
return exitInfo;
}
@@ -567,8 +573,9 @@ ExitInfo ExecutorWorker::generateCreateJob(SyncOpPtr syncOp, std::shared_ptraffectedNode()->lastmodified(), newNode);
!exitInfo) {
- LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for "
- << Utility::formatSyncName(syncOp->affectedNode()->name()));
+ LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for: "
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" "
+ << exitInfo);
return exitInfo;
}
@@ -636,13 +643,15 @@ ExitInfo ExecutorWorker::generateCreateJob(SyncOpPtr syncOp, std::shared_ptraffectedNode()->type() == NodeType::Directory) {
if (ExitInfo exitInfo = convertToPlaceholder(relativeLocalFilePath, syncOp->targetSide() == ReplicaSide::Remote);
!exitInfo) {
- LOGW_SYNCPAL_WARN(_logger, L"Failed to convert to placeholder for "
- << Utility::formatSyncName(syncOp->affectedNode()->name()));
+ LOGW_SYNCPAL_WARN(_logger, L"Failed to convert to placeholder for: "
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" "
+ << exitInfo);
_syncPal->setRestart(true);
if (!_syncPal->updateTree(ReplicaSide::Local)->deleteNode(syncOp->affectedNode())) {
LOGW_SYNCPAL_WARN(_logger, L"Error in UpdateTree::deleteNode: node name="
- << Utility::formatSyncName(syncOp->affectedNode()->name()));
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" "
+ << exitInfo);
}
return exitInfo;
@@ -662,16 +671,17 @@ ExitInfo ExecutorWorker::generateCreateJob(SyncOpPtr syncOp, std::shared_ptraffectedNode()->name()));
+ LOGW_SYNCPAL_WARN(_logger, L"Failed to convert to placeholder for: "
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" "
+ << exitInfo);
return exitInfo;
}
#endif
uint64_t filesize = 0;
if (ExitInfo exitInfo = getFileSize(absoluteLocalFilePath, filesize); !exitInfo) {
- LOGW_SYNCPAL_WARN(_logger,
- L"Error in ExecutorWorker::getFileSize for " << Utility::formatSyncPath(absoluteLocalFilePath));
+ LOGW_SYNCPAL_WARN(_logger, L"Error in ExecutorWorker::getFileSize for "
+ << Utility::formatSyncPath(absoluteLocalFilePath) << L" " << exitInfo);
return exitInfo;
}
@@ -707,15 +717,14 @@ ExitInfo ExecutorWorker::generateCreateJob(SyncOpPtr syncOp, std::shared_ptrvfsMode() == VirtualFileMode::Mac || _syncPal->vfsMode() == VirtualFileMode::Win) {
// Set VFS callbacks
- std::function vfsSetPinStateCallback =
+ std::function vfsSetPinStateCallback =
std::bind(&SyncPal::vfsSetPinState, _syncPal, std::placeholders::_1, std::placeholders::_2);
job->setVfsSetPinStateCallback(vfsSetPinStateCallback);
- std::function
+ std::function
vfsUpdateMetadataCallback =
std::bind(&SyncPal::vfsUpdateMetadata, _syncPal, std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6);
+ std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
job->setVfsUpdateMetadataCallback(vfsUpdateMetadataCallback);
std::function vfsCancelHydrateCallback =
@@ -723,7 +732,7 @@ ExitInfo ExecutorWorker::generateCreateJob(SyncOpPtr syncOp, std::shared_ptrsetVfsCancelHydrateCallback(vfsCancelHydrateCallback);
}
- std::function vfsForceStatusCallback =
+ std::function vfsForceStatusCallback =
std::bind(&SyncPal::vfsForceStatus, _syncPal, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
std::placeholders::_4);
job->setVfsForceStatusCallback(vfsForceStatusCallback);
@@ -744,9 +753,9 @@ ExitInfo ExecutorWorker::checkLiteSyncInfoForCreate(SyncOpPtr syncOp, const Sync
bool isHydrated = false;
bool isSyncing = false;
int progress = 0;
- if (!_syncPal->vfsStatus(path, isPlaceholder, isHydrated, isSyncing, progress)) {
- LOGW_SYNCPAL_WARN(_logger, L"Error in vfsStatus: " << Utility::formatSyncPath(path));
- return {ExitCode::SystemError, ExitCause::FileAccessError};
+ if (ExitInfo exitInfo = _syncPal->vfsStatus(path, isPlaceholder, isHydrated, isSyncing, progress); !exitInfo) {
+ LOGW_SYNCPAL_WARN(_logger, L"Error in vfsStatus: " << Utility::formatSyncPath(path) << L" " << exitInfo);
+ return exitInfo;
}
if (isPlaceholder && !isHydrated && !isSyncing) {
@@ -766,29 +775,8 @@ ExitInfo ExecutorWorker::createPlaceholder(const SyncPath &relativeLocalPath) {
return {ExitCode::DataError, ExitCause::InvalidSnapshot};
}
- bool exists = false;
- IoError ioError = IoError::Success;
- SyncPath absoluteLocalPath = _syncPal->localPath() / relativeLocalPath;
- if (!IoHelper::checkIfPathExists(absoluteLocalPath, exists, ioError)) {
- LOGW_SYNCPAL_WARN(_logger,
- L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(absoluteLocalPath, ioError));
- return ExitCode::SystemError;
- }
-
- if (ioError == IoError::AccessDenied) {
- LOGW_WARN(_logger, L"Access denied to " << Path2WStr(absoluteLocalPath).c_str());
- return {ExitCode::SystemError, ExitCause::FileAccessError};
- }
-
- if (exists) {
- LOGW_WARN(_logger, L"Item already exists: " << Utility::formatSyncPath(absoluteLocalPath));
- return {ExitCode::DataError, ExitCause::FileAlreadyExist};
- }
-
- if (!_syncPal->vfsCreatePlaceholder(relativeLocalPath, syncItem)) {
- // TODO: vfs functions should output an ioError parameter
- // Check if the item already exists on local replica
- return processCreateOrConvertToPlaceholderError(relativeLocalPath, true);
+ if (ExitInfo exitInfo = _syncPal->vfsCreatePlaceholder(relativeLocalPath, syncItem); !exitInfo) {
+ return exitInfo;
}
return ExitCode::Ok;
@@ -815,10 +803,9 @@ ExitInfo ExecutorWorker::convertToPlaceholder(const SyncPath &relativeLocalPath,
LOGW_SYNCPAL_WARN(_logger, L"Error in IoHelper::getFileStat: " << Utility::formatIoError(absoluteLocalFilePath, ioError));
return ExitCode::SystemError;
}
-
if (ioError == IoError::NoSuchFileOrDirectory) {
LOGW_SYNCPAL_WARN(_logger, L"Item does not exist anymore: " << Utility::formatSyncPath(absoluteLocalFilePath));
- return {ExitCode::DataError, ExitCause::InvalidSnapshot};
+ return {ExitCode::SystemError, ExitCause::NotFound};
} else if (ioError == IoError::AccessDenied) {
LOGW_SYNCPAL_WARN(_logger, L"Item misses search permission: " << Utility::formatSyncPath(absoluteLocalFilePath));
return {ExitCode::SystemError, ExitCause::FileAccessError};
@@ -827,66 +814,20 @@ ExitInfo ExecutorWorker::convertToPlaceholder(const SyncPath &relativeLocalPath,
syncItem.setLocalNodeId(std::to_string(fileStat.inode));
#endif
- if (!_syncPal->vfsConvertToPlaceholder(absoluteLocalFilePath, syncItem)) {
- // TODO: vfs functions should output an ioError parameter
- // Check that the item exists on local replica
- return processCreateOrConvertToPlaceholderError(relativeLocalPath, false);
+ if (ExitInfo exitInfo = _syncPal->vfsConvertToPlaceholder(absoluteLocalFilePath, syncItem); !exitInfo) {
+ return exitInfo;
}
- if (!_syncPal->vfsSetPinState(absoluteLocalFilePath, hydrated ? PinState::AlwaysLocal : PinState::OnlineOnly)) {
- LOGW_SYNCPAL_WARN(_logger, L"Error in vfsSetPinState: " << Utility::formatSyncPath(absoluteLocalFilePath));
- return {ExitCode::SystemError, ExitCause::FileAccessError};
+ if (ExitInfo exitInfo =
+ _syncPal->vfsSetPinState(absoluteLocalFilePath, hydrated ? PinState::AlwaysLocal : PinState::OnlineOnly);
+ !exitInfo) {
+ LOGW_SYNCPAL_WARN(_logger, L"Error in vfsSetPinState: " << Utility::formatSyncPath(absoluteLocalFilePath) << exitInfo);
+ return exitInfo;
}
return ExitCode::Ok;
}
-ExitInfo ExecutorWorker::processCreateOrConvertToPlaceholderError(const SyncPath &relativeLocalPath, bool create) {
- // TODO: Simplify/remove this function when vfs functions will output an ioError parameter
- SyncPath absoluteLocalFilePath = _syncPal->localPath() / relativeLocalPath;
- bool exists = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfPathExists(absoluteLocalFilePath, exists, ioError)) {
- LOGW_SYNCPAL_WARN(_logger,
- L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(absoluteLocalFilePath, ioError));
- return ExitCode::SystemError;
- }
-
- if (ioError == IoError::AccessDenied) {
- LOGW_SYNCPAL_WARN(_logger, L"Item misses search permission: " << Utility::formatSyncPath(absoluteLocalFilePath));
- return {ExitCode::SystemError, ExitCause::FileAccessError};
- }
-
- if (create && exists) {
- return {ExitCode::SystemError, ExitCause::FileAccessError};
- } else if (!create && !exists) {
- return {ExitCode::DataError, ExitCause::InvalidSnapshot};
- }
-
- if (create) {
- // Check if the parent folder exists on local replica
- bool parentExists = false;
- if (!IoHelper::checkIfPathExists(absoluteLocalFilePath.parent_path(), parentExists, ioError)) {
- LOGW_WARN(_logger, L"Error in IoHelper::checkIfPathExists: "
- << Utility::formatIoError(absoluteLocalFilePath.parent_path(), ioError));
- return ExitCode::SystemError;
- }
-
- if (ioError == IoError::AccessDenied) {
- LOGW_WARN(_logger,
- L"Item misses search permission: " << Utility::formatSyncPath(absoluteLocalFilePath.parent_path()));
- return {ExitCode::SystemError, ExitCause::FileAccessError};
- }
-
- if (!parentExists) {
- return {ExitCode::DataError, ExitCause::InvalidSnapshot};
- }
- }
-
- return {ExitCode::SystemError, ExitCause::FileAccessError};
-}
-
-// !!! When returning with hasError == true, _executorExitCode and _executorExitCause must be set !!!
ExitInfo ExecutorWorker::handleEditOp(SyncOpPtr syncOp, std::shared_ptr &job, bool &ignored) {
// The execution of the edit operation consists of three steps:
// 1. If omit-flag is False, propagate the file to replicaY, replacing the existing one.
@@ -907,7 +848,7 @@ ExitInfo ExecutorWorker::handleEditOp(SyncOpPtr syncOp, std::shared_ptraffectedNode()->name())
+ << L" " << exitInfo);
return exitInfo;
}
}
@@ -969,20 +912,19 @@ ExitInfo ExecutorWorker::generateEditJob(SyncOpPtr syncOp, std::shared_ptr downloadJob = std::dynamic_pointer_cast(job);
if (_syncPal->vfsMode() == VirtualFileMode::Mac || _syncPal->vfsMode() == VirtualFileMode::Win) {
- std::function vfsSetPinStateCallback =
+ std::function vfsSetPinStateCallback =
std::bind(&SyncPal::vfsSetPinState, _syncPal, std::placeholders::_1, std::placeholders::_2);
downloadJob->setVfsSetPinStateCallback(vfsSetPinStateCallback);
- std::function vfsForceStatusCallback =
+ std::function vfsForceStatusCallback =
std::bind(&SyncPal::vfsForceStatus, _syncPal, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4);
downloadJob->setVfsForceStatusCallback(vfsForceStatusCallback);
- std::function
+ std::function
vfsUpdateMetadataCallback =
std::bind(&SyncPal::vfsUpdateMetadata, _syncPal, std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6);
+ std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
downloadJob->setVfsUpdateMetadataCallback(vfsUpdateMetadataCallback);
}
} else {
@@ -991,7 +933,8 @@ ExitInfo ExecutorWorker::generateEditJob(SyncOpPtr syncOp, std::shared_ptr uploadJob = std::dynamic_pointer_cast(job);
if (_syncPal->vfsMode() == VirtualFileMode::Mac || _syncPal->vfsMode() == VirtualFileMode::Win) {
- std::function vfsForceStatusCallback =
+ std::function vfsForceStatusCallback =
std::bind(&SyncPal::vfsForceStatus, _syncPal, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4);
uploadJob->setVfsForceStatusCallback(vfsForceStatusCallback);
@@ -1081,9 +1024,9 @@ ExitInfo ExecutorWorker::checkLiteSyncInfoForEdit(SyncOpPtr syncOp, const SyncPa
bool isHydrated = false;
bool isSyncingTmp = false;
int progress = 0;
- if (!_syncPal->vfsStatus(absolutePath, isPlaceholder, isHydrated, isSyncingTmp, progress)) {
- LOGW_SYNCPAL_WARN(_logger, L"Error in vfsStatus: " << Utility::formatSyncPath(absolutePath));
- return {ExitCode::SystemError, ExitCause::FileAccessError};
+ if (ExitInfo exitInfo = _syncPal->vfsStatus(absolutePath, isPlaceholder, isHydrated, isSyncingTmp, progress); !exitInfo) {
+ LOGW_SYNCPAL_WARN(_logger, L"Error in vfsStatus: " << Utility::formatSyncPath(absolutePath) << L": " << exitInfo);
+ return exitInfo;
}
if (syncOp->targetSide() == ReplicaSide::Remote) {
@@ -1116,17 +1059,15 @@ ExitInfo ExecutorWorker::checkLiteSyncInfoForEdit(SyncOpPtr syncOp, const SyncPa
}
case PinState::OnlineOnly: {
// Update metadata
- std::string error;
- _syncPal->vfsUpdateMetadata(
- absolutePath,
- syncOp->affectedNode()->createdAt().has_value() ? *syncOp->affectedNode()->createdAt() : 0,
- syncOp->affectedNode()->lastmodified().has_value() ? *syncOp->affectedNode()->lastmodified() : 0,
- syncOp->affectedNode()->size(),
- syncOp->affectedNode()->id().has_value() ? *syncOp->affectedNode()->id() : std::string(), error);
- // TODO: Vfs functions should return an ExitInfo struct
syncOp->setOmit(true); // Do not propagate change in file system, only in DB
- if (!error.empty()) {
- return {ExitCode::SystemError, ExitCause::FileAccessError};
+ if (ExitInfo exitInfo = _syncPal->vfsUpdateMetadata(
+ absolutePath,
+ syncOp->affectedNode()->createdAt().has_value() ? *syncOp->affectedNode()->createdAt() : 0,
+ syncOp->affectedNode()->lastmodified().has_value() ? *syncOp->affectedNode()->lastmodified() : 0,
+ syncOp->affectedNode()->size(),
+ syncOp->affectedNode()->id().has_value() ? *syncOp->affectedNode()->id() : std::string());
+ !exitInfo) {
+ return exitInfo;
}
break;
}
@@ -1180,12 +1121,14 @@ ExitInfo ExecutorWorker::handleMoveOp(SyncOpPtr syncOp, bool &ignored, bool &byp
}
if (ExitInfo exitInfo = propagateMoveToDbAndTree(syncOp); !exitInfo) {
- LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for "
- << Utility::formatSyncName(syncOp->affectedNode()->name()));
+ LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for: "
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" " << exitInfo);
return exitInfo;
}
} else {
if (ExitInfo exitInfo = generateMoveJob(syncOp, ignored, bypassProgressComplete); !exitInfo) {
+ LOGW_SYNCPAL_WARN(_logger, L"Failed to generate move job for: " << SyncName2WStr(syncOp->affectedNode()->name())
+ << L" " << exitInfo);
return exitInfo;
}
}
@@ -1291,12 +1234,12 @@ ExitInfo ExecutorWorker::generateMoveJob(SyncOpPtr syncOp, bool &ignored, bool &
// Set callbacks
if (_syncPal->vfsMode() == VirtualFileMode::Mac || _syncPal->vfsMode() == VirtualFileMode::Win) {
- std::function vfsForceStatusCallback =
+ std::function vfsForceStatusCallback =
std::bind(&SyncPal::vfsForceStatus, _syncPal, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4);
job->setVfsForceStatusCallback(vfsForceStatusCallback);
- std::function vfsStatusCallback =
+ std::function vfsStatusCallback =
std::bind(&SyncPal::vfsStatus, _syncPal, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
std::placeholders::_4, std::placeholders::_5);
job->setVfsStatusCallback(vfsStatusCallback);
@@ -1311,8 +1254,8 @@ ExitInfo ExecutorWorker::generateMoveJob(SyncOpPtr syncOp, bool &ignored, bool &
// Propagate changes to DB and update trees
std::shared_ptr newNode = nullptr;
if (ExitInfo exitInfo = propagateChangeToDbAndTree(syncOp, job, newNode); !exitInfo) {
- LOGW_WARN(_logger, L"Failed to propagate changes in DB or update tree for "
- << Utility::formatSyncName(syncOp->affectedNode()->name()));
+ LOGW_WARN(_logger, L"Failed to propagate changes in DB or update tree for: "
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" " << exitInfo);
return exitInfo;
}
@@ -1379,8 +1322,8 @@ ExitInfo ExecutorWorker::handleDeleteOp(SyncOpPtr syncOp, bool &ignored, bool &b
}
if (ExitInfo exitInfo = propagateDeleteToDbAndTree(syncOp); !exitInfo) {
- LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for "
- << Utility::formatSyncName(syncOp->affectedNode()->name()));
+ LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for: "
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" " << exitInfo);
return exitInfo;
}
} else {
@@ -1405,9 +1348,11 @@ ExitInfo ExecutorWorker::generateDeleteJob(SyncOpPtr syncOp, bool &ignored, bool
bool isHydrated = false;
bool isSyncing = false;
int progress = 0;
- if (!_syncPal->vfsStatus(absoluteLocalFilePath, isPlaceholder, isHydrated, isSyncing, progress)) {
- LOGW_SYNCPAL_WARN(_logger, L"Error in vfsStatus: " << Utility::formatSyncPath(absoluteLocalFilePath));
- return {ExitCode::SystemError, ExitCause::FileAccessError};
+ if (ExitInfo exitInfo = _syncPal->vfsStatus(absoluteLocalFilePath, isPlaceholder, isHydrated, isSyncing, progress);
+ !exitInfo) {
+ LOGW_SYNCPAL_WARN(
+ _logger, L"Error in vfsStatus: " << Utility::formatSyncPath(absoluteLocalFilePath) << L" : " << exitInfo);
+ return exitInfo;
}
isDehydratedPlaceholder = isPlaceholder && !isHydrated;
}
@@ -1685,14 +1630,13 @@ ExitInfo ExecutorWorker::handleFinishedJob(std::shared_ptr job, Syn
if (networkJob && (networkJob->getStatusCode() == Poco::Net::HTTPResponse::HTTP_FORBIDDEN ||
networkJob->getStatusCode() == Poco::Net::HTTPResponse::HTTP_CONFLICT)) {
if (ExitInfo exitInfo = handleForbiddenAction(syncOp, relativeLocalPath, ignored); !exitInfo) {
- LOGW_SYNCPAL_WARN(_logger,
- L"Error in handleForbiddenAction for item: " << Utility::formatSyncPath(relativeLocalPath));
+ LOGW_SYNCPAL_WARN(_logger, L"Error in handleForbiddenAction for item: "
+ << Utility::formatSyncPath(relativeLocalPath) << L" " << exitInfo);
return exitInfo;
}
} else if (!handleExecutorError(syncOp, {job->exitCode(), job->exitCause()})) {
// Cancel all queued jobs
- LOGW_SYNCPAL_WARN(_logger,
- L"Cancelling jobs. exit code: " << job->exitCode() << L" exit cause: " << job->exitCause());
+ LOGW_SYNCPAL_WARN(_logger, L"Cancelling jobs. " << ExitInfo(job->exitCode(), job->exitCause()));
cancelAllOngoingJobs();
return {job->exitCode(), job->exitCause()};
@@ -2413,8 +2357,8 @@ ExitInfo ExecutorWorker::runCreateDirJob(SyncOpPtr syncOp, std::shared_ptr newNode = nullptr;
if (ExitInfo exitInfo = propagateCreateToDbAndTree(syncOp, newNodeId, newModTime, newNode); !exitInfo) {
- LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for "
- << Utility::formatSyncName(syncOp->affectedNode()->name()));
+ LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for: "
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" " << exitInfo);
return exitInfo;
}
@@ -2519,7 +2463,7 @@ ExitInfo ExecutorWorker::getFileSize(const SyncPath &path, uint64_t &size) {
return ExitCode::Ok;
}
-ExitInfo ExecutorWorker::handleExecutorError(SyncOpPtr syncOp, ExitInfo opsExitInfo) {
+ExitInfo ExecutorWorker::handleExecutorError(SyncOpPtr syncOp, const ExitInfo &opsExitInfo) {
assert((syncOp && !opsExitInfo) && "syncOp is nullptr in ExecutorWorker::handleExecutorError");
if (!syncOp) {
LOG_WARN(_logger, "syncOp is nullptr in ExecutorWorker::handleExecutorError");
@@ -2529,15 +2473,18 @@ ExitInfo ExecutorWorker::handleExecutorError(SyncOpPtr syncOp, ExitInfo opsExitI
return opsExitInfo;
}
+ LOG_WARN(_logger, "Handling " << opsExitInfo << " in ExecutorWorker::handleExecutorError");
+
// Handle specific errors
switch (static_cast(opsExitInfo)) {
case static_cast(ExitInfo(ExitCode::SystemError, ExitCause::FileAccessError)): {
- return handleOpsFileAccessError(syncOp, opsExitInfo);
+ return handleOpsLocalFileAccessError(syncOp, opsExitInfo);
}
case static_cast(ExitInfo(ExitCode::SystemError, ExitCause::NotFound)): {
return handleOpsFileNotFound(syncOp, opsExitInfo);
}
case static_cast(ExitInfo(ExitCode::BackError, ExitCause::FileAlreadyExist)):
+ case static_cast(ExitInfo(ExitCode::SystemError, ExitCause::FileAlreadyExist)):
case static_cast(ExitInfo(ExitCode::DataError, ExitCause::FileAlreadyExist)): {
return handleOpsAlreadyExistError(syncOp, opsExitInfo);
}
@@ -2545,12 +2492,11 @@ ExitInfo ExecutorWorker::handleExecutorError(SyncOpPtr syncOp, ExitInfo opsExitI
break;
}
};
- LOG_WARN(_logger,
- "Unhandled error in ExecutorWorker::handleExecutorError: " << opsExitInfo.code() << " " << opsExitInfo.cause());
+ LOG_WARN(_logger, "Unhandled error in ExecutorWorker::handleExecutorError: " << opsExitInfo);
return opsExitInfo;
}
-ExitInfo ExecutorWorker::handleOpsFileAccessError(SyncOpPtr syncOp, ExitInfo opsExitInfo) {
+ExitInfo ExecutorWorker::handleOpsLocalFileAccessError(SyncOpPtr syncOp, const ExitInfo &opsExitInfo) {
std::shared_ptr localBlacklistedNode = nullptr;
std::shared_ptr remoteBlacklistedNode = nullptr;
if (syncOp->targetSide() == ReplicaSide::Local && syncOp->type() == OperationType::Create) {
@@ -2576,17 +2522,12 @@ ExitInfo ExecutorWorker::handleOpsFileAccessError(SyncOpPtr syncOp, ExitInfo ops
return removeDependentOps(localBlacklistedNode, remoteBlacklistedNode, syncOp->type());
}
-ExitInfo ExecutorWorker::handleOpsFileNotFound(SyncOpPtr syncOp, ExitInfo opsExitInfo) {
- if (syncOp->targetSide() != ReplicaSide::Remote) {
- LOGW_SYNCPAL_WARN(_logger, L"Unhandled target side for " << opsExitInfo << L": " << syncOp->targetSide());
- return opsExitInfo; // Unable to handle this error
- }
-
+ExitInfo ExecutorWorker::handleOpsFileNotFound(SyncOpPtr syncOp, [[maybe_unused]] const ExitInfo &opsExitInfo) {
_syncPal->setRestart(true);
return removeDependentOps(syncOp);
}
-ExitInfo ExecutorWorker::handleOpsAlreadyExistError(SyncOpPtr syncOp, ExitInfo opsExitInfo) {
+ExitInfo ExecutorWorker::handleOpsAlreadyExistError(SyncOpPtr syncOp, const ExitInfo &opsExitInfo) {
// If the file/directory already exist either on local or remote side, we blacklist it localy and the remote
// verson will be downloaded again.
@@ -2655,16 +2596,15 @@ ExitInfo ExecutorWorker::handleOpsAlreadyExistError(SyncOpPtr syncOp, ExitInfo o
if (ExitInfo exitInfo = PlatformInconsistencyCheckerUtility::renameLocalFile(
absoluteLocalPath, PlatformInconsistencyCheckerUtility::SuffixType::Blacklisted);
!exitInfo) {
- LOGW_WARN(_logger, L"Failed to blacklist file: " << Utility::formatSyncPath(absoluteLocalPath) << L" ExitCode::"
- << exitInfo.code() << L" ExitCause::" << exitInfo.cause());
+ LOGW_WARN(_logger, L"Failed to blacklist file: " << Utility::formatSyncPath(absoluteLocalPath) << L" " << exitInfo);
return ExitCode::DataError; // The synchronization will be re-started.
}
_syncPal->setRestart(true);
if (ExitInfo exitInfo = propagateDeleteToDbAndTree(syncOp); !exitInfo) {
- LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for "
- << Utility::formatSyncName(syncOp->affectedNode()->name()));
+ LOGW_SYNCPAL_WARN(_logger, L"Failed to propagate changes in DB or update tree for: "
+ << Utility::formatSyncName(syncOp->affectedNode()->name()) << L" " << exitInfo);
return exitInfo;
}
return removeDependentOps(syncOp);
diff --git a/src/libsyncengine/propagation/executor/executorworker.h b/src/libsyncengine/propagation/executor/executorworker.h
index aa42f5be8..82977cee4 100644
--- a/src/libsyncengine/propagation/executor/executorworker.h
+++ b/src/libsyncengine/propagation/executor/executorworker.h
@@ -81,7 +81,6 @@ class ExecutorWorker : public OperationProcessor {
ExitInfo checkLiteSyncInfoForCreate(SyncOpPtr syncOp, const SyncPath &path, bool &isDehydratedPlaceholder);
ExitInfo createPlaceholder(const SyncPath &relativeLocalPath);
ExitInfo convertToPlaceholder(const SyncPath &relativeLocalPath, bool hydrated);
- ExitInfo processCreateOrConvertToPlaceholderError(const SyncPath &relativeLocalPath, bool create);
ExitInfo handleEditOp(SyncOpPtr syncOp, std::shared_ptr &job, bool &ignored);
ExitInfo generateEditJob(SyncOpPtr syncOp, std::shared_ptr &job);
@@ -150,10 +149,10 @@ class ExecutorWorker : public OperationProcessor {
// This methode will return ExitCode::Ok if the error is safely managed and the executor can continue. Else, it will
// return opsExitInfo.
- ExitInfo handleExecutorError(SyncOpPtr syncOp, ExitInfo opsExitInfo);
- ExitInfo handleOpsFileAccessError(SyncOpPtr syncOp, ExitInfo opsExitInfo);
- ExitInfo handleOpsFileNotFound(SyncOpPtr syncOp, ExitInfo opsExitInfo);
- ExitInfo handleOpsAlreadyExistError(SyncOpPtr syncOp, ExitInfo opsExitInfo);
+ ExitInfo handleExecutorError(SyncOpPtr syncOp, const ExitInfo &opsExitInfo);
+ ExitInfo handleOpsLocalFileAccessError(SyncOpPtr syncOp, const ExitInfo &opsExitInfo);
+ ExitInfo handleOpsFileNotFound(SyncOpPtr syncOp, const ExitInfo &opsExitInfo);
+ ExitInfo handleOpsAlreadyExistError(SyncOpPtr syncOp, const ExitInfo &opsExitInfo);
ExitInfo removeDependentOps(SyncOpPtr syncOp);
ExitInfo removeDependentOps(std::shared_ptr localNode, std::shared_ptr remoteNode, OperationType opType);
diff --git a/src/libsyncengine/syncpal/syncpal.cpp b/src/libsyncengine/syncpal/syncpal.cpp
index 212a79a8f..37e4a1923 100644
--- a/src/libsyncengine/syncpal/syncpal.cpp
+++ b/src/libsyncengine/syncpal/syncpal.cpp
@@ -362,126 +362,120 @@ void SyncPal::addCompletedItem(int syncDbId, const SyncFileItem &item) {
}
bool SyncPal::vfsIsExcluded(const SyncPath &itemPath, bool &isExcluded) {
- if (!_vfsIsExcluded) {
+ if (!_vfs) {
return false;
}
-
- return _vfsIsExcluded(syncDbId(), itemPath, isExcluded);
+ isExcluded = _vfs->isExcluded(itemPath.native());
+ return true;
}
bool SyncPal::vfsExclude(const SyncPath &itemPath) {
- if (!_vfsExclude) {
+ if (!_vfs) {
return false;
}
-
- return _vfsExclude(syncDbId(), itemPath);
+ _vfs->exclude(itemPath);
+ return true;
}
bool SyncPal::vfsPinState(const SyncPath &itemPath, PinState &pinState) {
- if (!_vfsPinState) {
+ if (!_vfs) {
return false;
}
-
- return _vfsPinState(syncDbId(), itemPath, pinState);
+ pinState = _vfs->pinState(itemPath);
+ return true;
}
-bool SyncPal::vfsSetPinState(const SyncPath &itemPath, PinState pinState) {
- if (!_vfsSetPinState) {
- return false;
+ExitInfo SyncPal::vfsSetPinState(const SyncPath &itemPath, PinState pinState) {
+ if (!_vfs) {
+ return ExitCode::LogicError;
}
-
- return _vfsSetPinState(syncDbId(), itemPath, pinState);
+ return _vfs->setPinState(itemPath, pinState);
}
-bool SyncPal::vfsStatus(const SyncPath &itemPath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress) {
- if (!_vfsStatus) {
- return false;
+ExitInfo SyncPal::vfsStatus(const SyncPath &itemPath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress) {
+ if (!_vfs) {
+ return ExitCode::LogicError;
}
-
- return _vfsStatus(syncDbId(), itemPath, isPlaceholder, isHydrated, isSyncing, progress);
+ return _vfs->status(itemPath, isPlaceholder, isHydrated, isSyncing, progress);
}
-bool SyncPal::vfsCreatePlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item) {
- if (!_vfsCreatePlaceholder) {
- return false;
+ExitInfo SyncPal::vfsCreatePlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item) {
+ if (!_vfs) {
+ return ExitCode::LogicError;
}
-
- return _vfsCreatePlaceholder(syncDbId(), relativeLocalPath, item);
+ return _vfs->createPlaceholder(relativeLocalPath, item);
}
-bool SyncPal::vfsConvertToPlaceholder(const SyncPath &path, const SyncFileItem &item) {
- if (!_vfsConvertToPlaceholder) {
- return false;
+ExitInfo SyncPal::vfsConvertToPlaceholder(const SyncPath &path, const SyncFileItem &item) {
+ if (!_vfs) {
+ return ExitCode::LogicError;
}
-
- return _vfsConvertToPlaceholder(syncDbId(), path, item);
+ return _vfs->convertToPlaceholder(path, item);
}
-bool SyncPal::vfsUpdateMetadata(const SyncPath &path, const SyncTime &creationTime, const SyncTime &modtime, const int64_t size,
- const NodeId &id, std::string &error) {
- if (!_vfsUpdateMetadata) {
- return false;
+ExitInfo SyncPal::vfsUpdateMetadata(const SyncPath &path, const SyncTime &creationTime, const SyncTime &modtime,
+ const int64_t size, const NodeId &id) {
+ if (!_vfs) {
+ return ExitCode::LogicError;
}
-
- return _vfsUpdateMetadata(syncDbId(), path, creationTime, modtime, size, id, error);
+ return _vfs->updateMetadata(path, creationTime, modtime, size, id);
}
-bool SyncPal::vfsUpdateFetchStatus(const SyncPath &tmpPath, const SyncPath &path, int64_t received, bool &canceled,
- bool &finished) {
+ExitInfo SyncPal::vfsUpdateFetchStatus(const SyncPath &tmpPath, const SyncPath &path, int64_t received, bool &canceled,
+ bool &finished) {
if (ParametersCache::isExtendedLogEnabled()) {
LOGW_SYNCPAL_DEBUG(_logger, L"vfsUpdateFetchStatus: " << Utility::formatSyncPath(path) << L" received=" << received);
}
-
- if (!_vfsUpdateFetchStatus) {
- return false;
+ if (!_vfs) {
+ return ExitCode::LogicError;
}
-
- return _vfsUpdateFetchStatus(syncDbId(), tmpPath, path, received, canceled, finished);
+ return _vfs->updateFetchStatus(tmpPath.native(), path.native(), received, canceled, finished);
}
bool SyncPal::vfsFileStatusChanged(const SyncPath &path, SyncFileStatus status) {
- if (!_vfsFileStatusChanged) {
+ if (!_vfs) {
return false;
}
-
- return _vfsFileStatusChanged(syncDbId(), path, status);
+ return _vfs->fileStatusChanged(path, status);
}
-bool SyncPal::vfsForceStatus(const SyncPath &path, bool isSyncing, int progress, bool isHydrated) {
- if (!_vfsForceStatus) {
- return false;
+ExitInfo SyncPal::vfsForceStatus(const SyncPath &path, bool isSyncing, int progress, bool isHydrated) {
+ if (!_vfs) {
+ return ExitCode::LogicError;
}
-
- return _vfsForceStatus(syncDbId(), path, isSyncing, progress, isHydrated);
+ return _vfs->forceStatus(path, isSyncing, progress, isHydrated);
}
bool SyncPal::vfsCleanUpStatuses() {
- if (!_vfsCleanUpStatuses) {
+ if (!_vfs) {
return false;
}
-
- return _vfsCleanUpStatuses(syncDbId());
+ return _vfs->cleanUpStatuses();
}
bool SyncPal::vfsClearFileAttributes(const SyncPath &path) {
- if (!_vfsClearFileAttributes) {
+ if (!_vfs) {
return false;
}
-
- return _vfsClearFileAttributes(syncDbId(), path);
+ _vfs->clearFileAttributes(path);
+ return true;
}
bool SyncPal::vfsCancelHydrate(const SyncPath &path) {
- if (!_vfsCancelHydrate) {
+ if (!_vfs) {
return false;
}
-
- return _vfsCancelHydrate(syncDbId(), path);
+ _vfs->cancelHydrate(path);
+ return true;
}
bool SyncPal::wipeVirtualFiles() {
LOG_SYNCPAL_INFO(_logger, "Wiping virtual files");
- VirtualFilesCleaner virtualFileCleaner(localPath(), syncDbId(), _syncDb, _vfsStatus, _vfsClearFileAttributes);
+ if (!_vfs) {
+ addError(Error(syncDbId(), errId(), ExitCode::LogicError, ExitCause::Unknown));
+ return false;
+ }
+ VirtualFilesCleaner virtualFileCleaner(localPath(), _syncDb, _vfs);
if (!virtualFileCleaner.run()) {
LOG_SYNCPAL_WARN(_logger, "Error in VirtualFilesCleaner::run");
addError(Error(syncDbId(), errId(), virtualFileCleaner.exitCode(), virtualFileCleaner.exitCause()));
@@ -492,7 +486,7 @@ bool SyncPal::wipeVirtualFiles() {
bool SyncPal::wipeOldPlaceholders() {
LOG_SYNCPAL_INFO(_logger, "Wiping old placeholders files");
- VirtualFilesCleaner virtualFileCleaner(localPath(), syncDbId());
+ VirtualFilesCleaner virtualFileCleaner(localPath());
std::vector failedToRemovePlaceholders;
if (!virtualFileCleaner.removeDehydratedPlaceholders(failedToRemovePlaceholders)) {
LOG_SYNCPAL_WARN(_logger, "Error in VirtualFilesCleaner::removeDehydratedPlaceholders");
@@ -824,7 +818,7 @@ ExitCode SyncPal::addDlDirectJob(const SyncPath &relativePath, const SyncPath &l
if (vfsMode() == VirtualFileMode::Mac || vfsMode() == VirtualFileMode::Win) {
// Set callbacks
- std::function vfsUpdateFetchStatusCallback =
+ std::function vfsUpdateFetchStatusCallback =
std::bind(&SyncPal::vfsUpdateFetchStatus, this, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
job->setVfsUpdateFetchStatusCallback(vfsUpdateFetchStatusCallback);
@@ -832,20 +826,20 @@ ExitCode SyncPal::addDlDirectJob(const SyncPath &relativePath, const SyncPath &l
#ifdef __APPLE__
// Not done in Windows case: the pin state and the status must not be set by the download job because hydration could be
// asked for a move and so, the file place will change just after the dl.
- std::function vfsSetPinStateCallback =
+ std::function vfsSetPinStateCallback =
std::bind(&SyncPal::vfsSetPinState, this, std::placeholders::_1, std::placeholders::_2);
job->setVfsSetPinStateCallback(vfsSetPinStateCallback);
- std::function vfsForceStatusCallback =
+ std::function vfsForceStatusCallback =
std::bind(&SyncPal::vfsForceStatus, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
std::placeholders::_4);
job->setVfsForceStatusCallback(vfsForceStatusCallback);
#endif
- std::function
+ std::function
vfsUpdateMetadataCallback =
std::bind(&SyncPal::vfsUpdateMetadata, this, std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6);
+ std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
job->setVfsUpdateMetadataCallback(vfsUpdateMetadataCallback);
std::function vfsCancelHydrateCallback =
diff --git a/src/libsyncengine/syncpal/syncpal.h b/src/libsyncengine/syncpal/syncpal.h
index 47412c405..4e9a740f2 100644
--- a/src/libsyncengine/syncpal/syncpal.h
+++ b/src/libsyncengine/syncpal/syncpal.h
@@ -29,6 +29,7 @@
#include "reconciliation/syncoperation.h"
#include "libcommonserver/log/log.h"
#include "libcommon/utility/types.h"
+#include "libcommonserver/vfs.h"
#include "libparms/db/parmsdb.h"
#include
@@ -106,54 +107,17 @@ class SYNCENGINE_EXPORT SyncPal : public std::enable_shared_from_this {
virtual ~SyncPal();
ExitCode setTargetNodeId(const std::string &targetNodeId);
-
- inline void setAddErrorCallback(void (*addError)(const Error &)) { _addError = addError; }
- inline void setAddCompletedItemCallback(void (*addCompletedItem)(int, const SyncFileItem &, bool)) {
+ inline void setAddErrorCallback(const std::function &addError) { _addError = addError; }
+ inline void setAddCompletedItemCallback(const std::function &addCompletedItem) {
_addCompletedItem = addCompletedItem;
}
- inline void setSendSignalCallback(void (*sendSignal)(SignalNum, int, const SigValueType &)) { _sendSignal = sendSignal; }
- inline void setVfsIsExcludedCallback(bool (*vfsIsExcluded)(int, const SyncPath &, bool &)) {
- _vfsIsExcluded = vfsIsExcluded;
- }
- inline void setVfsExcludeCallback(bool (*vfsExclude)(int, const SyncPath &)) { _vfsExclude = vfsExclude; }
- inline void setVfsPinStateCallback(bool (*vfsPinState)(int, const SyncPath &, PinState &)) { _vfsPinState = vfsPinState; }
- inline void setVfsSetPinStateCallback(bool (*vfsSetPinState)(int, const SyncPath &, PinState)) {
- _vfsSetPinState = vfsSetPinState;
- }
- inline void setVfsStatusCallback(bool (*vfsStatus)(int, const SyncPath &, bool &, bool &, bool &, int &)) {
- _vfsStatus = vfsStatus;
- }
- inline void setVfsCreatePlaceholderCallback(bool (*vfsCreatePlaceholder)(int, const SyncPath &, const SyncFileItem &)) {
- _vfsCreatePlaceholder = vfsCreatePlaceholder;
- }
- inline void setVfsConvertToPlaceholderCallback(bool (*vfsConvertToPlaceholder)(int, const SyncPath &,
- const SyncFileItem &)) {
- _vfsConvertToPlaceholder = vfsConvertToPlaceholder;
- }
- inline void setVfsUpdateMetadataCallback(bool (*vfsUpdateMetadata)(int, const SyncPath &, const SyncTime &,
- const SyncTime &, const int64_t, const NodeId &,
- std::string &)) {
- _vfsUpdateMetadata = vfsUpdateMetadata;
- }
- inline void setVfsUpdateFetchStatusCallback(bool (*vfsUpdateFetchStatus)(int, const SyncPath &, const SyncPath &, int64_t,
- bool &, bool &)) {
- _vfsUpdateFetchStatus = vfsUpdateFetchStatus;
- }
- inline void setVfsFileStatusChangedCallback(bool (*vfsFileStatusChanged)(int, const SyncPath &, SyncFileStatus)) {
- _vfsFileStatusChanged = vfsFileStatusChanged;
- }
- inline void setVfsForceStatusCallback(bool (*vfsForceStatus)(int, const SyncPath &, bool, int, bool)) {
- _vfsForceStatus = vfsForceStatus;
- }
- inline void setVfsCleanUpStatusesCallback(bool (*vfsCleanUpStatuses)(int)) { _vfsCleanUpStatuses = vfsCleanUpStatuses; }
- inline void setVfsClearFileAttributesCallback(bool (*vfsClearFileAttributes)(int, const SyncPath &)) {
- _vfsClearFileAttributes = vfsClearFileAttributes;
- }
- inline void setVfsCancelHydrateCallback(bool (*vfsCancelHydrate)(int, const SyncPath &)) {
- _vfsCancelHydrate = vfsCancelHydrate;
+ inline void setSendSignalCallback(const std::function &sendSignal) {
+ _sendSignal = sendSignal;
}
+ inline void setVfsPtr(const std::shared_ptr &vfs) { _vfs = vfs; }
+
// SyncPalInfo
[[nodiscard]] inline std::shared_ptr syncDb() const { return _syncDb; }
inline const SyncPalInfo &syncInfo() const { return _syncInfo; }
@@ -214,16 +178,16 @@ class SYNCENGINE_EXPORT SyncPal : public std::enable_shared_from_this {
bool vfsIsExcluded(const SyncPath &itemPath, bool &isExcluded);
bool vfsExclude(const SyncPath &itemPath);
bool vfsPinState(const SyncPath &itemPath, PinState &pinState);
- bool vfsSetPinState(const SyncPath &itemPath, PinState pinState);
- bool vfsStatus(const SyncPath &itemPath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress);
- bool vfsCreatePlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item);
- bool vfsConvertToPlaceholder(const SyncPath &path, const SyncFileItem &item);
- bool vfsUpdateMetadata(const SyncPath &path, const SyncTime &creationTime, const SyncTime &modtime, const int64_t size,
- const NodeId &id, std::string &error);
- bool vfsUpdateFetchStatus(const SyncPath &tmpPath, const SyncPath &path, int64_t received, bool &canceled,
- bool &finished);
+ ExitInfo vfsSetPinState(const SyncPath &itemPath, PinState pinState);
+ ExitInfo vfsStatus(const SyncPath &itemPath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress);
+ ExitInfo vfsCreatePlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item);
+ ExitInfo vfsConvertToPlaceholder(const SyncPath &path, const SyncFileItem &item);
+ ExitInfo vfsUpdateMetadata(const SyncPath &path, const SyncTime &creationTime, const SyncTime &modtime,
+ const int64_t size, const NodeId &id);
+ ExitInfo vfsUpdateFetchStatus(const SyncPath &tmpPath, const SyncPath &path, int64_t received, bool &canceled,
+ bool &finished);
bool vfsFileStatusChanged(const SyncPath &path, SyncFileStatus status);
- bool vfsForceStatus(const SyncPath &path, bool isSyncing, int progress, bool isHydrated = false);
+ ExitInfo vfsForceStatus(const SyncPath &path, bool isSyncing, int progress, bool isHydrated = false);
bool vfsCleanUpStatuses();
bool vfsClearFileAttributes(const SyncPath &path);
bool vfsCancelHydrate(const SyncPath &path);
@@ -291,27 +255,10 @@ class SYNCENGINE_EXPORT SyncPal : public std::enable_shared_from_this {
std::mutex _directDownloadJobsMapMutex;
// Callbacks
- void (*_addError)(const Error &error){nullptr};
- void (*_addCompletedItem)(int syncDbId, const SyncFileItem &item, bool notify){nullptr};
- void (*_sendSignal)(SignalNum sigId, int syncDbId, const SigValueType &val){nullptr};
-
- bool (*_vfsIsExcluded)(int syncDbId, const SyncPath &itemPath, bool &isExcluded){nullptr};
- bool (*_vfsExclude)(int syncDbId, const SyncPath &itemPath){nullptr};
- bool (*_vfsPinState)(int syncDbId, const SyncPath &itemPath, PinState &pinState){nullptr};
- bool (*_vfsSetPinState)(int syncDbId, const SyncPath &itemPath, PinState pinState){nullptr};
- bool (*_vfsStatus)(int syncDbId, const SyncPath &itemPath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing,
- int &progress){nullptr};
- bool (*_vfsCreatePlaceholder)(int syncDbId, const SyncPath &relativeLocalPath, const SyncFileItem &item){nullptr};
- bool (*_vfsConvertToPlaceholder)(int syncDbId, const SyncPath &path, const SyncFileItem &item){nullptr};
- bool (*_vfsUpdateMetadata)(int syncDbId, const SyncPath &path, const SyncTime &creationTime, const SyncTime &modtime,
- const int64_t size, const NodeId &id, std::string &error){nullptr};
- bool (*_vfsUpdateFetchStatus)(int syncDbId, const SyncPath &tmpPath, const SyncPath &path, int64_t received,
- bool &canceled, bool &finished){nullptr};
- bool (*_vfsFileStatusChanged)(int syncDbId, const SyncPath &path, SyncFileStatus status){nullptr};
- bool (*_vfsForceStatus)(int syncDbId, const SyncPath &path, bool isSyncing, int progress, bool isHydrated){nullptr};
- bool (*_vfsCleanUpStatuses)(int syncDbId){nullptr};
- bool (*_vfsClearFileAttributes)(int syncDbId, const SyncPath &path){nullptr};
- bool (*_vfsCancelHydrate)(int syncDbId, const SyncPath &path){nullptr};
+ std::function _addError;
+ std::function _addCompletedItem;
+ std::function _sendSignal;
+ std::shared_ptr _vfs;
// DB
std::shared_ptr _syncDb{nullptr};
diff --git a/src/libsyncengine/syncpal/syncpalworker.cpp b/src/libsyncengine/syncpal/syncpalworker.cpp
index a1de7a259..303a1f617 100644
--- a/src/libsyncengine/syncpal/syncpalworker.cpp
+++ b/src/libsyncengine/syncpal/syncpalworker.cpp
@@ -574,8 +574,8 @@ bool SyncPalWorker::resetVfsFilesStatus() {
bool isHydrated = false;
bool isSyncing = false;
int progress = 0;
- if (!_syncPal->vfsStatus(dirIt->path(), isPlaceholder, isHydrated, isSyncing, progress)) {
- LOGW_SYNCPAL_WARN(_logger, L"Error in vfsStatus : " << Utility::formatSyncPath(dirIt->path()).c_str());
+ if (ExitInfo exitInfo = _syncPal->vfsStatus(dirIt->path(), isPlaceholder, isHydrated, isSyncing, progress); !exitInfo) {
+ LOGW_SYNCPAL_WARN(_logger, L"Error in vfsStatus : " << Utility::formatSyncPath(dirIt->path()) << L": " << exitInfo);
ok = false;
continue;
}
@@ -590,9 +590,9 @@ bool SyncPalWorker::resetVfsFilesStatus() {
if (isPlaceholder) {
if (isSyncing) {
// Force status to dehydrated
- if (!_syncPal->vfsForceStatus(dirIt->path(), false, 0, false)) {
- LOGW_SYNCPAL_WARN(_logger,
- L"Error in vfsForceStatus : " << Utility::formatSyncPath(dirIt->path()).c_str());
+ if (ExitInfo exitInfo = _syncPal->vfsForceStatus(dirIt->path(), false, 0, false); !exitInfo) {
+ LOGW_SYNCPAL_WARN(_logger, L"Error in vfsForceStatus : " << Utility::formatSyncPath(dirIt->path())
+ << L": " << exitInfo);
ok = false;
continue;
}
@@ -601,25 +601,25 @@ bool SyncPalWorker::resetVfsFilesStatus() {
// Fix pinstate if needed
if (isHydrated && pinState != PinState::AlwaysLocal) {
- if (!_syncPal->vfsSetPinState(dirIt->path(), PinState::AlwaysLocal)) {
+ if (ExitInfo exitInfo = _syncPal->vfsSetPinState(dirIt->path(), PinState::AlwaysLocal); !exitInfo) {
LOGW_SYNCPAL_WARN(_logger,
- L"Error in vfsSetPinState : " << Utility::formatSyncPath(dirIt->path()).c_str());
+ L"Error in vfsSetPinState : " << Utility::formatSyncPath(dirIt->path()) << exitInfo);
ok = false;
continue;
}
} else if (!isHydrated && pinState != PinState::OnlineOnly) {
- if (!_syncPal->vfsSetPinState(dirIt->path(), PinState::OnlineOnly)) {
+ if (ExitInfo exitInfo = _syncPal->vfsSetPinState(dirIt->path(), PinState::OnlineOnly); !exitInfo) {
LOGW_SYNCPAL_WARN(_logger,
- L"Error in vfsSetPinState : " << Utility::formatSyncPath(dirIt->path()).c_str());
+ L"Error in vfsSetPinState : " << Utility::formatSyncPath(dirIt->path()) << exitInfo);
ok = false;
continue;
}
}
} else {
if (pinState == PinState::AlwaysLocal || pinState == PinState::OnlineOnly) {
- if (!_syncPal->vfsSetPinState(dirIt->path(), PinState::Unspecified)) {
+ if (ExitInfo exitInfo = _syncPal->vfsSetPinState(dirIt->path(), PinState::Unspecified); !exitInfo) {
LOGW_SYNCPAL_WARN(_logger,
- L"Error in vfsSetPinState : " << Utility::formatSyncPath(dirIt->path()).c_str());
+ L"Error in vfsSetPinState : " << Utility::formatSyncPath(dirIt->path()) << exitInfo);
ok = false;
continue;
}
diff --git a/src/libsyncengine/syncpal/virtualfilescleaner.cpp b/src/libsyncengine/syncpal/virtualfilescleaner.cpp
index e98f1ed88..0326c0db9 100644
--- a/src/libsyncengine/syncpal/virtualfilescleaner.cpp
+++ b/src/libsyncengine/syncpal/virtualfilescleaner.cpp
@@ -30,19 +30,16 @@
namespace KDC {
-VirtualFilesCleaner::VirtualFilesCleaner(const SyncPath &path, int syncDbId, std::shared_ptr syncDb,
- bool (*vfsStatus)(int, const SyncPath &, bool &, bool &, bool &, int &),
- bool (*vfsClearFileAttributes)(int, const SyncPath &)) :
- _logger(Log::instance()->getLogger()), _rootPath(path), _syncDbId(syncDbId), _syncDb(syncDb), _vfsStatus(vfsStatus),
- _vfsClearFileAttributes(vfsClearFileAttributes) {}
+VirtualFilesCleaner::VirtualFilesCleaner(const SyncPath &path, std::shared_ptr syncDb, const std::shared_ptr &vfs) :
+ _logger(Log::instance()->getLogger()), _rootPath(path), _syncDb(syncDb), _vfs(vfs) {}
-VirtualFilesCleaner::VirtualFilesCleaner(const SyncPath &path, int syncDbId) :
- _logger(Log::instance()->getLogger()), _rootPath(path), _syncDbId(syncDbId) {}
+VirtualFilesCleaner::VirtualFilesCleaner(const SyncPath &path) :
+ _logger(Log::instance()->getLogger()), _rootPath(path) {}
bool VirtualFilesCleaner::run() {
// Clear xattr on root path
- assert(_vfsClearFileAttributes);
- _vfsClearFileAttributes(_syncDbId, _rootPath);
+ assert(_vfs);
+ _vfs->clearFileAttributes(_rootPath);
return removePlaceholdersRecursively(_rootPath);
}
@@ -91,11 +88,12 @@ bool VirtualFilesCleaner::removePlaceholdersRecursively(const SyncPath &parentPa
bool isHydrated = false;
bool isSyncing = false;
int progress = 0;
- assert(_vfsStatus);
- if (!_vfsStatus(_syncDbId, dirIt->path(), isPlaceholder, isHydrated, isSyncing, progress)) {
- LOGW_WARN(_logger, L"Error in vfsStatus for path=" << Path2WStr(dirIt->path()).c_str());
- _exitCode = ExitCode::SystemError;
- _exitCause = ExitCause::Unknown;
+ assert(_vfs);
+ if (ExitInfo exitInfo = _vfs->status(entryPathStr, isPlaceholder, isHydrated, isSyncing, progress);
+ !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsStatus for path=" << Path2WStr(dirIt->path()) << L": " << exitInfo);
+ _exitCode = exitInfo.code();
+ _exitCause = exitInfo.cause();
return false;
}
@@ -164,8 +162,8 @@ bool VirtualFilesCleaner::removePlaceholdersRecursively(const SyncPath &parentPa
}
// Clear xattr
- assert(_vfsClearFileAttributes);
- _vfsClearFileAttributes(_syncDbId, dirIt->path());
+ assert(_vfs);
+ _vfs->clearFileAttributes(entryPathStr);
}
} catch (std::filesystem::filesystem_error &e) {
LOG_WARN(_logger, "Error caught in VirtualFilesCleaner::removePlaceholdersRecursively: code=" << e.code()
diff --git a/src/libsyncengine/syncpal/virtualfilescleaner.h b/src/libsyncengine/syncpal/virtualfilescleaner.h
index 6c5e53db8..1f5a61d7e 100644
--- a/src/libsyncengine/syncpal/virtualfilescleaner.h
+++ b/src/libsyncengine/syncpal/virtualfilescleaner.h
@@ -19,6 +19,7 @@
#pragma once
#include "utility/types.h"
+#include "libcommonserver/vfs.h"
#include
@@ -28,11 +29,9 @@ class SyncDb;
class VirtualFilesCleaner {
public:
- VirtualFilesCleaner(const SyncPath &path, int syncDbId, std::shared_ptr syncDb,
- bool (*vfsStatus)(int, const SyncPath &, bool &, bool &, bool &, int &),
- bool (*vfsClearFileAttributes)(int, const SyncPath &));
+ VirtualFilesCleaner(const SyncPath &path, std::shared_ptr syncDb, const std::shared_ptr &vfs);
- VirtualFilesCleaner(const SyncPath &path, int syncDbId);
+ explicit VirtualFilesCleaner(const SyncPath &path);
bool run();
bool removeDehydratedPlaceholders(std::vector &failedToRemovePlaceholders);
@@ -48,11 +47,8 @@ class VirtualFilesCleaner {
log4cplus::Logger _logger;
SyncPath _rootPath;
- int _syncDbId{-1};
std::shared_ptr _syncDb = nullptr;
- bool (*_vfsStatus)(int syncDbId, const SyncPath &itemPath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing,
- int &progress) = nullptr;
- bool (*_vfsClearFileAttributes)(int syncDbId, const SyncPath &itemPath) = nullptr;
+ std::shared_ptr _vfs;
ExitCode _exitCode = ExitCode::Unknown;
ExitCause _exitCause = ExitCause::Unknown;
diff --git a/src/libsyncengine/update_detection/file_system_observer/localfilesystemobserverworker.cpp b/src/libsyncengine/update_detection/file_system_observer/localfilesystemobserverworker.cpp
index 8e2278677..8f975e49d 100644
--- a/src/libsyncengine/update_detection/file_system_observer/localfilesystemobserverworker.cpp
+++ b/src/libsyncengine/update_detection/file_system_observer/localfilesystemobserverworker.cpp
@@ -277,8 +277,10 @@ void LocalFileSystemObserverWorker::changesDetected(const std::listvfsStatus(absolutePath, isPlaceholder, isHydrated, isSyncing, progress)) {
- LOGW_SYNCPAL_WARN(_logger, L"Error in vfsStatus: " << Utility::formatSyncPath(absolutePath));
+ if (ExitInfo exitInfo = _syncPal->vfsStatus(absolutePath, isPlaceholder, isHydrated, isSyncing, progress);
+ !exitInfo) {
+ LOGW_SYNCPAL_WARN(_logger,
+ L"Error in vfsStatus: " << Utility::formatSyncPath(absolutePath) << L": " << exitInfo);
invalidateSnapshot();
return;
}
@@ -454,6 +456,7 @@ void LocalFileSystemObserverWorker::execute() {
break;
}
if (!_folderWatcher->exitInfo()) {
+ LOG_SYNCPAL_WARN(_logger, "Error in FolderWatcher: " << _folderWatcher->exitInfo());
exitCode = _folderWatcher->exitInfo().code();
setExitCause(_folderWatcher->exitInfo().cause());
invalidateSnapshot();
@@ -538,9 +541,9 @@ bool LocalFileSystemObserverWorker::canComputeChecksum(const SyncPath &absoluteP
bool isHydrated = false;
bool isSyncing = false;
int progress = 0;
- if (!_syncPal->vfsStatus(absolutePath, isPlaceholder, isHydrated, isSyncing, progress)) {
- LOGW_WARN(_logger, L"Error in vfsStatus: " << Utility::formatSyncPath(absolutePath));
- return false;
+ if (ExitInfo exitInfo = _syncPal->vfsStatus(absolutePath, isPlaceholder, isHydrated, isSyncing, progress); !exitInfo) {
+ LOGW_WARN(_logger, L"Error in vfsStatus: " << Utility::formatSyncPath(absolutePath) << L": " << exitInfo);
+ return exitInfo;
}
return !isPlaceholder || (isHydrated && !isSyncing);
diff --git a/src/libsyncengine/update_detection/update_detector/updatetree.cpp b/src/libsyncengine/update_detection/update_detector/updatetree.cpp
index db49eacb9..c3d724d4c 100644
--- a/src/libsyncengine/update_detection/update_detector/updatetree.cpp
+++ b/src/libsyncengine/update_detection/update_detector/updatetree.cpp
@@ -181,7 +181,7 @@ bool UpdateTree::updateNodeId(std::shared_ptr node, const NodeId &newId) {
}
if (ParametersCache::isExtendedLogEnabled() && newId != oldId) {
- LOGW_WARN(Log::instance()->getLogger(), _side << L" update tree: Node ID changed from '" << Utility::s2ws(oldId)
+ LOGW_DEBUG(Log::instance()->getLogger(), _side << L" update tree: Node ID changed from '" << Utility::s2ws(oldId)
<< L"' to '" << Utility::s2ws(newId) << L"' for node "
<< Utility::formatSyncName(node->name()) << L"'.");
}
diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt
index 77e26dd32..520936f22 100644
--- a/src/server/CMakeLists.txt
+++ b/src/server/CMakeLists.txt
@@ -38,8 +38,6 @@ endif()
set(server_SRCS
../libcommonserver/commserver.h ../libcommonserver/commserver.cpp
- ../libcommonserver/vfs.h ../libcommonserver/vfs.cpp
- ../libcommonserver/plugin.h ../libcommonserver/plugin.cpp
navigationpanehelper.h navigationpanehelper.cpp
logarchiver/logarchiver.h logarchiver/logarchiver.cpp
logarchiver/logarchiverhelper.h logarchiver/logarchiverhelper.cpp
diff --git a/src/server/appserver.cpp b/src/server/appserver.cpp
index 7791f6bf2..31b91645d 100644
--- a/src/server/appserver.cpp
+++ b/src/server/appserver.cpp
@@ -1109,11 +1109,13 @@ void AppServer::onRequestReceived(int id, RequestNum num, const QByteArray ¶
return;
}
- exitCode = tryCreateAndStartVfs(sync);
- const bool start = exitCode == ExitCode::Ok;
+ if (ExitInfo exitInfo = tryCreateAndStartVfs(sync); !exitInfo) {
+ LOG_WARN(_logger, "Error in tryCreateAndStartVfs for syncDbId=" << sync.dbId() << " " << exitInfo);
+ return;
+ }
// Create and start SyncPal
- exitCode = initSyncPal(sync, blackList, QSet(), whiteList, start, false, true);
+ exitCode = initSyncPal(sync, blackList, QSet(), whiteList, true, false, true);
if (exitCode != ExitCode::Ok) {
LOG_WARN(_logger, "Error in initSyncPal for syncDbId=" << syncInfo.dbId() << " code=" << exitCode);
addError(Error(errId(), exitCode, exitCause));
@@ -1198,11 +1200,13 @@ void AppServer::onRequestReceived(int id, RequestNum num, const QByteArray ¶
return;
}
- exitCode = tryCreateAndStartVfs(sync);
- const bool start = exitCode == ExitCode::Ok;
+ if (ExitInfo exitInfo = tryCreateAndStartVfs(sync); !exitInfo) {
+ LOG_WARN(_logger, "Error in tryCreateAndStartVfs for syncDbId=" << sync.dbId() << " " << exitInfo);
+ return;
+ }
// Create and start SyncPal
- exitCode = initSyncPal(sync, blackList, QSet(), whiteList, start, false, true);
+ exitCode = initSyncPal(sync, blackList, QSet(), whiteList, true, false, true);
if (exitCode != ExitCode::Ok) {
LOG_WARN(_logger, "Error in initSyncPal for syncDbId=" << sync.dbId() << " code=" << exitCode);
addError(Error(errId(), exitCode, exitCause));
@@ -1938,19 +1942,17 @@ void AppServer::onRequestReceived(int id, RequestNum num, const QByteArray ¶
QDataStream paramsStream(params);
paramsStream >> syncDbId;
paramsStream >> state;
-
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(_logger, "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- resultStream << ExitCode::DataError;
+ std::shared_ptr vfsPtr;
+ if (ExitInfo exitInfo = getVfsPtr(syncDbId, vfsPtr); !exitInfo) {
+ LOG_WARN(_logger, "Error in getVfsPtr for syncDbId=" << syncDbId << " " << exitInfo);
+ resultStream << exitInfo.code();
break;
}
-
- if (!_vfsMap[syncDbId]->setPinState(QString(), state)) {
- LOG_WARN(_logger, "Error in Vfs::setPinState for root directory");
- resultStream << ExitCode::SystemError;
+ if (const ExitInfo exitInfo = vfsPtr->setPinState("", state); !exitInfo) {
+ LOG_WARN(_logger, "Error in vfsSetPinState for syncDbId=" << syncDbId << " " << exitInfo);
+ resultStream << exitInfo.code();
break;
}
-
resultStream << ExitCode::Ok;
break;
}
@@ -2307,206 +2309,29 @@ void AppServer::sendSignal(SignalNum sigNum, int syncDbId, const SigValueType &v
CommServer::instance()->sendSignal(sigNum, params, id);
}
-bool AppServer::vfsIsExcluded(int syncDbId, const SyncPath &itemPath, bool &isExcluded) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
+ExitInfo AppServer::getVfsPtr(int syncDbId, std::shared_ptr &vfs) {
+ auto vfsMapIt = _vfsMap.find(syncDbId);
+ if (vfsMapIt == _vfsMap.end()) {
LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
+ return ExitCode::LogicError;
}
-
- isExcluded = _vfsMap[syncDbId]->isExcluded(SyncName2QStr(itemPath.native()));
-
- return true;
-}
-
-bool AppServer::vfsExclude(int syncDbId, const SyncPath &itemPath) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- _vfsMap[syncDbId]->exclude(SyncName2QStr(itemPath.native()));
-
- return true;
-}
-
-bool AppServer::vfsPinState(int syncDbId, const SyncPath &absolutePath, PinState &pinState) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- SyncPath relativePath = CommonUtility::relativePath(_syncPalMap[syncDbId]->localPath(), absolutePath);
- PinState tmpPinState = _vfsMap[syncDbId]->pinState(SyncName2QStr(relativePath.native()));
- pinState = (tmpPinState != PinState::Inherited) ? tmpPinState : PinState::Unspecified;
- return true;
-}
-
-bool AppServer::vfsSetPinState(int syncDbId, const SyncPath &itemPath, PinState pinState) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- SyncPath relativePath = CommonUtility::relativePath(_syncPalMap[syncDbId]->localPath(), itemPath);
- if (!_vfsMap[syncDbId]->setPinState(SyncName2QStr(relativePath.native()), pinState)) {
- LOGW_WARN(Log::instance()->getLogger(),
- L"Error in Vfs::setPinState for syncDbId=" << syncDbId << L" and path=" << Path2WStr(itemPath).c_str());
- return false;
- }
-
- return true;
-}
-
-bool AppServer::vfsStatus(int syncDbId, const SyncPath &itemPath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing,
- int &progress) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- return _vfsMap[syncDbId]->status(SyncName2QStr(itemPath.native()), isPlaceholder, isHydrated, isSyncing, progress);
-}
-
-bool AppServer::vfsCreatePlaceholder(int syncDbId, const SyncPath &relativeLocalPath, const SyncFileItem &item) {
- auto vfsIt = _vfsMap.find(syncDbId);
- if (vfsIt == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- if (vfsIt->second && !vfsIt->second->createPlaceholder(relativeLocalPath, item)) {
- LOGW_WARN(Log::instance()->getLogger(), L"Error in Vfs::createPlaceholder for syncDbId="
- << syncDbId << L" and path=" << Path2WStr(item.path()).c_str());
- return false;
- }
-
- return true;
-}
-
-bool AppServer::vfsConvertToPlaceholder(int syncDbId, const SyncPath &path, const SyncFileItem &item) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- if (!_vfsMap[syncDbId]->convertToPlaceholder(SyncName2QStr(path.native()), item)) {
- LOGW_WARN(Log::instance()->getLogger(), L"Error in Vfs::convertToPlaceholder for syncDbId="
- << syncDbId << L" and path=" << Path2WStr(item.path()).c_str());
- return false;
- }
-
- return true;
-}
-
-bool AppServer::vfsUpdateMetadata(int syncDbId, const SyncPath &path, const SyncTime &creationTime, const SyncTime &modtime,
- const int64_t size, const NodeId &id, std::string &error) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- const QByteArray fileId(id.c_str());
- QString errorStr;
- if (!_vfsMap[syncDbId]->updateMetadata(SyncName2QStr(path.native()), creationTime, modtime, size, fileId, &errorStr)) {
- LOGW_WARN(Log::instance()->getLogger(),
- L"Error in Vfs::updateMetadata for syncDbId=" << syncDbId << L" and path=" << Path2WStr(path).c_str());
- error = errorStr.toStdString();
- return false;
- }
-
- return true;
-}
-
-bool AppServer::vfsUpdateFetchStatus(int syncDbId, const SyncPath &tmpPath, const SyncPath &path, int64_t received,
- bool &canceled, bool &finished) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- if (!_vfsMap[syncDbId]->updateFetchStatus(SyncName2QStr(tmpPath), SyncName2QStr(path), received, canceled, finished)) {
- LOGW_WARN(Log::instance()->getLogger(),
- L"Error in Vfs::updateFetchStatus for syncDbId=" << syncDbId << L" and path=" << Path2WStr(path).c_str());
- return false;
+ if (!vfsMapIt->second) {
+ LOG_WARN(Log::instance()->getLogger(), "Vfs is null for syncDbId=" << syncDbId);
+ return ExitCode::LogicError;
}
-
- return true;
-}
-
-bool AppServer::vfsFileStatusChanged(int syncDbId, const SyncPath &path, SyncFileStatus status) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- if (!_vfsMap[syncDbId]->fileStatusChanged(SyncName2QStr(path.native()), status)) {
- LOGW_WARN(Log::instance()->getLogger(),
- L"Error in Vfs::fileStatusChanged for syncDbId=" << syncDbId << L" and path=" << Path2WStr(path).c_str());
- return false;
- }
-
- return true;
-}
-
-bool AppServer::vfsForceStatus(int syncDbId, const SyncPath &path, bool isSyncing, int progress, bool isHydrated) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- if (!_vfsMap[syncDbId]->forceStatus(SyncName2QStr(path.native()), isSyncing, progress, isHydrated)) {
- LOGW_WARN(Log::instance()->getLogger(),
- L"Error in Vfs::forceStatus for syncDbId=" << syncDbId << L" and path=" << Path2WStr(path).c_str());
- return false;
- }
-
- return true;
-}
-
-bool AppServer::vfsCleanUpStatuses(int syncDbId) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- if (!_vfsMap[syncDbId]->cleanUpStatuses()) {
- LOGW_WARN(Log::instance()->getLogger(), L"Error in Vfs::cleanUpStatuses for syncDbId=" << syncDbId);
- return false;
- }
-
- return true;
-}
-
-bool AppServer::vfsClearFileAttributes(int syncDbId, const SyncPath &path) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- _vfsMap[syncDbId]->clearFileAttributes(SyncName2QStr(path.native()));
-
- return true;
-}
-
-bool AppServer::vfsCancelHydrate(int syncDbId, const SyncPath &path) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
- return false;
- }
-
- _vfsMap[syncDbId]->cancelHydrate(SyncName2QStr(path.native()));
-
- return true;
+ vfs = vfsMapIt->second;
+ return ExitCode::Ok;
}
void AppServer::syncFileStatus(int syncDbId, const SyncPath &path, SyncFileStatus &status) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
+ auto syncPalMapIt = _syncPalMap.find(syncDbId);
+ if (syncPalMapIt == _syncPalMap.end()) {
+ LOG_WARN(Log::instance()->getLogger(), "SyncPal not found in SyncPalMap for syncDbId=" << syncDbId);
addError(Error(errId(), ExitCode::DataError, ExitCause::Unknown));
return;
}
- ExitCode exitCode = _syncPalMap[syncDbId]->fileStatus(ReplicaSide::Local, path, status);
+ ExitCode exitCode = syncPalMapIt->second->fileStatus(ReplicaSide::Local, path, status);
if (exitCode != ExitCode::Ok) {
LOG_WARN(Log::instance()->getLogger(), "Error in SyncPal::fileStatus for syncDbId=" << syncDbId);
addError(Error(errId(), exitCode, ExitCause::Unknown));
@@ -2514,13 +2339,14 @@ void AppServer::syncFileStatus(int syncDbId, const SyncPath &path, SyncFileStatu
}
void AppServer::syncFileSyncing(int syncDbId, const SyncPath &path, bool &syncing) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
+ auto syncPalMapIt = _syncPalMap.find(syncDbId);
+ if (syncPalMapIt == _syncPalMap.end()) {
+ LOG_WARN(Log::instance()->getLogger(), "SyncPal not found in SyncPalMap for syncDbId=" << syncDbId);
addError(Error(errId(), ExitCode::DataError, ExitCause::Unknown));
return;
}
- ExitCode exitCode = _syncPalMap[syncDbId]->fileSyncing(ReplicaSide::Local, path, syncing);
+ ExitCode exitCode = syncPalMapIt->second->fileSyncing(ReplicaSide::Local, path, syncing);
if (exitCode != ExitCode::Ok) {
LOG_WARN(Log::instance()->getLogger(), "Error in SyncPal::fileSyncing for syncDbId=" << syncDbId);
addError(Error(errId(), exitCode, ExitCause::Unknown));
@@ -2528,13 +2354,14 @@ void AppServer::syncFileSyncing(int syncDbId, const SyncPath &path, bool &syncin
}
void AppServer::setSyncFileSyncing(int syncDbId, const SyncPath &path, bool syncing) {
- if (_vfsMap.find(syncDbId) == _vfsMap.end()) {
- LOG_WARN(Log::instance()->getLogger(), "Vfs not found in vfsMap for syncDbId=" << syncDbId);
+ auto syncPalMapIt = _syncPalMap.find(syncDbId);
+ if (syncPalMapIt == _syncPalMap.end()) {
+ LOG_WARN(Log::instance()->getLogger(), "SyncPal not found in SyncPalMap for syncDbId=" << syncDbId);
addError(Error(errId(), ExitCode::DataError, ExitCause::Unknown));
return;
}
- ExitCode exitCode = _syncPalMap[syncDbId]->setFileSyncing(ReplicaSide::Local, path, syncing);
+ ExitCode exitCode = syncPalMapIt->second->setFileSyncing(ReplicaSide::Local, path, syncing);
if (exitCode != ExitCode::Ok) {
LOG_WARN(Log::instance()->getLogger(), "Error in SyncPal::setFileSyncing for syncDbId=" << syncDbId);
addError(Error(errId(), exitCode, ExitCause::Unknown));
@@ -2792,18 +2619,16 @@ std::string liteSyncActivationLogMessage(bool enabled, int syncDbId) {
}
// This function will pause the synchronization in case of errors.
-ExitCode AppServer::tryCreateAndStartVfs(Sync &sync) noexcept {
+ExitInfo AppServer::tryCreateAndStartVfs(Sync &sync) noexcept {
const std::string liteSyncMsg = liteSyncActivationLogMessage(sync.virtualFileMode() != VirtualFileMode::Off, sync.dbId());
LOG_INFO(_logger, liteSyncMsg.c_str());
-
- ExitCause exitCause = ExitCause::Unknown;
- const ExitCode exitCode = createAndStartVfs(sync, exitCause);
- if (exitCode != ExitCode::Ok) {
- LOG_WARN(_logger, "Error in createAndStartVfs for syncDbId=" << sync.dbId() << " code=" << exitCode << ", pausing.");
- addError(Error(sync.dbId(), errId(), exitCode, exitCause));
+ const ExitInfo exitInfo = createAndStartVfs(sync);
+ if (!exitInfo) {
+ LOG_WARN(_logger, "Error in createAndStartVfs for syncDbId=" << sync.dbId() << " " << exitInfo << ", pausing.");
+ addError(Error(sync.dbId(), errId(), exitInfo.code(), exitInfo.cause()));
}
- return exitCode;
+ return exitInfo;
}
ExitCode AppServer::startSyncs(User &user, ExitCause &exitCause) {
@@ -2886,8 +2711,12 @@ ExitCode AppServer::startSyncs(User &user, ExitCause &exitCause) {
continue;
}
- exitCode = tryCreateAndStartVfs(sync);
- const bool start = exitCode == ExitCode::Ok && !user.keychainKey().empty();
+ if (ExitInfo exitInfo = tryCreateAndStartVfs(sync); !exitInfo) {
+ LOG_WARN(_logger, "Error in tryCreateAndStartVfs for syncDbId=" << sync.dbId() << " " << exitInfo);
+ mainExitCode = exitInfo.code();
+ continue;
+ }
+ const bool start = !user.keychainKey().empty();
// Create and start SyncPal
exitCode = initSyncPal(sync, blackList, undecidedList, QSet(), start, false, false);
@@ -3501,20 +3330,13 @@ ExitCode AppServer::initSyncPal(const Sync &sync, const std::unordered_setsetAddCompletedItemCallback(&addCompletedItem);
_syncPalMap[sync.dbId()]->setSendSignalCallback(&sendSignal);
- _syncPalMap[sync.dbId()]->setVfsIsExcludedCallback(&vfsIsExcluded);
- _syncPalMap[sync.dbId()]->setVfsExcludeCallback(&vfsExclude);
- _syncPalMap[sync.dbId()]->setVfsPinStateCallback(&vfsPinState);
- _syncPalMap[sync.dbId()]->setVfsSetPinStateCallback(&vfsSetPinState);
- _syncPalMap[sync.dbId()]->setVfsStatusCallback(&vfsStatus);
- _syncPalMap[sync.dbId()]->setVfsCreatePlaceholderCallback(&vfsCreatePlaceholder);
- _syncPalMap[sync.dbId()]->setVfsConvertToPlaceholderCallback(&vfsConvertToPlaceholder);
- _syncPalMap[sync.dbId()]->setVfsUpdateMetadataCallback(&vfsUpdateMetadata);
- _syncPalMap[sync.dbId()]->setVfsUpdateFetchStatusCallback(&vfsUpdateFetchStatus);
- _syncPalMap[sync.dbId()]->setVfsFileStatusChangedCallback(&vfsFileStatusChanged);
- _syncPalMap[sync.dbId()]->setVfsForceStatusCallback(&vfsForceStatus);
- _syncPalMap[sync.dbId()]->setVfsCleanUpStatusesCallback(&vfsCleanUpStatuses);
- _syncPalMap[sync.dbId()]->setVfsClearFileAttributesCallback(&vfsClearFileAttributes);
- _syncPalMap[sync.dbId()]->setVfsCancelHydrateCallback(&vfsCancelHydrate);
+ std::shared_ptr vfsPtr;
+ if (ExitInfo exitInfo = getVfsPtr(sync.dbId(), vfsPtr); !exitInfo) {
+ LOG_WARN(_logger, "Error in getVfsPtr for syncDbId=" << sync.dbId() << " " << exitInfo);
+ return exitInfo.code();
+ }
+
+ _syncPalMap[sync.dbId()]->setVfsPtr(vfsPtr);
if (blackList != std::unordered_set()) {
// Set blackList (create or overwrite the possible existing list in DB)
@@ -3620,20 +3442,18 @@ ExitCode AppServer::stopSyncPal(int syncDbId, bool pausedByUser, bool quit, bool
return ExitCode::Ok;
}
-ExitCode AppServer::createAndStartVfs(const Sync &sync, ExitCause &exitCause) noexcept {
+ExitInfo AppServer::createAndStartVfs(const Sync &sync) noexcept {
// Check that the sync folder exists.
bool exists = false;
IoError ioError = IoError::Success;
if (!IoHelper::checkIfPathExists(sync.localPath(), exists, ioError)) {
LOGW_WARN(_logger, L"Error in IoHelper::checkIfPathExists " << Utility::formatIoError(sync.localPath(), ioError).c_str());
- exitCause = ExitCause::Unknown;
return ExitCode::SystemError;
}
if (!exists) {
LOGW_WARN(_logger, L"Sync localpath " << Utility::formatSyncPath(sync.localPath()).c_str() << L" doesn't exist.");
- exitCause = ExitCause::SyncDirDoesntExist;
- return ExitCode::SystemError;
+ return {ExitCode::SystemError, ExitCause::SyncDirDoesntExist};
}
if (_vfsMap.find(sync.dbId()) == _vfsMap.end()) {
@@ -3642,37 +3462,31 @@ ExitCode AppServer::createAndStartVfs(const Sync &sync, ExitCause &exitCause) no
bool found;
if (!ParmsDb::instance()->selectDrive(sync.driveDbId(), drive, found)) {
LOG_WARN(_logger, "Error in ParmsDb::selectDrive");
- exitCause = ExitCause::DbAccessError;
- return ExitCode::DbError;
+ return {ExitCode::DbError, ExitCause::DbAccessError};
}
if (!found) {
LOG_WARN(_logger, "Drive not found in drive table for driveDbId=" << sync.driveDbId());
- exitCause = ExitCause::DbEntryNotFound;
- return ExitCode::DataError;
+ return {ExitCode::DataError, ExitCause::DbEntryNotFound};
}
Account account;
if (!ParmsDb::instance()->selectAccount(drive.accountDbId(), account, found)) {
LOG_WARN(_logger, "Error in ParmsDb::selectAccount");
- exitCause = ExitCause::DbAccessError;
- return ExitCode::DbError;
+ return {ExitCode::DbError, ExitCause::DbAccessError};
}
if (!found) {
LOG_WARN(_logger, "Account not found in account table for accountDbId=" << drive.accountDbId());
- exitCause = ExitCause::DbEntryNotFound;
- return ExitCode::DataError;
+ return {ExitCode::DataError, ExitCause::DbEntryNotFound};
}
User user;
if (!ParmsDb::instance()->selectUser(account.userDbId(), user, found)) {
LOG_WARN(_logger, "Error in ParmsDb::selectUser");
- exitCause = ExitCause::DbAccessError;
- return ExitCode::DbError;
+ return {ExitCode::DbError, ExitCause::DbAccessError};
}
if (!found) {
LOG_WARN(_logger, "User not found in user table for userDbId=" << account.userDbId());
- exitCause = ExitCause::DbEntryNotFound;
- return ExitCode::DataError;
+ return {ExitCode::DataError, ExitCause::DbEntryNotFound};
}
#endif
@@ -3693,8 +3507,7 @@ ExitCode AppServer::createAndStartVfs(const Sync &sync, ExitCause &exitCause) no
if (!vfsPtr) {
LOG_WARN(_logger, "Error in Vfs::createVfsFromPlugin for mode " << sync.virtualFileMode() << " : "
<< error.toStdString().c_str());
- exitCause = ExitCause::UnableToCreateVfs;
- return ExitCode::SystemError;
+ return {ExitCode::SystemError, ExitCause::UnableToCreateVfs};
}
_vfsMap[sync.dbId()] = vfsPtr;
_vfsMap[sync.dbId()]->setExtendedLog(ParametersCache::isExtendedLogEnabled());
@@ -3709,7 +3522,8 @@ ExitCode AppServer::createAndStartVfs(const Sync &sync, ExitCause &exitCause) no
}
// Start VFS
- if (!_vfsMap[sync.dbId()]->start(_vfsInstallationDone, _vfsActivationDone, _vfsConnectionDone)) {
+ if (ExitInfo exitInfo = _vfsMap[sync.dbId()]->start(_vfsInstallationDone, _vfsActivationDone, _vfsConnectionDone);
+ !exitInfo) {
#ifdef Q_OS_MAC
if (sync.virtualFileMode() == VirtualFileMode::Mac) {
if (_vfsInstallationDone && !_vfsActivationDone) {
@@ -3724,16 +3538,14 @@ ExitCode AppServer::createAndStartVfs(const Sync &sync, ExitCause &exitCause) no
LOG_WARN(_logger, "LiteSync extension is not enabled or doesn't have full disk access: "
<< liteSyncExtErrorDescr.c_str());
}
- exitCause = ExitCause::LiteSyncNotAllowed;
- return ExitCode::SystemError;
+ return {ExitCode::SystemError, ExitCause::LiteSyncNotAllowed};
}
}
}
#endif
- LOG_WARN(_logger, "Error in Vfs::start");
- exitCause = ExitCause::UnableToCreateVfs;
- return ExitCode::SystemError;
+ LOG_WARN(_logger, "Error in Vfs::start " << exitInfo);
+ return exitInfo;
}
#ifdef Q_OS_WIN
@@ -3757,13 +3569,11 @@ ExitCode AppServer::createAndStartVfs(const Sync &sync, ExitCause &exitCause) no
bool found = false;
if (!ParmsDb::instance()->updateSync(tmpSync, found)) {
LOG_WARN(_logger, "Error in ParmsDb::updateSync");
- exitCause = ExitCause::DbAccessError;
- return ExitCode::DbError;
+ return {ExitCode::DbError, ExitCause::DbAccessError};
}
if (!found) {
LOG_WARN(_logger, "Sync not found in sync table for syncDbId=" << tmpSync.dbId());
- exitCause = ExitCause::DbEntryNotFound;
- return ExitCode::DataError;
+ return {ExitCode::DataError, ExitCause::DbEntryNotFound};
}
#endif
return ExitCode::Ok;
@@ -3865,8 +3675,10 @@ ExitCode AppServer::setSupportsVirtualFiles(int syncDbId, bool value) {
// Delete previous vfs
_vfsMap.erase(syncDbId);
- exitCode = tryCreateAndStartVfs(sync);
- const bool start = exitCode == ExitCode::Ok;
+ if (ExitInfo exitInfo = tryCreateAndStartVfs(sync); !exitInfo) {
+ LOG_WARN(_logger, "Error in tryCreateAndStartVfs " << exitInfo);
+ return exitInfo;
+ }
QTimer::singleShot(100, this, [=]() {
if (newMode != VirtualFileMode::Off) {
@@ -3883,9 +3695,7 @@ ExitCode AppServer::setSupportsVirtualFiles(int syncDbId, bool value) {
sendVfsConversionCompleted(sync.dbId());
// Re-start sync
- if (start) {
- _syncPalMap[syncDbId]->start();
- }
+ _syncPalMap[syncDbId]->start();
});
}
@@ -4352,8 +4162,10 @@ void AppServer::onRestartSyncs() {
sendErrorsCleared(syncPalMapElt.first);
// Start VFS
- if (!_vfsMap[syncPalMapElt.first]->start(_vfsInstallationDone, _vfsActivationDone, _vfsConnectionDone)) {
- LOG_WARN(Log::instance()->getLogger(), "Error in Vfs::start");
+ if (ExitInfo exitInfo =
+ _vfsMap[syncPalMapElt.first]->start(_vfsInstallationDone, _vfsActivationDone, _vfsConnectionDone);
+ !exitInfo) {
+ LOG_WARN(Log::instance()->getLogger(), "Error in Vfs::start: " << exitInfo);
continue;
}
diff --git a/src/server/appserver.h b/src/server/appserver.h
index 44fd4dd05..3bd60e24a 100644
--- a/src/server/appserver.h
+++ b/src/server/appserver.h
@@ -140,9 +140,9 @@ class AppServer : public SharedTools::QtSingleApplication {
bool firstInit = false);
ExitCode stopSyncPal(int syncDbId, bool pausedByUser = false, bool quit = false, bool clear = false);
- ExitCode createAndStartVfs(const Sync &sync, ExitCause &exitCause) noexcept;
+ ExitInfo createAndStartVfs(const Sync &sync) noexcept;
// Call createAndStartVfs. Issue warnings, errors and pause the synchronization `sync` if needed.
- [[nodiscard]] ExitCode tryCreateAndStartVfs(Sync &sync) noexcept;
+ [[nodiscard]] ExitInfo tryCreateAndStartVfs(Sync &sync) noexcept;
ExitCode stopVfs(int syncDbId, bool unregister);
ExitCode setSupportsVirtualFiles(int syncDbId, bool value);
@@ -195,23 +195,7 @@ class AppServer : public SharedTools::QtSingleApplication {
static void addCompletedItem(int syncDbId, const SyncFileItem &item, bool notify);
static void sendSignal(SignalNum sigNum, int syncDbId, const SigValueType &val);
- static bool vfsIsExcluded(int syncDbId, const SyncPath &itemPath, bool &isExcluded);
- static bool vfsExclude(int syncDbId, const SyncPath &itemPath);
- static bool vfsPinState(int syncDbId, const SyncPath &absolutePath, PinState &pinState);
- static bool vfsSetPinState(int syncDbId, const SyncPath &itemPath, PinState pinState);
- static bool vfsStatus(int syncDbId, const SyncPath &itemPath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing,
- int &progress);
- static bool vfsCreatePlaceholder(int syncDbIdconst, const SyncPath &relativeLocalPath, const SyncFileItem &item);
- static bool vfsConvertToPlaceholder(int syncDbId, const SyncPath &path, const SyncFileItem &item);
- static bool vfsUpdateMetadata(int syncDbId, const SyncPath &path, const SyncTime &creationTime, const SyncTime &modtime,
- const int64_t size, const NodeId &id, std::string &error);
- static bool vfsUpdateFetchStatus(int syncDbId, const SyncPath &tmpPath, const SyncPath &path, int64_t received,
- bool &canceled, bool &finished);
- static bool vfsFileStatusChanged(int syncDbId, const SyncPath &path, SyncFileStatus status);
- static bool vfsForceStatus(int syncDbId, const SyncPath &path, bool isSyncing, int progress, bool isHydrated = false);
- static bool vfsCleanUpStatuses(int syncDbId);
- static bool vfsClearFileAttributes(int syncDbId, const SyncPath &path);
- static bool vfsCancelHydrate(int syncDbId, const SyncPath &path);
+ static ExitInfo getVfsPtr(int syncDbId, std::shared_ptr &vfs);
static void syncFileStatus(int syncDbId, const KDC::SyncPath &path, KDC::SyncFileStatus &status);
static void syncFileSyncing(int syncDbId, const KDC::SyncPath &path, bool &syncing);
@@ -255,6 +239,4 @@ class AppServer : public SharedTools::QtSingleApplication {
signals:
void socketApiExecuteCommandDirect(const QString &commandLine);
};
-
-
} // namespace KDC
diff --git a/src/server/socketapi.cpp b/src/server/socketapi.cpp
index 22bc2469e..371452c78 100644
--- a/src/server/socketapi.cpp
+++ b/src/server/socketapi.cpp
@@ -92,7 +92,8 @@ struct ListenerHasSocketPred {
SocketApi::SocketApi(const std::unordered_map> &syncPalMap,
const std::unordered_map> &vfsMap, QObject *parent) :
- QObject(parent), _syncPalMap(syncPalMap), _vfsMap(vfsMap) {
+ QObject(parent),
+ _syncPalMap(syncPalMap), _vfsMap(vfsMap) {
QString socketPath;
if (OldUtility::isWindows()) {
@@ -442,7 +443,7 @@ bool SocketApi::syncFileStatus(const FileData &fileData, KDC::SyncFileStatus &st
if (vfsMapIt->second->mode() == KDC::VirtualFileMode::Mac || vfsMapIt->second->mode() == KDC::VirtualFileMode::Win) {
bool isSyncing = false;
- if (!vfsMapIt->second->status(fileData.localPath, isPlaceholder, isHydrated, isSyncing, progress)) {
+ if (!vfsMapIt->second->status(QStr2Path(fileData.localPath), isPlaceholder, isHydrated, isSyncing, progress)) {
LOGW_WARN(KDC::Log::instance()->getLogger(),
L"Error in Vfs::status - " << Utility::formatPath(fileData.localPath).c_str());
return false;
@@ -477,24 +478,22 @@ std::unordered_map>::const_iterator SocketApi::re
return result;
}
-bool SocketApi::setPinState(const FileData &fileData, KDC::PinState pinState) {
- if (!fileData.syncDbId) return false;
+ExitInfo SocketApi::setPinState(const FileData &fileData, KDC::PinState pinState) {
+ if (!fileData.syncDbId) return {ExitCode::LogicError, ExitCause::InvalidArgument};
const auto vfsMapIt = retrieveVfsMapIt(fileData.syncDbId);
- if (vfsMapIt == _vfsMap.cend()) return false;
-
- vfsMapIt->second->setPinState(fileData.relativePath, pinState);
+ if (vfsMapIt == _vfsMap.cend()) return {ExitCode::SystemError, ExitCause::LiteSyncNotAllowed};
- return true;
+ return vfsMapIt->second->setPinState(QStr2Path(fileData.relativePath), pinState);
}
-bool SocketApi::dehydratePlaceholder(const FileData &fileData) {
- if (!fileData.syncDbId) return false;
+ExitInfo SocketApi::dehydratePlaceholder(const FileData &fileData) {
+ if (!fileData.syncDbId) return {ExitCode::LogicError, ExitCause::InvalidArgument};
const auto vfsMapIt = retrieveVfsMapIt(fileData.syncDbId);
- if (vfsMapIt == _vfsMap.cend()) return false;
+ if (vfsMapIt == _vfsMap.cend()) return {ExitCode::SystemError, ExitCause::LiteSyncNotAllowed};
- return vfsMapIt->second->dehydratePlaceholder(fileData.relativePath);
+ return vfsMapIt->second->dehydratePlaceholder(QStr2Path(fileData.relativePath));
}
bool SocketApi::addDownloadJob(const FileData &fileData) {
@@ -697,16 +696,16 @@ void SocketApi::command_MAKE_ONLINE_ONLY_DIRECT(const QString &filesArg, SocketL
}
// Set pin state
- if (!setPinState(fileData, KDC::PinState::OnlineOnly)) {
+ if (ExitInfo exitInfo = setPinState(fileData, KDC::PinState::OnlineOnly); !exitInfo) {
LOGW_INFO(KDC::Log::instance()->getLogger(),
- L"Error in SocketApi::setPinState - " << Utility::formatSyncPath(filePath).c_str());
+ L"Error in SocketApi::setPinState - " << Utility::formatSyncPath(filePath) << L": " << exitInfo);
continue;
}
// Dehydrate placeholder
- if (!dehydratePlaceholder(fileData)) {
+ if (ExitInfo exitInfo = dehydratePlaceholder(fileData); !exitInfo) {
LOGW_INFO(KDC::Log::instance()->getLogger(),
- L"Error in SocketApi::dehydratePlaceholder - " << Utility::formatSyncPath(filePath).c_str());
+ L"Error in SocketApi::dehydratePlaceholder - " << Utility::formatSyncPath(filePath) << exitInfo);
continue;
}
@@ -759,7 +758,7 @@ void SocketApi::command_CANCEL_HYDRATION_DIRECT(const QString &filesArg) {
auto vfsMapIt = retrieveVfsMapIt(fileData.syncDbId);
if (vfsMapIt == _vfsMap.cend()) continue;
- vfsMapIt->second->cancelHydrate(filePath);
+ vfsMapIt->second->cancelHydrate(QStr2Path(filePath));
}
#endif
}
@@ -918,7 +917,7 @@ void SocketApi::command_SET_THUMBNAIL(const QString &filePath) {
LOG_DEBUG(KDC::Log::instance()->getLogger(), "Thumbnail fetched - size=" << pixmap.width() << "x" << pixmap.height());
// Set thumbnail
- if (!vfsMapIt->second->setThumbnail(fileData.localPath, pixmap)) {
+ if (!vfsMapIt->second->setThumbnail(QStr2Path(fileData.localPath), pixmap)) {
LOGW_WARN(KDC::Log::instance()->getLogger(), L"Error in setThumbnail - " << Utility::formatPath(filePath).c_str());
return;
}
@@ -1095,7 +1094,7 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, SocketListener *
bool isHydrated = false;
bool isSyncing = false;
int progress = 0;
- if (!canCancelHydration && vfsMapIt->second->status(file, isPlaceholder, isHydrated, isSyncing, progress) &&
+ if (!canCancelHydration && vfsMapIt->second->status(QStr2Path(file), isPlaceholder, isHydrated, isSyncing, progress) &&
isSyncing) {
canCancelHydration = syncPalMapIt->second->isDownloadOngoing(QStr2Path(file));
}
@@ -1151,7 +1150,7 @@ void SocketApi::manageActionsOnSingleFile(SocketListener *listener, const QStrin
if (fileData.localPath.isEmpty()) {
return;
}
- bool isExcluded = vfsMapIt->second->isExcluded(fileData.localPath);
+ bool isExcluded = vfsMapIt->second->isExcluded(QStr2Path(fileData.localPath));
if (isExcluded) {
return;
}
diff --git a/src/server/socketapi.h b/src/server/socketapi.h
index 7c78e4bdd..f468e0c2b 100644
--- a/src/server/socketapi.h
+++ b/src/server/socketapi.h
@@ -172,8 +172,8 @@ class SocketApi : public QObject {
void processFileList(const QStringList &inFileList, std::list &outFileList);
bool syncFileStatus(const FileData &fileData, KDC::SyncFileStatus &status, bool &isPlaceholder, bool &isHydrated,
int &progress);
- bool setPinState(const FileData &fileData, KDC::PinState pinState);
- bool dehydratePlaceholder(const FileData &fileData);
+ ExitInfo setPinState(const FileData &fileData, KDC::PinState pinState);
+ ExitInfo dehydratePlaceholder(const FileData &fileData);
bool addDownloadJob(const FileData &fileData);
bool cancelDownloadJobs(int syncDbId, const QStringList &fileList);
diff --git a/src/server/vfs/mac/CMakeLists.txt b/src/server/vfs/mac/CMakeLists.txt
index c4c46e0c4..0cd70b5a7 100644
--- a/src/server/vfs/mac/CMakeLists.txt
+++ b/src/server/vfs/mac/CMakeLists.txt
@@ -4,8 +4,6 @@ find_package(Qt6)
add_library("${libsyncengine_NAME}_vfs_mac" SHARED
vfs_mac.h vfs_mac.cpp
litesyncextconnector.h litesyncextconnector.mm
- ../../../libcommonserver/vfs.h ../../../libcommonserver/vfs.cpp
- ../../../libcommonserver/plugin.h ../../../libcommonserver/plugin.cpp
../../../common/filepermissionholder.h ../../../common/filepermissionholder.cpp
../../../common/filesystembase.h ../../../common/filesystembase.cpp
)
diff --git a/src/server/vfs/mac/litesyncextconnector.h b/src/server/vfs/mac/litesyncextconnector.h
index 177bd4fc6..6e4b706ea 100644
--- a/src/server/vfs/mac/litesyncextconnector.h
+++ b/src/server/vfs/mac/litesyncextconnector.h
@@ -77,7 +77,7 @@ class LiteSyncExtConnector {
};
bool vfsSetAppExcludeList(const QString &appList);
bool vfsGetFetchingAppList(QHash &appTable);
- bool vfsUpdateMetadata(const QString &absoluteFilePath, const struct stat *fileStat, QString *error);
+ bool vfsUpdateMetadata(const QString &absoluteFilePath, const struct stat *fileStat);
bool vfsIsExcluded(const QString &path);
bool vfsProcessDirStatus(const QString &path, const QString &localSyncPath);
void vfsClearFileAttributes(const QString &path);
diff --git a/src/server/vfs/mac/litesyncextconnector.mm b/src/server/vfs/mac/litesyncextconnector.mm
index 717529d6c..95205b224 100644
--- a/src/server/vfs/mac/litesyncextconnector.mm
+++ b/src/server/vfs/mac/litesyncextconnector.mm
@@ -1292,12 +1292,11 @@ bool checkIoErrorAndLogIfNeeded(IoError ioError, const std::string &itemType, co
return _private->getFetchingAppList(appTable);
}
-bool LiteSyncExtConnector::vfsUpdateMetadata(const QString &absoluteFilePath, const struct stat *fileStat, QString *error) {
+bool LiteSyncExtConnector::vfsUpdateMetadata(const QString &absoluteFilePath, const struct stat *fileStat) {
FilePermissionHolder permHolder(absoluteFilePath);
if (!fileStat) {
LOG_WARN(_logger, "Bad parameters");
- *error = QObject::tr("Bad parameters");
return false;
}
@@ -1323,7 +1322,6 @@ bool checkIoErrorAndLogIfNeeded(IoError ioError, const std::string &itemType, co
fd = open(stdPath.c_str(), FWRITE);
if (fd == -1) {
LOGW_WARN(_logger, L"Call to open failed - " << Utility::formatPath(absoluteFilePath).c_str() << L" errno=" << errno);
- *error = QObject::tr("Call to open failed - path=%1").arg(absoluteFilePath);
return false;
}
}
@@ -1331,13 +1329,11 @@ bool checkIoErrorAndLogIfNeeded(IoError ioError, const std::string &itemType, co
if (ftruncate(fd, fileStat->st_size) == -1) {
LOGW_WARN(_logger,
L"Call to ftruncate failed - " << Utility::formatPath(absoluteFilePath).c_str() << L" errno=" << errno);
- *error = QObject::tr("Call to ftruncate failed - path=%1").arg(absoluteFilePath);
return false;
}
if (close(fd) == -1) {
LOGW_WARN(_logger, L"Call to close failed - " << Utility::formatPath(absoluteFilePath).c_str() << L" errno=" << errno);
- *error = QObject::tr("Call to close failed - path=%1").arg(absoluteFilePath);
return false;
}
diff --git a/src/server/vfs/mac/vfs_mac.cpp b/src/server/vfs/mac/vfs_mac.cpp
index b9b680d86..2b698c2be 100644
--- a/src/server/vfs/mac/vfs_mac.cpp
+++ b/src/server/vfs/mac/vfs_mac.cpp
@@ -30,10 +30,7 @@
#include
namespace KDC {
-
-const int s_nb_threads[NB_WORKERS] = {5, 5};
-
-VfsMac::VfsMac(KDC::VfsSetupParams &vfsSetupParams, QObject *parent) :
+VfsMac::VfsMac(const VfsSetupParams &vfsSetupParams, QObject *parent) :
Vfs(vfsSetupParams, parent), _localSyncPath{Path2QStr(_vfsSetupParams._localPath)} {
// Initialize LiteSync ext connector
LOG_INFO(logger(), "Initialize LiteSyncExtConnector");
@@ -47,59 +44,19 @@ VfsMac::VfsMac(KDC::VfsSetupParams &vfsSetupParams, QObject *parent) :
throw std::runtime_error("Unable to initialize LiteSyncExtConnector.");
}
- // Start hydration/dehydration workers
- // !!! Disabled for testing because no QEventLoop !!!
- if (qApp) {
- // Start worker threads
- for (int i = 0; i < NB_WORKERS; i++) {
- for (int j = 0; j < s_nb_threads[i]; j++) {
- QtLoggingThread *workerThread = new QtLoggingThread();
- _workerInfo[i]._threadList.append(workerThread);
- Worker *worker = new Worker(this, i, j, logger());
- worker->moveToThread(workerThread);
- connect(workerThread, &QThread::started, worker, &Worker::start);
- connect(workerThread, &QThread::finished, worker, &QObject::deleteLater);
- connect(workerThread, &QThread::finished, workerThread, &QObject::deleteLater);
- workerThread->start();
- }
- }
- }
-}
-
-VfsMac::~VfsMac() {
- // Ask worker threads to stop
- for (int i = 0; i < NB_WORKERS; i++) {
- _workerInfo[i]._mutex.lock();
- _workerInfo[i]._stop = true;
- _workerInfo[i]._mutex.unlock();
- _workerInfo[i]._queueWC.wakeAll();
- }
-
- // Force threads to stop if needed
- for (int i = 0; i < NB_WORKERS; i++) {
- for (QThread *thread: qAsConst(_workerInfo[i]._threadList)) {
- if (thread) {
- thread->quit();
- if (!thread->wait(1000)) {
- thread->terminate();
- thread->wait();
- }
- }
- }
- }
+ starVfsWorkers();
}
-
VirtualFileMode VfsMac::mode() const {
return VirtualFileMode::Mac;
}
-bool VfsMac::startImpl(bool &installationDone, bool &activationDone, bool &connectionDone) {
+ExitInfo VfsMac::startImpl(bool &installationDone, bool &activationDone, bool &connectionDone) {
LOG_DEBUG(logger(), "startImpl - syncDbId=" << _vfsSetupParams._syncDbId);
if (!_connector) {
LOG_WARN(logger(), "LiteSyncExtConnector not initialized!");
- return false;
+ return ExitCode::LogicError;
}
if (!installationDone) {
@@ -108,21 +65,21 @@ bool VfsMac::startImpl(bool &installationDone, bool &activationDone, bool &conne
installationDone = _connector->install(activationDone);
if (!installationDone) {
LOG_WARN(logger(), "Error in LiteSyncExtConnector::install!");
- return false;
+ return {ExitCode::SystemError, ExitCause::UnableToCreateVfs};
}
}
if (!activationDone) {
LOG_INFO(logger(), "LiteSync extension activation pending");
connectionDone = false;
- return false;
+ return {ExitCode::SystemError, ExitCause::UnableToCreateVfs};
}
if (!connectionDone) {
connectionDone = _connector->connect();
if (!connectionDone) {
LOG_WARN(logger(), "Error in LiteSyncExtConnector::connect!");
- return false;
+ return {ExitCode::SystemError, ExitCause::UnableToCreateVfs};
}
}
@@ -137,7 +94,7 @@ bool VfsMac::startImpl(bool &installationDone, bool &activationDone, bool &conne
if (!_connector->vfsStart(_vfsSetupParams._syncDbId, folderPath, isPlaceholder, isSyncing)) {
LOG_WARN(logger(), "Error in vfsStart!");
resetLiteSyncConnector();
- return false;
+ return {ExitCode::SystemError, ExitCause::UnableToCreateVfs};
}
QStringList filesToFix;
@@ -163,10 +120,10 @@ bool VfsMac::startImpl(bool &installationDone, bool &activationDone, bool &conne
ok = false;
}
}
- return ok;
+ return ok ? ExitInfo(ExitCode::Ok) : ExitInfo(ExitCode::SystemError, ExitCause::UnableToCreateVfs);
}
- return true;
+ return ExitCode::Ok;
}
void VfsMac::stopImpl(bool unregister) {
@@ -210,39 +167,33 @@ void VfsMac::hydrate(const QString &path) {
_setSyncFileSyncing(_vfsSetupParams._syncDbId, QStr2Path(relativePath), false);
}
-bool VfsMac::forceStatus(const QString &path, bool isSyncing, int progress, bool isHydrated /*= false*/) {
- SyncPath stdPath = QStr2Path(path);
-
- bool exists = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfPathExists(stdPath, exists, ioError)) {
- LOGW_WARN(logger(), L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(stdPath, ioError).c_str());
- return false;
+ExitInfo VfsMac::forceStatus(const SyncPath &pathStd, bool isSyncing, int progress, bool isHydrated /*= false*/) {
+ const QString path = SyncName2QStr(pathStd.native());
+ if (ExitInfo exitInfo = checkIfPathExists(pathStd, true); !exitInfo) {
+ return exitInfo;
}
- if (!exists) {
- // New file
- return true;
+ if (!_connector->vfsSetStatus(path, _localSyncPath, isSyncing, progress, isHydrated)) {
+ LOG_WARN(logger(), "Error in vfsSetStatus!");
+ return handleVfsError(pathStd);
}
- return _connector->vfsSetStatus(path, _localSyncPath, isSyncing, progress, isHydrated);
+ return ExitCode::Ok;
}
bool VfsMac::cleanUpStatuses() {
return _connector->vfsCleanUpStatuses(_localSyncPath);
}
-void VfsMac::clearFileAttributes(const QString &path) {
+void VfsMac::clearFileAttributes(const SyncPath &pathStd) {
+ QString path = SyncName2QStr(pathStd.native());
_connector->vfsClearFileAttributes(path);
}
-bool VfsMac::isHydrating() const {
- return false;
-}
-
-bool VfsMac::updateMetadata(const QString &absoluteFilePath, time_t creationTime, time_t modtime, qint64 size,
- const QByteArray &fileId, QString *error) {
- Q_UNUSED(fileId);
+ExitInfo VfsMac::updateMetadata(const SyncPath &absoluteFilePathStd, time_t creationTime, time_t modtime, int64_t size,
+ const NodeId &fileIdStr) {
+ Q_UNUSED(fileIdStr);
+ const QString absoluteFilePath = SyncName2QStr(absoluteFilePathStd.native());
if (extendedLog()) {
LOGW_DEBUG(logger(), L"updateMetadata - " << Utility::formatPath(absoluteFilePath).c_str());
@@ -250,7 +201,7 @@ bool VfsMac::updateMetadata(const QString &absoluteFilePath, time_t creationTime
if (!_connector) {
LOG_WARN(logger(), "LiteSyncExtConnector not initialized!");
- return false;
+ return ExitCode::LogicError;
}
struct stat fileStat;
@@ -260,29 +211,30 @@ bool VfsMac::updateMetadata(const QString &absoluteFilePath, time_t creationTime
fileStat.st_birthtimespec = {creationTime, 0};
fileStat.st_mode = S_IFREG;
- if (!_connector->vfsUpdateMetadata(absoluteFilePath, &fileStat, error)) {
+ if (!_connector->vfsUpdateMetadata(absoluteFilePath, &fileStat)) {
LOG_WARN(logger(), "Error in vfsUpdateMetadata!");
- return false;
+ return handleVfsError(QStr2Path(absoluteFilePath));
}
- return true;
+ return ExitCode::Ok;
}
-bool VfsMac::createPlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item) {
+ExitInfo VfsMac::createPlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item) {
if (extendedLog()) {
LOGW_DEBUG(logger(), L"createPlaceholder - file = " << Utility::formatSyncPath(relativeLocalPath).c_str());
}
- SyncPath fullPath(_vfsSetupParams._localPath / relativeLocalPath);
- std::error_code ec;
- if (std::filesystem::exists(fullPath, ec)) {
- LOGW_WARN(logger(), L"File/directory " << Utility::formatSyncPath(relativeLocalPath).c_str() << L" already exists!");
- return false;
+ if (relativeLocalPath.empty()) {
+ LOG_WARN(logger(), "VfsMac::createPlaceholder - relativeLocalPath cannot be empty.");
+ return {ExitCode::SystemError, ExitCause::InvalidArgument};
}
- if (ec) {
- LOGW_WARN(logger(), L"Failed to check if path exists " << Utility::formatStdError(fullPath, ec).c_str());
- return false;
+ SyncPath fullPath(_vfsSetupParams._localPath / relativeLocalPath);
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath, false); !exitInfo) {
+ return exitInfo;
+ }
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath.parent_path(), true); !exitInfo) {
+ return exitInfo;
}
// Create placeholder
@@ -299,29 +251,21 @@ bool VfsMac::createPlaceholder(const SyncPath &relativeLocalPath, const SyncFile
if (!_connector->vfsCreatePlaceHolder(QString::fromStdString(relativeLocalPath.native()), _localSyncPath, &fileStat)) {
LOG_WARN(logger(), "Error in vfsCreatePlaceHolder!");
- return false;
+ return defaultVfsError(); // handleVfsError is not suitable here, the file dosen't exist but we don't want to return
+ // NotFound as this make no sense in the context of a create
}
- return true;
+ return ExitCode::Ok;
}
-bool VfsMac::dehydratePlaceholder(const QString &path) {
+ExitInfo VfsMac::dehydratePlaceholder(const SyncPath &path) {
if (extendedLog()) {
- LOGW_DEBUG(logger(), L"dehydratePlaceholder - file " << Utility::formatPath(path).c_str());
+ LOGW_DEBUG(logger(), L"dehydratePlaceholder - file " << Utility::formatSyncPath(path));
}
- SyncPath fullPath(_vfsSetupParams._localPath / QStr2Path(path));
- std::error_code ec;
- if (!std::filesystem::exists(fullPath, ec)) {
- if (ec.value() != 0) {
- LOGW_WARN(logger(), L"Failed to check if path exists " << Utility::formatSyncPath(fullPath).c_str() << L": "
- << KDC::Utility::s2ws(ec.message()).c_str() << L" ("
- << ec.value() << L")");
- return false;
- }
- // File doesn't exist
- LOG_WARN(logger(), "File doesn't exist!");
- return false;
+ SyncPath fullPath(_vfsSetupParams._localPath / path.native());
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath, true); !exitInfo) {
+ return exitInfo;
}
// Check if the file is a placeholder
@@ -331,25 +275,32 @@ bool VfsMac::dehydratePlaceholder(const QString &path) {
int progress;
if (!_connector->vfsGetStatus(QString::fromStdString(fullPath.native()), isPlaceholder, isHydrated, isSyncing, progress)) {
LOG_WARN(logger(), "Error in vfsGetStatus!");
- return false;
+ return handleVfsError(fullPath);
+ }
+
+ if (!isPlaceholder) {
+ // Not a placeholder
+ LOGW_WARN(logger(), L"Not a placeholder: " << Utility::formatSyncPath(fullPath).c_str());
+ return {ExitCode::SystemError, ExitCause::NotPlaceHolder};
}
if (isHydrated) {
- LOGW_DEBUG(logger(), L"Dehydrate file with " << Utility::formatPath(path).c_str());
+ LOGW_DEBUG(logger(), L"Dehydrate file with " << Utility::formatSyncPath(fullPath));
dehydrate(QString::fromStdString(fullPath.string()));
}
- return true;
+ return ExitCode::Ok;
}
-bool VfsMac::convertToPlaceholder(const QString &path, const SyncFileItem &item) {
+ExitInfo VfsMac::convertToPlaceholder(const SyncPath &pathStd, const SyncFileItem &item) {
+ const QString path = SyncName2QStr(pathStd.native());
if (extendedLog()) {
LOGW_DEBUG(logger(), L"convertToPlaceholder - " << Utility::formatPath(path).c_str());
}
if (path.isEmpty()) {
LOG_WARN(logger(), "Invalid parameters");
- return false;
+ return {ExitCode::SystemError, ExitCause::NotFound};
}
SyncPath fullPath(QStr2Path(path));
@@ -361,14 +312,14 @@ bool VfsMac::convertToPlaceholder(const QString &path, const SyncFileItem &item)
int progress;
if (!_connector->vfsGetStatus(path, isPlaceholder, isHydrated, isSyncing, progress)) {
LOG_WARN(logger(), "Error in vfsGetStatus!");
- return false;
+ return handleVfsError(fullPath);
}
if (!isPlaceholder) {
// Convert to placeholder
if (!_connector->vfsConvertToPlaceHolder(QDir::toNativeSeparators(path), !item.dehydrated())) {
LOG_WARN(logger(), "Error in vfsConvertToPlaceHolder!");
- return false;
+ return handleVfsError(fullPath);
}
// If item is a directory, also convert items inside it
@@ -376,19 +327,19 @@ bool VfsMac::convertToPlaceholder(const QString &path, const SyncFileItem &item)
if (!IoHelper::getItemType(fullPath, itemType)) {
LOGW_WARN(KDC::Log::instance()->getLogger(),
L"Error in IoHelper::getItemType : " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ return ExitCode::SystemError;
}
if (itemType.ioError == IoError::NoSuchFileOrDirectory) {
LOGW_DEBUG(KDC::Log::instance()->getLogger(),
L"Item does not exist anymore : " << Utility::formatSyncPath(fullPath).c_str());
- return true;
+ return {ExitCode::SystemError, ExitCause::NotFound};
}
if (itemType.ioError == IoError::AccessDenied) {
LOGW_DEBUG(KDC::Log::instance()->getLogger(),
L"Item misses search permission : " << Utility::formatSyncPath(fullPath).c_str());
- return true;
+ return {ExitCode::SystemError, ExitCause::FileAccessError};
}
const bool isLink = itemType.linkType != LinkType::None;
@@ -398,7 +349,7 @@ bool VfsMac::convertToPlaceholder(const QString &path, const SyncFileItem &item)
if (!isDirectory && itemType.ioError != IoError::Success) {
LOGW_WARN(logger(), L"Failed to check if the path is a directory: "
<< Utility::formatIoError(fullPath, itemType.ioError).c_str());
- return false;
+ return ExitCode::SystemError;
}
}
@@ -407,7 +358,7 @@ bool VfsMac::convertToPlaceholder(const QString &path, const SyncFileItem &item)
}
}
- return true;
+ return ExitCode::Ok;
}
void VfsMac::convertDirContentToPlaceholder(const QString &dirPath, bool isHydratedIn) {
@@ -496,25 +447,24 @@ void VfsMac::resetLiteSyncConnector() {
}
}
-bool VfsMac::updateFetchStatus(const QString &tmpPath, const QString &path, qint64 received, bool &canceled, bool &finished) {
+ExitInfo VfsMac::updateFetchStatus(const SyncPath &tmpPathStd, const SyncPath &pathStd, int64_t received, bool &canceled,
+ bool &finished) {
+ QString tmpPath = SyncName2QStr(tmpPathStd.native());
+ QString path = SyncName2QStr(pathStd.native());
if (extendedLog()) {
LOGW_INFO(logger(), L"updateFetchStatus file " << Utility::formatPath(path).c_str() << L" - " << received);
}
- if (tmpPath.isEmpty() || path.isEmpty()) {
+ if (tmpPath.isEmpty()) {
LOG_WARN(logger(), "Invalid parameters");
- return false;
+ return ExitCode::SystemError;
}
std::filesystem::path fullPath(QStr2Path(path));
- std::error_code ec;
- if (!std::filesystem::exists(fullPath, ec)) {
- if (ec.value() != 0) {
- LOGW_WARN(logger(), L"Failed to check if path exists : " << Utility::formatSyncPath(fullPath).c_str() << L": "
- << Utility::s2ws(ec.message()).c_str() << L" (" << ec.value()
- << L")");
- return false;
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath, true); !exitInfo) {
+ if (exitInfo == ExitInfo(ExitCode::SystemError, ExitCause::NotFound)) {
+ return ExitCode::Ok;
}
- return true;
+ return exitInfo;
}
// Check if the file is a placeholder
@@ -524,37 +474,27 @@ bool VfsMac::updateFetchStatus(const QString &tmpPath, const QString &path, qint
int progress = 0;
if (!_connector->vfsGetStatus(Path2QStr(fullPath), isPlaceholder, isHydrated, isSyncing, progress)) {
LOG_WARN(logger(), "Error in vfsGetStatus!");
- return false;
+ return handleVfsError(fullPath);
}
+ finished = false;
std::filesystem::path tmpFullPath(QStr2Path(tmpPath));
- auto updateFct = [=, this](bool &canceled, bool &finished, bool &error) {
- // Update download progress
- finished = false;
- if (!_connector->vfsUpdateFetchStatus(Path2QStr(tmpFullPath), Path2QStr(fullPath), _localSyncPath,
- static_cast(received), canceled, finished)) {
- LOG_WARN(logger(), "Error in vfsUpdateFetchStatus!");
- error = true;
- return;
- }
-
- if (finished) {
- // Do nothing
- }
- };
-
- // Launch update in a separate thread
- bool error = false;
- updateFct(canceled, finished, error);
+ if (!_connector->vfsUpdateFetchStatus(Path2QStr(tmpFullPath), Path2QStr(fullPath), _localSyncPath,
+ static_cast(received), canceled, finished)) {
+ LOG_WARN(logger(), "Error in vfsUpdateFetchStatus!");
+ return handleVfsError(fullPath);
+ }
- return !error;
+ return ExitCode::Ok;
}
-void VfsMac::cancelHydrate(const QString &filePath) {
+void VfsMac::cancelHydrate(const SyncPath &filePathStd) {
+ const QString filePath = SyncName2QStr(filePathStd.native());
_connector->vfsCancelHydrate(filePath);
}
-bool VfsMac::isDehydratedPlaceholder(const QString &initFilePath, bool isAbsolutePath /*= false*/) {
+ExitInfo VfsMac::isDehydratedPlaceholder(const SyncPath &initFilePathStd, bool &isDehydrated, bool isAbsolutePath /*= false*/) {
+ const QString initFilePath = SyncName2QStr(initFilePathStd.native());
SyncPath filePath(isAbsolutePath ? QStr2Path(initFilePath) : _vfsSetupParams._localPath / QStr2Path(initFilePath));
bool isPlaceholder = false;
@@ -563,41 +503,34 @@ bool VfsMac::isDehydratedPlaceholder(const QString &initFilePath, bool isAbsolut
int progress = 0;
if (!_connector->vfsGetStatus(Path2QStr(filePath), isPlaceholder, isHydrated, isSyncing, progress)) {
LOG_WARN(logger(), "Error in vfsGetStatus!");
- return false;
+ return handleVfsError(filePath);
}
+ isDehydrated = !isHydrated;
- return !isHydrated;
+ return ExitCode::Ok;
}
-bool VfsMac::setPinState(const QString &fileRelativePath, PinState state) {
+ExitInfo VfsMac::setPinState(const SyncPath &fileRelativePathStd, PinState state) {
+ QString fileRelativePath = SyncName2QStr(fileRelativePathStd.native());
std::filesystem::path fullPath(_vfsSetupParams._localPath / QStr2Path(fileRelativePath));
- bool exists = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfPathExists(fullPath, exists, ioError)) {
- LOGW_WARN(logger(), L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(fullPath, ioError).c_str());
- return false;
- }
-
- if (!exists) {
- // New file
- LOGW_DEBUG(logger(), L"Item does not exist : " << Utility::formatSyncPath(fullPath).c_str());
- return true;
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath, true); !exitInfo) {
+ return exitInfo;
}
const QString strPath = Path2QStr(fullPath);
if (!_connector->vfsSetPinState(strPath, _localSyncPath,
(state == PinState::AlwaysLocal ? VFS_PIN_STATE_PINNED : VFS_PIN_STATE_UNPINNED))) {
LOG_WARN(logger(), "Error in vfsSetPinState!");
- return false;
+ return handleVfsError(fullPath);
}
- return true;
+ return ExitCode::Ok;
}
-PinState VfsMac::pinState(const QString &relativePath) {
+PinState VfsMac::pinState(const SyncPath &relativePathStd) {
// Read pin state from file attributes
- SyncPath fullPath(_vfsSetupParams._localPath / QStr2Path(relativePath));
+ SyncPath fullPath(_vfsSetupParams._localPath / relativePathStd.native());
QString pinState;
if (!_connector->vfsGetPinState(Path2QStr(fullPath), pinState)) {
return PinState::Unspecified;
@@ -612,17 +545,17 @@ PinState VfsMac::pinState(const QString &relativePath) {
return PinState::Unspecified;
}
-bool VfsMac::status(const QString &filePath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress) {
- SyncPath fullPath(QStr2Path(filePath));
- if (!_connector->vfsGetStatus(Path2QStr(fullPath), isPlaceholder, isHydrated, isSyncing, progress)) {
+ExitInfo VfsMac::status(const SyncPath &filePathStd, bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress) {
+ if (!_connector->vfsGetStatus(Path2QStr(filePathStd), isPlaceholder, isHydrated, isSyncing, progress)) {
LOG_WARN(logger(), "Error in vfsGetStatus!");
- return false;
+ return handleVfsError(filePathStd);
}
- return true;
+ return ExitCode::Ok;
}
-void VfsMac::exclude(const QString &path) {
+void VfsMac::exclude(const SyncPath &pathStd) {
+ const QString path = SyncName2QStr(pathStd.native());
LOGW_DEBUG(logger(), L"exclude - " << Utility::formatPath(path).c_str());
bool isPlaceholder = false;
@@ -657,7 +590,8 @@ void VfsMac::exclude(const QString &path) {
}
}
-bool VfsMac::isExcluded(const QString &filePath) {
+bool VfsMac::isExcluded(const SyncPath &filePathStd) {
+ const QString filePath = SyncName2QStr(filePathStd.native());
bool isPlaceholder;
bool isHydrated;
bool isSyncing;
@@ -674,43 +608,44 @@ bool VfsMac::isExcluded(const QString &filePath) {
return false;
}
-bool VfsMac::setThumbnail(const QString &absoluteFilePath, const QPixmap &pixmap) {
+ExitInfo VfsMac::setThumbnail(const SyncPath &absoluteFilePathStd, const QPixmap &pixmap) {
+ const QString absoluteFilePath = SyncName2QStr(absoluteFilePathStd.native());
if (!_connector->vfsSetThumbnail(absoluteFilePath, pixmap)) {
LOG_WARN(logger(), "Error in vfsSetThumbnail!");
- return false;
+ return handleVfsError(QStr2Path(absoluteFilePath));
}
- return true;
+ return ExitCode::Ok;
}
-bool VfsMac::setAppExcludeList() {
+ExitInfo VfsMac::setAppExcludeList() {
QString appExcludeList;
_exclusionAppList(appExcludeList);
if (!_connector->vfsSetAppExcludeList(appExcludeList)) {
LOG_WARN(logger(), "Error in vfsSetAppExcludeList!");
- return false;
+ return ExitCode::LogicError;
}
- return true;
+ return ExitCode::Ok;
}
-bool VfsMac::getFetchingAppList(QHash &appTable) {
+ExitInfo VfsMac::getFetchingAppList(QHash &appTable) {
if (!_connector->vfsGetFetchingAppList(appTable)) {
LOG_WARN(logger(), "Error in vfsGetFetchingAppList!");
- return false;
+ return ExitCode::LogicError;
}
- return true;
+ return ExitCode::Ok;
}
-bool VfsMac::fileStatusChanged(const QString &path, SyncFileStatus status) {
- LOGW_DEBUG(logger(), L"fileStatusChanged - " << Utility::formatPath(path).c_str() << L" - status = " << status);
-
- SyncPath fullPath(QStr2Path(path));
+bool VfsMac::fileStatusChanged(const SyncPath &pathStd, SyncFileStatus status) {
+ LOGW_DEBUG(logger(), L"fileStatusChanged - " << Utility::formatSyncPath(pathStd) << L" - status = " << status);
+ const QString path = SyncName2QStr(pathStd.native());
+ SyncPath fullPath(pathStd.native());
std::error_code ec;
if (!std::filesystem::exists(fullPath, ec)) {
if (ec.value() != 0) {
- LOGW_WARN(logger(), L"Failed to check if path exists : " << Utility::formatSyncPath(fullPath).c_str() << L": "
+ LOGW_WARN(logger(), L"Failed to check if path exists : " << Utility::formatSyncPath(fullPath) << L": "
<< Utility::s2ws(ec.message()).c_str() << L" (" << ec.value()
<< L")");
return false;
@@ -718,9 +653,10 @@ bool VfsMac::fileStatusChanged(const QString &path, SyncFileStatus status) {
// New file
return true;
}
+ SyncPath fileRelativePath = CommonUtility::relativePath(_vfsSetupParams._localPath, fullPath);
if (status == SyncFileStatus::Ignored) {
- exclude(QString::fromStdString(fullPath.native()));
+ exclude(fullPath);
} else if (status == SyncFileStatus::Success) {
// Do nothing
} else if (status == SyncFileStatus::Syncing) {
@@ -754,28 +690,31 @@ bool VfsMac::fileStatusChanged(const QString &path, SyncFileStatus status) {
}
if (!isLink && !isDirectory) {
- QString fileRelativePath =
- QStringView(path).mid(static_cast(_vfsSetupParams._localPath.string().size())).toUtf8();
auto localPinState = pinState(fileRelativePath);
- bool isDehydrated = isDehydratedPlaceholder(fileRelativePath);
+ bool isDehydrated = false;
+ if (ExitInfo exitInfo = isDehydratedPlaceholder(fileRelativePath, isDehydrated); !exitInfo) {
+ LOGW_WARN(logger(),
+ L"Error in isDehydratedPlaceholder : " << Utility::formatSyncPath(fullPath) << L" " << exitInfo);
+ return false;
+ }
if (localPinState == PinState::OnlineOnly && !isDehydrated) {
// Add file path to dehydration queue
- _workerInfo[WORKER_DEHYDRATION]._mutex.lock();
- _workerInfo[WORKER_DEHYDRATION]._queue.push_front(path);
- _workerInfo[WORKER_DEHYDRATION]._mutex.unlock();
- _workerInfo[WORKER_DEHYDRATION]._queueWC.wakeOne();
+ _workerInfo[workerDehydration]._mutex.lock();
+ _workerInfo[workerDehydration]._queue.push_front(path);
+ _workerInfo[workerDehydration]._mutex.unlock();
+ _workerInfo[workerDehydration]._queueWC.wakeOne();
} else if (localPinState == PinState::AlwaysLocal && isDehydrated) {
bool syncing;
- _syncFileSyncing(_vfsSetupParams._syncDbId, QStr2Path(fileRelativePath), syncing);
+ _syncFileSyncing(_vfsSetupParams._syncDbId, fileRelativePath, syncing);
if (!syncing) {
// Set hydrating indicator (avoid double hydration)
- _setSyncFileSyncing(_vfsSetupParams._syncDbId, QStr2Path(fileRelativePath), true);
+ _setSyncFileSyncing(_vfsSetupParams._syncDbId, fileRelativePath, true);
// Add file path to hydration queue
- _workerInfo[WORKER_HYDRATION]._mutex.lock();
- _workerInfo[WORKER_HYDRATION]._queue.push_front(path);
- _workerInfo[WORKER_HYDRATION]._mutex.unlock();
- _workerInfo[WORKER_HYDRATION]._queueWC.wakeOne();
+ _workerInfo[workerHydration]._mutex.lock();
+ _workerInfo[workerHydration]._queue.push_front(path);
+ _workerInfo[workerHydration]._mutex.unlock();
+ _workerInfo[workerHydration]._queueWC.wakeOne();
}
}
}
@@ -785,43 +724,4 @@ bool VfsMac::fileStatusChanged(const QString &path, SyncFileStatus status) {
return true;
}
-
-Worker::Worker(VfsMac *vfs, int type, int num, log4cplus::Logger logger) : _vfs(vfs), _type(type), _num(num), _logger(logger) {}
-
-void Worker::start() {
- LOG_DEBUG(logger(), "Worker " << _type << " - " << _num << " started");
-
- WorkerInfo &workerInfo = _vfs->_workerInfo[_type];
-
- forever {
- workerInfo._mutex.lock();
- while (workerInfo._queue.empty() && !workerInfo._stop) {
- LOG_DEBUG(logger(), "Worker " << _type << " - " << _num << " waiting");
- workerInfo._queueWC.wait(&workerInfo._mutex);
- }
-
- if (workerInfo._stop) {
- workerInfo._mutex.unlock();
- break;
- }
-
- QString path = workerInfo._queue.back();
- workerInfo._queue.pop_back();
- workerInfo._mutex.unlock();
-
- LOG_DEBUG(logger(), "Worker " << _type << " - " << _num << " working");
-
- switch (_type) {
- case WORKER_HYDRATION:
- _vfs->hydrate(path);
- break;
- case WORKER_DEHYDRATION:
- _vfs->dehydrate(path);
- break;
- }
- }
-
- LOG_DEBUG(logger(), "Worker " << _type << " - " << _num << " ended");
-}
-
} // namespace KDC
diff --git a/src/server/vfs/mac/vfs_mac.h b/src/server/vfs/mac/vfs_mac.h
index 9d4036319..1341e4b1b 100644
--- a/src/server/vfs/mac/vfs_mac.h
+++ b/src/server/vfs/mac/vfs_mac.h
@@ -31,70 +31,51 @@
#include
#include
-#define WORKER_HYDRATION 0
-#define WORKER_DEHYDRATION 1
-#define NB_WORKERS 2
-
namespace KDC {
-class Worker;
-
-struct WorkerInfo {
- QMutex _mutex;
- std::deque _queue;
- QWaitCondition _queueWC;
- bool _stop = false;
- QList _threadList;
-};
-
class VfsMac : public Vfs {
Q_OBJECT
Q_INTERFACES(KDC::Vfs)
public:
- WorkerInfo _workerInfo[NB_WORKERS];
-
- explicit VfsMac(KDC::VfsSetupParams &vfsSetupParams, QObject *parent = nullptr);
- ~VfsMac();
+ explicit VfsMac(const VfsSetupParams &vfsSetupParams, QObject *parent = nullptr);
VirtualFileMode mode() const override;
bool socketApiPinStateActionsShown() const override { return true; }
- bool isHydrating() const override;
- bool updateMetadata(const QString &absoluteFilePath, time_t creationTime, time_t modtime, qint64 size,
- const QByteArray &fileId, QString *error) override;
+ ExitInfo updateMetadata(const SyncPath &absoluteFilePath, time_t creationTime, time_t modtime, int64_t size,
+ const NodeId &fileId) override;
- bool createPlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item) override;
- bool dehydratePlaceholder(const QString &path) override;
- bool convertToPlaceholder(const QString &path, const SyncFileItem &item) override;
- bool updateFetchStatus(const QString &tmpPath, const QString &path, qint64 received, bool &canceled,
+ ExitInfo createPlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item) override;
+ ExitInfo dehydratePlaceholder(const SyncPath &path) override;
+ ExitInfo convertToPlaceholder(const SyncPath &path, const SyncFileItem &item) override;
+ ExitInfo updateFetchStatus(const SyncPath &tmpPath, const SyncPath &path, int64_t received, bool &canceled,
bool &finished) override;
- void cancelHydrate(const QString &filePath) override;
- bool forceStatus(const QString &path, bool isSyncing, int progress, bool isHydrated = false) override;
+ void cancelHydrate(const SyncPath &filePath) override;
+ ExitInfo forceStatus(const SyncPath &path, bool isSyncing, int progress, bool isHydrated = false) override;
bool cleanUpStatuses() override;
- virtual void clearFileAttributes(const QString &path) override;
+ virtual void clearFileAttributes(const SyncPath &path) override;
- bool needsMetadataUpdate(const SyncFileItem &) override { return false; }
- bool isDehydratedPlaceholder(const QString &filePath, bool isAbsolutePath = false) override;
+ ExitInfo isDehydratedPlaceholder(const SyncPath &filePath, bool &isDehydrated, bool isAbsolutePath = false) override;
- bool setPinState(const QString &fileRelativePath, PinState state) override;
- PinState pinState(const QString &relativePath) override;
- bool status(const QString &filePath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress) override;
- virtual void exclude(const QString &path) override;
- virtual bool isExcluded(const QString &filePath) override;
- virtual bool setThumbnail(const QString &absoluteFilePath, const QPixmap &pixmap) override;
- virtual bool setAppExcludeList() override;
- virtual bool getFetchingAppList(QHash &appTable) override;
- virtual bool fileStatusChanged(const QString &path, SyncFileStatus status) override;
+ ExitInfo setPinState(const SyncPath &fileRelativePath, PinState state) override;
+ PinState pinState(const SyncPath &relativePath) override;
+ ExitInfo status(const SyncPath &filePath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress) override;
+ void exclude(const SyncPath &path) override;
+ bool isExcluded(const SyncPath &filePath) override;
+ ExitInfo setThumbnail(const SyncPath &absoluteFilePath, const QPixmap &pixmap) override;
+ ExitInfo setAppExcludeList() override;
+ ExitInfo getFetchingAppList(QHash &appTable) override;
+ bool fileStatusChanged(const SyncPath &path, SyncFileStatus status) override;
- void dehydrate(const QString &path);
- void hydrate(const QString &path);
+ void dehydrate(const QString &path) final;
+ void hydrate(const QString &path) final;
virtual void convertDirContentToPlaceholder(const QString &filePath, bool isHydratedIn) override;
protected:
- bool startImpl(bool &installationDone, bool &activationDone, bool &connectionDone) override;
+ ExitInfo startImpl(bool &installationDone, bool &activationDone, bool &connectionDone) override;
void stopImpl(bool unregister) override;
friend class TestWorkers;
@@ -106,22 +87,6 @@ class VfsMac : public Vfs {
const QString _localSyncPath;
};
-class Worker : public QObject {
- Q_OBJECT
-
- public:
- Worker(VfsMac *vfs, int type, int num, log4cplus::Logger logger);
- void start();
-
- private:
- VfsMac *_vfs;
- int _type;
- int _num;
- log4cplus::Logger _logger;
-
- inline log4cplus::Logger logger() { return _logger; }
-};
-
class MacVfsPluginFactory : public QObject, public DefaultPluginFactory {
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.kdrive.PluginFactory" FILE "../vfspluginmetadata.json")
diff --git a/src/server/vfs/win/CMakeLists.txt b/src/server/vfs/win/CMakeLists.txt
index c268b189f..4eb455017 100644
--- a/src/server/vfs/win/CMakeLists.txt
+++ b/src/server/vfs/win/CMakeLists.txt
@@ -2,8 +2,6 @@ find_package(Qt6)
set(libsyncengine_vfs_win_SRCS
vfs_win.h vfs_win.cpp
- ../../../libcommonserver/vfs.h ../../../libcommonserver/vfs.cpp
- ../../../libcommonserver/plugin.h ../../../libcommonserver/plugin.cpp
../../../common/filepermissionholder.h ../../../common/filepermissionholder.cpp
../../../common/filesystembase.h ../../../common/filesystembase.cpp
)
diff --git a/src/server/vfs/win/vfs_win.cpp b/src/server/vfs/win/vfs_win.cpp
index 259aada4b..92a36ea05 100644
--- a/src/server/vfs/win/vfs_win.cpp
+++ b/src/server/vfs/win/vfs_win.cpp
@@ -37,12 +37,7 @@
#include
namespace KDC {
-
-const int s_nb_threads[NB_WORKERS] = {5, 5};
-
-std::unordered_map s_fetchMap;
-
-VfsWin::VfsWin(VfsSetupParams &vfsSetupParams, QObject *parent) : Vfs(vfsSetupParams, parent) {
+VfsWin::VfsWin(const VfsSetupParams &vfsSetupParams, QObject *parent) : Vfs(vfsSetupParams, parent) {
// Initialize LiteSync ext connector
LOG_INFO(logger(), "Initialize LiteSyncExtConnector");
@@ -59,46 +54,7 @@ VfsWin::VfsWin(VfsSetupParams &vfsSetupParams, QObject *parent) : Vfs(vfsSetupPa
return;
}
- // Start hydration/dehydration workers
- // !!! Disabled for testing because no QEventLoop !!!
- if (qApp) {
- // Start worker threads
- for (int i = 0; i < NB_WORKERS; i++) {
- for (int j = 0; j < s_nb_threads[i]; j++) {
- QThread *workerThread = new QThread();
- _workerInfo[i]._threadList.append(workerThread);
- Worker *worker = new Worker(this, i, j, logger());
- worker->moveToThread(workerThread);
- connect(workerThread, &QThread::started, worker, &Worker::start);
- connect(workerThread, &QThread::finished, worker, &QObject::deleteLater);
- connect(workerThread, &QThread::finished, workerThread, &QObject::deleteLater);
- workerThread->start();
- }
- }
- }
-}
-
-VfsWin::~VfsWin() {
- // Ask worker threads to stop
- for (int i = 0; i < NB_WORKERS; i++) {
- _workerInfo[i]._mutex.lock();
- _workerInfo[i]._stop = true;
- _workerInfo[i]._mutex.unlock();
- _workerInfo[i]._queueWC.wakeAll();
- }
-
- // Force threads to stop if needed
- for (int i = 0; i < NB_WORKERS; i++) {
- for (QThread *thread: qAsConst(_workerInfo[i]._threadList)) {
- if (thread) {
- thread->quit();
- if (!thread->wait(1000)) {
- thread->terminate();
- thread->wait();
- }
- }
- }
- }
+ starVfsWorkers();
}
void VfsWin::debugCbk(TraceLevel level, const wchar_t *msg) {
@@ -122,7 +78,7 @@ VirtualFileMode VfsWin::mode() const {
return VirtualFileMode::Win;
}
-bool VfsWin::startImpl(bool &, bool &, bool &) {
+ExitInfo VfsWin::startImpl(bool &, bool &, bool &) {
LOG_DEBUG(logger(), "startImpl: syncDbId=" << _vfsSetupParams._syncDbId);
wchar_t clsid[39] = L"";
@@ -131,12 +87,12 @@ bool VfsWin::startImpl(bool &, bool &, bool &) {
std::to_wstring(_vfsSetupParams._syncDbId).c_str(), _vfsSetupParams._localPath.filename().native().c_str(),
_vfsSetupParams._localPath.lexically_normal().native().c_str(), clsid, &clsidSize) != S_OK) {
LOG_WARN(logger(), "Error in vfsStart: syncDbId=" << _vfsSetupParams._syncDbId);
- return false;
+ return {ExitCode::SystemError, ExitCause::UnableToCreateVfs};
}
_vfsSetupParams._namespaceCLSID = Utility::ws2s(std::wstring(clsid));
- return true;
+ return ExitCode::Ok;
}
void VfsWin::stopImpl(bool unregister) {
@@ -175,9 +131,9 @@ void VfsWin::hydrate(const QString &path) {
_setSyncFileSyncing(_vfsSetupParams._syncDbId, QStr2Path(relativePath), false);
}
-void VfsWin::cancelHydrate(const QString &path) {
- LOGW_DEBUG(logger(), L"cancelHydrate: " << Utility::formatSyncPath(QStr2Path(path)).c_str());
-
+void VfsWin::cancelHydrate(const SyncPath &pathStd) {
+ LOGW_DEBUG(logger(), L"cancelHydrate: " << Utility::formatSyncPath(pathStd));
+ const QString path = SyncName2QStr(pathStd.native());
if (vfsCancelFetch(std::to_wstring(_vfsSetupParams._driveId).c_str(), std::to_wstring(_vfsSetupParams._syncDbId).c_str(),
QStr2Path(QDir::toNativeSeparators(path)).c_str()) != S_OK) {
LOGW_WARN(logger(), L"Error in vfsCancelFetch: " << Utility::formatSyncPath(QStr2Path(path)).c_str());
@@ -188,7 +144,8 @@ void VfsWin::cancelHydrate(const QString &path) {
_setSyncFileSyncing(_vfsSetupParams._syncDbId, QStr2Path(relativePath), false);
}
-void VfsWin::exclude(const QString &path) {
+void VfsWin::exclude(const SyncPath &pathStd) {
+ const QString path = SyncName2QStr(pathStd.native());
LOGW_DEBUG(logger(), L"exclude: " << Utility::formatSyncPath(QStr2Path(path)).c_str());
DWORD dwAttrs = GetFileAttributesW(QStr2Path(QDir::toNativeSeparators(path)).c_str());
@@ -205,33 +162,23 @@ void VfsWin::exclude(const QString &path) {
}
}
-void VfsWin::setPlaceholderStatus(const QString &path, bool syncOngoing) {
- if (vfsSetPlaceHolderStatus(QStr2Path(QDir::toNativeSeparators(path)).c_str(), syncOngoing) != S_OK) {
- LOGW_WARN(logger(), L"Error in vfsSetPlaceHolderStatus: " << Utility::formatSyncPath(QStr2Path(path)).c_str());
- return;
+ExitInfo VfsWin::setPlaceholderStatus(const QString &path, bool syncOngoing) {
+ auto stdPath = QStr2Path(QDir::toNativeSeparators(path));
+ if (vfsSetPlaceHolderStatus(stdPath.c_str(), syncOngoing) != S_OK) {
+ LOGW_WARN(logger(), L"Error in vfsSetPlaceHolderStatus: " << Utility::formatSyncPath(stdPath));
+ return handleVfsError(stdPath);
}
+ return ExitCode::Ok;
}
-bool VfsWin::isHydrating() const {
- return false;
-}
-
-bool VfsWin::updateMetadata(const QString &filePath, time_t creationTime, time_t modtime, qint64 size, const QByteArray &,
- QString *) {
+ExitInfo VfsWin::updateMetadata(const SyncPath &filePathStd, time_t creationTime, time_t modtime, int64_t size, const NodeId &) {
+ const QString filePath = SyncName2QStr(filePathStd.native());
LOGW_DEBUG(logger(), L"updateMetadata: " << Utility::formatSyncPath(QStr2Path(filePath)).c_str() << L" creationTime="
<< creationTime << L" modtime=" << modtime);
SyncPath fullPath(_vfsSetupParams._localPath / QStr2Path(filePath));
- bool exists = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfPathExists(fullPath, exists, ioError)) {
- LOGW_WARN(logger(), L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(fullPath, ioError).c_str());
- return false;
- }
-
- if (!exists) {
- LOGW_WARN(logger(), L"File/directory doesn't exists: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath, true); !exitInfo) {
+ return exitInfo;
}
// Update placeholder
@@ -244,36 +191,32 @@ bool VfsWin::updateMetadata(const QString &filePath, time_t creationTime, time_t
findData.dwFileAttributes = GetFileAttributesW(QStr2Path(filePath).c_str());
if (vfsUpdatePlaceHolder(QStr2Path(QDir::toNativeSeparators(filePath)).c_str(), &findData) != S_OK) {
- LOGW_WARN(logger(), L"Error in vfsUpdatePlaceHolder: " << Utility::formatSyncPath(fullPath).c_str());
+ LOGW_WARN(logger(), L"Error in vfsUpdatePlaceHolder: " << Utility::formatSyncPath(fullPath));
+ return handleVfsError(fullPath);
}
- return true;
+ return ExitCode::Ok;
}
-bool VfsWin::createPlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item) {
- LOGW_DEBUG(logger(), L"createPlaceholder: " << Utility::formatSyncPath(relativeLocalPath).c_str());
+ExitInfo VfsWin::createPlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item) {
+ LOGW_DEBUG(logger(), L"createPlaceholder: " << Utility::formatSyncPath(relativeLocalPath));
if (relativeLocalPath.empty()) {
- LOG_WARN(logger(), "Empty file!");
- return false;
+ LOG_WARN(logger(), "VfsWin::createPlaceholder - relativeLocalPath cannot be empty.");
+ return {ExitCode::SystemError, ExitCause::InvalidArgument};
}
if (!item.remoteNodeId().has_value()) {
- LOGW_WARN(logger(), L"Empty remote nodeId: " << Utility::formatSyncPath(relativeLocalPath).c_str());
- return false;
+ LOGW_WARN(logger(), L"VfsWin::createPlaceholder - Item has no remote ID: " << Utility::formatSyncPath(relativeLocalPath));
+ return {ExitCode::SystemError, ExitCause::InvalidArgument};
}
SyncPath fullPath(_vfsSetupParams._localPath / relativeLocalPath);
- bool exists = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfPathExists(fullPath, exists, ioError)) {
- LOGW_WARN(logger(), L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(fullPath, ioError).c_str());
- return false;
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath, false); !exitInfo) {
+ return exitInfo;
}
-
- if (exists) {
- LOGW_WARN(logger(), L"Item already exists: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath.parent_path(), true); !exitInfo) {
+ return exitInfo;
}
// Create placeholder
@@ -289,51 +232,40 @@ bool VfsWin::createPlaceholder(const SyncPath &relativeLocalPath, const SyncFile
relativeLocalPath.lexically_normal().native().c_str(),
_vfsSetupParams._localPath.lexically_normal().native().c_str(), &findData) != S_OK) {
LOGW_WARN(logger(), L"Error in vfsCreatePlaceHolder: " << Utility::formatSyncPath(fullPath).c_str());
+ return defaultVfsError(); // handleVfsError is not suitable here, the file dosen't exist but we don't want to return
+ // NotFound as this make no sense in the context of a create
}
// !!! Creating a placeholder DOESN'T triggers any file system event !!!
// Setting the pin state triggers an EDIT event and then the insertion into the local snapshot
if (vfsSetPinState(fullPath.lexically_normal().native().c_str(), VFS_PIN_STATE_UNPINNED) != S_OK) {
LOGW_WARN(logger(), L"Error in vfsSetPinState: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ return defaultVfsError(); // handleVfsError is not suitable here, the file dosen't exist but we don't want to return
+ // NotFound as this make no sense in the context of a create
}
- return true;
+ return ExitCode::Ok;
}
-bool VfsWin::dehydratePlaceholder(const QString &path) {
- LOGW_DEBUG(logger(), L"dehydratePlaceholder: " << Utility::formatSyncPath(QStr2Path(path)).c_str());
+ExitInfo VfsWin::dehydratePlaceholder(const SyncPath &path) {
+ LOGW_DEBUG(logger(), L"dehydratePlaceholder: " << Utility::formatSyncPath(path));
+ SyncPath fullPath(_vfsSetupParams._localPath / path);
- if (path.isEmpty()) {
- LOG_WARN(logger(), "Empty file!");
- return false;
- }
-
- SyncPath fullPath(_vfsSetupParams._localPath / QStr2Path(path));
- bool exists = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfPathExists(fullPath, exists, ioError)) {
- LOGW_WARN(logger(), L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(fullPath, ioError).c_str());
- return false;
- }
-
- if (!exists) {
- // File doesn't exist
- LOGW_WARN(logger(), L"File doesn't exist: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath, true); !exitInfo) {
+ return exitInfo;
}
// Check if the file is a placeholder
bool isPlaceholder;
if (vfsGetPlaceHolderStatus(fullPath.lexically_normal().native().c_str(), &isPlaceholder, nullptr, nullptr) != S_OK) {
LOGW_WARN(logger(), L"Error in vfsGetPlaceHolderStatus: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ return handleVfsError(fullPath);
}
if (!isPlaceholder) {
// Not a placeholder
LOGW_WARN(logger(), L"Not a placeholder: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ return {ExitCode::SystemError, ExitCause::NotPlaceHolder};
}
LOGW_DEBUG(logger(), L"Dehydrate file: " << Utility::formatSyncPath(fullPath).c_str());
@@ -341,15 +273,16 @@ bool VfsWin::dehydratePlaceholder(const QString &path) {
std::thread dehydrateTask(dehydrateFct);
dehydrateTask.detach();
- return true;
+ return ExitCode::Ok;
}
-bool VfsWin::convertToPlaceholder(const QString &path, const SyncFileItem &item) {
+ExitInfo VfsWin::convertToPlaceholder(const SyncPath &pathStd, const SyncFileItem &item) {
+ const QString path = SyncName2QStr(pathStd.native());
LOGW_DEBUG(logger(), L"convertToPlaceholder: " << Utility::formatSyncPath(QStr2Path(path)).c_str());
if (path.isEmpty()) {
- LOG_WARN(logger(), "Invalid parameters");
- return false;
+ LOG_WARN(logger(), "Empty path!");
+ return {ExitCode::SystemError, ExitCause::NotFound};
}
SyncPath fullPath(QStr2Path(path));
@@ -358,36 +291,32 @@ bool VfsWin::convertToPlaceholder(const QString &path, const SyncFileItem &item)
DWORD errorCode = GetLastError();
LOGW_WARN(logger(),
L"Error in GetFileAttributesW: " << Utility::formatSyncPath(fullPath).c_str() << L" code=" << errorCode);
- return false;
+ return handleVfsError(fullPath);
}
if (dwAttrs & FILE_ATTRIBUTE_DEVICE) {
LOGW_DEBUG(logger(), L"Not a valid file or directory: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ return handleVfsError(fullPath);
}
// Check if the file is already a placeholder
bool isPlaceholder;
if (vfsGetPlaceHolderStatus(fullPath.lexically_normal().native().c_str(), &isPlaceholder, nullptr, nullptr) != S_OK) {
LOGW_WARN(logger(), L"Error in vfsGetPlaceHolderStatus: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ return handleVfsError(fullPath);
}
if (!item.localNodeId().has_value()) {
LOGW_WARN(logger(), L"Item has no local ID: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ return {ExitCode::LogicError, ExitCause::InvalidArgument};
}
- if (!isPlaceholder) {
- // Convert to placeholder
- if (vfsConvertToPlaceHolder(Utility::s2ws(item.localNodeId().value()).c_str(),
- fullPath.lexically_normal().native().c_str()) != S_OK) {
- LOGW_WARN(logger(), L"Error in vfsConvertToPlaceHolder: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
- }
+ if (!isPlaceholder && (vfsConvertToPlaceHolder(Utility::s2ws(item.localNodeId().value()).c_str(),
+ fullPath.lexically_normal().native().c_str()) != S_OK)) {
+ LOGW_WARN(logger(), L"Error in vfsConvertToPlaceHolder: " << Utility::formatSyncPath(fullPath).c_str());
+ return handleVfsError(fullPath);
}
-
- return true;
+ return ExitCode::Ok;
}
void VfsWin::convertDirContentToPlaceholder(const QString &filePath, bool isHydratedIn) {
@@ -400,17 +329,13 @@ void VfsWin::convertDirContentToPlaceholder(const QString &filePath, bool isHydr
}
SyncPath fullPath(QStr2Path(tmpPath));
- bool exists = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfPathExists(fullPath, exists, ioError)) {
- LOGW_WARN(logger(), L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(fullPath, ioError).c_str());
- return;
- }
- if (!exists) {
- // File creation and rename
- LOGW_DEBUG(logger(), L"File doesn't exist: " << Utility::formatSyncPath(fullPath).c_str());
- continue;
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath, true); !exitInfo) {
+ if (exitInfo == ExitInfo(ExitCode::SystemError, ExitCause::NotFound)) {
+ continue;
+ }
+ LOGW_WARN(logger(), L"Error in checkIfPathExists: " << Utility::formatSyncPath(fullPath));
+ return;
}
// Check if the file is already a placeholder
@@ -451,95 +376,73 @@ void VfsWin::convertDirContentToPlaceholder(const QString &filePath, bool isHydr
}
}
-void VfsWin::clearFileAttributes(const QString &path) {
- std::filesystem::path fullPath(QStr2Path(path));
+void VfsWin::clearFileAttributes(const SyncPath &fullPath) {
if (vfsRevertPlaceHolder(fullPath.lexically_normal().native().c_str()) != S_OK) {
LOGW_WARN(logger(), L"Error in vfsRevertPlaceHolder: " << Utility::formatSyncPath(fullPath).c_str());
}
}
-bool VfsWin::updateFetchStatus(const QString &tmpPath, const QString &path, qint64 received, bool &canceled, bool &finished) {
+ExitInfo VfsWin::updateFetchStatus(const SyncPath &tmpPathStd, const SyncPath &pathStd, int64_t received, bool &canceled,
+ bool &finished) {
Q_UNUSED(finished)
+ const QString tmpPath = SyncName2QStr(tmpPathStd.native());
+ const QString path = SyncName2QStr(pathStd.native());
LOGW_DEBUG(logger(), L"updateFetchStatus: " << Utility::formatSyncPath(QStr2Path(path)).c_str());
- if (tmpPath.isEmpty() || path.isEmpty()) {
+ if (tmpPath.isEmpty()) {
LOG_WARN(logger(), "Invalid parameters");
- return false;
+ return ExitCode::SystemError;
}
SyncPath fullTmpPath(QStr2Path(tmpPath));
SyncPath fullPath(QStr2Path(path));
- bool exists = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfPathExists(fullPath, exists, ioError)) {
- LOGW_WARN(logger(), L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(fullPath, ioError).c_str());
- return false;
- }
-
- if (!exists) {
- return true;
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath, true); !exitInfo) {
+ if (exitInfo == ExitInfo(ExitCode::SystemError, ExitCause::NotFound)) {
+ return ExitCode::Ok;
+ }
}
// Check if the file is a placeholder
bool isPlaceholder;
if (vfsGetPlaceHolderStatus(fullPath.lexically_normal().native().c_str(), &isPlaceholder, nullptr, nullptr) != S_OK) {
LOGW_WARN(logger(), L"Error in vfsGetPlaceHolderStatus: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ return handleVfsError(fullPath);
}
- auto updateFct = [=](bool &canceled, bool &finished, bool &error) {
- // Update download progress
- if (vfsUpdateFetchStatus(std::to_wstring(_vfsSetupParams._driveId).c_str(),
- std::to_wstring(_vfsSetupParams._syncDbId).c_str(), fullPath.lexically_normal().native().c_str(),
- fullTmpPath.lexically_normal().native().c_str(), received, &canceled, &finished) != S_OK) {
- LOGW_WARN(logger(), L"Error in vfsUpdateFetchStatus: " << Utility::formatSyncPath(fullPath).c_str());
- error = true;
- return;
- }
- };
-
- // Launch update in a separate thread
- bool error = false;
- std::thread updateTask(updateFct, std::ref(canceled), std::ref(finished), std::ref(error));
- updateTask.join();
-
- return !error;
-}
-
-bool VfsWin::forceStatus(const QString &absolutePath, bool isSyncing, int, bool) {
- SyncPath stdPath = QStr2Path(absolutePath);
-
- bool exists = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfPathExists(stdPath, exists, ioError)) {
- LOGW_WARN(logger(), L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(stdPath, ioError).c_str());
- return false;
+ if (vfsUpdateFetchStatus(std::to_wstring(_vfsSetupParams._driveId).c_str(),
+ std::to_wstring(_vfsSetupParams._syncDbId).c_str(), fullPath.lexically_normal().native().c_str(),
+ fullTmpPath.lexically_normal().native().c_str(), received, &canceled, &finished) != S_OK) {
+ LOGW_WARN(logger(), L"Error in vfsUpdateFetchStatus: " << Utility::formatSyncPath(fullPath).c_str());
+ return handleVfsError(fullPath);
}
+ return ExitCode::Ok;
+}
- if (!exists) {
- // New file
- return true;
+ExitInfo VfsWin::forceStatus(const SyncPath &absolutePathStd, bool isSyncing, int, bool) {
+ QString absolutePath = SyncName2QStr(absolutePathStd.native());
+ if (ExitInfo exitInfo = checkIfPathExists(absolutePathStd, true); !exitInfo) {
+ return exitInfo;
}
- DWORD dwAttrs = GetFileAttributesW(stdPath.native().c_str());
+ DWORD dwAttrs = GetFileAttributesW(absolutePathStd.native().c_str());
if (dwAttrs == INVALID_FILE_ATTRIBUTES) {
DWORD errorCode = GetLastError();
LOGW_WARN(logger(),
- L"Error in GetFileAttributesW: " << Utility::formatSyncPath(stdPath).c_str() << L" code=" << errorCode);
- return false;
+ L"Error in GetFileAttributesW: " << Utility::formatSyncPath(absolutePathStd).c_str() << L" code=" << errorCode);
+ return handleVfsError(absolutePathStd);
}
if (dwAttrs & FILE_ATTRIBUTE_DEVICE) {
- LOGW_WARN(logger(), L"Not a valid file or directory: " << Utility::formatSyncPath(stdPath).c_str());
- return false;
+ LOGW_WARN(logger(), L"Not a valid file or directory: " << Utility::formatSyncPath(absolutePathStd).c_str());
+ return handleVfsError(absolutePathStd);
}
bool isPlaceholder = false;
- if (vfsGetPlaceHolderStatus(stdPath.native().c_str(), &isPlaceholder, nullptr, nullptr) != S_OK) {
- LOGW_WARN(logger(), L"Error in vfsGetPlaceHolderStatus: " << Utility::formatSyncPath(stdPath).c_str());
- return false;
+ if (vfsGetPlaceHolderStatus(absolutePathStd.native().c_str(), &isPlaceholder, nullptr, nullptr) != S_OK) {
+ LOGW_WARN(logger(), L"Error in vfsGetPlaceHolderStatus: " << Utility::formatSyncPath(absolutePathStd).c_str());
+ return handleVfsError(absolutePathStd);
}
// Some editors (notepad++) seems to remove the file attributes, therfore we need to verify that the file is still a
@@ -547,56 +450,59 @@ bool VfsWin::forceStatus(const QString &absolutePath, bool isSyncing, int, bool)
if (!isPlaceholder) {
FileStat filestat;
IoError ioError = IoError::Success;
- if (!IoHelper::getFileStat(stdPath, &filestat, ioError)) {
- LOGW_WARN(logger(), L"Error in IoHelper::getFileStat: " << Utility::formatIoError(stdPath, ioError).c_str());
- return false;
+ if (!IoHelper::getFileStat(absolutePathStd, &filestat, ioError)) {
+ LOGW_WARN(logger(), L"Error in IoHelper::getFileStat: " << Utility::formatIoError(absolutePathStd, ioError).c_str());
+ return ExitCode::SystemError;
}
-
if (ioError == IoError::NoSuchFileOrDirectory) {
- LOGW_DEBUG(logger(), L"Item does not exist anymore: " << Utility::formatSyncPath(stdPath).c_str());
- return true;
+ LOGW_DEBUG(logger(), L"Item does not exist anymore: " << Utility::formatSyncPath(absolutePathStd).c_str());
+ return {ExitCode::SystemError, ExitCause::NotFound};
} else if (ioError == IoError::AccessDenied) {
- LOGW_WARN(logger(), L"Item: " << Utility::formatSyncPath(stdPath).c_str() << L" rejected because access is denied");
- return true;
+ LOGW_WARN(logger(), L"Access is denied for item: " << Utility::formatSyncPath(absolutePathStd));
+ return {ExitCode::SystemError, ExitCause::FileAccessError};
}
NodeId localNodeId = std::to_string(filestat.inode);
// Convert to placeholder
- if (vfsConvertToPlaceHolder(Utility::s2ws(localNodeId).c_str(), stdPath.native().c_str()) != S_OK) {
- LOGW_WARN(logger(), L"Error in vfsConvertToPlaceHolder: " << Utility::formatSyncPath(stdPath).c_str());
- return false;
+ if (vfsConvertToPlaceHolder(Utility::s2ws(localNodeId).c_str(), absolutePathStd.native().c_str()) != S_OK) {
+ LOGW_WARN(logger(), L"Error in vfsConvertToPlaceHolder: " << Utility::formatSyncPath(absolutePathStd).c_str());
+ return handleVfsError(absolutePathStd);
}
}
// Set status
- LOGW_DEBUG(logger(), L"Setting syncing status to: " << isSyncing << L" for file: "
- << Utility::formatSyncPath(QStr2Path(absolutePath)).c_str());
- setPlaceholderStatus(absolutePath, isSyncing);
+ LOGW_DEBUG(logger(),
+ L"Setting syncing status to: " << isSyncing << L" for file: " << Utility::formatSyncPath(absolutePathStd));
+ if (ExitInfo exitInfo = setPlaceholderStatus(absolutePath, isSyncing); !exitInfo) {
+ LOGW_WARN(logger(), L"Error in setPlaceholderStatus: " << Utility::formatSyncPath(absolutePathStd) << L" " << exitInfo);
+ return exitInfo;
+ }
- return true;
+ return ExitCode::Ok;
}
-bool VfsWin::isDehydratedPlaceholder(const QString &initFilePath, bool isAbsolutePath /*= false*/) {
- bool isDehydrated;
+ExitInfo VfsWin::isDehydratedPlaceholder(const SyncPath &initFilePathStd, bool &isDehydrated, bool isAbsolutePath /*= false*/) {
+ QString initFilePath = SyncName2QStr(initFilePathStd.native());
SyncPath filePath(isAbsolutePath ? QStr2Path(initFilePath) : _vfsSetupParams._localPath / QStr2Path(initFilePath));
if (vfsGetPlaceHolderStatus(filePath.lexically_normal().native().c_str(), nullptr, &isDehydrated, nullptr) != S_OK) {
LOGW_WARN(logger(), L"Error in vfsGetPlaceHolderStatus: " << Utility::formatSyncPath(filePath).c_str());
- return false;
+ return handleVfsError(filePath);
}
- return isDehydrated;
+ return ExitCode::Ok;
}
-bool VfsWin::setPinState(const QString &relativePath, PinState state) {
+ExitInfo VfsWin::setPinState(const SyncPath &relativePathStd, PinState state) {
+ QString relativePath = SyncName2QStr(relativePathStd.native());
SyncPath fullPath(_vfsSetupParams._localPath / QStr2Path(relativePath));
DWORD dwAttrs = GetFileAttributesW(fullPath.lexically_normal().native().c_str());
if (dwAttrs == INVALID_FILE_ATTRIBUTES) {
DWORD errorCode = GetLastError();
LOGW_WARN(logger(),
L"Error in GetFileAttributesW: " << Utility::formatSyncPath(fullPath).c_str() << L" code=" << errorCode);
- return false;
+ return handleVfsError(fullPath);
}
VfsPinState vfsState;
@@ -617,17 +523,17 @@ bool VfsWin::setPinState(const QString &relativePath, PinState state) {
if (vfsSetPinState(fullPath.lexically_normal().native().c_str(), vfsState) != S_OK) {
LOGW_WARN(logger(), L"Error in vfsSetPinState: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ return handleVfsError(fullPath);
}
- return true;
+ return ExitCode::Ok;
}
-PinState VfsWin::pinState(const QString &relativePath) {
+PinState VfsWin::pinState(const SyncPath &relativePathStd) {
// TODO: Use vfsGetPinState instead of reading attributes (GetFileAttributesW). In this case return unspecified in case of
// VFS_PIN_STATE_INHERIT.
// Read pin state from file attributes
- SyncPath fullPath(_vfsSetupParams._localPath / QStr2Path(relativePath));
+ SyncPath fullPath(_vfsSetupParams._localPath / relativePathStd.native());
DWORD dwAttrs = GetFileAttributesW(fullPath.lexically_normal().native().c_str());
if (dwAttrs == INVALID_FILE_ATTRIBUTES) {
@@ -643,131 +549,105 @@ PinState VfsWin::pinState(const QString &relativePath) {
return PinState::Unspecified;
}
-bool VfsWin::status(const QString &filePath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &) {
+ExitInfo VfsWin::status(const SyncPath &filePath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &) {
// Check if the file is a placeholder
- SyncPath fullPath(QStr2Path(filePath));
bool isDehydrated = false;
- if (vfsGetPlaceHolderStatus(fullPath.lexically_normal().native().c_str(), &isPlaceholder, &isDehydrated, nullptr) != S_OK) {
- LOGW_WARN(logger(), L"Error in vfsGetPlaceHolderStatus: " << Utility::formatSyncPath(fullPath).c_str());
- return false;
+ if (vfsGetPlaceHolderStatus(filePath.lexically_normal().native().c_str(), &isPlaceholder, &isDehydrated, nullptr) != S_OK) {
+ LOGW_WARN(logger(), L"Error in vfsGetPlaceHolderStatus: " << Utility::formatSyncPath(filePath).c_str());
+ return handleVfsError(filePath);
}
isHydrated = !isDehydrated;
isSyncing = false;
- return true;
+ return ExitCode::Ok;
}
-bool VfsWin::fileStatusChanged(const QString &path, SyncFileStatus status) {
- LOGW_DEBUG(logger(), L"fileStatusChanged: " << Utility::formatSyncPath(QStr2Path(path)).c_str() << L" status = " << status);
-
- SyncPath fullPath(QStr2Path(path));
- bool exists = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfPathExists(fullPath, exists, ioError)) {
- LOGW_WARN(logger(), L"Error in IoHelper::checkIfPathExists: " << Utility::formatIoError(fullPath, ioError).c_str());
+bool VfsWin::fileStatusChanged(const SyncPath &pathStd, SyncFileStatus status) {
+ LOGW_DEBUG(logger(), L"fileStatusChanged: " << Utility::formatSyncPath(pathStd) << L" status = " << status);
+ const QString path = SyncName2QStr(pathStd.native());
+ SyncPath fullPath(pathStd.native());
+ if (ExitInfo exitInfo = checkIfPathExists(fullPath, true); !exitInfo) {
+ if (exitInfo == ExitInfo(ExitCode::SystemError, ExitCause::NotFound)) {
+ return true;
+ }
return false;
}
+ SyncPath fileRelativePath = CommonUtility::relativePath(_vfsSetupParams._localPath, fullPath);
- if (!exists) {
- // New file
- return true;
- }
+ switch (status) {
+ case SyncFileStatus::Conflict:
+ case SyncFileStatus::Ignored:
+ exclude(fullPath);
+ break;
+ case SyncFileStatus::Success: {
+ bool isDirectory = false;
- if (status == SyncFileStatus::Conflict || status == SyncFileStatus::Ignored) {
- exclude(path);
- } else if (status == SyncFileStatus::Success) {
- bool isDirectory = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfIsDirectory(fullPath, isDirectory, ioError)) {
- LOGW_WARN(logger(), L"Failed to check if path is a directory: " << Utility::formatIoError(fullPath, ioError).c_str());
- return false;
- }
+ if (IoError ioError = IoError::Success; !IoHelper::checkIfIsDirectory(fullPath, isDirectory, ioError)) {
+ LOGW_WARN(logger(),
+ L"Failed to check if path is a directory: " << Utility::formatIoError(fullPath, ioError).c_str());
+ return false;
+ }
- if (!isDirectory) {
- // File
- QString fileRelativePath = QStringView{path}.mid(_vfsSetupParams._localPath.native().size() + 1).toUtf8();
- bool isDehydrated = isDehydratedPlaceholder(fileRelativePath);
- forceStatus(path, false, 100, !isDehydrated);
- }
- } else if (status == SyncFileStatus::Syncing) {
- bool isDirectory = false;
- IoError ioError = IoError::Success;
- if (!IoHelper::checkIfIsDirectory(fullPath, isDirectory, ioError)) {
- LOGW_WARN(logger(), L"Failed to check if path is a directory: " << Utility::formatIoError(fullPath, ioError).c_str());
- return false;
- }
- if (!isDirectory) {
- // File
- QString fileRelativePath = QStringView{path}.mid(_vfsSetupParams._localPath.native().size() + 1).toUtf8();
- auto localPinState = pinState(fileRelativePath);
- if (localPinState == PinState::OnlineOnly || localPinState == PinState::AlwaysLocal) {
- bool isDehydrated = isDehydratedPlaceholder(fileRelativePath);
- if (localPinState == PinState::OnlineOnly && !isDehydrated) {
- // Add file path to dehydration queue
- _workerInfo[WORKER_DEHYDRATION]._mutex.lock();
- _workerInfo[WORKER_DEHYDRATION]._queue.push_front(path);
- _workerInfo[WORKER_DEHYDRATION]._mutex.unlock();
- _workerInfo[WORKER_DEHYDRATION]._queueWC.wakeOne();
- } else if (localPinState == PinState::AlwaysLocal && isDehydrated) {
- bool syncing;
- _syncFileSyncing(_vfsSetupParams._syncDbId, QStr2Path(fileRelativePath), syncing);
- if (!syncing) {
- // Set hydrating indicator (avoid double hydration)
- _setSyncFileSyncing(_vfsSetupParams._syncDbId, QStr2Path(fileRelativePath), true);
-
- // Add file path to hydration queue
- _workerInfo[WORKER_HYDRATION]._mutex.lock();
- _workerInfo[WORKER_HYDRATION]._queue.push_front(path);
- _workerInfo[WORKER_HYDRATION]._mutex.unlock();
- _workerInfo[WORKER_HYDRATION]._queueWC.wakeOne();
- }
+ if (!isDirectory) {
+ // File
+ bool isDehydrated = false;
+ if (ExitInfo exitInfo = isDehydratedPlaceholder(fileRelativePath, isDehydrated); !exitInfo) {
+ LOGW_WARN(logger(),
+ L"Error in isDehydratedPlaceholder: " << Utility::formatSyncPath(fullPath)
+ << L" - " << exitInfo);
+ return false;
}
+ forceStatus(fullPath, false, 100, !isDehydrated);
}
- }
- } else if (status == SyncFileStatus::Error) {
- // Nothing to do
- }
-
- return true;
-}
+ } break;
+ case SyncFileStatus::Syncing: {
+ bool isDirectory = false;
-Worker::Worker(VfsWin *vfs, int type, int num, log4cplus::Logger logger) : _vfs(vfs), _type(type), _num(num), _logger(logger) {}
+ if (IoError ioError = IoError::Success; !IoHelper::checkIfIsDirectory(fullPath, isDirectory, ioError)) {
+ LOGW_WARN(logger(),
+ L"Failed to check if path is a directory: " << Utility::formatIoError(fullPath, ioError).c_str());
+ return false;
+ }
+ if (isDirectory) break;
+ // File
+ auto localPinState = pinState(fileRelativePath);
-void Worker::start() {
- LOG_DEBUG(logger(), "Worker with type=" << _type << " and num=" << _num << " started");
+ if (localPinState != PinState::OnlineOnly && localPinState != PinState::AlwaysLocal) break;
- WorkerInfo &workerInfo = _vfs->_workerInfo[_type];
+ bool isDehydrated = false;
+ if (ExitInfo exitInfo = isDehydratedPlaceholder(fileRelativePath, isDehydrated); !exitInfo) {
+ LOGW_WARN(logger(),
+ L"Error in isDehydratedPlaceholder: " << Utility::formatSyncPath(fullPath) << L" - "
+ << exitInfo);
+ return false;
+ }
- forever {
- workerInfo._mutex.lock();
- while (workerInfo._queue.empty() && !workerInfo._stop) {
- LOG_DEBUG(logger(), "Worker with type=" << _type << " and num=" << _num << " waiting");
- workerInfo._queueWC.wait(&workerInfo._mutex);
- }
+ bool syncing;
+ _syncFileSyncing(_vfsSetupParams._syncDbId, fileRelativePath, syncing);
+
+ if (localPinState == PinState::OnlineOnly && !isDehydrated) {
+ // Add file path to dehydration queue
+ _workerInfo[workerDehydration]._mutex.lock();
+ _workerInfo[workerDehydration]._queue.push_front(path);
+ _workerInfo[workerDehydration]._mutex.unlock();
+ _workerInfo[workerDehydration]._queueWC.wakeOne();
+ } else if (localPinState == PinState::AlwaysLocal && isDehydrated && !syncing) {
+ // Set hydrating indicator (avoid double hydration)
+ _setSyncFileSyncing(_vfsSetupParams._syncDbId, fileRelativePath, true);
+
+ // Add file path to hydration queue
+ _workerInfo[workerHydration]._mutex.lock();
+ _workerInfo[workerHydration]._queue.push_front(path);
+ _workerInfo[workerHydration]._mutex.unlock();
+ _workerInfo[workerHydration]._queueWC.wakeOne();
+ }
- if (workerInfo._stop) {
- workerInfo._mutex.unlock();
+ } break;
+ default:
+ // Nothing to do
break;
- }
-
- QString path = workerInfo._queue.back();
- workerInfo._queue.pop_back();
- workerInfo._mutex.unlock();
-
- LOG_DEBUG(logger(), "Worker with type=" << _type << " and num=" << _num << " working");
-
- switch (_type) {
- case WORKER_HYDRATION:
- _vfs->hydrate(path);
- break;
- case WORKER_DEHYDRATION:
- _vfs->dehydrate(path);
- break;
- }
}
-
- LOG_DEBUG(logger(), "Worker with type=" << _type << " and num=" << _num << " ended");
+ return true;
}
-
} // namespace KDC
diff --git a/src/server/vfs/win/vfs_win.h b/src/server/vfs/win/vfs_win.h
index ec2b421c9..c7a921688 100644
--- a/src/server/vfs/win/vfs_win.h
+++ b/src/server/vfs/win/vfs_win.h
@@ -30,107 +30,65 @@
#include "debug.h"
#include "vfs.h"
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define WORKER_HYDRATION 0
-#define WORKER_DEHYDRATION 1
-#define NB_WORKERS 2
-
namespace KDC {
-class Worker;
-
-struct WorkerInfo {
- QMutex _mutex;
- std::deque _queue;
- QWaitCondition _queueWC;
- bool _stop = false;
- QList _threadList;
-};
-
class SYNCENGINEVFS_EXPORT VfsWin : public Vfs {
Q_OBJECT
Q_INTERFACES(KDC::Vfs)
public:
- WorkerInfo _workerInfo[NB_WORKERS];
-
- explicit VfsWin(VfsSetupParams &vfsSetupParams, QObject *parent = nullptr);
- ~VfsWin();
+ explicit VfsWin(const VfsSetupParams &vfsSetupParams, QObject *parent = nullptr);
void debugCbk(TraceLevel level, const wchar_t *msg);
- VirtualFileMode mode() const override;
+ VirtualFileMode mode() const final;
- bool socketApiPinStateActionsShown() const override { return false; }
- bool isHydrating() const override;
+ bool socketApiPinStateActionsShown() const final { return false; }
- bool updateMetadata(const QString &filePath, time_t creationTime, time_t modtime, qint64 size, const QByteArray &fileId,
- QString *error) override;
+ ExitInfo updateMetadata(const SyncPath &filePath, time_t creationTime, time_t modtime, int64_t size,
+ const NodeId &fileId) final;
- bool createPlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item) override;
- bool dehydratePlaceholder(const QString &path) override;
- bool convertToPlaceholder(const QString &path, const SyncFileItem &item) override;
- void convertDirContentToPlaceholder(const QString &filePath, bool isHydratedIn) override;
- virtual void clearFileAttributes(const QString &path) override;
+ ExitInfo createPlaceholder(const SyncPath &relativeLocalPath, const SyncFileItem &item) final;
+ ExitInfo dehydratePlaceholder(const SyncPath &path) final;
+ ExitInfo convertToPlaceholder(const SyncPath &path, const SyncFileItem &item) final;
+ void convertDirContentToPlaceholder(const QString &filePath, bool isHydratedIn) final;
+ void clearFileAttributes(const SyncPath &path) final;
- bool updateFetchStatus(const QString &tmpPath, const QString &path, qint64 received, bool &canceled,
- bool &finished) override;
- bool forceStatus(const QString &absolutePath, bool isSyncing, int progress, bool isHydrated = false) override;
+ ExitInfo updateFetchStatus(const SyncPath &tmpPath, const SyncPath &path, int64_t received, bool &canceled,
+ bool &finished) final;
+ ExitInfo forceStatus(const SyncPath &absolutePath, bool isSyncing, int progress, bool isHydrated = false) final;
- bool needsMetadataUpdate(const SyncFileItem &) override { return false; }
- bool isDehydratedPlaceholder(const QString &filePath, bool isAbsolutePath = false) override;
+ ExitInfo isDehydratedPlaceholder(const SyncPath &filePath, bool &isDehydrated, bool isAbsolutePath = false) final;
- bool setPinState(const QString &fileRelativePath, PinState state) override;
- PinState pinState(const QString &relativePath) override;
- bool status(const QString &, bool &, bool &, bool &, int &) override;
- virtual bool setThumbnail(const QString &, const QPixmap &) override { return true; };
- virtual bool setAppExcludeList() override { return true; }
- virtual bool getFetchingAppList(QHash &) override { return true; }
+ ExitInfo setPinState(const SyncPath &fileRelativePath, PinState state) final;
+ PinState pinState(const SyncPath &relativePath) final;
+ ExitInfo status(const SyncPath &, bool &, bool &, bool &, int &) final;
+ ExitInfo setThumbnail(const SyncPath &, const QPixmap &) final { return ExitCode::Ok; };
+ ExitInfo setAppExcludeList() final { return ExitCode::Ok; }
+ ExitInfo getFetchingAppList(QHash &) final { return ExitCode::Ok; }
- bool isExcluded(const QString &) override { return false; }
+ bool isExcluded(const SyncPath &) final { return false; }
virtual bool setCreationDate(const QString &, time_t) { return false; }
- virtual void cancelHydrate(const QString &path) override;
+ void cancelHydrate(const SyncPath &path) final;
- void dehydrate(const QString &path);
- void hydrate(const QString &path);
+ void dehydrate(const QString &path) final;
+ void hydrate(const QString &path) final;
public slots:
- bool fileStatusChanged(const QString &path, KDC::SyncFileStatus status) override;
+ bool fileStatusChanged(const SyncPath &path, KDC::SyncFileStatus status) final;
protected:
- bool startImpl(bool &installationDone, bool &activationDone, bool &connectionDone) override;
- void stopImpl(bool unregister) override;
+ ExitInfo startImpl(bool &installationDone, bool &activationDone, bool &connectionDone) final;
+ void stopImpl(bool unregister) final;
friend class TestWorkers;
private:
log4cplus::Logger _logger;
- void exclude(const QString &path) override;
- void setPlaceholderStatus(const QString &path, bool syncOngoing);
-};
-
-class Worker : public QObject {
- Q_OBJECT
-
- public:
- Worker(VfsWin *vfs, int type, int num, log4cplus::Logger logger);
- void start();
-
- private:
- VfsWin *_vfs;
- int _type;
- int _num;
- log4cplus::Logger _logger;
-
- inline log4cplus::Logger logger() { return _logger; }
+ void exclude(const SyncPath &path) final;
+ ExitInfo setPlaceholderStatus(const QString &path, bool syncOngoing);
};
class WinVfsPluginFactory : public QObject, public DefaultPluginFactory {
diff --git a/test/libcommon/utility/testutility.cpp b/test/libcommon/utility/testutility.cpp
index 20ad34182..a81da85a1 100644
--- a/test/libcommon/utility/testutility.cpp
+++ b/test/libcommon/utility/testutility.cpp
@@ -19,6 +19,7 @@
#include "config.h"
#include "testutility.h"
#include "libcommon/utility/utility.h"
+#include "libcommon/utility/sourcelocation.h"
#include "libcommonserver/io/iohelper.h"
#include "test_utility/localtemporarydirectory.h"
#include
@@ -299,6 +300,39 @@ void TestUtility::testCurrentVersion() {
CPPUNIT_ASSERT(std::regex_match(test, std::regex(R"(\d{1,2}\.{1}\d{1,2}\.{1}\d{1,2}\.{1}\d{0,8}$)")));
}
+SourceLocation testSourceLocationFooFunc(uint32_t &constructLine, SourceLocation location = SourceLocation::currentLoc()) {
+ constructLine = __LINE__ - 1;
+ return location;
+}
+
+void TestUtility::testSourceLocation() {
+ SourceLocation location = SourceLocation::currentLoc();
+ uint32_t correctLine = __LINE__ - 1;
+
+ CPPUNIT_ASSERT_EQUAL(std::string("testutility.cpp"), location.fileName());
+ CPPUNIT_ASSERT_EQUAL(correctLine, location.line());
+
+#ifdef SRC_LOC_AVALAIBALE
+ CPPUNIT_ASSERT_EQUAL(std::string("testSourceLocation"), location.functionName());
+#else
+ CPPUNIT_ASSERT_EQUAL(std::string(""), location.functionName());
+#endif
+
+ // Test as a default argument
+ uint32_t fooFuncLine = 0;
+ location = testSourceLocationFooFunc(fooFuncLine);
+ correctLine = __LINE__ - 1;
+
+ CPPUNIT_ASSERT_EQUAL(std::string("testutility.cpp"), location.fileName());
+#ifdef SRC_LOC_AVALAIBALE
+ CPPUNIT_ASSERT_EQUAL(std::string("testSourceLocation"), location.functionName());
+ CPPUNIT_ASSERT_EQUAL(correctLine, location.line());
+#else
+ CPPUNIT_ASSERT_EQUAL(std::string(""), location.functionName());
+ CPPUNIT_ASSERT_EQUAL(fooFuncLine, location.line());
+#endif
+}
+
void TestUtility::testGenerateRandomStringAlphaNum() {
{
int err = 0;
diff --git a/test/libcommon/utility/testutility.h b/test/libcommon/utility/testutility.h
index d481473c7..4d3e4a6af 100644
--- a/test/libcommon/utility/testutility.h
+++ b/test/libcommon/utility/testutility.h
@@ -31,6 +31,7 @@ class TestUtility : public CppUnit::TestFixture {
CPPUNIT_TEST(testArgsWriter);
CPPUNIT_TEST(testCompressFile);
CPPUNIT_TEST(testCurrentVersion);
+ CPPUNIT_TEST(testSourceLocation);
CPPUNIT_TEST(testGenerateRandomStringAlphaNum);
#ifdef _WIN32
CPPUNIT_TEST(testGetLastErrorMessage);
@@ -44,6 +45,7 @@ class TestUtility : public CppUnit::TestFixture {
void testArgsWriter();
void testCompressFile();
void testCurrentVersion();
+ void testSourceLocation();
void testGenerateRandomStringAlphaNum();
#ifdef _WIN32
void testGetLastErrorMessage();
diff --git a/test/libsyncengine/CMakeLists.txt b/test/libsyncengine/CMakeLists.txt
index d0e78417e..5d65b6f8e 100644
--- a/test/libsyncengine/CMakeLists.txt
+++ b/test/libsyncengine/CMakeLists.txt
@@ -4,6 +4,8 @@ find_package(SQLite3 3.8.0 REQUIRED)
find_package(Poco REQUIRED Foundation)
find_package(log4cplus 2.1.0 REQUIRED)
+set(CMAKE_AUTOMOC TRUE)
+
set(testsyncengine_NAME ${APPLICATION_NAME}_test_syncengine)
set(testsyncengine_SRCS
diff --git a/test/libsyncengine/jobs/network/testnetworkjobs.cpp b/test/libsyncengine/jobs/network/testnetworkjobs.cpp
index 743406380..33a91b021 100644
--- a/test/libsyncengine/jobs/network/testnetworkjobs.cpp
+++ b/test/libsyncengine/jobs/network/testnetworkjobs.cpp
@@ -338,7 +338,7 @@ void TestNetworkJobs::testDownload() {
return temporaryDirectory.path();
};
std::function MockRename =
- [](const SyncPath &, const SyncPath &, std::error_code &ec) {
+ []([[maybe_unused]] const SyncPath &, [[maybe_unused]] const SyncPath &, std::error_code &ec) {
#ifdef _WIN32
ec = std::make_error_code(static_cast(ERROR_NOT_SAME_DEVICE));
#else
diff --git a/test/libsyncengine/propagation/executor/testexecutorworker.cpp b/test/libsyncengine/propagation/executor/testexecutorworker.cpp
index e05200e4e..a1365f99c 100644
--- a/test/libsyncengine/propagation/executor/testexecutorworker.cpp
+++ b/test/libsyncengine/propagation/executor/testexecutorworker.cpp
@@ -86,25 +86,19 @@ void TestExecutorWorker::tearDown() {
void TestExecutorWorker::testCheckLiteSyncInfoForCreate() {
#ifdef __APPLE__
- // Setup dummy values. Test inputs are set in the callbacks defined below.
+ // Setup dummy values. Test inputs are set in the callbacks defined below.
const auto opPtr = std::make_shared();
opPtr->setTargetSide(ReplicaSide::Remote);
- const auto node = std::make_shared(1, ReplicaSide::Local, "test_file.txt", NodeType::File, OperationType::None, "1234",
- testhelpers::defaultTime, testhelpers::defaultTime, testhelpers::defaultFileSize,
- _syncPal->updateTree(ReplicaSide::Local)->rootNode());
+ const auto node = std::make_shared(1, ReplicaSide::Local, Str2SyncName("test_file.txt"), NodeType::File,
+ OperationType::None, "1234", testhelpers::defaultTime, testhelpers::defaultTime,
+ testhelpers::defaultFileSize, _syncPal->updateTree(ReplicaSide::Local)->rootNode());
opPtr->setAffectedNode(node);
+ std::shared_ptr mockVfs = std::make_shared();
+ _syncPal->setVfsPtr(mockVfs);
// A hydrated placeholder.
{
- _syncPal->setVfsStatusCallback([]([[maybe_unused]] int syncDbId, [[maybe_unused]] const SyncPath &itemPath,
- bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress) -> bool {
- isPlaceholder = true;
- isHydrated = true;
- isSyncing = false;
- progress = 0;
- return true;
- });
-
+ mockVfs->setVfsStatusOutput(true, true, false, 0);
bool isDehydratedPlaceholder = false;
_executorWorker->checkLiteSyncInfoForCreate(opPtr, "/", isDehydratedPlaceholder);
@@ -113,15 +107,7 @@ void TestExecutorWorker::testCheckLiteSyncInfoForCreate() {
// A dehydrated placeholder.
{
- _syncPal->setVfsStatusCallback([]([[maybe_unused]] int syncDbId, [[maybe_unused]] const SyncPath &itemPath,
- bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress) -> bool {
- isPlaceholder = true;
- isHydrated = false;
- isSyncing = false;
- progress = 0;
- return true;
- });
-
+ mockVfs->setVfsStatusOutput(true, false, false, 0);
bool isDehydratedPlaceholder = false;
_executorWorker->checkLiteSyncInfoForCreate(opPtr, "/", isDehydratedPlaceholder);
@@ -130,15 +116,7 @@ void TestExecutorWorker::testCheckLiteSyncInfoForCreate() {
// A partially hydrated placeholder (syncing item).
{
- _syncPal->setVfsStatusCallback([]([[maybe_unused]] int syncDbId, [[maybe_unused]] const SyncPath &itemPath,
- bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress) -> bool {
- isPlaceholder = true;
- isHydrated = false;
- isSyncing = true;
- progress = 30;
- return true;
- });
-
+ mockVfs->setVfsStatusOutput(true, false, true, 0);
bool isDehydratedPlaceholder = false;
_executorWorker->checkLiteSyncInfoForCreate(opPtr, "/", isDehydratedPlaceholder);
@@ -147,15 +125,7 @@ void TestExecutorWorker::testCheckLiteSyncInfoForCreate() {
// Not a placeholder.
{
- _syncPal->setVfsStatusCallback([]([[maybe_unused]] int syncDbId, [[maybe_unused]] const SyncPath &itemPath,
- bool &isPlaceholder, bool &isHydrated, bool &isSyncing, int &progress) -> bool {
- isPlaceholder = false;
- isHydrated = false;
- isSyncing = false;
- progress = 0;
- return true;
- });
-
+ mockVfs->setVfsStatusOutput(false, false, false, 0);
bool isDehydratedPlaceholder = false;
_executorWorker->checkLiteSyncInfoForCreate(opPtr, "/", isDehydratedPlaceholder);
@@ -210,7 +180,7 @@ SyncOpPtr TestExecutorWorker::generateSyncOperationWithNestedNodes(const DbNodeI
class ExecutorWorkerMock : public ExecutorWorker {
public:
ExecutorWorkerMock(std::shared_ptr syncPal, const std::string &name, const std::string &shortName) :
- ExecutorWorker(syncPal, name, shortName) {};
+ ExecutorWorker(syncPal, name, shortName){};
using ArgsMap = std::map, std::shared_ptr>;
void setCorrespondingNodeInOtherTree(ArgsMap nodeMap) { _correspondingNodeInOtherTree = nodeMap; };
@@ -258,20 +228,6 @@ void TestExecutorWorker::testIsValidDestination() {
const auto root = _syncPal->updateTree(ReplicaSide::Remote)->rootNode();
- // False if the item created on the local replica is not at the root of the synchronisation folder and has a
- // corresponding parent node with no id.
- {
- const auto correspondingParentNode = std::make_shared(
- 666, ReplicaSide::Remote, Str("parent_dir"), NodeType::Directory, OperationType::None, std::nullopt,
- testhelpers::defaultTime, testhelpers::defaultTime, testhelpers::defaultFileSize, root);
-
-
- SyncOpPtr op = generateSyncOperationWithNestedNodes(1, Str("test_file.txt"), OperationType::Create, NodeType::File);
- executorWorkerMock->setCorrespondingNodeInOtherTree({{op->affectedNode()->parentNode(), correspondingParentNode}});
- op->setTargetSide(ReplicaSide::Remote);
- CPPUNIT_ASSERT(!executorWorkerMock->isValidDestination(op));
- }
-
const auto correspondingParentCommonDocsNode = std::make_shared(
666, ReplicaSide::Remote, Utility::commonDocumentsFolderName(), NodeType::Directory, OperationType::None,
"common_docs_id", testhelpers::defaultTime, testhelpers::defaultTime, testhelpers::defaultFileSize, root);
diff --git a/test/libsyncengine/propagation/executor/testexecutorworker.h b/test/libsyncengine/propagation/executor/testexecutorworker.h
index 8d2d47a23..6b7bb6a37 100644
--- a/test/libsyncengine/propagation/executor/testexecutorworker.h
+++ b/test/libsyncengine/propagation/executor/testexecutorworker.h
@@ -24,6 +24,33 @@
namespace KDC {
+class MockVfs : public VfsOff {
+ Q_OBJECT
+ public:
+ explicit MockVfs() : VfsOff(vfsSetupParams) {}
+ void setVfsStatusOutput(bool isPlaceholder, bool isHydrated, bool isSyncing, int progress) {
+ vfsStatusIsHydrated = isHydrated;
+ vfsStatusIsSyncing = isSyncing;
+ vfsStatusIsPlaceholder = isPlaceholder;
+ vfsStatusProgress = progress;
+ }
+ ExitInfo status([[maybe_unused]] const SyncPath &filePath, bool &isPlaceholder, bool &isHydrated, bool &isSyncing,
+ int &progress) override {
+ isHydrated = vfsStatusIsHydrated;
+ isSyncing = vfsStatusIsSyncing;
+ isPlaceholder = vfsStatusIsPlaceholder;
+ progress = vfsStatusProgress;
+ return ExitCode::Ok;
+ }
+
+ private:
+ bool vfsStatusIsHydrated = false;
+ bool vfsStatusIsSyncing = false;
+ bool vfsStatusIsPlaceholder = false;
+ int vfsStatusProgress = 0;
+ VfsSetupParams vfsSetupParams;
+};
+
class TestExecutorWorker : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(TestExecutorWorker);
CPPUNIT_TEST(testCheckLiteSyncInfoForCreate);
diff --git a/test/libsyncengine/update_detection/file_system_observer/testlocalfilesystemobserverworker.cpp b/test/libsyncengine/update_detection/file_system_observer/testlocalfilesystemobserverworker.cpp
index c55ac792c..81e956976 100644
--- a/test/libsyncengine/update_detection/file_system_observer/testlocalfilesystemobserverworker.cpp
+++ b/test/libsyncengine/update_detection/file_system_observer/testlocalfilesystemobserverworker.cpp
@@ -84,9 +84,7 @@ void TestLocalFileSystemObserverWorker::setUp() {
_syncPal->createSharedObjects();
_syncPal->setLocalPath(_rootFolderPath);
_syncPal->_tmpBlacklistManager = std::make_shared(_syncPal);
- _syncPal->setVfsStatusCallback(&vfsStatus); // Do nothing
- _syncPal->setVfsPinStateCallback(&vfsPinState); // Do nothing
- _syncPal->setVfsFileStatusChangedCallback(&vfsFileStatusChanged); // Do nothing
+ _syncPal->setVfsPtr(std::make_shared());
#if defined(_WIN32)
_syncPal->_localFSObserverWorker = std::shared_ptr(
diff --git a/test/server/CMakeLists.txt b/test/server/CMakeLists.txt
index 596db3937..f36174c0e 100644
--- a/test/server/CMakeLists.txt
+++ b/test/server/CMakeLists.txt
@@ -10,8 +10,6 @@ set(testserver_NAME ${APPLICATION_NAME}_test_server)
set(server_srcs_path ${CMAKE_SOURCE_DIR}/src/server)
set(server_SRCS
- ${CMAKE_SOURCE_DIR}/src/libcommonserver/vfs.h ${CMAKE_SOURCE_DIR}/src/libcommonserver/vfs.cpp
- ${CMAKE_SOURCE_DIR}/src/libcommonserver/plugin.h ${CMAKE_SOURCE_DIR}/src/libcommonserver/plugin.cpp
${server_srcs_path}/logarchiver/logarchiver.h ${server_srcs_path}/logarchiver/logarchiver.cpp
${server_srcs_path}/socketapi.h ${server_srcs_path}/socketapi.cpp
${server_srcs_path}/socketlistener.h ${server_srcs_path}/socketlistener.cpp
diff --git a/test/server/workers/testworkers.cpp b/test/server/workers/testworkers.cpp
index f01634510..adb207acc 100644
--- a/test/server/workers/testworkers.cpp
+++ b/test/server/workers/testworkers.cpp
@@ -48,33 +48,6 @@ bool TestWorkers::_vfsConnectionDone = false;
constexpr bool connectorsAreAlreadyInstalled = false;
#endif
-bool TestWorkers::createPlaceholder(int syncDbId, const SyncPath &relativeLocalPath, const SyncFileItem &item) {
- (void) syncDbId;
-
- if (_vfsPtr && !_vfsPtr->createPlaceholder(relativeLocalPath, item)) {
- return false;
- }
- return true;
-}
-
-bool TestWorkers::convertToPlaceholder(int syncDbId, const SyncPath &relativeLocalPath, const SyncFileItem &item) {
- (void) syncDbId;
-
- if (_vfsPtr && !_vfsPtr->convertToPlaceholder(Path2QStr(relativeLocalPath), item)) {
- return false;
- }
- return true;
-}
-
-bool TestWorkers::setPinState(int syncDbId, const SyncPath &relativeLocalPath, PinState pinState) {
- (void) syncDbId;
-
- if (_vfsPtr && !_vfsPtr->setPinState(Path2QStr(relativeLocalPath), pinState)) {
- return false;
- }
- return true;
-}
-
void TestWorkers::setUp() {
_logger = Log::instance()->getLogger();
@@ -154,9 +127,7 @@ void TestWorkers::setUp() {
_syncPal->createWorkers();
_syncPal->syncDb()->setAutoDelete(true);
_syncPal->createProgressInfo();
- _syncPal->setVfsCreatePlaceholderCallback(createPlaceholder);
- _syncPal->setVfsConvertToPlaceholderCallback(convertToPlaceholder);
- _syncPal->setVfsSetPinStateCallback(setPinState);
+ _syncPal->setVfsPtr(_vfsPtr);
// Setup SocketApi
std::unordered_map> syncPalMap;
@@ -241,14 +212,12 @@ void TestWorkers::testCreatePlaceholder() {
// Folder doesn't exist (normal case)
exitInfo = _syncPal->_executorWorker->createPlaceholder(relativeFolderPath);
- CPPUNIT_ASSERT_EQUAL(ExitCode::Ok, exitInfo.code());
- CPPUNIT_ASSERT_EQUAL(ExitCause::Unknown, exitInfo.cause());
+ CPPUNIT_ASSERT_EQUAL(ExitInfo(ExitCode::Ok), exitInfo);
#if defined(__APPLE__) || defined(_WIN32)
// Folder already exists
exitInfo = _syncPal->_executorWorker->createPlaceholder(relativeFolderPath);
- CPPUNIT_ASSERT_EQUAL(ExitCode::DataError, exitInfo.code());
- CPPUNIT_ASSERT_EQUAL(ExitCause::FileAlreadyExist, exitInfo.cause());
+ CPPUNIT_ASSERT_EQUAL(ExitInfo(ExitCode::SystemError, ExitCause::FileAlreadyExist), exitInfo);
#endif
}
@@ -276,7 +245,8 @@ void TestWorkers::testCreatePlaceholder() {
CPPUNIT_ASSERT_EQUAL(ExitCode::SystemError, exitInfo.code());
CPPUNIT_ASSERT_EQUAL(ExitCause::FileAccessError, exitInfo.cause());
#else
- // Strangely (bug?), the Windows api is able to create a placeholder in a folder for which the user does not have rights
+ // Strangely (bug?), the Windows api is able to create a placeholder in a folder for which the user does not have
+ // rights
CPPUNIT_ASSERT_EQUAL(ExitCode::Ok, exitInfo.code());
CPPUNIT_ASSERT_EQUAL(ExitCause::Unknown, exitInfo.cause());
@@ -302,8 +272,7 @@ void TestWorkers::testCreatePlaceholder() {
#if defined(__APPLE__) || defined(_WIN32)
// File already exists
exitInfo = _syncPal->_executorWorker->createPlaceholder(relativeFilePath);
- CPPUNIT_ASSERT_EQUAL(ExitCode::DataError, exitInfo.code());
- CPPUNIT_ASSERT_EQUAL(ExitCause::FileAlreadyExist, exitInfo.cause());
+ CPPUNIT_ASSERT_EQUAL(ExitInfo(ExitCode::SystemError, ExitCause::FileAlreadyExist), exitInfo);
#endif
}
}
@@ -314,8 +283,7 @@ void TestWorkers::testConvertToPlaceholder() {
// Progress not intialized
{
exitInfo = _syncPal->_executorWorker->convertToPlaceholder(SyncPath("dummy"), true);
- CPPUNIT_ASSERT_EQUAL(ExitCode::DataError, exitInfo.code());
- CPPUNIT_ASSERT_EQUAL(ExitCause::InvalidSnapshot, exitInfo.cause());
+ CPPUNIT_ASSERT_EQUAL(ExitInfo(ExitCode::DataError, ExitCause::InvalidSnapshot), exitInfo);
}
// Convert folder operation
@@ -330,8 +298,7 @@ void TestWorkers::testConvertToPlaceholder() {
#if defined(__APPLE__) || defined(_WIN32)
// Folder doesn't exist
exitInfo = _syncPal->_executorWorker->convertToPlaceholder(relativeFolderPath, true);
- CPPUNIT_ASSERT_EQUAL(ExitCode::DataError, exitInfo.code());
- CPPUNIT_ASSERT_EQUAL(ExitCause::InvalidSnapshot, exitInfo.cause());
+ CPPUNIT_ASSERT_EQUAL(ExitInfo(ExitCode::SystemError, ExitCause::NotFound), exitInfo);
#endif
// Folder already exists (normal case)
@@ -339,8 +306,7 @@ void TestWorkers::testConvertToPlaceholder() {
CPPUNIT_ASSERT(std::filesystem::create_directory(_syncPal->localPath() / relativeFolderPath, ec) && ec.value() == 0);
exitInfo = _syncPal->_executorWorker->convertToPlaceholder(relativeFolderPath, true);
- CPPUNIT_ASSERT_EQUAL(ExitCode::Ok, exitInfo.code());
- CPPUNIT_ASSERT_EQUAL(ExitCause::Unknown, exitInfo.cause());
+ CPPUNIT_ASSERT_EQUAL(ExitInfo(ExitCode::Ok), exitInfo);
}
// Convert file operation
@@ -350,6 +316,7 @@ void TestWorkers::testConvertToPlaceholder() {
syncItem.setPath(relativeFilePath);
syncItem.setType(NodeType::File);
syncItem.setDirection(SyncDirection::Down);
+ syncItem.setRemoteNodeId("1");
CPPUNIT_ASSERT(_syncPal->initProgress(syncItem));
#if defined(__APPLE__) || defined(_WIN32)
@@ -359,8 +326,15 @@ void TestWorkers::testConvertToPlaceholder() {
ioError == IoError::Success);
exitInfo = _syncPal->_executorWorker->createPlaceholder(relativeFilePath);
- CPPUNIT_ASSERT_EQUAL(ExitCode::SystemError, exitInfo.code());
- CPPUNIT_ASSERT_EQUAL(ExitCause::FileAccessError, exitInfo.cause());
+#if defined(__APPLE__)
+ CPPUNIT_ASSERT_EQUAL(ExitInfo(ExitCode::SystemError, ExitCause::FileAccessError), exitInfo);
+#else
+ // Strangely (bug?), the Windows api is able to create a placeholder in a folder for which the user does not have
+ // rights
+ CPPUNIT_ASSERT_EQUAL(ExitInfo(ExitCode::Ok), exitInfo);
+ CPPUNIT_ASSERT(IoHelper::deleteItem(_syncPal->localPath() / relativeFilePath, ioError));
+ CPPUNIT_ASSERT_EQUAL(IoError::Success, ioError);
+#endif
ioError = IoError::Unknown;
CPPUNIT_ASSERT(IoHelper::setRights(_syncPal->localPath() / relativeFolderPath, true, true, true, ioError) &&
@@ -368,8 +342,7 @@ void TestWorkers::testConvertToPlaceholder() {
// File doesn't exist
exitInfo = _syncPal->_executorWorker->convertToPlaceholder(relativeFilePath, true);
- CPPUNIT_ASSERT_EQUAL(ExitCode::DataError, exitInfo.code());
- CPPUNIT_ASSERT_EQUAL(ExitCause::InvalidSnapshot, exitInfo.cause());
+ CPPUNIT_ASSERT_EQUAL(ExitInfo(ExitCode::SystemError, ExitCause::NotFound), exitInfo);
#endif
// File already exists (normal case)
@@ -379,8 +352,9 @@ void TestWorkers::testConvertToPlaceholder() {
}
exitInfo = _syncPal->_executorWorker->convertToPlaceholder(relativeFilePath, true);
- CPPUNIT_ASSERT_EQUAL(ExitCode::Ok, exitInfo.code());
- CPPUNIT_ASSERT_EQUAL(ExitCause::Unknown, exitInfo.cause());
+ (CppUnit::assertEquals((ExitInfo(ExitCode::Ok)), (exitInfo),
+ CppUnit::SourceLine("C:\\Projects\\desktop-kDrive\\test\\server\\workers\\testworkers.cpp", 374),
+ ""));
}
}
diff --git a/test/server/workers/testworkers.h b/test/server/workers/testworkers.h
index 7ae4d3c8f..891119ae3 100644
--- a/test/server/workers/testworkers.h
+++ b/test/server/workers/testworkers.h
@@ -48,9 +48,6 @@ class TestWorkers : public CppUnit::TestFixture {
protected:
static bool startVfs();
- static bool createPlaceholder(int syncDbId, const SyncPath &relativeLocalPath, const SyncFileItem &item);
- static bool convertToPlaceholder(int syncDbId, const SyncPath &relativeLocalPath, const SyncFileItem &item);
- static bool setPinState(int syncDbId, const SyncPath &relativeLocalPath, PinState pinState);
log4cplus::Logger _logger;
std::shared_ptr _syncPal;