]> git.llucax.com Git - z.facultad/75.42/plaqui.git/commitdiff
Varios cambios:
authorLeandro Lucarella <llucax@gmail.com>
Sun, 23 Nov 2003 05:07:37 +0000 (05:07 +0000)
committerLeandro Lucarella <llucax@gmail.com>
Sun, 23 Nov 2003 05:07:37 +0000 (05:07 +0000)
- Se empiezan a emprolijar las cosas, empezando por Runnable:
  * Se ponen atributos y signals como privados y se agrega mutex.
  * El thread que usa ahora no es joinable, por lo que finish() ahora no
    lleva argumentos.
- Se arreglan todas las otras clases (y el programa principal) para que anden
  con el nuevo Runnable (haciendo loops de espera cuando deben 'joinear' un
  thread).
- Se actuliza el plaqui-client y se le arreglan un par de bugs (ya anda la
  opcion desconectar del menu).
- Se implementa el comando /server/stop por completo (usando una conexion
  suicida para salir del accept()).
- Se agregan separadores de tipos, constantes, atributos y metodos mas
  llamativos :)

28 files changed:
Client/src/principal.cpp
Server/include/plaqui/server/command.h
Server/include/plaqui/server/connection.h
Server/include/plaqui/server/controlclient.h
Server/include/plaqui/server/controlserver.h
Server/include/plaqui/server/httperror.h
Server/include/plaqui/server/httpheaders.h
Server/include/plaqui/server/httpmessage.h
Server/include/plaqui/server/httprequest.h
Server/include/plaqui/server/httpresponse.h
Server/include/plaqui/server/plant.h
Server/include/plaqui/server/receiver.h
Server/include/plaqui/server/runnable.h
Server/include/plaqui/server/server.h
Server/include/plaqui/server/string.h
Server/include/plaqui/server/tcpserver.h
Server/include/plaqui/server/transmitter.h
Server/src/connection.cpp
Server/src/controlclient.cpp
Server/src/controlserver.cpp
Server/src/main.cpp
Server/src/plant.cpp
Server/src/receiver.cpp
Server/src/runnable.cpp
Server/src/server.cpp
Server/src/tcpserver.cpp
Server/src/transmitter.cpp
docs/cliente_servidor.dia

index 0b59c0b8040470fa36ec54d6cd17b0ef14e9112d..1b42b2b8a6742b158dc5362f0ea6329042f3db3c 100644 (file)
@@ -62,8 +62,13 @@ Principal::Principal(BaseObjectType *co, const Glib::RefPtr<Gnome::Glade::Xml> &
 
 Principal::~Principal()
 {
-       if (conexion != NULL)
-               delete conexion;
+       if (conexion) {
+               conexion->finish();
+       }
+       // Espera a que termine realmente.
+       while (conexion) {
+               Glib::usleep(10000); // 10 milisegundos
+       }
 }
 
 void Principal::on_dlg_connect_ok()
@@ -75,8 +80,9 @@ void Principal::on_dlg_connect_ok()
                }
                catch (...) {
                        txt_view->get_buffer()->insert_at_cursor("NO SE PUDO CREAR OBJETO\n");
-                       delete conexion;
-                       conexion == NULL;
+                       //delete conexion; XXX Si no me equivoco, si falla el
+                       //constructor, no se reserva la memoria (el delete no va).
+                       conexion = NULL;
                        return;
                }
 
@@ -122,7 +128,7 @@ void Principal::on_mnu_file_disconnect()
 
        PlaQui::Server::Command c("connection", "stop");
        c.add_arg(conexion->get_host());
-       c.add_arg("7522");
+       c.add_arg(conexion->get_port());
        conexion->send(c);
 }
 
index 00745573be6309ea6102143d6b495af1fbf6eb64..6f78b534f47152ad6cd9b62875c746f721d082a3 100644 (file)
@@ -43,6 +43,7 @@ namespace Server {
        /// Pedido HTTP.
        class Command: private HTTPRequest {
 
+               /////////////////////////////////////////////////////////////////////
                // Tipos.
 
                public:
@@ -50,6 +51,7 @@ namespace Server {
                        /// Tipo de métodos HTTP reconocidos.
                        typedef std::vector<std::string> Arguments;
 
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
                private:
@@ -63,6 +65,7 @@ namespace Server {
                        /// Lista de argumentos que recibe el comando.
                        Arguments args;
 
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                private:
index 1eab7faf8a1dbbe969e23fd90ad7d7481d1bb4b3..7eda17226a1e882a09e967f9e5b7f80081fb4ed5 100644 (file)
@@ -38,6 +38,7 @@ namespace Server {
        /// Conexión.
        class Connection: public Runnable {
 
+               /////////////////////////////////////////////////////////////////////
                // Tipos.
 
                public:
@@ -45,6 +46,7 @@ namespace Server {
                        /// Puerto.
                        typedef unsigned Port;
 
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
                protected:
@@ -61,6 +63,7 @@ namespace Server {
                        /// Mutex para el socket.
                        //Glib::Mutex socket_mutex;
 
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                public:
@@ -98,13 +101,10 @@ namespace Server {
                        /**
                         * Finaliza la conexión.
                         *
-                        * \param attach Si es true, la función no retorna hasta que no
-                        *               finalice la tearea (no recomendable).
-                        *
                         * \note Para saber cuando la tarea fue finalizada puede utilizar
                         *       la señal signal_finished().
                         */
-                       virtual void finish(bool attach = false);
+                       virtual void finish(void);
 
                        /**
                         * Obtiene el nombre del host local de la conexión.
index d046c8fa315e487a7029ef469b39b9d32cf1f501..254f815f2d975f6a49e9767013ed76533ec28519 100644 (file)
@@ -40,6 +40,7 @@ namespace Server {
        /// Conexión para enviar comandos de control a una planta.
        class ControlClient: public Connection {
 
+               /////////////////////////////////////////////////////////////////////
                // Tipos.
 
                public:
@@ -53,6 +54,7 @@ namespace Server {
                        /// Tipo de señal para indicar que se recibió un error.
                        typedef SigC::Signal1<void, unsigned> SignalErrorReceived;
 
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
                protected:
@@ -69,6 +71,7 @@ namespace Server {
                        /// Receptor del estado de la planta TODO Temporal.
                        Receiver* receiver;
 
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                private:
index 25d122453487eb5ee6345178ea779be8f51f3298..a5cb0feec017f6ec78841bc1ce6a877e245cfec9 100644 (file)
@@ -41,7 +41,7 @@ namespace Server {
        /// Conexión para recibir comandos de control para una planta.
        class ControlServer: public Connection {
 
-
+               /////////////////////////////////////////////////////////////////////
                // Tipos.
 
                public:
@@ -49,7 +49,7 @@ namespace Server {
                        /// Tipo de señal para indicar que se recibió un comando.
                        typedef SigC::Signal1<void, const Command&> SignalCommandReceived;
 
-
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
                private:
@@ -57,7 +57,7 @@ namespace Server {
                        /// Señal para indicar que se recibió un comando.
                        SignalCommandReceived command_received;
 
-
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                protected:
index 1cc4ee80a1c7a1ecd98c01fac419e32fdc989804..e55bf618316112e01e9fd0323aeac66feaf08ac8 100644 (file)
@@ -40,6 +40,7 @@ namespace Server {
        /// Error HTTP.
        class HTTPError: public std::runtime_error {
 
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
                public:
@@ -47,6 +48,7 @@ namespace Server {
                        /// Código de error.
                        unsigned code;
 
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                public:
index 23470f3e33f0597392274265bfaf0525b5a9c9f1..ce703b2ea81b8f109158731b8a284b5dc5c80a8f 100644 (file)
@@ -42,6 +42,7 @@ namespace Server {
        /// Cabeceras HTTP.
        class HTTPHeaders: public std::map<std::string, std::string> {
 
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                public:
index 30bc794de5dd336709934409ce984f5df2826dd6..37c0287764c7771ecdb3aadabdb50f1f67e39174 100644 (file)
@@ -38,6 +38,7 @@ namespace Server {
        /// Pedido HTTP.
        class HTTPMessage {
 
+               /////////////////////////////////////////////////////////////////////
                // Constantes.
 
                public:
@@ -52,6 +53,7 @@ namespace Server {
                        static const unsigned NOT_IMPLEMENTED            = 501;
                        static const unsigned HTTP_VERSION_NOT_SUPPORTED = 505;
 
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
                private:
@@ -67,6 +69,7 @@ namespace Server {
                        /// Cabeceras HTTP.
                        HTTPHeaders headers;
 
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                public:
index 5f0757ef66aeb064b53a0d2a9ad63ab43b6b554b..7b43f67c29bc3faaa5e9b623f7b67679f5699394 100644 (file)
@@ -42,6 +42,7 @@ namespace Server {
        /// Pedido HTTP.
        class HTTPRequest: public HTTPMessage {
 
+               /////////////////////////////////////////////////////////////////////
                // Constantes.
 
                protected:
@@ -73,6 +74,7 @@ namespace Server {
                        /// Caracteres no hexa para URIs (RFC 2396).
                        static const std::string CHARS_HEX;
 
+               /////////////////////////////////////////////////////////////////////
                // Tipos.
 
                public:
@@ -80,6 +82,7 @@ namespace Server {
                        /// Tipo de métodos HTTP reconocidos.
                        typedef enum {GET, POST} HTTPMethod;
 
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
                protected: // TODO hacer privados con get() y set() ???
@@ -96,6 +99,7 @@ namespace Server {
                        /// Query string.
                        std::string query;
 
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                public:
index 5aa8f626b1e5154ae433d1b9f7093eacd4154777..09ff21d02d7f5b849cb7aa2183e95a481934082e 100644 (file)
@@ -40,6 +40,7 @@ namespace Server {
        /// Respuesta HTTP.
        class HTTPResponse: public HTTPMessage {
 
+               /////////////////////////////////////////////////////////////////////
                // Tipos.
 
                public:
@@ -51,6 +52,7 @@ namespace Server {
                                MISSING_HTTP_RESPONSE_CODE
                        } Error;
 
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
                //protected: FIXME - hacer privado con get/set?
@@ -62,6 +64,7 @@ namespace Server {
                        /// Descripción del código (razón).
                        std::string reason;
 
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                public:
index 31aea96814261077799404d2c619c2c35a8e5341..753899b209a5fe06efdb67974f4dff7588e73888 100644 (file)
@@ -40,7 +40,7 @@ namespace Server {
        /// Planta Química.
        class Plant: public Runnable {
 
-
+               /////////////////////////////////////////////////////////////////////
                // Tipos.
 
                private:
@@ -48,7 +48,7 @@ namespace Server {
                        /// Lista de conexiones de control.
                        typedef std::list<Transmitter*> TransmitterList;
 
-
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
                private:
@@ -68,7 +68,7 @@ namespace Server {
                        /// Nombre del archivo donde esta el XML de la planta.
                        std::string filename;
 
-
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                protected:
index 462c739bbaadd2b91d97df40f342a2282e624efe..c33fd287b1bdfd94ffe235b606f09a6369bf4cc5 100644 (file)
@@ -40,6 +40,7 @@ namespace Server {
        /// Conexión para recibir el estado de una planta.
        class Receiver: public Connection {
 
+               /////////////////////////////////////////////////////////////////////
                // Constantes.
 
                private:
@@ -50,7 +51,7 @@ namespace Server {
                        /// Marca de fin de frame.
                        static const std::string FRAME_END;
 
-
+               /////////////////////////////////////////////////////////////////////
                // Tipos.
 
                public:
@@ -66,7 +67,7 @@ namespace Server {
                        /// Señal que indica que se recibió un cuadro.
                        SignalFrameReceived frame_received;
 
-
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                private:
index c46cf8cffedb9eea836e5e42bb6dde6972fa127a..258cd2df131b91f6531a5f10a51c5e5977a5523c 100644 (file)
@@ -38,6 +38,7 @@ namespace Server {
        /// ealizauna tarea (generalmente en un thread).
        class Runnable {
 
+               /////////////////////////////////////////////////////////////////////
                // Tipos.
 
                public:
@@ -51,28 +52,27 @@ namespace Server {
                        /// Tipo de señal para indicar que hubo un error.
                        typedef SigC::Signal2<void, const Error&, const std::string&> SignalError;
 
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
                private:
 
                        /// Thread en el cual correr la tarea.
-                       Glib::Thread* thread;
+                       Glib::Thread* _thread;
 
                        /// Señal que indica que se finalizó la tarea.
-                       SignalFinished finished;
-
-               protected:
+                       SignalFinished _finished;
 
                        /// Señal que indica que hubo un error.
-                       SignalError error;
+                       SignalError _error;
 
-                       /**
-                        * Indica si se debe frinalizar la tarea.
-                        *
-                        * \todo Poner como privado y poner get() set() con locks.
-                        */
-                       bool stop;
+                       /// Indica si se debe frinalizar la tarea.
+                       bool _stop;
 
+                       /// Mutex para stop.
+                       Glib::Mutex stop_mutex;
+
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                private:
@@ -86,7 +86,23 @@ namespace Server {
 
                protected:
 
-                       /// Realiza la terea.
+                       /**
+                        * Indica si la tarea debe finalizar.
+                        */
+                       bool stop(void);
+
+                       /**
+                        * Establece si la tarea debe finalizar.
+                        *
+                        * \param stop Nuevo valor.
+                        *
+                        * \return Valor anterior.
+                        */
+                       bool stop(bool stop);
+
+                       /**
+                        * Realiza la terea.
+                        */
                        virtual void real_run(void) = 0;
 
                public:
@@ -112,13 +128,10 @@ namespace Server {
                        /**
                         * Finaliza la tarea.
                         *
-                        * \param attach Si es true, la función no retorna hasta que no
-                        *               finalice la tearea (no recomendable).
-                        *
                         * \note Para saber cuando la tarea fue finalizada puede utilizar
                         *       la señal signal_finished().
                         */
-                       virtual void finish(bool attach = false);
+                       virtual void finish(void);
 
                        /**
                         * Obtiene la señal que avisa cuando la tarea es finalizada.
index ae83251fd9322dfc49fbaca2825684ac0e2e4cbd..f8757e7f62c997f1a0b4c79cb59b77b4ee5ebf9c 100644 (file)
@@ -47,6 +47,7 @@ namespace Server {
         */
        class Server: public TCPServer {
 
+               /////////////////////////////////////////////////////////////////////
                // Tipos.
 
                private:
@@ -54,6 +55,7 @@ namespace Server {
                        /// Lista de plantas químicas.
                        typedef std::map<std::string, Plant*> PlantList;
 
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
                private:
@@ -64,6 +66,7 @@ namespace Server {
                        /// Mutex para las plantas.
                        Glib::Mutex plants_mutex;
 
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                protected:
index 96e2bb864dc36a18400e60d1af43ce689896cbad..9c0d72a38550e69ba1b4e19179c13f1641dcfb9f 100644 (file)
@@ -51,9 +51,12 @@ namespace Server {
                return p2;
        }
 
-       /// Conexión.
+       /// String con varios métodos útiles.
        class String: public std::string {
 
+               /////////////////////////////////////////////////////////////////////
+               // Métodos.
+
                public:
 
                        /// Caracteres que son considerados espacios a la hora de parsear.
index a64b545eeaf9b64f7296d6872ca523c0b82f551e..d94918e5fdbc09f72e580698dd284449d9cdb800 100644 (file)
@@ -44,6 +44,7 @@ namespace Server {
         */
        class TCPServer: public Runnable {
 
+               /////////////////////////////////////////////////////////////////////
                // Constantes.
 
                private:
@@ -51,6 +52,7 @@ namespace Server {
                        /// Cantidad máxima de conexiones pendientes.
                        static const unsigned MAX_PENDING_CONNECTIONS = 10;
 
+               /////////////////////////////////////////////////////////////////////
                // Tipos.
 
                private:
@@ -71,12 +73,14 @@ namespace Server {
                        /// Lista de información de conexiones de control.
                        typedef std::vector<ConnectionInfo> ConnectionInfoList;
 
+               /////////////////////////////////////////////////////////////////////
                // Atributos.
 
-               private:
+               protected: //FIXME
 
                        /// Socket para escuchar conexiones.
                        sockinetbuf socket;
+               private: // FIXME
 
                        /// Conexiones de control.
                        ConnectionList connections;
@@ -84,6 +88,7 @@ namespace Server {
                        /// Mutex para las conexiones.
                        Glib::Mutex connections_mutex;
 
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                private:
@@ -121,13 +126,10 @@ namespace Server {
                        /**
                         * Finaliza la tarea.
                         *
-                        * \param attach Si es true, la función no retorna hasta que no
-                        *               finalice la tearea (no recomendable).
-                        *
                         * \note Para saber cuando la tarea fue finalizada puede utilizar
                         *       la señal signal_finished().
                         */
-                       //virtual void finish(bool attach = false);
+                       //virtual void finish(void);
 
                        /**
                         * Se encarga de borrar una conexión de la lista cuando finaliza.
index acf38e89b294d2fe5d1471de16f05381d752dcea..624ff3b8ac0adca616bee25fa52c612fac82c2d6 100644 (file)
@@ -38,6 +38,7 @@ namespace Server {
        /// Conexión para transmitir el estado de una planta.
        class Transmitter: public Connection {
 
+               /////////////////////////////////////////////////////////////////////
                // Métodos.
 
                private:
index 75915c96918ff34ab05e7ccd18d1d23c95eb2949..c355c86d0cf7e195627e69e5afd1c5a7870197e6 100644 (file)
@@ -74,19 +74,21 @@ Connection::Connection(const std::string& host, const Port& port):
 #endif // DEBUG
 }
 
-void Connection::finish(bool attach) {
+void Connection::finish(void) {
 #ifdef DEBUG
        cerr << __FILE__ << "(" << __LINE__ << ")"
-               << ": finish(attach = " << attach << ")." << endl;
+               << ": finish();" << endl;
 #endif // DEBUG
        //socket_mutex.lock();
        try {
                socket->shutdown(sockbuf::shut_readwrite);
+               // FIXME socket->close(sockbuf::shut_readwrite);
+               // close(socket->sd());
        } catch (const sockerr& e) {
-               error(e.serrno(), e.errstr());
+               signal_error().emit(e.serrno(), e.errstr());
        }
        //socket_mutex.unlock();
-       Runnable::finish(attach);
+       Runnable::finish();
 }
 
 const string& Connection::get_host(void) const {
index 75e330b5d3cfa8898c31e5cd1128e75527c6971f..653fcaecfb9424f1cce8013ac29a544e25188d7d 100644 (file)
@@ -43,7 +43,9 @@ ControlClient::~ControlClient(void) {
                << ": destructor." << endl;
 #endif // DEBUG
        // TODO Temporal: espero que el receiver muera.
-       receiver->finish(true);
+       // Conectar señal on_receiver_finished() y esperar a que el puntero sea
+       // NULL para saber que terminó.
+       receiver->finish();
 }
 
 ControlClient::ControlClient(const string& _host,
@@ -75,14 +77,14 @@ void ControlClient::real_run(void) {
        try {
        } catch (const sockerr& e) {
                // TODO Poner una señal de error específica?
-               error(e.serrno(), e.errstr());
+               signal_error().emit(e.serrno(), e.errstr());
                return;
        }
        // TODO sacar signal_connected?
        connected();
        // TODO Temporal: el receiver empieza a escuchar.
        receiver->run();
-       while (!stop) {
+       while (!stop()) {
                HTTPResponse response;
                try {
                        //Glib::Mutex::Lock lock(socket_mutex);
@@ -90,10 +92,10 @@ void ControlClient::real_run(void) {
                // Si se cerró el socket.
                } catch (const ios::failure& e) {
                        // TODO poner buenos codigos de error.
-                       error(1000000, "Se desconectó.");
+                       signal_error().emit(1000000, "Se desconectó.");
                        return;
                } catch (const sockerr& e) {
-                       error(e.serrno(), e.errstr());
+                       signal_error().emit(e.serrno(), e.errstr());
                        return;
                // Si hay un error al parsear la respuesta.
                } catch (const HTTPResponse::Error& e) {
@@ -120,7 +122,7 @@ void ControlClient::send(const Command& command) {
        try {
                socket << command << flush;
        } catch (const sockerr& e) {
-               error(e.serrno(), e.errstr());
+               signal_error().emit(e.serrno(), e.errstr());
                finish();
        }
 #ifdef DEBUG
index a9cf729fd091c1662b6733c0a0b3b4cb47d914ee..41d54197a42cce37d37b3bdebb2b88f44c592a2e 100644 (file)
@@ -63,17 +63,17 @@ void ControlServer::real_run(void) {
                << ": real_run()" << endl;
 #endif // DEBUG
        //char buf[BUFSIZ];
-       while (!stop) {
+       while (!stop()) {
                Command command;
                try {
                        //Glib::Mutex::Lock lock(socket_mutex);
                        socket >> command;
                } catch (const ios::failure& e) {
                        // TODO poner buenos codigos de error.
-                       error(1000000, "Se desconectó.");
+                       signal_error().emit(1000000, "Se desconectó.");
                        return;
                } catch (const sockerr& e) {
-                       error(e.serrno(), e.errstr());
+                       signal_error().emit(e.serrno(), e.errstr());
                        return;
                // Si se cerró el socket.
                //} catch (const ios::failure& e) {
index 7ac8ff4b331f5cf1fd47a885997468c2efaf7283..08c7cd50a5dbe83fb28ca82e30a3a3de42794cd2 100644 (file)
@@ -82,6 +82,10 @@ int main(int argc, char* argv[]) {
        } catch (const sockerr& e) {
                cerr << "Socket Error: " << e.operation() << " | serrno = "
                        << e.serrno() << " | errstr = " << e.errstr() << endl;
+               if (e.serrno() == 98) {
+                       cerr << "No se puede usar el puerto " << port << " porque ya está "
+                               "siendo utilizado por otro programa." << endl;
+               }
                if (e.io()) {
                        cerr << "Es: non-blocking and interrupt io recoverable error."
                                << endl;
@@ -112,16 +116,23 @@ int main(int argc, char* argv[]) {
        // Conecto señal para atender errores.
        server->signal_error().connect(SigC::slot(on_error));
 
+       // Conecto señal para atender la finalización del server.
+       server->signal_finished().connect(SigC::slot(on_finished));
+
        // Corre el server.
-       server->run(false);
+       server->run();
 
        // Espera a que el server se muera.
        while (server) {
-               Glib::usleep(1000000);
+               //cerr << "-----------------\n\nAHHHHHHH\n\n----------------" << endl;
+               Glib::usleep(100000); // 0,1 segundos
        }
+       // Espera un segundo más por las dudas, para asegurarse de que terminó.
+       Glib::usleep(1000000); // 1 segundo
 
        // Como no detachee el server, lo tengo que eliminar a mano.
        //delete server;
 
        return 0;
 }
+
index b020e2109e9882c4389bbe4405967c377825cb57..0e70a1fb17c8139500897f27bfd09379bcc9d602 100644 (file)
@@ -44,11 +44,20 @@ Plant::~Plant(void) {
        cerr << __FILE__ << "(" << __LINE__ << ")"
                << ": destructor." << endl;
 #endif // DEBUG
-       // Termino transmisiones.
-       Glib::Mutex::Lock lock(transmissions_mutex);
-       for (TransmitterList::iterator trans = transmissions.end();
+       // Mando a terminar todas las transmisiones.
+       transmissions_mutex.lock();
+       for (TransmitterList::iterator trans = transmissions.begin();
                        trans != transmissions.end(); trans++) {
-               (*trans)->finish(true);
+               (*trans)->finish();
+       }
+       TransmitterList::size_type count = transmissions.size();
+       transmissions_mutex.unlock();
+       // Espero que terminen realmente.
+       while (count) {
+               Glib::usleep(10000); // 10 milisegundos
+               transmissions_mutex.lock();
+               count = transmissions.size();
+               transmissions_mutex.unlock();
        }
 }
 
@@ -76,7 +85,7 @@ void Plant::real_run(void) {
        cerr << __FILE__ << "(" << __LINE__ << ")"
                << ": real_run." << endl;
 #endif // DEBUG
-       while (!stop) {
+       while (!stop()) {
                simulator_mutex.lock();
                simulator.simulate();
                string plantstatus = simulator.get_state_as_xml();
@@ -87,7 +96,7 @@ void Plant::real_run(void) {
                        (*i)->send(plantstatus);
                }
                transmissions_mutex.unlock();
-               Glib::usleep(1000000);
+               Glib::usleep(100000);
        }
 }
 
index 22cc1a89d5a03a4b4bd5f524fd80efe7baf4a012..6e6c503492662b9be5666e1577de2a04d48d29da 100644 (file)
@@ -68,13 +68,13 @@ void Receiver::real_run(void) {
        char buf[BUFSIZ];
        bool in_frame = false;
        stringstream ss;
-       while (!stop) {
+       while (!stop()) {
                try {
                        if (!socket.getline(buf, BUFSIZ)) {
                                return; // Se terminó la transmision.
                        }
                } catch (const sockerr& e) {
-                       error(e.serrno(), e.errstr());
+                       signal_error().emit(e.serrno(), e.errstr());
                        return;
                }
                string sbuf = buf;
index d9d5048ecbacf0dea076a3c43ab22251e7c317dc..7079143d86a27ba5044182299a4b3a1cd324331a 100644 (file)
@@ -46,7 +46,7 @@ Runnable::~Runnable(void) {
 #endif // DEBUG
 }
 
-Runnable::Runnable(void): thread(0), stop(false) {
+Runnable::Runnable(void): _thread(NULL), _stop(false) {
 #ifdef DEBUG
        cerr << __FILE__ << "(" << __LINE__ << ")"
                << ": constructor." << endl;
@@ -56,12 +56,10 @@ Runnable::Runnable(void): thread(0), stop(false) {
 void Runnable::static_run(Runnable* runner) {
 #ifdef DEBUG
        cerr << __FILE__ << "(" << __LINE__ << ")"
-               << ": static_run(runner = " << runner << ")"
-               << endl;
+               << ": static_run(runner = " << runner << ")" << endl;
 #endif // DEBUG
        runner->real_run();
-       runner->finished();
-       //runner->thread->join();
+       runner->_finished();
        delete runner;
 }
 
@@ -74,9 +72,9 @@ void Runnable::run(bool detach) {
        if (detach) {
                // Corremos el thread en una funcion estática para poder destruirlo al
                // finalizar, pasandole el puntero al objeto.
-               thread = Glib::Thread::create(
+               _thread = Glib::Thread::create(
                                SigC::bind<Runnable*>(SigC::slot(&Runnable::static_run), this),
-                               true);//false);
+                               false);//true);
        // Si no corremos la tarea normalmente.
        } else {
                real_run();
@@ -84,23 +82,33 @@ void Runnable::run(bool detach) {
                
 }
 
-void Runnable::finish(bool attach) {
+void Runnable::finish(void) {
 #ifdef DEBUG
        cerr << __FILE__ << "(" << __LINE__ << ")"
-               << ": finish(attach = " << attach << ")" << endl;
+               << ": finish();" << endl;
 #endif // DEBUG
-       stop = true;
-       if (attach) {
-               thread->join();
-       }
+       stop(true);
+}
+
+bool Runnable::stop(void) {
+       Glib::Mutex::Lock lock(stop_mutex);
+       bool tmp = _stop;
+       return tmp;
+}
+
+bool Runnable::stop(bool stop) {
+       Glib::Mutex::Lock lock(stop_mutex);
+       bool tmp = _stop;
+       _stop = stop;
+       return tmp;
 }
 
 Runnable::SignalFinished& Runnable::signal_finished(void) {
-       return finished;
+       return _finished;
 }
 
 Runnable::SignalError& Runnable::signal_error(void) {
-       return error;
+       return _error;
 }
 
 } // namespace Server
index 340c2f05801dbeebdc216f63a056e851f5413b16..e332866d37954f4b22da97a9dbb3b3c1ae976d41 100644 (file)
@@ -29,6 +29,7 @@
 #include "plaqui/server/connection.h"
 #include "plaqui/server/controlserver.h"
 #include <sigc++/class_slot.h>
+#include <glibmm/timer.h>
 #include <sstream>
 #include <exception>
 #ifdef DEBUG
@@ -47,10 +48,19 @@ Server::~Server(void) {
        cerr << __FILE__ << "(" << __LINE__ << ")"
                <<  ": destructor." << endl;
 #endif // DEBUG
-       // Termino plantas.
-       Glib::Mutex::Lock lock(plants_mutex);
-       for (PlantList::iterator i = plants.end(); i != plants.end(); i++) {
-               i->second->finish(true);
+       // Mando a terminar todas las plantas.
+       plants_mutex.lock();
+       for (PlantList::iterator i = plants.begin(); i != plants.end(); i++) {
+               i->second->finish();
+       }
+       PlantList::size_type count = plants.size();
+       plants_mutex.unlock();
+       // Espero que terminen realmente.
+       while (count) {
+               Glib::usleep(10000); // 10 milisegundos
+               plants_mutex.lock();
+               count = plants.size();
+               plants_mutex.unlock();
        }
 }
 
@@ -60,7 +70,7 @@ Server::Server(const string& plant_filename, const Connection::Port& port)
        cerr << __FILE__ << "(" << __LINE__ << ")"
                <<  ": port = " << port << endl;
 #endif // DEBUG
-       // FIXME
+       // FIXME - hacer que se puedan cargar mas plantas bien.
        Glib::Mutex::Lock lock(plants_mutex);
        plants["default"] = new Plant(plant_filename);
        plants["default"]->signal_finished().connect(
@@ -114,6 +124,19 @@ void Server::on_control_command_received(const Command& command,
                        finish();
                        response = new HTTPResponse(HTTPMessage::OK,
                                        "<response desc=\"El server se apagará en instantes...\" />");
+                       response->headers["Content-Type"] = "text/xml; charset=iso-8859-1";
+                       controlserver->send(*response);
+                       delete response;
+                       // Creo una conexión suicida para que el accept() del server retorne
+                       // el control y el server pueda terminar realmente.
+                       try {
+                               sockinetbuf suicida(sockbuf::sock_stream);
+                               suicida.connect(socket.localhost(), socket.localport());
+                       } catch (...) {
+                               // FIXME
+                               signal_error().emit(12345, "ahhhh! no puedo crear conexion suicida");
+                       }
+                       return;
                } else {
                        response = new HTTPResponse(HTTPMessage::NOT_FOUND,
                                        "<response desc=\"Invalid command for 'server' taget!\" />");
index ffbdead609cf9ae0ac28fe20fef4f232ae3780fc..8272e57aaf35456ce283410501ac1922dcb3e195 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "plaqui/server/tcpserver.h"
 #include <sigc++/class_slot.h>
+#include <glibmm/timer.h>
 #ifdef DEBUG
 #      include <iostream>
 #endif // DEBUG
@@ -42,10 +43,20 @@ TCPServer::~TCPServer(void) {
        cerr << __FILE__ << "(" << __LINE__ << ")"
                <<  ": destructor." << endl;
 #endif // DEBUG
-       Glib::Mutex::Lock lock(connections_mutex);
+       // Mando a terminar todas las conexiones.
+       connections_mutex.lock();
        for (ConnectionList::iterator con = connections.begin();
                        con != connections.end(); con++) {
-               (*con)->finish(true);
+               (*con)->finish();
+       }
+       ConnectionList::size_type count = connections.size();
+       connections_mutex.unlock();
+       // Espero que terminen realmente.
+       while (count) {
+               Glib::usleep(10000); // 10 milisegundos
+               connections_mutex.lock();
+               count = connections.size();
+               connections_mutex.unlock();
        }
 }
 
@@ -75,8 +86,13 @@ TCPServer::TCPServer(const Connection::Port& port) throw(sockerr):
 }
 
 /*void TCPServer::finish(bool attach) {
+#ifdef DEBUG
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": finish(attach = " << attach << ");" << endl;
+#endif // DEBUG
        //socket_mutex.lock();
-       socket.shutdown(sockbuf::shut_readwrite);
+       close(socket.sd());
+       //socket.shutdown(sockbuf::shut_readwrite);
        //socket_mutex.unlock();
        Runnable::finish(attach);
 }*/
@@ -106,12 +122,12 @@ void TCPServer::real_run(void) {
                <<  ": real_run()" << endl;
 #endif // DEBUG
        Connection* connection;
-       while (!stop) {
+       while (!stop()) {
                // Forma grasa de salir del accept: crear conexion que salga al toque.
                try {
                        connection = new_connection(socket.accept());
                } catch (const sockerr& e) { // No se si el accept() puede fallar.
-                       error(e.serrno(), e.errstr());
+                       signal_error().emit(e.serrno(), e.errstr());
                        continue; // Supongo que puede seguir aceptando conexiones.
                }
 #ifdef DEBUG
index 6ab9260ae3a3267b81e81ef7c9f7bd8b83ac9890..4348da6d80e01c07f118fde1a6460ff689079c3d 100644 (file)
@@ -71,7 +71,7 @@ void Transmitter::real_run(void) {
                << ": real_run()." << endl;
 #endif // DEBUG
        // No hace nada, porque solo actua cuando se manda algo con send().
-       while (!stop) {
+       while (!stop()) {
                Glib::usleep(500000); // 1/2 segundo
        }
 }
@@ -82,14 +82,14 @@ void Transmitter::send(const string& data) {
                << ": send()." << endl;
 //             << ": send(data = " << data << ")." << endl;
 #endif // DEBUG
-       if (stop) {
+       if (stop()) {
                return;
        }
        try {
                socket << data << flush;
        } catch (const sockerr& e) {
-               error(e.serrno(), e.errstr());
-               stop = true;
+               signal_error().emit(e.serrno(), e.errstr());
+               stop(true);
        }
 }
 
index cad9d442b557cc3c19d37c7ea440f9bbaf5cd5e8..1869c188757e8ed71d76bb0ce873756b9ab585e9 100644 (file)
Binary files a/docs/cliente_servidor.dia and b/docs/cliente_servidor.dia differ