1 #include "Event_Comm_i.h"
2 #include "ace/OS_NS_regex.h"
5 * Keeps track of context information associated with
6 * a <Event_Comm::Consumer> entry.
11 Consumer_Entry (Event_Comm::Consumer
*consumer
,
12 const char *filtering_criteria
);
15 ~Consumer_Entry (void);
18 // = Set/get filtering criteria.
19 void criteria (const char *criteria
);
20 const char *criteria (void);
22 // = Set/get Event_Comm::Consumer object reference.
23 Event_Comm::Consumer
*consumer (void);
24 void consumer (Event_Comm::Consumer
*);
26 // = Set/get the compiled regular expression buffer.
27 const char *regexp (void);
31 const char *filtering_criteria_
;
32 // String containing the filtering criteria.
34 char *compiled_regexp_
;
35 // Compiled representation of the regular expression (see
38 Event_Comm::Consumer_ptr consumer_
;
39 // Object reference for the <Event_Comm::Consumer>.
42 // = Set/get filtering criteria.
45 Consumer_Entry::criteria (const char *criteria
)
47 ACE_OS::free ((void *) this->filtering_criteria_
);
48 ACE_ALLOCATOR (this->filtering_criteria_
,
49 ACE_OS::strdup (criteria
));
53 Consumer_Entry::criteria (void)
55 return this->filtering_criteria_
;
58 // = Set/get Event_Comm::Consumer object reference.
60 Event_Comm::Consumer
*
61 Consumer_Entry::consumer (void)
63 return this->consumer_
;
67 Consumer_Entry::consumer (Event_Comm::Consumer
*consumer
)
69 this->consumer_
= consumer
;
73 Consumer_Entry::regexp (void)
75 return this->compiled_regexp_
;
79 Consumer_Entry::regexp (char *regexp
)
81 ACE_OS::free ((void *) this->compiled_regexp_
);
82 this->compiled_regexp_
= regexp
;
85 Consumer_Entry::Consumer_Entry (Event_Comm::Consumer
*consumer
,
86 const char *filtering_criteria
)
87 : filtering_criteria_ (0),
91 char *compile_buffer
= 0;
93 this->criteria (filtering_criteria
);
94 ACE_ASSERT (this->criteria ());
96 // Check for wildcard case first.
97 if (ACE_OS::strcmp (filtering_criteria
, "") == 0)
98 ACE_ALLOCATOR (compile_buffer
,
102 #if defined (ACE_HAS_REGEX)
103 // Compile the regular expression (the 0's cause ACE_OS::compile
104 // to allocate space).
105 compile_buffer
= ACE_OS::compile (filtering_criteria
, 0, 0);
107 // Win32 does not support regular expression functions such as compile.
108 ACE_ALLOCATOR (compile_buffer
,
109 ACE_OS::strdup (""));
110 #endif // #if defined (ACE_HAS_REGEX)
113 // Should throw an exception here!
114 ACE_ASSERT (compile_buffer
!= 0);
116 this->regexp (compile_buffer
);
117 ACE_ASSERT (this->regexp () != 0);
119 // Increment the reference count since we are keeping a copy of
121 this->consumer_
= Event_Comm::Consumer::_duplicate (this->consumer_
);
124 Consumer_Entry::~Consumer_Entry (void)
126 ACE_OS::free ((void *) this->filtering_criteria_
);
127 ACE_OS::free ((void *) this->compiled_regexp_
);
128 // Decrement the object reference count.
129 CORBA::release (this->consumer_
);
132 Notifier_i::Notifier_i (size_t size
)
135 // if platforms (such as win32) do not support the REGEXP functions
136 // such as <compile> and <step> then warn the user that the regular
137 // expression feature is not available.
138 #ifndef ACE_HAS_REGEX
139 ACE_DEBUG ((LM_DEBUG
, "\n WARNING: This platform does not support \
140 the functions for regular expressions.\n\
141 The filtering criteria will not work.\n"));
142 #endif //#ifndef ACE_HAS_REGEX
145 // Add a new consumer to the table, being careful to check for
146 // duplicate entries. A consumer is considered a duplicate under the
147 // following circumstances:
149 // 1. It has the same object reference and the same filtering
151 // 2. It has the same object reference and its filtering criteria is
152 // "" (the wild card).
155 Notifier_i::subscribe (Event_Comm::Consumer_ptr consumer_ref
,
156 const char *filtering_criteria
)
158 ACE_DEBUG ((LM_DEBUG
,
159 "in Notifier_i::subscribe for %x with filtering criteria \"%s\"\n",
161 filtering_criteria
));
163 MAP_ITERATOR
mi (this->map_
);
165 // Try to locate an entry checking if the object references are
166 // equivalent. If we don't find the entry, or if the filtering
167 // criteria is different that is good news since we currently don't
168 // allow duplicates... @@ Should duplicates be allowed?
170 for (MAP_ENTRY
*me
= 0; mi
.next (me
) != 0; mi
.advance ())
172 Consumer_Entry
*nr_entry
= me
->int_id_
;
174 // The <_is_equivalent> function checks if objects are the same.
175 // NOTE: this call might not behave well on other ORBs since
176 // <_is_equivalent> isn't guaranteed to differentiate object
179 // Check for a duplicate entry.
180 if (consumer_ref
->_is_equivalent (me
->ext_id_
)
181 && (ACE_OS::strcmp (filtering_criteria
,
183 || ACE_OS::strcmp (filtering_criteria
,
184 nr_entry
->criteria ()) == 0))
186 // Inform the caller that the <Event_Comm::Consumer> * is
187 // already being used.
189 throw Event_Comm::Notifier::CannotSubscribe (
190 "Duplicate consumer and filtering criteria found.\n");
194 // If we get this far then we didn't find a duplicate, so add the
196 Consumer_Entry
*nr_entry
;
198 Consumer_Entry (consumer_ref
,
199 filtering_criteria
));
201 // Try to add new <Consumer_Entry> to the map.
202 if (this->map_
.bind (nr_entry
->consumer(), nr_entry
) == -1)
204 // Prevent memory leaks.
206 throw Event_Comm::Notifier::CannotSubscribe (
207 "Failed to add Consumer to internal map\n");
211 // Remove a consumer from the table.
214 Notifier_i::unsubscribe (Event_Comm::Consumer_ptr consumer_ref
,
215 const char *filtering_criteria
)
217 ACE_DEBUG ((LM_DEBUG
,
218 "in Notifier_i::unsubscribe for %x\n",
221 Consumer_Entry
*nr_entry
= 0;
222 MAP_ITERATOR
mi (this->map_
);
225 // Locate <Consumer_Entry> and free up resources. @@ Note, we don't
226 // properly handle deallocation of KEYS!
228 for (MAP_ENTRY
*me
= 0;
232 nr_entry
= me
->int_id_
;
234 // The <_is_equivalent> function checks if objects are the same.
235 // NOTE: this call might not behave well on other ORBs since
236 // <_is_equivalent> isn't guaranteed to differentiate object
239 // Look for a match ..
240 if (consumer_ref
->_is_equivalent (me
->ext_id_
)
241 && (ACE_OS::strcmp (filtering_criteria
, "") == 0
242 || ACE_OS::strcmp (filtering_criteria
,
243 nr_entry
->criteria ()) == 0))
245 ACE_DEBUG ((LM_DEBUG
,
246 "removed entry %x with criteria \"%s\"\n",
248 filtering_criteria
));
250 // @@ This is a hack, we need a better approach!
251 if (this->map_
.unbind (me
->ext_id_
,
253 throw Event_Comm::Notifier::CannotUnsubscribe (
254 "Internal map unbind failed.");
261 throw Event_Comm::Notifier::CannotUnsubscribe (
262 "The Consumer and filtering criteria were not found.");
265 // Disconnect all the consumers, giving them the <reason>.
268 Notifier_i::disconnect (const char *reason
)
270 ACE_DEBUG ((LM_DEBUG
,
271 "in Notifier_i::send_disconnect = %s\n",
274 MAP_ITERATOR
mi (this->map_
);
277 // Notify all the consumers, taking into account the filtering
280 for (MAP_ENTRY
*me
= 0;
284 Event_Comm::Consumer_ptr consumer_ref
=
287 ACE_ASSERT (consumer_ref
!= 0);
288 ACE_DEBUG ((LM_DEBUG
,
289 "disconnecting client %x\n",
293 consumer_ref
->disconnect (reason
);
295 catch (const CORBA::Exception
& ex
)
297 ex
._tao_print_exception ("Unexpected exception\n");
307 ACE_DEBUG ((LM_DEBUG
,
308 "there was 1 consumer\n"));
310 ACE_DEBUG ((LM_DEBUG
,
311 "there were %d consumers\n",
315 // Notify all consumers whose filtering criteria match the event.
318 Notifier_i::push (const Event_Comm::Event
&event
)
320 ACE_DEBUG ((LM_DEBUG
,
321 "in Notifier_i::send_notification = %s\n",
322 (const char *) event
.tag_
));
323 MAP_ITERATOR
mi (this->map_
);
326 // Notify all the consumers.
328 for (MAP_ENTRY
*me
= 0; mi
.next (me
) != 0; mi
.advance ())
330 Event_Comm::Consumer_ptr consumer_ref
= me
->int_id_
->consumer ();
331 ACE_ASSERT (consumer_ref
!= 0);
333 #if defined (ACE_HAS_REGEX)
334 char *regexp
= const_cast<char *> (me
->int_id_
->regexp ());
337 const char *criteria
= me
->int_id_
->criteria ();
338 ACE_ASSERT (criteria
);
340 // Do a regular expression comparison to determine matching.
341 if (ACE_OS::strcmp ("", criteria
) == 0 // Everything matches the wildcard.
342 || ACE_OS::step (event
.tag_
, regexp
) != 0)
343 #endif // #if defined (ACE_HAS_REGEX)
344 // if ACE_HAS_REGEX has not been defined,
345 // let everything through.
347 ACE_DEBUG ((LM_DEBUG
,
348 "string %s matched regexp \"%s\" for client %x\n",
349 (const char *) event
.tag_
,
350 me
->int_id_
->criteria (),
354 consumer_ref
->push (event
);
356 catch (const CORBA::Exception
& ex
)
358 ex
._tao_print_exception ("Unexpected exception\n");
366 ACE_DEBUG ((LM_DEBUG
,
367 "there was 1 consumer\n"));
369 ACE_DEBUG ((LM_DEBUG
,
370 "there were %d consumers\n",
376 ShutdownCallback::~ShutdownCallback (void)
382 //FUZZ: disable check_for_lack_ACE_OS
383 Consumer_i::Consumer_i (void)
387 //FUZZ: enable check_for_lack_ACE_OS
389 Consumer_i::~Consumer_i (void)
393 // Inform the <Event_Comm::Consumer> that <event> has
397 Consumer_i::push (const Event_Comm::Event
&event
)
399 const char *tmpstr
= event
.tag_
;
401 ACE_DEBUG ((LM_DEBUG
,
402 "**** got notification = %s\n",
406 // Disconnect the <Event_Comm::Consumer> from the
407 // <Event_Comm::Notifier>.
410 Consumer_i::disconnect (const char *reason
)
412 ACE_DEBUG ((LM_DEBUG
,
413 "**** got disconnected due to %s\n",
416 ACE_ASSERT (shutdown
!= 0);
422 Consumer_i::set (ShutdownCallback
*_shutdown
)
424 shutdown
= _shutdown
;