diff options
author | wilson_d <wilson_d@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2003-12-22 01:44:39 +0000 |
---|---|---|
committer | wilson_d <wilson_d@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2003-12-22 01:44:39 +0000 |
commit | 33376cdf9dcd3c3e7fe0065114cbee6d79aeedc3 (patch) | |
tree | 8262d7e8599334f6f03607a19fbea89556dd952f /TAO/orbsvcs/tests/FT_App/FT_Client.cpp | |
parent | 8e0f932cdac06d7f1eadaf4f7602a317c2e49b2c (diff) | |
download | ATCD-33376cdf9dcd3c3e7fe0065114cbee6d79aeedc3.tar.gz |
ChangeLogTag: Sun Dec 21 19:35:44 2003 Dale Wilson <wilson_d@ociweb.com>
Diffstat (limited to 'TAO/orbsvcs/tests/FT_App/FT_Client.cpp')
-rw-r--r-- | TAO/orbsvcs/tests/FT_App/FT_Client.cpp | 621 |
1 files changed, 621 insertions, 0 deletions
diff --git a/TAO/orbsvcs/tests/FT_App/FT_Client.cpp b/TAO/orbsvcs/tests/FT_App/FT_Client.cpp new file mode 100644 index 00000000000..ddbe4984adf --- /dev/null +++ b/TAO/orbsvcs/tests/FT_App/FT_Client.cpp @@ -0,0 +1,621 @@ +// $Id$ + +#include "FT_TestReplicaC.h" +#include <ace/Vector_T.h> +#include <ace/SString.h> +#include <ace/Get_Opt.h> +#include <iostream> +#include <fstream> + +class FTClientMain +{ + typedef ACE_Vector<ACE_CString> StringVec; + public: + /////////////////////////// + // construction/destruction + FTClientMain (); + + ~FTClientMain (); + + ///////////////// + // initialization + int parse_args (int argc, char *argv[]); + + //////////// + // execution + int run (); + + ///////////////// + // implementation +private: + void usage (ostream & out)const; + void commandUsage (ostream & out); + int pass ( + long & counter, // inout + int & more, // out + ACE_CString & command, // inout + int retry // in + ); + + + int next_replica (ACE_ENV_SINGLE_ARG_DECL); + + //////////////////// + // forbidden methods + private: + FTClientMain (const FTClientMain & rhs); + FTClientMain & operator = (const FTClientMain & rhs); + + //////////////// + // Data members + private: + + CORBA::ORB_var orb_; + + int argc_; + char ** argv_; + const char * inFileName_; + std::ifstream inFile_; + std::istream *commandIn_; + + enum Verbosity{ + SILENT, + QUIET, + NORMAL, + NOISY, + LOUD} + verbose_; + + + StringVec replica_iors_; + size_t replica_pos_; + const char * replica_name_; + FT_TEST::TestReplica_var replica_; +}; + + +FTClientMain::FTClientMain () + : commandIn_(&std::cin) + , verbose_(NORMAL) + , replica_pos_(0) + , replica_name_("none") +{ +} + +FTClientMain::~FTClientMain () +{ + if (this->inFile_.is_open()) + { + this->inFile_.close(); + } +} + +void FTClientMain::commandUsage(ostream & out) +{ + out + << "Each command must be at the beginning of a separate line." << std::endl + << "Everything after the command (and operand if any) is ignored." << std::endl + << "Valid commands are:" << std::endl + << " Access via method call:" << std::endl + << " =N set counter to N" << std::endl + << " cN get counter and compare to N (c stands for \"check\""<< std::endl + << " +N increment counter by N" << std::endl + << " -N decrement counter by N" << std::endl + << " Access as attribute:" << std::endl + << " >N set attribute to N" << std::endl + << " < get attribite" << std::endl + << " Try methods to be used by fault tolerant infrastructure: " << std::endl + << " ! is_alive" << std::endl + << " s get_state" << std::endl + << " S set_state" << std::endl + << " u get_update" << std::endl + << " U set_update" << std::endl + << " Simulate failure:" << std::endl + << " dN die on condition:" << std::endl + << " d" << FT_TEST::TestReplica::NOT_YET << " don't die" << std::endl + << " d" << FT_TEST::TestReplica::RIGHT_NOW << " immediately" << std::endl + << " d" << FT_TEST::TestReplica::WHILE_IDLE << " while idle" << std::endl + << " (FT_TestReplica interface)" << std::endl + << " d" << FT_TEST::TestReplica::BEFORE_STATE_CHANGE << " before state change" << std::endl + << " d" << FT_TEST::TestReplica::BEFORE_REPLICATION << " after state change, before replication" << std::endl + << " d" << FT_TEST::TestReplica::BEFORE_REPLY << " after replication, before reply "<< std::endl + << " (Monitorable interface)" << std::endl + << " d" << FT_TEST::TestReplica::DURING_IS_ALIVE << " during is alive" << std::endl + << " d" << FT_TEST::TestReplica::DENY_IS_ALIVE << " is_alive returns false" << std::endl + << " (Updatable interface)" << std::endl + << " d" << FT_TEST::TestReplica::DURING_GET_UPDATE << " during get update" << std::endl + << " d" << FT_TEST::TestReplica::BEFORE_SET_UPDATE << " before set update" << std::endl + << " d" << FT_TEST::TestReplica::AFTER_SET_UPDATE << " after set update" << std::endl + << " (Checkpointable interface)" << std::endl + << " d" << FT_TEST::TestReplica::DURING_GET_STATE << " during get state" << std::endl + << " d" << FT_TEST::TestReplica::BEFORE_SET_STATE << " before set state" << std::endl + << " d" << FT_TEST::TestReplica::AFTER_SET_STATE << " after set state" << std::endl + << " Logistics commands:" << std::endl + << " # ignore this line (comment)." << std::endl + << " v set verbosity:" << std::endl + << " 0 don't check counter value." << std::endl + << " 1 only display counter value mismatch." << std::endl + << " 2 display counter value after every command (default)." << std::endl + << " 3 display commands." << std::endl + << " 4 display method calls." << std::endl + << " zN sleep N seconds." << std::endl + << " q quit (end the client, not the replica(s).)" << std::endl + << " q1 quit (end the client, and shutdown the currently active replica.)" << std::endl + << " ? help (this message)" << std::endl; +} + +int +FTClientMain::parse_args (int argc, char *argv[]) +{ + this->argc_ = argc; + this->argv_ = argv; + int result = 0; + + // note: dfnkx are simple_util options + // include them here so we can detect bad args + ACE_Get_Opt get_opts (argc, argv, "c:f:"); + int c; + + while (result == 0 && (c = get_opts ()) != -1) + { + switch (c) + { + case 'c': + { + this->inFileName_ = get_opts.opt_arg (); + this->inFile_.open(this->inFileName_); + if(this->inFile_.is_open() && this->inFile_.good()) + { + std::cout << "FT Client: Reading commands from " << this->inFileName_ << std::endl; + this->commandIn_ = & this->inFile_; + } + else + { + std::cout << "FT Client: Can't open input file: " << this->inFileName_ << std::endl; + result = -1; + } + break; + } + case 'f': + { + replica_iors_.push_back(get_opts.opt_arg ()); + break; + } + + default: + case '?': + usage(std::cerr); + result = 1; + } + } + return result; +} + +void FTClientMain::usage(ostream & out)const +{ + out << "usage" + << " -c <command file>" + << " [-f <ior file>]..." + << std::endl; +} + +int FTClientMain::pass ( + long & counter, + int & more, + ACE_CString & command, + int retry) +{ + int result = 0; + + ::FT::State_var state; + unsigned long stateValue = 0; + ::FT::State_var update; + unsigned long updateValue = 0; + + while(more && result == 0 && ! this->commandIn_->eof()) + { + if (! retry || command.length () == 0 ) + { + char buffer[1000]; + this->commandIn_->getline(buffer, sizeof(buffer)-1); + command = buffer; + } + retry = 0; + + if (command.length() >0) + { + char op = command[0]; + ACE_CString cdr = command.substr(1); + char * junque; + long operand = strtol(cdr.c_str(),&junque, 10); + + if (this->verbose_ >= NOISY) + { + std::cout << "FT Client: " << command << std::endl; + } + + // turn echo on (based on verbose) + // individual commands can turn it off + int echo = this->verbose_ >= QUIET; + + switch(op) + { + case '#': + { + echo = 0; + break; + } + case '=': + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->set(" << operand << ");" << std::endl; + } + this->replica_->set(operand ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + counter = operand; + break; + } + case 'c': + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->get();" << std::endl; + } + long value = this->replica_->counter(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + if (value == operand) + { + std::cout << "FT Client: Good: Read " << value << " expecting " << operand << std::endl; + counter = operand; + } + else + { + std::cout << "FT Client: Error: Read " << value << " expecting " << operand << std::endl; + } + echo = 0; + break; + + } + case '>': + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->counter(" << operand << ");" << std::endl; + } + this->replica_->counter(operand ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + counter = operand; + break; + } + case '+': + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->increment(" << operand << ");" << std::endl; + } + this->replica_->increment(operand ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + counter += operand; + break; + } + case '-': + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->increment(" << -operand << ");" << std::endl; + } + this->replica_->increment(-operand ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + counter -= operand; + break; + } + case '<': + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->counter();" << std::endl; + } + long attribute = this->replica_->counter(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + std::cout << "FT Client: Attribute: " << attribute << std::endl; + echo = 0; + break; + } + case '!': + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->is_alive();" << std::endl; + } + int alive = this->replica_->is_alive(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + std::cout << "FT Client: Is alive? " << alive << std::endl; + break; + } + case 'd': + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->die(" << operand << ");" << std::endl; + } + this->replica_->die(ACE_static_cast (FT_TEST::TestReplica::Bane, operand) ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + echo = 0; + break; + } + case 's': + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->get_state();" << std::endl; + } + state = this->replica_->get_state(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + stateValue = counter; + break; + } + case 'S': + { + if (state.in() != 0) + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->set_state(saved_state);" << std::endl; + } + this->replica_->set_state(state ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + counter = stateValue; + } + else + { + std::cout << "FT Client: Error: no saved state." << std::endl; + } + break; + } + case 'u': + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->get_update();" << std::endl; + } + update = this->replica_->get_update(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + updateValue = counter; + break; + } + case 'U': + { + if (update.in() != 0) + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->set_update(saved_update);" << std::endl; + } + this->replica_->set_update(update ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + counter = updateValue; + } + else + { + std::cout << "FT Client: ERROR: No saved update information." << std::endl; + } + break; + } + case 'v': + { + this->verbose_ = ACE_static_cast(Verbosity, operand); + break; + } + case 'z': + { + if (operand == 0) + { + operand = 1; + } + ACE_Time_Value tv (operand,0); + ACE_OS::sleep(tv); + break; + } + case 'q': + { + if (operand != 0) + { + ACE_TRY_NEW_ENV + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->shutdown();" << std::endl; + } + this->replica_->shutdown( ACE_ENV_SINGLE_ARG_PARAMETER); + // @@ Note: this is here because the corba event loop seems to go to sleep + // if there's nothing for it to do. + // not quite sure why, yet. Dale + this->replica_->is_alive(ACE_ENV_SINGLE_ARG_PARAMETER); + } + ACE_CATCHANY + { + std::cout << "FT Client: Ignoring expected exception during shutdown." << std::endl; + ; // ignore exception during shutdown + } + ACE_ENDTRY; + } + echo = 0; + more = 0; + break; + } + default: + { + if (op != '?') + { + std::cout << "FT Client: Unknown: " << command << std::endl; + } + commandUsage(std::cerr); + break; + } + } + if (echo && this->verbose_ >= QUIET) + { + if (this->verbose_ >= LOUD) + { + std::cout << "FT Client: ->get();" << std::endl; + } + + long value = this->replica_->get(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + if (value == counter) + { + if (this->verbose_ >= NORMAL) + { + std::cout << "FT Client: " << counter << std::endl;; + } + } + else + { + std::cout << "FT Client: Error: read " << value << " expecting " << counter << std::endl; + result = -1; + } + } + } + } + return result; +} + +int FTClientMain::next_replica (ACE_ENV_SINGLE_ARG_DECL) +{ + int result = 0; + if (this->replica_pos_ < this->replica_iors_.size()) + { + this->replica_name_ = this->replica_iors_[this->replica_pos_].c_str(); + this->replica_pos_ += 1; + CORBA::Object_var rep_obj = this->orb_->string_to_object (this->replica_name_ ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0) + replica_ = FT_TEST::TestReplica::_narrow (rep_obj.in ()); + if (! CORBA::is_nil (replica_.in ())) + { + result = 1; + } + else + { + std::cerr << "FT Client: Can't resolve IOR: " << this->replica_name_ << std::endl; + } + } + else + { + std::cerr << "***OUT_OF_REPLICAS*** " << this->replica_pos_ << std::endl; + } + return result; +} + + +int FTClientMain::run () +{ + int result = 0; + + this->orb_ = CORBA::ORB_init(this->argc_, this->argv_ ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1) + + if (next_replica ()) + { + // retry information + ACE_CString command; + int retry = 0; + long counter = this->replica_->get(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (this->verbose_ >= NORMAL) + { + std::cout << "FT Client: Initial counter " << counter << std::endl; + } + if (ACE_OS::isatty(fileno(stdin))) + { + std::cout << "FT Client: Commands(? for help):" << std::endl; + } + + int more = 1; + while (more && result == 0 && ! this->commandIn_->eof()) + { + ACE_TRY_NEW_ENV + { + result = pass (counter, more, command, retry); + ACE_TRY_CHECK; + } + ACE_CATCH (CORBA::SystemException, sysex) + { + std::cout << "FT Client: Caught system exception: " << std::endl; + ACE_PRINT_EXCEPTION (sysex, "FT Client"); + + retry = 0; + int handled = 0; + + handled = next_replica(); + if (handled) + { + std::cout << "FT Client: Recovering from fault." << std::endl; + std::cout << "FT Client: Activate " << this->replica_name_ << std::endl; + if (command.length () == 0) + { + std::cout << "FT Client: No command to retry." << std::endl; + } + else if (command[0] == 'd') + { + std::cout << "FT Client: Not retrying \"die\" command." << std::endl; + } + else if (sysex.completed () == CORBA::COMPLETED_YES) + { + std::cout << "FT Client: Last command completed. No retry needed." << std::endl; + } + else + { + if (sysex.completed () == CORBA::COMPLETED_MAYBE) + { + std::cout << "FT Client: Last command may have completed. Retrying anyway." << std::endl; + } + retry = 1; + std::cout << "FT Client: Retrying command: " << command << std::endl; + } + } + if (! handled) + { + std::cout << "FT Client: Exception not handled. Rethrow. " << std::endl; + ACE_RE_THROW; + } + } + ACE_ENDTRY; + } + } + else + { + std::cerr << "FT Client: Can't connect to replica." << std::endl; + } + return result; +} + + +int +main (int argc, char *argv[]) +{ + FTClientMain app; + int result = app.parse_args(argc, argv); + if (result == 0) + { + ACE_TRY_NEW_ENV + { + result = app.run (); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "FT_Client::main\t\n"); + result = -1; + } + ACE_ENDTRY; + } + return result; +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + template class ACE_Vector<ACE_CString>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +# pragma ACE_Vector<ACE_CString> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ |