Merge pull request #1551 from DOCGroup/plm_jira_333
[ACE_TAO.git] / TAO / examples / Callback_Quoter / Notifier_i.cpp
blob64855f0766d0c9fe3fb40b0dbf0b010a5537cb10
2 //=============================================================================
3 /**
4 * @file Notifier_i.cpp
6 * Implementation of the Notifier_i class. This class is the servant
7 * object for the callback quoter server.
9 * @author Kirthika Parameswaran <kirthika@cs.wustl.edu>
11 //=============================================================================
14 #include "Notifier_i.h"
17 Notifier_i::Notifier_i (void)
18 : notifier_exited_(0)
20 // No-op
23 Notifier_i::~Notifier_i (void)
25 // No-op
28 // Register a distributed callback handler that is invoked when the
29 // given stock reaches the desired threshold value.
31 void
32 Notifier_i::register_callback (const char *stock_name,
33 CORBA::Long threshold_value,
34 Callback_Quoter::Consumer_ptr consumer_handler)
36 // Store the client information.
37 Consumer_Data consumer_data;
39 // Necessary to make another copy of the consumer_handler using
40 // <_duplicate> so that we dont lose the consumer object reference
41 // after the method invocation is done.
42 consumer_data.consumer_ =
43 Callback_Quoter::Consumer::_duplicate (consumer_handler);
45 consumer_data.desired_value_= threshold_value;
47 CONSUMERS *consumers = 0;
49 // The consumer_map consists of the stockname and various consumers
50 // with their threshold values. To register a consumer into this
51 // map, first the stockname is matched with an existing one (if any)
52 // and the consumer and the threshold value is attached. Else, a new
53 // entry is created for the stockname.
55 if (this->consumer_map_.find (stock_name, consumers) == 0)
57 if ( consumers->insert (consumer_data) == -1)
58 throw Callback_Quoter::Invalid_Stock (
59 "Insertion failed! Invalid Stock!\n");
60 else
61 ACE_DEBUG ((LM_DEBUG,
62 "Inserted map entry: stockname %s threshold %d",
63 stock_name,
64 threshold_value));
66 else
68 // the unbounded set entry is created.
69 ACE_NEW_THROW_EX (consumers, CONSUMERS, CORBA::NO_MEMORY ());
71 // When a new entry is tried to be inserted into the unbounded set and it
72 // fails an exception is raised.
73 if (consumers->insert (consumer_data) == -1)
74 throw Callback_Quoter::Invalid_Stock (
75 "Insertion failed! Invalid Stock!\n");
77 // The bond between the stockname <hash_key> and the consumers <hash_value>
78 // is fused.
79 if (this->consumer_map_.bind (stock_name, consumers) == -1)
80 ACE_ERROR ((LM_ERROR,
81 "register_callback: Bind failed!/n"));
82 else
83 ACE_DEBUG ((LM_DEBUG,
84 "new map entry: stockname %s threshold %d\n",
85 stock_name,
86 threshold_value));
90 // Obtain a pointer to the orb.
92 void
93 Notifier_i::orb (CORBA::ORB_ptr orb)
95 this->orb_ = CORBA::ORB::_duplicate (orb);
98 // Remove the client handler.
100 void
101 Notifier_i::unregister_callback (Callback_Quoter::Consumer_ptr consumer)
103 // The consumer_map consists of a map of stocknames with consumers
104 // and their threshold values attached to it. To unregister a
105 // consumer it is necessary to remove that entry from the
106 // map. Hence, the map is iterated till the consumer entry to be
107 // removed is found and then removed from the map.
109 // Check to see whether the hash_map still exists. Chances are there
110 // that the notifier has exited closing the hash map.
111 if (notifier_exited_ == 1)
112 return;
114 for (CONSUMER_MAP::ITERATOR iter = this->consumer_map_.begin ();
115 iter != this->consumer_map_.end ();
116 ++iter)
118 // The *iter is nothing but the stockname + unbounded set of
119 // consumers+threshold values, i.e a ACE_Hash_Map_Entry.
121 Consumer_Data consumer_to_remove;
123 consumer_to_remove.consumer_ =
124 Callback_Quoter::Consumer::_duplicate (consumer);
126 // int_id is a member of the ACE_Hash_Map_Entry. The remove
127 // method will do a find internally using operator == which
128 // will check only the consumer pointers. If match found it
129 // will be removed from the set. If the consumer cannot be
130 // removed an exception is raised.
132 if ((*iter).int_id_->remove (consumer_to_remove) == -1)
133 throw Callback_Quoter::Invalid_Handle (
134 "Unregistration failed! Invalid Consumer Handle!\n");
135 else
136 ACE_DEBUG ((LM_DEBUG,
137 "unregister_callback:consumer removed\n"));
141 // Gets the market status and sends the information to the consumer
142 // who is interested in it.
144 void
145 Notifier_i::market_status (const char *stock_name,
146 CORBA::Long stock_value)
148 ACE_DEBUG ((LM_DEBUG,
149 "Notifier_i:: The stockname is %s with price %d\n",
150 stock_name,
151 stock_value));
153 CONSUMERS *consumers = 0;
155 if (this->consumer_map_.find (stock_name, consumers) == 0)
157 // Go through the list of <Consumer_Data> to find which
158 // registered client wants to be notified.
160 for (CONSUMERS::ITERATOR iter = consumers->begin ();
161 iter != consumers->end ();
162 ++iter)
164 // Check whether the stockname is equal before proceeding
165 // further.
166 if (stock_value >= (*iter).desired_value_)
168 Callback_Quoter::Info interested_consumer_data;
170 interested_consumer_data.stock_name =
171 CORBA::string_dup (stock_name);
172 interested_consumer_data.value =
173 stock_value;
175 ACE_DEBUG ((LM_DEBUG,
176 "pushing information to consumer\n"));
178 // The status desired by the consumer is then passed to
179 // it.
180 (*iter).consumer_->push (interested_consumer_data);
184 else
185 ACE_DEBUG ((LM_DEBUG,
186 " Stock Not Present!\n"));
187 // Raising an exception caused problems as they were caught by the Market daemon
188 // who exited prematurely.
192 void
193 Notifier_i::shutdown (void)
195 if ( this->consumer_map_.close () > 0)
196 ACE_ERROR ((LM_ERROR,
197 "Consumer_map_close error!\n"));
198 else
199 // This marks the exit of the notifier. This should be taken care of
200 // before the consumer tries to unregister after the notifier quits.
201 notifier_exited_ = 1;
203 ACE_DEBUG ((LM_DEBUG,
204 "The Callback Quoter server is shutting down...\n"));
207 // Instruct the ORB to shutdown.
208 this->orb_->shutdown ();
212 bool
213 Notifier_i::Consumer_Data::operator== (const Consumer_Data &rhs) const
215 // The <_is_equivalent> function checks if the _var and _ptr objects
216 // are the same. NOTE: this call might not behave well on other
217 // ORBs since <_is_equivalent> isn't guaranteed to differentiate
218 // object references.
220 return this->consumer_->_is_equivalent (rhs.consumer_.in ());