Fix local server for multiple applications
[anna.git] / handler / RemoteConnection.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 <anna/core/tracing/Logger.hpp>
10 #include <anna/core/functions.hpp>
11 #include <anna/core/mt/Guard.hpp>
12 #include <anna/core/tracing/TraceMethod.hpp>
13
14 #include <anna/xml/Node.hpp>
15 #include <anna/xml/Attribute.hpp>
16
17 #include <anna/comm/internal/RemoteConnection.hpp>
18 #include <anna/comm/Communicator.hpp>
19 #include <anna/comm/Device.hpp>
20 #include <anna/comm/Server.hpp>
21 #include <anna/comm/ClientSocket.hpp>
22 #include <anna/comm/internal/ConnectionRecover.hpp>
23 #include <anna/comm/Receiver.hpp>
24
25 #include <anna/comm/handler/RemoteConnection.hpp>
26
27 using namespace std;
28 using namespace anna;
29
30 //-------------------------------------------------------------------------------------------
31 // BackTrace:
32 // Host::createServer -> Server::connect -> Communicator::attach (RemoteConnection*) ->
33 // comm::handler::RemoteConnection::initialize
34 //-------------------------------------------------------------------------------------------
35
36 /*
37    <Guard Id="0x7fbfffeb68" Name="comm::Communicator::multithreadedAccept (ConnectionRecover)" LineNo="635">
38      <Method Id="comm::Server::connect" File="comm.Server.cc" Line="149" LineNo="637">
39         <Guard Id="0x7fbfffeb68" Name="comm::Communicator from comm::Server::connect" LineNo="639" Mode="Reentrant">
40            <Guard Id="0x690f20" Name="comm::Server::connect" LineNo="641">
41               <Method Id="comm::handler::RemoteConnection::initialize" File="handler.db/comm.handler.RemoteConnection.cc" Line="54" LineNo="643">
42                  <Guard Id="0x690ff0" Name="comm::ClientSocket (connect)" LineNo="645"/>
43                  <Method Id="comm::Communicator::eventCreateConnection" File="comm.Communicator.cc" Line="723" LineNo="655">
44                     <Method Id="comm::Delivery::recover" File="comm.Delivery.cc" Line="186" LineNo="659">
45                        <Guard Id="0x690750" Name="comm::Delivery::recover" LineNo="661">
46                           <Method Id="comm::Delivery::unsafe_recover" File="comm.Delivery.cc" Line="196" LineNo="663">
47                              <Guard Id="0x690f20" Name="Resource" LineNo="665" Mode="Reentrant"/>
48                           </Method>
49                        </Guard>
50                     </Method>
51                  </Method>
52               </Method>
53               <Guard Id="0x68f378" Name="anna::ThreadManager::createThread" LineNo="681"/>
54            </Guard>
55         </Guard>
56      </Method>
57 */
58 void comm::handler::RemoteConnection::initialize()
59 noexcept(false) {
60   LOGMETHOD(TraceMethod traceMethod("comm::handler::RemoteConnection", "initialize", ANNA_FILE_LOCATION));
61
62   if(a_remoteConnection == NULL) {
63     string msg(asString());
64     msg += " | No se ha establecido el comm::RemoteConnection";
65     throw RuntimeException(msg, ANNA_FILE_LOCATION);
66   }
67
68   if(a_remoteConnection->getClientSocket()  == NULL) {
69     string msg(asString());
70     msg += " | No se ha establecido el comm::ClientSocket";
71     throw RuntimeException(msg, ANNA_FILE_LOCATION);
72   }
73
74   comm::ClientSocket& clientSocket = *a_remoteConnection->getClientSocket();
75   comm::Server* server = a_remoteConnection->getServer();
76
77   try {
78     if(clientSocket.isConnected() == false)
79       clientSocket.connect();
80
81     server->enable();
82     a_communicator->eventCreateConnection(server);
83     // Notificacion al Receiver (EDU Febrero 2012)
84     Receiver* receiver;
85
86     if((receiver = clientSocket.getReceiver()) != NULL)
87       receiver->eventCreateConnection(server);
88
89     setfd(clientSocket.getfd());
90   } catch(RuntimeException&) {
91     a_communicator->getConnectionRecover()->annotateFault(server);
92     throw;
93   }
94 }
95
96 comm::ClientSocket* comm::handler::RemoteConnection::getClientSocket()
97 {
98   return (a_remoteConnection != NULL) ? a_remoteConnection->getClientSocket() : NULL;
99 }
100
101 /*
102  * Se invoca desde Communicator::detach.
103  *
104  * [Tx] -> Communicator
105  *
106  *
107  * Al caer en el parche 1.11.9 NO se mantenía el orden requerido de bloqueo:
108        <Method Id="comm::handler::MetaClientSocket::apply" File="handler.db/comm.handler.MetaClientSocket.cc" Line="45" LineNo="419" InitTime="03/12/2009 12:10:30">
109          <Guard Id="0x690ff0" Name="comm::ClientSocket from comm::handler::MetaClientSocket::apply" LineNo="421"/>
110          <Guard Id="0x7fbfffeb68" Name="comm::Communicator::detach" LineNo="427">
111             <Method Id="comm::handler::RemoteConnection::finalize" File="handler.db/comm.handler.RemoteConnection.cc" Line="101" LineNo="431">
112                <Guard Id="0x690f20" Name="comm::Server::reset" LineNo="433">
113                   <Guard Id="0x690ff0" Name="comm::Socket::close" LineNo="435">
114                      <Guard Id="0x685bc0" Name="PN7anna4comm16TransportFactoryE" LineNo="437"/>
115                   </Guard>
116                </Guard>
117                <Method Id="comm::Communicator::eventBreakConnection (server)" File="comm.Communicator.cc" Line="790" LineNo="447">
118                   <Method Id="comm::Delivery::fault" File="comm.Delivery.cc" Line="135" LineNo="451">
119                      <Guard Id="0x690750" Name="comm::Delivery::fault" LineNo="453">
120                         <Method Id="comm::Delivery::unsafe_fault" File="comm.Delivery.cc" Line="149" LineNo="455">
121                            <Guard Id="0x690f20" Name="Resource" LineNo="457"/>
122                         </Method>
123                      </Guard>
124                   </Method>
125                   <Guard Id="0x7fbfffeb68" Name="comm::Communicator::setStatus" LineNo="469" Mode="Reentrant"/>
126                </Method>
127             </Method>
128          </Guard>
129       </Method>
130  *
131  */
132 void comm::handler::RemoteConnection::finalize()
133 {
134   if(a_remoteConnection == NULL)
135     return;
136
137   LOGMETHOD(TraceMethod traceMethod("comm::handler::RemoteConnection", "finalize", ANNA_FILE_LOCATION));
138   comm::Server* server = a_remoteConnection->getServer();
139   Guard guard(server, "comm::Server");
140   comm::ClientSocket* clientSocket = a_remoteConnection->getClientSocket();
141
142   if(clientSocket != NULL) {
143     Receiver* receiver;
144
145     if((receiver = clientSocket->getReceiver()) != NULL)
146       receiver->eventBreakConnection(*clientSocket);
147
148     a_communicator->eventBreakConnection(*clientSocket);
149   }
150
151   // Cierra el socket y lo libera
152   server->reset();
153   // Establece la información que gestiona el reintento de uso por parte de los servicios de reparto
154   server->disable();
155   server->setTimeStamp(functions::millisecond());
156
157   if(a_communicator->hasRequestedStop() == false) {
158     a_communicator->eventBreakConnection(server);
159     a_communicator->getConnectionRecover()->annotateFault(server);
160   }
161
162   delete a_remoteConnection;
163   a_remoteConnection = NULL;
164 }
165
166 /*
167  * Se invoca en ST
168  */
169 void comm::handler::RemoteConnection::clone()
170 noexcept(false) {
171   comm::ClientSocket& clientSocket = *a_remoteConnection->getClientSocket();
172
173   try {
174     if(clientSocket.isConnected() == true)
175       clientSocket.close();
176
177     clientSocket.connect();
178     setfd(clientSocket.getfd());
179   } catch(RuntimeException&) {
180     a_communicator->getConnectionRecover()->annotateFault(a_remoteConnection->getServer());
181     throw;
182   }
183 }
184
185 string comm::handler::RemoteConnection::asString() const
186 {
187   string result("comm::handler::RemoteConnection { ");
188   result += comm::Handler::asString();
189   result += " | ";
190   result += functions::asString(a_remoteConnection);
191   return result += " }";
192 }
193
194 xml::Node* comm::handler::RemoteConnection::asXML(xml::Node* parent) const
195 {
196   xml::Node* result = parent->createChild("comm.handler.RemoteConnection");
197   comm::Handler::asAttribute(result);
198
199   if(a_remoteConnection)
200     a_remoteConnection->asXML(result);
201
202   return result;
203 }
204
205