[Libreoffice-commits] online.git: loolwsd/LOOLKit.cpp loolwsd/MessageQueue.cpp

Ashod Nakashian ashod.nakashian at collabora.co.uk
Thu Sep 1 20:47:28 UTC 2016


 loolwsd/LOOLKit.cpp      |   59 +++++++++++++++++++++++++++++++++++++++++++----
 loolwsd/MessageQueue.cpp |   43 ++++++++++++++++++++++------------
 2 files changed, 82 insertions(+), 20 deletions(-)

New commits:
commit 2663f9b63f986e97d092244ba793b56b347101cd
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Thu Sep 1 16:45:04 2016 -0400

    loolwsd: replace old tile requests with more recent ones
    
    A new queue with own thread now processes tile requests
    so we have a chance to cull backlogged tile requests
    that have since been invalidated.
    
    This reduces load on the server significantly, especially
    with multiple view at different zoom levels, and very fast
    typing.
    
    Change-Id: I6599939cd363dc71c30187f40d542aa37260dc56
    Reviewed-on: https://gerrit.libreoffice.org/28607
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index 0613aa7..b62754d 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -27,6 +27,7 @@
 #include <iostream>
 #include <memory>
 #include <sstream>
+#include <thread>
 
 #define LOK_USE_UNSTABLE_API
 #include <LibreOfficeKit/LibreOfficeKitInit.h>
@@ -396,18 +397,23 @@ public:
     Document(const std::shared_ptr<lok::Office>& loKit,
              const std::string& jailId,
              const std::string& docKey,
-             const std::string& url)
+             const std::string& url,
+             std::shared_ptr<TileQueue> queue,
+             const std::shared_ptr<WebSocket>& ws)
       : _multiView(std::getenv("LOK_VIEW_CALLBACK")),
         _loKit(loKit),
         _jailId(jailId),
         _docKey(docKey),
         _url(url),
+        _queue(queue),
+        _ws(ws),
         _docPassword(""),
         _haveDocPassword(false),
         _isDocPasswordProtected(false),
         _docPasswordType(PasswordType::ToView),
         _stop(false),
         _isLoading(0),
+        _tilesThread(tilesThread, this),
         _clientViews(0)
     {
         Log::info("Document ctor for url [" + _url + "] on child [" + _jailId +
@@ -1188,6 +1194,44 @@ private:
         Log::debug("Thread finished.");
     }
 
+    static void tilesThread(Document* pThis)
+    {
+        Util::setThreadName("tile_renderer");
+
+        Log::debug("Thread started.");
+
+        try
+        {
+            while (true)
+            {
+                const auto input = pThis->_queue->get();
+                const std::string message(input.data(), input.size());
+                StringTokenizer tokens(message, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+
+                if (tokens[0] == "eof")
+                {
+                    Log::info("Received EOF. Finishing.");
+                    break;
+                }
+
+                if (tokens[0] == "tile")
+                {
+                    pThis->renderTile(tokens, pThis->_ws);
+                }
+                else if (tokens[0] == "tilecombine")
+                {
+                    pThis->renderCombinedTiles(tokens, pThis->_ws);
+                }
+            }
+        }
+        catch (const std::exception& exc)
+        {
+            Log::error(std::string("QueueHandler::run: Exception: ") + exc.what());
+        }
+
+        Log::debug("Thread finished.");
+    }
+
 private:
 
     const bool _multiView;
@@ -1199,6 +1243,8 @@ private:
     std::string _renderOpts;
 
     std::shared_ptr<lok::Document> _loKitDocument;
+    std::shared_ptr<TileQueue> _queue;
+    std::shared_ptr<WebSocket> _ws;
 
     // Document password provided
     std::string _docPassword;
@@ -1216,6 +1262,7 @@ private:
     std::map<int, std::unique_ptr<CallbackDescriptor>> _viewIdToCallbackDescr;
     std::map<unsigned, std::shared_ptr<Connection>> _connections;
     Poco::Thread _callbackThread;
+    std::thread _tilesThread;
     Poco::NotificationQueue _callbackQueue;
     std::atomic_size_t _clientViews;
 };
@@ -1420,9 +1467,11 @@ void lokit_main(const std::string& childRoot,
         auto ws = std::make_shared<WebSocket>(cs, request, response);
         ws->setReceiveTimeout(0);
 
+        auto queue = std::make_shared<TileQueue>();
+
         const std::string socketName = "ChildControllerWS";
         IoUtil::SocketProcessor(ws,
-                [&socketName, &ws, &document, &loKit](const std::vector<char>& data)
+                [&socketName, &ws, &document, &loKit, &queue](const std::vector<char>& data)
                 {
                     std::string message(data.data(), data.size());
 
@@ -1449,7 +1498,7 @@ void lokit_main(const std::string& childRoot,
 
                         if (!document)
                         {
-                            document = std::make_shared<Document>(loKit, jailId, docKey, url);
+                            document = std::make_shared<Document>(loKit, jailId, docKey, url, queue, ws);
                         }
 
                         // Validate and create session.
@@ -1463,7 +1512,7 @@ void lokit_main(const std::string& childRoot,
                     {
                         if (document)
                         {
-                            document->renderTile(tokens, ws);
+                            queue->put(message);
                         }
                         else
                         {
@@ -1474,7 +1523,7 @@ void lokit_main(const std::string& childRoot,
                     {
                         if (document)
                         {
-                            document->renderCombinedTiles(tokens, ws);
+                            queue->put(message);
                         }
                         else
                         {
diff --git a/loolwsd/MessageQueue.cpp b/loolwsd/MessageQueue.cpp
index 642c7c0..b4a9c20 100644
--- a/loolwsd/MessageQueue.cpp
+++ b/loolwsd/MessageQueue.cpp
@@ -11,6 +11,8 @@
 
 #include <algorithm>
 
+#include <Log.hpp>
+
 MessageQueue::~MessageQueue()
 {
     clear();
@@ -93,24 +95,35 @@ void BasicTileQueue::put_impl(const Payload& value)
 
 void TileQueue::put_impl(const Payload& value)
 {
-    const auto msg = std::string(&value[0], value.size());
-    if (msg.compare(0, 5, "tile ") == 0)
+    if (!_queue.empty())
     {
-        // TODO: implement a real re-ordering here, so that the tiles closest to
-        // the cursor are returned first.
-        // * we will want to put just a general "tile" message to the queue
-        // * add a std::set that handles the tiles
-        // * change the get_impl() to decide which tile is the correct one to
-        //   be returned
-        // * we will also need to be informed about the position of the cursor
-        //   so that get_impl() returns optimal results
-        //
-        // For now: just don't put duplicates into the queue
-        for (const auto& it : _queue)
+        const auto msg = std::string(value.data(), value.size());
+        if (msg.compare(0, 4, "tile") == 0 || msg.compare(0, 10, "tilecombine") == 0)
         {
-            if (value == it)
+            const auto newMsg = msg.substr(0, msg.find(" ver"));
+
+            // TODO: implement a real re-ordering here, so that the tiles closest to
+            // the cursor are returned first.
+            // * we will want to put just a general "tile" message to the queue
+            // * add a std::set that handles the tiles
+            // * change the get_impl() to decide which tile is the correct one to
+            //   be returned
+            // * we will also need to be informed about the position of the cursor
+            //   so that get_impl() returns optimal results
+            //
+            // For now: just don't put duplicates into the queue
+            for (size_t i = 0; i < _queue.size(); ++i)
             {
-                return;
+                auto& it = _queue[i];
+                const std::string old(it.data(), it.size());
+                const auto oldMsg = old.substr(0, old.find(" ver"));
+                Log::error(std::to_string(i) + ": " + oldMsg);
+                if (newMsg == oldMsg)
+                {
+                    Log::trace("Replacing duplicate tile: " + oldMsg + " -> " + newMsg);
+                    _queue[i] = value;
+                    return;
+                }
             }
         }
     }


More information about the Libreoffice-commits mailing list