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