00001 /* 00002 * MapListenerSupport.hpp 00003 * 00004 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 00005 * 00006 * Oracle is a registered trademarks of Oracle Corporation and/or its 00007 * affiliates. 00008 * 00009 * This software is the confidential and proprietary information of Oracle 00010 * Corporation. You shall not disclose such confidential and proprietary 00011 * information and shall use it only in accordance with the terms of the 00012 * license agreement you entered into with Oracle. 00013 * 00014 * This notice may not be removed or altered. 00015 */ 00016 #ifndef COH_MAP_LISTENER_SUPPORT_HPP 00017 #define COH_MAP_LISTENER_SUPPORT_HPP 00018 00019 #include "coherence/lang.ns" 00020 00021 #include "coherence/net/cache/CacheEvent.hpp" 00022 #include "coherence/util/Converter.hpp" 00023 #include "coherence/util/Filter.hpp" 00024 #include "coherence/util/Listeners.hpp" 00025 #include "coherence/util/MapEvent.hpp" 00026 #include "coherence/util/MapListener.hpp" 00027 #include "coherence/util/Set.hpp" 00028 #include "coherence/util/SynchronousListener.hpp" 00029 00030 COH_OPEN_NAMESPACE2(coherence,util) 00031 00032 using coherence::net::cache::CacheEvent; 00033 00034 00035 /** 00036 * This class provides support for advanced MapListener functionality. 00037 * 00038 * @author js 2008.06.10 00039 */ 00040 class COH_EXPORT MapListenerSupport 00041 : public class_spec<MapListenerSupport> 00042 { 00043 friend class factory<MapListenerSupport>; 00044 00045 // ----- constructors --------------------------------------------------- 00046 00047 protected: 00048 /** 00049 * Create a new MapListenerSupport. 00050 */ 00051 MapListenerSupport(); 00052 00053 00054 // ----- MapListenerSupport interface ----------------------------------- 00055 00056 public: 00057 /** 00058 * Add a map listener that receives events based on a filter 00059 * evaluation. 00060 * 00061 * @param hListener the listener to add 00062 * @param vFilter a filter that will be passed MapEvent objects to 00063 * select from; a MapEvent will be delivered to the 00064 * listener only if the filter evaluates to true for 00065 * that MapEvent; NULL is equivalent to a filter 00066 * that alway returns true 00067 * @param fLite true to indicate that the MapEvent objects do not 00068 * have to include the OldValue and NewValue 00069 * property values in order to allow optimizations 00070 */ 00071 virtual void addListener(MapListener::Handle hListener, 00072 Filter::View vFilter, bool fLite); 00073 00074 /** 00075 * Add a map listener for a specific key. 00076 * 00077 * @param hListener the listener to add 00078 * @param vKey the key that identifies the entry for which to 00079 * raise events 00080 * @param fLite true to indicate that the MapEvent objects do not 00081 * have to include the OldValue and NewValue 00082 * property values in order to allow optimizations 00083 * 00084 */ 00085 virtual void addListener(MapListener::Handle hListener, 00086 Object::View vKey, bool fLite); 00087 00088 /** 00089 * Remove a map listener that previously signed up for events based on 00090 * a filter evaluation. 00091 * 00092 * @param vListener the listener to remove 00093 * @param vFilter a filter used to evaluate events 00094 */ 00095 virtual void removeListener(MapListener::View vListener, 00096 Filter::View vFilter); 00097 00098 /** 00099 * Remove a map listener that previously signed up for events about a 00100 * specific key. 00101 * 00102 * @param vListener the listener to remove 00103 * @param vKey the key that identifies the entry for which to 00104 * raise events 00105 */ 00106 virtual void removeListener(MapListener::View vListener, 00107 Object::View vKey); 00108 00109 /** 00110 * Remove all signed up listeners. 00111 */ 00112 virtual void clear(); 00113 00114 /** 00115 * Checks whether or not this MapListenerSupport object contains 00116 * any listeners. 00117 * 00118 * @return true iff there are no listeners encapsulated by this 00119 * MapListenerSupport object 00120 */ 00121 virtual bool isEmpty() const; 00122 00123 /** 00124 * Checks whether or not this MapListenerSupport object contains 00125 * any listeners for a given filter. 00126 * 00127 * @param vFilter the filter 00128 * 00129 * @return true iff there are no listeners for the specified filter 00130 * encapsulated by this MapListenerSupport object 00131 */ 00132 virtual bool isEmpty(Filter::View vFilter) const; 00133 00134 /** 00135 * Checks whether or not this MapListenerSupport object contains 00136 * any listeners for a given key. 00137 * 00138 * @param vKey the key 00139 * 00140 * @return true iff there are no listeners for the specified filter 00141 * encapsulated by this MapListenerSupport object 00142 */ 00143 virtual bool isEmpty(Object::View vKey) const; 00144 00145 /** 00146 * Checks whether or not this MapListenerSupport object contains 00147 * any standard (not lite) listeners for a given filter. 00148 * 00149 * @param vFilter the filter 00150 * 00151 * @return true iff there are no standard listeners for the specified 00152 * filter encapsulated by this MapListenerSupport object 00153 */ 00154 virtual bool containsStandardListeners( 00155 Filter::View vFilter) const; 00156 00157 /** 00158 * Checks whether or not this MapListenerSupport object contains 00159 * any standard (not lite) listeners for a given key. 00160 * 00161 * @param vKey the key 00162 * 00163 * @return true iff there are no standard listeners for the specified 00164 * filter encapsulated by this MapListenerSupport object 00165 */ 00166 virtual bool containsStandardListeners(Object::View vKey) const; 00167 00168 /** 00169 * Obtain a set of all filters that have assosiated global listeners. 00170 * <p> 00171 * <b>Note</b>: The returned value must be treated as an immutable. 00172 * 00173 * @return a set of all filters that have assosiated global listeners 00174 */ 00175 virtual Set::View getFilterSet() const; 00176 00177 /** 00178 * Obtain a set of all keys that have assosiated key listeners. 00179 * <p> 00180 * <b>Note</b>: The returned value must be treated as an immutable. 00181 * 00182 * @return a set of all keys that have assosiated key listeners 00183 */ 00184 virtual Set::View getKeySet() const; 00185 00186 /** 00187 * Obtain the Listeners object for a given filter. 00188 * 00189 * @param vFilter the filter 00190 * 00191 * @return the Listeners object for the filter; NULL if none exists 00192 */ 00193 virtual Listeners::View getListeners(Filter::View vFilter) const; 00194 00195 /** 00196 * Obtain the Listeners object for a given key. 00197 * 00198 * @param vKey the key 00199 * 00200 * @return the Listeners object for the key; NULL if none exists 00201 */ 00202 virtual Listeners::View getListeners(Object::View vKey) const; 00203 00204 /** 00205 * Collect all Listeners that should be notified for a given event. 00206 * <p> 00207 * <b>Note</b>: The returned value must be treated as an immutable. 00208 * 00209 * @param vEvent the MapEvent object 00210 * 00211 * @return the Listeners object containing the relevant listeners 00212 */ 00213 virtual Listeners::View collectListeners(MapEvent::View vEvent); 00214 00215 /** 00216 * Fire the specified map event. 00217 * 00218 * @param hEvent the map event 00219 * @param fStrict if true then any RuntimeException thrown by event 00220 * handlers stops all further event processing and 00221 * the exception is re-thrown; if false then all 00222 * exceptions are logged and the process continues 00223 */ 00224 virtual void fireEvent(MapEvent::Handle hEvent, bool fStrict); 00225 00226 /** 00227 * Convert the specified map event into another MapEvent that ensures 00228 * the lazy event data conversion using the specified converters. 00229 * 00230 * @param vEvent the map event 00231 * @param hmapConv the source for the converted event 00232 * @param vConvKey (optional) the key Converter 00233 * @param vConvVal (optional) the value converter 00234 * 00235 * @return the converted MapEvent object 00236 */ 00237 static MapEvent::Handle convertEvent(MapEvent::View vEvent, 00238 ObservableMap::Handle hmapConv, 00239 Converter::View vConvKey = NULL, 00240 Converter::View vConvVal = NULL); 00241 00242 /** 00243 * Transform the given MapEvent into a FilterEvent if it is not already a 00244 * FilterEvent and there are matching filters associated with the 00245 * specified Listeners object. 00246 * 00247 * @param hEvent the MapEvent to transform, if necessary 00248 * @param vListeners the Listeners object 00249 * 00250 * @return a FilterEvent if the given MapEvent is not a FilterEvent and 00251 * the specified Listeners object has associated filters; 00252 * otherwise, the given MapEvent 00253 * @since Coherence 3.7.1.8 00254 */ 00255 static MapEvent::Handle enrichEvent(MapEvent::Handle hEvent, 00256 Listeners::View vListeners); 00257 00258 /** 00259 * Unwrap the specified map event and return the underlying source event. 00260 * 00261 * @param vEvent the event to unwrap 00262 * 00263 * @return the unwrapped event 00264 */ 00265 static MapEvent::View unwrapEvent(MapEvent::View vEvent); 00266 00267 00268 // ----- helper methods ------------------------------------------------- 00269 00270 protected: 00271 /** 00272 * Evaluate whether or not the specified event should be delivered to the 00273 * listener associated with the specified filter. 00274 * 00275 * @param vFilter the filter 00276 * @param vEvent the event 00277 * 00278 * @return true iff the event should be delivered to the corresponding listener 00279 */ 00280 static bool evaluateEvent(Filter::View vFilter, MapEvent::View vEvent); 00281 00282 /** 00283 * Return true iff the specified event represents a transformed CacheEvent. 00284 * 00285 * @param vEvent the event to test 00286 * 00287 * @return true iff the event has been transformed 00288 */ 00289 static bool isTransformedEvent(MapEvent::View vEvent); 00290 00291 /** 00292 * Ensure that the specified map has a Listeners object assosiated 00293 * with the specified key and add the specified listener to it. 00294 * 00295 * @param hmapListeners map of listeners 00296 * @param vKey key of the listener 00297 * @param hListener the listener to add 00298 */ 00299 static void addSafeListener(Map::Handle hmapListeners, 00300 Object::View vKey, MapListener::Handle hListener); 00301 00302 /** 00303 * Ensure that the specified map has a Listeners object associated 00304 * with the specified Filter and add the specified listener to it. 00305 * 00306 * @param hmapListeners map of listeners 00307 * @param vFilter filter of the listener 00308 * @param hListener the listener to add 00309 * @since Coherence 3.7.1.8 00310 */ 00311 static void addSafeListener(Map::Handle hMapListeners, 00312 Filter::View vAnyFilter, MapListener::Handle hListener); 00313 00314 /** 00315 * Remove the specified listener from the Listeners object assosiated 00316 * with the specified key. 00317 * 00318 * @param hmapListeners map of listeners 00319 * @param vKey key of the listener 00320 * @param vListener the listener to remove 00321 */ 00322 static void removeSafeListener(Map::Handle hmapListeners, 00323 Object::View vKey, MapListener::View vListener); 00324 00325 /** 00326 * Add a state information (lite or standard) associated with 00327 * specified key and listener. 00328 * 00329 * @param hmapStandardListeners map of standard listeners 00330 * @param vKey key of the listener 00331 * @param hListener the listener to add 00332 * @param fLite true to indicate that the MapEvent 00333 * objects do not have to include the 00334 * OldValue and NewValue property values 00335 */ 00336 static void addListenerState(Map::Handle hmapStandardListeners, 00337 Object::View vKey, MapListener::Handle hListener, 00338 bool fLite); 00339 00340 /** 00341 * Remove a state information (lite or standard) assosiated with 00342 * specified key and listener. 00343 * 00344 * @param hmapStandardListeners map of standard listeners 00345 * @param vKey key of the listener 00346 * @param vListener the listener to remove 00347 */ 00348 static void removeListenerState(Map::Handle hmapStandardListeners, 00349 Object::View vKey, MapListener::View vListener); 00350 00351 00352 // ----- Object interface ----------------------------------------------- 00353 00354 public: 00355 /** 00356 * {@inheritDoc} 00357 */ 00358 virtual void toStream(std::ostream& out) const; 00359 00360 00361 // ----- inner class: FilterEvent --------------------------------------- 00362 00363 public: 00364 /** 00365 * An extension of the CacheEvent which may carry no values (old or 00366 * new), but instead holds an array of Filter objects being the 00367 * "cause" of the event. 00368 */ 00369 class COH_EXPORT FilterEvent 00370 : public class_spec<FilterEvent, 00371 extends<CacheEvent> > 00372 { 00373 friend class factory<FilterEvent>; 00374 00375 // ----- constructors --------------------------------------- 00376 00377 protected: 00378 /** 00379 * Create a new FilterEvent with no old and new values. 00380 * 00381 * @param hMap the map on which the Event initially 00382 * occurred 00383 * @param nId the events id (entry_inserted | 00384 * entry_updated | entry_deleted) 00385 * @param vKey the key into the map 00386 * @param fSynthetic true iff the event is caused by internal 00387 * cache processing such as eviction or 00388 * loading 00389 * @param vaFilters an array of Filters that caused this event. 00390 */ 00391 FilterEvent(ObservableMap::Handle hMap, int32_t nId, 00392 Object::View vKey, Object::View vValueOld, 00393 Object::View vValueNew, bool fSynthetic, 00394 ObjectArray::View vaFilters); 00395 00396 /** 00397 * Create a new FilterEvent with no old and new values. 00398 * 00399 * @param hMap the map on which the Event initially 00400 * occurred 00401 * @param nId the events id (entry_inserted | 00402 * entry_updated | entry_deleted) 00403 * @param vKey the key into the map 00404 * @param fSynthetic true iff the event is caused by internal 00405 * cache processing such as eviction or 00406 * loading 00407 * @param nTransformState the state describing how this event has 00408 * been or should be transformed 00409 * @param vaFilters an array of Filters that caused this event. 00410 */ 00411 FilterEvent(ObservableMap::Handle hMap, int32_t nId, 00412 Object::View vKey, Object::View vValueOld, 00413 Object::View vValueNew, bool fSynthetic, 00414 TransformationState nTransformState, 00415 ObjectArray::View vaFilters); 00416 00417 // ----- FilterEvent interface ------------------------------ 00418 00419 public: 00420 /** 00421 * Return an array of filters that are the cause of this 00422 * event. 00423 * 00424 * @return an array of filters 00425 */ 00426 virtual ObjectArray::View getFilter() const; 00427 00428 /** 00429 * Set the event that this FilterEvent wraps. 00430 * 00431 * @param vEvent the wrapped event 00432 * @since Coherence 3.7.1.8 00433 */ 00434 virtual void setEvent(MapEvent::View vEvent); 00435 00436 // ----- Describable interface ------------------------------ 00437 00438 public: 00439 /** 00440 * {@inheritDoc} 00441 */ 00442 virtual void outputDescription(std::ostream& out) const; 00443 00444 // ----- MapEvent methods ----------------------------------- 00445 00446 public: 00447 /** 00448 * {@inheritDoc} 00449 */ 00450 virtual Object::View getKey() const; 00451 00452 /** 00453 * {@inheritDoc} 00454 */ 00455 virtual Object::View getOldValue() const; 00456 00457 /** 00458 * {@inheritDoc} 00459 */ 00460 virtual Object::View getNewValue() const; 00461 00462 // ----- helper methods ------------------------------------- 00463 00464 public: 00465 /** 00466 * Determine if this filter event contains a specified filter. 00467 * 00468 * @param vFilter the filter to search for 00469 * 00470 * @return true if the event contained the specified filter, 00471 * false otherwise 00472 */ 00473 virtual bool containsFilter(Filter::View vFilter) const; 00474 00475 // ----- data members --------------------------------------- 00476 00477 protected: 00478 /** 00479 * Filters which caused the event. 00480 */ 00481 FinalView<ObjectArray> f_vaFilters; 00482 00483 /** 00484 * Optional wrapped MapEvent. 00485 * @since Coherence 3.7.1.8 00486 */ 00487 FinalView<MapEvent> f_vEvent; 00488 }; 00489 00490 00491 // ----- inner class: SynchronousListener ------------------------------- 00492 00493 public: 00494 /** 00495 * A tag interface indicating that tagged MapListener implementation 00496 * has to receive the MapEvent notifications in a synchronous manner. 00497 * <p> 00498 * Consider a MapListener that subscribes to receive notifications for 00499 * distributed (partitioned) cache. All events notifications are 00500 * received by the service thread and immediately queued to be 00501 * processed by the dedicated event dispatcher thread. This makes it 00502 * impossible to differentiate between the event caused by the updates 00503 * made by this thread and any other thread (possibly in a different 00504 * VM). Forcing the events to be processed on the service thread 00505 * guarantees that by the time "put" or "remove" requests return to 00506 * the caller all relevant MapEvent notification have been processed 00507 * (due to the "in order delivery" rule enforced by the TCMP). 00508 * <p> 00509 * This interface should be considered as a very advanced feature, so 00510 * a MapListener implementation that is tagged as a 00511 * SynchronousListener must exercise extreme caution during event 00512 * processing since any delay with return or unhandled exception will 00513 * cause a delay or complete shutdown of the corresponding cache 00514 * service. 00515 * <p> 00516 * <b>Note:</b> The contract by the event producer in respect to the 00517 * SynchronousListener is somewhat weaker then the general one. 00518 * First, the SynchronousListener implementaion should make no 00519 * assumptions about the event source obtained by {MapEvent#getMap()}. 00520 * Second, in the event of [automatic] service restart, the listener 00521 * has to be re-registered manually (for example, in response to the 00522 * {com::tangosol::net::MemberEvent#member_joined member_joined} 00523 * event). Third, and the most important, no calls against the 00524 * NamedCache are allowed during the synchronous event processing (the 00525 * only exception being a call to remove the listener itself). 00526 */ 00527 class COH_EXPORT SynchronousListener 00528 : public interface_spec<SynchronousListener, 00529 implements<coherence::util::SynchronousListener, MapListener> > 00530 { 00531 }; 00532 00533 00534 // ----- inner class: WrapperSynchronousListener ------------------------ 00535 00536 public: 00537 /** 00538 * A wrapper class that turns the specified MapListener into 00539 * a synchronous listener. 00540 */ 00541 class COH_EXPORT WrapperSynchronousListener 00542 : public class_spec<WrapperSynchronousListener, 00543 extends<Object>, 00544 implements<SynchronousListener> > 00545 { 00546 friend class factory<WrapperSynchronousListener>; 00547 00548 // ----- constructors --------------------------------------- 00549 00550 protected: 00551 /** 00552 * Create a new WrapperSynchronousListener. 00553 * 00554 * @param hListener the listener to be wrapped 00555 * 00556 * @return the new WrapperSynchronousListener instance 00557 */ 00558 WrapperSynchronousListener(MapListener::Handle hListener); 00559 00560 // ----- MapListener interface ------------------------------ 00561 00562 public: 00563 /** 00564 * {@inheritDoc} 00565 */ 00566 virtual void entryInserted(MapEvent::View vEvent); 00567 00568 /** 00569 * {@inheritDoc} 00570 */ 00571 virtual void entryUpdated(MapEvent::View vEvent); 00572 00573 /** 00574 * {@inheritDoc} 00575 */ 00576 virtual void entryDeleted(MapEvent::View vEvent); 00577 00578 // ----- Object interface ----------------------------------- 00579 00580 public: 00581 /** 00582 * {@inheritDoc} 00583 */ 00584 virtual size32_t hashCode() const; 00585 00586 /** 00587 * {@inheritDoc} 00588 */ 00589 virtual bool equals(Object::View v) const; 00590 00591 // ----- data members --------------------------------------- 00592 00593 protected: 00594 /** 00595 * Wrapped MapListener. 00596 */ 00597 MemberHandle<MapListener> m_hListener; 00598 }; 00599 00600 00601 // ----- enums ---------------------------------------------------------- 00602 00603 protected: 00604 /** 00605 * Optimization Plan enum. 00606 */ 00607 enum Plan 00608 { 00609 none, // A plan has not yet been formed 00610 no_listeners, // There are no listeners 00611 all_listener, // There is one all-keys non-filtered listener 00612 key_listener, // One key listener (even if for multiple keys) 00613 no_optimize // No optimized plan, use the default approach 00614 }; 00615 00616 00617 // ----- data members --------------------------------------------------- 00618 00619 protected: 00620 /** 00621 * The collections of MapListener objects that have signed up for 00622 * notifications from an ObservableMap implementation keyed by the 00623 * corresponding Filter objects. 00624 */ 00625 MemberHandle<Map> m_hmapListeners; 00626 00627 /** 00628 * The collections of MapListener objects that have signed up for key 00629 * based notifications from an ObservableMap implementation keyed by 00630 * the corresponding key objects. 00631 */ 00632 MemberHandle<Map> m_hmapKeyListeners; 00633 00634 // consider adding listener tag support to Listeners class, which 00635 // would allow getting rid of the following data structures ... 00636 /** 00637 * The subset of standard (not lite) global listeners. The keys are 00638 * the Filter objects, the values are sets of corresponding standard 00639 * listeners. 00640 */ 00641 MemberHandle<Map> m_hmapStandardListeners; 00642 00643 /** 00644 * The subset of standard (not lite) key listeners. The keys are the 00645 * key objects, the values are sets of corresponding standard 00646 * listeners. 00647 */ 00648 MemberHandle<Map> m_hmapStandardKeyListeners; 00649 00650 /** 00651 * The optimization plan which indicates the fastest way to put 00652 * together a set of listeners. 00653 */ 00654 Plan m_optimizationPlan; 00655 00656 /** 00657 * A cached set of Listeners. 00658 */ 00659 MemberView<Listeners> m_vListenersCached; 00660 }; 00661 00662 COH_CLOSE_NAMESPACE2 00663 00664 #endif // COH_MAP_LISTENER_SUPPORT_HPP 00665