[Libreoffice-commits] online.git: loolwsd/LOOLForKit.cpp loolwsd/LOOLKit.cpp loolwsd/LOOLWSD.cpp loolwsd/test loolwsd/Unit.hpp
Michael Meeks
michael.meeks at collabora.com
Tue Apr 12 20:58:48 UTC 2016
loolwsd/LOOLForKit.cpp | 2
loolwsd/LOOLKit.cpp | 3 -
loolwsd/LOOLWSD.cpp | 12 +++-
loolwsd/Unit.hpp | 21 ++++++-
loolwsd/test/UnitPrefork.cpp | 121 +++++++++++++++++++++++++++++++++++++++----
5 files changed, 144 insertions(+), 15 deletions(-)
New commits:
commit 25a092d7de440b5b284f451c26812145fd743521
Author: Michael Meeks <michael.meeks at collabora.com>
Date: Tue Apr 12 21:30:06 2016 +0100
Add memory accounting metric to UnitPrefork.
Also add hooks to allow custom LOK <-> WSD message for this test.
diff --git a/loolwsd/LOOLForKit.cpp b/loolwsd/LOOLForKit.cpp
index 4ad66b3..e3e8046 100644
--- a/loolwsd/LOOLForKit.cpp
+++ b/loolwsd/LOOLForKit.cpp
@@ -120,6 +120,8 @@ static int createLibreOfficeKit(const std::string& childRoot,
}
else
{
+ UnitKit::get().launchedKit(pid);
+
// parent
if (pid < 0)
Log::syserror("Fork failed.");
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index 9efa6d4..12e652e 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -1021,7 +1021,8 @@ void lokit_main(const std::string& childRoot,
{
std::string message(data.data(), data.size());
- UnitKit::get().kitMessage(message);
+ if (UnitKit::get().filterKitMessage(ws, message))
+ return true;
Log::debug(socketName + ": recv [" + LOOLProtocol::getAbbreviatedMessage(message) + "].");
StringTokenizer tokens(message, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index c48baad..ace66b1 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -667,6 +667,11 @@ public:
void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) override
{
+ if (UnitWSD::get().filterHandleRequest(
+ UnitWSD::TestRequest::TEST_REQ_CLIENT,
+ request, response))
+ return;
+
handleClientRequest(request,response);
}
@@ -721,6 +726,11 @@ public:
void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) override
{
+ if (UnitWSD::get().filterHandleRequest(
+ UnitWSD::TestRequest::TEST_REQ_PRISONER,
+ request, response))
+ return;
+
handlePrisonerRequest(request, response);
}
@@ -756,7 +766,7 @@ public:
newChildren.emplace_back(std::make_shared<ChildProcess>(pid, ws));
Log::info("Have " + std::to_string(newChildren.size()) + " " + (newChildren.size() == 1 ? "child" : "children") + ".");
newChildrenCV.notify_one();
- UnitWSD::get().newChild();
+ UnitWSD::get().newChild(ws);
return;
}
diff --git a/loolwsd/Unit.hpp b/loolwsd/Unit.hpp
index 658184d..ac925f2 100644
--- a/loolwsd/Unit.hpp
+++ b/loolwsd/Unit.hpp
@@ -21,6 +21,11 @@ class UnitTimeout;
class UnitHTTPServerRequest;
class UnitHTTPServerResponse;
+namespace Poco { namespace Net {
+ class HTTPServerRequest;
+ class HTTPServerResponse;
+} }
+
class StorageBase;
typedef UnitBase *(CreateUnitHooksFunction)();
@@ -103,13 +108,20 @@ public:
/// Tweak the count of pre-spawned kits.
virtual void preSpawnCount(int & /* numPrefork */) {}
/// When a new child kit process reports
- virtual void newChild() {}
+ virtual void newChild(const std::shared_ptr<Poco::Net::WebSocket> & /* socket */) {}
/// Intercept createStorage
virtual bool createStorage(const std::string& /* jailRoot */,
const std::string& /* jailPath */,
const Poco::URI& /* uri */,
std::unique_ptr<StorageBase> & /*rStorage */)
{ return false; }
+ /// Intercept incoming requests, so unit tests can silently communicate
+ virtual bool filterHandleRequest(
+ TestRequest /* type */,
+ Poco::Net::HTTPServerRequest& /* request */,
+ Poco::Net::HTTPServerResponse& /* response */)
+ { return false; }
+
};
/// Derive your Kit unit test / hooks from me.
@@ -129,13 +141,18 @@ public:
/// main-loop reached, time for testing
virtual void invokeForKitTest() {}
+ /// Post fork hook - just after we fork to init the child kit
+ virtual void launchedKit(int /* pid */) {}
+
// ---------------- Kit hooks ----------------
/// Post fork hook - just before we init the child kit
virtual void postFork() {}
/// Kit got a message
- virtual void kitMessage(std::string &/* message */) {}
+ virtual bool filterKitMessage(const std::shared_ptr<Poco::Net::WebSocket> & /* ws */,
+ std::string &/* message */)
+ { return false; }
};
#endif
diff --git a/loolwsd/test/UnitPrefork.cpp b/loolwsd/test/UnitPrefork.cpp
index b9239f7..c56e2fc 100644
--- a/loolwsd/test/UnitPrefork.cpp
+++ b/loolwsd/test/UnitPrefork.cpp
@@ -14,50 +14,149 @@
#include "Util.hpp"
#include "Unit.hpp"
+#include "LOOLProtocol.hpp"
#include <Poco/Timestamp.h>
-using Poco::Timestamp;
+#include <Poco/StringTokenizer.h>
+
+const int NumToPrefork = 20;
// Inside the WSD process
class UnitPrefork : public UnitWSD
{
int _numStarted;
- const int _numToPrefork;
- Timestamp _startTime;
+ Poco::Timestamp _startTime;
+ std::vector< std::shared_ptr<Poco::Net::WebSocket> > _childSockets;
public:
UnitPrefork()
- : _numStarted(0),
- _numToPrefork(20)
+ : _numStarted(0)
{
setHasKitHooks();
}
virtual void preSpawnCount(int &numPrefork) override
{
- numPrefork = _numToPrefork;
+ numPrefork = NumToPrefork;
+ }
+
+ std::string getMemory(const std::shared_ptr<Poco::Net::WebSocket> &socket)
+ {
+ /// Fetch memory usage data from the last process ...
+ socket->sendFrame("unit-memdump: \n", sizeof("unit-memdump: \n")-1);
+ int flags;
+ char buffer[4096];
+ std::cout << "Waiting for memory stats" << std::endl;
+
+ int length = socket->receiveFrame(buffer, sizeof (buffer), flags);
+ std::string memory = LOOLProtocol::getFirstLine(buffer, length);
+
+ return memory;
}
- virtual void newChild() override
+ virtual void newChild(const std::shared_ptr<Poco::Net::WebSocket> &socket) override
{
++_numStarted;
- if (_numStarted >= _numToPrefork)
+ _childSockets.push_back(socket);
+ if (_numStarted >= NumToPrefork)
{
- exitTest(TestResult::TEST_OK);
-
Poco::Timestamp::TimeDiff elapsed = _startTime.elapsed();
std::cout << "Launched " << _numStarted << " in "
<< (1.0 * elapsed)/Poco::Timestamp::resolution() << std::endl;
+ int num = 0;
+ for (auto child : _childSockets)
+ std::cout << "Memory of " << ++num << " : " <<
+ getMemory(child) << std::endl;
+
+ exitTest(TestResult::TEST_OK);
}
}
};
+namespace {
+ std::vector<int> pids;
+
+ const char *startsWith(const char *line, const char *tag)
+ {
+ int len = strlen(tag);
+ if (!strncmp(line, tag, len))
+ {
+ while (!isdigit(line[len]) && line[len] != '\0')
+ len++;
+// fprintf(stdout, "does start with %s: '%s'\n", tag, line + len);
+ return line + len;
+ }
+ else
+ return 0;
+ }
+
+ std::string readMemorySizes(FILE *inStream)
+ {
+ size_t numPSSKb = 0;
+ size_t numDirtyKb = 0;
+
+ char line[4096];
+ while (fgets(line, sizeof (line), inStream))
+ {
+ const char *value;
+ if ((value = startsWith(line, "Private_Dirty:")) ||
+ (value = startsWith(line, "Shared_Dirty:")))
+ numDirtyKb += atoi(value);
+ else if ((value = startsWith(line, "Pss:")))
+ numPSSKb += atoi(value);
+ }
+ std::ostringstream oss;
+ oss << numPSSKb << "k pss " << numDirtyKb << "k dirty";
+ return oss.str();
+ }
+}
+
// Inside the forkit & kit processes
class UnitKitPrefork : public UnitKit
{
+ FILE *_procSMaps;
+
public:
- UnitKitPrefork() {}
+ UnitKitPrefork()
+ : _procSMaps(NULL)
+ {
+ std::cerr << "UnitKit Prefork init !\n";
+ }
+ ~UnitKitPrefork()
+ {
+ fclose(_procSMaps);
+ }
+
+ virtual void launchedKit(int pid) override
+ {
+ // by the magic of forking - this should appear
+ // in the last kit child nearly fully formed.
+ pids.push_back(pid);
+ }
+
+ virtual void postFork() override
+ {
+ // before we drop the caps we can even open our /proc files !
+ std::string procName = std::string("/proc/") +
+ std::to_string(getpid()) +
+ std::string("/smaps");
+ _procSMaps = fopen(procName.c_str(), "r");
+ }
+
+ virtual bool filterKitMessage(const std::shared_ptr<Poco::Net::WebSocket> &ws,
+ std::string &message) override
+ {
+ std::string token = LOOLProtocol::getFirstToken(message.c_str(), message.length());
+ if (token == "unit-memdump:")
+ {
+ std::string memory = readMemorySizes(_procSMaps) + "\n";
+ ws->sendFrame(memory.c_str(), memory.length());
+ return true;
+ }
+
+ return false;
+ }
};
UnitBase *unit_create_wsd(void)
More information about the Libreoffice-commits
mailing list