[Libreoffice-commits] online.git: loolwsd/DocumentBroker.cpp loolwsd/DocumentBroker.hpp loolwsd/LOOLWSD.cpp
Ashod Nakashian
ashod.nakashian at collabora.co.uk
Mon Apr 11 03:11:56 UTC 2016
loolwsd/DocumentBroker.cpp | 30 +++++++++++++++++++++++++++---
loolwsd/DocumentBroker.hpp | 13 ++++++++++++-
loolwsd/LOOLWSD.cpp | 16 ++++++++++++----
3 files changed, 51 insertions(+), 8 deletions(-)
New commits:
commit 280669c253af08c001238b9465d6fa4e048cb545
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Sun Apr 10 22:07:09 2016 -0400
loolwsd: save on disconnection
Last client disconnection now correctly issues a save
and waits for the confirmation before tearing down
the sockets, queues and threads.
Change-Id: I28c28d79a17d359e9aa1fe67b983ca9fb592b847
Reviewed-on: https://gerrit.libreoffice.org/23978
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/loolwsd/DocumentBroker.cpp b/loolwsd/DocumentBroker.cpp
index b2d93f1..c7caba4 100644
--- a/loolwsd/DocumentBroker.cpp
+++ b/loolwsd/DocumentBroker.cpp
@@ -130,6 +130,8 @@ bool DocumentBroker::load(const std::string& jailId)
bool DocumentBroker::save()
{
+ std::unique_lock<std::mutex> lock(_saveMutex);
+
const auto uri = _uriPublic.toString();
Log::debug("Saving to URI [" + uri + "].");
@@ -139,6 +141,7 @@ bool DocumentBroker::save()
_lastSaveTime = std::chrono::steady_clock::now();
_tileCache->documentSaved();
Log::debug("Saved to URI [" + uri + "] and updated tile cache.");
+ _saveCV.notify_all();
return true;
}
@@ -146,13 +149,13 @@ bool DocumentBroker::save()
return false;
}
-void DocumentBroker::autoSave()
+bool DocumentBroker::autoSave(const bool force)
{
std::unique_lock<std::mutex> sessionsLock(_wsSessionsMutex);
if (_wsSessions.empty())
{
// Shouldn't happen.
- return;
+ return false;
}
// Find the most recent activity.
@@ -170,8 +173,10 @@ void DocumentBroker::autoSave()
if (inactivityTimeMs < timeSinceLastSaveMs)
{
// Either we've been idle long enough, or it's auto-save time.
+ // Or we are asked to save anyway.
if (inactivityTimeMs >= IdleSaveDurationMs ||
- timeSinceLastSaveMs >= AutoSaveDurationMs)
+ timeSinceLastSaveMs >= AutoSaveDurationMs ||
+ force)
{
Log::info("Auto-save triggered for doc [" + _docKey + "].");
@@ -192,8 +197,27 @@ void DocumentBroker::autoSave()
{
Log::error("Failed to auto-save doc [" + _docKey + "]: No valid sessions.");
}
+
+ return sent;
}
}
+
+ return false;
+}
+
+bool DocumentBroker::waitSave(const size_t timeoutMs)
+{
+ std::unique_lock<std::mutex> lock(_saveMutex);
+
+ // Remeber the last save time, since this is the predicate.
+ const auto lastSaveTime = _lastSaveTime;
+
+ if (_saveCV.wait_for(lock, std::chrono::milliseconds(timeoutMs)) == std::cv_status::no_timeout)
+ {
+ return true;
+ }
+
+ return (lastSaveTime != _lastSaveTime);
}
std::string DocumentBroker::getJailRoot() const
diff --git a/loolwsd/DocumentBroker.hpp b/loolwsd/DocumentBroker.hpp
index 17a1cfe..27a527a 100644
--- a/loolwsd/DocumentBroker.hpp
+++ b/loolwsd/DocumentBroker.hpp
@@ -13,6 +13,7 @@
#include <signal.h>
#include <atomic>
+#include <chrono>
#include <memory>
#include <mutex>
#include <string>
@@ -131,7 +132,15 @@ public:
bool save();
- void autoSave();
+ /// Save the document if there was activity since last save.
+ /// force when true, will force saving immediatly, regardless
+ /// of how long ago the activity was.
+ bool autoSave(const bool force);
+
+ /// Wait until the document is saved next.
+ /// This is used to cleanup after the last save.
+ /// Returns false if times out.
+ bool waitSave(const size_t timeoutMs);
Poco::URI getPublicUri() const { return _uriPublic; }
Poco::URI getJailedUri() const { return _uriJailed; }
@@ -178,6 +187,8 @@ private:
std::unique_ptr<TileCache> _tileCache;
std::shared_ptr<ChildProcess> _childProcess;
std::mutex _mutex;
+ std::condition_variable _saveCV;
+ std::mutex _saveMutex;
static constexpr auto IdleSaveDurationMs = 30 * 1000;
static constexpr auto AutoSaveDurationMs = 300 * 1000;
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 989c3f7..0f5a391 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -592,10 +592,18 @@ private:
if (docBroker->getSessionsCount() == 1 && !normalShutdown && !session->_bLoadError)
{
- //TODO: This isn't this simple. We need to wait for the notification
- // of save so Storage can persist the save (if necessary).
Log::info("Non-deliberate shutdown of the last session, saving the document before tearing down.");
- queue->put("uno .uno:Save");
+
+ // Use auto-save to save only when there are modifications since last save.
+ // We also need to wait until the save notification reaches us
+ // and Storage persists the document.
+ // Note: technically, there is a race between these two (we should
+ // hold the broker lock before issueing the save and waiting,)
+ // but in practice this shouldn't happen.
+ if (docBroker->autoSave(true) && !docBroker->waitSave(5000))
+ {
+ Log::error("Auto-save before closing failed.");
+ }
}
else
{
@@ -1562,7 +1570,7 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
std::unique_lock<std::mutex> docBrokersLock(docBrokersMutex);
for (auto& brokerIt : docBrokers)
{
- brokerIt.second->autoSave();
+ brokerIt.second->autoSave(false);
}
}
catch (const std::exception& exc)
More information about the Libreoffice-commits
mailing list