Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/desktop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/csync
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@woboq.com>2017-12-11 21:25:51 +0300
committerOlivier Goffart <olivier@woboq.com>2017-12-14 13:56:12 +0300
commit4dc49ff3b01f196dfac0ac928688d90a001b49e8 (patch)
tree7cf9995f7c23c88e70b1b11dd05e1ddfa54ca6c0 /src/csync
parent4369853ddb21525a9b83f83ef3d44dd838a17d8d (diff)
SyncEngine: Recover when the PUT reply (or chunkin's MOVE) is lost
This can happen if the upload of a file is finished, but we just got disconnected right before recieving the reply containing the etag. So nothing was save din the DB, and we are not sure if the server recieved the file properly or not. Further local update of the file will cause a conflict. In order to fix this, store the checksum of the uploading file in the uploadinfo table of the local db (even if there is no chunking involved). And when we have a conflict, check that it is not because of this situation by checking the entry in the uploadinfo table. Issue #5106
Diffstat (limited to 'src/csync')
-rw-r--r--src/csync/csync_reconcile.cpp30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/csync/csync_reconcile.cpp b/src/csync/csync_reconcile.cpp
index 97863fb8b..daad534ae 100644
--- a/src/csync/csync_reconcile.cpp
+++ b/src/csync/csync_reconcile.cpp
@@ -27,6 +27,7 @@
#include "csync_rename.h"
#include "common/c_jhash.h"
#include "common/asserts.h"
+#include "common/syncjournalfilerecord.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(lcReconcile, "sync.csync.reconciler", QtInfoMsg)
@@ -316,6 +317,35 @@ static int _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx) {
(ctx->current == REMOTE_REPLICA ? cur->checksumHeader : other->checksumHeader);
if (!remoteChecksumHeader.isEmpty()) {
is_conflict = true;
+
+ // Do we have an UploadInfo for this?
+ // Maybe the Upload was completed, but the connection was broken just before
+ // we recieved the etag (Issue #5106)
+ auto up = ctx->statedb->getUploadInfo(cur->path);
+ if (up._valid && up._contentChecksum == remoteChecksumHeader) {
+ // Solve the conflict into an upload, or nothing
+ auto remoteNode = ctx->current == REMOTE_REPLICA ? cur : other;
+ auto localNode = ctx->current == REMOTE_REPLICA ? other : cur;
+ remoteNode->instruction = CSYNC_INSTRUCTION_NONE;
+ localNode->instruction = up._modtime == localNode->modtime ? CSYNC_INSTRUCTION_UPDATE_METADATA : CSYNC_INSTRUCTION_SYNC;
+
+ // Update the etag and other server metadata in the journal already
+ // (We can't use a typical CSYNC_INSTRUCTION_UPDATE_METADATA because
+ // we must not store the size/modtime from the file system)
+ OCC::SyncJournalFileRecord rec;
+ if (ctx->statedb->getFileRecord(remoteNode->path, &rec)) {
+ rec._path = remoteNode->path;
+ rec._etag = remoteNode->etag;
+ rec._fileId = remoteNode->file_id;
+ rec._modtime = remoteNode->modtime;
+ rec._type = remoteNode->type;
+ rec._fileSize = remoteNode->size;
+ rec._remotePerm = remoteNode->remotePerm;
+ rec._checksumHeader = remoteNode->checksumHeader;
+ ctx->statedb->setFileRecordMetadata(rec);
+ }
+ break;
+ }
}
// SO: If there is no checksum, we can have !is_conflict here