loleaflet/src/core/Socket.js |   30 ++++++++++++++++++++++++++++
 wsd/LOOLWSD.cpp              |   45 ++++++++++++++++++++++++++++++++++++++-----
 wsd/protocol.txt             |    4 ++-
 3 files changed, 73 insertions(+), 6 deletions(-)

New commits:
commit 2b9ea3d4a68e7483e837426bda178e489ae7a4b2
Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk>
Date:   Sun Nov 27 19:11:30 2016 -0500

    loolwsd: notify clients before recycling wsd
    
    Change-Id: Ib2733a6af1c27fe39c54f5c3bc6f5bd3acb72a2b
    Reviewed-on: https://gerrit.libreoffice.org/31298
    Reviewed-by: Ashod Nakashian <ashnak...@gmail.com>
    Tested-by: Ashod Nakashian <ashnak...@gmail.com>

diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index eab6ca8..40c4cf2 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -195,6 +195,36 @@ L.Socket = L.Class.extend({
                        else if (textMsg === 'shuttingdown') {
                                msg = _('Server is shutting down for 
maintenance (auto-saving)');
                        }
+                       else if (textMsg === 'recycling') {
+                               msg = _('Server is recycling and will be 
available shortly');
+
+                               this._map._active = false;
+
+                               // Prevent reconnecting the world at the same 
time.
+                               var min = 5000;
+                               var max = 10000;
+                               var timeoutMs = Math.floor(Math.random() * (max 
- min) + min);
+
+                               socket = this;
+                               map = this._map;
+                               vex.timer = setInterval(function() {
+                                       if (socket.connected()) {
+                                               // We're connected: cancel 
timer and dialog.
+                                               clearTimeout(vex.timer);
+                                               if (vex.dialogID > 0) {
+                                                       var id = vex.dialogID;
+                                                       vex.dialogID = -1;
+                                                       vex.close(id);
+                                               }
+                                               return;
+                                       }
+
+                                       try {
+                                               socket.initialize(map);
+                                       } catch (error) {
+                                       }
+                               }, timeoutMs);
+                       }
 
                        // Close any open dialogs first.
                        if (vex.dialogID > 0) {
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 25a4bab..6b143a4 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -175,6 +175,10 @@ static std::atomic<int> OutstandingForks(1); // Forkit 
always spawns 1.
 static std::map<std::string, std::shared_ptr<DocumentBroker>> DocBrokers;
 static std::mutex DocBrokersMutex;
 
+/// Used when shutting down to notify them all that the server is recycling.
+static std::vector<std::shared_ptr<LOOLWebSocket>> ClientWebSockets;
+static std::mutex ClientWebSocketsMutex;
+
 #if ENABLE_DEBUG
 static int careerSpanSeconds = 0;
 #endif
@@ -983,6 +987,13 @@ private:
                 }
             }
 
+            if (SigUtil::isShuttingDown())
+            {
+                std::lock_guard<std::mutex> lock(ClientWebSocketsMutex);
+                LOG_TRC("Capturing Client WS for [" << id << "]");
+                ClientWebSockets.push_back(ws);
+            }
+
             LOOLWSD::dumpEventTrace(docBroker->getJailId(), id, "EndSession: " 
+ uri);
             LOG_INF("Finishing GET request handler for session [" << id << 
"].");
         }
@@ -1011,11 +1022,14 @@ private:
         }
         else
         {
-            // something wrong, with internal exceptions
-            LOG_TRC("Abnormal close handshake.");
-            session->closeFrame();
-            // FIXME: handle exception thrown from here ? ...
-            ws->shutdown(WebSocket::WS_ENDPOINT_GOING_AWAY);
+            if (!SigUtil::isShuttingDown())
+            {
+                // something wrong, with internal exceptions
+                LOG_TRC("Abnormal close handshake.");
+                session->closeFrame();
+                // FIXME: handle exception thrown from here ? ...
+                ws->shutdown(WebSocket::WS_ENDPOINT_GOING_AWAY);
+            }
         }
 
         LOG_INF("Finished GET request handler for session [" << id << "].");
@@ -2149,6 +2163,27 @@ int LOOLWSD::main(const std::vector<std::string>& 
/*args*/)
         FileUtil::removeFile(path, true);
     }
 
+    if (SigUtil::isShuttingDown())
+    {
+        // At this point there should be no other thread, but...
+        std::lock_guard<std::mutex> lock(ClientWebSocketsMutex);
+
+        LOG_INF("Notifying clients that we are recycling.");
+        static const std::string msg("close: recycling");
+        for (auto& ws : ClientWebSockets)
+        {
+            try
+            {
+                ws->sendFrame(msg.data(), msg.size());
+                ws->shutdown(WebSocket::WS_ENDPOINT_GOING_AWAY);
+            }
+            catch (const std::exception& ex)
+            {
+                LOG_ERR("Error while notifying client of recycle: " << 
ex.what());
+            }
+        }
+    }
+
     // Finally, we no longer need SSL.
     if (LOOLWSD::isSSLEnabled())
     {
diff --git a/wsd/protocol.txt b/wsd/protocol.txt
index 2ebdc33..b6d55ef 100644
--- a/wsd/protocol.txt
+++ b/wsd/protocol.txt
@@ -248,11 +248,13 @@ close: <reason>
     ability to kill all other sessions if EnableOwnerTermination flag in WOPI
     CheckFileInfo is 'true' (assumed to be 'false' by default).
 
-
     * shuttingdown - Sent when the server is going down in a graceful fashion.
     The server doesn't disconnect from clients yet, but starts
     saving document and tearing down internals.
 
+    * recycling - The last message sent from the server when it is gracefully
+    shutting down to let clients know they can try connecting
+    after a short interval.
 
 getchildid: id=<id>
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to