Remove warnings
[anna.git] / example / comm / client / main.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 /**
10    Realiza peticiones automaticas sobre el servidor de operaciones aritmeticas.
11
12    La cadencia de envio de mensajes se establece mediante un temporizador.
13    Los operadores se calculan de forma aleatoria.
14
15    El servidor de este cliente: server
16 */
17
18 #include <iostream>
19
20 #include <string.h>
21 #include <unistd.h>
22
23 #include <anna/core/core.hpp>
24 #include <anna/app/functions.hpp>
25 #include <anna/comm/comm.hpp>
26
27 #include <anna/timex/Engine.hpp>
28 #include <anna/timex/Clock.hpp>
29
30 #include <anna/test/Response.hpp>
31 #include <anna/test/Request.hpp>
32
33 class Sender : public anna::timex::Clock {
34 public:
35    Sender () : Clock ("Sender", (Millisecond)1000), 
36       a_messageBySecond (0), 
37       a_nquarter (0), 
38       a_requests ("Request"), 
39       a_errorCounter (0),
40       a_txMessageCounter (0)
41    {;}
42
43    void setMessageBySecond (const int messageBySecond) throw () { a_messageBySecond = messageBySecond; }
44
45    int getTxMessageCounter () const throw () { return a_txMessageCounter; }
46
47 private:
48    int a_messageBySecond;
49    int a_nquarter;
50    int a_errorCounter;
51    int a_txMessageCounter;
52    ThreadData <test::Request> a_requests;
53
54    bool tick () throw (RuntimeException);
55 };
56
57 class MyCommunicator : public Communicator {
58 public:
59    MyCommunicator () : Communicator (), a_avgResponseTime (0), a_rxMessageCounter (0), a_responses ("Response")  {;}
60
61 private:
62    ThreadData <test::Response> a_responses;
63    int a_avgResponseTime;
64    int a_rxMessageCounter;
65
66    void eventReceiveMessage (ClientSocket &, const Message&)
67       throw (RuntimeException);
68
69 protected:
70
71    using Communicator::eventBreakConnection;
72
73    void eventBreakConnection (const ClientSocket&) throw ();
74
75    void eventBreakConnection (Server* server) throw () {
76       comm::Communicator::eventBreakConnection (server);
77    }
78    void eventBreakConnection (const Service* service) throw () { 
79       comm::Communicator::eventBreakConnection (service);
80    }
81    
82    static bool isOk (const test::Response& response) throw ();
83 };
84
85 class HeavyClient : public anna::comm::Application {
86 public:
87    HeavyClient ();
88
89    Server* getServer () const throw () { return a_server; }
90    const Sender* getSender () const throw () { return &a_sender; }
91
92 private:
93    MyCommunicator a_communicator;
94    anna::timex::Engine a_timeController;
95    Sender a_sender;
96    Server* a_server;
97
98    void initialize () throw (RuntimeException);
99    void run () throw (RuntimeException);
100 };
101
102 using namespace std;
103
104 int main (int argc, const char** argv)
105 {
106    CommandLine& commandLine (CommandLine::instantiate ());
107    HeavyClient app;
108
109    srand (time (NULL));
110
111    try {
112       commandLine.initialize (argv, argc);
113       commandLine.verify ();
114
115       Logger::setLevel (Logger::Information);
116       string traceFile ("client.");
117       traceFile += anna::functions::asString ((int) getpid ());
118       traceFile += ".trace";
119       Logger::initialize ("arithmeticClient", new TraceWriter (traceFile.c_str (),4096000));
120
121       app.start ();
122    }
123    catch (Exception& ex) {
124       cout << ex.asString () << endl;
125    }
126
127    return 0;
128 }
129
130 HeavyClient::HeavyClient () :
131    Application ("arithmeticClient", "Cliente de operaciones aritm�icas", "1.0"),
132    a_communicator (),
133    a_timeController ((Millisecond)1000, (Millisecond)250)
134 {
135    CommandLine& commandLine (CommandLine::instantiate ());
136
137    commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que el servidor atiende respuestas.");
138    commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP Puerto en el que el servidor atiende respuestas.");
139    commandLine.add ("n", CommandLine::Argument::Mandatory, "Numero de mensajes por segundo");
140    commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
141 }
142
143 void HeavyClient::initialize ()
144    throw (RuntimeException)
145 {
146    CommandLine& cl (CommandLine::instantiate ());
147
148    Network& network = Network::instantiate ();
149
150    a_server = network.createServer (cl.getValue ("a"), cl.getIntegerValue ("p"), true);
151    a_sender.setMessageBySecond (cl.getIntegerValue ("n"));
152
153    if (cl.exists ("trace"))
154       Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
155 }
156
157 void HeavyClient::run ()
158    throw (RuntimeException)
159 {
160    a_timeController.activate (a_sender);
161
162    a_communicator.accept ();
163 }
164
165 void MyCommunicator::eventReceiveMessage (ClientSocket&, const Message& message)
166    throw (RuntimeException)
167 {
168    test::Response& response = a_responses.get ();
169    response.decode (message.getBody ());
170
171    const anna::Millisecond now = anna::functions::millisecond ();
172    const int delay =  now - (Millisecond) response.initTime;
173
174    if (delay > 0 && isOk (response) == true) {
175       a_rxMessageCounter ++;
176       a_avgResponseTime += delay;
177
178       LOGINFORMATION (
179          string msg = anna::functions::asString (
180             "%d %c %d = %d", response.x, response.op, response.y, response.result
181          );
182          msg += anna::functions::asText (" | Delay: ", delay);
183          Logger::information (msg, ANNA_FILE_LOCATION);
184       );
185    }
186    else {
187       LOGWARNING (
188          string msg = anna::functions::asString (
189             "Flip: %d %c %d = %d", response.x, response.op, response.y, response.result
190          );
191          msg += anna::functions::asText (" | Message: ", message.getBody ());
192          msg += anna::functions::asText (" | Delay: ", delay);
193          Logger::warning (msg, ANNA_FILE_LOCATION);
194       );
195    }
196 }
197
198 void MyCommunicator::eventBreakConnection (const ClientSocket& clientSocket)
199    throw ()
200 {
201    if (a_rxMessageCounter == 0)
202       return;
203
204    LOGNOTICE (
205       HeavyClient& app = static_cast <HeavyClient&> (anna::app::functions::getApp ());   
206       string msg ("Tiempo medio respuesta: ");
207       msg += anna::functions::asString (a_avgResponseTime / a_rxMessageCounter);
208       msg += " ms";
209       msg += anna::functions::asText (" | Rx: ", a_rxMessageCounter);
210       msg += anna::functions::asText (" | Tx: ", app.getSender ()->getTxMessageCounter ());
211       Logger::notice (msg, ANNA_FILE_LOCATION);
212
213       cout << msg << endl << endl;
214    );
215    requestStop ();
216    comm::Communicator::eventBreakConnection (clientSocket);
217 }
218
219 bool MyCommunicator::isOk (const test::Response& response) 
220    throw ()
221 {
222    if (response.op != '+' && response.op != '-' && response.op != '*' && response.op != '/') 
223       return false;
224       
225    int result = 0;
226    
227    switch (response.op) {
228       case '+':
229          result = response.x + response.y;
230          break;
231       case '-':
232          result = response.x - response.y;
233          break;
234       case '*':
235          result = response.x * response.y;
236          break;
237       case '/':
238          result = (response.y != 0) ? (response.x / response.y): 0;
239          break;
240    }
241     
242    return result == response.result;   
243 }
244
245 bool Sender::tick ()
246    throw (RuntimeException)
247 {
248    Server* server = static_cast <HeavyClient&> (anna::app::functions::getApp ()).getServer ();
249    Communicator* communicator = anna::app::functions::component <Communicator> (ANNA_FILE_LOCATION);
250
251    if (a_errorCounter > 10) {
252       Logger::warning ("Terminado por errores continuos en la conexion", ANNA_FILE_LOCATION);
253       try {
254          communicator->requestStop ();
255       }
256       catch (RuntimeException& ex) {
257          ex.trace ();
258       }
259       return false;
260    }
261
262    test::Request& request = a_requests.get ();
263
264    for (int n = 0; n < a_messageBySecond && communicator->hasRequestedStop () == false; n ++) {
265       request.op = '+';
266       request.x = rand () % 1000;
267       request.y = rand () % 1000;
268       request.initTime = anna::functions::millisecond ();
269
270       try {
271          server->send (request);
272          a_txMessageCounter ++;
273       }
274       catch (RuntimeException& ex) {
275          string msg (ex.getText ());
276          msg += anna::functions::asText (" | ErrorCounter: ", ++ a_errorCounter);
277          Logger::warning (msg, ANNA_FILE_LOCATION);
278          break;
279       }
280    }
281
282    return true;
283 }
284