Various bits of server tidying up.
authorCarl Hetherington <cth@carlh.net>
Wed, 6 Nov 2013 16:43:01 +0000 (16:43 +0000)
committerCarl Hetherington <cth@carlh.net>
Wed, 6 Nov 2013 16:43:01 +0000 (16:43 +0000)
src/lib/encoder.cc
src/lib/encoder.h
src/lib/server.cc
src/lib/server.h
src/lib/server_finder.cc
src/lib/server_finder.h
src/tools/dcpomatic_server_cli.cc
src/wx/servers_list_dialog.cc
src/wx/servers_list_dialog.h

index 2ec32deb72e037bdb9d55dd2a2c35a9785787731..ccaeab18c6ad0f6b9226ecb519421610b5b6c908 100644 (file)
@@ -79,9 +79,7 @@ void
 Encoder::add_worker_threads (ServerDescription d)
 {
        for (int i = 0; i < d.threads(); ++i) {
-               _threads.push_back (
-                       make_pair (d, new boost::thread (boost::bind (&Encoder::encoder_thread, this, d)))
-                       );
+               _threads.push_back (new boost::thread (boost::bind (&Encoder::encoder_thread, this, d)));
        }
 }
 
@@ -89,12 +87,7 @@ void
 Encoder::process_begin ()
 {
        for (int i = 0; i < Config::instance()->num_local_encoding_threads (); ++i) {
-               _threads.push_back (
-                       make_pair (
-                               optional<ServerDescription> (),
-                               new boost::thread (boost::bind (&Encoder::encoder_thread, this, optional<ServerDescription> ()))
-                               )
-                       );
+               _threads.push_back (new boost::thread (boost::bind (&Encoder::encoder_thread, this, optional<ServerDescription> ())));
        }
 
        vector<ServerDescription> servers = Config::instance()->servers ();
@@ -104,8 +97,7 @@ Encoder::process_begin ()
        }
 
        _writer.reset (new Writer (_film, _job));
-       _server_finder.reset (new ServerFinder ());
-       _server_finder->ServerFound.connect (boost::bind (&Encoder::server_found, this, _1));
+       ServerFinder::instance()->connect (boost::bind (&Encoder::server_found, this, _1));
 }
 
 
@@ -257,11 +249,11 @@ Encoder::terminate_threads ()
                _condition.notify_all ();
        }
 
-       for (ThreadList::iterator i = _threads.begin(); i != _threads.end(); ++i) {
-               if (i->second->joinable ()) {
-                       i->second->join ();
+       for (list<boost::thread *>::iterator i = _threads.begin(); i != _threads.end(); ++i) {
+               if ((*i)->joinable ()) {
+                       (*i)->join ();
                }
-               delete i->second;
+               delete *i;
        }
 
        _threads.clear ();
@@ -354,14 +346,5 @@ Encoder::encoder_thread (optional<ServerDescription> server)
 void
 Encoder::server_found (ServerDescription s)
 {
-       /* See if we already know about this server */
-       boost::mutex::scoped_lock lm (_mutex);
-       ThreadList::iterator i = _threads.begin();
-       while (i != _threads.end() && (!i->first || i->first.get().host_name() != s.host_name())) {
-               ++i;
-       }
-       
-       if (i == _threads.end ()) {
-               add_worker_threads (s);
-       }
+       add_worker_threads (s);
 }
index 902dae2d5e1f113ea8ebdaa0e9e4cb40a30a8779..9875a179b45152407b73ffeead41317a670f4de1 100644 (file)
@@ -107,13 +107,11 @@ private:
        bool _have_a_real_frame[EYES_COUNT];
        bool _terminate;
        std::list<boost::shared_ptr<DCPVideoFrame> > _queue;
-       typedef std::list<std::pair<boost::optional<ServerDescription>, boost::thread *> > ThreadList;
-       ThreadList _threads;
+       std::list<boost::thread *> _threads;
        mutable boost::mutex _mutex;
        boost::condition _condition;
 
        boost::shared_ptr<Writer> _writer;
-       boost::shared_ptr<ServerFinder> _server_finder;
 };
 
 #endif
index bad7ad89310d95ccb8619488e13ae873771de31f..2930e3c4b6381f83597776a8d4708ba760930d83 100644 (file)
@@ -209,7 +209,7 @@ Server::run (int num_threads)
 {
        _log->log (String::compose ("Server starting with %1 threads", num_threads));
        if (_verbose) {
-               cout << "DCP-o-matic server started with " << num_threads << " threads.\n";
+               cout << "DCP-o-matic server starting with " << num_threads << " threads.\n";
        }
        
        for (int i = 0; i < num_threads; ++i) {
@@ -243,6 +243,7 @@ Server::run (int num_threads)
 
 void
 Server::broadcast_thread ()
+try
 {
        boost::asio::io_service io_service;
 
@@ -261,6 +262,10 @@ Server::broadcast_thread ()
 
        io_service.run ();
 }
+catch (...)
+{
+       store_current ();
+}
 
 void
 Server::broadcast_received ()
index 68de3c2f04960d6d32713632432d33b906713dab..9be47bd944fadbb94c8a3b1f63a01a4f91642610 100644 (file)
@@ -32,6 +32,7 @@
 #include <boost/optional.hpp>
 #include <libxml++/libxml++.h>
 #include "log.h"
+#include "exceptions.h"
 
 class Socket;
 
@@ -91,7 +92,7 @@ private:
        int _threads;
 };
 
-class Server : public boost::noncopyable
+class Server : public ExceptionStore, public boost::noncopyable
 {
 public:
        Server (boost::shared_ptr<Log> log, bool verbose);
index c0b554eeef84883faab4415649aabab840b29a95..56f52b7fc292d9510d0b77a0264ca68ef8fede41 100644 (file)
 
 using std::string;
 using std::stringstream;
+using std::list;
 using boost::shared_ptr;
 using boost::scoped_array;
 
+ServerFinder* ServerFinder::_instance = 0;
+
 ServerFinder::ServerFinder ()
        : _broadcast_thread (0)
        , _listen_thread (0)
-       , _terminate (false)
 {
        _broadcast_thread = new boost::thread (boost::bind (&ServerFinder::broadcast_thread, this));
        _listen_thread = new boost::thread (boost::bind (&ServerFinder::listen_thread, this));
 }
 
-ServerFinder::~ServerFinder ()
-{
-       {
-               boost::mutex::scoped_lock lm (_mutex);
-               _terminate = true;
-       }
-       
-       if (_broadcast_thread && _broadcast_thread->joinable ()) {
-               _broadcast_thread->join ();
-       }
-       delete _broadcast_thread;
-
-       if (_listen_thread && _listen_thread->joinable ()) {
-               _listen_thread->join ();
-       }
-       delete _listen_thread;
-}
-
 void
 ServerFinder::broadcast_thread ()
 {
@@ -74,16 +58,8 @@ ServerFinder::broadcast_thread ()
         boost::asio::ip::udp::endpoint end_point (boost::asio::ip::address_v4::broadcast(), Config::instance()->server_port_base() + 1);            
 
        while (1) {
-               boost::mutex::scoped_lock lm (_mutex);
-               if (_terminate) {
-                       socket.close (error);
-                       return;
-               }
-               
-               string data = DCPOMATIC_HELLO;
+               string const data = DCPOMATIC_HELLO;
                socket.send_to (boost::asio::buffer (data.c_str(), data.size() + 1), end_point);
-
-               lm.unlock ();
                dcpomatic_sleep (10);
        }
 }
@@ -92,14 +68,6 @@ void
 ServerFinder::listen_thread ()
 {
        while (1) {
-               {
-                       /* See if we need to stop */
-                       boost::mutex::scoped_lock lm (_mutex);
-                       if (_terminate) {
-                               return;
-                       }
-               }
-
                shared_ptr<Socket> sock (new Socket (10));
 
                try {
@@ -116,9 +84,44 @@ ServerFinder::listen_thread ()
                shared_ptr<cxml::Document> xml (new cxml::Document ("ServerAvailable"));
                xml->read_stream (s);
 
-               ui_signaller->emit (boost::bind (boost::ref (ServerFound), ServerDescription (
-                                                        sock->socket().remote_endpoint().address().to_string (),
-                                                        xml->number_child<int> ("Threads")
-                                                        )));
+               boost::mutex::scoped_lock lm (_mutex);
+
+               string const ip = sock->socket().remote_endpoint().address().to_string ();
+               list<ServerDescription>::const_iterator i = _servers.begin();
+               while (i != _servers.end() && i->host_name() != ip) {
+                       ++i;
+               }
+
+               if (i == _servers.end ()) {
+                       ServerDescription sd (ip, xml->number_child<int> ("Threads"));
+                       _servers.push_back (sd);
+                       ui_signaller->emit (boost::bind (boost::ref (ServerFound), sd));
+               }
        }
 }
+
+void
+ServerFinder::connect (boost::function<void (ServerDescription)> fn)
+{
+       boost::mutex::scoped_lock lm (_mutex);
+
+       /* Emit the current list of servers */
+       for (list<ServerDescription>::iterator i = _servers.begin(); i != _servers.end(); ++i) {
+               fn (*i);
+       }
+
+       ServerFound.connect (fn);
+}
+
+ServerFinder*
+ServerFinder::instance ()
+{
+       if (!_instance) {
+               _instance = new ServerFinder ();
+       }
+
+       return _instance;
+}
+
+       
+       
index 8b56022de693fc36694c5cd20e210fff48a077c7..04a7786cf4442a255268660a93a9673626f4dcc8 100644 (file)
 class ServerFinder
 {
 public:
-       ServerFinder ();
-       ~ServerFinder ();
+       void connect (boost::function<void (ServerDescription)>);
 
-       boost::signals2::signal<void (ServerDescription)> ServerFound;
+       static ServerFinder* instance ();
 
 private:
+       ServerFinder ();
+
        void broadcast_thread ();
        void listen_thread ();
+
+       boost::signals2::signal<void (ServerDescription)> ServerFound;
        
-       /** A thread to periodically issue broadcasts to find encoding servers */
+       /** Thread to periodically issue broadcasts to find encoding servers */
        boost::thread* _broadcast_thread;
+       /** Thread to listen to the responses from servers */
        boost::thread* _listen_thread;
 
-       bool _terminate;
+       std::list<ServerDescription> _servers;
        boost::mutex _mutex;
+
+       static ServerFinder* _instance;
 };
index e9540ff70944a1570fc5d44aecbbdd7b154e50db..1ec985b4ba7c60d4c28f0b60c9d22cdcc2ed5dc9 100644 (file)
@@ -98,6 +98,14 @@ main (int argc, char* argv[])
        Scaler::setup_scalers ();
        shared_ptr<FileLog> log (new FileLog ("dcpomatic_server_cli.log"));
        Server server (log, verbose);
-       server.run (num_threads);
+       try {
+               server.run (num_threads);
+       } catch (boost::system::system_error e) {
+               if (e.code() == boost::system::errc::address_in_use) {
+                       cerr << argv[0] << ": address already in use.  Is another DCP-o-matic server instance already running?\n";
+                       exit (EXIT_FAILURE);
+               }
+               cerr << argv[0] << ": " << e.what() << "\n";
+       }
        return 0;
 }
index 49d91fca404be51ab9a3aa1ba7c56155c9d3b593..be69a14ed47a4df5900880f3a9f20205bebf76d8 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include <boost/lexical_cast.hpp>
+#include "lib/server_finder.h"
 #include "servers_list_dialog.h"
 #include "wx_util.h"
 
@@ -60,21 +61,12 @@ ServersListDialog::ServersListDialog (wxWindow* parent)
        s->Layout ();
        s->SetSizeHints (this);
        
-       _server_finder.ServerFound.connect (boost::bind (&ServersListDialog::server_found, this, _1));
+       ServerFinder::instance()->connect (boost::bind (&ServersListDialog::server_found, this, _1));
 }
 
 void
 ServersListDialog::server_found (ServerDescription s)
 {
-       list<ServerDescription>::const_iterator i = _servers.begin();
-       while (i != _servers.end() && i->host_name() != s.host_name()) {
-               ++i;
-       }
-
-       if (i != _servers.end ()) {
-               return;
-       }
-
        wxListItem list_item;
        int const n = _list->GetItemCount ();
        list_item.SetId (n);
index 0662a141d5b808d93f0c6fb9a8bf9fb2ef262f75..63f1cd6a9b87c2330af12d04d26385a45b16c7e8 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <wx/wx.h>
 #include <wx/listctrl.h>
-#include "lib/server_finder.h"
 
 class ServersListDialog : public wxDialog
 {
@@ -29,7 +28,6 @@ public:
 private:
        void server_found (ServerDescription);
 
-       ServerFinder _server_finder;
        std::list<ServerDescription> _servers;
        wxListCtrl* _list;
 };