libreoffice-online/loolwsd/MasterProcessSession.hpp
Ashod Nakashian e6a6b296ea 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@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2016-04-27 03:50:22 +00:00

102 lines
3.7 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef INCLUDED_MASTERPROCESSSESSION_HPP
#define INCLUDED_MASTERPROCESSSESSION_HPP
#include <time.h>
#include <Poco/Random.h>
#include "LOOLSession.hpp"
#include "MessageQueue.hpp"
class DocumentBroker;
class MasterProcessSession final : public LOOLSession, public std::enable_shared_from_this<MasterProcessSession>
{
public:
MasterProcessSession(const std::string& id,
const Kind kind,
std::shared_ptr<Poco::Net::WebSocket> ws,
std::shared_ptr<DocumentBroker> docBroker,
std::shared_ptr<BasicTileQueue> queue);
virtual ~MasterProcessSession();
virtual bool getStatus(const char *buffer, int length) override;
virtual bool getCommandValues(const char *buffer, int length, Poco::StringTokenizer& tokens) override;
virtual bool getPartPageRectangles(const char *buffer, int length) override;
/**
* Return the URL of the saved-as document when it's ready. If called
* before it's ready, the call blocks till then.
*/
std::string getSaveAs();
std::shared_ptr<DocumentBroker> getDocumentBroker() const { return _docBroker; }
std::shared_ptr<BasicTileQueue> getQueue() const { return _queue; }
void setPeer(const std::shared_ptr<MasterProcessSession>& peer) { _peer = peer; }
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);
public:
// Raise this flag on ToClient from ToPrisoner to let ToClient know of load failures
bool _bLoadError = false;
protected:
virtual bool loadDocument(const char *buffer, int length, Poco::StringTokenizer& tokens) override;
virtual void sendTile(const char *buffer, int length, Poco::StringTokenizer& tokens) override;
virtual void sendCombinedTiles(const char *buffer, int length, Poco::StringTokenizer& tokens) override;
virtual void sendFontRendering(const char *buffer, int length, Poco::StringTokenizer& tokens) override;
private:
void dispatchChild();
void forwardToPeer(const char *buffer, int length);
// If _kind==ToPrisoner and the child process has started and completed its handshake with the
// parent process: Points to the WebSocketSession for the child process handling the document in
// question, if any.
// In the session to the child process, points to the LOOLSession for the LOOL client. This will
// obvious have to be rethought when we add collaboration and there can be several LOOL clients
// per document being edited (i.e., per child process).
std::weak_ptr<MasterProcessSession> _peer;
static
Poco::Path getJailPath(const std::string& childId);
virtual bool _handleInput(const char *buffer, int length) override;
int _curPart;
int _loadPart;
/// Kind::ToClient instances store URLs of completed 'save as' documents.
MessageQueue _saveAsQueue;
std::shared_ptr<DocumentBroker> _docBroker;
std::shared_ptr<BasicTileQueue> _queue;
// 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
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */