1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
18 #include <sys/types.h>
20 #include <anna/core/RuntimeException.hpp>
21 #include <anna/core/tracing/Logger.hpp>
22 #include <anna/core/functions.hpp>
23 #include <anna/core/tracing/TraceWriter.hpp>
24 #include <anna/core/tracing/TraceMethod.hpp>
25 #include <anna/core/internal/ModuleManager.hpp>
26 #include <anna/core/util/CommandLine.hpp>
28 #include <anna/app/Application.hpp>
29 #include <anna/app/Component.hpp>
30 #include <anna/app/internal/sccs.hpp>
31 #include <anna/app/functions.hpp>
33 #include <anna/xml/Node.hpp>
34 #include <anna/xml/Attribute.hpp>
35 #include <anna/xml/Compiler.hpp>
41 #define WEBSITE_PROJECT "http://redmine.teslayout.com/projects/anna-suite"
42 #define WEBSITE_GENERAL "http://www.teslayout.com"
44 app::Application* app::Application::st_application = NULL;
46 app::Application::Application(const char* shortName, const char* title, const char* version, const char* date, const char* time) :
47 a_shortName(shortName),
52 sigset(SIGUSR1, handlerSignalUSR);
53 sigset(SIGUSR2, handlerSignalUSR);
54 sigset(SIGTERM, handlerSignalTerminate);
56 app::sccs::activate();
57 a_version += functions::getArchitecture();
60 if(st_application == NULL)
61 st_application = this;
63 cout << a_shortName << " - " << a_title << ". Version " << a_version << endl;
66 cout << "Revision date: ";
68 if(date) cout << date << " ";
70 if(time) cout << time;
75 cout << "(c) Copyright 2001-2006 Eduardo Ramos Testillano & Francisco Antonio Ruiz Rayo" << endl;
76 cout << " eduardo.ramos.testillano@gmail.com & cisco.tierra@gmail.com" << endl;
77 cout << " (project site: " << WEBSITE_PROJECT << ")" << endl << endl;
78 //cout << " - Project site: " << WEBSITE_PROJECT << endl;
79 //cout << " - Main site: " << WEBSITE_GENERAL << endl << endl;
82 app::Component* app::Application::find(const char* className)
85 for(iterator ii = begin(), maxii = end(); ii != maxii; ii ++) {
86 component = Application::component(ii);
88 if(anna_strcmp(className, component->getClassName()) == 0)
96 * (1) Si se ejecuta el metodo clone evita que los hijos que termina se queden como zombies.
98 void app::Application::start()
100 TraceMethod tm("app::Application", "start", ANNA_FILE_LOCATION);
101 ModuleManager& moduleManager = ModuleManager::instantiate();
103 if(a_running == true) {
104 string msg("app::Application { Name; ");
106 msg += " | Already on execution";
107 throw RuntimeException(msg, ANNA_FILE_LOCATION);
110 if(sigset(SIGCHLD, handlerChildTerminate) != 0) // (1)
111 throw RuntimeException("Error installing terminate handler", ANNA_FILE_LOCATION);
114 if(a_enableGPL == true) {
115 cout << "This program is free software: you can redistribute it and/or modify" << endl;
116 cout << "it under the terms of the GNU General Public License as published by" << endl;
117 cout << "the Free Software Foundation, either version 3 of the License, or" << endl;
118 cout << "(at your option) any later version." << endl << endl;
119 cout << "This program is distributed in the hope that it will be useful," << endl;
120 cout << "but WITHOUT ANY WARRANTY; without even the implied warranty of" << endl;
121 cout << "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << endl;
122 cout << "GNU General Public License for more details." << endl << endl;
123 cout << "You should have received a copy of the GNU General Public License" << endl;
124 cout << "along with this program. If not, see <http://www.gnu.org/licenses/>." << endl << endl;
127 cout << "ANNA Suite. Version " << functions::getVersion() << endl;
128 cout << "Revision date: " << __DATE__ << " " << __TIME__ << endl;
129 cout << "(c) Copyright 2001-2006 Eduardo Ramos Testillano & Francisco Antonio Ruiz Rayo" << endl;
130 cout << " eduardo.ramos.testillano@gmail.com & cisco.tierra@gmail.com" << endl << endl;
132 cout << "Activating application modules ....................." << endl;
134 for(ModuleManager::const_iterator ii = moduleManager.begin(), maxii = moduleManager.end(); ii != maxii; ii ++) {
135 cout << "\t Module " << ModuleManager::module(ii) << endl;
144 } catch(RuntimeException& ex) {
151 void app::Application::startComponents()
153 LOGMETHOD(TraceMethod tm("app::Application", "startComponents", ANNA_FILE_LOCATION));
154 Component* component;
156 for(iterator ii = begin(); ii != end(); ii ++) {
157 component = Application::component(ii);
159 std::string msg("Starting component | ");
160 msg += component->asString();
161 Logger::write(Logger::Information, msg, ANNA_FILE_LOCATION);
163 component->initialize();
167 void app::Application::stopComponents()
169 LOGMETHOD(TraceMethod tm("app::Application", "stopComponents", ANNA_FILE_LOCATION));
170 Component* component;
172 for(iterator ii = begin(); ii != end(); ii ++) {
173 component = Application::component(ii);
175 std::string msg("Stopping component | ");
176 msg += component->asString();
177 Logger::write(Logger::Information, msg, ANNA_FILE_LOCATION);
184 * (1) Este el codigo que ejecuta la copia que acabamos de crear.
185 * (1.1) Limpia la lista de hijos que pudiera tener el padre.
187 app::Application& app::Application::clone()
189 if(anna::functions::supportMultithread() == true) {
190 string msg("app::Application::clone | pid: ");
191 msg += functions::asString((int) a_pid);
192 msg += " | Application clone is only supported for ST applications";
193 throw RuntimeException(msg, errno, ANNA_FILE_LOCATION);
196 const pid_t pid = ::fork();
199 string msg("app::Application::clone | pid: ");
200 msg += functions::asString((int) a_pid);
201 throw RuntimeException(msg, errno, ANNA_FILE_LOCATION);
204 Component* component;
206 if(pid == 0) { // (1)
207 Logger::showPID(true);
209 a_pids.clear(); // (1.1)
212 for(iterator ii = begin(); ii != end(); ii ++) {
213 component = Application::component(ii);
215 std::string msg("Cloning component on child | ");
216 msg += component->asString();
217 Logger::write(Logger::Information, msg, ANNA_FILE_LOCATION);
219 component->do_cloneChild();
223 } catch(RuntimeException& ex) {
229 string msg("app::Application::clone | Parent pid: ");
230 msg += functions::asString((int) a_pid);
231 msg += " | Child pid: ";
232 msg += functions::asString((int) pid);
233 Logger::warning(msg, ANNA_FILE_LOCATION);
237 for(iterator ii = begin(); ii != end(); ii ++) {
238 component = Application::component(ii);
240 std::string msg("Cloning component on parent | ");
241 msg += component->asString();
242 Logger::write(Logger::Information, msg, ANNA_FILE_LOCATION);
244 component->do_cloneParent();
248 a_pids.push_back(pid);
249 } catch(RuntimeException& ex) {
250 string msg("app::Application::clone | Abort execution: ");
251 msg += msg += functions::asString((int) pid);
252 Logger::error(msg, ANNA_FILE_LOCATION);
261 //---------------------------------------------------------------------------------------
262 // (1) Se invoca desde los constructores de los componentes => no se puede invocar a
263 // ningn m�odo virtual => obliga a que est� definidos antes de comenzar la
264 // ejecucin de la aplicacin => se inicilizar� en el Application::start ya que en
265 // ese momento los objetos est� completamente creados.
266 //---------------------------------------------------------------------------------------
267 void app::Application::attach(app::Component* component)
269 if(component == NULL)
270 throw RuntimeException("Cannot attach a NULL component", ANNA_FILE_LOCATION);
272 iterator ii = std::find(begin(), end(), component);
276 //string msg((*ii)->asString());
277 string msg((*ii)->getClassName());
278 msg += " | Was previously attached !";
279 Logger::write(Logger::Information, msg, ANNA_FILE_LOCATION);
285 string msg("app::Application::attach | ");
286 msg += component->asString();
287 Logger::debug(msg, ANNA_FILE_LOCATION);
289 a_components.push_back(component);
293 std::string msg("Starting component | ");
294 msg += component->asString();
295 Logger::write(Logger::Information, msg, ANNA_FILE_LOCATION);
297 component->initialize();
301 void app::Application::detach(app::Component* component)
303 LOGMETHOD(TraceMethod tm("app::Application", "detach(component)", ANNA_FILE_LOCATION));
305 if(component == NULL)
306 throw RuntimeException("Cannot detach a NULL component", ANNA_FILE_LOCATION);
309 string msg("app::Application::detach | ");
310 msg += component->asString();
311 Logger::debug(msg, ANNA_FILE_LOCATION);
313 iterator ii = std::find(begin(), end(), component);
316 LOGDEBUG(Logger::write(Logger::Debug, "Detached", (*ii)->asString(), ANNA_FILE_LOCATION));
317 a_components.erase(ii);
321 void app::Application::writeContext(const std::string& file)
324 out.open(file.c_str());
326 if(out.is_open() == false) {
327 string msg("Error opening '");
330 throw RuntimeException(msg, ANNA_FILE_LOCATION);
334 string msg("app::Application::writeContext | File: ");
336 Logger::notice(msg, ANNA_FILE_LOCATION);
338 xml::Node root("Application");
339 out << xml::Compiler().apply(asXML(&root)) << endl;
343 xml::Node* app::Application::asXML(xml::Node* app) const
345 xml::Node* node(NULL);
346 app->createAttribute("Name", getShortName());
347 app->createAttribute("Version", getVersion());
348 app->createAttribute("pid", getPid());
350 CommandLine::instantiate().asXML(app);
351 node = app->createChild("app.Clones");
353 for(const_pid_iterator ii = pid_begin(), maxii = pid_end(); ii != maxii; ii ++)
354 node->createChild("Clone")->createAttribute("PID", pid(ii));
356 ModuleManager& moduleManager = ModuleManager::instantiate();
357 node = app->createChild("app.Modules");
359 for(ModuleManager::const_iterator ii = moduleManager.begin(), maxii = moduleManager.end(); ii != maxii; ii ++)
360 node->createChild("Module")->createAttribute("Id", ModuleManager::module(ii));
363 node = app->createChild("app.Components");
365 for(const_iterator ii = begin(), maxii = end(); ii != maxii; ii ++) {
366 Guard guard(cc = component(ii));
373 void app::Application::signalUSR(int signal)
375 if (signal == SIGUSR1) signalUSR1();
376 else if (signal == SIGUSR2) signalUSR2();
379 void app::Application::signalUSR1()
381 writeContext(anna::functions::asString("/var/tmp/anna.context.%05d", getPid()));
384 void app::Application::signalUSR2()
386 Logger::notice("Captured signal SIGUSR2. Nothing implemented at the moment", ANNA_FILE_LOCATION);
389 void app::Application::sendSignalToChilds(const int signal)
391 for(pid_iterator ii = pid_begin(), maxii = pid_end(); ii != maxii; ii ++)
392 kill(pid(ii), signal);
395 void app::Application::handlerSignalUSR(int signal)
400 Application& app = anna::app::functions::getApp();
401 app.sendSignalToChilds(signal);
402 app.signalUSR(signal);
403 } catch(Exception& ex) {
407 sigset(signal, handlerSignalUSR);
410 void app::Application::handlerSignalTerminate(int)
416 Logger::write(Logger::Warning, "app::Application | Received SIGTERM", ANNA_FILE_LOCATION);
418 Application& app = anna::app::functions::getApp();
419 app.sendSignalToChilds(SIGTERM);
420 app.signalTerminate();
421 } catch(Exception& ex) {
426 sigset(SIGTERM, handlerSignalTerminate);
430 * Se recoge el estado de terminacion del hijo para que no se quede considerado como un zombie y se
431 * elimina de la lista de procesos hijos.
433 void app::Application::handlerChildTerminate(int sig)
437 pid_t pid = wait(&status);
439 if(st_application == NULL)
442 pid_iterator maxii = st_application->pid_end();
443 pid_iterator ii = ::find(st_application->pid_begin(), maxii, pid);
446 st_application->a_pids.erase(ii);