wsd: upload to storage when per_document.always_save_on_exit is set

Saving the document on exit is not enough, we also need
to send it to the storage. We now force doing that,
even when there is no modifiction to the document
(i.e. a new version wasn't really saved).

Reviewed-on: https://gerrit.libreoffice.org/81336
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit f2913f20b03e916ce8a70f927ca3f5655a3768a8)

Change-Id: Ic4e1b1424f32d3141e98c936a51e47c9e4b9f753
Reviewed-on: https://gerrit.libreoffice.org/81576
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
This commit is contained in:
Ashod Nakashian 2019-10-22 10:28:57 -04:00 committed by Ashod Nakashian
parent 967d3a4156
commit 35fdc48e28
3 changed files with 41 additions and 21 deletions

View file

@ -677,7 +677,6 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
session->setUserName(username);
session->setUserExtraInfo(userExtraInfo);
session->setWatermarkText(watermarkText);
if(!watermarkText.empty())
session->setHash(watermarkText);
else
@ -834,13 +833,21 @@ bool DocumentBroker::saveToStorage(const std::string& sessionId,
{
assertCorrectThread();
if (force)
// Force saving on exit, if enabled.
if (!force && isMarkedToDestroy())
{
LOG_TRC("Document will be saved forcefully to storage.");
_storage->forceSave();
static const bool always_save = LOOLWSD::getConfigValue<bool>("per_document.always_save_on_exit", false);
if (always_save)
{
LOG_TRC("Enabling forced saving to storage per always_save_on_exit config.");
_storage->forceSave();
force = true;
}
}
const bool res = saveToStorageInternal(sessionId, success, result);
constexpr bool isRename = false;
const bool res = saveToStorageInternal(sessionId, success, result, /*saveAsPath*/ std::string(),
/*saveAsFilename*/ std::string(), isRename, force);
// If marked to destroy, or session is disconnected, remove.
const auto it = _sessions.find(sessionId);
@ -864,22 +871,21 @@ bool DocumentBroker::saveAsToStorage(const std::string& sessionId, const std::st
return saveToStorageInternal(sessionId, true, "", saveAsPath, saveAsFilename, isRename);
}
bool DocumentBroker::saveToStorageInternal(const std::string& sessionId,
bool success, const std::string& result,
const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename)
bool DocumentBroker::saveToStorageInternal(const std::string& sessionId, bool success,
const std::string& result, const std::string& saveAsPath,
const std::string& saveAsFilename, const bool isRename,
const bool force)
{
assertCorrectThread();
// Record that we got a response to avoid timing out on saving.
_lastSaveResponseTime = std::chrono::steady_clock::now();
const bool isSaveAs = !saveAsPath.empty();
// If save requested, but core didn't save because document was unmodified
// notify the waiting thread, if any.
LOG_TRC("Saving to storage docKey [" << _docKey << "] for session [" << sessionId <<
"]. Success: " << success << ", result: " << result);
if (!success && result == "unmodified" && !isRename)
LOG_TRC("Uploading to storage docKey [" << _docKey << "] for session [" << sessionId <<
"]. Success: " << success << ", result: " << result << ", force: " << force);
if (!success && result == "unmodified" && !isRename && !force)
{
LOG_DBG("Save skipped as document [" << _docKey << "] was not modified.");
_lastSaveTime = std::chrono::steady_clock::now();
@ -890,18 +896,26 @@ bool DocumentBroker::saveToStorageInternal(const std::string& sessionId,
const auto it = _sessions.find(sessionId);
if (it == _sessions.end())
{
LOG_ERR("Session with sessionId [" << sessionId << "] not found while saving docKey [" << _docKey << "].");
LOG_ERR("Session with sessionId ["
<< sessionId << "] not found while storing document docKey [" << _docKey
<< "]. The document will not be uploaded to storage at this time.");
return false;
}
// Check that we are actually about to upload a successfully saved document.
if (!success)
if (!success && !force)
{
LOG_ERR("Cannot save docKey [" << _docKey << "], the .uno:Save has failed in LOK.");
LOG_ERR("Cannot store docKey [" << _docKey << "] as .uno:Save has failed in LOK.");
it->second->sendTextFrame("error: cmd=storage kind=savefailed");
return false;
}
if (force)
{
LOG_DBG("Document docKey [" << _docKey << "] will be forcefully uploaded to storage.");
}
const bool isSaveAs = !saveAsPath.empty();
const Authorization auth = it->second->getAuthorization();
const std::string uri = isSaveAs ? saveAsPath : it->second->getPublicUri().toString();
@ -1060,7 +1074,7 @@ bool DocumentBroker::autoSave(const bool force, const bool dontSaveIfUnmodified)
std::string savingSessionId;
for (auto& sessionIt : _sessions)
{
// Save the document using an editable session, or first ...
// Save the document using an editable and loaded session, or first ...
if (savingSessionId.empty()
|| (!sessionIt.second->isReadOnly() && sessionIt.second->isViewLoaded()
&& !sessionIt.second->inWaitDisconnected()))
@ -1278,15 +1292,15 @@ size_t DocumentBroker::removeSession(const std::string& id)
_markToDestroy = (_sessions.size() <= 1);
const bool lastEditableSession = !it->second->isReadOnly() && !haveAnotherEditableSession(id);
static const bool dontSaveIfUnmodified = !LOOLWSD::getConfigValue<bool>("per_document.always_save_on_exit", false);
LOG_INF("Removing session ["
<< id << "] on docKey [" << _docKey << "]. Have " << _sessions.size()
<< " sessions. IsReadOnly: " << it->second->isReadOnly()
<< ", IsViewLoaded: " << it->second->isViewLoaded() << ", IsWaitDisconnected: "
<< it->second->inWaitDisconnected() << ", MarkToDestroy: " << _markToDestroy
<< ", LastEditableSession: " << lastEditableSession);
const auto dontSaveIfUnmodified = !LOOLWSD::getConfigValue<bool>("per_document.always_save_on_exit", false);
<< ", LastEditableSession: " << lastEditableSession
<< ", dontSaveIfUnmodified: " << dontSaveIfUnmodified);
// If last editable, save and don't remove until after uploading to storage.
if (!lastEditableSession || !autoSave(isPossiblyModified(), dontSaveIfUnmodified))
@ -1677,6 +1691,7 @@ void DocumentBroker::sendRequestedTiles(const std::shared_ptr<ClientSession>& se
float tilesOnFlyUpperLimit = 0;
if (normalizedVisArea.hasSurface() && session->getTileWidthInTwips() != 0 && session->getTileHeightInTwips() != 0)
{
const int tilesFitOnWidth = std::ceil(normalizedVisArea.getRight() / session->getTileWidthInTwips()) -
std::ceil(normalizedVisArea.getLeft() / session->getTileWidthInTwips()) + 1;
const int tilesFitOnHeight = std::ceil(normalizedVisArea.getBottom() / session->getTileHeightInTwips()) -

View file

@ -397,7 +397,11 @@ private:
void terminateChild(const std::string& closeReason);
/// Saves the doc to the storage.
bool saveToStorageInternal(const std::string& sesionId, bool success, const std::string& result = "", const std::string& saveAsPath = std::string(), const std::string& saveAsFilename = std::string(), const bool isRename = false);
bool saveToStorageInternal(const std::string& sesionId, bool success,
const std::string& result = std::string(),
const std::string& saveAsPath = std::string(),
const std::string& saveAsFilename = std::string(),
const bool isRename = false, const bool force = false);
/// True iff a save is in progress (requested but not completed).
bool isSaving() const { return _lastSaveResponseTime < _lastSaveRequestTime; }

View file

@ -829,6 +829,7 @@ void LOOLWSD::initialize(Application& self)
{ "net.proto", "all" },
{ "net.service_root", "" },
{ "num_prespawn_children", "1" },
{ "per_document.always_save_on_exit", "false" },
{ "per_document.autosave_duration_secs", "300" },
{ "per_document.document_signing_url", VEREIGN_URL },
{ "per_document.idle_timeout_secs", "3600" },