2 //=============================================================================
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 //=============================================================================
13 #include "Notifier_i.h"
15 // Register a distributed callback handler that is invoked when the
16 // given stock reaches the desired threshold value.
18 Notifier_i::register_callback (const char *stock_name
,
19 CORBA::Long threshold_value
,
20 Callback_Quoter::Consumer_ptr consumer_handler
)
22 // Store the client information.
23 Consumer_Data consumer_data
;
25 // Necessary to make another copy of the consumer_handler using
26 // <_duplicate> so that we dont lose the consumer object reference
27 // after the method invocation is done.
28 consumer_data
.consumer_
=
29 Callback_Quoter::Consumer::_duplicate (consumer_handler
);
31 consumer_data
.desired_value_
= threshold_value
;
33 CONSUMERS
*consumers
= 0;
35 // The consumer_map consists of the stockname and various consumers
36 // with their threshold values. To register a consumer into this
37 // map, first the stockname is matched with an existing one (if any)
38 // and the consumer and the threshold value is attached. Else, a new
39 // entry is created for the stockname.
41 if (this->consumer_map_
.find (stock_name
, consumers
) == 0)
43 if ( consumers
->insert (consumer_data
) == -1)
44 throw Callback_Quoter::Invalid_Stock (
45 "Insertion failed! Invalid Stock!\n");
48 "Inserted map entry: stockname %s threshold %d",
54 // the unbounded set entry is created.
55 ACE_NEW_THROW_EX (consumers
, CONSUMERS
, CORBA::NO_MEMORY ());
57 // When a new entry is tried to be inserted into the unbounded set and it
58 // fails an exception is raised.
59 if (consumers
->insert (consumer_data
) == -1)
60 throw Callback_Quoter::Invalid_Stock (
61 "Insertion failed! Invalid Stock!\n");
63 // The bond between the stockname <hash_key> and the consumers <hash_value>
65 if (this->consumer_map_
.bind (stock_name
, consumers
) == -1)
67 "register_callback: Bind failed!/n"));
70 "new map entry: stockname %s threshold %d\n",
76 // Obtain a pointer to the orb.
78 Notifier_i::orb (CORBA::ORB_ptr orb
)
80 this->orb_
= CORBA::ORB::_duplicate (orb
);
83 // Remove the client handler.
85 Notifier_i::unregister_callback (Callback_Quoter::Consumer_ptr consumer
)
87 // The consumer_map consists of a map of stocknames with consumers
88 // and their threshold values attached to it. To unregister a
89 // consumer it is necessary to remove that entry from the
90 // map. Hence, the map is iterated till the consumer entry to be
91 // removed is found and then removed from the map.
93 // Check to see whether the hash_map still exists. Chances are there
94 // that the notifier has exited closing the hash map.
95 if (notifier_exited_
== 1)
98 for (CONSUMER_MAP::ITERATOR iter
= this->consumer_map_
.begin ();
99 iter
!= this->consumer_map_
.end ();
102 // The *iter is nothing but the stockname + unbounded set of
103 // consumers+threshold values, i.e a ACE_Hash_Map_Entry.
105 Consumer_Data consumer_to_remove
;
107 consumer_to_remove
.consumer_
=
108 Callback_Quoter::Consumer::_duplicate (consumer
);
110 // int_id is a member of the ACE_Hash_Map_Entry. The remove
111 // method will do a find internally using operator == which
112 // will check only the consumer pointers. If match found it
113 // will be removed from the set. If the consumer cannot be
114 // removed an exception is raised.
116 if ((*iter
).int_id_
->remove (consumer_to_remove
) == -1)
117 throw Callback_Quoter::Invalid_Handle (
118 "Unregistration failed! Invalid Consumer Handle!\n");
120 ACE_DEBUG ((LM_DEBUG
,
121 "unregister_callback:consumer removed\n"));
125 // Gets the market status and sends the information to the consumer
126 // who is interested in it.
128 Notifier_i::market_status (const char *stock_name
,
129 CORBA::Long stock_value
)
131 ACE_DEBUG ((LM_DEBUG
,
132 "Notifier_i:: The stockname is %C with price %d\n",
136 CONSUMERS
*consumers
= 0;
138 if (this->consumer_map_
.find (stock_name
, consumers
) == 0)
140 // Go through the list of <Consumer_Data> to find which
141 // registered client wants to be notified.
143 for (CONSUMERS::ITERATOR iter
= consumers
->begin ();
144 iter
!= consumers
->end ();
147 // Check whether the stockname is equal before proceeding
149 if (stock_value
>= (*iter
).desired_value_
)
151 Callback_Quoter::Info interested_consumer_data
;
153 interested_consumer_data
.stock_name
=
154 CORBA::string_dup (stock_name
);
155 interested_consumer_data
.value
=
158 ACE_DEBUG ((LM_DEBUG
,
159 "pushing information to consumer\n"));
161 // The status desired by the consumer is then passed to
163 (*iter
).consumer_
->push (interested_consumer_data
);
168 ACE_DEBUG ((LM_DEBUG
,
169 " Stock Not Present!\n"));
170 // Raising an exception caused problems as they were caught by the Market daemon
171 // who exited prematurely.
175 Notifier_i::shutdown ()
177 if ( this->consumer_map_
.close () > 0)
178 ACE_ERROR ((LM_ERROR
,
179 "Consumer_map_close error!\n"));
181 // This marks the exit of the notifier. This should be taken care of
182 // before the consumer tries to unregister after the notifier quits.
183 notifier_exited_
= 1;
185 ACE_DEBUG ((LM_DEBUG
,
186 "The Callback Quoter server is shutting down...\n"));
189 // Instruct the ORB to shutdown.
190 this->orb_
->shutdown ();
194 Notifier_i::Consumer_Data::operator== (const Consumer_Data
&rhs
) const
196 // The <_is_equivalent> function checks if the _var and _ptr objects
197 // are the same. NOTE: this call might not behave well on other
198 // ORBs since <_is_equivalent> isn't guaranteed to differentiate
199 // object references.
201 return this->consumer_
->_is_equivalent (rhs
.consumer_
.in ());