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