loolwsd/LOOLBroker.cpp |  175 +++++++++++++++++++++++++++++++++++--------------
 loolwsd/LOOLKit.cpp    |   18 +++--
 2 files changed, 137 insertions(+), 56 deletions(-)

New commits:
commit 7f13face521315bc14feb8d67056ebbe57828d49
Author: Michael Meeks <michael.me...@collabora.com>
Date:   Fri Apr 1 20:27:14 2016 +0100

    Attempt at loolbroker benchmark mode.
    
    Change-Id: Ia1d7450b1e99686e3c654f427c231fd7e0cf8254
    Reviewed-on: https://gerrit.libreoffice.org/23773
    Reviewed-by: Ashod Nakashian <ashnak...@gmail.com>
    Tested-by: Ashod Nakashian <ashnak...@gmail.com>

diff --git a/loolwsd/LOOLBroker.cpp b/loolwsd/LOOLBroker.cpp
index d79b032..ec27fa4 100644
--- a/loolwsd/LOOLBroker.cpp
+++ b/loolwsd/LOOLBroker.cpp
@@ -41,7 +41,7 @@ static std::string loolkitPath;
 static std::atomic<unsigned> forkCounter;
 static std::chrono::steady_clock::time_point lastMaintenanceTime = 
std::chrono::steady_clock::now();
 static unsigned int childCounter = 0;
-static int numPreSpawnedChildren = 0;
+static int numPreSpawnedChildren = 1;
 
 static std::mutex forkMutex;
 
@@ -202,6 +202,8 @@ public:
                 return false;
             }
 
+            Log::debug("Got message from child ! '" + response + "'");
+
             StringTokenizer tokens(response, " ", 
StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
             if (tokens.count() > 0 && tokens[0] != childPid)
             {
@@ -284,6 +286,16 @@ public:
         Log::debug("Thread [" + thread_name + "] finished.");
     }
 
+    bool waitForResponse()
+    {
+        std::string response;
+        if (_childPipeReader.readLine(response, [](){ return TerminationFlag; 
}) <= 0)
+            Log::error("Error reading response to benchmark message from 
child");
+        else
+            Log::debug("got response '" + response + "'");
+        return response == "started";
+    }
+
 private:
     IoUtil::PipeReader _childPipeReader;
 };
@@ -340,7 +352,8 @@ static int createLibreOfficeKit(const bool sharePages,
                                 const std::string& childRoot,
                                 const std::string& sysTemplate,
                                 const std::string& loTemplate,
-                                const std::string& loSubPath)
+                                const std::string& loSubPath,
+                                bool doBenchmark)
 {
     Process::PID childPID;
     int fifoWriter = -1;
@@ -370,7 +383,7 @@ static int createLibreOfficeKit(const bool sharePages,
                 Thread::sleep(std::stoul(std::getenv("SLEEPKITFORDEBUGGER")) * 
1000);
             }
 
-            lokit_main(childRoot, sysTemplate, loTemplate, loSubPath, pipeKit);
+            lokit_main(childRoot, sysTemplate, loTemplate, loSubPath, pipeKit, 
doBenchmark);
             _exit(Application::EXIT_OK);
         }
         else
@@ -487,6 +500,78 @@ static bool waitForTerminationChild(const Process::PID 
pid, int count = CHILD_TI
     return false;
 }
 
+static void printArgumentHelp()
+{
+    std::cout << "Usage: loolbroker [OPTION]..." << std::endl;
+    std::cout << "  Single threaded process broker that spawns lok instances" 
<< std::endl;
+    std::cout << "  note: running this standalone is not possible, it is 
spawned by the loolwsd" << std::endl;
+    std::cout << "        and is controlled via a pipe." << std::endl;
+    std::cout << "" << std::endl;
+    std::cout << "  Some parameters are required and passed on to the lok 
instance:" << std::endl;
+    std::cout << "  --losubpath=<path>        path to chroot for child to live 
inside." << std::endl;
+    std::cout << "  --childroot=<path>        path to chroot for child to live 
inside." << std::endl;
+    std::cout << "  --systemplate=<path>      path of system template to 
pre-populate chroot with." << std::endl;
+    std::cout << "  --lotemplate=<path>       path of libreoffice template to 
pre-populate chroot with." << std::endl;
+    std::cout << "  --pipe=<path>             path of loolwsd pipe to connect 
to on startup." << std::endl;
+    std::cout << "  --losubpath=<path>        path to libreoffice install" << 
std::endl;
+    std::cout << "" << std::endl;
+    std::cout << "  Some paramaters are optional:" << std::endl;
+    std::cout << "  --numprespawns=<number>   pre-fork at least <number> 
processes [1]" << std::endl;
+    std::cout << "  --benchmark               pre-fork processes, and print 
statistics before exiting" << std::endl;
+}
+
+void setupPipes(const std::string &childRoot, bool doBenchmark)
+{
+    const Path pipePath = Path::forDirectory(childRoot + Path::separator() + 
FIFO_PATH);
+    if (!doBenchmark)
+    {
+        const std::string pipeLoolwsd = Path(pipePath, 
FIFO_LOOLWSD).toString();
+        if ( (readerBroker = open(pipeLoolwsd.c_str(), O_RDONLY) ) < 0 )
+        {
+            Log::error("Error: failed to open pipe [" + pipeLoolwsd + "] read 
only. Exiting.");
+            std::exit(Application::EXIT_SOFTWARE);
+        }
+    }
+
+    int pipeFlags = O_RDONLY | O_NONBLOCK;
+    const std::string pipeBroker = Path(pipePath, FIFO_BROKER).toString();
+    if (mkfifo(pipeBroker.c_str(), 0666) < 0 && errno != EEXIST)
+    {
+        Log::error("Error: Failed to create pipe FIFO [" + FIFO_BROKER + "].");
+        std::exit(Application::EXIT_SOFTWARE);
+    }
+
+    if ((readerChild = open(pipeBroker.c_str(), pipeFlags) ) < 0)
+    {
+        Log::error("Error: pipe opened for reading.");
+        std::exit(Application::EXIT_SOFTWARE);
+    }
+
+    if ((pipeFlags = fcntl(readerChild, F_GETFL, 0)) < 0)
+    {
+        Log::error("Error: failed to get pipe flags [" + FIFO_BROKER + "].");
+        std::exit(Application::EXIT_SOFTWARE);
+    }
+
+    pipeFlags &= ~O_NONBLOCK;
+    if (fcntl(readerChild, F_SETFL, pipeFlags) < 0)
+    {
+        Log::error("Error: failed to set pipe flags [" + FIFO_BROKER + "].");
+        std::exit(Application::EXIT_SOFTWARE);
+    }
+
+    if (!doBenchmark)
+    {
+        // Open notify pipe
+        const std::string pipeNotify = Path(pipePath, FIFO_NOTIFY).toString();
+        if ((writerNotify = open(pipeNotify.c_str(), O_WRONLY) ) < 0)
+        {
+            Log::error("Error: failed to open notify pipe [" + FIFO_NOTIFY + 
"] for writing.");
+            exit(Application::EXIT_SOFTWARE);
+        }
+    }
+}
+
 // Broker process
 int main(int argc, char** argv)
 {
@@ -508,6 +593,7 @@ int main(int argc, char** argv)
     std::string loSubPath;
     std::string sysTemplate;
     std::string loTemplate;
+    bool doBenchmark = false;
 
     for (int i = 0; i < argc; ++i)
     {
@@ -543,22 +629,18 @@ int main(int argc, char** argv)
             eq = std::strchr(cmd, '=');
             ClientPortNumber = std::stoll(std::string(eq+1));
         }
+        else if (std::strstr(cmd, "--benchmark"))
+            doBenchmark = true;
     }
 
     loolkitPath = Poco::Path(argv[0]).parent().toString() + "loolkit";
 
-    assert(!loSubPath.empty());
-    assert(!sysTemplate.empty());
-    assert(!loTemplate.empty());
-    assert(!childRoot.empty());
-    assert(numPreSpawnedChildren >= 1);
-
-    const Path pipePath = Path::forDirectory(childRoot + Path::separator() + 
FIFO_PATH);
-    const std::string pipeLoolwsd = Path(pipePath, FIFO_LOOLWSD).toString();
-    if ( (readerBroker = open(pipeLoolwsd.c_str(), O_RDONLY) ) < 0 )
+    if (loSubPath.empty() || sysTemplate.empty() ||
+        loTemplate.empty() || childRoot.empty() ||
+        numPreSpawnedChildren < 1)
     {
-        Log::error("Error: failed to open pipe [" + pipeLoolwsd + "] read 
only. Exiting.");
-        std::exit(Application::EXIT_SOFTWARE);
+        printArgumentHelp();
+        return 1;
     }
 
     if (!std::getenv("LD_BIND_NOW"))
@@ -567,40 +649,7 @@ int main(int argc, char** argv)
     if (!std::getenv("LOK_VIEW_CALLBACK"))
         Log::info("Note: LOK_VIEW_CALLBACK is not set.");
 
-    int pipeFlags = O_RDONLY | O_NONBLOCK;
-    const std::string pipeBroker = Path(pipePath, FIFO_BROKER).toString();
-    if (mkfifo(pipeBroker.c_str(), 0666) < 0 && errno != EEXIST)
-    {
-        Log::error("Error: Failed to create pipe FIFO [" + FIFO_BROKER + "].");
-        std::exit(Application::EXIT_SOFTWARE);
-    }
-
-    if ((readerChild = open(pipeBroker.c_str(), pipeFlags) ) < 0)
-    {
-        Log::error("Error: pipe opened for reading.");
-        std::exit(Application::EXIT_SOFTWARE);
-    }
-
-    if ((pipeFlags = fcntl(readerChild, F_GETFL, 0)) < 0)
-    {
-        Log::error("Error: failed to get pipe flags [" + FIFO_BROKER + "].");
-        std::exit(Application::EXIT_SOFTWARE);
-    }
-
-    pipeFlags &= ~O_NONBLOCK;
-    if (fcntl(readerChild, F_SETFL, pipeFlags) < 0)
-    {
-        Log::error("Error: failed to set pipe flags [" + FIFO_BROKER + "].");
-        std::exit(Application::EXIT_SOFTWARE);
-    }
-
-    // Open notify pipe
-    const std::string pipeNotify = Path(pipePath, FIFO_NOTIFY).toString();
-    if ((writerNotify = open(pipeNotify.c_str(), O_WRONLY) ) < 0)
-    {
-        Log::error("Error: failed to open notify pipe [" + FIFO_NOTIFY + "] 
for writing.");
-        exit(Application::EXIT_SOFTWARE);
-    }
+    setupPipes(childRoot, doBenchmark);
 
     // Initialize LoKit and hope we can fork and save memory by sharing pages.
     const bool sharePages = std::getenv("LOK_NO_PREINIT") == nullptr
@@ -614,7 +663,7 @@ int main(int argc, char** argv)
 
     // We must have at least one child, more is created dynamically.
     if (createLibreOfficeKit(sharePages, childRoot, sysTemplate,
-                             loTemplate, loSubPath) < 0)
+                             loTemplate, loSubPath, doBenchmark) < 0)
     {
         Log::error("Error: failed to create children.");
         std::exit(Application::EXIT_SOFTWARE);
@@ -637,6 +686,8 @@ int main(int argc, char** argv)
 
     Log::info("loolbroker is ready.");
 
+    Poco::Timestamp startTime;
+
     int childExitCode = EXIT_SUCCESS;
     unsigned timeoutCounter = 0;
     while (!TerminationFlag)
@@ -741,7 +792,7 @@ int main(int argc, char** argv)
                 do
                 {
                     if (createLibreOfficeKit(sharePages, childRoot, 
sysTemplate,
-                                             loTemplate, loSubPath) < 0)
+                                             loTemplate, loSubPath, 
doBenchmark) < 0)
                     {
                         Log::error("Error: fork failed.");
                     }
@@ -770,6 +821,30 @@ int main(int argc, char** argv)
             childExitCode = EXIT_SUCCESS;
             sleep(MAINTENANCE_INTERVAL);
         }
+
+        if (doBenchmark)
+            break;
+    }
+
+    if (doBenchmark)
+    {
+        Log::info("loolbroker benchmark - waiting for kits.");
+
+        int numSpawned = 0;
+        while (numSpawned < numPreSpawnedChildren)
+        {
+            if (pipeHandler.waitForResponse())
+                numSpawned++;
+            Log::info("got children " + std::to_string(numSpawned));
+        }
+
+        sleep (10);
+
+        Poco::Timestamp::TimeDiff elapsed = startTime.elapsed();
+        std::cerr << "Time to launch " << numPreSpawnedChildren << " children: 
" << (1.0 * elapsed)/Poco::Timestamp::resolution() << std::endl;
+        Log::info("loolbroker benchmark complete.");
+
+        TerminationFlag = true;
     }
 
     // Terminate child processes.
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index 620a40b..23c498f 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -807,7 +807,8 @@ void lokit_main(const std::string& childRoot,
                 const std::string& sysTemplate,
                 const std::string& loTemplate,
                 const std::string& loSubPath,
-                const std::string& pipe)
+                const std::string& pipe,
+                bool doBenchmark = false)
 {
 #ifdef LOOLKIT_NO_MAIN
     // Reinitialize logging when forked.
@@ -859,12 +860,15 @@ void lokit_main(const std::string& childRoot,
             std::exit(Application::EXIT_SOFTWARE);
         }
 
-        // Open notify pipe
-        const std::string pipeNotify = Path(pipePath, FIFO_NOTIFY).toString();
-        if ((writerNotify = open(pipeNotify.c_str(), O_WRONLY) ) < 0)
+        if (!doBenchmark)
         {
-            Log::error("Error: failed to open notify pipe [" + FIFO_NOTIFY + 
"] for writing.");
-            exit(Application::EXIT_SOFTWARE);
+            // Open notify pipe
+            const std::string pipeNotify = Path(pipePath, 
FIFO_NOTIFY).toString();
+            if ((writerNotify = open(pipeNotify.c_str(), O_WRONLY) ) < 0)
+            {
+                Log::error("Error: failed to open notify pipe [" + FIFO_NOTIFY 
+ "] for writing.");
+                exit(Application::EXIT_SOFTWARE);
+            }
         }
 
         const Path jailPath = Path::forDirectory(childRoot + Path::separator() 
+ jailId);
@@ -953,6 +957,8 @@ void lokit_main(const std::string& childRoot,
         }
 
         Log::info("loolkit [" + std::to_string(Process::id()) + "] is ready.");
+        if (doBenchmark)
+            IoUtil::writeFIFO(writerBroker, "started\n");
 
         char buffer[READ_BUFFER_SIZE];
         std::string message;
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to