Solve legacy problem with clear operation (coredump with running threads)
[anna.git] / source / comm / internal / ConnectionRecover.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 <algorithm>
10
11 #include <anna/core/tracing/TraceMethod.hpp>
12 #include <anna/core/tracing/Logger.hpp>
13 #include <anna/core/functions.hpp>
14
15 #include <anna/xml/Node.hpp>
16
17 #include <anna/comm/Communicator.hpp>
18 #include <anna/comm/Server.hpp>
19 #include <anna/comm/ClientSocket.hpp>
20
21 using namespace std;
22 using namespace anna;
23
24 /*
25  * Se invoca desde el handler::RemoteConnection::finalize y debe estar protegido por la SSCC del Communicator
26  */
27 void comm::ConnectionRecover::annotateFault(comm::Server* server)
28 throw() {
29   if(server->autoRecovery() == false)
30     return;
31
32   if(find(a_breaks.begin(), a_breaks.end(), server) != a_breaks.end())
33     return;
34
35   if(a_isRunning == false) {
36     a_nextTime = functions::millisecond() + a_communicator.getRecoveryTime();
37     a_isRunning = true;
38   }
39
40   a_breaks.push_back(server);
41   a_recovering = a_breaks.begin();
42   string msg("comm::ConnectionRecover::fault | ");
43   msg += server->asString();
44   msg += anna::functions::asText(" | NextTime: ", a_nextTime);
45   Logger::error(msg, ANNA_FILE_LOCATION);
46 }
47
48 /*
49  * Se invoca desde el Communicator y en MT debe estar protegido por la SSCC del Communicator
50  */
51 void comm::ConnectionRecover::tryRecover()
52 throw() {
53   LOGMETHOD(TraceMethod traceMethod(Logger::Local7, "comm::ConnectionRecover", "tryRecover", ANNA_FILE_LOCATION));
54   Millisecond now(functions::millisecond());
55
56   if(now < a_nextTime)
57     return;
58
59   if(a_recovering == a_breaks.end())
60     return;
61
62   Millisecond maxTime = now + a_communicator.getTryingConnectionTime();
63   break_iterator beginning = a_recovering;
64   Server* server;
65
66   while(now < maxTime && a_breaks.size() > 0) {
67     server = *a_recovering;
68
69     try {
70       server->connect();
71       LOGNOTICE(
72         Logger::write(Logger::Notice, "Recover", server->asString(), ANNA_FILE_LOCATION)
73       );
74       a_recovering = a_breaks.erase(a_recovering);
75     } catch(Exception& ex) {
76       a_recovering ++;
77     }
78
79     if(a_recovering == a_breaks.end())
80       a_recovering = a_breaks.begin();
81
82     if(a_recovering == beginning)
83       break;
84
85     now = functions::millisecond();
86   }
87
88   a_isRunning = (a_breaks.size() > 0);
89   a_nextTime = now + a_communicator.getRecoveryTime();
90   LOGDEBUG(
91     string msg("comm::ConnectionRecover::recover | Running: ");
92     msg += anna::functions::asString(a_isRunning);
93     msg += anna::functions::asText(" | N: ", (int) a_breaks.size());
94     msg += anna::functions::asText(" | NextTime: ", a_nextTime);
95     Logger::debug(msg, ANNA_FILE_LOCATION);
96   );
97 }
98
99 /*
100 bool comm::ConnectionRecover::contains (comm::Server* server) const
101    throw ()
102 {
103    Guard guard (a_mutex, "comm::ConnectionRecover::contains");
104    return std::find (a_breaks.begin (), a_breaks.end (), server) != a_breaks.end ();
105 }
106
107 void comm::ConnectionRecover::erase (comm::Server* server)
108    throw ()
109 {
110    Guard guard (a_mutex, "comm::ConnectionRecover::erase");
111
112    vector <Server*>::iterator ii = find (a_breaks.begin (), a_breaks.end (), server);
113
114    if (ii == a_breaks.end ())
115       return;
116
117    if (ii == a_recovering)
118       if ((a_recovering = a_breaks.erase (ii)) == a_breaks.end ())
119          a_recovering = a_breaks.begin ();
120
121    a_isRunning = (a_breaks.size () > 0);
122 }
123 */
124
125 xml::Node* comm::ConnectionRecover::asXML(xml::Node* parent) const
126 throw(RuntimeException) {
127   xml::Node* connectionRecover = parent->createChild("comm.ConnectionRecover");
128   connectionRecover->createAttribute("Active", functions::asString(a_isRunning));
129
130   for(std::vector <Server*>::const_iterator ii = a_breaks.begin(), maxii = a_breaks.end(); ii != maxii; ii ++)
131     (*ii)->asXML(connectionRecover);
132
133   return connectionRecover;
134 }
135
136
137