mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-21 20:45:51 +03:00
Fix files not unlocking after lock time expired
Signed-off-by: Claudio Cambra <claudio.cambra@gmail.com>
This commit is contained in:
parent
311469a0e5
commit
fd332a52e2
5 changed files with 49 additions and 11 deletions
|
@ -1351,7 +1351,7 @@ bool SyncJournalDb::updateFileRecordChecksum(const QString &filename,
|
|||
}
|
||||
|
||||
bool SyncJournalDb::updateLocalMetadata(const QString &filename,
|
||||
qint64 modtime, qint64 size, quint64 inode)
|
||||
qint64 modtime, qint64 size, quint64 inode, const SyncJournalFileLockInfo &lockInfo)
|
||||
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
@ -1365,7 +1365,9 @@ bool SyncJournalDb::updateLocalMetadata(const QString &filename,
|
|||
}
|
||||
|
||||
const auto query = _queryManager.get(PreparedSqlQueryManager::SetFileRecordLocalMetadataQuery, QByteArrayLiteral("UPDATE metadata"
|
||||
" SET inode=?2, modtime=?3, filesize=?4"
|
||||
" SET inode=?2, modtime=?3, filesize=?4, lock=?5, lockType=?6,"
|
||||
" lockOwnerDisplayName=?7, lockOwnerId=?8, lockOwnerEditor = ?9,"
|
||||
" lockTime=?10, lockTimeout=?11"
|
||||
" WHERE phash == ?1;"),
|
||||
_db);
|
||||
if (!query) {
|
||||
|
@ -1376,6 +1378,13 @@ bool SyncJournalDb::updateLocalMetadata(const QString &filename,
|
|||
query->bindValue(2, inode);
|
||||
query->bindValue(3, modtime);
|
||||
query->bindValue(4, size);
|
||||
query->bindValue(5, lockInfo._locked ? 1 : 0);
|
||||
query->bindValue(6, lockInfo._lockOwnerDisplayName);
|
||||
query->bindValue(7, lockInfo._lockOwnerId);
|
||||
query->bindValue(8, lockInfo._lockOwnerType);
|
||||
query->bindValue(9, lockInfo._lockEditorApp);
|
||||
query->bindValue(10, lockInfo._lockTime);
|
||||
query->bindValue(11, lockInfo._lockTimeout);
|
||||
return query->exec();
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
const QByteArray &contentChecksum,
|
||||
const QByteArray &contentChecksumType);
|
||||
[[nodiscard]] bool updateLocalMetadata(const QString &filename,
|
||||
qint64 modtime, qint64 size, quint64 inode);
|
||||
qint64 modtime, qint64 size, quint64 inode, const SyncJournalFileLockInfo &lockInfo);
|
||||
|
||||
/// Return value for hasHydratedOrDehydratedFiles()
|
||||
struct HasHydratedDehydrated
|
||||
|
|
|
@ -394,6 +394,17 @@ void ProcessDirectoryJob::processFile(PathTuple path,
|
|||
if (item->_type == ItemTypeVirtualFileDehydration)
|
||||
item->_type = ItemTypeFile;
|
||||
|
||||
// We want to check the lock state of this file after the lock time has expired
|
||||
if(serverEntry.locked == SyncFileItem::LockStatus::LockedItem) {
|
||||
const auto lockExpirationTime = serverEntry.lockTime + serverEntry.lockTimeout;
|
||||
const auto timeRemaining = QDateTime::currentDateTime().secsTo(QDateTime::fromSecsSinceEpoch(lockExpirationTime));
|
||||
const auto timerInterval = qMax(5LL, timeRemaining);
|
||||
|
||||
qCInfo(lcDisco) << "Will re-check lock status for:" << path._original << "in:" << timerInterval << "seconds.";
|
||||
_discoveryData->_anotherSyncNeeded = true;
|
||||
_discoveryData->_scheduleSyncInSecs = timerInterval;
|
||||
}
|
||||
|
||||
// VFS suffixed files on the server are ignored
|
||||
if (isVfsWithSuffix()) {
|
||||
if (hasVirtualFileSuffix(serverEntry.name)
|
||||
|
@ -505,6 +516,7 @@ void ProcessDirectoryJob::processFileAnalyzeRemoteInfo(
|
|||
const bool isVirtualE2EePlaceholder = isDbEntryAnE2EePlaceholder && serverEntry.size >= Constants::e2EeTagSize;
|
||||
const qint64 sizeOnServer = isVirtualE2EePlaceholder ? serverEntry.size - Constants::e2EeTagSize : serverEntry.size;
|
||||
const bool metaDataSizeNeedsUpdateForE2EeFilePlaceholder = isVirtualE2EePlaceholder && dbEntry._fileSize == serverEntry.size;
|
||||
const bool serverEntryLockedAsBool = serverEntry.locked == SyncFileItem::LockStatus::LockedItem;
|
||||
|
||||
if (serverEntry.isDirectory != dbEntry.isDirectory()) {
|
||||
// If the type of the entity changed, it's like NEW, but
|
||||
|
@ -551,6 +563,8 @@ void ProcessDirectoryJob::processFileAnalyzeRemoteInfo(
|
|||
}
|
||||
item->_instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
item->_direction = SyncFileItem::Down;
|
||||
} else if(serverEntryLockedAsBool != dbEntry._lockstate._locked) {
|
||||
item->_instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
} else {
|
||||
// if (is virtual mode enabled and folder is encrypted - check if the size is the same as on the server and then - trigger server query
|
||||
// to update a placeholder with corrected size (-16 Bytes)
|
||||
|
@ -815,7 +829,7 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo(
|
|||
|
||||
bool serverModified = item->_instruction == CSYNC_INSTRUCTION_NEW || item->_instruction == CSYNC_INSTRUCTION_SYNC
|
||||
|| item->_instruction == CSYNC_INSTRUCTION_RENAME || item->_instruction == CSYNC_INSTRUCTION_TYPE_CHANGE;
|
||||
|
||||
|
||||
qCDebug(lcDisco) << "File" << item->_file << "- servermodified:" << serverModified
|
||||
<< "noServerEntry:" << noServerEntry;
|
||||
|
||||
|
@ -1029,7 +1043,7 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo(
|
|||
item->_size = localEntry.size;
|
||||
item->_modtime = localEntry.modtime;
|
||||
_childModified = true;
|
||||
|
||||
|
||||
qCDebug(lcDisco) << "Local file was changed: File" << item->_file
|
||||
<< "item->_instruction:" << item->_instruction
|
||||
<< "noServerEntry:" << noServerEntry
|
||||
|
@ -1316,7 +1330,7 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo(
|
|||
chopVirtualFileSuffix(serverOriginalPath);
|
||||
auto job = new RequestEtagJob(_discoveryData->_account, serverOriginalPath, this);
|
||||
connect(job, &RequestEtagJob::finishedWithResult, this, [=](const HttpResult<QByteArray> &etag) mutable {
|
||||
|
||||
|
||||
|
||||
if (!etag || (etag.get() != base._etag && !item->isDirectory()) || _discoveryData->isRenamed(originalPath)
|
||||
|| (isAnyParentBeingRestored(originalPath) && !isRename(originalPath))) {
|
||||
|
@ -1382,7 +1396,7 @@ void ProcessDirectoryJob::processFileConflict(const SyncFileItemPtr &item, Proce
|
|||
<< "localEntry.modtime:" << localEntry.modtime;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!serverEntry.checksumHeader.isEmpty()) {
|
||||
qCDebug(lcDisco) << "CSYNC_INSTRUCTION_CONFLICT: File" << item->_file << "if (!serverEntry.checksumHeader.isEmpty())";
|
||||
qCDebug(lcDisco) << "CSYNC_INSTRUCTION_CONFLICT: serverEntry.size:" << serverEntry.size
|
||||
|
@ -1425,7 +1439,7 @@ void ProcessDirectoryJob::processFileConflict(const SyncFileItemPtr &item, Proce
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!up._valid || up._contentChecksum != serverEntry.checksumHeader) {
|
||||
qCDebug(lcDisco) << "CSYNC_INSTRUCTION_SYNC: File" << item->_file << "if (!up._valid && up._contentChecksum != serverEntry.checksumHeader)";
|
||||
qCDebug(lcDisco) << "CSYNC_INSTRUCTION_SYNC: up._valid:" << up._valid
|
||||
|
@ -1636,7 +1650,7 @@ bool ProcessDirectoryJob::isRename(const QString &originalPath) const
|
|||
|
||||
/* TODO: This was needed at some point to cover an edge case which I am no longer to reproduce and it might no longer be the case.
|
||||
* Still, leaving this here just in case the edge case is caught at some point in future.
|
||||
*
|
||||
*
|
||||
OCC::SyncJournalFileRecord base;
|
||||
// are we allowed to rename?
|
||||
if (!_discoveryData || !_discoveryData->_statedb || !_discoveryData->_statedb->getFileRecord(originalPath, &base)) {
|
||||
|
|
|
@ -283,6 +283,7 @@ public:
|
|||
// output
|
||||
QByteArray _dataFingerprint;
|
||||
bool _anotherSyncNeeded = false;
|
||||
int _scheduleSyncInSecs = -1;
|
||||
|
||||
signals:
|
||||
void fatalError(const QString &errorString);
|
||||
|
|
|
@ -391,7 +391,17 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
|
|||
emit itemCompleted(item);
|
||||
} else {
|
||||
// Update only outdated data from the disk.
|
||||
if (!_journal->updateLocalMetadata(item->_file, item->_modtime, item->_size, item->_inode)) {
|
||||
|
||||
SyncJournalFileLockInfo lockInfo;
|
||||
lockInfo._locked = item->_locked == SyncFileItem::LockStatus::LockedItem;
|
||||
lockInfo._lockTime = item->_lockTime;
|
||||
lockInfo._lockTimeout = item->_lockTimeout;
|
||||
lockInfo._lockOwnerId = item->_lockOwnerId;
|
||||
lockInfo._lockOwnerType = static_cast<qint64>(item->_lockOwnerType);
|
||||
lockInfo._lockOwnerDisplayName = item->_lockOwnerDisplayName;
|
||||
lockInfo._lockEditorApp = item->_lockOwnerDisplayName;
|
||||
|
||||
if (!_journal->updateLocalMetadata(item->_file, item->_modtime, item->_size, item->_inode, lockInfo)) {
|
||||
qCWarning(lcEngine) << "Could not update local metadata for file" << item->_file;
|
||||
}
|
||||
}
|
||||
|
@ -689,7 +699,11 @@ void SyncEngine::slotDiscoveryFinished()
|
|||
restoreOldFiles(_syncItems);
|
||||
}
|
||||
|
||||
if (_discoveryPhase->_anotherSyncNeeded && _anotherSyncNeeded == NoFollowUpSync) {
|
||||
if (_discoveryPhase->_anotherSyncNeeded && _discoveryPhase->_scheduleSyncInSecs > 0) {
|
||||
QTimer::singleShot(_discoveryPhase->_scheduleSyncInSecs * 1000, this, [this]{
|
||||
this->startSync();
|
||||
});
|
||||
} else if (_discoveryPhase->_anotherSyncNeeded && _anotherSyncNeeded == NoFollowUpSync) {
|
||||
_anotherSyncNeeded = ImmediateFollowUp;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue