loolwsd/MasterProcessSession.cpp |   27 +++++++++++++++++++++
 loolwsd/MasterProcessSession.hpp |    1 
 loolwsd/TileCache.cpp            |   50 +++++++++++++++++++++++++++++++++++++++
 loolwsd/TileCache.hpp            |   27 ++++++++++++++++++++-
 4 files changed, 103 insertions(+), 2 deletions(-)

New commits:
commit d5bb373447ea57029b6be846e93a15e99c7045fc
Author: Tor Lillqvist <t...@collabora.com>
Date:   Fri Apr 15 18:24:00 2016 +0300

    Improve efficiency when multiple clients of same doc ask for same tile(s)
    
    Keep track of tiles being rendered in TileCache, and when asked to
    render the same tile as is already being rendered, just "subscribe" to
    the existing ongoing rendering. When a tile has been rendered and is
    being sent out to clients, check if there are "subscriptions" and send
    it to them, too.
    
    One problem is that if the client that caused a tile rendering to be
    initiated goes away before the rendering has completed, it will never
    complete, and the subscribers are left without the tile.
    
    Change-Id: Icca237876a0f466c29eb5bf60ffd4da3d9d68600
    Reviewed-on: https://gerrit.libreoffice.org/24228
    Reviewed-by: Ashod Nakashian <ashnak...@gmail.com>
    Tested-by: Ashod Nakashian <ashnak...@gmail.com>

diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index c2d4856..ccdc6b0 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -181,6 +181,22 @@ bool MasterProcessSession::_handleInput(const char 
*buffer, int length)
 
                 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);
+                auto lock = _docBroker->tileCache().getTilesBeingRenderdLock();
+                std::shared_ptr<TileBeingRendered> tileBeingRendered = 
_docBroker->tileCache().findTileBeingRendered(part, width, height, tilePosX, 
tilePosY, tileWidth, tileHeight);
+                if (tileBeingRendered)
+                {
+                    for (auto i: tileBeingRendered->getSubscribers())
+                    {
+                        auto subscriber = i.lock();
+                        if (subscriber)
+                        {
+                            Log::debug("Sending tile also to subscriber " + 
subscriber->getName());
+                            subscriber->sendBinaryFrame(buffer, length);
+                        }
+                    }
+                    _docBroker->tileCache().forgetTileBeingRendered(part, 
width, height, tilePosX, tilePosY, tileWidth, tileHeight);
+                }
+                lock.unlock();
             }
             else if (tokens[0] == "status:")
             {
@@ -569,6 +585,17 @@ void MasterProcessSession::sendTile(const char *buffer, 
int length, StringTokeni
         return;
     }
 
+    auto lock = _docBroker->tileCache().getTilesBeingRenderdLock();
+    std::shared_ptr<TileBeingRendered> tileBeingRendered = 
_docBroker->tileCache().findTileBeingRendered(part, width, height, tilePosX, 
tilePosY, tileWidth, tileHeight);
+    if (tileBeingRendered)
+    {
+        Log::debug("Tile is already being rendered, subscribing");
+        tileBeingRendered->subscribe(shared_from_this());
+        return;
+    }
+    _docBroker->tileCache().rememberTileAsBeingRendered(part, width, height, 
tilePosX, tilePosY, tileWidth, tileHeight);
+    lock.unlock();
+
     if (_peer.expired())
         dispatchChild();
     forwardToPeer(buffer, length);
diff --git a/loolwsd/MasterProcessSession.hpp b/loolwsd/MasterProcessSession.hpp
index c38b20f..beffa34 100644
--- a/loolwsd/MasterProcessSession.hpp
+++ b/loolwsd/MasterProcessSession.hpp
@@ -16,7 +16,6 @@
 
 #include "LOOLSession.hpp"
 #include "MessageQueue.hpp"
-#include "TileCache.hpp"
 
 class DocumentBroker;
 
diff --git a/loolwsd/TileCache.cpp b/loolwsd/TileCache.cpp
index 26f986a..409f316 100644
--- a/loolwsd/TileCache.cpp
+++ b/loolwsd/TileCache.cpp
@@ -18,6 +18,7 @@
 #include <mutex>
 #include <sstream>
 #include <string>
+#include <vector>
 
 #include <Poco/DigestEngine.h>
 #include <Poco/DirectoryIterator.h>
@@ -43,6 +44,16 @@ using Poco::URI;
 
 using namespace LOOLProtocol;
 
+void TileBeingRendered::subscribe(std::weak_ptr<MasterProcessSession> session)
+{
+    _subscribers.push_back(session);
+}
+
+std::vector<std::weak_ptr<MasterProcessSession>> 
TileBeingRendered::getSubscribers()
+{
+    return _subscribers;
+}
+
 TileCache::TileCache(const std::string& docURL,
                      const Timestamp& modifiedTime,
                      const std::string& rootCacheDir) :
@@ -78,6 +89,45 @@ TileCache::TileCache(const std::string& docURL,
 TileCache::~TileCache()
 {
     Log::info("~TileCache dtor for uri [" + _docURL + "].");
+#if 0
+    auto lock = getTilesBeingRenderdLock();
+    _tilesBeingRendered.clear();
+#endif
+}
+
+std::unique_lock<std::mutex> TileCache::getTilesBeingRenderdLock()
+{
+    return std::unique_lock<std::mutex>(_tilesBeingRenderedMutex);
+}
+
+void TileCache::rememberTileAsBeingRendered(int part, int width, int height, 
int tilePosX, int tilePosY, int tileWidth, int tileHeight)
+{
+    const std::string cachedName = cacheFileName(part, width, height, 
tilePosX, tilePosY, tileWidth, tileHeight);
+
+    assert(_tilesBeingRendered.find(cachedName) == _tilesBeingRendered.end());
+
+    _tilesBeingRendered[cachedName] = std::make_shared<TileBeingRendered>();
+}
+
+std::shared_ptr<TileBeingRendered> TileCache::findTileBeingRendered(int part, 
int width, int height, int tilePosX, int tilePosY, int tileWidth, int 
tileHeight)
+{
+    const std::string cachedName = cacheFileName(part, width, height, 
tilePosX, tilePosY, tileWidth, tileHeight);
+
+    auto tile = _tilesBeingRendered.find(cachedName);
+
+    if (tile == _tilesBeingRendered.end())
+        return nullptr;
+
+    return tile->second;
+}
+
+void TileCache::forgetTileBeingRendered(int part, int width, int height, int 
tilePosX, int tilePosY, int tileWidth, int tileHeight)
+{
+    const std::string cachedName = cacheFileName(part, width, height, 
tilePosX, tilePosY, tileWidth, tileHeight);
+
+    assert(_tilesBeingRendered.find(cachedName) != _tilesBeingRendered.end());
+
+    _tilesBeingRendered.erase(cachedName);
 }
 
 std::unique_ptr<std::fstream> TileCache::lookupTile(int part, int width, int 
height, int tilePosX, int tilePosY, int tileWidth, int tileHeight)
diff --git a/loolwsd/TileCache.hpp b/loolwsd/TileCache.hpp
index 163ab7b..54a462e 100644
--- a/loolwsd/TileCache.hpp
+++ b/loolwsd/TileCache.hpp
@@ -14,6 +14,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <vector>
 
 #include <Poco/Timestamp.h>
 
@@ -26,6 +27,18 @@ The cache consists of 2 cache directories:
 
 The editing cache is cleared on startup, and copied to the persistent on each 
save.
 */
+
+class MasterProcessSession;
+
+class TileBeingRendered
+{
+    std::vector<std::weak_ptr<MasterProcessSession>> _subscribers;
+
+public:
+    void subscribe(std::weak_ptr<MasterProcessSession> session);
+    std::vector<std::weak_ptr<MasterProcessSession>> getSubscribers();
+};
+
 class TileCache
 {
 public:
@@ -37,7 +50,16 @@ public:
 
     TileCache(const TileCache&) = delete;
 
+    std::unique_lock<std::mutex> getTilesBeingRenderdLock();
+
+    void rememberTileAsBeingRendered(int part, int width, int height, int 
tilePosX, int tilePosY, int tileWidth, int tileHeight);
+
+    std::shared_ptr<TileBeingRendered> findTileBeingRendered(int part, int 
width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight);
+
+    void forgetTileBeingRendered(int part, int width, int height, int 
tilePosX, int tilePosY, int tileWidth, int tileHeight);
+
     std::unique_ptr<std::fstream> lookupTile(int part, int width, int height, 
int tilePosX, int tilePosY, int tileWidth, int tileHeight);
+
     void saveTile(int part, int width, int height, int tilePosX, int tilePosY, 
int tileWidth, int tileHeight, const char *data, size_t size);
     std::string getTextFile(std::string fileName);
 
@@ -80,7 +102,6 @@ private:
     /// Store the timestamp to modtime.txt.
     void saveLastModified(const Poco::Timestamp& timestamp);
 
-private:
     const std::string _docURL;
     const std::string _rootCacheDir;
     const std::string _persCacheDir;
@@ -96,6 +117,10 @@ private:
     std::set<std::string> _toBeRemoved;
 
     std::mutex _cacheMutex;
+
+    std::mutex _tilesBeingRenderedMutex;
+
+    std::map<std::string, std::shared_ptr<TileBeingRendered>> 
_tilesBeingRendered;
 };
 
 #endif
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to