loolwsd: canceltiles re-designed using tilecache instead of queue

Change-Id: I4b9ba91ee08bc9dd8d27df275e303f5517d9740c
Reviewed-on: https://gerrit.libreoffice.org/28526
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
This commit is contained in:
Ashod Nakashian 2016-08-30 23:15:44 -04:00 committed by Ashod Nakashian
parent fad6715f7d
commit 571ff06906
8 changed files with 58 additions and 10 deletions

View file

@ -119,12 +119,6 @@ bool ChildSession::_handleInput(const char *buffer, int length)
// Just to update the activity of a view-only client.
return true;
}
else if (tokens[0] == "canceltiles")
{
// This command makes sense only on the command queue level.
// Shouldn't get this here.
return true;
}
else if (tokens[0] == "commandvalues")
{
return getCommandValues(buffer, length, tokens);

View file

@ -147,10 +147,7 @@ bool ClientSession::_handleInput(const char *buffer, int length)
}
else if (tokens[0] == "canceltiles")
{
if (!_peer.expired())
{
return forwardToPeer(_peer, buffer, length, false);
}
_docBroker->cancelTileRequests(shared_from_this());
}
else if (tokens[0] == "commandvalues")
{

View file

@ -613,6 +613,13 @@ void DocumentBroker::handleTileCombinedRequest(TileCombined& tileCombined,
}
}
void DocumentBroker::cancelTileRequests(const std::shared_ptr<ClientSession>& session)
{
std::unique_lock<std::mutex> lock(_mutex);
tileCache().cancelTiles(session);
}
void DocumentBroker::handleTileResponse(const std::vector<char>& payload)
{
const std::string firstLine = getFirstLine(payload);

View file

@ -214,6 +214,8 @@ public:
void handleTileCombinedRequest(TileCombined& tileCombined,
const std::shared_ptr<ClientSession>& session);
void cancelTileRequests(const std::shared_ptr<ClientSession>& session);
void handleTileResponse(const std::vector<char>& payload);
void handleTileCombinedResponse(const std::vector<char>& payload);

View file

@ -461,4 +461,26 @@ int TileCache::subscribeToTileRendering(const TileDesc& tile, const std::shared_
}
}
void TileCache::cancelTiles(const std::shared_ptr<ClientSession> &subscriber)
{
std::unique_lock<std::mutex> lock(_tilesBeingRenderedMutex);
const auto sub = subscriber.get();
Log::trace("Cancelling tiles for " + subscriber->getName());
for (auto it = _tilesBeingRendered.begin(); it != _tilesBeingRendered.end(); )
{
auto& subscribers = it->second->_subscribers;
Log::trace("Tile " + it->first + " has " + std::to_string(subscribers.size()) + " subscribers.");
subscribers.erase(std::remove_if(subscribers.begin(), subscribers.end(),
[sub](std::weak_ptr<ClientSession>& ptr){ return ptr.lock().get() == sub; }),
subscribers.end());
Log::trace(" Tile " + it->first + " has " + std::to_string(subscribers.size()) + " subscribers.");
// Remove if there are no more subscribers on this tile.
it = (subscribers.empty() ? _tilesBeingRendered.erase(it) : ++it);
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -42,6 +42,9 @@ public:
/// Otherwise returns 0 to signify a subscription exists.
int subscribeToTileRendering(const TileDesc& tile, const std::shared_ptr<ClientSession> &subscriber);
/// Cancels all tile requests by the given subscriber.
void cancelTiles(const std::shared_ptr<ClientSession> &subscriber);
std::unique_ptr<std::fstream> lookupTile(const TileDesc& tile);
void saveTileAndNotify(const TileDesc& tile, const char *data, const size_t size, const bool priority);

View file

@ -33,6 +33,7 @@ class TileCacheTests : public CPPUNIT_NS::TestFixture
CPPUNIT_TEST(testSimple);
CPPUNIT_TEST(testSimpleCombine);
CPPUNIT_TEST(testPerformance);
CPPUNIT_TEST(testCancelTiles);
CPPUNIT_TEST(testUnresponsiveClient);
CPPUNIT_TEST(testClientPartImpress);
CPPUNIT_TEST(testClientPartCalc);
@ -48,6 +49,7 @@ class TileCacheTests : public CPPUNIT_NS::TestFixture
void testSimple();
void testSimpleCombine();
void testPerformance();
void testCancelTiles();
void testUnresponsiveClient();
void testClientPartImpress();
void testClientPartCalc();
@ -208,6 +210,18 @@ void TileCacheTests::testPerformance()
socket.shutdown();
}
void TileCacheTests::testCancelTiles()
{
const auto testName = "cancelTiles ";
auto socket = *loadDocAndGetSocket("load12.ods", _uri, testName);
// Request a huge tile, and cancel immediately.
sendTextFrame(socket, "tilecombine part=0 width=2560 height=2560 tileposx=0 tileposy=0 tilewidth=38400 tileheight=38400");
sendTextFrame(socket, "canceltiles");
assertNotInResponse(socket, "tile:", testName);
}
void TileCacheTests::testUnresponsiveClient()
{
const std::string docFilename = "hello.odt";

View file

@ -330,6 +330,15 @@ std::string assertResponseLine(T& ws, const std::string& prefix, const std::stri
return res;
}
/// Assert that we don't get a response with the given prefix.
template <typename T>
std::string assertNotInResponse(T& ws, const std::string& prefix, const std::string name = "")
{
const auto res = getResponseLine(ws, prefix, name);
CPPUNIT_ASSERT_MESSAGE("Did not expect getting message [" + res + "].", res.empty());
return res;
}
inline
void getResponseMessage(const std::shared_ptr<Poco::Net::WebSocket>& ws, const std::string& prefix, std::string& response, const bool isLine)
{