diff options
author | William R. Otte <wotte@dre.vanderbilt.edu> | 2006-07-24 15:50:21 +0000 |
---|---|---|
committer | William R. Otte <wotte@dre.vanderbilt.edu> | 2006-07-24 15:50:21 +0000 |
commit | 3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c (patch) | |
tree | 197c810e5f5bce17b1233a7cb8d7b50c0bcd25e2 /TAO/examples/Callback_Quoter | |
parent | 6b846cf03c0bcbd8c276cb0af61a181e5f98eaae (diff) | |
download | ATCD-3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c.tar.gz |
Repo restructuring
Diffstat (limited to 'TAO/examples/Callback_Quoter')
26 files changed, 3146 insertions, 0 deletions
diff --git a/TAO/examples/Callback_Quoter/Callback_Quoter.mpc b/TAO/examples/Callback_Quoter/Callback_Quoter.mpc new file mode 100644 index 00000000000..6f8864086d4 --- /dev/null +++ b/TAO/examples/Callback_Quoter/Callback_Quoter.mpc @@ -0,0 +1,55 @@ +// -*- MPC -*- +// $Id$ + +project(*IDL): taoidldefaults { + IDL_Files { + Consumer.idl + Notifier.idl + } + custom_only = 1 +} + +project(Callback_Quoter notifier): namingexe, utils { + after += *IDL + Source_Files { + Notifier_i.cpp + Notifier_Input_Handler.cpp + notifier.cpp + NotifierS.cpp + NotifierC.cpp + ConsumerC.cpp + } + IDL_Files { + } +} + +project(Callback_Quoter consumer): namingexe, portableserver { + after += *IDL + Source_Files { + Consumer_Input_Handler.cpp + Consumer_Signal_Handler.cpp + Consumer_Handler.cpp + consumer.cpp + Consumer_i.cpp + ConsumerS.cpp + ConsumerC.cpp + NotifierC.cpp + } + IDL_Files { + } +} + +project(Callback_Quoter supplier): namingexe, portableserver { + after += *IDL + Source_Files { + Supplier_i.cpp + Supplier_Timer_Handler.cpp + supplier.cpp + Consumer_i.cpp + ConsumerS.cpp + ConsumerC.cpp + NotifierC.cpp + } + IDL_Files { + } +} diff --git a/TAO/examples/Callback_Quoter/Consumer.idl b/TAO/examples/Callback_Quoter/Consumer.idl new file mode 100644 index 00000000000..4e6020992e6 --- /dev/null +++ b/TAO/examples/Callback_Quoter/Consumer.idl @@ -0,0 +1,60 @@ +/* -*- C++ -*- */ +// $Id$ + +#if !defined (_CONSUMER_IDL) +#define _CONSUMER_IDL + +module Callback_Quoter +{ + // = TITLE + // This module contains the data structure defined to store + // information and the consumer interface. + + exception Invalid_Stock + { + // = TITLE + // Requested stock does not exist. + + string reason; + // The message which declares the reason for this execption. + + }; + + exception Invalid_Handle + { + // = TITLE + // Requested object does not exist. + + string reason; + // The actual reason which caused the exception. + + }; + + struct Info + { + // = TITLE + // The information passed by the Notifier to the consumer. + + string stock_name; + // This is the name of the stock about whom the consumer + // is seeking information. + + long value; + // This is the market price of the stock. + }; + + interface Consumer + { + // = TITLE + // The Consumer interface which is utilized by the Notifier + // to pass information to the consumer. + + void push (in Callback_Quoter::Info data); + // Notifier sends data to the consumer. + + void shutdown (); + // the process shuts down. + }; +}; + +#endif /* _CONSUMER_IDL */ diff --git a/TAO/examples/Callback_Quoter/Consumer_Handler.cpp b/TAO/examples/Callback_Quoter/Consumer_Handler.cpp new file mode 100644 index 00000000000..4aeab0b4941 --- /dev/null +++ b/TAO/examples/Callback_Quoter/Consumer_Handler.cpp @@ -0,0 +1,382 @@ +// $Id$ + +// =========================================================== +// +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Consumer_Input_Handler.cpp +// +// = DESCRIPTION +// Implementation of the Consumer_Handler class. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#include "Consumer_Handler.h" + +#include "tao/ORB.h" +#include "tao/ORB_Core.h" +#include "tao/debug.h" + +#include "ace/Read_Buffer.h" +#include "ace/Get_Opt.h" +#include "ace/Read_Buffer.h" +#include "ace/OS.h" +#include "ace/Reactor.h" +#include "ace/Event_Handler.h" + +Consumer_Handler::Consumer_Handler (void) + : stock_name_ ("Unknown"), + threshold_value_ (0), + server_ (), + registered_ (0), + unregistered_ (0), + ior_ (0), + shutdown_ (0), + use_naming_service_ (1), + interactive_ (1) +{ + +} + +Consumer_Handler::~Consumer_Handler (void) +{ + // Make sure to cleanup the STDIN handler. + + if (this->interactive_ == 1) + { + if (ACE_Event_Handler::remove_stdin_handler + (this->orb_->orb_core ()->reactor (), + this->orb_->orb_core ()->thr_mgr ()) == -1) + ACE_ERROR ((LM_ERROR, + "%p\n", + "remove_stdin_handler")); + } +} + +// Reads the Server factory IOR from a file. + +int +Consumer_Handler::read_ior (char *filename) +{ + // Open the file for reading. + ACE_HANDLE f_handle = ACE_OS::open (filename, 0); + + if (f_handle == ACE_INVALID_HANDLE) + ACE_ERROR_RETURN ((LM_ERROR, + "Unable to open %s for reading: %p\n", + filename), + -1); + + ACE_Read_Buffer ior_buffer (f_handle); + char *data = ior_buffer.read (); + + if (data == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Unable to read ior: %p\n"), + -1); + + this->ior_ = ACE_OS::strdup (data); + ior_buffer.alloc ()->free (data); + + ACE_OS::close (f_handle); + + return 0; +} + +// Parses the command line arguments and returns an error status. + +int +Consumer_Handler::parse_args (void) +{ + ACE_Get_Opt get_opts (argc_, argv_, "a:t:d:f:xk:xs"); + int c; + int result; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'd': // debug flag + TAO_debug_level++; //**** + break; + + case 'k': // ior provide on command line + this->ior_ = ACE_OS::strdup (get_opts.opt_arg ()); + break; + + case 'f': // read the IOR from the file. + result = this->read_ior (get_opts.opt_arg ()); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Unable to read ior from %s : %p\n", + get_opts.opt_arg ()), + -1); + break; + + case 's': // don't use the naming service + this->use_naming_service_ = 0; + break; + + case 'a': // to be given only on using run_test.pl + this->stock_name_ = get_opts.opt_arg (); + this->interactive_ = 0; + break; + + case 't': + this->threshold_value_ = ACE_OS::atoi (get_opts.opt_arg ()); + break; + + + case 'x': + this->shutdown_ = 1; + break; + + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s" + " [-d]" + " [-f ior-file]" + " [-k ior]" + " [-x]" + " [-s]" + " [-a stock_name]" + " [-t threshold]" + "\n", + this->argv_ [0]), + -1); + } + + // Indicates successful parsing of command line. + return 0; +} + +// this method uses the naming service to obtain the server object refernce. + +int +Consumer_Handler::via_naming_service (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + // Initialization of the naming service. + if (naming_services_client_.init (orb_.in ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + CosNaming::Name notifier_ref_name (1); + notifier_ref_name.length (1); + notifier_ref_name[0].id = CORBA::string_dup ("Notifier"); + + CORBA::Object_var notifier_obj = + this->naming_services_client_->resolve (notifier_ref_name + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // The CORBA::Object_var object is downcast to Notifier_var using + // the <_narrow> method. + this->server_ = + Notifier::_narrow (notifier_obj.in () + ACE_ENV_ARG_PARAMETER); + + ACE_TRY_CHECK; + + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Consumer_Handler::via_naming_service\n"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + + return 0; +} + +// Init function. +int +Consumer_Handler::init (int argc, char **argv) +{ + + this->argc_ = argc; + this->argv_ = argv; + + // Register our <Input_Handler> to handle STDIN events, which will + // trigger the <handle_input> method to process these events. + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + // Retrieve the ORB. + this->orb_ = CORBA::ORB_init (this->argc_, + this->argv_, + 0 + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + + // Parse command line and verify parameters. + if (this->parse_args () == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "parse_args failed\n"), + -1); + + if (this->interactive_ == 1) + { + ACE_DEBUG ((LM_DEBUG, + " Services provided:\n " + " * Registration <type 'r'>\n " + " * Unregistration <type 'u'>\n " + " * Quit <type 'q'>\n ")); + + ACE_NEW_RETURN (consumer_input_handler_, + Consumer_Input_Handler (this), + -1); + + if (ACE_Event_Handler::register_stdin_handler + (consumer_input_handler_, + this->orb_->orb_core ()->reactor (), + this->orb_->orb_core ()->thr_mgr ()) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "register_stdin_handler"), + -1); + + // Register the signal event handler for ^C + ACE_NEW_RETURN (consumer_signal_handler_, + Consumer_Signal_Handler (this), + -1); + + if (this->reactor_used ()->register_handler + (SIGINT, + consumer_signal_handler_) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "register_handler for SIGINT"), + -1); + } + // use the naming service. + if (this->use_naming_service_) + { + if (via_naming_service () == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "via_naming_service failed\n"), + -1); + } + else + { + + if (this->ior_ == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "%s: no ior specified\n", + this->argv_[0]), + -1); + + CORBA::Object_var server_object = + this->orb_->string_to_object (this->ior_ + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (server_object.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + "invalid ior <%s>\n", + this->ior_), + -1); + // The downcasting from CORBA::Object_var to Notifier_var is + // done using the <_narrow> method. + this->server_ = Notifier::_narrow (server_object.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION(ACE_ANY_EXCEPTION, "Consumer_Handler::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + + return 0; +} + +int +Consumer_Handler::run (void) +{ + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + // Obtain and activate the RootPOA. + CORBA::Object_var obj = + this->orb_->resolve_initial_references ("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + PortableServer::POA_var root_poa = + PortableServer::POA::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + PortableServer::POAManager_var poa_manager= + root_poa->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_NEW_RETURN (this->consumer_servant_, + Consumer_i (), + -1); + // Set the orb in the consumer_ object. + this->consumer_servant_->orb (this->orb_.in ()); + + // Get the consumer stub (i.e consumer object) pointer. + this->consumer_var_ = + this->consumer_servant_->_this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (this->interactive_ == 0) + { + + // Register with the server. + this->server_->register_callback (this->stock_name_, + this->threshold_value_, + this->consumer_var_.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Note the registration. + this->registered_ = 1; + this->unregistered_ = 0; + + ACE_DEBUG ((LM_DEBUG, + "registeration done!\n")); + } + + // Run the ORB. + this->orb_->run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Consumer_Handler::init"); + return -1; + } + ACE_ENDTRY; + + return 0; +} + +ACE_Reactor * +Consumer_Handler::reactor_used (void) const +{ + return this->orb_->orb_core ()->reactor (); +} diff --git a/TAO/examples/Callback_Quoter/Consumer_Handler.h b/TAO/examples/Callback_Quoter/Consumer_Handler.h new file mode 100644 index 00000000000..ebd8581071e --- /dev/null +++ b/TAO/examples/Callback_Quoter/Consumer_Handler.h @@ -0,0 +1,138 @@ +/* -*- C++ -*- */ +// $Id$ + +// =========================================================== +// +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Consumer_Handler.h +// +// = DESCRIPTION +// Definition of the Callback_Qouter Consumer Client class, Consumer_Handler. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#ifndef CONSUMER_HANDLER_H +#define CONSUMER_HANDLER_H + +#include "ConsumerC.h" +#include "NotifierC.h" +#include "Consumer_i.h" +#include "ace/Read_Buffer.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "orbsvcs/Naming/Naming_Client.h" +#include "orbsvcs/CosNamingC.h" + +#include "Consumer_Input_Handler.h" +#include "Consumer_Signal_Handler.h" + +class Consumer_Input_Handler; +class Consumer_Signal_Handler; + +class Consumer_Handler +{ + // = TITLE + // Callback Quoter Consumer Client class. + // + // = DESCRIPTION + // Connects to the Callback Quoter server and + // registers the Consumer object with the it + // and receives the stock status from the Notifier. + +public: + // = Initialization and termination methods. + Consumer_Handler (void); + // Constructor. + + ~Consumer_Handler (void); + // Destructor. + + int init (int argc, char *argv[]); + // Initialize the client communication with the server. + + int run (void); + // Start the ORB object. + + const char *stock_name_; + // the name of the stock the consumer is interested in. + + int threshold_value_; + // the desired price of the stock. + + Notifier_var server_; + // Server object ptr. + + Consumer_i *consumer_servant_; + // The consumer object. + + Callback_Quoter::Consumer_var consumer_var_; + // Pointer to the consumer object registered with the ORB. + + ACE_Reactor* reactor_used (void) const; + // This method gives the reactor pointer. + + int registered_; + // Flag which notes whether the consumer has got registered with the + // Notifier-server. + + int unregistered_; + // Flag which notes whether the consumer has got unregistered from + // the Notifier-server. + +private: + + CORBA::ORB_var orb_; + // Our orb. + + int read_ior (char *filename); + // Function to read the server IOR from a file. + + int parse_args (void); + // Parse the command line arguments. Returns 0 on success, -1 on + // error. + + int via_naming_service (void); + // This method initialises the naming service and registers the + // object with the POA. + + int argc_; + // # of arguments on the command line. + + char **argv_; + // arguments from command line. + + char *ior_; + // IOR of the obj ref of the server. + + int shutdown_; + // Flag for server shutdown. + + TAO_Naming_Client naming_services_client_; + // An instance of the name client used for resolving the factory + // objects. + + int use_naming_service_; + // This variable denotes whether the naming service + // is used or not. + + Consumer_Input_Handler *consumer_input_handler_; + // Reference to the input_event_handler. + + Consumer_Signal_Handler *consumer_signal_handler_; + // Reference to the signal_event_handler. + + int interactive_; + // Is the example interactive? +}; + +#endif /* CONSUMER_HANDLER_H */ diff --git a/TAO/examples/Callback_Quoter/Consumer_Input_Handler.cpp b/TAO/examples/Callback_Quoter/Consumer_Input_Handler.cpp new file mode 100644 index 00000000000..a27c762615e --- /dev/null +++ b/TAO/examples/Callback_Quoter/Consumer_Input_Handler.cpp @@ -0,0 +1,220 @@ +// $Id$ +// =========================================================== +// +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Consumer_Input_Handler.cpp +// +// = DESCRIPTION +// Implementation of the Consumer_Input_Handler class. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#include "Consumer_Input_Handler.h" +#include "ace/Read_Buffer.h" +#include "ace/OS_NS_unistd.h" +#include "ace/os_include/os_ctype.h" + +Consumer_Input_Handler::Consumer_Input_Handler (Consumer_Handler *consumer_handler) + { + consumer_handler_ = consumer_handler; + + } + +int +Consumer_Input_Handler::handle_input (ACE_HANDLE) +{ + char buf[BUFSIZ]; + + // The string could read contains \n\0 hence using ACE_OS::read + // which returns the no of bytes read and hence i can manipulate + // and remove the devil from the picture i.e '\n' ! ;) + + ssize_t strlen = ACE_OS::read (ACE_STDIN, + buf, + sizeof buf); + if (buf[strlen -1] == '\n') + buf[strlen -1] = '\0'; + + switch (tolower (buf[0])) + { + case Consumer_Input_Handler::REGISTER: + { + this->register_consumer (); + break; + } + case Consumer_Input_Handler::UNREGISTER: + { + this->unregister_consumer (); + break; + } + case Consumer_Input_Handler::EXIT: + { + this->quit_consumer_process (); + break; + } + } + return 0; +} + + +int +Consumer_Input_Handler::register_consumer () +{ + + // Get the stockname the consumer is interested in. + static char stockname[BUFSIZ]; + + ACE_DEBUG ((LM_DEBUG, + "Stockname?")); + + ssize_t strlen = ACE_OS::read (ACE_STDIN, + stockname, + sizeof stockname - 1); + + // Taking care of platforms where an carriage return is padded with newline. + if (stockname[strlen -2] == '\n' || stockname[strlen -2] == '\r') + stockname[strlen -2] = '\0'; + else + if (stockname[strlen -1] == '\n' || stockname[strlen -1] == '\r') + stockname[strlen -1] = '\0'; + + + this->consumer_handler_->stock_name_ = stockname; + + // Get the threshold value. + char needed_stock_value[BUFSIZ]; + ACE_DEBUG ((LM_DEBUG, + "Threshold Stock value?")); + + strlen = ACE_OS::read (ACE_STDIN, + needed_stock_value, + sizeof needed_stock_value); + + if (needed_stock_value[strlen -1] == '\n') + needed_stock_value[strlen -1] = '\0'; + + this->consumer_handler_->threshold_value_ = + ACE_OS::atoi (needed_stock_value); + + ACE_DECLARE_NEW_CORBA_ENV; + + ACE_TRY + { + + // Register with the server. + this->consumer_handler_->server_->register_callback (this->consumer_handler_->stock_name_, + this->consumer_handler_->threshold_value_, + this->consumer_handler_->consumer_var_.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Note the registration. + consumer_handler_->registered_ = 1; + consumer_handler_->unregistered_ = 0; + + // @@ Up to this point.. + + ACE_DEBUG ((LM_DEBUG, + "registeration done!\n")); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Consumer_Input_Handler::register_consumer()\n"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + +return 0; +} + + + +int +Consumer_Input_Handler::unregister_consumer () +{ + // Only if the consumer is registered can the + // unregistration take place. + + if (consumer_handler_->registered_ == 1) + { + this->consumer_handler_->server_->unregister_callback (this->consumer_handler_->consumer_var_.in()); + + ACE_DEBUG ((LM_DEBUG, + " Consumer Unregistered \n ")); + consumer_handler_->unregistered_ = 1; + consumer_handler_->registered_ = 0; + } + else + ACE_DEBUG ((LM_DEBUG, + " Invalid Operation: Consumer not Registered\n")); + + + return 0; +} + +int +Consumer_Input_Handler::quit_consumer_process () +{ + // Only if the consumer is registered and wants to shut + // down, its necessary to unregister and then shutdown. + + ACE_DECLARE_NEW_CORBA_ENV; + + ACE_TRY + { + if (consumer_handler_->unregistered_ != 1 && consumer_handler_->registered_ == 1) + { + // If the notifier has exited and the consumer tries to call + // the unregister_callback method tehn an execption will be + // raised. Hence check for this case using ACE_ENV_SINGLE_ARG_PARAMETER. + this->consumer_handler_->server_->unregister_callback (this->consumer_handler_->consumer_var_.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, + " Consumer Unregistered \n ")); + consumer_handler_->unregistered_ = 0; + consumer_handler_->registered_ = 0; + } + this->consumer_handler_->consumer_servant_->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + // There would be an exception only if there is a communication + // failure between the notifier and consumer. On catching the + // exception proclaim the problem and do a graceful exit. + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Communication failed!\n"); + + ACE_TRY_EX (block1) + { + this->consumer_handler_->consumer_servant_->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK_EX (block1); + } + ACE_CATCHANY + { + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + + return 0; +} + +Consumer_Input_Handler::~Consumer_Input_Handler (void) +{ + // No-op +} diff --git a/TAO/examples/Callback_Quoter/Consumer_Input_Handler.h b/TAO/examples/Callback_Quoter/Consumer_Input_Handler.h new file mode 100644 index 00000000000..d64a6bcb66d --- /dev/null +++ b/TAO/examples/Callback_Quoter/Consumer_Input_Handler.h @@ -0,0 +1,101 @@ +/* -*- C++ -*- */ +// $Id$ + +// =========================================================== +// +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Consumer_Input_Handler.h +// +// = DESCRIPTION +// Definition of the Callback_Qouter Consumer Client class, Consumer_Input_Handler. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#ifndef CONSUMER_INPUT_HANDLER_H +#define CONSUMER_INPUT_HANDLER_H + +#include "ace/Reactor.h" +#include "ace/Event_Handler.h" +#include "Consumer_Handler.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +// Creating a class to handle input events. +// Since only inputs need to be handled, only the handle_input +// method is overlaoded. + +class Consumer_Handler; + +class Consumer_Input_Handler : public ACE_Event_Handler +{ + // = TITLE + // Callback Quoter Consumer Client class. + // + // = DESCRIPTION + // Connects to the Callback Quoter server and + // registers the Consumer object with the it + // and receives the stock status from the Notifier. + +public: + Consumer_Input_Handler (Consumer_Handler *consumer_handler); + // Constructor. + + int handle_input (ACE_HANDLE); + // Handle the user input. + + int register_consumer (void); + // Registration with the notifier. + + int unregister_consumer (void); + // Cancelling the registration with the notifier. + + int quit_consumer_process (void); + // Ends the consumer process. + + friend class ACE_Shutup_GPlusPlus; + // Turn off g++ warning + + enum + { + // = TITLE + // A set of values for the execution of the consumer. + // + // = DESCRIPTION + // Used so that the process of registering, unregistering + // and exitting neednt be dependent on 'r' 'u' and 'q'. + // Also, #define clutters up the global namespace. + + REGISTER = 'r', + // The character that the user must type to register the consumer with + // the Notifier_server. + + UNREGISTER = 'u', + // The character that the user must type to unregister the consumer with + // the Notifier_server. + + EXIT = 'q' + // The character the user must type to quit the consumer client + // application. + }; + +private: + ~Consumer_Input_Handler (void); + // the destructor. + + Consumer_Handler *consumer_handler_; + // The Consumer_Handler object. + + + +}; + +#endif /* CONSUMER_INPUT_HANDLER_H */ diff --git a/TAO/examples/Callback_Quoter/Consumer_Signal_Handler.cpp b/TAO/examples/Callback_Quoter/Consumer_Signal_Handler.cpp new file mode 100644 index 00000000000..5fe25a265f6 --- /dev/null +++ b/TAO/examples/Callback_Quoter/Consumer_Signal_Handler.cpp @@ -0,0 +1,87 @@ +/* -*- C++ -*- */ +// $Id$ + +// =========================================================== +// +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Consumer_Input_Handler.cpp +// +// = DESCRIPTION +// Implementation of the Consumer_Signal_Handler class. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#include "Consumer_Signal_Handler.h" + +Consumer_Signal_Handler::Consumer_Signal_Handler (Consumer_Handler *consumer_handler) + : consumer_handler_ (consumer_handler) +{ +} + +Consumer_Signal_Handler:: ~Consumer_Signal_Handler (void) +{ +} + +// Method to handle the ^C signal. +int +Consumer_Signal_Handler::handle_signal (int /* signum */, + siginfo_t*, + ucontext_t*) +{ + ACE_DEBUG ((LM_DEBUG, + " Exiting on receiving ^C\n")); + + quit_on_signal (); + + return 0; +} + +// Method called before the Event_Handler dies. +int +Consumer_Signal_Handler::handle_close (ACE_HANDLE, + ACE_Reactor_Mask) +{ + // End of the signal handler. + delete this; + + return 0; +} + +int +Consumer_Signal_Handler::quit_on_signal (void) +{ + // Only if the consumer is registered and wants to shut down, its + // necessary to unregister and then shutdown. + + ACE_DECLARE_NEW_CORBA_ENV; + + ACE_TRY + { + if (consumer_handler_->unregistered_ != 1 + && consumer_handler_->registered_ == 1) + { + this->consumer_handler_->server_->unregister_callback + (this->consumer_handler_->consumer_var_.in ()); + ACE_DEBUG ((LM_DEBUG, + "Consumer Unregistered\n")); + } + this->consumer_handler_->consumer_servant_->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Consumer_Input_Handler::quit_consumer_process()"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + + return 0; +} diff --git a/TAO/examples/Callback_Quoter/Consumer_Signal_Handler.h b/TAO/examples/Callback_Quoter/Consumer_Signal_Handler.h new file mode 100644 index 00000000000..04b3add1d77 --- /dev/null +++ b/TAO/examples/Callback_Quoter/Consumer_Signal_Handler.h @@ -0,0 +1,70 @@ +/* -*- C++ -*- */ +// $Id$ + +// =========================================================== +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Consumer_Input_Handler.h +// +// = DESCRIPTION +// Definition of the Consumer_Signal_Handler class. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#ifndef CONSUMER_SIGNAL_HANDLER_H +#define CONSUMER_SIGNAL_HANDLER_H + +#include "ace/Reactor.h" +#include "ace/Event_Handler.h" +#include "Consumer_Handler.h" + +class Consumer_Handler; + +class Consumer_Signal_Handler : public ACE_Event_Handler +{ + // = TITLE + // Creating a class to handle signal events. + // + // = DESCRIPTION + // Since only signals need to be handled, only the <handle_signal> method + // is overlaoded. +public: + + Consumer_Signal_Handler (Consumer_Handler *consumer_handler); + // The consumer_handler refernce will be used to access the servant + // methods. + + int handle_signal (int signum, + siginfo_t*, + ucontext_t*); + // This method takes action on an signal event. + + int handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask close_mask); + // For removal of the signal handler from the dispatch tables. When + // the handle_signal () returns < 0 this method will be executed + // automatically. + +private: + friend class ACE_Shutup_GPlusPlus; + // Turn off g++ warning + + ~Consumer_Signal_Handler (void); + // Private destructor so that the signal handler is always created + // dynamically and hence the heap doesnt get corrupted. + + int quit_on_signal (void); + // Exit gracefully on a signal. + + Consumer_Handler *consumer_handler_; + // Reference to the Consumer_Handler which is used in accessing the + // servant methods. +}; + +#endif /* CONSUMER_SIGNAL_HANDLER_H */ diff --git a/TAO/examples/Callback_Quoter/Consumer_i.cpp b/TAO/examples/Callback_Quoter/Consumer_i.cpp new file mode 100644 index 00000000000..b892a31372c --- /dev/null +++ b/TAO/examples/Callback_Quoter/Consumer_i.cpp @@ -0,0 +1,63 @@ +// $Id$ + +// =========================================================== +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Consumer_i.cpp +// +// = DESCRIPTION +// Implements the Consumer_i class, which is used by the +// callback quoter client. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#include "Consumer_i.h" + +Consumer_i::Consumer_i (void) +{ +} + +Consumer_i::~Consumer_i (void) +{ +} + +void +Consumer_i::push (const Callback_Quoter::Info &data + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + // On getting the needed information you now proceed to the next + // step, which could be obtaining the shares. + + ACE_DEBUG ((LM_DEBUG, + "Selling 10,000 %s shares at %d!!\n", + data.stock_name.in (), + data.value)); +} + +void +Consumer_i::shutdown (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + + // Instruct the ORB to shutdown. + + ACE_DEBUG ((LM_DEBUG, + " consumer shutting down \n ")); + + this->orb_->shutdown (); +} + +void +Consumer_i::orb (CORBA::ORB_ptr o) +{ + // Makes a copy of the ORB pointer. + + this->orb_ = CORBA::ORB::_duplicate (o); +} diff --git a/TAO/examples/Callback_Quoter/Consumer_i.h b/TAO/examples/Callback_Quoter/Consumer_i.h new file mode 100644 index 00000000000..839f2768c6a --- /dev/null +++ b/TAO/examples/Callback_Quoter/Consumer_i.h @@ -0,0 +1,66 @@ +/* -*- C++ -*- */ +// $Id$ + +// =========================================================== +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Consumer_i.h +// +// = DESCRIPTION +// Defines the implementation header for the Consumer interface. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#ifndef CONSUMER_I_H +#define CONSUMER_I_H +#include "ConsumerS.h" +#include "ConsumerC.h" +#include "NotifierS.h" + +class Consumer_i : public POA_Callback_Quoter::Consumer +{ + // = TITLE + // Consumer object implementation. + // + // = DESCRIPTION + // This class has methods that are called by the callback quoter + // server. +public: + // = Initialization and termination methods. + Consumer_i (void); + // Constructor. + + ~Consumer_i (void); + // Destructor. + + void push (const Callback_Quoter::Info & data + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + // Gets the stock information from the Notifier. + + virtual void shutdown (ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + // Used to get the consumer to shut down. + + void orb (CORBA::ORB_ptr o); + // Set the ORB pointer. + +private: + CORBA::ORB_var orb_; + // ORB pointer. + + int quit_; + // If 1 denotes that the consumer is dead else alive. + + // @@ Please rename to Notifier. + Notifier_var server_; + // Smart pointer to the Notifier object. +}; + +#endif /* CONSUMER_I_H */ diff --git a/TAO/examples/Callback_Quoter/Makefile.am b/TAO/examples/Callback_Quoter/Makefile.am new file mode 100644 index 00000000000..b43f75b062d --- /dev/null +++ b/TAO/examples/Callback_Quoter/Makefile.am @@ -0,0 +1,174 @@ +## Process this file with automake to create Makefile.in +## +## $Id$ +## +## This file was generated by MPC. Any changes made directly to +## this file will be lost the next time it is generated. +## +## MPC Command: +## ../bin/mwc.pl -type automake -noreldefs TAO.mwc + +ACE_BUILDDIR = $(top_builddir)/.. +ACE_ROOT = $(top_srcdir)/.. +TAO_BUILDDIR = $(top_builddir) +TAO_IDL = ACE_ROOT=$(ACE_ROOT) TAO_ROOT=$(TAO_ROOT) $(TAO_BUILDDIR)/TAO_IDL/tao_idl +TAO_IDL_DEP = $(TAO_BUILDDIR)/TAO_IDL/tao_idl +TAO_IDLFLAGS = -Ge 1 -Wb,pre_include=ace/pre.h -Wb,post_include=ace/post.h -I$(TAO_ROOT) -I$(srcdir) -g $(ACE_BUILDDIR)/apps/gperf/src/gperf +TAO_ROOT = $(top_srcdir) + +## Makefile.Callback_Quoter_IDL.am + +BUILT_SOURCES = \ + ConsumerC.cpp \ + ConsumerC.h \ + ConsumerC.inl \ + ConsumerS.cpp \ + ConsumerS.h \ + ConsumerS.inl + +CLEANFILES = \ + Consumer-stamp \ + ConsumerC.cpp \ + ConsumerC.h \ + ConsumerC.inl \ + ConsumerS.cpp \ + ConsumerS.h \ + ConsumerS.inl + +ConsumerC.cpp ConsumerC.h ConsumerC.inl ConsumerS.cpp ConsumerS.h ConsumerS.inl: Consumer-stamp + +Consumer-stamp: $(srcdir)/Consumer.idl $(TAO_IDL_DEP) + $(TAO_IDL) $(TAO_IDLFLAGS) -Sa -St $(srcdir)/Consumer.idl + @touch $@ + +BUILT_SOURCES += \ + NotifierC.cpp \ + NotifierC.h \ + NotifierC.inl \ + NotifierS.cpp \ + NotifierS.h \ + NotifierS.inl + +CLEANFILES += \ + Notifier-stamp \ + NotifierC.cpp \ + NotifierC.h \ + NotifierC.inl \ + NotifierS.cpp \ + NotifierS.h \ + NotifierS.inl + +NotifierC.cpp NotifierC.h NotifierC.inl NotifierS.cpp NotifierS.h NotifierS.inl: Notifier-stamp + +Notifier-stamp: $(srcdir)/Notifier.idl $(TAO_IDL_DEP) + $(TAO_IDL) $(TAO_IDLFLAGS) -Sa -St $(srcdir)/Notifier.idl + @touch $@ + + +noinst_HEADERS = \ + Consumer.idl \ + Notifier.idl + +## Makefile.Callback_Quoter_consumer.am + +noinst_PROGRAMS = consumer + +consumer_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -I$(TAO_ROOT) \ + -I$(TAO_BUILDDIR) \ + -I$(TAO_ROOT)/orbsvcs \ + -I$(TAO_BUILDDIR)/orbsvcs + +consumer_SOURCES = \ + ConsumerC.cpp \ + ConsumerS.cpp \ + Consumer_Handler.cpp \ + Consumer_Input_Handler.cpp \ + Consumer_Signal_Handler.cpp \ + Consumer_i.cpp \ + NotifierC.cpp \ + consumer.cpp \ + Consumer_Handler.h \ + Consumer_Input_Handler.h \ + Consumer_Signal_Handler.h \ + Consumer_i.h + +consumer_LDADD = \ + $(TAO_BUILDDIR)/tao/libTAO_PortableServer.la \ + $(TAO_BUILDDIR)/orbsvcs/orbsvcs/libTAO_CosNaming.la \ + $(TAO_BUILDDIR)/tao/libTAO_AnyTypeCode.la \ + $(TAO_BUILDDIR)/tao/libTAO.la \ + $(ACE_BUILDDIR)/ace/libACE.la + +## Makefile.Callback_Quoter_notifier.am + +noinst_PROGRAMS += notifier + +notifier_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -I$(TAO_ROOT) \ + -I$(TAO_BUILDDIR) \ + -I$(TAO_ROOT)/orbsvcs \ + -I$(TAO_BUILDDIR)/orbsvcs + +notifier_SOURCES = \ + ConsumerC.cpp \ + NotifierC.cpp \ + NotifierS.cpp \ + Notifier_Input_Handler.cpp \ + Notifier_i.cpp \ + notifier.cpp \ + Notifier_Input_Handler.h \ + Notifier_i.h + +notifier_LDADD = \ + $(TAO_BUILDDIR)/tao/libTAO_Utils.la \ + $(TAO_BUILDDIR)/tao/libTAO_PI.la \ + $(TAO_BUILDDIR)/tao/libTAO_CodecFactory.la \ + $(TAO_BUILDDIR)/tao/libTAO_PortableServer.la \ + $(TAO_BUILDDIR)/orbsvcs/orbsvcs/libTAO_CosNaming.la \ + $(TAO_BUILDDIR)/tao/libTAO_AnyTypeCode.la \ + $(TAO_BUILDDIR)/tao/libTAO.la \ + $(ACE_BUILDDIR)/ace/libACE.la + +## Makefile.Callback_Quoter_supplier.am + +noinst_PROGRAMS += supplier + +supplier_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -I$(TAO_ROOT) \ + -I$(TAO_BUILDDIR) \ + -I$(TAO_ROOT)/orbsvcs \ + -I$(TAO_BUILDDIR)/orbsvcs + +supplier_SOURCES = \ + ConsumerC.cpp \ + ConsumerS.cpp \ + Consumer_i.cpp \ + NotifierC.cpp \ + Supplier_Timer_Handler.cpp \ + Supplier_i.cpp \ + supplier.cpp \ + Consumer_i.h \ + Supplier_Timer_Handler.h \ + Supplier_i.h + +supplier_LDADD = \ + $(TAO_BUILDDIR)/tao/libTAO_PortableServer.la \ + $(TAO_BUILDDIR)/orbsvcs/orbsvcs/libTAO_CosNaming.la \ + $(TAO_BUILDDIR)/tao/libTAO_AnyTypeCode.la \ + $(TAO_BUILDDIR)/tao/libTAO.la \ + $(ACE_BUILDDIR)/ace/libACE.la + +## Clean up template repositories, etc. +clean-local: + -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.* + -rm -f gcctemp.c gcctemp so_locations *.ics + -rm -rf cxx_repository ptrepository ti_files + -rm -rf templateregistry ir.out + -rm -rf ptrepository SunWS_cache Templates.DB diff --git a/TAO/examples/Callback_Quoter/Notifier.idl b/TAO/examples/Callback_Quoter/Notifier.idl new file mode 100644 index 00000000000..1c86ed60537 --- /dev/null +++ b/TAO/examples/Callback_Quoter/Notifier.idl @@ -0,0 +1,35 @@ +/* -*- C++ -*- */ +// $Id$ + +#if !defined (_NOTIFIER_IDL) +#define _NOTTIFIER_IDL + +#include "Consumer.idl" + +interface Notifier +{ + // = TITLE + // The Notifier interface in the Callback_Quoter example which + // contains the methods by which the consumer can register, + // unregister from the Notifier. + + void register_callback (in string stock_name, + in long threshold_value, + in Callback_Quoter::Consumer consumer_handler) + raises (Callback_Quoter::Invalid_Stock); + // Register a distributed callback handler that is invoked when the + // given stock reaches the desired threshold value. + + void unregister_callback (in Callback_Quoter::Consumer consumer_handler) + raises (Callback_Quoter::Invalid_Handle); + // Remove the handler. + + void market_status (in string stock_name, + in long stock_value); + // Get market status. + + void shutdown (); + // Shuts the server down. +}; + +#endif /* _NOTIFIER_IDL */ diff --git a/TAO/examples/Callback_Quoter/Notifier_Input_Handler.cpp b/TAO/examples/Callback_Quoter/Notifier_Input_Handler.cpp new file mode 100644 index 00000000000..7874c0ef56b --- /dev/null +++ b/TAO/examples/Callback_Quoter/Notifier_Input_Handler.cpp @@ -0,0 +1,276 @@ +// $Id$ + +// =========================================================== +// +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Notifier_Input_Handler.cpp +// +// = DESCRIPTION +// Implementation of the callback quoter Notifier_Input_Handler class. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#include "Notifier_Input_Handler.h" +#include "tao/debug.h" +#include "tao/ORB_Core.h" +#include "ace/Get_Opt.h" +#include "ace/OS_NS_unistd.h" +#include "ace/os_include/os_ctype.h" + +// Constructor. + +Notifier_Input_Handler::Notifier_Input_Handler (void) + : ior_output_file_ (0), + argc_ (0), + argv_ (0), + using_naming_service_ (1) +{ + // no-op. +} + +// Destructor. + +Notifier_Input_Handler::~Notifier_Input_Handler (void) +{ + // Make sure to cleanup the STDIN handler. + + if (ACE_Event_Handler::remove_stdin_handler + (this->notifier_i_.orb_->orb_core ()->reactor (), + this->notifier_i_.orb_->orb_core ()->thr_mgr ()) == -1) + ACE_ERROR ((LM_ERROR, + "%p\n", + "remove_stdin_handler")); + +} + +// The naming service is initialized and the naming context as well as +// the object name is bound to the naming server. + +int +Notifier_Input_Handler::init_naming_service (ACE_ENV_SINGLE_ARG_DECL) +{ + + CORBA::ORB_var orb = this->orb_manager_.orb (); + + if (this->naming_server_.init (orb.in ()) == -1) + return -1; + + // create the name for the naming service + CosNaming::Name notifier_obj_name (1); + notifier_obj_name.length (1); + notifier_obj_name[0].id = CORBA::string_dup ("Notifier"); + + // (re)Bind the object. + ACE_TRY + { + Notifier_var notifier_obj = notifier_i_._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->orb_manager_.activate_poa_manager (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + naming_server_->rebind (notifier_obj_name, + notifier_obj.in() + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + } + ACE_CATCH (CosNaming::NamingContext::AlreadyBound, ex) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Unable to bind %s \n", + "Notifier"), + -1); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + + return 0; +} + +// Parse the command-line arguments and set options. +int +Notifier_Input_Handler::parse_args (void) +{ + ACE_Get_Opt get_opts (this->argc_, this->argv_, "df:s "); + int c; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'd': // debug flag. + TAO_debug_level++; ///***** + break; + + case 'f': // output the IOR toi a file. + this->ior_output_file_ = ACE_OS::fopen (get_opts.opt_arg (), "w"); + if (this->ior_output_file_ == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Unable to open %s for writing: %p\n", + get_opts.opt_arg ()), + -1); + break; + + case 's': // don't use the naming service + this->using_naming_service_ = 0; + break; + + case '?': // display help for use of the server. + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s" + " [-d]" + " [-f] <ior_output_file>" + " [-s]" + "\n", + argv_ [0]), + 1); + } + + // Indicates successful parsing of command line. + return 0; +} + +// Initialize the server. + +int +Notifier_Input_Handler::init (int argc, + char *argv[] + ACE_ENV_ARG_DECL) +{ + + // Call the init of <TAO_ORB_Manager> to initialize the ORB and + // create the child poa under the root POA. + + this->argc_ = argc; + this->argv_ = argv; + + if (this->orb_manager_.init_child_poa (this->argc_, + this->argv_, + "child_poa" + ACE_ENV_ARG_PARAMETER) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "init_child_poa"), + -1); + ACE_CHECK_RETURN (-1); + + int retval = this->parse_args (); + + if (retval != 0) + return retval; + + // Register our <Input_Handler> to handle STDIN events, which will + // trigger the <handle_input> method to process these events. + + CORBA::ORB_var orb = this->orb_manager_.orb (); + + if (ACE_Event_Handler::register_stdin_handler + (this, + orb->orb_core ()->reactor (), + orb->orb_core ()->thr_mgr ()) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "register_stdin_handler"), + -1); + + // Stash our ORB pointer for later reference. + this->notifier_i_.orb (orb.in ()); + + // Activate the servant in the POA. + CORBA::String_var str = + this->orb_manager_.activate_under_child_poa ("Notifier", + &this->notifier_i_ + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG ((LM_DEBUG, + "The IOR is: <%s>\n", + str.in ())); + + if (this->ior_output_file_) + { + ACE_OS::fprintf (this->ior_output_file_, + "%s", + str.in ()); + ACE_OS::fclose (this->ior_output_file_); + } + + if (this->using_naming_service_) + { + this->init_naming_service (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + } + return 0; +} + +int +Notifier_Input_Handler::run (ACE_ENV_SINGLE_ARG_DECL) +{ + // Run the main event loop for the ORB. + + + ACE_DEBUG ((LM_DEBUG, + " Type \"q\" to quit \n ")); + + int result = this->orb_manager_.run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (result == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Notifier_Input_Handler::run"), + -1); + } + + return 0; +} + +int +Notifier_Input_Handler::handle_input (ACE_HANDLE) +{ + char buf[BUFSIZ]; + + ACE_DECLARE_NEW_CORBA_ENV; + + ACE_TRY + { + // The string could read contains \n\0 hence using ACE_OS::read + // which returns the no of bytes read and hence i can manipulate + // and remove the devil from the picture i.e '\n' ! ;) + + ssize_t strlen = ACE_OS::read (ACE_STDIN, + buf, + sizeof buf); + if (buf[strlen -1] == '\n') + buf[strlen -1] = '\0'; + + ACE_DEBUG ((LM_DEBUG, + "%s", + buf)); + + if (tolower(buf[0]) == 'q') + { + // @@ Please remove this call if it's not used. + // (this->notifier_i_.consumer_map_).close(); + this->notifier_i_.shutdown (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Input_Handler::init"); + return -1; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + + return 0; +} diff --git a/TAO/examples/Callback_Quoter/Notifier_Input_Handler.h b/TAO/examples/Callback_Quoter/Notifier_Input_Handler.h new file mode 100644 index 00000000000..109db1f6bc0 --- /dev/null +++ b/TAO/examples/Callback_Quoter/Notifier_Input_Handler.h @@ -0,0 +1,92 @@ +/* -*- C++ -*- */ +// $Id$ +// =========================================================== +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Notifier_Input_Handler.h +// +// = DESCRIPTION +// Definition of the Callback_Quoter Notifier_Input_Handler class. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#ifndef SUPPLIER_INPUT_HANDLER_H +#define SUPPLIER_INPUT_HANDLER_H + +#include "Notifier_i.h" +#include "NotifierS.h" +#include "ace/Event_Handler.h" +#include "tao/Utils/ORB_Manager.h" +#include "orbsvcs/CosNamingS.h" +#include "orbsvcs/Naming/Naming_Client.h" + +class Notifier_Input_Handler : public ACE_Event_Handler +{ + // = TITLE + // The class defines the callback quoter Notifier initialization + // and run methods. + // + // = DESCRIPTION + // This class handles initialization tasks, as well, such as + // setting up the Orb manager and registers the Notifier servant + // object. +public: + // = Initialization and termination methods. + Notifier_Input_Handler (void); + // Constructor. + + ~Notifier_Input_Handler (void); + // Destructor. + + int init (int argc, + char *argv[] + ACE_ENV_ARG_DECL); + // Initialize the Notifier who plays the role of the server here. + + int run (ACE_ENV_SINGLE_ARG_DECL); + // Run the ORB. + + virtual int handle_input (ACE_HANDLE); + // Handle the user input. + +private: + + TAO_ORB_Manager orb_manager_; + // The tao orb manager object. + + int parse_args (void); + // Parses the command line arguments. + + int init_naming_service (ACE_ENV_SINGLE_ARG_DECL); + // Initialises the name server and registers the Notifier object + // name with the name server. + + FILE *ior_output_file_; + // File where the IOR of the Notifier object is stored. + + int argc_; + // Number of command line arguments. + + char **argv_; + // The command line arguments. + + CosNaming::NamingContext_var naming_context_; + // Naming context for the naming service. + + TAO_Naming_Client naming_server_; + // helper class for getting access to Naming Service. + + Notifier_i notifier_i_; + // The servant object registered with the orb. + + int using_naming_service_; + // This specifies whether the naming service is to be used. +}; + +#endif /* NOTIFIER_INPUT_HANDLER_H */ diff --git a/TAO/examples/Callback_Quoter/Notifier_i.cpp b/TAO/examples/Callback_Quoter/Notifier_i.cpp new file mode 100644 index 00000000000..995338205c4 --- /dev/null +++ b/TAO/examples/Callback_Quoter/Notifier_i.cpp @@ -0,0 +1,235 @@ +// $Id$ + +// =========================================================== +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Notifier_i.cpp +// +// = DESCRIPTION +// Implementation of the Notifier_i class. This class is the servant +// object for the callback quoter server. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#include "Notifier_i.h" + + +Notifier_i::Notifier_i (void) + : notifier_exited_(0) +{ + // No-op +} + +Notifier_i::~Notifier_i (void) +{ + // No-op +} + +// Register a distributed callback handler that is invoked when the +// given stock reaches the desired threshold value. + +void +Notifier_i::register_callback (const char *stock_name, + CORBA::Long threshold_value, + Callback_Quoter::Consumer_ptr consumer_handler + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + Callback_Quoter::Invalid_Stock)) +{ + // Store the client information. + Consumer_Data consumer_data; + + // Necessary to make another copy of the consumer_handler using + // <_duplicate> so that we dont lose the consumer object reference + // after the method invocation is done. + consumer_data.consumer_ = + Callback_Quoter::Consumer::_duplicate (consumer_handler); + + consumer_data.desired_value_= threshold_value; + + CONSUMERS *consumers = 0; + + // The consumer_map consists of the stockname and various consumers + // with their threshold values. To register a consumer into this + // map, first the stockname is matched with an existing one (if any) + // and the consumer and the threshold value is attached. Else, a new + // entry is created for the stockname. + + if (this->consumer_map_.find (stock_name, consumers) == 0) + { + if ( consumers->insert (consumer_data) == -1) + ACE_THROW ( Callback_Quoter::Invalid_Stock ("Insertion failed! Invalid Stock!\n")); + else + ACE_DEBUG ((LM_DEBUG, + "Inserted map entry: stockname %s threshold %d", + stock_name, + threshold_value)); + } + else + { + // the unbounded set entry is created. + ACE_NEW_THROW_EX (consumers, CONSUMERS, CORBA::NO_MEMORY ()); + ACE_CHECK; + + // When a new entry is tried to be inserted into the unbounded set and it + // fails an exception is raised. + if (consumers->insert (consumer_data) == -1) + ACE_THROW ( Callback_Quoter::Invalid_Stock ("Insertion failed! Invalid Stock!\n")); + + // The bond between the stockname <hash_key> and the consumers <hash_value> + // is fused. + if (this->consumer_map_.bind (stock_name, consumers) == -1) + ACE_ERROR ((LM_ERROR, + "register_callback: Bind failed!/n")); + else + ACE_DEBUG ((LM_DEBUG, + "new map entry: stockname %s threshold %d\n", + stock_name, + threshold_value)); + } +} + +// Obtain a pointer to the orb. + +void +Notifier_i::orb (CORBA::ORB_ptr orb) +{ + this->orb_ = orb; +} + +// Remove the client handler. + +void +Notifier_i::unregister_callback (Callback_Quoter::Consumer_ptr consumer + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + Callback_Quoter::Invalid_Handle)) +{ + // The consumer_map consists of a map of stocknames with consumers + // and their threshold values attached to it. To unregister a + // consumer it is necessary to remove that entry from the + // map. Hence, the map is iterated till the consumer entry to be + // removed is found and then removed from the map. + + // Check to see whether the hash_map still exists. Chances are there + // that the notifier has exited closing the hash map. + if (notifier_exited_ == 1) + return; + + for (CONSUMER_MAP::ITERATOR iter = this->consumer_map_.begin (); + iter != this->consumer_map_.end (); + ++iter) + { + // The *iter is nothing but the stockname + unbounded set of + // consumers+threshold values, i.e a ACE_Hash_Map_Entry. + + Consumer_Data consumer_to_remove; + + consumer_to_remove.consumer_ = + Callback_Quoter::Consumer::_duplicate (consumer); + + // int_id is a member of the ACE_Hash_Map_Entry. The remove + // method will do a find internally using operator == which + // will check only the consumer pointers. If match found it + // will be removed from the set. If the consumer cannot be + // removed an exception is raised. + + if ((*iter).int_id_->remove (consumer_to_remove) == -1) + ACE_THROW (Callback_Quoter::Invalid_Handle ( "Unregistration failed! Invalid Consumer Handle!\n")); + else + ACE_DEBUG ((LM_DEBUG, + "unregister_callback:consumer removed\n")); + } +} + +// Gets the market status and sends the information to the consumer +// who is interested in it. + +void +Notifier_i::market_status (const char *stock_name, + CORBA::Long stock_value + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_DEBUG ((LM_DEBUG, + "Notifier_i:: The stockname is %s with price %d\n", + stock_name, + stock_value)); + + CONSUMERS *consumers = 0; + + if (this->consumer_map_.find (stock_name, consumers) == 0) + { + // Go through the list of <Consumer_Data> to find which + // registered client wants to be notified. + + for (CONSUMERS::ITERATOR iter = consumers->begin (); + iter != consumers->end (); + ++iter) + { + // Check whether the stockname is equal before proceeding + // further. + if (stock_value >= (*iter).desired_value_) + { + Callback_Quoter::Info interested_consumer_data; + + interested_consumer_data.stock_name = + CORBA::string_dup (stock_name); + interested_consumer_data.value = + stock_value; + + ACE_DEBUG ((LM_DEBUG, + "pushing information to consumer\n")); + + // The status desired by the consumer is then passed to + // it. + (*iter).consumer_->push (interested_consumer_data); + } + } + } + else + ACE_DEBUG ((LM_DEBUG, + " Stock Not Present!\n")); + // Raising an exception caused problems as they were caught by the Market daemon + // who exited prematurely. + +} + +void +Notifier_i::shutdown (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + if ( this->consumer_map_.close () > 0) + ACE_ERROR ((LM_ERROR, + "Consumer_map_close error!\n")); + else + // This marks the exit of the notifier. This should be taken care of + // before the consumer tries to unregister after the notifier quits. + notifier_exited_ = 1; + + ACE_DEBUG ((LM_DEBUG, + "The Callback Quoter server is shutting down...\n")); + + + // Instruct the ORB to shutdown. + this->orb_->shutdown (); + +} + +bool +Notifier_i::Consumer_Data::operator== (const Consumer_Data &rhs) +{ + // The <_is_equivalent> function checks if the _var and _ptr objects + // are the same. NOTE: this call might not behave well on other + // ORBs since <_is_equivalent> isn't guaranteed to differentiate + // object references. + + return this->consumer_->_is_equivalent (rhs.consumer_.in ()); +} + diff --git a/TAO/examples/Callback_Quoter/Notifier_i.h b/TAO/examples/Callback_Quoter/Notifier_i.h new file mode 100644 index 00000000000..d40647a2274 --- /dev/null +++ b/TAO/examples/Callback_Quoter/Notifier_i.h @@ -0,0 +1,120 @@ +/* -*- C++ -*- */ +// $Id$ + +// =========================================================== +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Notifier.h +// +// = DESCRIPTION +// Defines the implementation header for the Supplier interface. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#ifndef NOTIFIER_I_H +#define NOTIFIER_I_H + +#include "NotifierS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ConsumerC.h" +#include "ace/Hash_Map_Manager.h" +#include "ace/Containers.h" +#include "ace/SString.h" +#include "ace/Null_Mutex.h" + +class Notifier_i : public POA_Notifier +{ + // = TITLE + // Notifier servant class. + // + // = DESCRIPTION + // The implementation of the Notifier class, which is the servant + // object for the callback quoter server. + // +public: + // = Initialization and termination methods. + Notifier_i (void); + // Constructor. + + ~Notifier_i (void); + // Destructor. + + virtual void register_callback (const char *stock_name, + CORBA::Long threshold_value, + Callback_Quoter::Consumer_ptr consumer_handler + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + Callback_Quoter::Invalid_Stock)); + // Register a distributed callback handler that is invoked when the + // given stock reaches the desired threshold value. + + virtual void unregister_callback (Callback_Quoter::Consumer_ptr consumer_handler + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + Callback_Quoter::Invalid_Handle)); + // Remove the consumer object. + + virtual void market_status (const char *stock_name, + CORBA::Long stock_value + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + // Get the market status. + + void orb (CORBA::ORB_ptr orb); + // Get the orb pointer. + + virtual void shutdown (ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + // Shutdown the Notifier. + + // CONSUMER_MAP* get_consumer_map_ptr (); + // Returns the consumer map ptr. + + //private: +public: + CORBA::ORB_ptr orb_; + // The ORB manager. + + class Consumer_Data + { + // = TITLE + // Saves the Consumer_var and the threshold stock value. + public: + bool operator== (const Consumer_Data &rhs); + // Comparison operator. + + Callback_Quoter::Consumer_var consumer_; + // Stores the consumer object reference. + + CORBA::Long desired_value_; + // Stores the stock threshold value. + }; + + typedef ACE_Unbounded_Set<Consumer_Data> + CONSUMERS; + + typedef ACE_Hash_Map_Manager<ACE_CString, CONSUMERS *, ACE_Null_Mutex> + CONSUMER_MAP; + + CONSUMER_MAP consumer_map_; + // This is the hash map with each hash_entry consisting of the stockname + // and an unbounded set of consumer object pointer and the desired stockvalue. + + int notifier_exited_; + //This marks the exit of the notifier. This should be taken care of + // before the consumer tries to unregister after the notifier quits. + + +}; + +#endif /* NOTIFIER_I_H */ diff --git a/TAO/examples/Callback_Quoter/README b/TAO/examples/Callback_Quoter/README new file mode 100644 index 00000000000..201c39fb56b --- /dev/null +++ b/TAO/examples/Callback_Quoter/README @@ -0,0 +1,121 @@ +****************************************************************************** +CALLBACK QUOTER TEST EXAMPLE -- Kirthika Parameswaran + <kirthika@cs.wustl.edu> +****************************************************************************** + +This is an distributed application which highlights the importance +of the callback feature in helping meet the demands of various clients +without them having to poll continously for input from the server. + +There are three parts to the Callback Quoter Example. + +1) Supplier +2) Notifier +3) Consumer + + +In detail: +_________ + +1) Supplier +--is the market feed daemon who keeps feeding the current stock +information to the Notifier periodically. +The timer handler has been used in the implementation of the daemon +process. It reads the current stock value from a file and sends it to +the Notifier. + +2) Notifier +-- On getting information form the supplier, it checks whether there are +any consumers ineterested in the information and accordingly sends it to +them. The consumer object is registered with the notifier and the data +is pushed to the consumer usoing this refernce. + +3) Consumer +-- He is the stock broker interested in the stock values in the market. +He will make decisions of selling only if the stock he is interested in +has a price greater than the threshold value he has set for that stock. +He just registers himself with the Notifier. This saves the time he wastes in +simply polling for information from the Notifier. +This is the callback feature in this example. + + +Running the application: +________________________ + +CASE I: USing the Naming Service +================================ + +a) Non-interactive + + SImply execute the ./run_test.pl, ofcourse after you start off the Naming Service. + +b) Interactive + +There are 3 parts to it: + +1) shell 1: type at the command prompt: + +./notifier + + + +2) shell 2: type at the command prompt: + +./consumer + +register yourself with 'r' +Enter the stockname and value. +Now wait for information to arrive. + +You can unregister by typing 'u' and quit by typing 'q'. + + + +3) shell 3: type at the command prompt: + +./supplier -ifilename + +The -i option simply tells the daemon where to pick information from. +TIP:: the contents of the input file per line should be: stockname and its price. + Sample: ./example.stocks + +The other option includes setting the period for the stock feed. + +---------------------------------------------------------------------------- + +CASE II: Without using the Naming Service. +========================================= + +There are 3 parts to it: + +1) shell 1: type at the command prompt: + +./notifier -fior_file -s + + + +2) shell 2: type at the command prompt: + +./consumer -fior_file -s + +register yourself with 'r' +Enter the stockname and value. +Now wait for information to arrive. + +You can unregister by typing 'u' and quit by typing 'q'. + + + +3) shell 3: type at the command prompt: + +./supplier -ifilename -fior_file -s + +The -i option simply tells the daemon where to pick information from. +TIP:: the contents of the input file per line should be: stockname and its price. + Sample: ./example.stocks + +The other option includes setting the period for the stock feed. + +----------------------------------------------------------------------------- + +Happy troubleshooting!!! diff --git a/TAO/examples/Callback_Quoter/Supplier_Timer_Handler.cpp b/TAO/examples/Callback_Quoter/Supplier_Timer_Handler.cpp new file mode 100644 index 00000000000..bd4df9d7029 --- /dev/null +++ b/TAO/examples/Callback_Quoter/Supplier_Timer_Handler.cpp @@ -0,0 +1,101 @@ +// $Id$ +// =========================================================== +// +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Supplier_Time _Handler.cpp +// +// = DESCRIPTION +// Implementation of the Supplier_Time_Handler class. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#include "ace/OS.h" +#include "ace/ACE.h" + +#include "Supplier_Timer_Handler.h" + + +ACE_RCSID(Callback_Quoter, Supplier, "$Id$") + +// The supplier refernce is got so that the mathods in the supplier +// can be accessed. + +Supplier_Timer_Handler:: Supplier_Timer_Handler (Supplier *supplier, + ACE_Reactor *reactor, + FILE *file_ptr) + :supplier_obj_ (supplier), + reactor_ (reactor), + file_ptr_ (file_ptr) +{ + // No-op. +} + +// Destructor. + + Supplier_Timer_Handler::~Supplier_Timer_Handler (void) +{ + // No-op. +} + +// Method which will be called by the reactor on timeout. + +int +Supplier_Timer_Handler:: handle_timeout (const ACE_Time_Value & /* tv */, + const void * /* arg */) +{ + + ACE_DEBUG ((LM_DEBUG, + "Sending Stock Market Information to Notifier... \n")); + + // The next current stock rates are obtained from a file. + if (this->get_stock_information () == -1) + return 0; + + + // Send the stock information to the notifier. Graceful exit when + // the notifier doesnt accept the information. + if (this->supplier_obj_->send_market_status (stockname_, + value_) < 0) + { + this->reactor_->end_event_loop (); + ACE_ERROR_RETURN ((LM_ERROR, + "handle_timeout: send_market_status failed! %p\n", + "send_market_status"), + -1); + } + + return 0; +} + +// Get the stock information from a file. + +int +Supplier_Timer_Handler::get_stock_information (void) +{ + // Scan the file and obtain the stock information. + if (fscanf (file_ptr_, + "%s %ld\n", + stockname_, + &value_) != EOF) + { + ACE_DEBUG ((LM_DEBUG, + "Stockname: %s, Stockvalue: %d\n", + stockname_, + value_)); + return 0; + } + else + { + // Close down the Reactor. + this->reactor_->end_event_loop (); + return -1; + } +} + diff --git a/TAO/examples/Callback_Quoter/Supplier_Timer_Handler.h b/TAO/examples/Callback_Quoter/Supplier_Timer_Handler.h new file mode 100644 index 00000000000..b359a59e40c --- /dev/null +++ b/TAO/examples/Callback_Quoter/Supplier_Timer_Handler.h @@ -0,0 +1,77 @@ +/* -*- C++ -*- */ +// $Id$ + +// =========================================================== +// +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Consumer_Input_Handler.h +// +// = DESCRIPTION +// Definition of the Supplier_Timer_Handler class. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#ifndef SUPPLIER_TIMER_HANDLER_H +#define SUPPLIER_TIMER_HANDLER_H +#include "ace/Reactor.h" +#include "ace/Timer_Queue.h" +#include "ace/Event_Handler.h" +#include "Supplier_i.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class Supplier; + +class Supplier_Timer_Handler : public ACE_Event_Handler +{ + // = TITLE + // Feeds stock information to the Callback Quoter notifier + // periodically. + // + // = Description + // Create a class to handle timer events. Since only timer events + // need to be handled, only the handle_timeout method is overlaoded. +public: + Supplier_Timer_Handler (Supplier *supplier, + ACE_Reactor *reactor, + FILE *file_ptr); + // Initilization. + + ~Supplier_Timer_Handler (void); + // Destructor. + + virtual int handle_timeout (const ACE_Time_Value &tv, + const void *arg = 0); + // Method which will be called by the Reactor when timeout occurs. + +private: + + int get_stock_information (void); + // The values of the stock and its rate are got from the file. + + Supplier *supplier_obj_; + // The supplier instance. + + ACE_Reactor *reactor_; + // Reactor used by the supplier. + + FILE* file_ptr_; + // The file handle of the file from where the stock input is obtained. + + char stockname_[BUFSIZ]; + // The name of the stock. + + long value_; + // The market value of the stock.It will be typecasted to long later. +}; + +#endif /* SUPPLIER_TIMER_HANDLER_H */ diff --git a/TAO/examples/Callback_Quoter/Supplier_i.cpp b/TAO/examples/Callback_Quoter/Supplier_i.cpp new file mode 100644 index 00000000000..35bcc26633a --- /dev/null +++ b/TAO/examples/Callback_Quoter/Supplier_i.cpp @@ -0,0 +1,350 @@ +// $Id$ +// =========================================================== +// +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// Supplier_i.cpp +// +// = DESCRIPTION +// Implementation of the Supplier class. +// +// = AUTHOR +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// =========================================================== + +#include "Supplier_i.h" +#include "tao/debug.h" +#include "ace/Get_Opt.h" +#include "ace/Read_Buffer.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_unistd.h" +#include "ace/Reactor.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_fcntl.h" + +// Constructor. + +Supplier::Supplier (void) + : ior_ (0), + use_naming_service_ (1), + notifier_ (), + f_ptr_ (0), + loop_count_ (10), + period_value_ (1) +{ + // No-op. +} + +Supplier::~Supplier (void) +{ + // Release the memory allocated for ior_. + ACE_OS::free (this->ior_); + + // Close the stream. + ACE_OS::fclose (f_ptr_); + + ACE_DEBUG ((LM_DEBUG, + "Market Status Supplier daemon exiting!\n")); +} + +// Reads the Server factory IOR from a file. + +int +Supplier::read_ior (char *filename) +{ + // Open the file for reading. + ACE_HANDLE f_handle = ACE_OS::open (filename, 0); + + if (f_handle == ACE_INVALID_HANDLE) + ACE_ERROR_RETURN ((LM_ERROR, + "Unable to open %s for reading\n", + filename), + -1); + + ACE_Read_Buffer ior_buffer (f_handle); + char *data = ior_buffer.read (); + + if (data == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Unable to read ior\n"), + -1); + + this->ior_ = ACE_OS::strdup (data); + ior_buffer.alloc ()->free (data); + + ACE_OS::close (f_handle); + + return 0; +} + +// Parses the command line arguments and returns an error status. + +int +Supplier::parse_args (void) +{ + ACE_Get_Opt get_opts (argc_, argv_, "dn:f:i:xk:xs"); + + int c; + int result; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'd': // Debug flag + TAO_debug_level++; //**** + break; + + case 'n': // Period_value: time between two successive stockfeeds. + this->period_value_ = ACE_OS::atoi (get_opts.opt_arg ()); + break; + + case 'i': // Stock market information is got from a file. + result = this->read_file (get_opts.opt_arg ()); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Unable to read stock information from %s : %p\n", + get_opts.opt_arg (), + "get_args"), + -1); + break; + + case 'k': // Ior provide on command line + this->ior_ = ACE_OS::strdup (get_opts.opt_arg ()); + break; + + case 'f': // Read the IOR from the file. + result = this->read_ior (get_opts.opt_arg ()); + if (result < 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Unable to read ior from %s : %p\n", + get_opts.opt_arg (), + "get_args"), + -1); + break; + + case 's': // Don't use the naming service + this->use_naming_service_ = 0; + break; + + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s" + " [-d]" + " [-n period]" + " [-f ior-file]" + " [-i input_filename]" + " [-k ior]" + " [-x]" + " [-s]" + "\n", + this->argv_ [0]), + -1); + } + + // Indicates successful parsing of command line. + return 0; +} + +// Give the stock status information to the Notifier. + +int +Supplier::send_market_status (const char *stock_name, + long value) +{ + ACE_DECLARE_NEW_CORBA_ENV; + + ACE_TRY + { + + // Make the RMI. + this->notifier_->market_status (stock_name, + value + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (CORBA::SystemException, sysex) + { + ACE_PRINT_EXCEPTION (sysex, "System Exception : Supplier::send_market_status"); + return -1; + } + ACE_CATCH (CORBA::UserException, userex) + { + ACE_PRINT_EXCEPTION (userex, "User Exception : Supplier::send_market_status"); + return -1; + } + ACE_ENDTRY; + return 0; +} + +// Execute client example code. + +int +Supplier::run (void) +{ + + long timer_id = 0; + + ACE_DEBUG ((LM_DEBUG, + "Market Status Supplier Daemon is running...\n ")); + + // This sets the period for the stock-feed. + ACE_Time_Value period (period_value_); + + // "Your time starts now!" ;) the timer is scheduled to begin work. + timer_id = reactor_used ()->schedule_timer (supplier_timer_handler_, + "Periodic stockfeed", + period, + period); + if (timer_id == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "schedule_timer"), + -1); + + // The reactor starts executing in a loop. + return this->reactor_used ()->run_reactor_event_loop (); +} + + +int +Supplier::via_naming_service (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + + ACE_TRY + { + // Initialization of the naming service. + if (naming_services_client_.init (orb_.in ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + CosNaming::Name notifier_ref_name (1); + notifier_ref_name.length (1); + notifier_ref_name[0].id = CORBA::string_dup ("Notifier"); + + CORBA::Object_var notifier_obj = + this->naming_services_client_->resolve (notifier_ref_name + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // The CORBA::Object_var object is downcast to Notifier_var + // using the <_narrow> method. + this->notifier_ = + Notifier::_narrow (notifier_obj.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (CORBA::SystemException, sysex) + { + ACE_PRINT_EXCEPTION (sysex, "System Exception : Supplier::via_naming_service\n"); + return -1; + } + ACE_CATCH (CORBA::UserException, userex) + { + ACE_PRINT_EXCEPTION (userex, "User Exception : Supplier::via_naming_service\n"); + return -1; + } + ACE_ENDTRY; + + return 0; +} + +// Init function. + +int +Supplier::init (int argc, char **argv) +{ + this->argc_ = argc; + this->argv_ = argv; + + ACE_DECLARE_NEW_CORBA_ENV; + + ACE_TRY + { + // Retrieve the ORB. + this->orb_ = CORBA::ORB_init (this->argc_, + this->argv_, + 0 + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Parse command line and verify parameters. + if (this->parse_args () == -1) + return -1; + + // Create the Timer_Handler. + ACE_NEW_RETURN (supplier_timer_handler_, + Supplier_Timer_Handler (this, + this->reactor_used (), + this->f_ptr_), + -1); + + if (this->use_naming_service_) + return via_naming_service (); + + if (this->ior_ == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "%s: no ior specified\n", + this->argv_[0]), + -1); + CORBA::Object_var notifier_object = + this->orb_->string_to_object (this->ior_ + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (notifier_object.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + "invalid ior <%s>\n", + this->ior_), + -1); + // The downcasting from CORBA::Object_var to Notifier_var is + // done using the <_narrow> method. + this->notifier_ = Notifier::_narrow (notifier_object.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (CORBA::SystemException, sysex) + { + ACE_PRINT_EXCEPTION (sysex, "System Exception : Supplier::init"); + return -1; + } + ACE_CATCH (CORBA::UserException, userex) + { + ACE_PRINT_EXCEPTION (userex, "User Exception : Supplier::init"); + return -1; + } + ACE_ENDTRY; + + return 0; +} + +ACE_Reactor* +Supplier::reactor_used (void) const +{ + return ACE_Reactor::instance (); +} + +// The stock market information is read from a file. + +int +Supplier::read_file (char *filename) +{ + f_ptr_ = ACE_OS::fopen (filename, "r"); + + ACE_DEBUG ((LM_DEBUG, + "filename = %s\n",filename)); + + // the stock values are to be read from a file. + if (f_ptr_ == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Unable to open %s for writing: %p\n", + filename), + -1); + return 0; +} diff --git a/TAO/examples/Callback_Quoter/Supplier_i.h b/TAO/examples/Callback_Quoter/Supplier_i.h new file mode 100644 index 00000000000..2753e58c776 --- /dev/null +++ b/TAO/examples/Callback_Quoter/Supplier_i.h @@ -0,0 +1,114 @@ +// -*- C++ -*- +// $Id$ +// ============================================================================ +// +// = LIBRARY +// TAO/examples/Callback_Quoter +// +// = FILENAME +// MarketFeed.h +// +// = DESCRIPTION +// This class implements a simple CORBA server that keeps +// on sending stock values to the Notifier. +// +// = AUTHORS +// Kirthika Parameswaran <kirthika@cs.wustl.edu> +// +// ============================================================================ +#ifndef SUPPLIER_I_H +#define SUPPLIER_I_H + +#include "orbsvcs/Naming/Naming_Client.h" +#include "orbsvcs/CosNamingC.h" +#include "ace/Reactor.h" +#include "ace/Read_Buffer.h" +#include "NotifierC.h" +#include "Supplier_Timer_Handler.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class Supplier_Timer_Handler; +class Supplier +{ + // = TITLE + // Market feed daemon implementation. + // + // = DESCRIPTION + // This class feeds stock information to the Callback Quoter + // notifier. +public: + // = Initialization and termination methods. + Supplier (void); + // Constructor. + + ~Supplier (void); + // Destructor. + + int run (void); + // Execute the daemon. + + int init (int argc, char *argv[]); + // Initialize the client communication endpoint with Notifier. + + int send_market_status (const char *stock_name, + long value); + // Sends the stock name and its value. + + Supplier_Timer_Handler *supplier_timer_handler_; + // The timer handler used to send the market status to the notifier + // periodically. + +private: + CORBA::ORB_var orb_; + // Remember our orb. + + int read_ior (char *filename); + // Function to read the Notifier IOR from a file. + + int parse_args (void); + // Parses the arguments passed on the command line. + + int via_naming_service(void); + // This method initialises the naming service and registers the + // object with the POA. + + ACE_Reactor *reactor_used (void) const; + // returns the TAO instance of the singleton Reactor. + + int read_file (char *filename); + // This method used for getting stock information from a file. + + int argc_; + // # of arguments on the command line. + + char **argv_; + // arguments from command line. + + char *ior_; + // IOR of the obj ref of the Notifier. + + TAO_Naming_Client naming_services_client_; + // An instance of the name client used for resolving the factory + // objects. + + int use_naming_service_; + // This variable denotes whether the naming service + // is used or not. + + Notifier_var notifier_; + // Notifier object reference. + + FILE *f_ptr_; + // The pointer for accessing the input stream. + + int loop_count_; + // Iteration count. + + long period_value_; + // Time period between two succesive market feeds to the Notifier. +}; + +#endif /*SUPPLIER_I_H */ diff --git a/TAO/examples/Callback_Quoter/consumer.cpp b/TAO/examples/Callback_Quoter/consumer.cpp new file mode 100644 index 00000000000..9060eb9ec1d --- /dev/null +++ b/TAO/examples/Callback_Quoter/consumer.cpp @@ -0,0 +1,19 @@ +// $Id$ + +#include "Consumer_Handler.h" + +// This function runs the Callback Quoter Consumer application. + +int +main (int argc, char **argv) +{ + Consumer_Handler consumer; + + ACE_DEBUG ((LM_DEBUG, + "\n\t***Consumer***\n\n")); + + if (consumer.init (argc, argv) == -1) + return -1; + else + return consumer.run (); +} diff --git a/TAO/examples/Callback_Quoter/example.stocks b/TAO/examples/Callback_Quoter/example.stocks new file mode 100644 index 00000000000..3c01518ff86 --- /dev/null +++ b/TAO/examples/Callback_Quoter/example.stocks @@ -0,0 +1,56 @@ +TAO 1 +ACE 1 +TAO 2 +ACE 2 +TAO 3 +ACE 3 +TAO 4 +ACE 4 +TAO 5 +ACE 5 +TAO 6 +ACE 6 +TAO 7 +ACE 7 +TAO 8 +ACE 8 +TAO 9 +ACE 9 +TAO 10 +ACE 10 +TAO 11 +ACE 11 +TAO 12 +ACE 12 +TAO 13 +ACE 13 +TAO 14 +ACE 14 +TAO 1 +ACE 1 +TAO 2 +ACE 2 +TAO 3 +ACE 3 +TAO 4 +ACE 4 +TAO 5 +ACE 5 +TAO 6 +ACE 6 +TAO 7 +ACE 7 +TAO 8 +ACE 8 +TAO 9 +ACE 9 +TAO 10 +ACE 10 +TAO 11 +ACE 11 +TAO 12 +ACE 12 +TAO 13 +ACE 13 +TAO 14 +ACE 14 diff --git a/TAO/examples/Callback_Quoter/notifier.cpp b/TAO/examples/Callback_Quoter/notifier.cpp new file mode 100644 index 00000000000..44f07d70cd1 --- /dev/null +++ b/TAO/examples/Callback_Quoter/notifier.cpp @@ -0,0 +1,44 @@ +// $Id$ + +#include "Notifier_Input_Handler.h" + +ACE_RCSID(notifier, Callback_Quoter, "$Id$") + +// This is the main driver program for the Callback Quoter Notifier. + +int +main (int argc, char *argv[]) +{ + Notifier_Input_Handler notifier; + + ACE_DEBUG ((LM_DEBUG, + "\n\tNotifier\n\n")); + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + int rc = notifier.init (argc, argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (rc == -1) + return 1; + else + { + notifier.run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + } + ACE_CATCH (CORBA::SystemException, sysex) + { + ACE_PRINT_EXCEPTION (sysex, "System Exception"); + return -1; + } + ACE_CATCH (CORBA::UserException, userex) + { + ACE_PRINT_EXCEPTION (userex, "User Exception"); + return -1; + } + ACE_ENDTRY; + + return 0; +} diff --git a/TAO/examples/Callback_Quoter/run_test.pl b/TAO/examples/Callback_Quoter/run_test.pl new file mode 100755 index 00000000000..78aeb41bd07 --- /dev/null +++ b/TAO/examples/Callback_Quoter/run_test.pl @@ -0,0 +1,71 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# $Id$ +# -*- perl -*- + +use lib '../../../bin'; +use PerlACE::Run_Test; + +$status = 0; +$ns_ior = PerlACE::LocalFile ("NameService.ior"); +$sleeptime = 5; + +unlink $ns_ior; + +$NS = new PerlACE::Process ("../../orbsvcs/Naming_Service/Naming_Service", "-o $ns_ior"); +$N = new PerlACE::Process ("notifier", "-ORBInitRef NameService=file://$ns_ior"); +$C = new PerlACE::Process ("consumer", "-ORBInitRef NameService=file://$ns_ior -t 12 -a TAO"); +$S = new PerlACE::Process ("supplier", "-ORBInitRef NameService=file://$ns_ior -iexample.stocks"); + +print STDERR "================ Remote test\n"; + +$NS->Spawn (); + +if (PerlACE::waitforfile_timed ($ns_ior, 5) == -1) { + print STDERR "ERROR: cannot find file <$ns_ior>\n"; + $NS->Kill (); + exit 1; +} + + +$N->Spawn (); + +sleep $sleeptime; + +$C->Spawn (); + +sleep $sleeptime; + +$supplier = $S->SpawnWaitKill (60); + +if ($supplier != 0) { + print STDERR "ERROR: supplier returned $supplier\n"; + $status = 1; +} + +$server = $C->TerminateWaitKill (5); + +if ($server != 0) { + print STDERR "ERROR: consumer returned $server\n"; + $status = 1; +} + +$server = $N->TerminateWaitKill (5); + +if ($server != 0) { + print STDERR "ERROR: notifier returned $server\n"; + $status = 1; +} + +$server = $NS->TerminateWaitKill (5); + +if ($server != 0) { + print STDERR "ERROR: naming service returned $server\n"; + $status = 1; +} + +unlink $ns_ior; + +exit $status; diff --git a/TAO/examples/Callback_Quoter/supplier.cpp b/TAO/examples/Callback_Quoter/supplier.cpp new file mode 100644 index 00000000000..5d746eb0bc9 --- /dev/null +++ b/TAO/examples/Callback_Quoter/supplier.cpp @@ -0,0 +1,19 @@ +// $Id$ + +#include "Supplier_i.h" + +// This function runs the Callback Quoter Supplier daemon. + +int +main (int argc, char **argv) +{ + Supplier supplier; + + ACE_DEBUG ((LM_DEBUG, + "\n\tMarket Status Supplier Daemon\n\n")); + + if (supplier.init (argc, argv) == -1) + return -1; + else + return supplier.run (); +} |