[Libreoffice-commits] online.git: test/TileCacheTests.cpp wsd/ClientSession.cpp wsd/DocumentBroker.cpp wsd/TileCache.cpp wsd/TileCache.hpp wsd/TileDesc.hpp

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Tue Mar 5 05:59:13 UTC 2019


 test/TileCacheTests.cpp |   11 ++
 wsd/ClientSession.cpp   |   14 +--
 wsd/DocumentBroker.cpp  |    1 
 wsd/TileCache.cpp       |  208 +++++++++++++++++++++++++-----------------------
 wsd/TileCache.hpp       |  106 +++++++++++++++++++-----
 wsd/TileDesc.hpp        |    2 
 6 files changed, 212 insertions(+), 130 deletions(-)

New commits:
commit 6634d3b3e9c6ac8aac37a344fc2de4f543f52170
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Fri Feb 15 21:55:47 2019 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Tue Mar 5 06:58:50 2019 +0100

    TileCache: key almost everything on TileDesc instead of string names.
    
    Saves lots of string construction and storage, simplifies lots of code.
    
    Store the more exotic font-caching bits etc. in a separate store: we
    should also pre-render these really and share them.
    
    Change-Id: Icaeff8fd72f52d7215c06a687b1e39cfb7631503

diff --git a/test/TileCacheTests.cpp b/test/TileCacheTests.cpp
index c02989dee..d6577f50a 100644
--- a/test/TileCacheTests.cpp
+++ b/test/TileCacheTests.cpp
@@ -57,6 +57,7 @@ class TileCacheTests : public CPPUNIT_NS::TestFixture
 
     CPPUNIT_TEST_SUITE(TileCacheTests);
 
+    CPPUNIT_TEST(testDesc);
     CPPUNIT_TEST(testSimple);
     CPPUNIT_TEST(testSimpleCombine);
     CPPUNIT_TEST(testCancelTiles);
@@ -91,6 +92,7 @@ class TileCacheTests : public CPPUNIT_NS::TestFixture
 
     CPPUNIT_TEST_SUITE_END();
 
+    void testDesc();
     void testSimple();
     void testSimpleCombine();
     void testCancelTiles();
@@ -173,6 +175,15 @@ public:
     }
 };
 
+void TileCacheTests::testDesc()
+{
+    TileCacheDesc descA = TileDesc(0, 256, 256, 0, 0, 3200, 3200, /* ignored in cache */ 0, 1234, 1, true);
+    TileCacheDesc descB = TileDesc(0, 256, 256, 0, 0, 3200, 3200, /* ignored in cache */ 1, 1235, 2, false);
+
+    CPPUNIT_ASSERT_MESSAGE("versions do match", descA.getVersion() != descB.getVersion());
+    CPPUNIT_ASSERT_MESSAGE("Compare includes fields it should not", descA == descB);
+}
+
 void TileCacheTests::testSimple()
 {
     if (isStandalone())
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index c3d5b9a83..6b61765ae 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -480,15 +480,11 @@ bool ClientSession::getCommandValues(const char *buffer, int length, const std::
 {
     std::string command;
     if (tokens.size() != 2 || !getTokenString(tokens[1], "command", command))
-    {
         return sendTextFrame("error: cmd=commandvalues kind=syntax");
-    }
 
     std::string cmdValues;
-    if (docBroker->tileCache().getTextFile("cmdValues" + command + ".txt", cmdValues))
-    {
+    if (docBroker->tileCache().getTextStream(TileCache::StreamType::CmdValues, command, cmdValues))
         return sendTextFrame(cmdValues);
-    }
 
     return forwardToChild(std::string(buffer, length), docBroker);
 }
@@ -505,8 +501,7 @@ bool ClientSession::sendFontRendering(const char *buffer, int length, const std:
 
     getTokenString(tokens[2], "char", text);
 
-
-    TileCache::Tile cachedTile = docBroker->tileCache().lookupCachedTile(font+text, "font");
+    TileCache::Tile cachedTile = docBroker->tileCache().lookupCachedStream(TileCache::StreamType::Font, font+text);
     if (cachedTile)
     {
         const std::string response = "renderfont: " + Poco::cat(std::string(" "), tokens.begin() + 1, tokens.end()) + "\n";
@@ -951,7 +946,7 @@ bool ClientSession::handleKitToClientMessage(const char* buffer, const int lengt
                     commandName == ".uno:StyleApply")
                 {
                     // other commands should not be cached
-                    docBroker->tileCache().saveTextFile(stringMsg, "cmdValues" + commandName + ".txt");
+                    docBroker->tileCache().saveTextStream(TileCache::StreamType::CmdValues, stringMsg, commandName);
                 }
             }
         }
@@ -1006,7 +1001,8 @@ bool ClientSession::handleKitToClientMessage(const char* buffer, const int lengt
 
             getTokenString(tokens[2], "char", text);
             assert(firstLine.size() < static_cast<std::string::size_type>(length));
-            docBroker->tileCache().saveRendering(font+text, "font", buffer + firstLine.size() + 1, length - firstLine.size() - 1);
+            docBroker->tileCache().saveStream(TileCache::StreamType::Font, font+text,
+                                              buffer + firstLine.size() + 1, length - firstLine.size() - 1);
             return forwardToClient(payload);
         }
     }
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 888500de8..3194d4f58 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -1645,7 +1645,6 @@ void DocumentBroker::setModified(const bool value)
     }
 
     _storage->setUserModified(value);
-    _tileCache->setUnsavedChanges(value);
 }
 
 bool DocumentBroker::isInitialSettingSet(const std::string& name) const
diff --git a/wsd/TileCache.cpp b/wsd/TileCache.cpp
index 6ca40c9f9..3b9fb9d41 100644
--- a/wsd/TileCache.cpp
+++ b/wsd/TileCache.cpp
@@ -67,6 +67,8 @@ TileCache::~TileCache()
 void TileCache::clear()
 {
     _cache.clear();
+    for (auto i : _streamCache)
+        i.clear();
     LOG_INF("Completely cleared tile cache for: " << _docURL);
 }
 
@@ -75,15 +77,13 @@ void TileCache::clear()
 /// rendering latency.
 struct TileCache::TileBeingRendered
 {
-    TileBeingRendered(const std::string& cachedName, const TileDesc& tile)
+    TileBeingRendered(const TileDesc& tile)
      : _startTime(std::chrono::steady_clock::now()),
-       _tile(tile),
-       _cachedName(cachedName)
+       _tile(tile)
     {
     }
 
     const TileDesc& getTile() const { return _tile; }
-    const std::string& getCacheName() const { return _cachedName; }
     int getVersion() const { return _tile.getVersion(); }
     void setVersion(int version) { _tile.setVersion(version); }
 
@@ -95,7 +95,6 @@ private:
     std::vector<std::weak_ptr<ClientSession>> _subscribers;
     std::chrono::steady_clock::time_point _startTime;
     TileDesc _tile;
-    std::string _cachedName;
 };
 
 size_t TileCache::countTilesBeingRenderedForSession(const std::shared_ptr<ClientSession>& session)
@@ -111,13 +110,16 @@ size_t TileCache::countTilesBeingRenderedForSession(const std::shared_ptr<Client
     return count;
 }
 
-std::shared_ptr<TileCache::TileBeingRendered> TileCache::findTileBeingRendered(const TileDesc& tileDesc)
+bool TileCache::hasTileBeingRendered(const std::shared_ptr<TileCache::TileBeingRendered>& tileBeingRendered)
 {
-    const std::string cachedName = cacheFileName(tileDesc);
+    return _tilesBeingRendered.find(tileBeingRendered->getTile()) != _tilesBeingRendered.end();
+}
 
+std::shared_ptr<TileCache::TileBeingRendered> TileCache::findTileBeingRendered(const TileDesc& tileDesc)
+{
     assertCorrectThread();
 
-    const auto tile = _tilesBeingRendered.find(cachedName);
+    const auto tile = _tilesBeingRendered.find(tileDesc);
     return tile != _tilesBeingRendered.end() ? tile->second : nullptr;
 }
 
@@ -125,23 +127,24 @@ void TileCache::forgetTileBeingRendered(const std::shared_ptr<TileCache::TileBei
 {
     assertCorrectThread();
     assert(tileBeingRendered);
-    assert(_tilesBeingRendered.find(tileBeingRendered->getCacheName()) != _tilesBeingRendered.end());
+    assert(hasTileBeingRendered(tileBeingRendered));
 
-    _tilesBeingRendered.erase(tileBeingRendered->getCacheName());
+    LOG_TRC("Removing all subscribers for " << tileBeingRendered->getTile().serialize());
+    _tilesBeingRendered.erase(tileBeingRendered->getTile());
 }
 
-double TileCache::getTileBeingRenderedElapsedTimeMs(const std::string& tileCacheName) const
+double TileCache::getTileBeingRenderedElapsedTimeMs(const TileDesc &tileDesc) const
 {
-    auto iterator = _tilesBeingRendered.find(tileCacheName);
-    if(iterator == _tilesBeingRendered.end())
+    auto it = _tilesBeingRendered.find(tileDesc);
+    if (it == _tilesBeingRendered.end())
         return -1.0; // Negativ value means that we did not find tileBeingRendered object
 
-    return iterator->second->getElapsedTimeMs();
+    return it->second->getElapsedTimeMs();
 }
 
 bool TileCache::hasTileBeingRendered(const TileDesc& tile)
 {
-    return (findTileBeingRendered(tile) != nullptr);
+    return findTileBeingRendered(tile) != nullptr;
 }
 
 int TileCache::getTileBeingRenderedVersion(const TileDesc& tile)
@@ -158,8 +161,7 @@ TileCache::Tile TileCache::lookupTile(const TileDesc& tile)
     if (_dontCache)
         return TileCache::Tile();
 
-    const std::string fileName = cacheFileName(tile);
-    TileCache::Tile ret = loadTile(fileName);
+    TileCache::Tile ret = findTile(tile);
 
     UnitWSD::get().lookupTile(tile.getPart(), tile.getWidth(), tile.getHeight(),
                               tile.getTilePosX(), tile.getTilePosY(),
@@ -168,16 +170,6 @@ TileCache::Tile TileCache::lookupTile(const TileDesc& tile)
     return ret;
 }
 
-void TileCache::saveDataToCache(const std::string &fileName, const char *data, const size_t size)
-{
-    if (_dontCache)
-        return;
-
-    TileCache::Tile tile = std::make_shared<std::vector<char>>(size);
-    std::memcpy(tile->data(), data, size);
-    _cache[fileName] = tile;
-}
-
 void TileCache::saveTileAndNotify(const TileDesc& tile, const char *data, const size_t size)
 {
     assertCorrectThread();
@@ -185,14 +177,11 @@ void TileCache::saveTileAndNotify(const TileDesc& tile, const char *data, const
     std::shared_ptr<TileBeingRendered> tileBeingRendered = findTileBeingRendered(tile);
 
     // Save to disk.
-    const std::string cachedName = (tileBeingRendered ? tileBeingRendered->getCacheName()
-                                               : cacheFileName(tile));
 
     // Ignore if we can't save the tile, things will work anyway, but slower.
     // An error indication is supposed to be sent to all users in that case.
-    const auto fileName = cachedName;
-    saveDataToCache(fileName, data, size);
-    LOG_TRC("Saved cache tile: " << fileName);
+    saveDataToCache(tile, data, size);
+    LOG_TRC("Saved cache tile: " << cacheFileName(tile) << " of size " << size << " bytes");
 
     // Notify subscribers, if any.
     if (tileBeingRendered)
@@ -242,7 +231,7 @@ void TileCache::saveTileAndNotify(const TileDesc& tile, const char *data, const
         }
         else
         {
-            LOG_DBG("No subscribers for: " << cachedName);
+            LOG_DBG("No subscribers for: " << cacheFileName(tile));
         }
 
         // Remove subscriptions.
@@ -255,13 +244,13 @@ void TileCache::saveTileAndNotify(const TileDesc& tile, const char *data, const
     }
     else
     {
-        LOG_DBG("No subscribers for: " << cachedName);
+        LOG_DBG("No subscribers for: " << cacheFileName(tile));
     }
 }
 
-bool TileCache::getTextFile(const std::string& fileName, std::string& content)
+bool TileCache::getTextStream(StreamType type, const std::string& fileName, std::string& content)
 {
-    Tile textStream = loadTile(fileName);
+    Tile textStream = lookupCachedStream(type, fileName);
     if (!textStream)
     {
         LOG_INF("Could not open " << fileName);
@@ -280,33 +269,30 @@ bool TileCache::getTextFile(const std::string& fileName, std::string& content)
     return true;
 }
 
-void TileCache::saveTextFile(const std::string& text, const std::string& fileName)
+void TileCache::saveTextStream(StreamType type, const std::string& text, const std::string& fileName)
 {
     LOG_INF("Saving '" << LOOLProtocol::getAbbreviatedMessage(text.c_str(), text.size()) <<
-            "' to " << fileName);
+            "' to " << fileName << " of size " << text.size() << " bytes");
 
-    saveDataToCache(fileName, text.c_str(), text.size());
+    saveDataToStreamCache(type, fileName, text.c_str(), text.size());
 }
 
-void TileCache::setUnsavedChanges(bool state)
-{
-    if (state)
-        saveTextFile("1", "unsaved.txt");
-    else
-        removeFile("unsaved.txt");
-}
-
-void TileCache::saveRendering(const std::string& name, const std::string& dir, const char *data, std::size_t size)
+void TileCache::saveStream(StreamType type, const std::string& name, const char *data, std::size_t size)
 {
     // can fonts be invalidated?
-    const std::string fileName = dir + "/" + name;
-
-    saveDataToCache(fileName, data, size);
+    saveDataToStreamCache(type, name, data, size);
 }
 
-TileCache::Tile TileCache::lookupCachedTile(const std::string& name, const std::string& dir)
+TileCache::Tile TileCache::lookupCachedStream(StreamType type, const std::string& name)
 {
-    return loadTile(dir + "/" + name);
+    auto it = _streamCache[type].find(name);
+    if (it != _streamCache[type].end())
+    {
+        LOG_TRC("Found stream cache tile: " << name << " of size " << it->second->size() << " bytes");
+        return it->second;
+    }
+    else
+        return TileCache::Tile();
 }
 
 void TileCache::invalidateTiles(int part, int x, int y, int width, int height)
@@ -320,10 +306,9 @@ void TileCache::invalidateTiles(int part, int x, int y, int width, int height)
 
     for (auto it = _cache.begin(); it != _cache.end();)
     {
-        const std::string fileName = it->first;
-        if (intersectsTile(fileName, part, x, y, width, height))
+        if (intersectsTile(it->first, part, x, y, width, height))
         {
-            LOG_DBG("Removing tile: " << it->first);
+            LOG_DBG("Removing tile: " << it->first.serialize());
             it = _cache.erase(it);
         }
         else
@@ -375,13 +360,13 @@ std::pair<int, Util::Rectangle> TileCache::parseInvalidateMsg(const std::string&
     return std::pair<int, Util::Rectangle>(-1, Util::Rectangle(0, 0, 0, 0));
 }
 
-void TileCache::removeFile(const std::string& fileName)
+void TileCache::removeStream(StreamType type, const std::string& fileName)
 {
-    auto it = _cache.find(fileName);
-    if (it != _cache.end())
+    auto it = _streamCache[type].find(fileName);
+    if (it != _streamCache[type].end())
     {
         LOG_INF("Removed file: " << fileName);
-        _cache.erase(it);
+        _streamCache[type].erase(it);
     }
 }
 
@@ -399,24 +384,17 @@ bool TileCache::parseCacheFileName(const std::string& fileName, int& part, int&
     return std::sscanf(fileName.c_str(), "%d_%dx%d.%d,%d.%dx%d.png", &part, &width, &height, &tilePosX, &tilePosY, &tileWidth, &tileHeight) == 7;
 }
 
-bool TileCache::intersectsTile(const std::string& fileName, int part, int x, int y, int width, int height)
+bool TileCache::intersectsTile(const TileDesc &tileDesc, int part, int x, int y, int width, int height)
 {
-    int tilePart, tilePixelWidth, tilePixelHeight, tilePosX, tilePosY, tileWidth, tileHeight;
-    if (parseCacheFileName(fileName, tilePart, tilePixelWidth, tilePixelHeight, tilePosX, tilePosY, tileWidth, tileHeight))
-    {
-        if (part != -1 && tilePart != part)
-            return false;
-
-        const int left = std::max(x, tilePosX);
-        const int right = std::min(x + width, tilePosX + tileWidth);
-        const int top = std::max(y, tilePosY);
-        const int bottom = std::min(y + height, tilePosY + tileHeight);
+    if (part != -1 && tileDesc.getPart() != part)
+        return false;
 
-        if (left <= right && top <= bottom)
-            return true;
-    }
+    const int left = std::max(x, tileDesc.getTilePosX());
+    const int right = std::min(x + width, tileDesc.getTilePosX() + tileDesc.getTileWidth());
+    const int top = std::max(y, tileDesc.getTilePosY());
+    const int bottom = std::min(y + height, tileDesc.getTilePosY() + tileDesc.getTileHeight());
 
-    return false;
+    return left <= right && top <= bottom;
 }
 
 // FIXME: to be further simplified when we centralize tile messages.
@@ -456,15 +434,13 @@ void TileCache::subscribeToTileRendering(const TileDesc& tile, const std::shared
     else
     {
         LOG_DBG("Subscribing " << subscriber->getName() << " to tile " << name <<
-                " ver=" << tile.getVersion() << " which has no subscribers.");
+                " ver=" << tile.getVersion() << " which has no subscribers " << tile.serialize());
 
-        const std::string cachedName = cacheFileName(tile);
+        assert(_tilesBeingRendered.find(tile) == _tilesBeingRendered.end());
 
-        assert(_tilesBeingRendered.find(cachedName) == _tilesBeingRendered.end());
-
-        tileBeingRendered = std::make_shared<TileBeingRendered>(cachedName, tile);
+        tileBeingRendered = std::make_shared<TileBeingRendered>(tile);
         tileBeingRendered->getSubscribers().push_back(subscriber);
-        _tilesBeingRendered[cachedName] = tileBeingRendered;
+        _tilesBeingRendered[tile] = tileBeingRendered;
     }
 }
 
@@ -482,12 +458,10 @@ void TileCache::registerTileBeingRendered(const TileDesc& tile)
     }
     else
     {
-        const std::string cachedName = cacheFileName(tile);
-
-        assert(_tilesBeingRendered.find(cachedName) == _tilesBeingRendered.end());
+        assert(_tilesBeingRendered.find(tile) == _tilesBeingRendered.end());
 
-        tileBeingRendered = std::make_shared<TileBeingRendered>(cachedName, tile);
-        _tilesBeingRendered[cachedName] = tileBeingRendered;
+        tileBeingRendered = std::make_shared<TileBeingRendered>(tile);
+        _tilesBeingRendered[tile] = tileBeingRendered;
     }
 }
 
@@ -512,13 +486,13 @@ std::string TileCache::cancelTiles(const std::shared_ptr<ClientSession> &subscri
         }
 
         auto& subscribers = it->second->getSubscribers();
-        LOG_TRC("Tile " << it->first << " has " << subscribers.size() << " subscribers.");
+        LOG_TRC("Tile " << it->first.serialize() << " has " << subscribers.size() << " subscribers.");
 
         const auto itRem = std::find_if(subscribers.begin(), subscribers.end(),
                                         [sub](std::weak_ptr<ClientSession>& ptr){ return ptr.lock().get() == sub; });
         if (itRem != subscribers.end())
         {
-            LOG_TRC("Tile " << it->first << " has " << subscribers.size() <<
+            LOG_TRC("Tile " << it->first.serialize() << " has " << subscribers.size() <<
                     " subscribers. Removing " << subscriber->getName() << ".");
             subscribers.erase(itRem, itRem + 1);
             if (subscribers.empty())
@@ -547,29 +521,69 @@ void TileCache::assertCorrectThread()
     assert (correctThread);
 }
 
-TileCache::Tile TileCache::loadTile(const std::string &fileName)
+TileCache::Tile TileCache::findTile(const TileDesc &desc)
 {
-    auto it = _cache.find(fileName);
+    auto it = _cache.find(desc);
     if (it != _cache.end())
     {
-        LOG_TRC("Found cache tile: " << fileName);
+        LOG_TRC("Found cache tile: " << desc.serialize() << " of size " << it->second->size() << " bytes");
         return it->second;
     }
     else
         return TileCache::Tile();
 }
 
+void TileCache::saveDataToCache(const TileDesc &desc, const char *data, const size_t size)
+{
+    if (_dontCache)
+        return;
+
+    TileCache::Tile tile = std::make_shared<std::vector<char>>(size);
+    std::memcpy(tile->data(), data, size);
+    _cache[desc] = tile;
+}
+
+void TileCache::saveDataToStreamCache(StreamType type, const std::string &fileName, const char *data, const size_t size)
+{
+    if (_dontCache)
+        return;
+
+    TileCache::Tile tile = std::make_shared<std::vector<char>>(size);
+    std::memcpy(tile->data(), data, size);
+    _streamCache[type][fileName] = tile;
+}
+
 void TileCache::dumpState(std::ostream& os)
 {
-    size_t num = 0, size = 0;
-    for (auto it : _cache)
     {
-        num++; size += it.second->size();
+        size_t num = 0, size = 0;
+        for (auto it : _cache)
+        {
+            num++; size += it.second->size();
+        }
+        os << "  tile cache: num: " << num << " size: " << size << " bytes\n";
+        for (auto it : _cache)
+        {
+            os << "    " << std::setw(4) << it.first.getWireId()
+               << "\t" << std::setw(6) << it.second->size() << " bytes"
+               << "\t'" << it.first.serialize() << "'\n" ;
+        }
     }
-    os << "  tile cache: num: " << num << " size: " << size << " bytes\n";
-    for (auto it : _cache)
+
+    int type = 0;
+    for (auto i : _streamCache)
     {
-        os << "    " /* << std::setw(4) << it.first->getWireId() */ << " - '" << it.first << "' - " << it.second->size() << " bytes\n";
+        size_t num = 0, size = 0;
+        for (auto it : i)
+        {
+            num++; size += it.second->size();
+        }
+        os << "  stream cache: " << type++ << " num: " << num << " size: " << size << " bytes\n";
+        for (auto it : i)
+        {
+            os << "    " << it.first
+               << "\t" << std::setw(6) << it.second->size() << " bytes\n";
+        }
     }
 }
 
diff --git a/wsd/TileCache.hpp b/wsd/TileCache.hpp
index 70dc04fa1..d922b941f 100644
--- a/wsd/TileCache.hpp
+++ b/wsd/TileCache.hpp
@@ -11,10 +11,10 @@
 #define INCLUDED_TILECACHE_HPP
 
 #include <iosfwd>
-#include <map>
 #include <memory>
 #include <thread>
 #include <string>
+#include <unordered_map>
 
 #include <Poco/Timestamp.h>
 #include <Rectangle.hpp>
@@ -23,11 +23,58 @@
 
 class ClientSession;
 
+class TileCacheDesc : public TileDesc
+{
+public:
+    TileCacheDesc(const TileDesc &copy)
+        : TileDesc(copy)
+    {
+    }
+
+    // The cache cares about only some properties.
+    bool operator==(const TileCacheDesc& other) const
+    {
+        return _part == other._part &&
+               _width == other._width &&
+               _height == other._height &&
+               _tilePosX == other._tilePosX &&
+               _tilePosY == other._tilePosY &&
+               _tileWidth == other._tileWidth &&
+               _tileHeight == other._tileHeight;
+    }
+};
+
+// The cache cares about only some properties.
+struct TileCacheDescCompareEqual
+{
+    bool operator()(const TileCacheDesc &l, const TileCacheDesc &r) const { return l == r; }
+};
+
+// The cache cares about only some properties.
+struct TileCacheDescHasher
+{
+    size_t
+    operator()(const TileCacheDesc &t) const
+    {
+        size_t hash = t.getPart();
+
+        hash = (hash << 5) + hash + t.getWidth();
+        hash = (hash << 5) + hash + t.getHeight();
+        hash = (hash << 5) + hash + t.getTilePosX();
+        hash = (hash << 5) + hash + t.getTilePosY();
+        hash = (hash << 5) + hash + t.getTileWidth();
+        hash = (hash << 5) + hash + t.getTileHeight();
+
+        return hash;
+    }
+};
+
 /// Handles the caching of tiles of one document.
 class TileCache
 {
     struct TileBeingRendered;
 
+    bool hasTileBeingRendered(const std::shared_ptr<TileCache::TileBeingRendered>& tileBeingRendered);
     std::shared_ptr<TileBeingRendered> findTileBeingRendered(const TileDesc& tile);
 
 public:
@@ -61,23 +108,26 @@ public:
 
     void saveTileAndNotify(const TileDesc& tile, const char* data, const size_t size);
 
+    enum StreamType {
+        Font,
+        Style,
+        CmdValues,
+        Last
+    };
+
     /// Get the content of a cache file.
     /// @param content Valid only when the call returns true.
     /// @return true when the file actually exists
-    bool getTextFile(const std::string& fileName, std::string& content);
+    bool getTextStream(StreamType type, const std::string& fileName, std::string& content);
 
     // Save some text into a file in the cache directory
-    void saveTextFile(const std::string& text, const std::string& fileName);
-
-    // Set the unsaved-changes state, used for sanity checks, ideally not needed
-    void setUnsavedChanges(bool state);
+    void saveTextStream(StreamType type, const std::string& text, const std::string& fileName);
 
     // Saves a font / style / etc rendering
-    // The dir parameter should be the type of rendering, like "font", "style", etc
-    void saveRendering(const std::string& name, const std::string& dir, const char* data, size_t size);
+    void saveStream(StreamType type, const std::string& name, const char* data, size_t size);
 
     /// Return the tile data if we have it, or nothing.
-    Tile lookupCachedTile(const std::string& name, const std::string& dir);
+    Tile lookupCachedStream(StreamType type, const std::string& name);
 
     // The tiles parameter is an invalidatetiles: message as sent by the child process
     void invalidateTiles(const std::string& tiles);
@@ -86,12 +136,11 @@ public:
     static std::pair<int, Util::Rectangle> parseInvalidateMsg(const std::string& tiles);
 
     void forgetTileBeingRendered(const std::shared_ptr<TileCache::TileBeingRendered>& tileBeingRendered);
-    double getTileBeingRenderedElapsedTimeMs(const std::string& tileCacheName) const;
-
-    size_t countTilesBeingRenderedForSession(const std::shared_ptr<ClientSession>& subscriber);
+    double getTileBeingRenderedElapsedTimeMs(const TileDesc &tileDesc) const;
 
-    bool hasTileBeingRendered(const TileDesc& tile);
-    int  getTileBeingRenderedVersion(const TileDesc& tile);
+    size_t countTilesBeingRenderedForSession(const std::shared_ptr<ClientSession>& session);
+    bool hasTileBeingRendered(const TileDesc& tileDesc);
+    int  getTileBeingRenderedVersion(const TileDesc& tileDesc);
 
     // Debugging bits ...
     void dumpState(std::ostream& os);
@@ -102,26 +151,39 @@ private:
     void invalidateTiles(int part, int x, int y, int width, int height);
 
     /// Lookup tile in our cache.
-    TileCache::Tile loadTile(const std::string &fileName);
+    TileCache::Tile findTile(const TileDesc &desc);
+
+    /// Lookup tile in our stream cache.
+    TileCache::Tile findStreamTile(StreamType type, const std::string &fileName);
 
-    /// Removes the given file from the cache
-    void removeFile(const std::string& fileName);
+    /// Removes the named stream from the cache
+    void removeStream(StreamType type, const std::string& fileName);
 
-    static std::string cacheFileName(const TileDesc& tile);
+    static std::string cacheFileName(const TileDesc& tileDesc);
     static bool parseCacheFileName(const std::string& fileName, int& part, int& width, int& height, int& tilePosX, int& tilePosY, int& tileWidth, int& tileHeight);
 
     /// Extract location from fileName, and check if it intersects with [x, y, width, height].
-    static bool intersectsTile(const std::string& fileName, int part, int x, int y, int width, int height);
+    static bool intersectsTile(const TileDesc &tileDesc, int part, int x, int y, int width, int height);
 
-    void saveDataToCache(const std::string &fileName, const char *data, const size_t size);
+    void saveDataToCache(const TileDesc &desc, const char *data, const size_t size);
+    void saveDataToStreamCache(StreamType type, const std::string &fileName, const char *data, const size_t size);
 
     const std::string _docURL;
 
     std::thread::id _owner;
 
     bool _dontCache;
-    std::map<std::string, Tile> _cache;
-    std::map<std::string, std::shared_ptr<TileBeingRendered> > _tilesBeingRendered;
+    // FIXME: should we have a tile-desc to WID map instead and a simpler lookup ?
+    std::unordered_map<TileCacheDesc, Tile,
+                       TileCacheDescHasher,
+                       TileCacheDescCompareEqual> _cache;
+    // FIXME: TileBeingRendered contains TileDesc too ...
+    std::unordered_map<TileCacheDesc, std::shared_ptr<TileBeingRendered>,
+                       TileCacheDescHasher,
+                       TileCacheDescCompareEqual> _tilesBeingRendered;
+
+    // old-style file-name to data grab-bag.
+    std::map<std::string, Tile> _streamCache[(int)StreamType::Last];
 };
 
 #endif
diff --git a/wsd/TileDesc.hpp b/wsd/TileDesc.hpp
index 3a68040c8..38e805d38 100644
--- a/wsd/TileDesc.hpp
+++ b/wsd/TileDesc.hpp
@@ -233,7 +233,7 @@ public:
         return tileID.str();
     }
 
-private:
+protected:
     int _part;
     int _width;
     int _height;


More information about the Libreoffice-commits mailing list