Merge pull request #1551 from DOCGroup/plm_jira_333
[ACE_TAO.git] / TAO / orbsvcs / tests / FT_App / FT_Client.cpp
blob9572565a286483aed4c8c7ce9d95a35f539a227c
1 #include "FT_TestReplicaC.h"
2 #include <ace/Vector_T.h>
3 #include <ace/SString.h>
4 #include <ace/Get_Opt.h>
5 // FUZZ: disable check_for_streams_include
6 #include "ace/streams.h"
7 #include "ace/OS_NS_unistd.h"
8 #include "ace/OS_NS_stdio.h"
10 class FTClientMain
12 typedef ACE_Vector<ACE_CString> StringVec;
13 public:
14 ///////////////////////////
15 // construction/destruction
16 FTClientMain ();
18 ~FTClientMain ();
20 /////////////////
21 // initialization
22 int parse_args (int argc, ACE_TCHAR *argv[]);
24 ////////////
25 // execution
26 int run (void);
28 /////////////////
29 // implementation
30 private:
31 void usage (FILE* out)const;
32 void commandUsage (FILE* out);
33 int pass (
34 long & counter, // inout
35 int & more, // out
36 ACE_CString & command, // inout
37 int retry // in
41 int next_replica (void);
43 ////////////////////
44 // forbidden methods
45 private:
46 FTClientMain (const FTClientMain & rhs);
47 FTClientMain & operator = (const FTClientMain & rhs);
49 ////////////////
50 // Data members
51 private:
53 CORBA::ORB_var orb_;
55 int argc_;
56 ACE_TCHAR ** argv_;
57 const ACE_TCHAR * inFileName_;
58 FILE *inFile_;
59 FILE *commandIn_;
61 enum Verbosity{
62 SILENT,
63 QUIET,
64 NORMAL,
65 NOISY,
66 LOUD}
67 verbose_;
70 StringVec replica_iors_;
71 size_t replica_pos_;
72 const char * replica_name_;
73 FT_TEST::TestReplica_var replica_;
77 FTClientMain::FTClientMain ()
78 : inFile_(0)
79 , commandIn_(stdin)
80 , verbose_(NORMAL)
81 , replica_pos_(0)
82 , replica_name_("none")
86 FTClientMain::~FTClientMain ()
88 if (this->inFile_)
90 ACE_OS::fclose (this->inFile_);
91 this->inFile_ = 0;
95 void FTClientMain::commandUsage(FILE* out)
97 ACE_OS::fprintf (out,
98 "Each command must be at the beginning of a separate line.\n"
99 "Everything after the command (and operand if any) is ignored.\n"
100 "Valid commands are:\n"
101 " Access via method call:\n"
102 " =N set counter to N\n"
103 " cN get counter and compare to N (c stands for \"check\"\n"
104 " +N increment counter by N\n"
105 " -N decrement counter by N\n"
106 " Access as attribute:\n"
107 " >N set attribute to N\n"
108 " < get attribite\n"
109 " Try methods to be used by fault tolerant infrastructure:\n"
110 " ! is_alive\n"
111 " s get_state\n"
112 " S set_state\n"
113 " u get_update\n"
114 " U set_update\n"
115 " Simulate failure:\n"
116 " dN die on condition:\n"
117 " d%d don't die\n"
118 " d%d immediately\n"
119 " d%d while idle\n"
120 " (FT_TestReplica interface)\n"
121 " d%d before state change\n"
122 " d%d after state change, before replication\n"
123 " d%d after replication, before reply\n"
124 " (Monitorable interface)\n"
125 " d%d during is alive\n"
126 " d%d is_alive returns false\n"
127 " (Updatable interface)\n"
128 " d%d during get update\n"
129 " d%d before set update\n"
130 " d%d after set update\n"
131 " (Checkpointable interface)\n"
132 " d%d during get state\n"
133 " d%d before set state\n"
134 " d%d after set state\n"
135 " Logistics commands:\n"
136 " # ignore this line (comment).\n"
137 " v set verbosity:\n"
138 " 0 don't check counter value.\n"
139 " 1 only display counter value mismatch.\n"
140 " 2 display counter value after every command (default).\n"
141 " 3 display commands.\n"
142 " 4 display method calls.\n"
143 " zN sleep N seconds.\n"
144 " q quit (end the client, not the replica(s).)\n"
145 " q1 quit (end the client, and shutdown the currently active replica.)\n"
146 " ? help (this message)\n",
147 FT_TEST::TestReplica::NOT_YET,
148 FT_TEST::TestReplica::RIGHT_NOW,
149 FT_TEST::TestReplica::WHILE_IDLE,
150 FT_TEST::TestReplica::BEFORE_STATE_CHANGE,
151 FT_TEST::TestReplica::BEFORE_REPLICATION,
152 FT_TEST::TestReplica::BEFORE_REPLY,
153 FT_TEST::TestReplica::DURING_IS_ALIVE,
154 FT_TEST::TestReplica::DENY_IS_ALIVE,
155 FT_TEST::TestReplica::DURING_GET_UPDATE,
156 FT_TEST::TestReplica::BEFORE_SET_UPDATE,
157 FT_TEST::TestReplica::AFTER_SET_UPDATE,
158 FT_TEST::TestReplica::DURING_GET_STATE,
159 FT_TEST::TestReplica::BEFORE_SET_STATE,
160 FT_TEST::TestReplica::AFTER_SET_STATE);
164 FTClientMain::parse_args (int argc, ACE_TCHAR *argv[])
166 this->argc_ = argc;
167 this->argv_ = argv;
168 int result = 0;
170 // note: dfnkx are simple_util options
171 // include them here so we can detect bad args
172 ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("c:f:"));
173 int c;
175 while (result == 0 && (c = get_opts ()) != -1)
177 switch (c)
179 case 'c':
181 this->inFileName_ = get_opts.opt_arg ();
182 this->inFile_ = ACE_OS::fopen (this->inFileName_, "r");
183 if(this->inFile_ && !ferror (this->inFile_))
185 ACE_OS::fprintf (stdout, "FT Client: Reading commands from %s\n",
186 ACE_TEXT_ALWAYS_CHAR (this->inFileName_));
187 this->commandIn_ = this->inFile_;
189 else
191 ACE_OS::fprintf (stderr, "FT Client: Can't open input file: %s\n",
192 ACE_TEXT_ALWAYS_CHAR (this->inFileName_));
193 result = -1;
195 break;
197 case 'f':
199 replica_iors_.push_back(ACE_TEXT_ALWAYS_CHAR(get_opts.opt_arg ()));
200 break;
203 default:
204 case '?':
205 usage(stderr);
206 result = 1;
209 return result;
212 void FTClientMain::usage(FILE* out)const
214 ACE_OS::fprintf (out, "usage"
215 " -c <command file>"
216 " [-f <ior file>]...\n");
219 int FTClientMain::pass (
220 long & counter,
221 int & more,
222 ACE_CString & command,
223 int retry)
225 int result = 0;
227 ::FT::State_var state;
228 unsigned long stateValue = 0;
229 ::FT::State_var update;
230 unsigned long updateValue = 0;
232 while(more && result == 0 && !feof (this->commandIn_))
234 if (! retry || command.length () == 0 )
236 char buffer[1000];
237 char *str_ = ACE_OS::fgets (buffer, sizeof(buffer)-1, this->commandIn_);
238 if ( str_ )
240 str_ = ACE_OS::strrchr (str_, '\n');
241 if ( str_ )
242 *str_ = '\0';
244 command = buffer;
246 retry = 0;
248 if (command.length() >0)
250 char op = command[0];
251 ACE_CString cdr = command.substr(1);
252 char * junque;
253 long operand = ACE_OS::strtol(cdr.c_str(),&junque, 10);
255 if (this->verbose_ >= NOISY)
257 ACE_OS::fprintf (stdout, "FT Client: %s\n", command.c_str());
260 // turn echo on (based on verbose)
261 // individual commands can turn it off
262 int echo = this->verbose_ >= QUIET;
264 switch(op)
266 case '#':
268 echo = 0;
269 break;
271 case '=':
273 if (this->verbose_ >= LOUD)
275 ACE_OS::fprintf (stdout, "FT Client: ->set(%ld);\n", operand);
277 this->replica_->set(operand);
278 counter = operand;
279 break;
281 case 'c':
283 if (this->verbose_ >= LOUD)
285 ACE_OS::fprintf (stdout, "FT Client: ->get();\n");
287 long value = this->replica_->counter();
288 if (value == operand)
290 ACE_OS::fprintf (stdout, "FT Client: Good: Read %ld expecting %ld\n", value, operand);
291 counter = operand;
293 else
295 ACE_OS::fprintf (stdout, "FT Client: Error: Read %ld expecting %ld\n", value, operand);
297 echo = 0;
298 break;
301 case '>':
303 if (this->verbose_ >= LOUD)
305 ACE_OS::fprintf (stdout, "FT Client: ->counter(%ld);\n", operand);
307 this->replica_->counter(operand);
308 counter = operand;
309 break;
311 case '+':
313 if (this->verbose_ >= LOUD)
315 ACE_OS::fprintf (stdout, "FT Client: ->increment(%ld);\n", operand);
317 this->replica_->increment(operand);
318 counter += operand;
319 break;
321 case '-':
323 if (this->verbose_ >= LOUD)
325 ACE_OS::fprintf (stdout, "FT Client: ->increment(%ld);\n", -operand);
327 this->replica_->increment(-operand);
328 counter -= operand;
329 break;
331 case '<':
333 if (this->verbose_ >= LOUD)
335 ACE_OS::fprintf (stdout, "FT Client: ->counter();\n");
337 long attribute = this->replica_->counter();
338 ACE_OS::fprintf (stdout, "FT Client: Attribute: %ld\n", attribute);
339 echo = 0;
340 break;
342 case '!':
344 if (this->verbose_ >= LOUD)
346 ACE_OS::fprintf (stdout, "FT Client: ->is_alive();\n");
348 int alive = this->replica_->is_alive();
349 ACE_OS::fprintf (stdout, "FT Client: Is alive? %d\n", alive);
350 break;
352 case 'd':
354 if (this->verbose_ >= LOUD)
356 ACE_OS::fprintf (stdout, "FT Client: ->die(%ld);\n", operand);
358 this->replica_->die(static_cast<FT_TEST::TestReplica::Bane> (operand));
359 echo = 0;
360 break;
362 case 's':
364 if (this->verbose_ >= LOUD)
366 ACE_OS::fprintf (stdout, "FT Client: ->get_state();\n");
368 state = this->replica_->get_state();
369 stateValue = counter;
370 break;
372 case 'S':
374 if (state->length () > 0)
376 if (this->verbose_ >= LOUD)
378 ACE_OS::fprintf (stdout, "FT Client: ->set_state(saved_state);\n");
380 this->replica_->set_state (state.in ());
381 counter = stateValue;
383 else
385 ACE_OS::fprintf (stdout, "FT Client: Error: no saved state.\n");
387 break;
389 case 'u':
391 if (this->verbose_ >= LOUD)
393 ACE_OS::fprintf (stdout, "FT Client: ->get_update();\n");
395 update = this->replica_->get_update();
396 updateValue = counter;
397 break;
399 case 'U':
401 if (update->length () > 0)
403 if (this->verbose_ >= LOUD)
405 ACE_OS::fprintf (stdout, "FT Client: ->set_update(saved_update);\n");
407 this->replica_->set_update(update.in ());
408 counter = updateValue;
410 else
412 ACE_OS::fprintf (stdout, "FT Client: ERROR: No saved update information.\n");
414 break;
416 case 'v':
418 this->verbose_ = static_cast<Verbosity> (operand);
419 break;
421 case 'z':
423 if (operand == 0)
425 operand = 1;
427 ACE_Time_Value tv (operand,0);
428 ACE_OS::sleep(tv);
429 break;
431 case 'q':
433 if (operand != 0)
437 if (this->verbose_ >= LOUD)
439 ACE_OS::fprintf (stdout, "FT Client: ->shutdown();\n");
441 this->replica_->shutdown();
442 // @@ Note: this is here because the corba event loop seems to go to sleep
443 // if there's nothing for it to do.
444 // not quite sure why, yet. Dale
445 this->replica_->is_alive();
447 catch (const CORBA::Exception&)
449 ACE_OS::fprintf (stdout, "FT Client: Ignoring expected exception during shutdown.\n");
450 ; // ignore exception during shutdown
453 echo = 0;
454 more = 0;
455 break;
457 default:
459 if (op != '?')
461 ACE_OS::fprintf (stdout, "FT Client: Unknown: %s\n", command.c_str());
463 commandUsage(stderr);
464 break;
467 if (echo && this->verbose_ >= QUIET)
469 if (this->verbose_ >= LOUD)
471 ACE_OS::fprintf (stdout, "FT Client: ->get();\n");
474 long value = this->replica_->get();
475 if (value == counter)
477 if (this->verbose_ >= NORMAL)
479 ACE_OS::fprintf (stdout, "FT Client: %ld\n", counter);
482 else
484 ACE_OS::fprintf (stdout, "FT Client: Error: read %ld expecting %ld\n", value, counter);
485 result = -1;
490 return result;
493 int FTClientMain::next_replica (void)
495 int result = 0;
496 if (this->replica_pos_ < this->replica_iors_.size())
498 this->replica_name_ = this->replica_iors_[this->replica_pos_].c_str();
499 this->replica_pos_ += 1;
500 CORBA::Object_var rep_obj = this->orb_->string_to_object (this->replica_name_);
501 this->replica_ = FT_TEST::TestReplica::_narrow (rep_obj.in ());
502 if (! CORBA::is_nil (replica_.in ()))
504 result = 1;
506 else
508 ACE_OS::fprintf (stderr, "FT Client: Can't resolve IOR: %s\n", this->replica_name_);
511 else
513 ACE_OS::fprintf (stderr,
514 "***OUT_OF_REPLICAS*** "
515 ACE_SIZE_T_FORMAT_SPECIFIER_ASCII
516 "\n",
517 this->replica_pos_);
519 return result;
523 int FTClientMain::run (void)
525 int result = 0;
527 this->orb_ = CORBA::ORB_init(this->argc_, this->argv_);
529 int ok = next_replica ();
530 if (ok)
532 // retry information
533 ACE_CString command;
534 int retry = 0;
535 long counter = this->replica_->get();
537 if (this->verbose_ >= NORMAL)
539 ACE_OS::fprintf (stdout, "FT Client: Initial counter %ld\n", counter);
541 if (ACE_OS::isatty(ACE_OS::fileno(stdin)))
543 ACE_OS::fprintf (stdout, "FT Client: Commands(? for help):\n");
546 int more = 1;
547 while (more && result == 0 && !feof (this->commandIn_))
551 result = pass (counter, more, command, retry);
553 catch (const CORBA::SystemException& sysex)
555 ACE_OS::fprintf (stdout, "FT Client: Caught system exception:\n");
556 sysex._tao_print_exception ("FT Client");
558 retry = 0;
559 int handled = 0;
561 handled = next_replica();
562 if (handled)
564 ACE_OS::fprintf (stdout, "FT Client: Recovering from fault.\n");
565 ACE_OS::fprintf (stdout, "FT Client: Activate %s\n", this->replica_name_);
566 if (command.length () == 0)
568 ACE_OS::fprintf (stdout, "FT Client: No command to retry.\n");
570 else if (command[0] == 'd')
572 ACE_OS::fprintf (stdout, "FT Client: Not retrying \"die\" command.\n");
574 else if (sysex.completed () == CORBA::COMPLETED_YES)
576 ACE_OS::fprintf (stdout, "FT Client: Last command completed. No retry needed.\n");
578 else
580 if (sysex.completed () == CORBA::COMPLETED_MAYBE)
582 ACE_OS::fprintf (stdout, "FT Client: Last command may have completed. Retrying anyway.\n");
584 retry = 1;
585 ACE_OS::fprintf (stdout, "FT Client: Retrying command: %s\n", command.c_str());
588 if (! handled)
590 ACE_OS::fprintf (stdout, "FT Client: Exception not handled. Rethrow. ");
591 throw;
596 else
598 ACE_OS::fprintf (stderr, "FT Client: Can't connect to replica.\n");
600 return result;
605 ACE_TMAIN(int argc, ACE_TCHAR *argv[])
607 FTClientMain app;
608 int result = app.parse_args(argc, argv);
609 if (result == 0)
613 result = app.run ();
615 catch (const CORBA::Exception& ex)
617 ex._tao_print_exception ("FT_Client::main\t\n");
618 result = -1;
621 return result;