summaryrefslogtreecommitdiffstats
path: root/wsd/DocumentBroker.cpp
diff options
context:
space:
mode:
authorAshod Nakashian <ashod.nakashian@collabora.co.uk>2022-01-27 10:13:18 -0500
committerAshod Nakashian <Ashod@users.noreply.github.com>2022-02-08 20:46:01 -0500
commitd8c2578ec426db9fc81d76af21055037e161a0eb (patch)
treedb8e0096af11dc9000fbfb6b5a35997c1c137260 /wsd/DocumentBroker.cpp
parentwsd: do not force uploading when in conflict (diff)
downloadonline-d8c2578ec426db9fc81d76af21055037e161a0eb.tar.gz
online-d8c2578ec426db9fc81d76af21055037e161a0eb.zip
wsd: detect storage conflict with no clients
When the last client connection is closed, there is UI (or user) to provide input on the document conflict dialog. In this case, we detect that the situation is final and unresolvable and we simply give up. We log a warning and dump the document state before terminating. Change-Id: I111a446b8743a0d16b7ed8b39751a419036c927f Signed-off-by: Ashod Nakashian <ashod.nakashian@collabora.co.uk>
Diffstat (limited to 'wsd/DocumentBroker.cpp')
-rw-r--r--wsd/DocumentBroker.cpp46
1 files changed, 36 insertions, 10 deletions
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 797a958aa0..78f7d0e2ab 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -452,7 +452,9 @@ void DocumentBroker::pollThread()
_poll->continuePolling() << ", ShutdownRequestFlag: " << SigUtil::getShutdownRequestFlag() <<
", TerminationFlag: " << SigUtil::getTerminationFlag() << ", closeReason: " << _closeReason << ". Flushing socket.");
- if (isModified())
+ // If the document is modified at exit, dump the state and warn.
+ // Unless, that is, the user discarded the changes.
+ if (isModified() && !(_docState.isCloseRequested() && _documentChangedInStorage))
{
std::stringstream state;
dumpState(state);
@@ -1459,11 +1461,9 @@ void DocumentBroker::handleUploadToStorageResponse(const StorageBase::UploadResu
return;
}
- // Storage save is considered successful when either storage returns OK or the document on the storage
- // was changed and it was used to overwrite local changes
+ // Storage upload is considered successful only when storage returns OK.
const bool lastUploadSuccessful =
- uploadResult.getResult() == StorageBase::UploadResult::Result::OK ||
- uploadResult.getResult() == StorageBase::UploadResult::Result::DOC_CHANGED;
+ uploadResult.getResult() == StorageBase::UploadResult::Result::OK;
LOG_TRC("lastUploadSuccessful: " << lastUploadSuccessful);
_storageManager.setLastUploadResult(lastUploadSuccessful);
@@ -1677,9 +1677,22 @@ void DocumentBroker::handleUploadToStorageResponse(const StorageBase::UploadResu
const std::string message
= isPossiblyModified() ? "error: cmd=storage kind=documentconflict" : "close: documentconflict";
- broadcastMessage(message);
+ const std::size_t activeClients = broadcastMessage(message);
broadcastSaveResult(false, "Conflict: Document changed in storage",
uploadResult.getReason());
+ if (activeClients == 0)
+ {
+ // No clients were contacted; we will never resolve this conflict.
+ stop("conflict");
+ std::stringstream state;
+ dumpState(state);
+ LOG_WRN("The document ["
+ << _docKey
+ << "] could not be uploaded to storage because there is a newer version there, "
+ "and no active clients exist to resolve the conflict. The document should "
+ "be recoverable from the quarantine. State:\n"
+ << state.str());
+ }
}
}
@@ -3085,20 +3098,33 @@ void DocumentBroker::closeDocument(const std::string& reason)
{
assertCorrectThread();
- LOG_DBG("Closing DocumentBroker for docKey [" << _docKey << "] with reason: " << reason);
- _closeReason = reason;
_docState.setCloseRequested();
+ _closeReason = reason;
+ if (_documentChangedInStorage)
+ {
+ // Discarding changes in the face of conflict in storage.
+ LOG_DBG("Closing DocumentBroker for docKey ["
+ << _docKey << "] and discarding changes with reason: " << reason);
+ stop(reason);
+ }
+ else
+ {
+ LOG_DBG("Closing DocumentBroker for docKey [" << _docKey << "] with reason: " << reason);
+ }
}
-void DocumentBroker::broadcastMessage(const std::string& message) const
+std::size_t DocumentBroker::broadcastMessage(const std::string& message) const
{
assertCorrectThread();
LOG_DBG("Broadcasting message [" << message << "] to all " << _sessions.size() << " sessions.");
+ std::size_t count = 0;
for (const auto& sessionIt : _sessions)
{
- sessionIt.second->sendTextFrame(message);
+ count += sessionIt.second->sendTextFrame(message);
}
+
+ return count;
}
void DocumentBroker::broadcastMessageToOthers(const std::string& message, const std::shared_ptr<ClientSession>& _session) const