2015-04-13 04:09:02 -05:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
2015-03-12 09:18:35 -05:00
|
|
|
/*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
2017-12-20 07:06:26 -06:00
|
|
|
#include <config.h>
|
2015-03-12 09:18:35 -05:00
|
|
|
|
2017-03-08 10:38:22 -06:00
|
|
|
#include "TileCache.hpp"
|
|
|
|
|
2015-05-28 04:53:14 -05:00
|
|
|
#include <cassert>
|
2015-05-29 00:39:21 -05:00
|
|
|
#include <climits>
|
2019-09-02 03:18:12 -05:00
|
|
|
#include <cstddef>
|
2020-07-12 11:25:49 -05:00
|
|
|
#include <cstdio>
|
2015-03-12 09:18:35 -05:00
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
|
|
|
#include <memory>
|
2015-08-04 13:37:05 -05:00
|
|
|
#include <sstream>
|
2015-05-05 06:57:51 -05:00
|
|
|
#include <string>
|
2020-07-12 11:25:49 -05:00
|
|
|
#include <utility>
|
2016-04-15 10:24:00 -05:00
|
|
|
#include <vector>
|
2015-03-12 09:18:35 -05:00
|
|
|
|
loolwsd: include cleanup and organization
A source file (.cpp) must include its own header first.
This insures that the header is self-contained and
doesn't depend on arbitrary (and accidental) includes
before it to compile.
Furthermore, system headers should go next, followed by
C then C++ headers, then libraries (Poco, etc) and, finally,
project headers come last.
This makes sure that headers and included in the same dependency
order to avoid side-effects. For example, Poco should never rely on
anything from our project in the same way that a C header should
never rely on anything in C++, Poco, or project headers.
Also, includes ought to be sorted where possible, to improve
readability and avoid accidental duplicates (of which there
were a few).
Change-Id: I62cc1343e4a091d69195e37ed659dba20cfcb1ef
Reviewed-on: https://gerrit.libreoffice.org/25262
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2016-05-21 09:23:07 -05:00
|
|
|
#include "ClientSession.hpp"
|
2017-12-20 07:06:26 -06:00
|
|
|
#include <Common.hpp>
|
|
|
|
#include <Protocol.hpp>
|
2022-03-29 20:37:57 -05:00
|
|
|
#include <StringVector.hpp>
|
2017-12-20 07:06:26 -06:00
|
|
|
#include <Unit.hpp>
|
|
|
|
#include <Util.hpp>
|
|
|
|
#include <common/FileUtil.hpp>
|
2017-11-08 02:34:37 -06:00
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
using namespace COOLProtocol;
|
2015-03-12 09:18:35 -05:00
|
|
|
|
2020-07-12 11:25:49 -05:00
|
|
|
TileCache::TileCache(std::string docURL, const std::chrono::system_clock::time_point& modifiedTime,
|
|
|
|
bool dontCache)
|
|
|
|
: _docURL(std::move(docURL))
|
|
|
|
, _dontCache(dontCache)
|
|
|
|
, _cacheSize(0)
|
2023-06-23 09:18:49 -05:00
|
|
|
, _maxCacheSize(1024 * 1024)
|
2015-03-12 18:34:42 -05:00
|
|
|
{
|
2018-06-15 09:28:55 -05:00
|
|
|
#ifndef BUILDING_TESTS
|
2021-11-18 06:08:14 -06:00
|
|
|
LOG_INF("TileCache ctor for uri [" << COOLWSD::anonymizeUrl(_docURL) <<
|
2019-08-30 12:37:55 -05:00
|
|
|
"], modifiedTime=" << std::chrono::duration_cast<std::chrono::seconds>
|
|
|
|
(modifiedTime.time_since_epoch()).count() << "], dontCache=" << _dontCache);
|
2018-06-15 09:28:55 -05:00
|
|
|
#endif
|
2019-02-14 15:40:33 -06:00
|
|
|
(void)modifiedTime;
|
2015-03-12 09:18:35 -05:00
|
|
|
}
|
|
|
|
|
2016-03-26 06:50:13 -05:00
|
|
|
TileCache::~TileCache()
|
|
|
|
{
|
2018-09-03 10:58:43 -05:00
|
|
|
_owner = std::thread::id();
|
2018-06-15 09:28:55 -05:00
|
|
|
#ifndef BUILDING_TESTS
|
2021-11-18 06:08:14 -06:00
|
|
|
LOG_INF("~TileCache dtor for uri [" << COOLWSD::anonymizeUrl(_docURL) << "].");
|
2018-06-15 09:28:55 -05:00
|
|
|
#endif
|
2016-04-15 10:24:00 -05:00
|
|
|
}
|
|
|
|
|
2019-02-14 15:40:33 -06:00
|
|
|
void TileCache::clear()
|
2017-04-12 13:04:30 -05:00
|
|
|
{
|
2019-02-14 15:40:33 -06:00
|
|
|
_cache.clear();
|
2019-10-28 08:26:15 -05:00
|
|
|
_cacheSize = 0;
|
2022-12-16 05:20:38 -06:00
|
|
|
for (std::map<std::string, Blob>& i : _streamCache)
|
2019-02-15 14:55:47 -06:00
|
|
|
i.clear();
|
2020-07-12 11:25:49 -05:00
|
|
|
|
2019-02-14 15:40:33 -06:00
|
|
|
LOG_INF("Completely cleared tile cache for: " << _docURL);
|
2017-04-12 13:04:30 -05:00
|
|
|
}
|
|
|
|
|
2016-08-13 23:01:13 -05:00
|
|
|
/// Tracks the rendering of a given tile
|
|
|
|
/// to avoid duplication and help clock
|
|
|
|
/// rendering latency.
|
2016-04-25 04:04:25 -05:00
|
|
|
struct TileCache::TileBeingRendered
|
2016-04-15 10:24:00 -05:00
|
|
|
{
|
2020-08-07 11:36:56 -05:00
|
|
|
explicit TileBeingRendered(const TileDesc& tile, const std::chrono::steady_clock::time_point &now)
|
|
|
|
: _startTime(now), _tile(tile) { }
|
2016-05-15 09:19:49 -05:00
|
|
|
|
2016-09-21 17:47:00 -05:00
|
|
|
const TileDesc& getTile() const { return _tile; }
|
2022-06-16 10:31:37 -05:00
|
|
|
|
|
|
|
/// The version is used to ensure that if we have two in-progress
|
|
|
|
/// renders sent to the kit, racing each other that the completion of
|
|
|
|
/// the first does not remove the subscribers waiting for the second.
|
2016-09-21 17:47:00 -05:00
|
|
|
int getVersion() const { return _tile.getVersion(); }
|
|
|
|
void setVersion(int version) { _tile.setVersion(version); }
|
2016-05-22 13:31:18 -05:00
|
|
|
|
2016-05-15 09:19:49 -05:00
|
|
|
std::chrono::steady_clock::time_point getStartTime() const { return _startTime; }
|
2020-12-06 21:45:46 -06:00
|
|
|
std::chrono::milliseconds getElapsedTimeMs(const std::chrono::steady_clock::time_point* now
|
|
|
|
= nullptr) const
|
|
|
|
{
|
|
|
|
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
|
|
(now ? *now : std::chrono::steady_clock::now()) - _startTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isStale(const std::chrono::steady_clock::time_point* now = nullptr) const
|
|
|
|
{
|
|
|
|
return getElapsedTimeMs(now) > std::chrono::milliseconds(COMMAND_TIMEOUT_MS);
|
|
|
|
}
|
|
|
|
|
2018-11-20 02:14:44 -06:00
|
|
|
std::vector<std::weak_ptr<ClientSession>>& getSubscribers() { return _subscribers; }
|
2019-03-05 00:15:50 -06:00
|
|
|
|
|
|
|
void dumpState(std::ostream& os);
|
|
|
|
|
2016-05-15 09:19:49 -05:00
|
|
|
private:
|
2018-11-20 02:14:44 -06:00
|
|
|
std::vector<std::weak_ptr<ClientSession>> _subscribers;
|
2016-05-15 09:19:49 -05:00
|
|
|
std::chrono::steady_clock::time_point _startTime;
|
2016-09-21 17:47:00 -05:00
|
|
|
TileDesc _tile;
|
2016-04-25 04:04:25 -05:00
|
|
|
};
|
2016-04-15 10:24:00 -05:00
|
|
|
|
2020-08-07 11:36:56 -05:00
|
|
|
size_t TileCache::countTilesBeingRenderedForSession(const std::shared_ptr<ClientSession>& session,
|
|
|
|
const std::chrono::steady_clock::time_point &now)
|
2019-03-02 12:26:08 -06:00
|
|
|
{
|
|
|
|
size_t count = 0;
|
2020-07-12 11:25:49 -05:00
|
|
|
for (auto& it : _tilesBeingRendered)
|
2019-03-02 12:26:08 -06:00
|
|
|
{
|
2020-08-07 11:36:56 -05:00
|
|
|
if (it.second->isStale(&now))
|
|
|
|
continue;
|
|
|
|
|
2020-07-12 11:25:49 -05:00
|
|
|
for (auto& s : it.second->getSubscribers())
|
|
|
|
{
|
2019-03-02 12:26:08 -06:00
|
|
|
if (s.lock() == session)
|
2020-07-12 11:25:49 -05:00
|
|
|
++count;
|
2019-03-02 12:26:08 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-12 11:25:49 -05:00
|
|
|
return count;
|
2019-02-15 14:55:47 -06:00
|
|
|
}
|
2016-04-15 10:24:00 -05:00
|
|
|
|
2020-08-07 11:36:56 -05:00
|
|
|
bool TileCache::hasTileBeingRendered(const TileDesc& tileDesc, const std::chrono::steady_clock::time_point *now) const
|
|
|
|
{
|
|
|
|
const auto it = _tilesBeingRendered.find(tileDesc);
|
|
|
|
if (it == _tilesBeingRendered.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/// did we stall ? if so re-issue.
|
|
|
|
return !now ? true : !it->second->isStale(now);
|
|
|
|
}
|
|
|
|
|
2019-02-15 14:55:47 -06:00
|
|
|
std::shared_ptr<TileCache::TileBeingRendered> TileCache::findTileBeingRendered(const TileDesc& tileDesc)
|
|
|
|
{
|
2023-05-17 05:34:26 -05:00
|
|
|
ASSERT_CORRECT_THREAD_OWNER(_owner);
|
2016-04-15 10:24:00 -05:00
|
|
|
|
2019-02-15 14:55:47 -06:00
|
|
|
const auto tile = _tilesBeingRendered.find(tileDesc);
|
2017-03-30 04:15:28 -05:00
|
|
|
return tile != _tilesBeingRendered.end() ? tile->second : nullptr;
|
2016-04-15 10:24:00 -05:00
|
|
|
}
|
|
|
|
|
2022-06-16 10:31:37 -05:00
|
|
|
void TileCache::forgetTileBeingRendered(const TileDesc &descForKitReply,
|
|
|
|
const std::shared_ptr<TileCache::TileBeingRendered>& tileBeingRendered)
|
2016-04-15 10:24:00 -05:00
|
|
|
{
|
2023-05-17 05:34:26 -05:00
|
|
|
ASSERT_CORRECT_THREAD_OWNER(_owner);
|
2018-07-23 09:09:55 -05:00
|
|
|
assert(tileBeingRendered);
|
2020-07-12 11:25:49 -05:00
|
|
|
assert(hasTileBeingRendered(tileBeingRendered->getTile()));
|
2016-04-15 10:24:00 -05:00
|
|
|
|
2022-06-16 10:31:37 -05:00
|
|
|
if (tileBeingRendered->getVersion() <= descForKitReply.getVersion())
|
|
|
|
{
|
|
|
|
LOG_TRC("Removing all subscribers for " << tileBeingRendered->getTile().serialize());
|
|
|
|
_tilesBeingRendered.erase(tileBeingRendered->getTile());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
LOG_TRC("Racing renderings for tile " << tileBeingRendered->getTile().serialize() <<
|
|
|
|
" waiting for ver " << tileBeingRendered->getVersion() << " but have " << descForKitReply.getVersion());
|
2016-03-26 06:50:13 -05:00
|
|
|
}
|
|
|
|
|
2018-09-26 15:15:26 -05:00
|
|
|
int TileCache::getTileBeingRenderedVersion(const TileDesc& tile)
|
|
|
|
{
|
|
|
|
std::shared_ptr<TileBeingRendered> tileBeingRendered = findTileBeingRendered(tile);
|
2020-07-12 11:25:49 -05:00
|
|
|
return tileBeingRendered ? tileBeingRendered->getVersion() : 0;
|
2018-09-26 15:15:26 -05:00
|
|
|
}
|
|
|
|
|
2021-11-13 05:49:35 -06:00
|
|
|
Tile TileCache::lookupTile(const TileDesc& tile)
|
2015-03-12 09:18:35 -05:00
|
|
|
{
|
2019-02-14 15:40:33 -06:00
|
|
|
if (_dontCache)
|
2021-11-13 05:49:35 -06:00
|
|
|
return Tile();
|
2018-07-04 23:07:43 -05:00
|
|
|
|
2021-11-13 05:49:35 -06:00
|
|
|
Tile ret = findTile(tile);
|
2015-03-12 09:18:35 -05:00
|
|
|
|
2022-08-30 00:27:44 -05:00
|
|
|
UnitWSD::get().lookupTile(tile.getPart(), tile.getEditMode(),
|
|
|
|
tile.getWidth(), tile.getHeight(),
|
2016-05-15 17:47:08 -05:00
|
|
|
tile.getTilePosX(), tile.getTilePosY(),
|
2021-11-13 05:49:35 -06:00
|
|
|
tile.getTileWidth(), tile.getTileHeight(), ret);
|
2018-06-15 09:28:55 -05:00
|
|
|
|
2019-02-14 13:01:43 -06:00
|
|
|
return ret;
|
2015-03-12 09:18:35 -05:00
|
|
|
}
|
|
|
|
|
2022-03-25 13:32:01 -05:00
|
|
|
void TileCache::saveTileAndNotify(const TileDesc& desc, const char *data, const size_t size)
|
2015-03-12 09:18:35 -05:00
|
|
|
{
|
2023-05-17 05:34:26 -05:00
|
|
|
ASSERT_CORRECT_THREAD_OWNER(_owner);
|
2015-06-24 15:05:49 -05:00
|
|
|
|
2022-03-25 13:32:01 -05:00
|
|
|
std::shared_ptr<TileBeingRendered> tileBeingRendered = findTileBeingRendered(desc);
|
|
|
|
|
|
|
|
// Save to in-memory cache.
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
Tile tile = saveDataToCache(desc, data, size);
|
2023-01-25 14:37:32 -06:00
|
|
|
if (!_dontCache)
|
|
|
|
LOG_TRC("Saved cache tile: " << cacheFileName(desc) << " of size " << size << " bytes");
|
|
|
|
else
|
|
|
|
LOG_TRC("Got (non-cached) tile: " << cacheFileName(desc));
|
2016-05-22 14:20:24 -05:00
|
|
|
|
|
|
|
// Notify subscribers, if any.
|
|
|
|
if (tileBeingRendered)
|
|
|
|
{
|
2018-11-20 02:14:44 -06:00
|
|
|
const size_t subscriberCount = tileBeingRendered->getSubscribers().size();
|
2022-03-25 13:32:01 -05:00
|
|
|
|
|
|
|
// sendTile also does enqueueSendMessage underneath ...
|
2023-07-14 15:51:36 -05:00
|
|
|
if (tile && subscriberCount > 0)
|
2016-05-22 14:20:24 -05:00
|
|
|
{
|
2022-03-25 13:32:01 -05:00
|
|
|
for (size_t i = 0; i < subscriberCount; ++i)
|
2016-05-22 14:20:24 -05:00
|
|
|
{
|
2022-03-25 13:32:01 -05:00
|
|
|
auto& subscriber = tileBeingRendered->getSubscribers()[i];
|
|
|
|
std::shared_ptr<ClientSession> session = subscriber.lock();
|
|
|
|
if (session)
|
2023-06-27 11:31:25 -05:00
|
|
|
session->sendTileNow(desc, tile);
|
2016-05-22 14:20:24 -05:00
|
|
|
}
|
|
|
|
}
|
2020-08-07 12:37:53 -05:00
|
|
|
else if (subscriberCount == 0)
|
2022-03-25 13:32:01 -05:00
|
|
|
LOG_DBG("No subscribers for: " << cacheFileName(desc));
|
2020-08-07 12:37:53 -05:00
|
|
|
// else zero sized
|
2016-05-22 14:20:24 -05:00
|
|
|
|
|
|
|
// Remove subscriptions.
|
2022-06-16 10:31:37 -05:00
|
|
|
LOG_DBG("STATISTICS: tile " << desc.getVersion() << " internal roundtrip " <<
|
|
|
|
tileBeingRendered->getElapsedTimeMs());
|
|
|
|
forgetTileBeingRendered(desc, tileBeingRendered);
|
2016-05-22 14:20:24 -05:00
|
|
|
}
|
2016-09-20 20:40:28 -05:00
|
|
|
else
|
2022-03-25 13:32:01 -05:00
|
|
|
LOG_DBG("No subscribers for: " << cacheFileName(desc));
|
2015-03-12 18:34:42 -05:00
|
|
|
}
|
|
|
|
|
2019-02-15 14:55:47 -06:00
|
|
|
bool TileCache::getTextStream(StreamType type, const std::string& fileName, std::string& content)
|
2015-03-13 07:17:51 -05:00
|
|
|
{
|
2021-11-08 13:48:14 -06:00
|
|
|
Blob textStream = lookupCachedStream(type, fileName);
|
2019-02-14 15:40:33 -06:00
|
|
|
if (!textStream)
|
2016-03-26 07:06:39 -05:00
|
|
|
{
|
2021-11-24 08:08:41 -06:00
|
|
|
// This is not an error because the first time
|
|
|
|
// we lookup a file, it won't be in the cache.
|
|
|
|
LOG_INF("Could not open " << fileName);
|
2017-01-17 09:42:31 -06:00
|
|
|
return false;
|
2016-03-26 07:06:39 -05:00
|
|
|
}
|
2015-03-16 14:08:07 -05:00
|
|
|
|
2019-02-14 15:40:33 -06:00
|
|
|
std::vector<char> buffer = *textStream;
|
2015-03-13 07:17:51 -05:00
|
|
|
|
2020-07-12 11:25:49 -05:00
|
|
|
if (!buffer.empty() && buffer.back() == '\n')
|
2016-04-22 06:00:11 -05:00
|
|
|
buffer.pop_back();
|
|
|
|
|
2017-01-17 09:42:31 -06:00
|
|
|
content = std::string(buffer.data(), buffer.size());
|
2021-11-18 06:08:14 -06:00
|
|
|
LOG_INF("Read '" << COOLProtocol::getAbbreviatedMessage(content.c_str(), content.size()) <<
|
2019-02-14 15:40:33 -06:00
|
|
|
"' from " << fileName);
|
2015-03-16 14:08:07 -05:00
|
|
|
|
2017-01-17 09:42:31 -06:00
|
|
|
return true;
|
2015-03-13 07:17:51 -05:00
|
|
|
}
|
|
|
|
|
2022-06-05 17:37:03 -05:00
|
|
|
void TileCache::saveTextStream(StreamType type, const std::string& fileName,
|
|
|
|
const std::vector<char>& data)
|
2015-06-24 15:05:49 -05:00
|
|
|
{
|
2022-06-05 17:37:03 -05:00
|
|
|
LOG_INF("Saving '" << COOLProtocol::getAbbreviatedMessage(data.data(), data.size()) << "' to " << fileName
|
|
|
|
<< " of size " << data.size() << " bytes");
|
2015-06-24 15:05:49 -05:00
|
|
|
|
2022-06-05 17:37:03 -05:00
|
|
|
saveDataToStreamCache(type, fileName, data.data(), data.size());
|
2015-06-24 15:05:49 -05:00
|
|
|
}
|
|
|
|
|
2019-02-15 14:55:47 -06:00
|
|
|
void TileCache::saveStream(StreamType type, const std::string& name, const char *data, std::size_t size)
|
2015-11-27 08:12:44 -06:00
|
|
|
{
|
|
|
|
// can fonts be invalidated?
|
2019-02-15 14:55:47 -06:00
|
|
|
saveDataToStreamCache(type, name, data, size);
|
2015-11-27 08:12:44 -06:00
|
|
|
}
|
|
|
|
|
2021-11-13 05:49:35 -06:00
|
|
|
Blob TileCache::lookupCachedStream(StreamType type, const std::string& name)
|
2015-11-27 08:12:44 -06:00
|
|
|
{
|
2019-02-15 14:55:47 -06:00
|
|
|
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;
|
|
|
|
}
|
2020-07-12 11:25:49 -05:00
|
|
|
|
2021-11-13 05:49:35 -06:00
|
|
|
return Blob();
|
2015-11-27 08:12:44 -06:00
|
|
|
}
|
|
|
|
|
2022-08-30 00:27:44 -05:00
|
|
|
void TileCache::invalidateTiles(int part, int mode, int x, int y, int width, int height, int normalizedViewId)
|
2015-05-28 10:39:05 -05:00
|
|
|
{
|
2022-08-30 00:27:44 -05:00
|
|
|
LOG_TRC("Removing invalidated tiles: part: " << part << ", mode: " << mode <<
|
2017-03-11 13:42:50 -06:00
|
|
|
", x: " << x << ", y: " << y <<
|
|
|
|
", width: " << width <<
|
2022-03-25 13:32:01 -05:00
|
|
|
", height: " << height <<
|
|
|
|
", viewid: " << normalizedViewId);
|
2016-04-14 19:08:25 -05:00
|
|
|
|
2023-05-17 05:34:26 -05:00
|
|
|
ASSERT_CORRECT_THREAD_OWNER(_owner);
|
2016-05-22 13:31:18 -05:00
|
|
|
|
2019-02-14 15:40:33 -06:00
|
|
|
for (auto it = _cache.begin(); it != _cache.end();)
|
2015-05-28 10:39:05 -05:00
|
|
|
{
|
2022-08-30 00:27:44 -05:00
|
|
|
if (intersectsTile(it->first, part, mode, x, y, width, height, normalizedViewId))
|
2022-03-25 13:32:01 -05:00
|
|
|
{
|
|
|
|
// FIXME: only want to keep as invalid keyframes in the view area(s)
|
|
|
|
it->second->invalidate();
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
#if 0
|
2015-05-28 10:39:05 -05:00
|
|
|
{
|
2019-04-22 11:03:49 -05:00
|
|
|
LOG_TRC("Removing tile: " << it->first.serialize());
|
2019-10-28 08:26:15 -05:00
|
|
|
_cacheSize -= itemCacheSize(it->second);
|
2019-02-14 15:40:33 -06:00
|
|
|
it = _cache.erase(it);
|
2015-05-28 10:39:05 -05:00
|
|
|
}
|
2022-03-25 13:32:01 -05:00
|
|
|
#endif
|
2019-02-14 15:40:33 -06:00
|
|
|
else
|
2020-07-12 11:25:49 -05:00
|
|
|
{
|
2019-02-14 15:40:33 -06:00
|
|
|
++it;
|
2020-07-12 11:25:49 -05:00
|
|
|
}
|
2015-05-28 10:39:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-15 07:35:35 -05:00
|
|
|
void TileCache::invalidateTiles(const std::string& tiles, int normalizedViewId)
|
2018-05-31 13:20:09 -05:00
|
|
|
{
|
2023-07-06 06:08:59 -05:00
|
|
|
int part = 0, mode = 0;
|
|
|
|
TileWireId wireId = 0;
|
|
|
|
const Util::Rectangle invalidateRect = TileCache::parseInvalidateMsg(tiles, part, mode, wireId);
|
|
|
|
|
2022-08-30 00:27:44 -05:00
|
|
|
invalidateTiles(part, mode, invalidateRect.getLeft(), invalidateRect.getTop(),
|
2020-07-12 11:25:49 -05:00
|
|
|
invalidateRect.getWidth(), invalidateRect.getHeight(), normalizedViewId);
|
2018-05-31 13:20:09 -05:00
|
|
|
}
|
|
|
|
|
2023-07-06 06:08:59 -05:00
|
|
|
Util::Rectangle TileCache::parseInvalidateMsg(const std::string& tiles, int &part, int &mode, TileWireId &wireId)
|
2015-05-28 10:39:05 -05:00
|
|
|
{
|
2022-03-29 20:37:57 -05:00
|
|
|
StringVector tokens = StringVector::tokenize(tiles);
|
2015-05-28 10:39:05 -05:00
|
|
|
|
2020-07-12 11:25:49 -05:00
|
|
|
assert(!tokens.empty() && tokens.equals(0, "invalidatetiles:"));
|
2015-05-28 10:39:05 -05:00
|
|
|
|
2023-07-06 06:08:59 -05:00
|
|
|
mode = 0;
|
|
|
|
part = 0;
|
|
|
|
wireId = 0;
|
2020-03-09 03:05:30 -05:00
|
|
|
if (tokens.size() == 2 && tokens.equals(1, "EMPTY"))
|
2015-05-29 00:39:21 -05:00
|
|
|
{
|
2023-07-06 06:08:59 -05:00
|
|
|
part = -1;
|
|
|
|
return Util::Rectangle(0, 0, INT_MAX, INT_MAX);
|
2016-10-20 09:58:58 -05:00
|
|
|
}
|
2023-07-06 06:08:59 -05:00
|
|
|
else if (tokens.size() == 3 && tokens.equals(1, "EMPTY,"))
|
2016-10-20 09:58:58 -05:00
|
|
|
{
|
2023-07-06 06:08:59 -05:00
|
|
|
part = -1;
|
|
|
|
if (!tokens.getUInt32(2, "wid", wireId))
|
|
|
|
assert(false && "missing wid");
|
|
|
|
return Util::Rectangle(0, 0, INT_MAX, INT_MAX);
|
2022-08-30 00:27:44 -05:00
|
|
|
}
|
|
|
|
else if (tokens.size() == 4 && tokens.equals(1, "EMPTY,"))
|
2023-07-06 06:08:59 -05:00
|
|
|
{
|
|
|
|
if (stringToInteger(tokens[2], part))
|
|
|
|
{
|
|
|
|
if (!tokens.getUInt32(3, "wid", wireId))
|
|
|
|
assert(false && "missing wid");
|
|
|
|
return Util::Rectangle(0, 0, INT_MAX, INT_MAX);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (tokens.size() == 5 && tokens.equals(1, "EMPTY,"))
|
2022-08-30 00:27:44 -05:00
|
|
|
{
|
|
|
|
if (stringToInteger(tokens[2], part))
|
|
|
|
{
|
|
|
|
if (stringToInteger(tokens[3], mode))
|
|
|
|
{
|
2023-07-06 06:08:59 -05:00
|
|
|
if (!tokens.getUInt32(4, "wid", wireId))
|
|
|
|
assert(false && "missing wid");
|
|
|
|
return Util::Rectangle(0, 0, INT_MAX, INT_MAX);
|
2022-08-30 00:27:44 -05:00
|
|
|
}
|
|
|
|
}
|
2015-05-29 00:39:21 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-01 05:27:58 -06:00
|
|
|
int x = 0;
|
|
|
|
int y = 0;
|
|
|
|
int width = 0;
|
|
|
|
int height = 0;
|
2023-07-06 06:08:59 -05:00
|
|
|
if (tokens.size() == 7 &&
|
2016-10-02 14:30:59 -05:00
|
|
|
getTokenInteger(tokens[1], "part", part) &&
|
2021-12-08 01:52:16 -06:00
|
|
|
getNonNegTokenInteger(tokens[2], "x", x) &&
|
|
|
|
getNonNegTokenInteger(tokens[3], "y", y) &&
|
|
|
|
getNonNegTokenInteger(tokens[4], "width", width) &&
|
2023-07-06 06:08:59 -05:00
|
|
|
getNonNegTokenInteger(tokens[5], "height", height) &&
|
|
|
|
tokens.getUInt32(6, "wid", wireId))
|
2015-07-21 06:53:53 -05:00
|
|
|
{
|
2023-07-06 06:08:59 -05:00
|
|
|
return Util::Rectangle(x, y, width, height);
|
2022-08-30 00:27:44 -05:00
|
|
|
}
|
2023-07-06 06:08:59 -05:00
|
|
|
else if (tokens.size() == 8 &&
|
2022-08-30 00:27:44 -05:00
|
|
|
getTokenInteger(tokens[1], "part", part) &&
|
|
|
|
getTokenInteger(tokens[2], "mode", mode) &&
|
|
|
|
getNonNegTokenInteger(tokens[3], "x", x) &&
|
|
|
|
getNonNegTokenInteger(tokens[4], "y", y) &&
|
|
|
|
getNonNegTokenInteger(tokens[5], "width", width) &&
|
2023-07-06 06:08:59 -05:00
|
|
|
getNonNegTokenInteger(tokens[6], "height", height) &&
|
|
|
|
tokens.getUInt32(7, "wid", wireId))
|
2022-08-30 00:27:44 -05:00
|
|
|
{
|
2023-07-06 06:08:59 -05:00
|
|
|
return Util::Rectangle(x, y, width, height);
|
2016-10-02 14:30:59 -05:00
|
|
|
}
|
2015-05-29 00:39:21 -05:00
|
|
|
}
|
2016-10-20 09:58:58 -05:00
|
|
|
|
2016-11-29 21:59:47 -06:00
|
|
|
LOG_ERR("Unexpected invalidatetiles request [" << tiles << "].");
|
2023-07-06 06:08:59 -05:00
|
|
|
assert(false && "Unexpected invalidatetiles request");
|
|
|
|
part = -1;
|
|
|
|
return Util::Rectangle(0, 0, 0, 0);
|
2015-05-28 10:39:05 -05:00
|
|
|
}
|
|
|
|
|
2016-05-15 17:47:08 -05:00
|
|
|
std::string TileCache::cacheFileName(const TileDesc& tile)
|
2015-03-12 18:34:42 -05:00
|
|
|
{
|
2016-03-26 08:16:23 -05:00
|
|
|
std::ostringstream oss;
|
2022-08-30 00:27:44 -05:00
|
|
|
oss << tile.getNormalizedViewId() << '_' << tile.getPart() << '_' << tile.getEditMode() << '_'
|
|
|
|
<< tile.getWidth() << 'x' << tile.getHeight() << '.'
|
2016-05-15 17:47:08 -05:00
|
|
|
<< tile.getTilePosX() << ',' << tile.getTilePosY() << '.'
|
|
|
|
<< tile.getTileWidth() << 'x' << tile.getTileHeight() << ".png";
|
2016-03-26 08:16:23 -05:00
|
|
|
return oss.str();
|
2015-03-12 18:34:42 -05:00
|
|
|
}
|
|
|
|
|
2022-08-30 00:27:44 -05:00
|
|
|
bool TileCache::parseCacheFileName(const std::string& fileName, int& part, int& mode, int& width, int& height,
|
2020-07-12 11:25:49 -05:00
|
|
|
int& tilePosX, int& tilePosY, int& tileWidth, int& tileHeight,
|
|
|
|
int& nviewid)
|
2015-05-28 10:39:05 -05:00
|
|
|
{
|
2022-08-30 00:27:44 -05:00
|
|
|
return std::sscanf(fileName.c_str(), "%d_%d_%d_%dx%d.%d,%d.%dx%d.png", &nviewid, &part, &mode,
|
|
|
|
&width, &height, &tilePosX, &tilePosY, &tileWidth, &tileHeight)
|
2020-07-12 11:25:49 -05:00
|
|
|
== 8;
|
2015-06-24 15:05:49 -05:00
|
|
|
}
|
|
|
|
|
2022-08-30 00:27:44 -05:00
|
|
|
bool TileCache::intersectsTile(const TileDesc &tileDesc, int part, int mode, int x, int y, int width, int height, int normalizedViewId)
|
2015-06-24 15:05:49 -05:00
|
|
|
{
|
2019-02-15 14:55:47 -06:00
|
|
|
if (part != -1 && tileDesc.getPart() != part)
|
|
|
|
return false;
|
2015-06-24 15:05:49 -05:00
|
|
|
|
2022-08-30 00:27:44 -05:00
|
|
|
if (mode != tileDesc.getEditMode())
|
|
|
|
return false;
|
|
|
|
|
2019-10-15 07:35:35 -05:00
|
|
|
if (normalizedViewId != tileDesc.getNormalizedViewId())
|
|
|
|
return false;
|
|
|
|
|
2019-02-15 14:55:47 -06:00
|
|
|
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());
|
2015-06-24 15:05:49 -05:00
|
|
|
|
2019-02-15 14:55:47 -06:00
|
|
|
return left <= right && top <= bottom;
|
2015-05-28 10:39:05 -05:00
|
|
|
}
|
|
|
|
|
2016-04-25 04:04:25 -05:00
|
|
|
// FIXME: to be further simplified when we centralize tile messages.
|
2020-08-07 11:36:56 -05:00
|
|
|
void TileCache::subscribeToTileRendering(const TileDesc& tile, const std::shared_ptr<ClientSession>& subscriber,
|
|
|
|
const std::chrono::steady_clock::time_point &now)
|
2016-04-23 11:11:11 -05:00
|
|
|
{
|
2023-05-17 05:34:26 -05:00
|
|
|
ASSERT_CORRECT_THREAD_OWNER(_owner);
|
2016-10-30 14:24:27 -05:00
|
|
|
|
|
|
|
std::shared_ptr<TileBeingRendered> tileBeingRendered = findTileBeingRendered(tile);
|
|
|
|
|
2016-04-23 11:11:11 -05:00
|
|
|
if (tileBeingRendered)
|
|
|
|
{
|
2020-08-07 11:36:56 -05:00
|
|
|
if (tileBeingRendered->isStale(&now))
|
|
|
|
LOG_DBG("Painting stalled; need to re-issue on tile " << tile.debugName());
|
|
|
|
|
2018-11-20 02:14:44 -06:00
|
|
|
for (const auto &s : tileBeingRendered->getSubscribers())
|
2016-04-25 04:04:25 -05:00
|
|
|
{
|
|
|
|
if (s.lock().get() == subscriber.get())
|
|
|
|
{
|
wsd: reduce debug and generally redundant logs
In 'debug' log-level we expect a detailed, but
still readable output. Having one area with
disproportionately large number of logs reduces
the overall utility of the log output.
This patch reduces a number of redundant log
entries, including errors that are already
logged. It also reduces the level of some
others from 'information' to 'debug' and
from 'debug' to 'trace'.
The goal is to make 'debug' level as useful as
possible to read the progress and be able to
understand what was going on, such that one is
able to decide which area to dig deeper into.
Then, trace level could be used to get more
insight into that area, if necessary. For
example, when investigating a test failure,
one first enables 'debug' logs and reads through.
Once a section between two debug entries is
identified as being of interest, enabling 'trace'
level logs becomes more productive as it's
now possible to easily reach the first DBG
entry and read through until the second one.
It's unfortunate that we don't have per-area
control for enabling/disabling logs, so it
is common to see more and more 'debug' log
entries added all around, making logs
less and less readable.
It is also a limitation of the levels we have
that we really only have 3 usable levels:
one, two, many. That is, 'information' for
the most important events, 'debug' for
technical details needed to investigate issues,
and 'trace' for everything else. ('warning'
and 'error' aren't really 'levels'; they have
semantics that makes them special-cases.)
So we have to avoid degrading one into the
other, or have differences without distinction.
If any of these entries are needed to be
displayed more frequently, changing them
back to 'debug' or even 'information' should
be done. Though for me they seem special
cases that don't benefit most log readings.
Change-Id: Id2c6a9dc027483b81a066b0b4b50a298c5eff449
Signed-off-by: Ashod Nakashian <ashod.nakashian@collabora.co.uk>
2022-02-19 07:30:26 -06:00
|
|
|
LOG_TRC("Redundant request to subscribe on tile " << tile.debugName());
|
2022-06-16 10:31:37 -05:00
|
|
|
// the version stops us unsubscribing when we get there.
|
2016-09-21 17:48:14 -05:00
|
|
|
tileBeingRendered->setVersion(tile.getVersion());
|
2016-09-25 15:04:27 -05:00
|
|
|
return;
|
2016-04-25 04:04:25 -05:00
|
|
|
}
|
|
|
|
}
|
2016-09-19 19:51:10 -05:00
|
|
|
|
2020-08-07 11:36:56 -05:00
|
|
|
LOG_DBG("Subscribing " << subscriber->getName() << " to tile " << tile.debugName() << " which has " <<
|
2018-11-20 02:14:44 -06:00
|
|
|
tileBeingRendered->getSubscribers().size() << " subscribers already.");
|
|
|
|
tileBeingRendered->getSubscribers().push_back(subscriber);
|
2016-04-23 11:11:11 -05:00
|
|
|
}
|
2016-04-25 04:04:25 -05:00
|
|
|
else
|
|
|
|
{
|
2020-08-07 11:36:56 -05:00
|
|
|
LOG_DBG("Subscribing " << subscriber->getName() << " to tile " << tile.debugName() <<
|
2019-02-15 14:55:47 -06:00
|
|
|
" ver=" << tile.getVersion() << " which has no subscribers " << tile.serialize());
|
2016-05-04 21:05:09 -05:00
|
|
|
|
2019-02-15 14:55:47 -06:00
|
|
|
assert(_tilesBeingRendered.find(tile) == _tilesBeingRendered.end());
|
2016-04-23 11:11:11 -05:00
|
|
|
|
2020-08-07 11:36:56 -05:00
|
|
|
tileBeingRendered = std::make_shared<TileBeingRendered>(tile, now);
|
2018-11-20 02:14:44 -06:00
|
|
|
tileBeingRendered->getSubscribers().push_back(subscriber);
|
2019-02-15 14:55:47 -06:00
|
|
|
_tilesBeingRendered[tile] = tileBeingRendered;
|
2016-04-25 04:04:25 -05:00
|
|
|
}
|
2016-04-23 11:11:11 -05:00
|
|
|
}
|
|
|
|
|
2021-11-13 05:49:35 -06:00
|
|
|
Tile TileCache::findTile(const TileDesc &desc)
|
2019-02-14 15:40:33 -06:00
|
|
|
{
|
2020-07-12 11:25:49 -05:00
|
|
|
const auto it = _cache.find(desc);
|
|
|
|
if (it != _cache.end() && it->first.getNormalizedViewId() == desc.getNormalizedViewId())
|
2019-02-14 15:40:33 -06:00
|
|
|
{
|
2021-11-08 13:48:14 -06:00
|
|
|
LOG_TRC("Found cache tile: " << desc.serialize() << " of size " << it->second);
|
2020-07-12 11:25:49 -05:00
|
|
|
return it->second;
|
2019-02-14 15:40:33 -06:00
|
|
|
}
|
2020-07-12 11:25:49 -05:00
|
|
|
|
2021-11-13 05:49:35 -06:00
|
|
|
return Tile();
|
2019-02-14 15:40:33 -06:00
|
|
|
}
|
|
|
|
|
2022-03-25 13:32:01 -05:00
|
|
|
Tile TileCache::saveDataToCache(const TileDesc &desc, const char *data, const size_t size)
|
2019-02-15 14:55:47 -06:00
|
|
|
{
|
|
|
|
if (_dontCache)
|
2022-06-16 12:11:58 -05:00
|
|
|
return std::make_shared<TileData>(desc.getWireId(), data, size);
|
2019-02-15 14:55:47 -06:00
|
|
|
|
2019-10-28 08:26:15 -05:00
|
|
|
ensureCacheSize();
|
|
|
|
|
2022-03-25 13:32:01 -05:00
|
|
|
Tile tile = _cache[desc];
|
|
|
|
if (!tile)
|
2019-10-28 08:26:15 -05:00
|
|
|
{
|
2022-06-16 12:11:58 -05:00
|
|
|
if (!TileData::isKeyframe(data, size))
|
|
|
|
{
|
|
|
|
// canceltiles removes all subscribers - which allows the
|
|
|
|
// TileCache re-balancing to remove the in-process delta's
|
|
|
|
// underlying keyframe.
|
|
|
|
LOG_TRC("rare race between canceltiles and delta rendering - "
|
|
|
|
"discarding delta for " << desc.serialize());
|
|
|
|
_cache.erase(desc);
|
|
|
|
return Tile();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LOG_TRC("new tile for " << desc.serialize() << " of size " << size);
|
|
|
|
tile = std::make_shared<TileData>(desc.getWireId(), data, size);
|
|
|
|
_cache[desc] = tile;
|
|
|
|
_cacheSize += itemCacheSize(tile);
|
|
|
|
}
|
2022-03-25 13:32:01 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LOG_TRC("append blob to " << desc.serialize() << " of size " << size);
|
|
|
|
_cacheSize += tile->appendBlob(desc.getWireId(), data, size);
|
2019-10-28 08:26:15 -05:00
|
|
|
}
|
2022-03-25 13:32:01 -05:00
|
|
|
|
|
|
|
return tile;
|
2019-10-28 08:26:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t TileCache::itemCacheSize(const Tile &tile)
|
|
|
|
{
|
2021-11-08 13:48:14 -06:00
|
|
|
return sizeof(Tile) + sizeof(TileDesc) + tile->size();
|
2019-10-28 08:26:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void TileCache::assertCacheSize()
|
|
|
|
{
|
2020-12-10 03:39:43 -06:00
|
|
|
#if ENABLE_DEBUG
|
2020-07-12 11:25:49 -05:00
|
|
|
size_t recalcSize = 0;
|
|
|
|
for (const auto& it : _cache)
|
2019-10-28 08:26:15 -05:00
|
|
|
{
|
2020-07-12 11:25:49 -05:00
|
|
|
recalcSize += itemCacheSize(it.second);
|
2019-10-28 08:26:15 -05:00
|
|
|
}
|
2020-07-12 11:25:49 -05:00
|
|
|
assert(recalcSize == _cacheSize);
|
2019-10-28 08:26:15 -05:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void TileCache::ensureCacheSize()
|
|
|
|
{
|
|
|
|
assertCacheSize();
|
|
|
|
|
|
|
|
if (_cacheSize < _maxCacheSize || _cache.size() < 2)
|
|
|
|
return;
|
|
|
|
|
|
|
|
LOG_TRC("Cleaning tile cache of size " << _cacheSize << " vs. " << _maxCacheSize <<
|
|
|
|
" with " << _cache.size() << " entries");
|
|
|
|
|
|
|
|
struct WidSize {
|
|
|
|
TileWireId _wid;
|
|
|
|
size_t _size;
|
|
|
|
WidSize(TileWireId w, size_t s) : _wid(w), _size(s) {}
|
|
|
|
};
|
|
|
|
std::vector<WidSize> wids;
|
2020-06-09 21:24:13 -05:00
|
|
|
for (const auto& it : _cache)
|
|
|
|
wids.emplace_back(it.first.getWireId(), itemCacheSize(it.second));
|
2020-07-12 11:25:49 -05:00
|
|
|
|
2019-10-28 08:26:15 -05:00
|
|
|
std::sort(wids.begin(), wids.end(),
|
|
|
|
[](const WidSize &a, const WidSize &b) { return a._wid < b._wid; });
|
|
|
|
|
2019-10-28 17:11:21 -05:00
|
|
|
// FIXME: should we just take a wid 25% into the list ?
|
|
|
|
TileWireId maxToRemove = wids.front()._wid;
|
|
|
|
|
2019-10-28 08:26:15 -05:00
|
|
|
// do we have (the very rare) WID wrap-around
|
2020-07-12 11:25:49 -05:00
|
|
|
if (wids.back()._wid - wids.front()._wid > 256 * 256 * 256)
|
|
|
|
{
|
2019-10-28 08:26:15 -05:00
|
|
|
maxToRemove = wids.back()._wid;
|
2022-06-16 08:42:40 -05:00
|
|
|
LOG_TRC("Rare wid wrap-around detected, clear tile cache");
|
2020-07-12 11:25:49 -05:00
|
|
|
}
|
2019-10-28 08:26:15 -05:00
|
|
|
else
|
|
|
|
{
|
2020-07-12 11:25:49 -05:00
|
|
|
// calculate which wid to start at.
|
2019-10-28 08:26:15 -05:00
|
|
|
size_t total = 0;
|
2020-07-12 11:25:49 -05:00
|
|
|
for (const auto &it : wids)
|
2019-10-28 08:26:15 -05:00
|
|
|
{
|
|
|
|
total += it._size;
|
|
|
|
maxToRemove = it._wid;
|
2020-07-12 11:25:49 -05:00
|
|
|
if (total > _maxCacheSize / 4)
|
2019-10-28 08:26:15 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LOG_TRC("cleaning up to wid " << maxToRemove << " between " <<
|
|
|
|
wids.front()._wid << " and " << wids.back()._wid);
|
|
|
|
|
|
|
|
for (auto it = _cache.begin(); it != _cache.end();)
|
|
|
|
{
|
|
|
|
if (it->first.getWireId() <= maxToRemove)
|
|
|
|
{
|
2022-06-16 08:42:40 -05:00
|
|
|
auto rit = _tilesBeingRendered.find(it->first);
|
|
|
|
if (rit != _tilesBeingRendered.end())
|
|
|
|
{
|
|
|
|
// avoid getting a delta instead of a keyframe at the bottom.
|
|
|
|
LOG_TRC("skip cleaning tile we are waiting on: " << it->first.serialize() <<
|
|
|
|
" which has " << rit->second->getSubscribers().size() << " waiting");
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LOG_TRC("cleaned out tile: " << it->first.serialize());
|
|
|
|
_cacheSize -= itemCacheSize(it->second);
|
|
|
|
it = _cache.erase(it);
|
|
|
|
}
|
2019-10-28 08:26:15 -05:00
|
|
|
}
|
|
|
|
else
|
2020-07-12 11:25:49 -05:00
|
|
|
{
|
2019-10-28 08:26:15 -05:00
|
|
|
++it;
|
2020-07-12 11:25:49 -05:00
|
|
|
}
|
2019-10-28 08:26:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
LOG_TRC("Cache is now of size " << _cacheSize << " and " <<
|
|
|
|
_cache.size() << " entries after cleaning");
|
|
|
|
|
|
|
|
assertCacheSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TileCache::setMaxCacheSize(size_t cacheSize)
|
|
|
|
{
|
|
|
|
_maxCacheSize = cacheSize;
|
|
|
|
ensureCacheSize();
|
2019-02-15 14:55:47 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void TileCache::saveDataToStreamCache(StreamType type, const std::string &fileName, const char *data, const size_t size)
|
|
|
|
{
|
|
|
|
if (_dontCache)
|
|
|
|
return;
|
|
|
|
|
2021-11-13 05:49:35 -06:00
|
|
|
Blob blob = std::make_shared<BlobData>(size);
|
2021-11-08 13:48:14 -06:00
|
|
|
std::memcpy(blob->data(), data, size);
|
|
|
|
_streamCache[type][fileName] = blob;
|
2019-02-15 14:55:47 -06:00
|
|
|
}
|
|
|
|
|
2019-03-05 00:15:50 -06:00
|
|
|
void TileCache::TileBeingRendered::dumpState(std::ostream& os)
|
|
|
|
{
|
2020-12-06 21:45:46 -06:00
|
|
|
os << " " << _tile.serialize() << ' ' << std::setw(4) << getElapsedTimeMs()
|
|
|
|
<< _subscribers.size() << " subscribers\n";
|
2019-03-08 01:37:14 -06:00
|
|
|
for (const auto& it : _subscribers)
|
2019-03-05 00:15:50 -06:00
|
|
|
{
|
|
|
|
std::shared_ptr<ClientSession> session = it.lock();
|
2020-04-19 13:46:01 -05:00
|
|
|
if (session)
|
2020-07-12 11:25:49 -05:00
|
|
|
{
|
2020-04-19 13:46:01 -05:00
|
|
|
os << " " << session->getId() << ' ' << session->getUserId() << ' '
|
|
|
|
<< session->getName() << '\n';
|
2020-07-12 11:25:49 -05:00
|
|
|
}
|
2019-03-05 00:15:50 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-15 13:42:00 -06:00
|
|
|
void TileCache::dumpState(std::ostream& os)
|
|
|
|
{
|
2022-02-14 06:08:27 -06:00
|
|
|
os << "\n TileCache:";
|
|
|
|
os << "\n num: " << _cache.size() << " size: " << _cacheSize << " bytes\n";
|
2019-10-28 08:26:15 -05:00
|
|
|
for (const auto& it : _cache)
|
2019-02-15 13:42:00 -06:00
|
|
|
{
|
2019-10-28 08:26:15 -05:00
|
|
|
os << " " << std::setw(4) << it.first.getWireId()
|
2020-05-24 08:10:18 -05:00
|
|
|
<< '\t' << std::setw(6) << it.second->size() << " bytes"
|
2022-03-25 13:32:01 -05:00
|
|
|
<< "\t'" << it.first.serialize() << " ";
|
|
|
|
it.second->dumpState(os);
|
|
|
|
os << "\n";
|
2019-02-15 13:42:00 -06:00
|
|
|
}
|
2019-02-15 14:55:47 -06:00
|
|
|
|
|
|
|
int type = 0;
|
2019-03-08 01:37:14 -06:00
|
|
|
for (const auto& i : _streamCache)
|
2019-02-15 13:42:00 -06:00
|
|
|
{
|
2020-07-12 11:25:49 -05:00
|
|
|
size_t num = 0;
|
|
|
|
size_t size = 0;
|
2019-03-08 01:37:14 -06:00
|
|
|
for (const auto& it : i)
|
2019-02-15 14:55:47 -06:00
|
|
|
{
|
2020-07-12 11:25:49 -05:00
|
|
|
num++;
|
|
|
|
size += it.second->size();
|
2019-02-15 14:55:47 -06:00
|
|
|
}
|
2020-07-12 11:25:49 -05:00
|
|
|
|
2022-02-14 06:08:27 -06:00
|
|
|
os << " stream cache: " << type++ << " num: " << num << " size: " << size << " bytes\n";
|
2019-03-08 01:37:14 -06:00
|
|
|
for (const auto& it : i)
|
2019-02-15 14:55:47 -06:00
|
|
|
{
|
|
|
|
os << " " << it.first
|
2020-05-24 08:10:18 -05:00
|
|
|
<< '\t' << std::setw(6) << it.second->size() << " bytes\n";
|
2019-02-15 14:55:47 -06:00
|
|
|
}
|
2019-02-15 13:42:00 -06:00
|
|
|
}
|
2019-03-05 00:15:50 -06:00
|
|
|
|
2022-02-14 06:08:27 -06:00
|
|
|
os << " tiles being rendered " << _tilesBeingRendered.size() << '\n';
|
2019-03-08 01:37:14 -06:00
|
|
|
for (const auto& it : _tilesBeingRendered)
|
2019-03-05 00:15:50 -06:00
|
|
|
it.second->dumpState(os);
|
2019-02-15 13:42:00 -06:00
|
|
|
}
|
|
|
|
|
2015-03-12 09:18:35 -05:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|