Skip to content

Commit

Permalink
maintain lock state if unlock happens during sync
Browse files Browse the repository at this point in the history
currently unlock can happen during the sync
in that case, it may be possible that the propagator will lose the lock
state changes and override them when updating teh etag after a file has
been uploaded

detect that case and ensure we keep consistent state about files

Signed-off-by: Matthieu Gallien <[email protected]>
  • Loading branch information
mgallien authored and backportbot-nextcloud[bot] committed Dec 5, 2023
1 parent bb05341 commit 61b5a60
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 1 deletion.
6 changes: 6 additions & 0 deletions src/libsync/bulkpropagatorjob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,12 @@ void BulkPropagatorJob::slotPutFinishedOneFile(const BulkUploadItem &singleFile,
// the file id should only be empty for new files up- or downloaded
computeFileId(singleFile._item, fileReply);

if (SyncJournalFileRecord oldRecord; propagator()->_journal->getFileRecord(singleFile._item->destination(), &oldRecord) && oldRecord.isValid()) {
if (oldRecord._etag != singleFile._item->_etag) {
singleFile._item->updateLockStateFromDbRecord(oldRecord);
}
}

singleFile._item->_etag = etag;
singleFile._item->_fileId = getHeaderFromJsonReply(fileReply, "fileid");
singleFile._item->_remotePerm = RemotePermissions::fromServerString(getHeaderFromJsonReply(fileReply, "permissions"));
Expand Down
7 changes: 7 additions & 0 deletions src/libsync/propagateupload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ bool PollJob::finished()
if (status == QLatin1String("finished")) {
_item->_status = SyncFileItem::Success;
_item->_fileId = json["fileId"].toString().toUtf8();

if (SyncJournalFileRecord oldRecord; _journal->getFileRecord(_item->destination(), &oldRecord) && oldRecord.isValid()) {
if (oldRecord._etag != _item->_etag) {
_item->updateLockStateFromDbRecord(oldRecord);
}
}

_item->_etag = parseEtag(json["ETag"].toString().toUtf8());
} else { // error
_item->_status = classifyError(QNetworkReply::UnknownContentError, _item->_httpErrorCode);
Expand Down
8 changes: 7 additions & 1 deletion src/libsync/propagateuploadng.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,14 @@ void PropagateUploadFileNG::slotMoveJobFinished()
_item->_fileId = fid;
}

if (SyncJournalFileRecord oldRecord; propagator()->_journal->getFileRecord(_item->destination(), &oldRecord) && oldRecord.isValid()) {
if (oldRecord._etag != _item->_etag) {
_item->updateLockStateFromDbRecord(oldRecord);
}
}

_item->_etag = getEtagFromReply(job->reply());
;

if (_item->_etag.isEmpty()) {
qCWarning(lcPropagateUploadNG) << "Server did not return an ETAG" << _item->_file;
abortWithError(SyncFileItem::NormalError, tr("Missing ETag from server"));
Expand Down
6 changes: 6 additions & 0 deletions src/libsync/propagateuploadv1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,12 @@ void PropagateUploadFileV1::slotPutFinished()
_item->_fileId = fid;
}

if (SyncJournalFileRecord oldRecord; propagator()->_journal->getFileRecord(_item->destination(), &oldRecord) && oldRecord.isValid()) {
if (oldRecord._etag != _item->_etag) {
_item->updateLockStateFromDbRecord(oldRecord);
}
}

_item->_etag = etag;

if (job->reply()->rawHeader("X-OC-MTime") != "accepted") {
Expand Down
11 changes: 11 additions & 0 deletions src/libsync/syncfileitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,15 @@ SyncFileItemPtr SyncFileItem::fromProperties(const QString &filePath, const QMap
return item;
}

void SyncFileItem::updateLockStateFromDbRecord(const SyncJournalFileRecord &dbRecord)
{
_locked = dbRecord._lockstate._locked ? LockStatus::LockedItem : LockStatus::UnlockedItem;
_lockOwnerId = dbRecord._lockstate._lockOwnerId;
_lockOwnerDisplayName = dbRecord._lockstate._lockOwnerDisplayName;
_lockOwnerType = static_cast<LockOwnerType>(dbRecord._lockstate._lockOwnerType);
_lockEditorApp = dbRecord._lockstate._lockEditorApp;
_lockTime = dbRecord._lockstate._lockTime;
_lockTimeout = dbRecord._lockstate._lockTimeout;
}

}
2 changes: 2 additions & 0 deletions src/libsync/syncfileitem.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ class OWNCLOUDSYNC_EXPORT SyncFileItem

[[nodiscard]] bool isEncrypted() const { return _e2eEncryptionStatus != EncryptionStatus::NotEncrypted; }

void updateLockStateFromDbRecord(const SyncJournalFileRecord &dbRecord);

// Variables useful for everybody

/** The syncfolder-relative filesystem path that the operation is about
Expand Down

0 comments on commit 61b5a60

Please sign in to comment.