Skip to content

Commit 5eb8f40

Browse files
committed
feat: support notify_file_id push notifications
For this to work we also now need to store the fileId from the sync root folder, otherwise we would never know about new files inside the configured sync root Signed-off-by: Jyrki Gadinger <[email protected]>
1 parent 26e8d6f commit 5eb8f40

16 files changed

+175
-6
lines changed

src/common/syncjournaldb.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,6 +1762,40 @@ bool SyncJournalDb::updateLocalMetadata(const QString &filename,
17621762
return true;
17631763
}
17641764

1765+
bool SyncJournalDb::hasFileIds(const QList<qint64> &fileIds)
1766+
{
1767+
QMutexLocker locker(&_mutex);
1768+
1769+
if (!checkConnect()) {
1770+
return false;
1771+
}
1772+
1773+
QStringList fileIdStrings = {};
1774+
for (const auto &fileId : fileIds) {
1775+
fileIdStrings.append(QString::number(fileId));
1776+
}
1777+
1778+
// quick workaround for looking up pure numeric file IDs: simply `round()` that field!
1779+
// this will return the file ID as e.g. 12345.0, but that's still good enough to use it
1780+
// with the IN operator -- e.g. (12345, 1337, 29001)
1781+
SqlQuery query(
1782+
QLatin1String{"SELECT 1 FROM metadata WHERE ROUND(fileid) IN (%1) LIMIT 1;"}
1783+
.arg(fileIdStrings.join(QLatin1String{", "})).toLocal8Bit(),
1784+
_db
1785+
);
1786+
1787+
if (!query.exec()) {
1788+
qCWarning(lcDb) << "file id query failed:" << query.error();
1789+
return false;
1790+
}
1791+
1792+
if (query.next().hasData && query.intValue(0) == 1) {
1793+
return true;
1794+
}
1795+
1796+
return false;
1797+
}
1798+
17651799
Optional<SyncJournalDb::HasHydratedDehydrated> SyncJournalDb::hasHydratedOrDehydratedFiles(const QByteArray &filename)
17661800
{
17671801
QMutexLocker locker(&_mutex);

src/common/syncjournaldb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ class OCSYNC_EXPORT SyncJournalDb : public QObject
7676
[[nodiscard]] bool updateLocalMetadata(const QString &filename,
7777
qint64 modtime, qint64 size, quint64 inode, const SyncJournalFileLockInfo &lockInfo);
7878

79+
[[nodiscard]] bool hasFileIds(const QList<qint64> &fileIds);
80+
7981
/// Return value for hasHydratedOrDehydratedFiles()
8082
struct HasHydratedDehydrated
8183
{

src/gui/folder.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ Folder::Folder(const FolderDefinition &definition,
9292

9393
connect(_accountState.data(), &AccountState::isConnectedChanged, this, &Folder::canSyncChanged);
9494
connect(_engine.data(), &SyncEngine::rootEtag, this, &Folder::etagRetrievedFromSyncEngine);
95+
connect(_engine.data(), &SyncEngine::rootFileIdReceived, this, &Folder::rootFileIdReceivedFromSyncEngine);
9596

9697
connect(_engine.data(), &SyncEngine::started, this, &Folder::slotSyncStarted, Qt::QueuedConnection);
9798
connect(_engine.data(), &SyncEngine::finished, this, &Folder::slotSyncFinished, Qt::QueuedConnection);
@@ -397,6 +398,11 @@ void Folder::etagRetrievedFromSyncEngine(const QByteArray &etag, const QDateTime
397398
_lastEtag = etag;
398399
}
399400

401+
void Folder::rootFileIdReceivedFromSyncEngine(const qint64 fileId)
402+
{
403+
qCDebug(lcFolder).nospace() << "retrieved root fileId=" << fileId;
404+
_rootFileId = fileId;
405+
}
400406

401407
void Folder::showSyncResultPopup()
402408
{
@@ -1003,6 +1009,11 @@ void Folder::migrateBlackListPath(const QString &legacyPath)
10031009
}
10041010
}
10051011

1012+
bool Folder::hasFileIds(const QList<qint64>& fileIds) const
1013+
{
1014+
return fileIds.contains(_rootFileId) || journalDb()->hasFileIds(fileIds);
1015+
}
1016+
10061017
QString Folder::filePath(const QString& fileName)
10071018
{
10081019
const auto folderDir = QDir(_canonicalLocalPath);

src/gui/folder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,9 @@ class Folder : public QObject
316316
void blacklistPath(const QString &path);
317317
void migrateBlackListPath(const QString &legacyPath);
318318

319+
/// whether the current folder contains any of the passed fileIds
320+
[[nodiscard]] bool hasFileIds(const QList<qint64>& fileIds) const;
321+
319322
signals:
320323
void syncStateChange();
321324
void syncStarted();
@@ -429,6 +432,8 @@ private slots:
429432
void etagRetrieved(const QByteArray &, const QDateTime &tp);
430433
void etagRetrievedFromSyncEngine(const QByteArray &, const QDateTime &time);
431434

435+
void rootFileIdReceivedFromSyncEngine(const qint64 fileId);
436+
432437
void slotEmitFinishedDelayed();
433438

434439
void slotNewBigFolderDiscovered(const QString &, bool isExternal);
@@ -585,6 +590,9 @@ private slots:
585590
QMetaObject::Connection _officeFileLockReleaseUnlockFailure;
586591
QMetaObject::Connection _fileLockSuccess;
587592
QMetaObject::Connection _fileLockFailure;
593+
594+
/// The remote file ID of the current folder.
595+
qint64 _rootFileId = 0;
588596
};
589597
}
590598

src/gui/folderman.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,15 +2079,35 @@ void FolderMan::slotSetupPushNotifications(const Folder::Map &folderMap)
20792079

20802080
void FolderMan::slotProcessFilesPushNotification(Account *account)
20812081
{
2082-
qCInfo(lcFolderMan) << "Got files push notification for account" << account;
2082+
qCDebug(lcFolderMan) << "received notify_file push notification account=" << account->displayName();
20832083

20842084
for (auto folder : std::as_const(_folderMap)) {
20852085
// Just run on the folders that belong to this account
20862086
if (folder->accountState()->account() != account) {
20872087
continue;
20882088
}
20892089

2090-
qCInfo(lcFolderMan) << "Schedule folder" << folder << "for sync";
2090+
qCInfo(lcFolderMan).nospace() << "scheduling sync account=" << account->displayName() << " folder=" << folder->alias() << " reason=notify_file";
2091+
scheduleFolder(folder);
2092+
}
2093+
}
2094+
2095+
void FolderMan::slotProcessFileIdsPushNotification(Account *account, const QList<qint64> &fileIds)
2096+
{
2097+
qCDebug(lcFolderMan).nospace() << "received notify_file_id push notification account=" << account->displayName() << " fileIds=" << fileIds;
2098+
2099+
for (auto folder : std::as_const(_folderMap)) {
2100+
// Just run on the folders that belong to this account
2101+
if (folder->accountState()->account() != account) {
2102+
continue;
2103+
}
2104+
2105+
if (!folder->hasFileIds(fileIds)) {
2106+
qCDebug(lcFolderMan).nospace() << "no matching file ids, ignoring account=" << account->displayName() << " folder=" << folder->alias();
2107+
continue;
2108+
}
2109+
2110+
qCInfo(lcFolderMan).nospace() << "scheduling sync account=" << account->displayName() << " folder=" << folder->alias() << " reason=notify_file_id";
20912111
scheduleFolder(folder);
20922112
}
20932113
}
@@ -2099,6 +2119,7 @@ void FolderMan::slotConnectToPushNotifications(const AccountPtr &account)
20992119
if (pushNotificationsFilesReady(account)) {
21002120
qCInfo(lcFolderMan) << "Push notifications ready";
21012121
connect(pushNotifications, &PushNotifications::filesChanged, this, &FolderMan::slotProcessFilesPushNotification, Qt::UniqueConnection);
2122+
connect(pushNotifications, &PushNotifications::fileIdsChanged, this, &FolderMan::slotProcessFileIdsPushNotification, Qt::UniqueConnection);
21022123
}
21032124
}
21042125

src/gui/folderman.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ private slots:
329329

330330
void slotSetupPushNotifications(const OCC::Folder::Map &);
331331
void slotProcessFilesPushNotification(OCC::Account *account);
332+
void slotProcessFileIdsPushNotification(OCC::Account *account, const QList<qint64> &fileIds);
332333
void slotConnectToPushNotifications(const OCC::AccountPtr &account);
333334

334335
void slotLeaveShare(const QString &localFile, const QByteArray &folderToken = {});

src/libsync/discovery.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2235,6 +2235,7 @@ DiscoverySingleDirectoryJob *ProcessDirectoryJob::startAsyncServerQuery()
22352235
}
22362236

22372237
connect(serverJob, &DiscoverySingleDirectoryJob::etag, this, &ProcessDirectoryJob::etag);
2238+
connect(serverJob, &DiscoverySingleDirectoryJob::rootFileIdReceived, this, &ProcessDirectoryJob::rootFileIdReceived);
22382239
connect(serverJob, &DiscoverySingleDirectoryJob::setfolderQuota, this, &ProcessDirectoryJob::setFolderQuota);
22392240
_discoveryData->_currentlyActiveJobs++;
22402241
_pendingAsyncJobs++;

src/libsync/discovery.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ class ProcessDirectoryJob : public QObject
306306
// The root etag of this directory was fetched
307307
void etag(const QByteArray &, const QDateTime &time);
308308
void updatedRootFolderQuota(const int64_t &bytesUsed, const int64_t &bytesAvailable);
309+
void rootFileIdReceived(const qint64 fileId);
309310

310311
private slots:
311312
void setFolderQuota(const FolderQuota &folderQuota);

src/libsync/discoveryphase.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,8 +613,17 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(const QString &fi
613613
_localFileId = map.value(QStringLiteral("fileid")).toUtf8();
614614
}
615615
if (map.contains("id")) {
616+
// this is from the "oc:id" property, the format is e.g. "00000002oc123xyz987e"
616617
_fileId = map.value("id").toUtf8();
617618
}
619+
if (map.contains("fileid")) {
620+
// this is from the "oc:fileid" property, this is the plain ID without any special format (e.g. "2")
621+
bool ok = false;
622+
if (qint64 numericFileId = map.value("fileid").toLongLong(&ok); ok) {
623+
qCDebug(lcDiscovery).nospace() << "received numericFileId=" << numericFileId;
624+
emit rootFileIdReceived(numericFileId);
625+
}
626+
}
618627
if (map.contains("is-encrypted") && map.value("is-encrypted") == QStringLiteral("1")) {
619628
_encryptionStatusCurrent = SyncFileItem::EncryptionStatus::EncryptedMigratedV2_0;
620629
Q_ASSERT(!_fileId.isEmpty());

src/libsync/discoveryphase.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ class DiscoverySingleDirectoryJob : public QObject
186186
void etag(const QByteArray &, const QDateTime &time);
187187
void finished(const OCC::HttpResult<QVector<OCC::RemoteInfo>> &result);
188188
void setfolderQuota(const FolderQuota &folderQuota);
189+
void rootFileIdReceived(const qint64 fileId);
189190

190191
private slots:
191192
void directoryListingIteratedSlot(const QString &, const QMap<QString, QString> &);

0 commit comments

Comments
 (0)