[Libreoffice-commits] online.git: loolwsd/ChildProcessSession.cpp loolwsd/ChildProcessSession.hpp loolwsd/DocumentBroker.cpp loolwsd/DocumentBroker.hpp loolwsd/LOOLKit.cpp loolwsd/MasterProcessSession.cpp loolwsd/TileCache.cpp loolwsd/TileCache.hpp

Ashod Nakashian ashod.nakashian at collabora.co.uk
Wed May 4 10:36:19 UTC 2016


 loolwsd/ChildProcessSession.cpp  |   77 ---------------------
 loolwsd/ChildProcessSession.hpp  |    2 
 loolwsd/DocumentBroker.cpp       |  120 +++++++++++++++++++++++++++++++++
 loolwsd/DocumentBroker.hpp       |    6 +
 loolwsd/LOOLKit.cpp              |   94 ++++++++++++++++++++++++++
 loolwsd/MasterProcessSession.cpp |  138 +--------------------------------------
 loolwsd/TileCache.cpp            |   13 +--
 loolwsd/TileCache.hpp            |    2 
 8 files changed, 233 insertions(+), 219 deletions(-)

New commits:
commit a240f2666f4ce8d54008777e154c6258bd816be1
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Sun May 1 20:50:11 2016 -0400

    loolwsd: tile traffic is now completely centralized
    
    WSD's DocumentBroker and Kit's Document now handle
    the communication of tiles as well as all aspects
    of rendering, caching, unifying requests and
    distributing results etc.
    
    Change-Id: Ie22fbaaae26b91185ee348ec7077f30430eec0f6
    Reviewed-on: https://gerrit.libreoffice.org/24640
    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 bf9b8d2..5ca7d6e 100644
--- a/loolwsd/ChildProcessSession.cpp
+++ b/loolwsd/ChildProcessSession.cpp
@@ -443,7 +443,7 @@ bool ChildProcessSession::_handleInput(const char *buffer, int length)
     }
     else if (tokens[0] == "tile")
     {
-        sendTile(buffer, length, tokens);
+        assert(!"Tile traffic should go through the DocumentBroker-LoKit WS.");
     }
     else if (tokens[0] == "tilecombine")
     {
@@ -725,81 +725,6 @@ namespace {
     }
 }
 
-void ChildProcessSession::sendTile(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens)
-{
-    int part, width, height, tilePosX, tilePosY, tileWidth, tileHeight;
-
-    if (tokens.count() < 8 ||
-        !getTokenInteger(tokens[1], "part", part) ||
-        !getTokenInteger(tokens[2], "width", width) ||
-        !getTokenInteger(tokens[3], "height", height) ||
-        !getTokenInteger(tokens[4], "tileposx", tilePosX) ||
-        !getTokenInteger(tokens[5], "tileposy", tilePosY) ||
-        !getTokenInteger(tokens[6], "tilewidth", tileWidth) ||
-        !getTokenInteger(tokens[7], "tileheight", tileHeight))
-    {
-        sendTextFrame("error: cmd=tile kind=syntax");
-        return;
-    }
-
-    if (part < 0 ||
-        width <= 0 ||
-        height <= 0 ||
-        tilePosX < 0 ||
-        tilePosY < 0 ||
-        tileWidth <= 0 ||
-        tileHeight <= 0)
-    {
-        sendTextFrame("error: cmd=tile kind=invalid");
-        return;
-    }
-
-    std::unique_lock<std::recursive_mutex> lock(Mutex);
-
-    if (_multiView)
-        _loKitDocument->pClass->setView(_loKitDocument, _viewId);
-
-    std::string response = "tile: " + Poco::cat(std::string(" "), tokens.begin() + 1, tokens.end());
-
-#if ENABLE_DEBUG
-    response += " renderid=" + Util::UniqueId();
-#endif
-    response += "\n";
-
-    std::vector<char> output;
-    output.reserve(response.size() + (4 * width * height));
-    output.resize(response.size());
-    std::memcpy(output.data(), response.data(), response.size());
-
-    std::vector<unsigned char> pixmap;
-    pixmap.resize(4 * width * height);
-
-    bool makeSlow = delayAndRewritePart(part);
-
-    if (_docType != "text" && part != _loKitDocument->pClass->getPart(_loKitDocument))
-    {
-        _loKitDocument->pClass->setPart(_loKitDocument, part);
-    }
-
-    Timestamp timestamp;
-    _loKitDocument->pClass->paintTile(_loKitDocument, pixmap.data(), width, height, tilePosX, tilePosY, tileWidth, tileHeight);
-    Log::trace() << "paintTile at [" << tilePosX << ", " << tilePosY
-                 << "] rendered in " << (timestamp.elapsed()/1000.) << " ms" << Log::end;
-
-    const LibreOfficeKitTileMode mode =
-            static_cast<LibreOfficeKitTileMode>(_loKitDocument->pClass->getTileMode(_loKitDocument));
-    if (!Util::encodeBufferToPNG(pixmap.data(), width, height, output, mode))
-    {
-        sendTextFrame("error: cmd=tile kind=failure");
-        return;
-    }
-
-    if (makeSlow)
-        delay();
-
-    sendBinaryFrame(output.data(), output.size());
-}
-
 void ChildProcessSession::sendCombinedTiles(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens)
 {
     int part, pixelWidth, pixelHeight, tileWidth, tileHeight;
diff --git a/loolwsd/ChildProcessSession.hpp b/loolwsd/ChildProcessSession.hpp
index 6f295ab..ec6855e 100644
--- a/loolwsd/ChildProcessSession.hpp
+++ b/loolwsd/ChildProcessSession.hpp
@@ -67,8 +67,6 @@ public:
  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;
diff --git a/loolwsd/DocumentBroker.cpp b/loolwsd/DocumentBroker.cpp
index 0cc1975..a390320 100644
--- a/loolwsd/DocumentBroker.cpp
+++ b/loolwsd/DocumentBroker.cpp
@@ -17,6 +17,27 @@
 #include "LOOLWSD.hpp"
 #include "Storage.hpp"
 #include "TileCache.hpp"
+#include "LOOLProtocol.hpp"
+
+using namespace LOOLProtocol;
+
+void ChildProcess::socketProcessor()
+{
+    IoUtil::SocketProcessor(_ws,
+        [this](const std::vector<char>& payload)
+        {
+            auto docBroker = this->_docBroker.lock();
+            if (docBroker)
+            {
+                return docBroker->handleInput(payload);
+            }
+
+            Log::warn("No DocumentBroker to handle child message: [" + LOOLProtocol::getAbbreviatedMessage(payload) + "].");
+            return true;
+        },
+        []() { },
+        [this]() { return !!this->_stop; });
+}
 
 namespace
 {
@@ -355,6 +376,105 @@ size_t DocumentBroker::removeSession(const std::string& id)
     return _sessions.size();
 }
 
+bool DocumentBroker::handleInput(const std::vector<char>& payload)
+{
+    Log::trace("DocumentBroker got child message: [" + LOOLProtocol::getAbbreviatedMessage(payload) + "].");
+
+    const auto command = LOOLProtocol::getFirstToken(payload);
+    if (command == "tile:")
+    {
+        handleTileResponse(payload);
+    }
+
+    return true;
+}
+
+void DocumentBroker::handleTileRequest(int part, int width, int height, int tilePosX,
+                                       int tilePosY, int tileWidth, int tileHeight,
+                                       const std::shared_ptr<MasterProcessSession>& session)
+{
+    std::unique_lock<std::mutex> lock(_mutex);
+
+    std::unique_ptr<std::fstream> cachedTile = tileCache().lookupTile(part, width, height, tilePosX, tilePosY, tileWidth, tileHeight);
+
+    if (cachedTile)
+    {
+        std::ostringstream oss;
+        oss << "tile: part=" << part
+            << " width=" << width
+            << " height=" << height
+            << " tileposx=" << tilePosX
+            << " tileposy=" << tilePosY
+            << " tilewidth=" << tileWidth
+            << " tileheight=" << tileHeight;
+
+#if ENABLE_DEBUG
+        oss << " renderid=cached";
+#endif
+        oss << "\n";
+        const auto response = oss.str();
+
+        std::vector<char> output;
+        output.reserve(4 * width * height);
+        output.resize(response.size());
+        std::memcpy(output.data(), response.data(), response.size());
+
+        assert(cachedTile->is_open());
+        cachedTile->seekg(0, std::ios_base::end);
+        size_t pos = output.size();
+        std::streamsize size = cachedTile->tellg();
+        output.resize(pos + size);
+        cachedTile->seekg(0, std::ios_base::beg);
+        cachedTile->read(output.data() + pos, size);
+        cachedTile->close();
+
+        session->sendBinaryFrame(output.data(), output.size());
+        return;
+    }
+
+    if (tileCache().isTileBeingRenderedIfSoSubscribe(
+            part, width, height, tilePosX, tilePosY, tileWidth,
+            tileHeight, session))
+        return;
+
+    // Forward to child to render.
+    std::ostringstream oss;
+    oss << "tile part=" << part
+        << " width=" << width
+        << " height=" << height
+        << " tileposx=" << tilePosX
+        << " tileposy=" << tilePosY
+        << " tilewidth=" << tileWidth
+        << " tileheight=" << tileHeight;
+    const std::string request = oss.str();
+
+    _childProcess->getWebSocket()->sendFrame(request.data(), request.size());
+}
+
+void DocumentBroker::handleTileResponse(const std::vector<char>& payload)
+{
+    const std::string firstLine = getFirstLine(payload);
+    Poco::StringTokenizer tokens(firstLine, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
+
+    int part, width, height, tilePosX, tilePosY, tileWidth, tileHeight;
+    if (tokens.count() < 8 ||
+        !getTokenInteger(tokens[1], "part", part) ||
+        !getTokenInteger(tokens[2], "width", width) ||
+        !getTokenInteger(tokens[3], "height", height) ||
+        !getTokenInteger(tokens[4], "tileposx", tilePosX) ||
+        !getTokenInteger(tokens[5], "tileposy", tilePosY) ||
+        !getTokenInteger(tokens[6], "tilewidth", tileWidth) ||
+        !getTokenInteger(tokens[7], "tileheight", tileHeight))
+        assert(false);
+
+    const auto buffer = payload.data();
+    const auto length = payload.size();
+    assert(firstLine.size() < static_cast<std::string::size_type>(length));
+    tileCache().saveTile(part, width, height, tilePosX, tilePosY, tileWidth, tileHeight, buffer + firstLine.size() + 1, length - firstLine.size() - 1);
+
+    tileCache().notifyAndRemoveSubscribers(part, width, height, tilePosX, tilePosY, tileWidth, tileHeight);
+}
+
 bool DocumentBroker::canDestroy()
 {
     std::unique_lock<std::mutex> lock(_mutex);
diff --git a/loolwsd/DocumentBroker.hpp b/loolwsd/DocumentBroker.hpp
index 49b5d32..bf8df26 100644
--- a/loolwsd/DocumentBroker.hpp
+++ b/loolwsd/DocumentBroker.hpp
@@ -197,6 +197,12 @@ public:
     /// Removes a session by ID. Returns the new number of sessions.
     size_t removeSession(const std::string& id);
 
+    void handleTileRequest(int part, int width, int height, int tilePosX,
+                           int tilePosY, int tileWidth, int tileHeight,
+                           const std::shared_ptr<MasterProcessSession>& session);
+
+    void handleTileResponse(const std::vector<char>& payload);
+
     // Called when the last view is going out.
     bool canDestroy();
     bool isMarkedToDestroy() const { return _markToDestroy; }
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index a0b32cd..a5269a9 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -574,6 +574,93 @@ public:
         Log::info("setDocumentPassword returned");
     }
 
+    void renderTile(StringTokenizer& tokens, const std::shared_ptr<Poco::Net::WebSocket>& ws)
+    {
+        int part, width, height, tilePosX, tilePosY, tileWidth, tileHeight;
+
+        if (tokens.count() < 8 ||
+            !getTokenInteger(tokens[1], "part", part) ||
+            !getTokenInteger(tokens[2], "width", width) ||
+            !getTokenInteger(tokens[3], "height", height) ||
+            !getTokenInteger(tokens[4], "tileposx", tilePosX) ||
+            !getTokenInteger(tokens[5], "tileposy", tilePosY) ||
+            !getTokenInteger(tokens[6], "tilewidth", tileWidth) ||
+            !getTokenInteger(tokens[7], "tileheight", tileHeight))
+        {
+            //FIXME: Return error.
+            //sendTextFrame("error: cmd=tile kind=syntax");
+            return;
+        }
+
+        if (part < 0 ||
+            width <= 0 ||
+            height <= 0 ||
+            tilePosX < 0 ||
+            tilePosY < 0 ||
+            tileWidth <= 0 ||
+            tileHeight <= 0)
+        {
+            //FIXME: Return error.
+            //sendTextFrame("error: cmd=tile kind=invalid");
+            return;
+        }
+
+        std::unique_lock<std::recursive_mutex> lock(ChildProcessSession::getLock());
+
+        if (_loKitDocument == nullptr)
+        {
+            Log::error("Tile rendering requested before loading document.");
+            return;
+        }
+
+        //TODO: Support multiviews.
+        //if (_multiView)
+            //_loKitDocument->pClass->setView(_loKitDocument, _viewId);
+
+        std::string response = "tile: " + Poco::cat(std::string(" "), tokens.begin() + 1, tokens.end());
+
+#if ENABLE_DEBUG
+        response += " renderid=" + Util::UniqueId();
+#endif
+        response += "\n";
+
+        std::vector<char> output;
+        output.reserve(response.size() + (4 * width * height));
+        output.resize(response.size());
+        std::memcpy(output.data(), response.data(), response.size());
+
+        std::vector<unsigned char> pixmap;
+        pixmap.resize(4 * width * height);
+
+        if (part != _loKitDocument->pClass->getPart(_loKitDocument))
+        {
+            _loKitDocument->pClass->setPart(_loKitDocument, part);
+        }
+
+        Timestamp timestamp;
+        _loKitDocument->pClass->paintTile(_loKitDocument, pixmap.data(), width, height, tilePosX, tilePosY, tileWidth, tileHeight);
+        Log::trace() << "paintTile at [" << tilePosX << ", " << tilePosY
+                     << "] rendered in " << (timestamp.elapsed()/1000.) << " ms" << Log::end;
+
+        const LibreOfficeKitTileMode mode =
+                static_cast<LibreOfficeKitTileMode>(_loKitDocument->pClass->getTileMode(_loKitDocument));
+        if (!Util::encodeBufferToPNG(pixmap.data(), width, height, output, mode))
+        {
+            //FIXME: Return error.
+            //sendTextFrame("error: cmd=tile kind=failure");
+            return;
+        }
+
+        const auto length = output.size();
+        if (length > SMALL_MESSAGE_SIZE)
+        {
+            const std::string nextmessage = "nextmessage: size=" + std::to_string(length);
+            ws->sendFrame(nextmessage.data(), nextmessage.size());
+        }
+
+        ws->sendFrame(output.data(), length, WebSocket::FRAME_BINARY);
+    }
+
 private:
 
     static void ViewCallback(int , const char* , void* )
@@ -1037,6 +1124,13 @@ void lokit_main(const std::string& childRoot,
                             Log::debug("CreateSession failed.");
                         }
                     }
+                    else if (tokens[0] == "tile")
+                    {
+                        if (document)
+                        {
+                            document->renderTile(tokens, ws);
+                        }
+                    }
                     else if (document && document->canDiscard())
                     {
                         TerminationFlag = true;
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index 8d07645..28c7ada 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -181,22 +181,7 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length)
         {
             if (tokens[0] == "tile:")
             {
-                int part, width, height, tilePosX, tilePosY, tileWidth, tileHeight;
-                if (tokens.count() < 8 ||
-                    !getTokenInteger(tokens[1], "part", part) ||
-                    !getTokenInteger(tokens[2], "width", width) ||
-                    !getTokenInteger(tokens[3], "height", height) ||
-                    !getTokenInteger(tokens[4], "tileposx", tilePosX) ||
-                    !getTokenInteger(tokens[5], "tileposy", tilePosY) ||
-                    !getTokenInteger(tokens[6], "tilewidth", tileWidth) ||
-                    !getTokenInteger(tokens[7], "tileheight", tileHeight))
-                    assert(false);
-
-                assert(_kind == Kind::ToPrisoner);
-                assert(firstLine.size() < static_cast<std::string::size_type>(length));
-                _docBroker->tileCache().saveTile(part, width, height, tilePosX, tilePosY, tileWidth, tileHeight, buffer + firstLine.size() + 1, length - firstLine.size() - 1);
-
-                _docBroker->tileCache().notifyAndRemoveSubscribers(part, width, height, tilePosX, tilePosY, tileWidth, tileHeight, this);
+                assert(!"Tile traffic should go through the DocumentBroker-LoKit WS.");
             }
             else if (tokens[0] == "status:")
             {
@@ -504,9 +489,8 @@ void MasterProcessSession::sendFontRendering(const char *buffer, int length, Str
     forwardToPeer(buffer, length);
 }
 
-void MasterProcessSession::sendTile(const char *buffer, int length, StringTokenizer& tokens)
+void MasterProcessSession::sendTile(const char * /*buffer*/, int /*length*/, StringTokenizer& tokens)
 {
-
     int part, width, height, tilePosX, tilePosY, tileWidth, tileHeight;
     if (tokens.count() < 8 ||
         !getTokenInteger(tokens[1], "part", part) ||
@@ -533,44 +517,8 @@ void MasterProcessSession::sendTile(const char *buffer, int length, StringTokeni
         return;
     }
 
-    std::unique_ptr<std::fstream> cachedTile = _docBroker->tileCache().lookupTile(part, width, height, tilePosX, tilePosY, tileWidth, tileHeight);
-
-    if (cachedTile)
-    {
-        std::string response = "tile: " + Poco::cat(std::string(" "), tokens.begin() + 1, tokens.end());
-
-#if ENABLE_DEBUG
-        response += " renderid=cached";
-#endif
-        response += "\n";
-
-        std::vector<char> output;
-        output.reserve(4 * width * height);
-        output.resize(response.size());
-        std::memcpy(output.data(), response.data(), response.size());
-
-        assert(cachedTile->is_open());
-        cachedTile->seekg(0, std::ios_base::end);
-        size_t pos = output.size();
-        std::streamsize size = cachedTile->tellg();
-        output.resize(pos + size);
-        cachedTile->seekg(0, std::ios_base::beg);
-        cachedTile->read(output.data() + pos, size);
-        cachedTile->close();
-
-        sendBinaryFrame(output.data(), output.size());
-
-        return;
-    }
-
-    if (_docBroker->tileCache().isTileBeingRenderedIfSoSubscribe(
-            part, width, height, tilePosX, tilePosY, tileWidth,
-            tileHeight, shared_from_this()))
-        return;
-
-    if (_peer.expired())
-        dispatchChild();
-    forwardToPeer(buffer, length);
+    _docBroker->handleTileRequest(part, width, height, tilePosX, tilePosY,
+                                  tileWidth, tileHeight, shared_from_this());
 }
 
 void MasterProcessSession::sendCombinedTiles(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens)
@@ -614,8 +562,6 @@ void MasterProcessSession::sendCombinedTiles(const char* /*buffer*/, int /*lengt
         return;
     }
 
-    std::string forwardTileX;
-    std::string forwardTileY;
     for (size_t i = 0; i < numberOfPositions; ++i)
     {
         int x = 0;
@@ -632,81 +578,9 @@ void MasterProcessSession::sendCombinedTiles(const char* /*buffer*/, int /*lengt
             return;
         }
 
-        std::unique_ptr<std::fstream> cachedTile = _docBroker->tileCache().lookupTile(part, pixelWidth, pixelHeight, x, y, tileWidth, tileHeight);
-
-        if (cachedTile)
-        {
-            assert(cachedTile->is_open());
-            std::ostringstream oss;
-            oss << "tile: part=" << part
-                << " width=" << pixelWidth
-                << " height=" << pixelHeight
-                << " tileposx=" << x
-                << " tileposy=" << y
-                << " tilewidth=" << tileWidth
-                << " tileheight=" << tileHeight;
-
-            if (!reqTimestamp.empty())
-            {
-                oss << " timestamp=" << reqTimestamp;
-            }
-
-#if ENABLE_DEBUG
-            oss << " renderid=cached";
-#endif
-
-            oss << "\n";
-            const std::string response = oss.str();
-
-            std::vector<char> output;
-            output.reserve(4 * pixelWidth * pixelHeight);
-            output.resize(response.size());
-            std::memcpy(output.data(), response.data(), response.size());
-            cachedTile->seekg(0, std::ios_base::end);
-            const size_t pos = output.size();
-            const std::streamsize size = cachedTile->tellg();
-            output.resize(pos + size);
-            cachedTile->seekg(0, std::ios_base::beg);
-            cachedTile->read(output.data() + pos, size);
-            cachedTile->close();
-
-            sendBinaryFrame(output.data(), output.size());
-        }
-        else
-        {
-            if (!_docBroker->tileCache().isTileBeingRenderedIfSoSubscribe(
-                    part, pixelWidth, pixelHeight, x, y, tileWidth,
-                    tileHeight, shared_from_this()))
-            {
-                if (!forwardTileX.empty())
-                    forwardTileX += ",";
-                forwardTileX += std::to_string(x);
-
-                if (!forwardTileY.empty())
-                    forwardTileY += ",";
-                forwardTileY += std::to_string(y);
-            }
-        }
+        _docBroker->handleTileRequest(part, pixelWidth, pixelHeight, x, y,
+                                      tileWidth, tileHeight, shared_from_this());
     }
-
-    if (forwardTileX.empty() && forwardTileY.empty())
-        return;
-
-    if (_peer.expired())
-        dispatchChild();
-
-    std::string forward = "tilecombine part=" + std::to_string(part) +
-                          " width=" + std::to_string(pixelWidth) +
-                          " height=" + std::to_string(pixelHeight) +
-                          " tileposx=" + forwardTileX +
-                          " tileposy=" + forwardTileY +
-                          " tilewidth=" + std::to_string(tileWidth) +
-                          " tileheight=" + std::to_string(tileHeight);
-
-    if (!reqTimestamp.empty())
-        forward += " timestamp=" + reqTimestamp;
-
-    forwardToPeer(forward.c_str(), forward.size());
 }
 
 void MasterProcessSession::dispatchChild()
diff --git a/loolwsd/TileCache.cpp b/loolwsd/TileCache.cpp
index 856c684..edd88a7 100644
--- a/loolwsd/TileCache.cpp
+++ b/loolwsd/TileCache.cpp
@@ -330,7 +330,7 @@ void TileCache::saveLastModified(const Timestamp& timestamp)
     modTimeFile.close();
 }
 
-void TileCache::notifyAndRemoveSubscribers(int part, int width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight, MasterProcessSession *emitter)
+void TileCache::notifyAndRemoveSubscribers(int part, int width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight)
 {
     std::unique_lock<std::mutex> lock(_tilesBeingRenderedMutex);
 
@@ -345,12 +345,7 @@ void TileCache::notifyAndRemoveSubscribers(int part, int width, int height, int
         auto subscriber = i.lock();
         if (subscriber)
         {
-            if (subscriber.get() == emitter)
-            {
-                Log::error("Refusing to queue new tile message for ourselves");
-                continue;
-            }
-
+            //FIXME: This is inefficient; should just send directly to each client (although that is risky as well!
             std::shared_ptr<BasicTileQueue> queue;
             queue = subscriber->getQueue();
             // Re-emit the tile command in the other thread(s) to re-check and hit
@@ -404,7 +399,9 @@ bool TileCache::isTileBeingRenderedIfSoSubscribe(int part, int width, int height
 
         assert(_tilesBeingRendered.find(cachedName) == _tilesBeingRendered.end());
 
-        _tilesBeingRendered[cachedName] = std::make_shared<TileBeingRendered>();
+        auto tileBeingRendered = std::make_shared<TileBeingRendered>();
+        tileBeingRendered->_subscribers.push_back(subscriber);
+        _tilesBeingRendered[cachedName] = tileBeingRendered;
 
         return false;
     }
diff --git a/loolwsd/TileCache.hpp b/loolwsd/TileCache.hpp
index 1cf2cbe..5f40eb4 100644
--- a/loolwsd/TileCache.hpp
+++ b/loolwsd/TileCache.hpp
@@ -45,7 +45,7 @@ public:
 
     void saveTile(int part, int width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight, const char *data, size_t size);
 
-    void notifyAndRemoveSubscribers(int part, int width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight, MasterProcessSession *emitter);
+    void notifyAndRemoveSubscribers(int part, int width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight);
 
     std::string getTextFile(const std::string& fileName);
 


More information about the Libreoffice-commits mailing list