Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kdesktop 1359 vfs functions should return an exit info #404

Open
wants to merge 96 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
433af19
Convert return type of Vfs::start and Vfs::startImpl from bool to Exi…
herve-er Nov 22, 2024
4886cdb
Remove unused Vfs::isHydrating.
herve-er Nov 22, 2024
30d3eb0
Convert return type of Vfs::updateMetadata and from bool to ExitInfo.
herve-er Nov 22, 2024
8338aec
Convert return type of Vfs::updateMetadata and from bool to ExitInfo …
herve-er Nov 22, 2024
de04c2d
Fix log.
herve-er Nov 25, 2024
bb03a34
Convert return type of Vfs::createPlaceholder from bool to ExitInfo.
herve-er Nov 25, 2024
39dc17f
Convert return type of Vfs::createPlaceholder from bool to ExitInfo. 2
herve-er Nov 25, 2024
f823148
Convert return type of Vfs::convertToPlaceHolder from bool to ExitInfo.
herve-er Nov 25, 2024
c46ab58
Merge branch 'develop' into KDESKTOP-1359-Vfs-functions-should-return…
herve-er Nov 25, 2024
50210bd
Convert return type of Vfs::convertToPlaceHolder from bool to ExitInf…
herve-er Nov 25, 2024
98e4908
Merge branch 'KDESKTOP-1359-Vfs-functions-should-return-an-ExitInfo' …
herve-er Nov 25, 2024
8126145
Remove unused Vfs::needsMetadataUpdate.
herve-er Nov 25, 2024
d5dea10
Fix file access typo.
herve-er Nov 25, 2024
cac7627
Convert return type of Vfs::updateFetchStatus from bool to ExitInfo.
herve-er Nov 25, 2024
4e62c48
Fix call to getXAttrValue.
herve-er Nov 25, 2024
159ec24
Fix tests.
herve-er Nov 25, 2024
93ad883
Fix liteSyncconnector.mm
herve-er Nov 25, 2024
865fc21
Fixe tests.
herve-er Nov 25, 2024
2b8706e
fix vfs_mac
herve-er Nov 25, 2024
3ef5927
Convert return type of Vfs::forceStatus from bool to ExitInfo.
herve-er Nov 25, 2024
6133157
Revert macOS change
herve-er Nov 25, 2024
6b1b8f4
Convert return type of Vfs::setPinstate from bool to ExitInfo.
herve-er Nov 25, 2024
02d62cd
Convert return type of Vfs::Status from bool to ExitInfo.
herve-er Nov 25, 2024
8ea1990
Fusion
herve-er Nov 26, 2024
89a8c0a
Convert setThumbnail & setAppExcludeList & getFetchingAppList return …
herve-er Nov 26, 2024
1c08e10
Continue the propagation of ExitInfo and add comment on possible Exit…
herve-er Nov 28, 2024
8cea04c
Add VfsWinExitInfo
herve-er Nov 29, 2024
fb6d0af
Revert "Add VfsWinExitInfo"
herve-er Nov 29, 2024
c9d275d
Add NotFound and FileAccessError in vfsWin.
herve-er Nov 29, 2024
5a20598
Fix comments.
herve-er Dec 3, 2024
67bec39
Return ExitCode::LogicError in case of missing vfsCallBack.
herve-er Dec 3, 2024
c91bcce
Correct handling of vfs error
herve-er Dec 4, 2024
d14c3ee
Remove a log
herve-er Dec 4, 2024
b1dada9
Implement source location and add it to ExitInfo.
herve-er Dec 4, 2024
fd972b3
Merge branch 'develop' into KDESKTOP-1359-Vfs-functions-should-return…
herve-er Dec 4, 2024
bacd051
Fix wrong if condition
herve-er Dec 4, 2024
627049f
Merge branch 'KDESKTOP-1359-Vfs-functions-should-return-an-ExitInfo' …
herve-er Dec 4, 2024
1b2c274
Edit print format of SourceLocation.
herve-er Dec 4, 2024
61b7948
Merge branch 'develop' into KDESKTOP-1359-Vfs-functions-should-return…
herve-er Dec 5, 2024
f5b1e13
Fix buid.
herve-er Dec 9, 2024
c7159c4
Merge branch 'develop' into KDESKTOP-1359-Vfs-functions-should-return…
herve-er Dec 9, 2024
143be6f
Fix a LOG macro.
herve-er Dec 9, 2024
7dfe630
Merge branch 'KDESKTOP-1359-Vfs-functions-should-return-an-ExitInfo' …
herve-er Dec 9, 2024
eda5917
Use SourceLocation for Vfs::handleVfsError
herve-er Dec 9, 2024
6d7219d
ExitInfo in vfs_mac
herve-er Dec 9, 2024
5db6b9f
Fx build.
herve-er Dec 9, 2024
9b61586
Fix macOS build.
herve-er Dec 9, 2024
21b30dc
Fix macOS build.
herve-er Dec 9, 2024
dd589cb
Fix macOS test.
herve-er Dec 9, 2024
96a4b45
Fix vfs_mac build.
herve-er Dec 9, 2024
ad94069
Sonar issue.
herve-er Dec 9, 2024
6019442
fix mac build.
herve-er Dec 9, 2024
9bc7ead
Missing QStr2Path
herve-er Dec 9, 2024
3b06f33
Fix testSourceLocation
herve-er Dec 9, 2024
d160e46
Fix TestExecutorWorker::testIsValidDestination
herve-er Dec 9, 2024
30108bf
More useful insight in case of test faillure.
herve-er Dec 9, 2024
2bedb3c
Fix tests
herve-er Dec 10, 2024
2d0fc28
Merge branch 'develop' into KDESKTOP-1359-Vfs-functions-should-return…
herve-er Dec 10, 2024
582d0cf
Sonar issue part 1
herve-er Dec 10, 2024
226b373
Merge branch 'KDESKTOP-1359-Vfs-functions-should-return-an-ExitInfo' …
herve-er Dec 10, 2024
9a2674b
Sonar issues part 2
herve-er Dec 10, 2024
f27705a
Merge branch 'develop' into KDESKTOP-1359-Vfs-functions-should-return…
herve-er Dec 10, 2024
d42b92a
Catch SystemError FileAlreadyExists.
herve-er Dec 10, 2024
030b85c
Merge branch 'KDESKTOP-1359-Vfs-functions-should-return-an-ExitInfo' …
herve-er Dec 10, 2024
d7c77eb
Fix build
herve-er Dec 10, 2024
405f623
Fix handleExecutorError switch
herve-er Dec 10, 2024
fde6b46
Remove duplicated line.
herve-er Dec 10, 2024
2462afa
Revert "Remove duplicated line."
herve-er Dec 10, 2024
d4e7ff0
Remove duplicated line.
herve-er Dec 10, 2024
173e527
Reduce code duplication.
herve-er Dec 10, 2024
5a93804
Reduce code duplication.
herve-er Dec 10, 2024
a8eacbd
Fusion.
herve-er Dec 10, 2024
6bbd21b
Reduce code duplication
herve-er Dec 11, 2024
bf2c7f0
Self reveiw.
herve-er Dec 11, 2024
ac4daaf
Remove vfs callback in appserver.
herve-er Dec 11, 2024
bd9abee
Replace QString with SyncPath in VFS function signatures.
herve-er Dec 12, 2024
4101d24
Merge branch 'develop' into KDESKTOP-1359-Vfs-functions-should-return…
herve-er Dec 12, 2024
0273c0d
Fix Sonar issue
herve-er Dec 12, 2024
e07fa27
Merge branch 'KDESKTOP-1359-Vfs-functions-should-return-an-ExitInfo' …
herve-er Dec 12, 2024
3368732
Fix macOs test
herve-er Dec 12, 2024
7e1ed53
Merge branch 'develop' into KDESKTOP-1359-Vfs-functions-should-return…
herve-er Dec 12, 2024
d8750cd
Fix macOs test
herve-er Dec 12, 2024
529b11a
Merge branch 'KDESKTOP-1359-Vfs-functions-should-return-an-ExitInfo' …
herve-er Dec 12, 2024
64b4aaa
Fix cmakes.
herve-er Dec 12, 2024
5fbccd9
Remove commented code.
herve-er Dec 12, 2024
74b7ca4
Fix vfs_mac.cpp
herve-er Dec 12, 2024
1e9a8c0
Fix vfs_mac.cpp
herve-er Dec 12, 2024
c12d432
Remove unused variables.
herve-er Dec 12, 2024
b54fd59
Solve conflict.
herve-er Dec 20, 2024
4300ab7
Merge conflict.
herve-er Dec 20, 2024
e62e234
Remove a sub test in testIsValidDestination as it is now impossible t…
herve-er Dec 20, 2024
27865e1
Merge branch 'develop' into KDESKTOP-1359-Vfs-functions-should-return…
herve-er Jan 3, 2025
692a689
Fix develop merge.
herve-er Jan 3, 2025
f1afeb5
Fix merge.
herve-er Jan 3, 2025
588f4d1
Merge branch 'develop' into KDESKTOP-1359-Vfs-functions-should-return…
herve-er Jan 8, 2025
3e21b3b
Merge branch 'develop' into KDESKTOP-1359-Vfs-functions-should-return…
herve-er Jan 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions src/libcommon/utility/sourcelocation.h
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/

#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 <source_location>
#endif // SRC_LOC_AVALAIBALE

#include <filesystem>
#include <string>

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
28 changes: 23 additions & 5 deletions src/libcommon/utility/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <string>
Expand All @@ -28,6 +27,7 @@
#include <variant>
#include <qdebug.h>
#include <signal.h>
#include "sourcelocation.h"

namespace KDC {

Expand Down Expand Up @@ -230,32 +230,50 @@ 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; }

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);

Expand Down
5 changes: 5 additions & 0 deletions src/libcommonserver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
Expand Down
156 changes: 134 additions & 22 deletions src/libcommonserver/vfs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down
Loading
Loading