Skip to content

Commit

Permalink
Merge pull request #7203 from nextcloud/backport/7193/stable-3.13
Browse files Browse the repository at this point in the history
[stable-3.13] Bugfix/fix upload locked files
  • Loading branch information
mgallien authored Sep 25, 2024
2 parents 9559c83 + 55e1643 commit 4e38a99
Show file tree
Hide file tree
Showing 12 changed files with 46 additions and 14 deletions.
30 changes: 19 additions & 11 deletions src/common/syncjournaldb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Q_LOGGING_CATEGORY(lcDb, "nextcloud.sync.database", QtInfoMsg)
#define GET_FILE_RECORD_QUERY \
"SELECT path, inode, modtime, type, md5, fileid, remotePerm, filesize," \
" ignoredChildrenRemote, contentchecksumtype.name || ':' || contentChecksum, e2eMangledName, isE2eEncrypted, " \
" lock, lockOwnerDisplayName, lockOwnerId, lockType, lockOwnerEditor, lockTime, lockTimeout, isShared, lastShareStateFetchedTimestmap, sharedByMe" \
" lock, lockOwnerDisplayName, lockOwnerId, lockType, lockOwnerEditor, lockTime, lockTimeout, lockToken, isShared, lastShareStateFetchedTimestmap, sharedByMe" \
" FROM metadata" \
" LEFT JOIN checksumtype as contentchecksumtype ON metadata.contentChecksumTypeId == contentchecksumtype.id"

Expand All @@ -74,9 +74,10 @@ static void fillFileRecordFromGetQuery(SyncJournalFileRecord &rec, SqlQuery &que
rec._lockstate._lockEditorApp = query.stringValue(16);
rec._lockstate._lockTime = query.int64Value(17);
rec._lockstate._lockTimeout = query.int64Value(18);
rec._isShared = query.intValue(19) > 0;
rec._lastShareStateFetchedTimestamp = query.int64Value(20);
rec._sharedByMe = query.intValue(21) > 0;
rec._lockstate._lockToken = query.stringValue(19);
rec._isShared = query.intValue(20) > 0;
rec._lastShareStateFetchedTimestamp = query.int64Value(21);
rec._sharedByMe = query.intValue(22) > 0;
}

static QByteArray defaultJournalMode(const QString &dbPath)
Expand Down Expand Up @@ -823,6 +824,7 @@ bool SyncJournalDb::updateMetadataTableStructure()
addColumn(QStringLiteral("lockOwnerEditor"), QStringLiteral("TEXT"));
addColumn(QStringLiteral("lockTime"), QStringLiteral("INTEGER"));
addColumn(QStringLiteral("lockTimeout"), QStringLiteral("INTEGER"));
addColumn(QStringLiteral("lockToken"), QStringLiteral("TEXT"));

SqlQuery query(_db);
query.prepare("CREATE INDEX IF NOT EXISTS caseconflicts_basePath ON caseconflicts(basePath);");
Expand Down Expand Up @@ -984,8 +986,8 @@ Result<void, QString> SyncJournalDb::setFileRecord(const SyncJournalFileRecord &
const auto query = _queryManager.get(PreparedSqlQueryManager::SetFileRecordQuery, QByteArrayLiteral("INSERT OR REPLACE INTO metadata "
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote, "
"contentChecksum, contentChecksumTypeId, e2eMangledName, isE2eEncrypted, lock, lockType, lockOwnerDisplayName, lockOwnerId, "
"lockOwnerEditor, lockTime, lockTimeout, isShared, lastShareStateFetchedTimestmap, sharedByMe) "
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28);"),
"lockOwnerEditor, lockTime, lockTimeout, lockToken, isShared, lastShareStateFetchedTimestmap, sharedByMe) "
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29);"),
_db);
if (!query) {
return query->error();
Expand Down Expand Up @@ -1016,9 +1018,10 @@ Result<void, QString> SyncJournalDb::setFileRecord(const SyncJournalFileRecord &
query->bindValue(23, record._lockstate._lockEditorApp);
query->bindValue(24, record._lockstate._lockTime);
query->bindValue(25, record._lockstate._lockTimeout);
query->bindValue(26, record._isShared);
query->bindValue(27, record._lastShareStateFetchedTimestamp);
query->bindValue(28, record._sharedByMe);
query->bindValue(26, record._lockstate._lockToken);
query->bindValue(27, record._isShared);
query->bindValue(28, record._lastShareStateFetchedTimestamp);
query->bindValue(29, record._sharedByMe);

if (!query->exec()) {
return query->error();
Expand Down Expand Up @@ -1543,7 +1546,7 @@ bool SyncJournalDb::updateLocalMetadata(const QString &filename,
const auto query = _queryManager.get(PreparedSqlQueryManager::SetFileRecordLocalMetadataQuery, QByteArrayLiteral("UPDATE metadata"
" SET inode=?2, modtime=?3, filesize=?4, lock=?5, lockType=?6,"
" lockOwnerDisplayName=?7, lockOwnerId=?8, lockOwnerEditor = ?9,"
" lockTime=?10, lockTimeout=?11"
" lockTime=?10, lockTimeout=?11, lockToken=?12"
" WHERE phash == ?1;"),
_db);
if (!query) {
Expand All @@ -1561,7 +1564,12 @@ bool SyncJournalDb::updateLocalMetadata(const QString &filename,
query->bindValue(9, lockInfo._lockEditorApp);
query->bindValue(10, lockInfo._lockTime);
query->bindValue(11, lockInfo._lockTimeout);
return query->exec();
query->bindValue(12, lockInfo._lockToken);
if (!query->exec()) {
qCDebug(lcDb) << "database error:" << query->error();
return false;
}
return true;
}

Optional<SyncJournalDb::HasHydratedDehydrated> SyncJournalDb::hasHydratedOrDehydratedFiles(const QByteArray &filename)
Expand Down
1 change: 1 addition & 0 deletions src/common/syncjournalfilerecord.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct SyncJournalFileLockInfo {
QString _lockEditorApp;
qint64 _lockTime = 0;
qint64 _lockTimeout = 0;
QString _lockToken;
};

/**
Expand Down
4 changes: 3 additions & 1 deletion src/libsync/discovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ void ProcessDirectoryJob::processFileAnalyzeRemoteInfo(const SyncFileItemPtr &it
item->_lockEditorApp = serverEntry.lockEditorApp;
item->_lockTime = serverEntry.lockTime;
item->_lockTimeout = serverEntry.lockTimeout;
item->_lockToken = serverEntry.lockToken;

qCDebug(lcDisco()) << "item lock for:" << item->_file
<< item->_locked
Expand All @@ -676,7 +677,8 @@ void ProcessDirectoryJob::processFileAnalyzeRemoteInfo(const SyncFileItemPtr &it
<< item->_lockOwnerType
<< item->_lockEditorApp
<< item->_lockTime
<< item->_lockTimeout;
<< item->_lockTimeout
<< item->_lockToken;

// Check for missing server data
{
Expand Down
7 changes: 5 additions & 2 deletions src/libsync/discoveryphase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,8 @@ void DiscoverySingleDirectoryJob::start()
<< "http://nextcloud.org/ns:lock-owner-type"
<< "http://nextcloud.org/ns:lock-owner-editor"
<< "http://nextcloud.org/ns:lock-time"
<< "http://nextcloud.org/ns:lock-timeout";
<< "http://nextcloud.org/ns:lock-timeout"
<< "http://nextcloud.org/ns:lock-token";
}
props << "http://nextcloud.org/ns:is-mount-root";

Expand Down Expand Up @@ -545,7 +546,9 @@ static void propertyMapToRemoteInfo(const QMap<QString, QString> &map, RemotePer
result.lockTimeout = 0;
}
}

if (property == "lock-token") {
result.lockToken = value;
}
}

if (result.isDirectory && map.contains("size")) {
Expand Down
1 change: 1 addition & 0 deletions src/libsync/discoveryphase.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ struct RemoteInfo
QString lockEditorApp;
qint64 lockTime = 0;
qint64 lockTimeout = 0;
QString lockToken;
};

struct LocalInfo
Expand Down
4 changes: 4 additions & 0 deletions src/libsync/lockfilejobs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ void LockFileJob::setFileRecordLocked(SyncJournalFileRecord &record) const
record._lockstate._lockEditorApp = _editorName;
record._lockstate._lockTime = _lockTime;
record._lockstate._lockTimeout = _lockTimeout;
record._lockstate._lockToken = _lockToken;
if (!_etag.isEmpty()) {
record._etag = _etag;
}
Expand All @@ -129,6 +130,7 @@ void LockFileJob::resetState()
_userId.clear();
_lockTime = 0;
_lockTimeout = 0;
_lockToken.clear();
}

SyncJournalFileRecord LockFileJob::handleReply()
Expand Down Expand Up @@ -241,6 +243,8 @@ void LockFileJob::decodeStartElement(const QString &name,
_editorName = reader.readElementText();
} else if (name == QStringLiteral("getetag")) {
_etag = reader.readElementText().toUtf8();
} else if (name == QStringLiteral("lock-token")) {
_lockToken = reader.readElementText();
}
}

Expand Down
1 change: 1 addition & 0 deletions src/libsync/lockfilejobs.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class OWNCLOUDSYNC_EXPORT LockFileJob : public AbstractNetworkJob
QByteArray _etag;
qint64 _lockTime = 0;
qint64 _lockTimeout = 0;
QString _lockToken;
QString _remoteSyncPathWithTrailingSlash;
QString _localSyncPath;
};
Expand Down
3 changes: 3 additions & 0 deletions src/libsync/propagateuploadng.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ void PropagateUploadFileNG::finishUpload()

const auto fileSize = _fileToUpload._size;
headers[QByteArrayLiteral("OC-Total-Length")] = QByteArray::number(fileSize);
if (_item->_locked == SyncFileItem::LockStatus::LockedItem) {
headers[QByteArrayLiteral("If")] = (QLatin1String("<") + propagator()->account()->davUrl().toString() + _fileToUpload._file + "> (<opaquelocktoken:" + _item->_lockToken.toUtf8() + ">)").toUtf8();
}

const auto job = new MoveJob(propagator()->account(), Utility::concatUrlPath(chunkUploadFolderUrl(), "/.file"), destination, headers, this);
_jobs.append(job);
Expand Down
4 changes: 4 additions & 0 deletions src/libsync/propagateuploadv1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ void PropagateUploadFileV1::startNextChunk()

QString path = _fileToUpload._file;

if (_item->_locked == SyncFileItem::LockStatus::LockedItem) {
headers[QByteArrayLiteral("If")] = (QLatin1String("<") + propagator()->account()->davUrl().toString() + _fileToUpload._file + "> (<opaquelocktoken:" + _item->_lockToken.toUtf8() + ">)").toUtf8();
}

qint64 chunkStart = 0;
qint64 currentChunkSize = fileSize;
bool isFinalChunk = false;
Expand Down
1 change: 1 addition & 0 deletions src/libsync/syncengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
lockInfo._lockOwnerType = static_cast<qint64>(item->_lockOwnerType);
lockInfo._lockOwnerDisplayName = item->_lockOwnerDisplayName;
lockInfo._lockEditorApp = item->_lockOwnerDisplayName;
lockInfo._lockToken = item->_lockToken;

if (!_journal->updateLocalMetadata(item->_file, item->_modtime, item->_size, item->_inode, lockInfo)) {
qCWarning(lcEngine) << "Could not update local metadata for file" << item->_file;
Expand Down
3 changes: 3 additions & 0 deletions src/libsync/syncfileitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ SyncJournalFileRecord SyncFileItem::toSyncJournalFileRecordWithInode(const QStri
rec._lockstate._lockEditorApp = _lockEditorApp;
rec._lockstate._lockTime = _lockTime;
rec._lockstate._lockTimeout = _lockTimeout;
rec._lockstate._lockToken = _lockToken;

// Update the inode if possible
rec._inode = _inode;
Expand Down Expand Up @@ -163,6 +164,7 @@ SyncFileItemPtr SyncFileItem::fromSyncJournalFileRecord(const SyncJournalFileRec
item->_lockEditorApp = rec._lockstate._lockEditorApp;
item->_lockTime = rec._lockstate._lockTime;
item->_lockTimeout = rec._lockstate._lockTimeout;
item->_lockToken = rec._lockstate._lockToken;
item->_sharedByMe = rec._sharedByMe;
item->_isShared = rec._isShared;
item->_lastShareStateFetchedTimestamp = rec._lastShareStateFetchedTimestamp;
Expand Down Expand Up @@ -251,6 +253,7 @@ void SyncFileItem::updateLockStateFromDbRecord(const SyncJournalFileRecord &dbRe
_lockEditorApp = dbRecord._lockstate._lockEditorApp;
_lockTime = dbRecord._lockstate._lockTime;
_lockTimeout = dbRecord._lockstate._lockTimeout;
_lockToken = dbRecord._lockstate._lockToken;
}

}
1 change: 1 addition & 0 deletions src/libsync/syncfileitem.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ class OWNCLOUDSYNC_EXPORT SyncFileItem
QString _lockEditorApp;
qint64 _lockTime = 0;
qint64 _lockTimeout = 0;
QString _lockToken;

bool _isShared = false;
time_t _lastShareStateFetchedTimestamp = 0;
Expand Down

0 comments on commit 4e38a99

Please sign in to comment.