summaryrefslogtreecommitdiff
path: root/TAO/examples/Callback_Quoter/Notifier_i.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/examples/Callback_Quoter/Notifier_i.cpp')
-rw-r--r--TAO/examples/Callback_Quoter/Notifier_i.cpp235
1 files changed, 235 insertions, 0 deletions
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 ());
+}
+