Avoid service overhead about checking netstat ports
[anna.git] / source / comm / Handler.cpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
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 //
7
8
9 #include <poll.h>
10
11 #include <anna/core/tracing/Logger.hpp>
12 #include <anna/core/mt/Semaphore.hpp>
13
14 #include <anna/xml/Node.hpp>
15 #include <anna/xml/Attribute.hpp>
16
17 #include <anna/comm/Communicator.hpp>
18 #include <anna/comm/Handler.hpp>
19 #include <anna/comm/Transport.hpp>
20
21 using namespace std;
22 using namespace anna;
23
24 //------------------------------------------------------------------------------------------------
25 // En modo MT aprovechamos las capacidades que tiene esta clase por el hecho de heredar de
26 // anna::Runnable -> invocaremos a do_action atraves de Runnnable::run.
27 //
28 // En modo ST invocamos directamente al Handler::apply.
29 //------------------------------------------------------------------------------------------------
30 void comm::Handler::do_action()
31 throw(RuntimeException) {
32   pollfd pollfd;
33   pollfd.fd = getfd();
34   pollfd.events = POLLIN | POLLRDNORM;
35   const int npoll = poll(&pollfd, 1, 1000);
36
37   if(npoll == -1 && errno != EINTR) {
38     const int xerrno(errno);
39     string msg(asString());
40     msg += " | Error checking messages";
41     throw RuntimeException(msg, xerrno, ANNA_FILE_LOCATION);
42   }
43
44   bool done(false);
45
46   if(supportTimeout() == false) {
47     if(npoll == 1 && (pollfd.revents & (POLLIN | POLLRDNORM)) != 0) {
48       done = true;
49       a_loop = 0;
50
51       try {
52         apply();
53       } catch(RuntimeException& ex) {
54         ex.trace();
55       }
56     }
57     /*
58      * En la práctica este código sólo se ejecutará en modo MT, ya que en modo ST, sólo se invocará a Handler::do_action
59      * cuando se compruebe que actividad en el 'fd' asociado a este manejador.
60      *
61      * Sin embargo en MT el thread está ejecutando este código periódicamente.
62      */
63     else if(++ a_loop == 5) {
64       a_loop = 0;
65
66       try {
67         testClose();
68       } catch(RuntimeException& ex) {
69         ex.trace();
70       }
71     }
72   } else {
73     Microsecond now(anna::functions::hardwareClock());
74
75     if(npoll == 1 && (pollfd.revents & (POLLIN | POLLRDNORM)) != 0) {
76       done = true;
77
78       try {
79         beat(now);
80         apply();
81       } catch(RuntimeException& ex) {
82         ex.trace();
83       }
84     } else if(isTimeout(now) == true) {
85       done = true;
86       LOGWARNING(
87         string msg(asString());
88         msg += " | Closed due to inactivity";
89         Logger::warning(msg, ANNA_FILE_LOCATION);
90       );
91       a_communicator->detach(this);
92     }
93   }
94
95   /**
96    * Parece ser que puede ser que además de los POLLIN y POLLRDNORN que estamos comprobando
97    * pueden aparecer más bits, POLLINVAL (p.e) lo que provocaría
98    */
99   if(npoll == 1 && done == false) {
100     LOGWARNING(
101       string msg(asString());
102       msg += " | Detected unsupported event";
103       Logger::warning(msg, ANNA_FILE_LOCATION);
104     )
105     a_communicator->detach(this);
106   }
107 }
108
109 std::string comm::Handler::asString() const
110 throw() {
111   string msg("comm::Handler { ");
112   msg += Runnable::asString();
113
114   if(a_type == Type::Custom)
115     msg += " | Type: Custom";
116
117   msg += functions::asString(" | fd: %d", a_fd);
118
119   if(a_timeout > 0) {
120     msg += " | Timeout: ";
121     msg += a_timeout.asString();
122     msg += " ms";
123   }
124
125   return msg += " }";
126 }
127
128 xml::Node* comm::Handler::asXML(xml::Node* parent) const
129 throw(RuntimeException) {
130   xml::Node* result = parent->createChild("comm.Handler");
131   asAttribute(result);
132   return result;
133 }
134
135 void comm::Handler::asAttribute(xml::Node* node) const
136 throw(RuntimeException) {
137   node->createAttribute("Id", getId());
138   node->createAttribute("RequestStop", anna::functions::asString(hasRequestedStop()));
139
140   if(a_type == Type::Custom)
141     node->createAttribute("Type", "Custom");
142
143   node->createAttribute("fd", a_fd);
144
145   if(supportTimeout())
146     node->createAttribute("Timeout", a_timeout / 1000);
147   else
148     node->createAttribute("Timeout", "none");
149 }
150