Updated license
[anna.git] / include / anna / app / Application.hpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #ifndef anna_app_Application_hpp
38 #define anna_app_Application_hpp
39
40 #include <vector>
41
42 #include <anna/core/RuntimeException.hpp>
43
44 namespace anna {
45
46 namespace xml {
47 class Node;
48 }
49
50 namespace app {
51
52 class Component;
53 struct functions;
54
55 /**
56    Abstraccion de la aplicacion.
57
58    Mantiene la informacion de todos los recursos usados (version, titulo, linea de comandos,
59    threads, etc ...) por nuestras aplicaciones.
60
61    Slo puede haber una nica instancia de la aplicacio, que seria accesible mediante el
62    metodo anna::functions::getApp.
63 */
64 class Application {
65 public:
66   typedef std::vector <Component*>::iterator iterator;
67   typedef std::vector <Component*>::const_iterator const_iterator;
68   typedef std::vector <pid_t> pid_container;
69   typedef pid_container::iterator pid_iterator;
70   typedef pid_container::const_iterator const_pid_iterator;
71
72   /**
73      Constructor.
74
75      @param shortName Nombre logico de esta instancia.
76      @param title Titulo de la aplicacion que aparecera al arrancar.
77      @param version version de este programa. Aconsejamos el forma X.YRZZ. Donde X es la
78      version principal, Y la version secundaria y ZZ es el numero de entrega realizada.
79      \param date Fecha de realizacion del componente. Normalmente sera el contenido de la macro __DATE__.
80      \param time Hora de realizacion del componente. Normalmente sera el contenido de la macro __TIME__.
81   */
82   Application(const char* shortName, const char* title, const char* version, const char* date = NULL, const char* time = NULL);
83
84   /**
85      Destructor.
86   */
87   virtual ~Application() { a_components.clear(); }
88
89   // Accesores
90   /**
91      Devuelve el nombre corto indicado en el constructor.
92      \return El nombre corto indicado en el constructor.
93   */
94   const char* getShortName() const throw() { return a_shortName; }
95
96   /**
97      Devuelve la version indicado en el contructor de esta aplicacion.
98      \return La version indicado en el contructor de esta aplicacion.
99   */
100   const std::string& getVersion() const throw() { return a_version; }
101
102   /**
103      Devuelve el titulo indicado en el contructor de esta aplicacion.
104      \return el titulo indicado en el contructor de esta aplicacion.
105   */
106   const std::string& getTitle() const throw() { return a_title; }
107
108   /**
109      Devuelve el pid asignado por el sistema operativo a la aplicacion que estamos ejecutando.
110      @return El pid asignado por el sistema operativo a la aplicacion que estamos ejecutando.
111   */
112   pid_t getPid() const throw() { return a_pid; }
113
114   /**
115      Activa la salida por pantalla del mensaje referente a la licencia GPL 3.0.
116      \warning Para que tenga efecto debe ser invocado antes de ejecutar el metodo Application::start.
117   */
118   void activateGeneralPublicLicense() throw() { a_enableGPL = true; }
119
120   /**
121    * Crea un nuevo proceso a partir de este usando el metodo \em fork.
122    *
123    * Estrictamente este metodo retonara dos veces, una en el ambito del proceso que lo invoco y
124    * otra en el ambito del nuevo proceso, llamado proceso hijo.
125    *
126    * Si la duplicacion se realiza de forma correcta se invoca a los metodos #do_cloneChild y #do_cloneParent de nuestra
127    * aplicacion y Component::do_cloneChild y Component::do_cloneParent de cada uno de los componentes registrados.
128    *
129    * Para saber en cual de los procesos
130    * \return La instancia de la nueva aplicacion.
131    */
132   Application& clone() throw(RuntimeException);
133
134   /**
135      Devuelve la instancia del componente que corresponde con el nombre recibido.
136      \return La instancia del componente que corresponde con el nombre recibido. Puede ser NULL si no
137      hay ningun componente asociado a la �ta aplicacion que corresponda con el nombre.
138   */
139   Component* find(const char* className) throw();
140
141   /**
142      Inicializa los elementos propios de nuestra aplicacio, invoca al metodo #initialize
143      e invoca al metodo #run.
144   */
145   void start() throw(RuntimeException);
146
147   /**
148      Devuelve un iterador al primer componente definido en la aplicacion.
149      \return un iterador al primer componente definido en la aplicacion.
150   */
151   const_iterator begin() const throw() { return a_components.begin(); }
152
153   /**
154      Devuelve un iterador al primer componente definido en la aplicacion.
155      \return un iterador al primer componente definido en la aplicacion.
156   */
157   iterator begin() throw() { return a_components.begin(); }
158
159   /**
160      Devuelve un iterador al ultimo componente definido en la aplicacion.
161      \return un iterador al ultimo componente definido en la aplicacion.
162   */
163   const_iterator end() const throw() { return a_components.end(); }
164
165   /**
166      Devuelve un iterador al ultimo componente definido en la aplicacion.
167      \return un iterador al ultimo componente definido en la aplicacion.
168   */
169   iterator end() throw() { return a_components.end(); }
170
171   /**
172      Vuelva un documento XML con el contexto de la aplicacion.
173      \param file Ruta completa del fichero en el que grabar el contexto de la aplicacion.
174   */
175   void writeContext(const std::string& file) throw(RuntimeException);
176
177   /**
178      metodo que puede ser reescrito en las clases heredadas de Application y que nos
179      da la posibilidad de inicializar los elementos particulares de nuestra aplicacion.
180      Por defecto no realiza ninguna operacion.
181      \warning En el momento de invocar a esta funcin los componentes (\see Component) pueden no
182      estar disponibles.
183   */
184   virtual void initialize() throw(RuntimeException) {;}
185
186   /**
187      Devuelve si esta aplicacion tiene soporto para comunicaciones entre procesos.
188      \return \em true si la aplicacion tiene soporta para comunicacion entre proceso o \em false
189      en otro caso.
190   */
191   virtual bool supportCommunication() const throw() { return false; }
192
193   /**
194    * Este método se invocará cuando alguna capa superior a ésta detecte un problema tan grave
195    * como para parar la aplicación de forma súbita.
196    * \param className Nombre de la clase que genera el evento.
197    *
198    * \warning En el momento de invocar a este método la aplicación puede estar en un estado
199    * no muy estable por lo que se deberían minizar las operaciones a realizar para evitar
200    * bloquear la aplicación.
201    */
202   virtual void eventAbnormalTermination(const char* className) throw() { ; }
203
204   /**
205      Devuelve una cadena con la informacion referente a esta instancia.
206      \param parent Nodo XML del que dependende la informacion.
207      @return Una cadena con la informacion referente a esta instancia.
208   */
209   virtual xml::Node* asXML(xml::Node* parent) const throw();
210
211   /**
212      Devuelve el objeto sobre el que esta posicionado el iterator recibido como parametro.
213      \param ii Iterator que deberia estar comprendido entre #begin y #end.
214      \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
215   */
216   static const Component* component(const_iterator& ii) throw() { return *ii; }
217
218   /**
219      Devuelve el objeto sobre el que esta posicionado el iterator recibido como parametro.
220      \param ii Iterator que deberia estar comprendido entre #begin y #end.
221      \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
222   */
223   static Component* component(iterator& ii) throw() { return *ii; }
224
225 protected:
226   static Application* st_application;
227
228   /**
229      metodo que debemos implementar para ejecutar nuestra aplicacion.
230   */
231   virtual void run() throw(RuntimeException) = 0;
232
233   /**
234      Handler for SIGUSR1. Application context written by default.
235   */
236   virtual void signalUSR1() throw(RuntimeException);
237
238   /**
239      Handler for SIGUSR2. Nothing done by default.
240   */
241   virtual void signalUSR2() throw(RuntimeException);
242
243   /**
244      Metodo manejador que podemos re-escribir para tratar la recepcion de la senhal SIGTERM.
245   */
246   virtual void signalTerminate() throw(RuntimeException) {;}
247
248   /**
249    * Metodo que debemos implementar en la clase heredada para tratar el proceso de clonado de
250    * esta aplicacion desde el punto de vista del proceso original.
251    * \warning Si se detecta algun error terminara abortara la ejecucion del proceso hijo.
252    */
253   virtual void do_cloneParent() throw(RuntimeException) {;}
254
255   /**
256    * Metodo que debemos implementar en la clase heredada para tratar el proceso de clonado de
257    * esta aplicacion desde el punto de vista del proceso hijo.
258    * \warning Si se detecta algun error terminara abortara la ejecucion de este proceso.
259    */
260   virtual void do_cloneChild() throw(RuntimeException) {;}
261
262   /**
263      Devuelve un iterador al primer proceso hijo creado por la aplicacion (ver #clone),
264      \return un iterador al primer proceso hijo definido en la aplicacion.
265   */
266   pid_iterator pid_begin() throw() { return a_pids.begin(); }
267
268   /**
269      Devuelve un iterador al final de lista lista de procesos hijos creados por la aplicacion (ver #clone).
270      \return un iterador al primer proceso hijo definido en la aplicacion.
271   */
272   pid_iterator pid_end() throw() { return a_pids.end(); }
273
274   /**
275    * Devuelve el numero de procesos hijos.
276    * \return el numero de procesos hijos.
277    */
278   int pid_size() const throw() { return a_pids.size(); }
279
280   /**
281      Devuelve un iterador al primer proceso hijo creado por la aplicacion (ver #clone),
282      \return un iterador al primer proceso hijo definido en la aplicacion.
283   */
284   const_pid_iterator pid_begin() const throw() { return a_pids.begin(); }
285
286   /**
287      Devuelve un iterador al final de lista lista de procesos hijos creados por la aplicacion (ver #clone).
288      \return un iterador al primer proceso hijo definido en la aplicacion.
289   */
290   const_pid_iterator pid_end() const throw() { return a_pids.end(); }
291
292   /**
293      Devuelve el PID sobre el que esta posicionado el iterator recibido como parametro.
294      \param ii Iterator que deberia estar comprendido entre #pid_begin y #pid_end.
295      \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
296   */
297   static pid_t pid(pid_iterator& ii) throw() { return *ii; }
298
299   /**
300      Devuelve el PID sobre el que esta posicionado el iterator recibido como parametro.
301      \param ii Iterator que deberia estar comprendido entre #pid_begin y #pid_end.
302      \return El objeto sobre el que esta posicionado el iterator recibido como parametro.
303   */
304   static pid_t pid(const_pid_iterator& ii) throw() { return *ii; }
305
306 private:
307   bool a_running;
308   std::string a_version;
309   const std::string a_title;
310   std::vector <Component*> a_components;
311   pid_t a_pid;
312   const char* a_shortName;
313   bool a_enableGPL;
314   pid_container a_pids;
315
316   void attach(Component*) throw(RuntimeException);
317   void detach(Component*) throw(RuntimeException);
318
319   void startComponents() throw(RuntimeException);
320   void stopComponents() throw(RuntimeException);
321   void sendSignalToChilds(const int signal) throw();
322
323   void signalUSR(int) throw(RuntimeException);
324   static void handlerSignalUSR(int) throw();
325   static void handlerSignalTerminate(int) throw();
326   static void handlerChildTerminate(int sig) throw();
327
328   friend class Component;  // Para poder acceder a los metodo attach y detach
329   friend struct functions;
330 };
331
332 }
333 }
334
335 #endif
336