1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
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
17 // * Neither the name of the copyright holder 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.
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.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
38 Realiza peticiones automaticas sobre el servidor de operaciones aritmeticas.
40 Mediante un servicio de reparto por RoundRobin.
42 El servidor de este cliente: server.p rserver.p
50 #include <anna/core/core.hpp>
51 #include <anna/app/functions.hpp>
52 #include <anna/comm/comm.hpp>
54 #include <anna/timex/Engine.hpp>
55 #include <anna/timex/Clock.hpp>
57 #include <anna/test/Response.hpp>
58 #include <anna/test/Request.hpp>
60 class Sender : public timex::Clock {
62 Sender () : Clock ("Sender", (Millisecond)1000),
63 a_messageBySecond (0),
65 a_requests ("Request"),
67 a_txMessageCounter (0)
70 void setMessageBySecond (const int messageBySecond) throw () { a_messageBySecond = messageBySecond; }
72 int getTxMessageCounter () const throw () { return a_txMessageCounter; }
75 int a_messageBySecond;
78 int a_txMessageCounter;
79 ThreadData <test::Request> a_requests;
81 bool tick () throw (RuntimeException);
84 class MyCommunicator : public Communicator {
86 MyCommunicator () : Communicator (), a_avgResponseTime (0), a_rxMessageCounter (0), a_responses ("Response") {;}
89 ThreadData <test::Response> a_responses;
90 int a_avgResponseTime;
91 int a_rxMessageCounter;
93 void eventReceiveMessage (ClientSocket &, const Message&) throw (RuntimeException);
95 void eventBreakConnection (const ClientSocket&) throw ();
97 void eventBreakConnection (Server* server) throw () {
98 comm::Communicator::eventBreakConnection (server);
101 void eventBreakConnection (const Service* service) throw ();
103 static bool isOk (const test::Response& response) throw ();
106 class RRClient : public anna::comm::Application {
110 Service* getService () const throw () { return a_service; }
111 const Sender* getSender () const throw () { return &a_sender; }
114 MyCommunicator a_communicator;
115 timex::Engine a_timeController;
119 void initialize () throw (RuntimeException);
120 void run () throw (RuntimeException);
125 int main (int argc, const char** argv)
127 CommandLine& commandLine (CommandLine::instantiate ());
133 commandLine.initialize (argv, argc);
134 commandLine.verify ();
136 Logger::setLevel (Logger::Information);
137 string traceFile ("client.");
138 traceFile += anna::functions::asString ((int) getpid ());
139 traceFile += ".trace";
140 Logger::initialize ("arithmeticClient", new TraceWriter (traceFile.c_str (),4096000));
144 catch (Exception& ex) {
145 cout << ex.asString () << endl;
151 RRClient::RRClient () :
152 Application ("arithmeticClient", "Cliente de operaciones aritmeticas", "1.0"),
154 a_timeController ((Millisecond)1000, (Millisecond)250)
156 CommandLine& commandLine (CommandLine::instantiate ());
158 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puertos de los servidores (separados por comas)");
159 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP Puerto en el que el servidor atiende respuestas.");
160 commandLine.add ("n", CommandLine::Argument::Mandatory, "Numero de mensajes por segundo");
161 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
164 void RRClient::initialize ()
165 throw (RuntimeException)
167 CommandLine& cl (CommandLine::instantiate ());
169 if (cl.exists ("trace"))
170 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
172 a_sender.setMessageBySecond (cl.getIntegerValue ("n"));
174 Network& network = Network::instantiate ();
175 Tokenizer ports (cl.getValue ("p"), ",");
178 a_service = new comm::RoundRobinDelivery ("Service_Arithmetic", true);
180 for (Tokenizer::const_iterator ii = ports.begin (), maxii = ports.end (); ii != maxii; ii ++) {
181 port = atoi (Tokenizer::data (ii));
182 a_service->attach (network.createServer (cl.getValue ("a"), port, true));
185 a_communicator.attach (a_service);
188 void RRClient::run ()
189 throw (RuntimeException)
191 a_timeController.activate (a_sender);
193 a_communicator.accept ();
196 void MyCommunicator::eventReceiveMessage (ClientSocket&, const Message& message)
197 throw (RuntimeException)
199 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
201 test::Response& response = a_responses.get ();
202 response.decode (message.getBody ());
204 const anna::Millisecond now = anna::functions::millisecond ();
205 const int delay = now - (Millisecond) response.initTime;
207 if (delay > 0 && isOk (response) == true) {
208 a_rxMessageCounter ++;
209 a_avgResponseTime += delay;
212 string msg = anna::functions::asString (
213 "%d %c %d = %d", response.x, response.op, response.y, response.result
215 msg += anna::functions::asText (" | Delay: ", delay);
216 Logger::information (msg, ANNA_FILE_LOCATION);
221 string msg = anna::functions::asString (
222 "Flip: %d %c %d = %d", response.x, response.op, response.y, response.result
224 msg += anna::functions::asText (" | Message: ", message.getBody ());
225 msg += anna::functions::asText (" | Delay: ", delay);
226 Logger::warning (msg, ANNA_FILE_LOCATION);
231 void MyCommunicator::eventBreakConnection (const Service* service)
234 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventBreakConnection", ANNA_FILE_LOCATION));
236 if (a_rxMessageCounter == 0)
239 comm::Communicator::eventBreakConnection (service);
241 if (service->isAvailable () == true) {
242 LOGNOTICE (Logger::notice (service->asString (), ANNA_FILE_LOCATION));
247 RRClient& app = static_cast <RRClient&> (anna::app::functions::getApp ());
248 string msg ("Tiempo medio respuesta: ");
249 msg += anna::functions::asString (a_avgResponseTime / a_rxMessageCounter);
251 msg += anna::functions::asText (" | Rx: ", a_rxMessageCounter);
252 msg += anna::functions::asText (" | Tx: ", app.getSender ()->getTxMessageCounter ());
253 Logger::notice (msg, ANNA_FILE_LOCATION);
255 cout << msg << endl << endl;
260 bool MyCommunicator::isOk (const test::Response& response)
263 if (response.op != '+' && response.op != '-' && response.op != '*' && response.op != '/')
268 switch (response.op) {
270 result = response.x + response.y;
273 result = response.x - response.y;
276 result = response.x * response.y;
279 result = (response.y != 0) ? (response.x / response.y): 0;
283 return result == response.result;
287 throw (RuntimeException)
289 LOGMETHOD (TraceMethod tm (Logger::Local7, "Sender", "tick", ANNA_FILE_LOCATION));
291 Service* service = static_cast <RRClient&> (anna::comm::functions::getApp ()).getService ();
292 Communicator* communicator = anna::app::functions::component <Communicator> (ANNA_FILE_LOCATION);
294 if (a_messageBySecond == 0)
295 throw RuntimeException ("Hay que indicar el nÂș de mensajes por segundo", ANNA_FILE_LOCATION);
298 if (a_errorCounter > 100) {
299 communicator->requestStop ();
300 Logger::warning ("Terminado por errores continuos en la conexion", ANNA_FILE_LOCATION);
304 test::Request& request = a_requests.get ();
306 for (int n = 0; n < a_messageBySecond && communicator->hasRequestedStop () == false; n ++) {
308 request.x = rand () % 1000;
309 request.y = rand () % 1000;
310 request.initTime = anna::functions::millisecond ();
313 service->send (request);
314 a_txMessageCounter ++;
316 catch (RuntimeException& ex) {