[Libreoffice-commits] online.git: 6 commits - loolwsd/LoadTest.cpp loolwsd/LOOLSession.cpp loolwsd/LOOLSession.hpp loolwsd/LOOLWSD.cpp loolwsd/loolwsd-systemplate-setup loolwsd/protocol.txt loolwsd/tsqueue.h
Tor Lillqvist
tml at collabora.com
Tue Jun 9 08:30:50 PDT 2015
loolwsd/LOOLSession.cpp | 28 ++++---
loolwsd/LOOLSession.hpp | 7 +
loolwsd/LOOLWSD.cpp | 149 ++++++++++++++++++++++++++++++--------
loolwsd/LoadTest.cpp | 21 +++--
loolwsd/loolwsd-systemplate-setup | 2
loolwsd/protocol.txt | 8 +-
loolwsd/tsqueue.h | 65 ++++++++++++++++
7 files changed, 230 insertions(+), 50 deletions(-)
New commits:
commit 680475046320abe21db8d4e3346f6041f5051560
Author: Tor Lillqvist <tml at collabora.com>
Date: Tue Jun 9 18:22:09 2015 +0300
Don't bother with storing a ref to Application::instance() in a variable in some places
diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index 9da6244..2b2d9bb 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -663,12 +663,10 @@ ChildProcessSession::~ChildProcessSession()
bool ChildProcessSession::handleInput(const char *buffer, int length)
{
- Application& app = Application::instance();
-
std::string firstLine = getFirstLine(buffer, length);
StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
- app.logger().information(Util::logPrefix() + "Input: " + getAbbreviatedMessage(buffer, length));
+ Application::instance().logger().information(Util::logPrefix() + "Input: " + getAbbreviatedMessage(buffer, length));
if (tokens[0] == "load")
{
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 7bbe69c..f654612 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -169,8 +169,6 @@ public:
return;
}
- Application& app = Application::instance();
-
tsqueue<std::string> queue;
Thread queueHandlerThread;
QueueHandler handler(queue);
@@ -258,7 +256,7 @@ public:
}
catch (WebSocketException& exc)
{
- app.logger().error(Util::logPrefix() + "WebSocketException: " + exc.message());
+ Application::instance().logger().error(Util::logPrefix() + "WebSocketException: " + exc.message());
switch (exc.code())
{
case WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
@@ -276,7 +274,7 @@ public:
}
catch (IOException& exc)
{
- app.logger().error(Util::logPrefix() + "IOException: " + exc.message());
+ Application::instance().logger().error(Util::logPrefix() + "IOException: " + exc.message());
}
queue.clear();
queue.put("eof");
@@ -293,7 +291,6 @@ public:
HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request) override
{
- Application& app = Application::instance();
std::string line = (Util::logPrefix() + "Request from " +
request.clientAddress().toString() + ": " +
request.getMethod() + " " +
@@ -305,7 +302,7 @@ public:
line += " / " + it->first + ": " + it->second;
}
- app.logger().information(line);
+ Application::instance().logger().information(line);
return new WebSocketRequestHandler();
}
};
@@ -322,7 +319,6 @@ public:
{
int flags;
int n;
- Application& app = Application::instance();
_ws.setReceiveTimeout(0);
try
{
@@ -343,7 +339,7 @@ public:
}
catch (WebSocketException& exc)
{
- app.logger().error(Util::logPrefix() + "WebSocketException: " + exc.message());
+ Application::instance().logger().error(Util::logPrefix() + "WebSocketException: " + exc.message());
_ws.close();
}
}
diff --git a/loolwsd/LoadTest.cpp b/loolwsd/LoadTest.cpp
index c03d581..b146ed2 100644
--- a/loolwsd/LoadTest.cpp
+++ b/loolwsd/LoadTest.cpp
@@ -86,7 +86,6 @@ public:
int flags;
int n;
int tileCount = 0;
- Application& app = Application::instance();
try
{
do
@@ -135,7 +134,7 @@ public:
}
catch (WebSocketException& exc)
{
- app.logger().error("WebSocketException: " + exc.message());
+ Application::instance().logger().error("WebSocketException: " + exc.message());
_ws.close();
}
std::cout << Util::logPrefix() << "Got " << tileCount << " tiles" << std::endl;
commit d3f4ddd355e7131626c1aee79c65123d45b5c9ce
Author: Tor Lillqvist <tml at collabora.com>
Date: Tue Jun 9 18:04:46 2015 +0300
Use a queue also in the child processes
diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index 159955b..9da6244 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -239,7 +239,8 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
}
return loadDocument(buffer, length, tokens);
}
- else if (tokens[0] != "invalidatetiles" &&
+ else if (tokens[0] != "canceltiles" &&
+ tokens[0] != "invalidatetiles" &&
tokens[0] != "key" &&
tokens[0] != "mouse" &&
tokens[0] != "resetselection" &&
@@ -258,6 +259,11 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
sendTextFrame("error: cmd=" + tokens[0] + " kind=nodocloaded");
return false;
}
+ else if (tokens[0] == "canceltiles")
+ {
+ if (!_peer.expired())
+ forwardToPeer(buffer, length);
+ }
else if (tokens[0] == "invalidatetiles")
{
return invalidateTiles(buffer, length, tokens);
diff --git a/loolwsd/LOOLSession.hpp b/loolwsd/LOOLSession.hpp
index 9742e5f..4e7e3dd 100644
--- a/loolwsd/LOOLSession.hpp
+++ b/loolwsd/LOOLSession.hpp
@@ -45,6 +45,8 @@ public:
virtual bool getStatus(const char *buffer, int length) = 0;
+ virtual bool handleInput(const char *buffer, int length) = 0;
+
protected:
LOOLSession(std::shared_ptr<Poco::Net::WebSocket> ws, Kind kind);
virtual ~LOOLSession();
@@ -53,8 +55,6 @@ protected:
const Kind _kind;
- virtual bool handleInput(const char *buffer, int length) = 0;
-
void sendBinaryFrame(const char *buffer, int length);
virtual bool loadDocument(const char *buffer, int length, Poco::StringTokenizer& tokens) = 0;
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index cdced5f..7bbe69c 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -121,15 +121,15 @@ using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::ServerApplication;
-class FromClientQueueHandler: public Runnable
+class QueueHandler: public Runnable
{
public:
- FromClientQueueHandler(tsqueue<std::string>& queue):
+ QueueHandler(tsqueue<std::string>& queue):
_queue(queue)
{
}
- void setSession(std::shared_ptr<MasterProcessSession> session)
+ void setSession(std::shared_ptr<LOOLSession> session)
{
_session = session;
}
@@ -147,7 +147,7 @@ public:
}
private:
- std::shared_ptr<MasterProcessSession> _session;
+ std::shared_ptr<LOOLSession> _session;
tsqueue<std::string>& _queue;
};
@@ -173,7 +173,7 @@ public:
tsqueue<std::string> queue;
Thread queueHandlerThread;
- FromClientQueueHandler handler(queue);
+ QueueHandler handler(queue);
try
{
@@ -209,11 +209,11 @@ public:
char buffer[100000];
n = ws->receiveFrame(buffer, sizeof(buffer), flags);
- std::string firstLine = getFirstLine(buffer, n);
- StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
-
if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
{
+ std::string firstLine = getFirstLine(buffer, n);
+ StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+
if (kind == LOOLSession::Kind::ToClient && firstLine.size() == static_cast<std::string::size_type>(n))
{
// Check if it is a "canceltiles" and in that case remove outstanding
@@ -221,6 +221,9 @@ public:
if (tokens.count() == 1 && tokens[0] == "canceltiles")
{
queue.remove_if([](std::string& x){ return x.find("tile ") == 0;});
+
+ // Also forward the "canceltiles" to the child process, if any
+ session->handleInput(buffer, n);
}
else
{
@@ -747,12 +750,19 @@ int LOOLWSD::childMain()
HTTPResponse response;
std::shared_ptr<WebSocket> ws(new WebSocket(cs, request, response));
- ChildProcessSession session(ws, loKit);
+ std::shared_ptr<ChildProcessSession> session(new ChildProcessSession(ws, loKit));
ws->setReceiveTimeout(0);
std::string hello("child " + std::to_string(_childId));
- session.sendTextFrame(hello);
+ session->sendTextFrame(hello);
+
+ tsqueue<std::string> queue;
+ Thread queueHandlerThread;
+ QueueHandler handler(queue);
+
+ handler.setSession(session);
+ queueHandlerThread.start(handler);
int flags;
int n;
@@ -762,10 +772,30 @@ int LOOLWSD::childMain()
n = ws->receiveFrame(buffer, sizeof(buffer), flags);
if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
- if (!session.handleInput(buffer, n))
- n = 0;
+ {
+ std::string firstLine = getFirstLine(buffer, n);
+ StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+
+ // The only kind of messages a child process receives are the single-line ones (?)
+ assert(firstLine.size() == static_cast<std::string::size_type>(n));
+
+ // Check if it is a "canceltiles" and in that case remove outstanding
+ // "tile" messages from the queue.
+ if (tokens.count() == 1 && tokens[0] == "canceltiles")
+ {
+ queue.remove_if([](std::string& x){ return x.find("tile ") == 0;});
+ }
+ else
+ {
+ queue.put(firstLine);
+ }
+ }
}
while (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
+
+ queue.clear();
+ queue.put("eof");
+ queueHandlerThread.join();
}
catch (Exception& exc)
{
commit 8a2329d698867fba3d5235f0f09419fe289e7789
Author: Tor Lillqvist <tml at collabora.com>
Date: Tue Jun 9 17:13:13 2015 +0300
Log the number of tiles requests and replies
diff --git a/loolwsd/LoadTest.cpp b/loolwsd/LoadTest.cpp
index c0c2eed..c03d581 100644
--- a/loolwsd/LoadTest.cpp
+++ b/loolwsd/LoadTest.cpp
@@ -85,6 +85,7 @@ public:
{
int flags;
int n;
+ int tileCount = 0;
Application& app = Application::instance();
try
{
@@ -117,15 +118,17 @@ public:
"Client got " << n << " bytes: " << getAbbreviatedMessage(largeBuffer, n) <<
std::endl;
#endif
- // We don't actually need to do anything with the buffer in this program. We
- // only parse status: messages and they are not preceded by nextmessage:
- // messages.
+ response = getFirstLine(buffer, n);
}
if (response.find("status:") == 0)
{
parseStatus(response, _type, _numParts, _currentPart, _width, _height);
_cond.signal();
}
+ else if (response.find("tile:") == 0)
+ {
+ tileCount++;
+ }
}
}
while (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
@@ -135,6 +138,7 @@ public:
app.logger().error("WebSocketException: " + exc.message());
_ws.close();
}
+ std::cout << Util::logPrefix() << "Got " << tileCount << " tiles" << std::endl;
}
WebSocket& _ws;
@@ -224,6 +228,8 @@ private:
std::uniform_int_distribution<> dis(0, 20);
int extra = dis(_g);
+ int requestCount = 0;
+
// Exercise the server with this document for some minutes
while (!documentStartTimestamp.isElapsed((20 + extra) * Timespan::SECONDS) && !clientDurationExceeded())
{
@@ -236,6 +242,7 @@ private:
"tileposy=" + std::to_string(y * DOCTILESIZE) + " "
"tilewidth=" + std::to_string(DOCTILESIZE) + " "
"tileheight=" + std::to_string(DOCTILESIZE));
+ requestCount++;
x = ((x + 1) % ((output._width-1)/DOCTILESIZE + 1));
if (x == 0)
break;
@@ -247,7 +254,7 @@ private:
Thread::sleep(10000);
- std::cout << Util::logPrefix() << "Shutting down client for '" << document << "'" << std::endl;
+ std::cout << Util::logPrefix() << "Sent " << requestCount << " tile requests, shutting down client for '" << document << "'" << std::endl;
ws.shutdown();
thread.join();
commit 70b1e58f4c11b90890d86e31b147678c0770ff06
Author: Tor Lillqvist <tml at collabora.com>
Date: Tue Jun 9 16:09:23 2015 +0300
Typo
diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt
index 655dcba..74af6c3 100644
--- a/loolwsd/protocol.txt
+++ b/loolwsd/protocol.txt
@@ -14,7 +14,7 @@ client -> server
canceltiles
All outstanding tile messages from the client to the server are
- dropped and will not be handled. There is no guarantee of exacely
+ dropped and will not be handled. There is no guarantee of exactly
which tile: messages might still be sent back to the client.
invalidatetiles part=<partNumber> tileposx=<xpos> tileposy=<ypos> tilewidth=<tileWidth> tileheight=<tileHeight>
commit 629ba8713984ff5b70b66af32255dabb3e96271d
Author: Tor Lillqvist <tml at collabora.com>
Date: Fri Jun 5 16:12:06 2015 +0300
Add a "canceltiles" message to the protocol and handle it
Implementing this Was harder than I first expected. The basic idea is as
follows: The master process puts each message arriving from a client that
isn't "canceltiles" into a (client-specific) queue. A separate thread that
pulls messages from the queue at its own pace and handles them as
before. Incoming "canceltiles" messages are handled specially, though: The
queue is emptied of "tile" messages.
The above sounds simple but there are several details that were a bit tricky
to get right.
diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index 5b30949..159955b 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -87,11 +87,21 @@ LOOLSession::~LOOLSession()
void LOOLSession::sendTextFrame(const std::string& text)
{
+ std::unique_lock<std::mutex> lock(_mutex);
+
_ws->sendFrame(text.data(), text.size());
}
void LOOLSession::sendBinaryFrame(const char *buffer, int length)
{
+ std::unique_lock<std::mutex> lock(_mutex);
+
+ if (length > 1000)
+ {
+ std::string nextmessage = "nextmessage: size=" + std::to_string(length);
+ _ws->sendFrame(nextmessage.data(), nextmessage.size());
+ }
+
_ws->sendFrame(buffer, length, WebSocket::FRAME_BINARY);
}
@@ -529,8 +539,6 @@ void MasterProcessSession::sendTile(const char *buffer, int length, StringTokeni
cachedTile->read(output.data() + pos, size);
cachedTile->close();
- sendTextFrame("nextmessage: size=" + std::to_string(output.size()));
-
sendBinaryFrame(output.data(), output.size());
return;
@@ -628,7 +636,7 @@ void MasterProcessSession::forwardToPeer(const char *buffer, int length)
auto peer = _peer.lock();
if (!peer)
return;
- peer->_ws->sendFrame(buffer, length, WebSocket::FRAME_BINARY);
+ peer->sendBinaryFrame(buffer, length);
}
ChildProcessSession::ChildProcessSession(std::shared_ptr<WebSocket> ws, LibreOfficeKit *loKit) :
@@ -893,8 +901,6 @@ void ChildProcessSession::sendTile(const char *buffer, int length, StringTokeniz
delete[] pixmap;
- sendTextFrame("nextmessage: size=" + std::to_string(output.size()));
-
sendBinaryFrame(output.data(), output.size());
}
diff --git a/loolwsd/LOOLSession.hpp b/loolwsd/LOOLSession.hpp
index 8eef54e..9742e5f 100644
--- a/loolwsd/LOOLSession.hpp
+++ b/loolwsd/LOOLSession.hpp
@@ -69,6 +69,9 @@ protected:
// The actual URL, also in the child, even if the child never accesses that.
std::string _docURL;
+
+private:
+ std::mutex _mutex;
};
template<typename charT, typename traits>
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 18c21b3..cdced5f 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -86,6 +86,7 @@ DEALINGS IN THE SOFTWARE.
#include "LOOLProtocol.hpp"
#include "LOOLSession.hpp"
#include "LOOLWSD.hpp"
+#include "tsqueue.h"
#include "Util.hpp"
using namespace LOOLProtocol;
@@ -120,6 +121,36 @@ using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::ServerApplication;
+class FromClientQueueHandler: public Runnable
+{
+public:
+ FromClientQueueHandler(tsqueue<std::string>& queue):
+ _queue(queue)
+ {
+ }
+
+ void setSession(std::shared_ptr<MasterProcessSession> session)
+ {
+ _session = session;
+ }
+
+ void run() override
+ {
+ while (true)
+ {
+ std::string input = _queue.get();
+ if (input == "eof")
+ break;
+ if (!_session->handleInput(input.c_str(), input.size()))
+ break;
+ }
+ }
+
+private:
+ std::shared_ptr<MasterProcessSession> _session;
+ tsqueue<std::string>& _queue;
+};
+
class WebSocketRequestHandler: public HTTPRequestHandler
/// Handle a WebSocket connection.
{
@@ -139,26 +170,37 @@ public:
}
Application& app = Application::instance();
+
+ tsqueue<std::string> queue;
+ Thread queueHandlerThread;
+ FromClientQueueHandler handler(queue);
+
try
{
try
{
std::shared_ptr<WebSocket> ws(new WebSocket(request, response));
- std::shared_ptr<MasterProcessSession> session;
+ LOOLSession::Kind kind;
if (request.getURI() == LOOLWSD::CHILD_URI && request.serverAddress().port() == LOOLWSD::MASTER_PORT_NUMBER)
- {
- session.reset(new MasterProcessSession(ws, LOOLSession::Kind::ToPrisoner));
- }
+ kind = LOOLSession::Kind::ToPrisoner;
else
+ kind = LOOLSession::Kind::ToClient;
+
+ std::shared_ptr<MasterProcessSession> session(new MasterProcessSession(ws, kind));
+
+ // For ToClient sessions, we store incoming messages in a queue and have a separate
+ // thread that handles them. This is so that we can empty the queue when we get a
+ // "canceltiles" message.
+ if (kind == LOOLSession::Kind::ToClient)
{
- session.reset(new MasterProcessSession(ws, LOOLSession::Kind::ToClient));
+ handler.setSession(session);
+ queueHandlerThread.start(handler);
}
- // Loop, receiving WebSocket messages either from the
- // client, or from the child process (to be forwarded to
- // the client).
+ // Loop, receiving WebSocket messages either from the client, or from the child
+ // process (to be forwarded to the client).
int flags;
int n;
ws->setReceiveTimeout(0);
@@ -167,25 +209,43 @@ public:
char buffer[100000];
n = ws->receiveFrame(buffer, sizeof(buffer), flags);
+ std::string firstLine = getFirstLine(buffer, n);
+ StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+
if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
{
- if (!session->handleInput(buffer, n))
- n = 0;
- }
- if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
- {
- std::string firstLine = getFirstLine(buffer, n);
- StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
-
- int size;
- if (tokens.count() == 2 && tokens[0] == "nextmessage:" && getTokenInteger(tokens[1], "size", size) && size > 0)
+ if (kind == LOOLSession::Kind::ToClient && firstLine.size() == static_cast<std::string::size_type>(n))
{
- char largeBuffer[size];
-
- n = ws->receiveFrame(largeBuffer, size, flags);
- if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
+ // Check if it is a "canceltiles" and in that case remove outstanding
+ // "tile" messages from the queue.
+ if (tokens.count() == 1 && tokens[0] == "canceltiles")
+ {
+ queue.remove_if([](std::string& x){ return x.find("tile ") == 0;});
+ }
+ else
+ {
+ queue.put(firstLine);
+ }
+ }
+ else
+ {
+ // Check if it is a "nextmessage:" and in that case read the large
+ // follow-up message separately, and handle that only.
+ int size;
+ if (tokens.count() == 2 && tokens[0] == "nextmessage:" && getTokenInteger(tokens[1], "size", size) && size > 0)
+ {
+ char largeBuffer[size];
+
+ n = ws->receiveFrame(largeBuffer, size, flags);
+ if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
+ {
+ if (!session->handleInput(largeBuffer, n))
+ n = 0;
+ }
+ }
+ else
{
- if (!session->handleInput(largeBuffer, n))
+ if (!session->handleInput(buffer, n))
n = 0;
}
}
@@ -215,6 +275,9 @@ public:
{
app.logger().error(Util::logPrefix() + "IOException: " + exc.message());
}
+ queue.clear();
+ queue.put("eof");
+ queueHandlerThread.join();
}
};
diff --git a/loolwsd/LoadTest.cpp b/loolwsd/LoadTest.cpp
index 7b7ca38..c0c2eed 100644
--- a/loolwsd/LoadTest.cpp
+++ b/loolwsd/LoadTest.cpp
@@ -241,8 +241,9 @@ private:
break;
}
y = ((y + 1) % ((output._height-1)/DOCTILESIZE + 1));
- Thread::sleep(200);
+ Thread::sleep(50);
}
+ sendTextFrame(ws, "canceltiles");
Thread::sleep(10000);
diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt
index 82d3b90..655dcba 100644
--- a/loolwsd/protocol.txt
+++ b/loolwsd/protocol.txt
@@ -11,6 +11,12 @@ tiles proactively (guessing what the client might need). Etc.
client -> server
================
+canceltiles
+
+ All outstanding tile messages from the client to the server are
+ dropped and will not be handled. There is no guarantee of exacely
+ which tile: messages might still be sent back to the client.
+
invalidatetiles part=<partNumber> tileposx=<xpos> tileposy=<ypos> tilewidth=<tileWidth> tileheight=<tileHeight>
All parameters are numbers. Makes the server remove any cached
@@ -88,7 +94,7 @@ nextmessage: size=<byteSize>
message). Can be ignored by clients using an API that can read
arbitrarily large buffers from a WebSocket (like JavaScript), but
must be handled by clients that cannot (like those using Poco
- 1.6.0).
+ 1.6.0, like the "loadtest" program in the loolwsd sources).
status: type=<typeName> parts=<numberOfParts> current=<currentPartNumber> width=<width> height=<height>
diff --git a/loolwsd/tsqueue.h b/loolwsd/tsqueue.h
new file mode 100644
index 0000000..9511efb
--- /dev/null
+++ b/loolwsd/tsqueue.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * 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/.
+ */
+
+#ifndef INCLUDED_TSQUEUE_H
+#define INCLUDED_TSQUEUE_H
+
+#include "config.h"
+
+#include <condition_variable>
+#include <mutex>
+#include <deque>
+
+// Thread-safe queue
+
+template <class T>
+class tsqueue
+{
+public:
+ void put(const T& value)
+ {
+ std::unique_lock<std::mutex> lock(_mutex);
+ _queue.push_back(value);
+ lock.unlock();
+ _cv.notify_one();
+ }
+
+ T get()
+ {
+ std::unique_lock<std::mutex> lock(_mutex);
+ _cv.wait(lock, [this] { return _queue.size() > 0; });
+ T result = _queue.front();
+ _queue.pop_front();
+ return result;
+ }
+
+ void clear()
+ {
+ std::unique_lock<std::mutex> lock(_mutex);
+ while (_queue.size())
+ _queue.pop_front();
+ }
+
+ template<class UnaryPredicate>
+ void remove_if(UnaryPredicate p)
+ {
+ std::unique_lock<std::mutex> lock(_mutex);
+ _queue.erase(std::remove_if(_queue.begin(), _queue.end(), p),
+ _queue.end());
+ }
+
+private:
+ std::mutex _mutex;
+ std::condition_variable _cv;
+ std::deque<T> _queue;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 1954d95e91aaf662a818f3d775bd44db0cca3501
Author: Tor Lillqvist <tml at collabora.com>
Date: Mon Jun 8 16:58:34 2015 +0300
Clarify usage message
diff --git a/loolwsd/loolwsd-systemplate-setup b/loolwsd/loolwsd-systemplate-setup
index 8af0517..7e310fb 100755
--- a/loolwsd/loolwsd-systemplate-setup
+++ b/loolwsd/loolwsd-systemplate-setup
@@ -1,6 +1,6 @@
#!/bin/bash
-test $# -eq 2 || { echo "Usage: $0 <chroot template directory> <LO installation directory>"; exit 1; }
+test $# -eq 2 || { echo "Usage: $0 <chroot template directory for system libs to create> <LO installation directory>"; exit 1; }
# No provision for spaces or other weird characters in pathnames. So sue me.
More information about the Libreoffice-commits
mailing list