Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ add_feature_info(AppImageUpdate WITH_APPIMAGEUPDATER "Built-in libappimageupdate
option(WITH_EXTERNAL_BRANDING "A URL to an external branding repo" "")

# specify additional vfs plugins
set(VIRTUAL_FILE_SYSTEM_PLUGINS off cfapi CACHE STRING "Name of internal plugin in src/libsync/vfs or the locations of virtual file plugins")
set(VIRTUAL_FILE_SYSTEM_PLUGINS xattr off cfapi CACHE STRING "Name of internal plugin in src/libsync/vfs or the locations of virtual file plugins")

if(APPLE)
set( SOCKETAPI_TEAM_IDENTIFIER_PREFIX "" CACHE STRING "SocketApi prefix (including a following dot) that must match the codesign key's TeamIdentifier/Organizational Unit" )
Expand Down
1 change: 1 addition & 0 deletions src/gui/folder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,7 @@ void Folder::registerFolderWatcher()
_folderWatcher.reset(new FolderWatcher(this));
connect(_folderWatcher.data(), &FolderWatcher::pathChanged, this,
[this](const QSet<QString> &paths) { slotWatchedPathsChanged(paths, Folder::ChangeReason::Other); });

connect(_folderWatcher.data(), &FolderWatcher::changesDetected, this, [this] {
// don't set to not yet started if a sync is already running
if (!isSyncRunning()) {
Expand Down
3 changes: 2 additions & 1 deletion src/gui/folder.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ class OPENCLOUD_GUI_EXPORT Folder : public QObject
public:
enum class ChangeReason {
Other,
UnLock
UnLock,
XAttr
};
Q_ENUM(ChangeReason)

Expand Down
3 changes: 2 additions & 1 deletion src/gui/folderwatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ FolderWatcher::FolderWatcher(Folder *folder)
_timer.setInterval(notificationTimeoutC);
_timer.setSingleShot(true);
connect(&_timer, &QTimer::timeout, this, [this] {
auto paths = popChangeSet();
_timer.stop();
auto paths = std::move(_changeSet);
Q_ASSERT(!paths.empty());
if (!paths.isEmpty()) {
qCInfo(lcFolderWatcher) << u"Detected changes in paths:" << paths;
Expand Down
6 changes: 5 additions & 1 deletion src/gui/folderwatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,19 @@ class OPENCLOUD_GUI_EXPORT FolderWatcher : public QObject
/// For testing linux behavior only
int testLinuxWatchCount() const;


// pop the accumulated changes
QSet<QString> popChangeSet();


Q_SIGNALS:
/** Emitted when one of the watched directories or one
* of the contained files is changed. */
void pathChanged(const QSet<QString> &path);

/** Emitted when an extended file attribute changed on one
* of the files in the list */
void xattrChanged(const QSet<QString> &path);

/**
* We detected a file change, this signal can be used to trigger the prepareSync state
*/
Expand Down
3 changes: 2 additions & 1 deletion src/gui/folderwatcher_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ void FolderWatcherPrivate::slotReceivedNotification(int fd)
// Filter out journal changes - redundant with filtering in FolderWatcher::pathIsIgnored.
if (fileName.startsWith("._sync_")
|| fileName.startsWith(".csync_journal.db")
|| fileName.startsWith(".sync_")) {
|| fileName.startsWith(".sync_")
|| fileName == QByteArrayLiteral(".OpenCloudSync.log") ) {
continue;
}

Expand Down
7 changes: 6 additions & 1 deletion src/gui/folderwizard/folderwizard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,12 @@ const AccountStatePtr &FolderWizardPrivate::accountState()

bool FolderWizardPrivate::useVirtualFiles() const
{
return VfsPluginManager::instance().bestAvailableVfsMode() == Vfs::WindowsCfApi;
const auto bavm = VfsPluginManager::instance().bestAvailableVfsMode();
if (Utility::isWindows())
return bavm == Vfs::WindowsCfApi;
if (Utility::isLinux())
return bavm == Vfs::XAttr;
return false;
}

FolderWizard::FolderWizard(const AccountStatePtr &account, QWidget *parent)
Expand Down
24 changes: 23 additions & 1 deletion src/gui/socketapi/socketapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ SocketApi::SocketApi(QObject *parent)
unregisterAccount(accountState->account());
}
});

const QJsonObject args { { QStringLiteral("size"), 5 } };
const QJsonObject obj { { QStringLiteral("id"), QString::number(17) }, { QStringLiteral("arguments"), args } };
const auto json = QJsonDocument(obj).toJson(QJsonDocument::Indented);

qCDebug(lcSocketApi) << u"JSON:" << json;

}

SocketApi::~SocketApi()
Expand Down Expand Up @@ -283,7 +290,7 @@ void SocketApi::slotReadSocket()
}
} else if (command.startsWith(QLatin1String("V2/"))) {
QJsonParseError error;
const auto json = QJsonDocument::fromJson(argument.toUtf8(), &error).object();
const auto json = QJsonDocument::fromJson(argument.trimmed().toUtf8(), &error).object();
if (error.error != QJsonParseError::NoError) {
qCWarning(lcSocketApi()) << u"Invalid json" << argument << error.errorString();
listener->sendError(error.errorString());
Expand Down Expand Up @@ -709,6 +716,21 @@ void SocketApi::command_V2_GET_CLIENT_ICON(const QSharedPointer<SocketApiJobV2>
job->success({ { QStringLiteral("png"), QString::fromUtf8(data) } });
}

void SocketApi::command_V2_HYDRATE_FILE(const QSharedPointer<SocketApiJobV2> &job) const
{
OC_ASSERT(job);
const auto &arguments = job->arguments();

const auto &file = arguments[QStringLiteral("file")].toString();

auto fileData = FileData::get(file);

if (fileData.folder) {
// call the getfile job to hydrate
}
job->success({ {QStringLiteral("hydration"), QStringLiteral("STARTED") } });
}

void SocketApi::emailPrivateLink(const QUrl &link)
{
Utility::openEmailComposer(
Expand Down
3 changes: 3 additions & 0 deletions src/gui/socketapi/socketapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ private Q_SLOTS:
Q_INVOKABLE void command_OPEN_APP_LINK(const QString &localFile, SocketListener *listener);
// External sync
Q_INVOKABLE void command_V2_LIST_ACCOUNTS(const QSharedPointer<SocketApiJobV2> &job) const;
// VFS
Q_INVOKABLE void command_V2_HYDRATE_FILE(const QSharedPointer<SocketApiJobV2> &job) const;


// Sends the id and the client icon as PNG image (base64 encoded) in Json key "png"
// e.g. { "id" : "1", "arguments" : { "png" : "hswehs343dj8..." } } or an error message in key "error"
Expand Down
1 change: 1 addition & 0 deletions src/libsync/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ target_sources(libsync PRIVATE
utility.cpp
remotepermissions.cpp
vfs.cpp
hydrationjob.cpp
pinstate.cpp
plugin.cpp
restartmanager.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/

#include "plugins/vfs/cfapi/hydrationjob.h"

#include "plugins/vfs/cfapi/cfapiwrapper.h"
#include "plugins/vfs/cfapi/vfs_cfapi.h"
#include "hydrationjob.h"

#include "libsync/common/syncjournaldb.h"
#include "libsync/common/vfs.h"
#include "libsync/filesystem.h"
#include "libsync/networkjobs/getfilejob.h"

Expand All @@ -19,7 +17,7 @@ using namespace Qt::Literals::StringLiterals;

Q_LOGGING_CATEGORY(lcHydration, "sync.vfs.hydrationjob", QtDebugMsg)

OCC::HydrationJob::HydrationJob(const CfApiWrapper::CallBackContext &context)
OCC::HydrationJob::HydrationJob(const CallBackContext &context)
: QObject(context.vfs)
, _context(context)
{
Expand Down Expand Up @@ -103,7 +101,7 @@ OCC::HydrationJob::Status OCC::HydrationJob::status() const
return _status;
}

const OCC::CfApiWrapper::CallBackContext OCC::HydrationJob::context() const
const OCC::CallBackContext OCC::HydrationJob::context() const
{
return _context;
}
Expand Down Expand Up @@ -132,21 +130,22 @@ void OCC::HydrationJob::start()
Q_ASSERT(_localRoot.endsWith('/'_L1));

const auto startServer = [this](const QString &serverName) -> QLocalServer * {
QLocalServer::removeServer(serverName);
const auto server = new QLocalServer(this);
const auto listenResult = server->listen(serverName);
if (!listenResult) {
qCCritical(lcHydration) << u"Couldn't get server to listen" << serverName << _localRoot << _context;
//qCCritical(lcHydration) << u"Couldn't get server to listen" << serverName << _localRoot << _context;
if (!_isCancelled) {
emitFinished(Status::Error);
}
return nullptr;
}
qCInfo(lcHydration) << u"Server ready, waiting for connections" << serverName << _localRoot << _context;
// qCInfo(lcHydration) << u"Server ready, waiting for connections" << serverName << _localRoot << _context;
return server;
};

// Start cancellation server
_signalServer = startServer(_context.requestHexId() + u":cancellation"_s);
_signalServer = startServer(_context.requestHexId() + QStringLiteral(":cancellation"));
Q_ASSERT(_signalServer);
if (!_signalServer) {
return;
Expand Down Expand Up @@ -209,7 +208,7 @@ void OCC::HydrationJob::onCancellationServerNewConnection()
{
Q_ASSERT(!_signalSocket);

qCInfo(lcHydration) << u"Got new connection on cancellation server" << _context;
// qCInfo(lcHydration) << u"Got new connection on cancellation server" << _context;
_signalSocket = _signalServer->nextPendingConnection();
}

Expand All @@ -220,7 +219,7 @@ void OCC::HydrationJob::onNewConnection()
handleNewConnection();
}

void OCC::HydrationJob::finalize(OCC::VfsCfApi *vfs)
void OCC::HydrationJob::finalize(OCC::Vfs *vfs)
{
auto item = SyncFileItem::fromSyncJournalFileRecord(_record);
if (_isCancelled) {
Expand All @@ -246,10 +245,10 @@ void OCC::HydrationJob::finalize(OCC::VfsCfApi *vfs)
FileSystem::getInode(FileSystem::toFilesystemPath(localFilePathAbs()), &item->_inode);
const auto result = _journal->setFileRecord(SyncJournalFileRecord::fromSyncFileItem(*item));
if (!result) {
qCWarning(lcHydration) << u"Error when setting the file record to the database" << _context << result.error();
// qCWarning(lcHydration) << u"Error when setting the file record to the database" << _context << result.error();
}
} else {
qCWarning(lcHydration) << u"Hydration succeeded but the file appears to be moved" << _context;
// qCWarning(lcHydration) << u"Hydration succeeded but the file appears to be moved" << _context;
}
}

Expand All @@ -271,9 +270,9 @@ void OCC::HydrationJob::onGetFinished()
}
}
if (!_errorString.isEmpty()) {
qCInfo(lcHydration) << u"GETFileJob finished" << _context << _errorCode << _statusCode << _errorString;
// qCInfo(lcHydration) << u"GETFileJob finished" << _context << _errorCode << _statusCode << _errorString;
} else {
qCInfo(lcHydration) << u"GETFileJob finished" << _context;
// qCInfo(lcHydration) << u"GETFileJob finished" << _context;
}
if (_isCancelled) {
_errorCode = QNetworkReply::NoError;
Expand All @@ -292,7 +291,8 @@ void OCC::HydrationJob::onGetFinished()

void OCC::HydrationJob::handleNewConnection()
{
qCInfo(lcHydration) << u"Got new connection starting GETFileJob" << _context;
// FIXME: Fix all the loggings which require the operator<< from vfs.cpp for CallBackContext
// qCInfo(lcHydration) << u"Got new connection starting GETFileJob" << _context;
_transferDataSocket = _transferDataServer->nextPendingConnection();
_job = new GETFileJob(_account, _remoteSyncRootPath, _remoteFilePathRel, _transferDataSocket, {}, {}, 0, this);
_job->setExpectedContentLength(_record.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*/
#pragma once

#include "cfapiwrapper.h"
#include "libsync/account.h"
#include "libsync/common/syncjournalfilerecord.h"

Expand All @@ -16,7 +15,18 @@ class QLocalSocket;
namespace OCC {
class GETFileJob;
class SyncJournalDb;
class VfsCfApi;
class Vfs;

struct CallBackContext
{
OCC::Vfs *vfs;
QString path;
int64_t requestId;
QByteArray fileId;
QMap<QByteArray, QVariant> extraArgs;

inline QString requestHexId() const { return QString::number(requestId, 16); }
};

// TODO: check checksums
class HydrationJob : public QObject
Expand All @@ -30,7 +40,7 @@ class HydrationJob : public QObject
};
Q_ENUM(Status)

explicit HydrationJob(const CfApiWrapper::CallBackContext &context);
explicit HydrationJob(const CallBackContext &context);

~HydrationJob() override;

Expand Down Expand Up @@ -58,15 +68,15 @@ class HydrationJob : public QObject

Status status() const;

const CfApiWrapper::CallBackContext context() const;
const CallBackContext context() const;

[[nodiscard]] int errorCode() const;
[[nodiscard]] int statusCode() const;
[[nodiscard]] QString errorString() const;

void start();
void cancel();
void finalize(OCC::VfsCfApi *vfs);
void finalize(OCC::Vfs *vfs);

Q_SIGNALS:
void finished(HydrationJob *job);
Expand All @@ -89,7 +99,7 @@ class HydrationJob : public QObject
SyncJournalDb *_journal = nullptr;
bool _isCancelled = false;

CfApiWrapper::CallBackContext _context;
OCC::CallBackContext _context;
QString _remoteFilePathRel;

SyncJournalFileRecord _record;
Expand Down
18 changes: 18 additions & 0 deletions src/libsync/common/pinstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,24 @@

using namespace OCC;

template <>
QString Utility::enumToDisplayName(PinState state)
{
switch (state) {
case PinState::AlwaysLocal:
return QStringLiteral("AlwaysLocal");
case PinState::Excluded:
return QStringLiteral("Excluded");
case PinState::Inherited:
return QStringLiteral("Inherited");
case PinState::OnlineOnly:
return QStringLiteral("OnlineOnly");
case PinState::Unspecified:
return QStringLiteral("Unspecified");
}
Q_UNREACHABLE();
}

template <>
QString Utility::enumToDisplayName(VfsItemAvailability availability)
{
Expand Down
2 changes: 2 additions & 0 deletions src/libsync/common/pinstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ namespace PinStateEnums {
Q_ENUM_NS(VfsItemAvailability)
}
using namespace PinStateEnums;
template <>
OPENCLOUD_SYNC_EXPORT QString Utility::enumToDisplayName(PinState state);

template <>
OPENCLOUD_SYNC_EXPORT QString Utility::enumToDisplayName(VfsItemAvailability availability);
Expand Down
Loading