}
bool SyncJournalDb::updateLocalMetadata(const QString &filename,
- qint64 modtime, qint64 size, quint64 inode)
+ qint64 modtime, qint64 size, quint64 inode, const SyncJournalFileLockInfo &lockInfo)
{
QMutexLocker locker(&_mutex);
}
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) {
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();
}
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
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)
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
}
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)
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;
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
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))) {
<< "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
}
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
/* 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)) {
// output
QByteArray _dataFingerprint;
bool _anotherSyncNeeded = false;
+ int _scheduleSyncInSecs = -1;
signals:
void fatalError(const QString &errorString);
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;
}
}
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;
}