test/TileQueueTests.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ wsd/SenderQueue.hpp | 57 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 114 insertions(+), 5 deletions(-)
New commits: commit 839d7a9b436adc2b8ad05fd7b72a6f7b9bb42934 Author: Ashod Nakashian <[email protected]> Date: Sun Dec 18 17:28:35 2016 -0500 wsd: deduplicate invalidate view cursor messages Change-Id: I898c98ad42fb807ebeafafa47d85930025def57f Reviewed-on: https://gerrit.libreoffice.org/32162 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> diff --git a/test/TileQueueTests.cpp b/test/TileQueueTests.cpp index 7df94ef..0e12f48 100644 --- a/test/TileQueueTests.cpp +++ b/test/TileQueueTests.cpp @@ -47,6 +47,7 @@ class TileQueueTests : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(testPreviewsDeprioritization); CPPUNIT_TEST(testSenderQueue); CPPUNIT_TEST(testSenderQueueTileDeduplication); + CPPUNIT_TEST(testInvalidateViewCursorDeduplication); CPPUNIT_TEST_SUITE_END(); @@ -57,6 +58,7 @@ class TileQueueTests : public CPPUNIT_NS::TestFixture void testPreviewsDeprioritization(); void testSenderQueue(); void testSenderQueueTileDeduplication(); + void testInvalidateViewCursorDeduplication(); }; void TileQueueTests::testTileQueuePriority() @@ -295,6 +297,7 @@ void TileQueueTests::testSenderQueue() CPPUNIT_ASSERT_EQUAL(true, queue.waitDequeue(item, 0)); CPPUNIT_ASSERT_EQUAL(1UL, queue.size()); CPPUNIT_ASSERT_EQUAL(messages[1], std::string(item->data().data(), item->data().size())); + CPPUNIT_ASSERT_EQUAL(true, queue.waitDequeue(item, 0)); CPPUNIT_ASSERT_EQUAL(0UL, queue.size()); CPPUNIT_ASSERT_EQUAL(messages[2], std::string(item->data().data(), item->data().size())); @@ -352,6 +355,65 @@ void TileQueueTests::testSenderQueueTileDeduplication() CPPUNIT_ASSERT_EQUAL(0UL, queue.size()); } +void TileQueueTests::testInvalidateViewCursorDeduplication() +{ + SenderQueue<std::shared_ptr<MessagePayload>> queue; + + std::shared_ptr<MessagePayload> item; + + // Empty queue + CPPUNIT_ASSERT_EQUAL(false, queue.waitDequeue(item, 10)); + CPPUNIT_ASSERT_EQUAL(0UL, queue.size()); + + const std::vector<std::string> view_messages = + { + "invalidateviewcursor: { \"viewId\": \"1\", \"rectangle\": \"3999, 1418, 0, 298\", \"part\": \"0\" }", + "invalidateviewcursor: { \"viewId\": \"2\", \"rectangle\": \"3999, 1418, 0, 298\", \"part\": \"0\" }", + "invalidateviewcursor: { \"viewId\": \"3\", \"rectangle\": \"3999, 1418, 0, 298\", \"part\": \"0\" }", + }; + + for (const auto& msg : view_messages) + { + queue.enqueue(std::make_shared<MessagePayload>(msg)); + } + + CPPUNIT_ASSERT_EQUAL(3UL, queue.size()); + + CPPUNIT_ASSERT_EQUAL(true, queue.waitDequeue(item, 0)); + CPPUNIT_ASSERT_EQUAL(2UL, queue.size()); + CPPUNIT_ASSERT_EQUAL(view_messages[0], std::string(item->data().data(), item->data().size())); + + CPPUNIT_ASSERT_EQUAL(true, queue.waitDequeue(item, 0)); + CPPUNIT_ASSERT_EQUAL(1UL, queue.size()); + CPPUNIT_ASSERT_EQUAL(view_messages[1], std::string(item->data().data(), item->data().size())); + + CPPUNIT_ASSERT_EQUAL(true, queue.waitDequeue(item, 0)); + CPPUNIT_ASSERT_EQUAL(0UL, queue.size()); + CPPUNIT_ASSERT_EQUAL(view_messages[2], std::string(item->data().data(), item->data().size())); + + CPPUNIT_ASSERT_EQUAL(0UL, queue.size()); + + const std::vector<std::string> dup_messages = + { + "invalidateviewcursor: { \"viewId\": \"1\", \"rectangle\": \"3999, 1418, 0, 298\", \"part\": \"0\" }", + "invalidateviewcursor: { \"viewId\": \"1\", \"rectangle\": \"1000, 1418, 0, 298\", \"part\": \"0\" }", + "invalidateviewcursor: { \"viewId\": \"1\", \"rectangle\": \"2000, 1418, 0, 298\", \"part\": \"0\" }", + }; + + for (const auto& msg : dup_messages) + { + queue.enqueue(std::make_shared<MessagePayload>(msg)); + } + + CPPUNIT_ASSERT_EQUAL(1UL, queue.size()); + CPPUNIT_ASSERT_EQUAL(true, queue.waitDequeue(item, 0)); + + // The last one should persist. + CPPUNIT_ASSERT_EQUAL(dup_messages[2], std::string(item->data().data(), item->data().size())); + + CPPUNIT_ASSERT_EQUAL(0UL, queue.size()); +} + CPPUNIT_TEST_SUITE_REGISTRATION(TileQueueTests); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/wsd/SenderQueue.hpp b/wsd/SenderQueue.hpp index 4e1c425..3c42264 100644 --- a/wsd/SenderQueue.hpp +++ b/wsd/SenderQueue.hpp @@ -16,6 +16,11 @@ #include <mutex> #include <vector> +#include <Poco/Dynamic/Var.h> +#include <Poco/JSON/JSON.h> +#include <Poco/JSON/Object.h> +#include <Poco/JSON/Parser.h> + #include "common/SigUtil.hpp" #include "LOOLWebSocket.hpp" #include "Log.hpp" @@ -26,16 +31,17 @@ class MessagePayload { public: - enum class Type { Text, Binary }; + enum class Type { Text, JSON, Binary }; /// Construct a text message. /// message must include the full first-line. - MessagePayload(const std::string& message) : + MessagePayload(const std::string& message, + const enum Type type = Type::Text) : _data(message.data(), message.data() + message.size()), _tokens(LOOLProtocol::tokenize(_data.data(), _data.size())), _firstLine(LOOLProtocol::getFirstLine(_data.data(), _data.size())), _abbreviation(LOOLProtocol::getAbbreviatedMessage(_data.data(), _data.size())), - _type(Type::Text) + _type(type) { } @@ -44,8 +50,8 @@ public: /// message must include the full first-line. MessagePayload(const std::string& message, const enum Type type, - const size_t reserve = 0) : - _data(reserve), + const size_t reserve) : + _data(std::max(reserve, message.size())), _tokens(LOOLProtocol::tokenize(_data.data(), _data.size())), _firstLine(LOOLProtocol::getFirstLine(_data.data(), _data.size())), _abbreviation(LOOLProtocol::getAbbreviatedMessage(_data.data(), _data.size())), @@ -76,6 +82,18 @@ public: const std::string& firstLine() const { return _firstLine; } const std::string& abbreviation() const { return _abbreviation; } + /// Returns the json part of the message, if any. + std::string jsonString() const + { + if (_tokens.size() > 1 && _tokens[1] == "{") + { + const auto firstTokenSize = _tokens[0].size(); + return std::string(_data.data() + firstTokenSize, _data.size() - firstTokenSize); + } + + return std::string(); + } + /// Append more data to the message. void append(const char* data, const size_t size) { @@ -193,6 +211,35 @@ private: _queue.erase(pos); } } + else if (command == "invalidateviewcursor:") + { + // Remove previous cursor invalidation for same view, + // if any, and use most recent (incoming). + const std::string newMsg = item->jsonString(); + Poco::JSON::Parser newParser; + const auto newResult = newParser.parse(newMsg); + const auto& newJson = newResult.extract<Poco::JSON::Object::Ptr>(); + const auto viewId = newJson->get("viewId").toString(); + const auto& pos = std::find_if(_queue.begin(), _queue.end(), + [command, viewId](const queue_item_t& cur) + { + if (cur->firstToken() == command) + { + const std::string msg = cur->jsonString(); + Poco::JSON::Parser parser; + const auto result = parser.parse(msg); + const auto& json = result.extract<Poco::JSON::Object::Ptr>(); + return (viewId == json->get("viewId").toString()); + } + + return false; + }); + + if (pos != _queue.end()) + { + _queue.erase(pos); + } + } return true; } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
