// client.cpp,v 1.5 2000/01/19 02:40:01 irfan Exp // ================================================================ // // = FILENAME // client.cpp // // = DESCRIPTION // This is a client that uses ACS callbacks. // Has been written taking the AMI example and changing // as little as possible to use ACS callbacks instead of AMI // callbacks // // = AUTHOR // G.Chiozzi, R.Lemke (Irfan Pyarali for the AMI example) // // ================================================================ #include "ace/Get_Opt.h" #include "ace/Read_Buffer.h" #include "testS.h" ACE_RCSID(AMI, client, "client.cpp,v 1.5 2000/01/19 02:40:01 irfan Exp"); /* GCH/RLE * * baci include defines callback objects * */ #include // Name of file contains ior. static const char *IOR = "file://ior"; // Default iterations. static CORBA::ULong iterations = 20; // Time interval between invocation (in milli seconds). static long interval = 1000; // Flag indicates whether to shutdown remote server or not upon client // shutdown. static int shutdown_server = 0; // AMI call or regular call. static int invoke_ami_style = 1; // Flag indicates that all replies have been received static int received_all_replies = 0; /* GCH/RLE * * This callback class is used to handle the * callbacks from asynchronous calls * We are actually using only the done() method, * but we have to provide an implementation also for * the abstract working() and negotiate(). * This callback class is anyway rather generic and can * be used for all remote calls. * On the contrary, the Reply_Handler of the AMI example * is specific for the test class and has to implement * xxx and xxx_excep methods for each single * method in the test interface. */ class MyCBlong: public virtual POA_ESO::CBlong { private: public: void done (CORBA::Long value, const ESO::Completion & c, const ESO::CBDescOut & desc, CORBA::Environment &ACE_TRY_ENV = TAO_default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)) { static CORBA::ULong replyCounter = 0; ACE_DEBUG ((LM_DEBUG, "client: ACS Reply %d @ %T\n", value)); // Last reply flips the flag. replyCounter++; if (replyCounter == iterations) received_all_replies = 1; } void working (CORBA::Long value, const ESO::Completion & c, const ESO::CBDescOut & desc, CORBA::Environment &ACE_TRY_ENV = TAO_default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)) { ACE_DEBUG ((LM_DEBUG, "client: ACS Working\n")); } CORBA::Boolean negotiate (ESO::TimeInterval time_to_transmit, const ESO::CBDescOut & desc, CORBA::Environment &ACE_TRY_ENV = TAO_default_environment ()) ACE_THROW_SPEC ((CORBA::SystemException)) {return 1;} }; static int parse_args (int argc, char **argv) { ACE_Get_Opt get_opts (argc, argv, "a:b:k:m:i:t:x"); int c; while ((c = get_opts ()) != -1) switch (c) { case 'k': IOR = get_opts.optarg; break; case 'a': invoke_ami_style = ::atoi (get_opts.optarg); break; case 'i': iterations = ::atoi (get_opts.optarg); break; case 't': interval = ::atoi (get_opts.optarg); break; case 'x': shutdown_server = 1; break; case '?': default: ACE_ERROR_RETURN ((LM_ERROR, "usage: %s " "-k IOR " "-a invoke AMI style [0/1] " "-i iterations " "-t interval between calls " "-x shutdown server " "\n", argv [0]), -1); } if (IOR == 0) ACE_ERROR_RETURN ((LM_ERROR, "Please specify the IOR for the servant\n"), -1); // Without AMI, replies are immediate. if (!invoke_ami_style) received_all_replies = 1; // Indicates successful parsing of command line. return 0; } int main (int argc, char **argv) { ACE_DECLARE_NEW_CORBA_ENV; ACE_TRY { // Initialize the ORB. CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, 0, ACE_TRY_ENV); ACE_TRY_CHECK; // Initialize options based on command-line arguments. int parse_args_result = parse_args (argc, argv); if (parse_args_result != 0) return parse_args_result; CORBA::Object_var base = orb->resolve_initial_references ("RootPOA", ACE_TRY_ENV); ACE_TRY_CHECK; PortableServer::POA_var root_poa = PortableServer::POA::_narrow (base.in (), ACE_TRY_ENV); ACE_TRY_CHECK; // Get an object reference from the argument string. base = orb->string_to_object (IOR, ACE_TRY_ENV); ACE_TRY_CHECK; PortableServer::POAManager_var poa_manager = root_poa->the_POAManager (ACE_TRY_ENV); ACE_TRY_CHECK; poa_manager->activate (ACE_TRY_ENV); ACE_TRY_CHECK; // Try to narrow the object reference to a reference. test_var test_object = test::_narrow (base.in (), ACE_TRY_ENV); ACE_TRY_CHECK; /* GCH/RLE * * Instead of a Reply_Handler, here we just have to instantiate a * MyCBlong object, used by the servant to send back the reply. */ MyCBlong* mcb = new MyCBlong; ESO::CBlong_var cb = mcb->_this(); ACE_TRY_CHECK; ACE_TRY_CHECK; for (CORBA::ULong i = 1; i <= iterations; ++i) { ACE_DEBUG ((LM_DEBUG, "client: Iteration %d @ %T\n", i)); if (invoke_ami_style) { /* GCH/RLE * * The call to the remote method looks essentially the same * as for AMI */ ESO::CBDescIn desc; test_object->method_async(i, cb.in(), desc, ACE_TRY_ENV); ACE_TRY_CHECK; } else { CORBA::ULong reply_number = 0; // Invoke the regular method. test_object->method (i, reply_number, ACE_TRY_ENV); ACE_TRY_CHECK; ACE_DEBUG ((LM_DEBUG, "client: Regular Reply %d @ %T\n", reply_number)); } // Interval between successive calls. ACE_Time_Value sleep_interval (0, interval * 1000); orb->run (sleep_interval); } // Loop until all replies have been received. while (!received_all_replies) { orb->perform_work (); } // Shutdown server. if (shutdown_server) { test_object->shutdown (ACE_TRY_ENV); ACE_TRY_CHECK; } root_poa->destroy (1, 1, ACE_TRY_ENV); ACE_TRY_CHECK; // Destroy the ORB. On some platforms, e.g., Win32, the socket // library is closed at the end of main(). This means that any // socket calls made after main() fail. Hence if we wait for // static destructors to flush the queues, it will be too late. // Therefore, we use explicit destruction here and flush the // queues before main() ends. orb->destroy (ACE_TRY_ENV); ACE_TRY_CHECK; } ACE_CATCHANY { ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Exception caught:"); return -1; } ACE_ENDTRY; ACE_CHECK_RETURN (-1); return 0; }