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

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Fri Feb 15 11:42:32 UTC 2019


 test/Makefile.am        |    1 
 test/TileCacheTests.cpp |    2 
 wsd/DocumentBroker.cpp  |   16 ++--
 wsd/TileCache.cpp       |  187 +++++++++++++++---------------------------------
 wsd/TileCache.hpp       |   23 ++---
 5 files changed, 82 insertions(+), 147 deletions(-)

New commits:
commit 66ac62429c67a4fadca4f5481c76bdbb98361f0a
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Thu Feb 14 22:40:33 2019 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Fri Feb 15 12:10:16 2019 +0100

    TileCache: switch to in-memory, rather than persistent.
    
    Remove significant complexity; if we need it later lets do it more simply
    serializing when we start / finish a session.
    
    Turn off caching for mobile - possibly should kill for single-user too.
    
    Change-Id: I5ea56088ddbb61f22fe7920f8c9ac7440cb3296a

diff --git a/test/Makefile.am b/test/Makefile.am
index 7af9b467b..2683bce16 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -122,6 +122,7 @@ check-local:
 	./run_unit.sh --log-file test.log --trs-file test.trs
 # FIXME 2: unit-oob.la fails with symbol undefined:
 # UnitWSD::testHandleRequest(UnitWSD::TestRequest, UnitHTTPServerRequest&, UnitHTTPServerResponse&) ,
+
 TESTS = unit-typing.la unit-convert.la unit-prefork.la unit-tilecache.la \
 	unit-timeout.la unit-oauth.la unit-wopi.la unit-wopi-saveas.la \
         unit-wopi-ownertermination.la unit-wopi-versionrestore.la \
diff --git a/test/TileCacheTests.cpp b/test/TileCacheTests.cpp
index 982d0351c..c02989dee 100644
--- a/test/TileCacheTests.cpp
+++ b/test/TileCacheTests.cpp
@@ -183,7 +183,7 @@ void TileCacheTests::testSimple()
 
     // Create TileCache and pretend the file was modified as recently as
     // now, so it discards the cached data.
-    TileCache tc("doc.ods", Poco::Timestamp(), "/tmp/tile_cache_tests", true);
+    TileCache tc("doc.ods", Poco::Timestamp());
 
     int part = 0;
     int width = 256;
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 3cce77e62..01a78b9b8 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -391,9 +391,8 @@ void DocumentBroker::pollThread()
     LOOLWSD::doHousekeeping();
 #endif
 
-    // Remove all tiles related to this document from the cache if configured so.
-    if (_tileCache && !LOOLWSD::TileCachePersistent)
-        _tileCache->completeCleanup();
+    if (_tileCache)
+        _tileCache->clear();
 
     LOG_INF("Finished docBroker polling thread for docKey [" << _docKey << "].");
 }
@@ -727,7 +726,15 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
 
         // Use the local temp file's timestamp.
         _lastFileModifiedTime = Poco::File(_storage->getRootFilePath()).getLastModified();
-        _tileCache.reset(new TileCache(_storage->getUriString(), _lastFileModifiedTime, _cacheRoot, LOOLWSD::TileCachePersistent));
+
+        bool dontUseCache = false;
+#if MOBILEAPP
+        // avoid memory consumption for single-user local bits.
+        // FIXME: arguably should/could do this for single user documents too.
+        dontUseCache = true;
+#endif
+
+        _tileCache.reset(new TileCache(_storage->getUriString(), _lastFileModifiedTime, dontUseCache));
         _tileCache->setThreadOwner(std::this_thread::get_id());
     }
 
@@ -856,7 +863,6 @@ bool DocumentBroker::saveToStorageInternal(const std::string& sessionId,
             // Saved and stored; update flags.
             setModified(false);
             _lastFileModifiedTime = newFileModifiedTime;
-            _tileCache->saveLastModified(_lastFileModifiedTime);
             _lastSaveTime = std::chrono::steady_clock::now();
 
             // Save the storage timestamp.
diff --git a/wsd/TileCache.cpp b/wsd/TileCache.cpp
index b709bde2c..e87fe9214 100644
--- a/wsd/TileCache.cpp
+++ b/wsd/TileCache.cpp
@@ -44,54 +44,18 @@ using Poco::File;
 using Poco::StringTokenizer;
 using Poco::Timestamp;
 
-namespace {
-    TileCache::Tile loadTile(const std::string &fileName)
-    {
-        TileCache::Tile ret;
-
-        std::unique_ptr<std::fstream> result(new std::fstream(fileName, std::ios::in));
-        if (result && result->is_open())
-        {
-            LOG_TRC("Found cache tile: " << fileName);
-
-            result->seekg(0, std::ios_base::end);
-            std::streamsize size = result->tellg();
-            ret = std::make_shared<std::vector<char>>(size);
-            result->seekg(0, std::ios_base::beg);
-            result->read(ret->data(), size);
-            result->close();
-        }
-        return ret;
-    }
-}
-
 TileCache::TileCache(const std::string& docURL,
                      const Timestamp& modifiedTime,
-                     const std::string& cacheDir,
-                     const bool tileCachePersistent) :
+                     bool dontCache) :
     _docURL(docURL),
-    _cacheDir(cacheDir),
-    _tileCachePersistent(tileCachePersistent)
+    _dontCache(dontCache)
 {
 #ifndef BUILDING_TESTS
     LOG_INF("TileCache ctor for uri [" << LOOLWSD::anonymizeUrl(_docURL) <<
-            "], cacheDir: [" << _cacheDir <<
             "], modifiedTime=" << (modifiedTime.raw()/1000000) <<
-            " getLastModified()=" << (getLastModified().raw()/1000000));
+            "], dontCache=" << _dontCache);
 #endif
-    File directory(_cacheDir);
-    std::string unsaved;
-    if (directory.exists() &&
-        (getLastModified() < modifiedTime ||
-         getTextFile("unsaved.txt", unsaved)))
-    {
-        // Document changed externally or modifications were not saved after all. Cache not useful.
-        completeCleanup();
-    }
-
-    File(_cacheDir).createDirectories();
-
-    saveLastModified(modifiedTime);
+    (void)modifiedTime;
 }
 
 TileCache::~TileCache()
@@ -102,10 +66,10 @@ TileCache::~TileCache()
 #endif
 }
 
-void TileCache::completeCleanup() const
+void TileCache::clear()
 {
-    FileUtil::removeFile(_cacheDir, true);
-    LOG_INF("Completely cleared tile cache: " << _cacheDir);
+    _cache.clear();
+    LOG_INF("Completely cleared tile cache for: " << _docURL);
 }
 
 /// Tracks the rendering of a given tile
@@ -187,10 +151,10 @@ int TileCache::getTileBeingRenderedVersion(const TileDesc& tile)
 
 TileCache::Tile TileCache::lookupTile(const TileDesc& tile)
 {
-    if (!_tileCachePersistent)
-        return nullptr;
+    if (_dontCache)
+        return TileCache::Tile();
 
-    const std::string fileName = _cacheDir + "/" + cacheFileName(tile);
+    const std::string fileName = cacheFileName(tile);
     TileCache::Tile ret = loadTile(fileName);
 
     UnitWSD::get().lookupTile(tile.getPart(), tile.getWidth(), tile.getHeight(),
@@ -200,6 +164,16 @@ 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();
@@ -212,11 +186,9 @@ void TileCache::saveTileAndNotify(const TileDesc& tile, const char *data, const
 
     // 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 = _cacheDir + "/" + cachedName;
-    if (_tileCachePersistent && FileUtil::saveDataToFileSafely(fileName, data, size))
-    {
-        LOG_TRC("Saved cache tile: " << fileName);
-    }
+    const auto fileName = cachedName;
+    saveDataToCache(fileName, data, size);
+    LOG_TRC("Saved cache tile: " << fileName);
 
     // Notify subscribers, if any.
     if (tileBeingRendered)
@@ -285,51 +257,31 @@ void TileCache::saveTileAndNotify(const TileDesc& tile, const char *data, const
 
 bool TileCache::getTextFile(const std::string& fileName, std::string& content)
 {
-    const std::string fullFileName =  _cacheDir + "/" + fileName;
-
-    std::fstream textStream(fullFileName, std::ios::in);
-    if (!textStream.is_open())
+    Tile textStream = loadTile(fileName);
+    if (!textStream)
     {
-        LOG_INF("Could not open " << fullFileName);
+        LOG_INF("Could not open " << fileName);
         return false;
     }
 
-    std::vector<char> buffer;
-    textStream.seekg(0, std::ios_base::end);
-    std::streamsize size = textStream.tellg();
-    buffer.resize(size);
-    textStream.seekg(0, std::ios_base::beg);
-    textStream.read(buffer.data(), size);
-    textStream.close();
+    std::vector<char> buffer = *textStream;
 
     if (buffer.size() > 0 && buffer.back() == '\n')
         buffer.pop_back();
 
     content = std::string(buffer.data(), buffer.size());
     LOG_INF("Read '" << LOOLProtocol::getAbbreviatedMessage(content.c_str(), content.size()) <<
-            "' from " << fullFileName);
+            "' from " << fileName);
 
     return true;
 }
 
 void TileCache::saveTextFile(const std::string& text, const std::string& fileName)
 {
-    const std::string fullFileName = _cacheDir + "/" + fileName;
-    std::fstream textStream(fullFileName, std::ios::out);
+    LOG_INF("Saving '" << LOOLProtocol::getAbbreviatedMessage(text.c_str(), text.size()) <<
+            "' to " << fileName);
 
-    if (!textStream.is_open())
-    {
-        LOG_ERR("Could not save '" << text << "' to " << fullFileName);
-        return;
-    }
-    else
-    {
-        LOG_INF("Saving '" << LOOLProtocol::getAbbreviatedMessage(text.c_str(), text.size()) <<
-                "' to " << fullFileName);
-    }
-
-    textStream << text << std::endl;
-    textStream.close();
+    saveDataToCache(fileName, text.c_str(), text.size());
 }
 
 void TileCache::setUnsavedChanges(bool state)
@@ -343,25 +295,14 @@ void TileCache::setUnsavedChanges(bool state)
 void TileCache::saveRendering(const std::string& name, const std::string& dir, const char *data, std::size_t size)
 {
     // can fonts be invalidated?
-    const std::string dirName = _cacheDir + "/" + dir;
-
-    File(dirName).createDirectories();
+    const std::string fileName = dir + "/" + name;
 
-    const std::string fileName = dirName + "/" + name;
-
-    FileUtil::saveDataToFileSafely(fileName, data, size);
+    saveDataToCache(fileName, data, size);
 }
 
 TileCache::Tile TileCache::lookupCachedTile(const std::string& name, const std::string& dir)
 {
-    const std::string dirName = _cacheDir + "/" + dir;
-    const std::string fileName = dirName + "/" + name;
-    File directory(dirName);
-
-    if (directory.exists() && directory.isDirectory() && File(fileName).exists())
-        return loadTile(fileName);
-    else
-        return Tile();
+    return loadTile(dir + "/" + name);
 }
 
 void TileCache::invalidateTiles(int part, int x, int y, int width, int height)
@@ -371,21 +312,18 @@ void TileCache::invalidateTiles(int part, int x, int y, int width, int height)
             ", width: " << width <<
             ", height: " << height);
 
-    File dir(_cacheDir);
-
     assertCorrectThread();
 
-    if (dir.exists() && dir.isDirectory())
+    for (auto it = _cache.begin(); it != _cache.end();)
     {
-        for (auto tileIterator = DirectoryIterator(dir); tileIterator != DirectoryIterator(); ++tileIterator)
+        const std::string fileName = it->first;
+        if (intersectsTile(fileName, part, x, y, width, height))
         {
-            const std::string fileName = tileIterator.path().getFileName();
-            if (intersectsTile(fileName, part, x, y, width, height))
-            {
-                LOG_DBG("Removing tile: " << tileIterator.path().toString());
-                FileUtil::removeFile(tileIterator.path());
-            }
+            LOG_DBG("Removing tile: " << it->first);
+            it = _cache.erase(it);
         }
+        else
+            ++it;
     }
 }
 
@@ -435,10 +373,12 @@ std::pair<int, Util::Rectangle> TileCache::parseInvalidateMsg(const std::string&
 
 void TileCache::removeFile(const std::string& fileName)
 {
-    const std::string fullFileName = _cacheDir + "/" + fileName;
-
-    if (std::remove(fullFileName.c_str()) == 0)
-        LOG_INF("Removed file: " << fullFileName);
+    auto it = _cache.find(fileName);
+    if (it != _cache.end())
+    {
+        LOG_INF("Removed file: " << fileName);
+        _cache.erase(it);
+    }
 }
 
 std::string TileCache::cacheFileName(const TileDesc& tile)
@@ -475,27 +415,6 @@ bool TileCache::intersectsTile(const std::string& fileName, int part, int x, int
     return false;
 }
 
-Timestamp TileCache::getLastModified()
-{
-    std::fstream modTimeFile(_cacheDir + "/modtime.txt", std::ios::in);
-
-    if (!modTimeFile.is_open())
-        return 0;
-
-    Timestamp::TimeVal result;
-    modTimeFile >> result;
-
-    modTimeFile.close();
-    return result;
-}
-
-void TileCache::saveLastModified(const Timestamp& timestamp)
-{
-    std::fstream modTimeFile(_cacheDir + "/modtime.txt", std::ios::out);
-    modTimeFile << timestamp.raw() << std::endl;
-    modTimeFile.close();
-}
-
 // FIXME: to be further simplified when we centralize tile messages.
 void TileCache::subscribeToTileRendering(const TileDesc& tile, const std::shared_ptr<ClientSession>& subscriber)
 {
@@ -628,4 +547,16 @@ void TileCache::assertCorrectThread()
     assert (correctThread);
 }
 
+TileCache::Tile TileCache::loadTile(const std::string &fileName)
+{
+    auto it = _cache.find(fileName);
+    if (it != _cache.end())
+    {
+        LOG_TRC("Found cache tile: " << fileName);
+        return it->second;
+    }
+    else
+        return TileCache::Tile();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/wsd/TileCache.hpp b/wsd/TileCache.hpp
index 1a9ba0a26..9f847fc5d 100644
--- a/wsd/TileCache.hpp
+++ b/wsd/TileCache.hpp
@@ -36,11 +36,11 @@ public:
     /// When the docURL is a non-file:// url, the timestamp has to be provided by the caller.
     /// For file:// url's, it's ignored.
     /// When it is missing for non-file:// url, it is assumed the document must be read, and no cached value used.
-    TileCache(const std::string& docURL, const Poco::Timestamp& modifiedTime, const std::string& cacheDir, bool tileCachePersistent);
+    TileCache(const std::string& docURL, const Poco::Timestamp& modifiedTime, bool dontCache = false);
     ~TileCache();
 
-    /// Remove the entire cache directory.
-    void completeCleanup() const;
+    /// Completely clear the cache contents.
+    void clear();
 
     TileCache(const TileCache&) = delete;
 
@@ -85,9 +85,6 @@ public:
     /// Parse invalidateTiles message to a part number and a rectangle of the invalidated area
     static std::pair<int, Util::Rectangle> parseInvalidateMsg(const std::string& tiles);
 
-    /// Store the timestamp to modtime.txt.
-    void saveLastModified(const Poco::Timestamp& timestamp);
-
     void forgetTileBeingRendered(const std::shared_ptr<TileCache::TileBeingRendered>& tileBeingRendered, const TileDesc& tile);
     double getTileBeingRenderedElapsedTimeMs(const std::string& tileCacheName) const;
 
@@ -102,7 +99,10 @@ public:
 private:
     void invalidateTiles(int part, int x, int y, int width, int height);
 
-    // Removes the given file from the cache
+    /// Lookup tile in our cache.
+    TileCache::Tile loadTile(const std::string &fileName);
+
+    /// Removes the given file from the cache
     void removeFile(const std::string& fileName);
 
     static std::string cacheFileName(const TileDesc& tile);
@@ -111,17 +111,14 @@ private:
     /// 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);
 
-    /// Load the timestamp from modtime.txt.
-    Poco::Timestamp getLastModified();
+    void saveDataToCache(const std::string &fileName, const char *data, const size_t size);
 
     const std::string _docURL;
 
-    const std::string _cacheDir;
-
-    const bool _tileCachePersistent;
-
     std::thread::id _owner;
 
+    bool _dontCache;
+    std::map<std::string, Tile> _cache;
     std::map<std::string, std::shared_ptr<TileBeingRendered> > _tilesBeingRendered;
 };
 


More information about the Libreoffice-commits mailing list