[Libreoffice-commits] online.git: 2 commits - loleaflet/dist loleaflet/src loolwsd/ChildProcessSession.cpp loolwsd/DocumentBroker.cpp loolwsd/DocumentBroker.hpp loolwsd/LOOLWSD.cpp loolwsd/MasterProcessSession.cpp loolwsd/MasterProcessSession.hpp
Pranav Kant
pranavk at collabora.com
Thu Mar 31 13:57:22 UTC 2016
loleaflet/dist/toolbar/toolbar.js | 36 ++++++++++++++++++++
loleaflet/src/layer/tile/TileLayer.js | 10 +++++
loolwsd/ChildProcessSession.cpp | 7 +++
loolwsd/DocumentBroker.cpp | 53 ++++++++++++++++++++++++++++++
loolwsd/DocumentBroker.hpp | 18 +++++++++-
loolwsd/LOOLWSD.cpp | 60 ++++++++++++++++++----------------
loolwsd/MasterProcessSession.cpp | 22 +++++++++++-
loolwsd/MasterProcessSession.hpp | 13 ++++++-
8 files changed, 188 insertions(+), 31 deletions(-)
New commits:
commit b81abc4079047c2735b1f5160f18fffda70aed72
Author: Pranav Kant <pranavk at collabora.com>
Date: Thu Mar 24 00:48:21 2016 +0530
loleaflet: Edit lock implemention on front-end
Change-Id: I97c2b2e0a4ef51c6335cefe3e9ec8f5904deb9f4
diff --git a/loleaflet/dist/toolbar/toolbar.js b/loleaflet/dist/toolbar/toolbar.js
index 5f1da68..6e3e174 100644
--- a/loleaflet/dist/toolbar/toolbar.js
+++ b/loleaflet/dist/toolbar/toolbar.js
@@ -137,6 +137,10 @@ $(function () {
{ type: 'button', id: 'duplicatepage', img: 'duplicatepage', hint: _("Duplicate Page") },
{ type: 'button', id: 'deletepage', img: 'deletepage', hint: _("Delete Page") },
{ type: 'html', id: 'right' },
+ { type: 'break' },
+ { type: 'button', id: 'takeedit', img: 'edit', hint: _("Take edit lock (others can only view)")},
+ { type: 'html', id: 'takeedit_text', html: '<div id="takeedit_text">VIEWING</div>' },
+ { type: 'break' },
{ type: 'button', id: 'prev', img: 'prev', hint: _("Previous page/part") },
{ type: 'button', id: 'next', img: 'next', hint: _("Next page/part") },
{ type: 'break' },
@@ -271,6 +275,11 @@ function onClick(id) {
callback: onSaveAs
});
}
+ else if (id === 'takeedit') {
+ if (!item.checked) {
+ map._socket.sendMessage('takeedit');
+ }
+ }
else if (id === 'searchprev') {
map.search(L.DomUtil.get('search-input').value, true);
}
@@ -869,6 +878,33 @@ map.on('hyperlinkclicked', function (e) {
window.open(e.url, '_blank');
});
+map.on('editlock', function (e) {
+ var toolbar = w2ui['toolbar-down'];
+ if (e.value) {
+ toolbar.check('takeedit');
+ toolbar.disable('takeedit');
+ toolbar.set('takeedit', {hint: _('You are editing (others can only view)')});
+
+ $('#takeedit_text')
+ .w2tag('You are editing now')
+ .html('EDITING');
+ setTimeout(function() {
+ $('#takeedit_text').w2tag('');
+ }, 5000);
+ }
+ else {
+ toolbar.uncheck('takeedit');
+ toolbar.enable('takeedit');
+ toolbar.set('takeedit', {hint: _('Take edit lock (others can only view)')});
+ $('#takeedit_text')
+ .w2tag('You are viewing now')
+ .html('VIEWING');
+ setTimeout(function() {
+ $('#takeedit_text').w2tag('');
+ }, 5000);
+ }
+});
+
$(window).resize(function() {
resizeToolbar();
});
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 202fb0d..5eee647 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -330,6 +330,9 @@ L.TileLayer = L.GridLayer.extend({
else if (textMsg.startsWith('unocommandresult:')) {
this._onUnoCommandResultMsg(textMsg);
}
+ else if (textMsg.startsWith('editlock')) {
+ this._onEditLock(textMsg);
+ }
},
_onCommandValuesMsg: function (textMsg) {
@@ -1237,6 +1240,13 @@ L.TileLayer = L.GridLayer.extend({
}
},
+ _onEditLock: function (textMsg) {
+ var val = parseInt(textMsg.split(' ')[1]);
+ if (!isNaN(val)) {
+ this._map.fire('editlock', {value: val});
+ }
+ },
+
_invalidatePreviews: function () {
if (this._map._docPreviews && this._previewInvalidations.length > 0) {
var toInvalidate = {};
commit b8e9075f23f0f474874c52fd62bd6057de260c86
Author: Pranav Kant <pranavk at collabora.com>
Date: Wed Mar 23 22:25:28 2016 +0530
bccu#1621: Introduce an edit lock
... which can be taken only one at a time. Others can only view,
not edit. When a session with edit lock exits, the edit lock is
handed over to the next alive session.
Change-Id: I712a4e70369f1d07c1d83af416a0f5c288b05c7d
diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp
index 3c74b15..32bd228 100644
--- a/loolwsd/ChildProcessSession.cpp
+++ b/loolwsd/ChildProcessSession.cpp
@@ -334,7 +334,12 @@ bool ChildProcessSession::_handleInput(const char *buffer, int length)
const std::string firstLine = getFirstLine(buffer, length);
StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
- if (tokens[0] == "canceltiles")
+ if (tokens[0] == "dummymsg")
+ {
+ // Just to update the activity of view-only mode
+ return true;
+ }
+ else if (tokens[0] == "canceltiles")
{
// this command makes sense only on the command queue level, nothing
// to do here
diff --git a/loolwsd/DocumentBroker.cpp b/loolwsd/DocumentBroker.cpp
index 5e35a86..c36067e 100644
--- a/loolwsd/DocumentBroker.cpp
+++ b/loolwsd/DocumentBroker.cpp
@@ -137,4 +137,57 @@ std::string DocumentBroker::getJailRoot() const
return Poco::Path(_childRoot, _jailId).toString();
}
+void DocumentBroker::takeEditLock(const std::string id)
+{
+ std::lock_guard<std::mutex> sessionsLock(_wsSessionsMutex);
+ for (auto& it: _wsSessions)
+ {
+ if (it.first != id)
+ {
+ it.second->setEditLock(false);
+ it.second->sendTextFrame("editlock 0");
+ }
+ else
+ {
+ it.second->setEditLock(true);
+ it.second->sendTextFrame("editlock 1");
+ }
+ }
+}
+
+void DocumentBroker::addWSSession(const std::string id, std::shared_ptr<MasterProcessSession>& ws)
+{
+ std::lock_guard<std::mutex> sessionsLock(_wsSessionsMutex);
+ auto ret = _wsSessions.emplace(id, ws);
+ if (!ret.second)
+ {
+ Log::warn("DocumentBroker: Trying to add already existed session.");
+ }
+}
+
+void DocumentBroker::removeWSSession(const std::string id)
+{
+ std::lock_guard<std::mutex> sessionsLock(_wsSessionsMutex);
+ bool bEditLock = false;
+ auto it = _wsSessions.find(id);
+ if (it != _wsSessions.end())
+ {
+ if (it->second->isEditLocked())
+ bEditLock = true;
+
+ _wsSessions.erase(it);
+ }
+
+ if (bEditLock)
+ {
+ // pass the edit lock to first session in map
+ it = _wsSessions.begin();
+ if (it != _wsSessions.end())
+ {
+ it->second->setEditLock(true);
+ it->second->sendTextFrame("editlock 1");
+ }
+ }
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/loolwsd/DocumentBroker.hpp b/loolwsd/DocumentBroker.hpp
index c2fa43b..3d848de 100644
--- a/loolwsd/DocumentBroker.hpp
+++ b/loolwsd/DocumentBroker.hpp
@@ -14,10 +14,12 @@
#include <memory>
#include <mutex>
#include <string>
+#include <map>
#include <Poco/URI.h>
-#include <Util.hpp>
+#include "MasterProcessSession.hpp"
+#include "Util.hpp"
// Forwards.
class StorageBase;
@@ -68,6 +70,20 @@ public:
std::string getJailRoot() const;
+ /// Ignore input events from all web socket sessions
+ /// except this one
+ void takeEditLock(const std::string id);
+
+ void addWSSession(const std::string id, std::shared_ptr<MasterProcessSession>& ws);
+
+ void removeWSSession(const std::string id);
+
+ unsigned getWSSessionsCount() { return _wsSessions.size(); }
+
+public:
+ std::map<std::string, std::shared_ptr<MasterProcessSession>> _wsSessions;
+ std::mutex _wsSessionsMutex;
+
private:
const Poco::URI _uriPublic;
const std::string _docKey;
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 4f6cb52..8246a01 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -178,9 +178,6 @@ using Poco::XML::NodeList;
static std::map<std::string, std::shared_ptr<DocumentBroker>> docBrokers;
static std::mutex docBrokersMutex;
-static std::unordered_set<std::shared_ptr<MasterProcessSession>> sessions;
-static std::mutex sessionsMutex;
-
/// Handles the filename part of the convert-to POST request payload.
class ConvertToPartHandler : public PartHandler
{
@@ -255,6 +252,7 @@ private:
std::shared_ptr<WebSocket> ws;
const LOOLSession::Kind kind = LOOLSession::Kind::ToClient;
auto session = std::make_shared<MasterProcessSession>(id, kind, ws, docBroker);
+ session->setEditLock(true);
docBroker->incSessions();
lock.unlock();
@@ -455,10 +453,11 @@ private:
docBroker->incSessions();
docBrokersLock.unlock();
- std::unique_lock<std::mutex> sessionsLock(sessionsMutex);
- sessions.insert(session);
- Log::debug("sessions++: " + std::to_string(sessions.size()));
- sessionsLock.unlock();
+ docBroker->addWSSession(id, session);
+ unsigned wsSessionsCount = docBroker->getWSSessionsCount();
+ Log::warn(docKey + ", ws_sessions++: " + std::to_string(wsSessionsCount));
+ if (wsSessionsCount == 1)
+ session->setEditLock(true);
// Request a kit process for this doc.
const std::string aMessage = "request " + id + " " + docKey + "\n";
@@ -509,10 +508,9 @@ private:
queue.clear();
}
- sessionsLock.lock();
- sessions.erase(session);
- Log::debug("sessions--: " + std::to_string(sessions.size()));
- sessionsLock.unlock();
+ docBroker->removeWSSession(id);
+ wsSessionsCount = docBroker->getWSSessionsCount();
+ Log::warn(docKey + ", ws_sessions--: " + std::to_string(wsSessionsCount));
Log::info("Finishing GET request handler for session [" + id + "]. Joining the queue.");
queue.put("eof");
@@ -1327,16 +1325,20 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
Log::debug("30-second check");
last30SecCheck = now;
- std::unique_lock<std::mutex> sessionsLock(sessionsMutex);
- for (auto& it : sessions)
+ std::unique_lock<std::mutex> docBrokersLock(docBrokersMutex);
+ for (auto& brokerIt : docBrokers)
{
- if (it->_lastMessageTime > it->_idleSaveTime &&
- it->_lastMessageTime < now - 30)
+ std::unique_lock<std::mutex> sessionsLock(brokerIt.second->_wsSessionsMutex);
+ for (auto& sessionIt: brokerIt.second->_wsSessions)
{
- // Trigger a .uno:Save
- Log::info("Idle save triggered for session " + it->getId());
-
- it->_idleSaveTime = now;
+ if (sessionIt.second->_lastMessageTime > sessionIt.second->_idleSaveTime &&
+ sessionIt.second->_lastMessageTime < now - 30)
+ {
+ // Trigger a .uno:Save
+ Log::info("Idle save triggered for session " + sessionIt.second->getId());
+
+ sessionIt.second->_idleSaveTime = now;
+ }
}
}
}
@@ -1345,16 +1347,20 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
Log::debug("Five-minute check");
lastFiveMinuteCheck = now;
- std::unique_lock<std::mutex> sessionsLock(sessionsMutex);
- for (auto& it : sessions)
+ std::unique_lock<std::mutex> docBrokersLock(docBrokersMutex);
+ for (auto& brokerIt : docBrokers)
{
- if (it->_lastMessageTime >= it->_idleSaveTime &&
- it->_lastMessageTime >= it->_autoSaveTime)
+ std::unique_lock<std::mutex> sessionsLock(brokerIt.second->_wsSessionsMutex);
+ for (auto& sessionIt: brokerIt.second->_wsSessions)
{
- // Trigger a .uno:Save
- Log::info("Auto-save triggered for session " + it->getId());
-
- it->_autoSaveTime = now;
+ if (sessionIt.second->_lastMessageTime >= sessionIt.second->_idleSaveTime &&
+ sessionIt.second->_lastMessageTime >= sessionIt.second->_autoSaveTime)
+ {
+ // Trigger a .uno:Save
+ Log::info("Auto-save triggered for session " + sessionIt.second->getId());
+
+ sessionIt.second->_autoSaveTime = now;
+ }
}
}
}
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index 90a82af..a494c5e 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -232,6 +232,11 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length)
else if (tokens[0] == "status:")
{
_docBroker->tileCache().saveTextFile(std::string(buffer, length), "status.txt");
+
+ // let clients know if they hold the edit lock
+ std::string message = "editlock ";
+ message += std::to_string(peer->isEditLocked());
+ forwardToPeer(message.c_str(), message.size());
}
else if (tokens[0] == "commandvalues:")
{
@@ -294,6 +299,11 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length)
Log::error(getName() + ": Unexpected request [" + tokens[0] + "].");
assert(false);
}
+ else if (tokens[0] == "takeedit")
+ {
+ _docBroker->takeEditLock(getId());
+ return true;
+ }
else if (tokens[0] == "load")
{
if (_docURL != "")
@@ -389,7 +399,12 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length)
_docBroker->tileCache().removeFile("status.txt");
}
- if (tokens[0] != "requestloksession")
+ if (_kind == Kind::ToClient && !isEditLocked())
+ {
+ std::string dummyFrame = "dummymsg";
+ forwardToPeer(dummyFrame.c_str(), dummyFrame.size());
+ }
+ else if (tokens[0] != "requestloksession")
{
forwardToPeer(buffer, length);
}
@@ -460,6 +475,10 @@ bool MasterProcessSession::getStatus(const char *buffer, int length)
if (status.size() > 0)
{
sendTextFrame(status);
+ // let clients know if they hold the edit lock
+ std::string message = "editlock ";
+ message += std::to_string(isEditLocked());
+ sendTextFrame(message);
return true;
}
@@ -812,6 +831,7 @@ void MasterProcessSession::forwardToPeer(const char *buffer, int length)
Log::error(getName() + ": no peer to forward to.");
return;
}
+
peer->sendBinaryFrame(buffer, length);
}
diff --git a/loolwsd/MasterProcessSession.hpp b/loolwsd/MasterProcessSession.hpp
index be09337..7b57709 100644
--- a/loolwsd/MasterProcessSession.hpp
+++ b/loolwsd/MasterProcessSession.hpp
@@ -14,10 +14,11 @@
#include <Poco/Random.h>
-#include "DocumentBroker.hpp"
#include "LOOLSession.hpp"
#include "TileCache.hpp"
+class DocumentBroker;
+
class MasterProcessSession final : public LOOLSession, public std::enable_shared_from_this<MasterProcessSession>
{
public:
@@ -44,6 +45,11 @@ class MasterProcessSession final : public LOOLSession, public std::enable_shared
std::shared_ptr<DocumentBroker> getDocumentBroker() const { return _docBroker; }
+ void setEditLock(const bool value) { _bEditLock = value; }
+
+ bool isEditLocked() const { return _bEditLock; }
+
+public:
// Sessions to pre-spawned child processes that have connected but are not yet assigned a
// document to work on.
static std::map<std::string, std::shared_ptr<MasterProcessSession>> AvailableChildSessions;
@@ -88,6 +94,11 @@ class MasterProcessSession final : public LOOLSession, public std::enable_shared
/// Kind::ToClient instances store URLs of completed 'save as' documents.
MessageQueue _saveAsQueue;
std::shared_ptr<DocumentBroker> _docBroker;
+
+ // If this document holds the edit lock.
+ // An edit lock will only allow the current session to make edits,
+ // while other session opening the same document can only see
+ bool _bEditLock = false;
};
#endif
More information about the Libreoffice-commits
mailing list