[Libreoffice-commits] online.git: loolwsd/ChildProcessSession.cpp loolwsd/DocumentBroker.cpp loolwsd/MasterProcessSession.cpp loolwsd/MasterProcessSession.hpp
Ashod Nakashian
ashod.nakashian at collabora.co.uk
Wed Apr 27 03:50:45 UTC 2016
loolwsd/ChildProcessSession.cpp | 15 ++++++++++++++-
loolwsd/DocumentBroker.cpp | 21 +++++++--------------
loolwsd/MasterProcessSession.cpp | 8 ++++++++
loolwsd/MasterProcessSession.hpp | 4 ++--
4 files changed, 31 insertions(+), 17 deletions(-)
New commits:
commit e6a6b296ea354c05f4b43ffab9fce6c8d1b50739
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Tue Apr 26 21:55:18 2016 -0400
loolwsd: avoid communicating with clients under shared lock
DocumentBroker is a central document management object.
Using it to communicate with clients leaves it open
to the whims of slow connections. When its lock
is help for a long time, all clients stall, giving
users a very poor experience.
The culprit in this case was takeEditLock, which
sent to all clients the new edit lock state.
To avoid this, DocumentBroker now sends this
state to the children (via a loopback socket,)
which process messages in a separate process and
each on its own queue thread. The children then
in turn echo this edit lock state back to the
clients. This communication back is done on the
prisoner socket thread, which doesn't lock or
stall any shared objects or threads.
Change-Id: I475f6b3ecac9ae2a689bd30f43d416871aa0e384
Reviewed-on: https://gerrit.libreoffice.org/24420
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp
index 0def91d..71fd825 100644
--- a/loolwsd/ChildProcessSession.cpp
+++ b/loolwsd/ChildProcessSession.cpp
@@ -456,7 +456,8 @@ bool ChildProcessSession::_handleInput(const char *buffer, int length)
tokens[0] == "resetselection" ||
tokens[0] == "saveas" ||
tokens[0] == "useractive" ||
- tokens[0] == "userinactive");
+ tokens[0] == "userinactive" ||
+ tokens[0] == "editlock:");
{
std::unique_lock<std::recursive_mutex> lock(Mutex);
@@ -534,6 +535,18 @@ bool ChildProcessSession::_handleInput(const char *buffer, int length)
{
setIsActive(false);
}
+ else if (tokens[0] == "editlock:")
+ {
+ // Nothing for us to do but to let the
+ // client know about the edit lock state.
+ // Yes, this is echoed back because it's better
+ // to do this on each child's queue and thread
+ // than for WSD to potentially stall while notifying
+ // each client with the edit lock state.
+ Log::trace("Echoing back [" + firstLine + "].");
+ sendTextFrame(firstLine);
+ return true;
+ }
else
{
assert(false);
diff --git a/loolwsd/DocumentBroker.cpp b/loolwsd/DocumentBroker.cpp
index 62485ae..69728cb 100644
--- a/loolwsd/DocumentBroker.cpp
+++ b/loolwsd/DocumentBroker.cpp
@@ -269,19 +269,13 @@ std::string DocumentBroker::getJailRoot() const
void DocumentBroker::takeEditLock(const std::string& id)
{
+ Log::debug("Session " + id + " taking the editing lock.");
std::lock_guard<std::mutex> lock(_mutex);
+
+ // Forward to all children.
for (auto& it: _sessions)
{
- if (it.first != id)
- {
- it.second->setEditLock(false);
- it.second->sendTextFrame("editlock: 0");
- }
- else
- {
- it.second->setEditLock(true);
- it.second->sendTextFrame("editlock: 1");
- }
+ it.second->setEditLock(it.first == id);
}
}
@@ -304,8 +298,8 @@ size_t DocumentBroker::addSession(std::shared_ptr<MasterProcessSession>& session
if (_sessions.size() == 1)
{
- session->setEditLock(true);
- session->sendTextFrame("editlock: 1");
+ Log::debug("Giving editing lock to the first session [" + id + "].");
+ _sessions.begin()->second->markEditLock(true);
}
return _sessions.size();
@@ -336,7 +330,7 @@ size_t DocumentBroker::removeSession(const std::string& id)
if (it != _sessions.end())
{
const auto haveEditLock = it->second->isEditLocked();
- it->second->setEditLock(false);
+ it->second->markEditLock(false);
_sessions.erase(it);
if (haveEditLock)
@@ -346,7 +340,6 @@ size_t DocumentBroker::removeSession(const std::string& id)
if (it != _sessions.end())
{
it->second->setEditLock(true);
- it->second->sendTextFrame("editlock: 1");
}
}
}
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index f85b4f3..12660fe 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -420,6 +420,14 @@ bool MasterProcessSession::getStatus(const char *buffer, int length)
return true;
}
+void MasterProcessSession::setEditLock(const bool value)
+{
+ // Update the sate and forward to child.
+ _bEditLock = value;
+ const auto msg = std::string("editlock: ") + (value ? "1" : "0");
+ forwardToPeer(msg.data(), msg.size());
+}
+
bool MasterProcessSession::getCommandValues(const char *buffer, int length, StringTokenizer& tokens)
{
std::string command;
diff --git a/loolwsd/MasterProcessSession.hpp b/loolwsd/MasterProcessSession.hpp
index 16d9b64..c3e1662 100644
--- a/loolwsd/MasterProcessSession.hpp
+++ b/loolwsd/MasterProcessSession.hpp
@@ -47,8 +47,8 @@ class MasterProcessSession final : public LOOLSession, public std::enable_shared
void setPeer(const std::shared_ptr<MasterProcessSession>& peer) { _peer = peer; }
- void setEditLock(const bool value) { _bEditLock = value; }
-
+ void setEditLock(const bool value);
+ void markEditLock(const bool value) { _bEditLock = value; }
bool isEditLocked() const { return _bEditLock; }
bool shutdownPeer(Poco::UInt16 statusCode, const std::string& message);
More information about the Libreoffice-commits
mailing list