summaryrefslogtreecommitdiff
path: root/TAO/examples/Callback_Quoter
diff options
context:
space:
mode:
authorWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:21 +0000
committerWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:21 +0000
commit3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c (patch)
tree197c810e5f5bce17b1233a7cb8d7b50c0bcd25e2 /TAO/examples/Callback_Quoter
parent6b846cf03c0bcbd8c276cb0af61a181e5f98eaae (diff)
downloadATCD-3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c.tar.gz
Repo restructuring
Diffstat (limited to 'TAO/examples/Callback_Quoter')
-rw-r--r--TAO/examples/Callback_Quoter/Callback_Quoter.mpc55
-rw-r--r--TAO/examples/Callback_Quoter/Consumer.idl60
-rw-r--r--TAO/examples/Callback_Quoter/Consumer_Handler.cpp382
-rw-r--r--TAO/examples/Callback_Quoter/Consumer_Handler.h138
-rw-r--r--TAO/examples/Callback_Quoter/Consumer_Input_Handler.cpp220
-rw-r--r--TAO/examples/Callback_Quoter/Consumer_Input_Handler.h101
-rw-r--r--TAO/examples/Callback_Quoter/Consumer_Signal_Handler.cpp87
-rw-r--r--TAO/examples/Callback_Quoter/Consumer_Signal_Handler.h70
-rw-r--r--TAO/examples/Callback_Quoter/Consumer_i.cpp63
-rw-r--r--TAO/examples/Callback_Quoter/Consumer_i.h66
-rw-r--r--TAO/examples/Callback_Quoter/Makefile.am174
-rw-r--r--TAO/examples/Callback_Quoter/Notifier.idl35
-rw-r--r--TAO/examples/Callback_Quoter/Notifier_Input_Handler.cpp276
-rw-r--r--TAO/examples/Callback_Quoter/Notifier_Input_Handler.h92
-rw-r--r--TAO/examples/Callback_Quoter/Notifier_i.cpp235
-rw-r--r--TAO/examples/Callback_Quoter/Notifier_i.h120
-rw-r--r--TAO/examples/Callback_Quoter/README121
-rw-r--r--TAO/examples/Callback_Quoter/Supplier_Timer_Handler.cpp101
-rw-r--r--TAO/examples/Callback_Quoter/Supplier_Timer_Handler.h77
-rw-r--r--TAO/examples/Callback_Quoter/Supplier_i.cpp350
-rw-r--r--TAO/examples/Callback_Quoter/Supplier_i.h114
-rw-r--r--TAO/examples/Callback_Quoter/consumer.cpp19
-rw-r--r--TAO/examples/Callback_Quoter/example.stocks56
-rw-r--r--TAO/examples/Callback_Quoter/notifier.cpp44
-rwxr-xr-xTAO/examples/Callback_Quoter/run_test.pl71
-rw-r--r--TAO/examples/Callback_Quoter/supplier.cpp19
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 ();
+}