[Libreoffice-commits] online.git: loolwsd/LOOLWSD.cpp loolwsd/MasterProcessSession.cpp loolwsd/MasterProcessSession.hpp

Henry Castro hcastro at collabora.com
Sun Apr 10 04:18:36 UTC 2016


 loolwsd/LOOLWSD.cpp              |   83 +++++++++++++++++++++++++++++++++++++--
 loolwsd/MasterProcessSession.cpp |   48 ----------------------
 loolwsd/MasterProcessSession.hpp |    2 
 3 files changed, 81 insertions(+), 52 deletions(-)

New commits:
commit 9ae7fa5b9b26ef4fa2bee1d48362ea384787ea65
Author: Henry Castro <hcastro at collabora.com>
Date:   Sat Apr 9 11:54:22 2016 -0400

    loolwsd: wait until bridge is completed

diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 9e32cbd..34291f8 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -151,6 +151,12 @@ static std::mutex newChildrenMutex;
 static std::condition_variable newChildrenCV;
 static std::map<std::string, std::shared_ptr<DocumentBroker>> docBrokers;
 static std::mutex docBrokersMutex;
+// Sessions to pre-spawned child processes that have connected but are not yet assigned a
+// document to work on.
+static std::mutex AvailableChildSessionMutex;
+static std::condition_variable AvailableChildSessionCV;
+static std::map<std::string, std::shared_ptr<MasterProcessSession>> AvailableChildSessions;
+
 
 static void forkChildren(const int number)
 {
@@ -244,6 +250,51 @@ class ClientRequestHandler: public HTTPRequestHandler
 {
 private:
 
+    static bool waitBridgeCompleted(const std::shared_ptr<MasterProcessSession>& clientSession,
+                                    const std::shared_ptr<DocumentBroker>& docBroker)
+    {
+        int retries = 5;
+        bool isFound = false;
+
+        // Wait until the client has connected with a prison socket.
+        std::shared_ptr<MasterProcessSession> prisonSession;
+        std::unique_lock<std::mutex> lock(AvailableChildSessionMutex);
+
+        Log::debug() << "Waiting for client session [" << clientSession->getId() << "] to connect." << Log::end;
+        while (retries-- && !isFound)
+        {
+            AvailableChildSessionCV.wait_for(
+                lock,
+                std::chrono::milliseconds(3000),
+                [&isFound, &clientSession]
+                {
+                    return (isFound = AvailableChildSessions.find(clientSession->getId()) != AvailableChildSessions.end());
+                });
+
+                if (!isFound)
+                {
+                    Log::info() << "Retrying client permission... " << retries << Log::end;
+                    // request again new URL session
+                    const std::string message = "request " + clientSession->getId() + " " + docBroker->getDocKey() + '\n';
+                    Log::trace("MasterToBroker: " + message.substr(0, message.length()-1));
+                    IoUtil::writeFIFO(LOOLWSD::ForKitWritePipe, message);
+                }
+        }
+
+        if (isFound)
+        {
+            Log::debug("Waiting child session permission, done!");
+            prisonSession = AvailableChildSessions[clientSession->getId()];
+            AvailableChildSessions.erase(clientSession->getId());
+
+            clientSession->setPeer(prisonSession);
+            prisonSession->setPeer(clientSession);
+            Log::debug("Connected " + clientSession->getName() + " - " + prisonSession->getName() + ".");
+        }
+
+        return isFound;
+    }
+
     static void handlePostRequest(HTTPServerRequest& request, HTTPServerResponse& response, const std::string& id)
     {
         Log::info("Post request: [" + request.getURI() + "]");
@@ -295,6 +346,18 @@ private:
                     docBroker->incSessions();
                     lock.unlock();
 
+                    if (!waitBridgeCompleted(session, docBroker))
+                    {
+                        Log::error(session->getName() + ": Failed to connect to lokit child.");
+                        // Let the client know we can't serve now.
+                        response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_SERVICE_UNAVAILABLE);
+                        response.setContentLength(0);
+                        response.send();
+                        return;
+                    }
+                    // Now the bridge beetween the client and kit process is connected
+                    // Let messages flow
+
                     std::string encodedFrom;
                     URI::encode(docBroker->getPublicUri().getPath(), "", encodedFrom);
                     const std::string load = "load url=" + encodedFrom;
@@ -495,6 +558,18 @@ private:
         if (wsSessionsCount == 1)
             session->setEditLock(true);
 
+        if (!waitBridgeCompleted(session, docBroker))
+        {
+            Log::error(session->getName() + ": Failed to connect to child. Client cannot serve now.");
+            // Let the client know we can't serve now.
+            response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_SERVICE_UNAVAILABLE);
+            response.setContentLength(0);
+            response.send();
+            return;
+        }
+        // Now the bridge beetween the client and kit process is connected
+        // Let messages flow
+
         QueueHandler handler(queue, session, "wsd_queue_" + session->getId());
 
         Thread queueHandlerThread;
@@ -747,14 +822,14 @@ public:
             auto ws = std::make_shared<WebSocket>(request, response);
             auto session = std::make_shared<MasterProcessSession>(sessionId, LOOLSession::Kind::ToPrisoner, ws, docBroker, nullptr);
 
-            std::unique_lock<std::mutex> lock(MasterProcessSession::AvailableChildSessionMutex);
-            MasterProcessSession::AvailableChildSessions.emplace(sessionId, session);
+            std::unique_lock<std::mutex> lock(AvailableChildSessionMutex);
+            AvailableChildSessions.emplace(sessionId, session);
 
             Log::info() << " mapped " << session << " jailId=" << jailId << ", id=" << sessionId
-                        << " into _availableChildSessions, size=" << MasterProcessSession::AvailableChildSessions.size() << Log::end;
+                        << " into _availableChildSessions, size=" << AvailableChildSessions.size() << Log::end;
 
             lock.unlock();
-            MasterProcessSession::AvailableChildSessionCV.notify_one();
+            AvailableChildSessionCV.notify_one();
 
             const auto uri = request.getURI();
             std::ostringstream message;
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index 8339ab1..71ffe79 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -29,10 +29,6 @@ using namespace LOOLProtocol;
 using Poco::Path;
 using Poco::StringTokenizer;
 
-std::map<std::string, std::shared_ptr<MasterProcessSession>> MasterProcessSession::AvailableChildSessions;
-std::mutex MasterProcessSession::AvailableChildSessionMutex;
-std::condition_variable MasterProcessSession::AvailableChildSessionCV;
-
 MasterProcessSession::MasterProcessSession(const std::string& id,
                                            const Kind kind,
                                            std::shared_ptr<Poco::Net::WebSocket> ws,
@@ -761,50 +757,6 @@ void MasterProcessSession::sendCombinedTiles(const char* /*buffer*/, int /*lengt
 
 void MasterProcessSession::dispatchChild()
 {
-    int retries = 3;
-    bool isFound = false;
-
-    // Wait until the child has connected with Master.
-    std::shared_ptr<MasterProcessSession> childSession;
-    std::unique_lock<std::mutex> lock(AvailableChildSessionMutex);
-
-    Log::debug() << "Waiting for child session [" << getId() << "] to connect." << Log::end;
-    while (retries-- && !isFound)
-    {
-        AvailableChildSessionCV.wait_for(
-            lock,
-            std::chrono::milliseconds(3000),
-            [&isFound, this]
-            {
-                return (isFound = AvailableChildSessions.find(getId()) != AvailableChildSessions.end());
-            });
-
-        if (!isFound)
-        {
-            Log::info() << "Retrying child permission... " << retries << Log::end;
-            // request again new URL session
-            const std::string message = "request " + getId() + " " + _docBroker->getDocKey() + '\n';
-            Log::trace("MasterToBroker: " + message.substr(0, message.length()-1));
-            IoUtil::writeFIFO(LOOLWSD::ForKitWritePipe, message);
-        }
-    }
-
-    if (!isFound)
-    {
-        Log::error(getName() + ": Failed to connect to child. Shutting down socket.");
-        IoUtil::shutdownWebSocket(_ws);
-        throw std::runtime_error("Failed to connect to child.");
-    }
-
-    Log::debug("Waiting child session permission, done!");
-    childSession = AvailableChildSessions[getId()];
-    AvailableChildSessions.erase(getId());
-
-    _peer = childSession;
-    childSession->_peer = shared_from_this();
-    childSession->_docBroker = _docBroker;
-    Log::debug("Connected " + getName() + " - " + childSession->getName() + ".");
-
     std::ostringstream oss;
     oss << "load";
     oss << " url=" << _docBroker->getPublicUri().toString();
diff --git a/loolwsd/MasterProcessSession.hpp b/loolwsd/MasterProcessSession.hpp
index f2b5d22..e1422fc 100644
--- a/loolwsd/MasterProcessSession.hpp
+++ b/loolwsd/MasterProcessSession.hpp
@@ -49,6 +49,8 @@ class MasterProcessSession final : public LOOLSession, public std::enable_shared
 
     std::shared_ptr<BasicTileQueue> getQueue() const { return _queue; }
 
+    void setPeer(const std::shared_ptr<MasterProcessSession>& peer) { _peer = peer; }
+
     void setEditLock(const bool value) { _bEditLock = value; }
 
     bool isEditLocked() const { return _bEditLock; }


More information about the Libreoffice-commits mailing list