00001 /* 00002 * CachingMap.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_CACHING_MAP_HPP 00017 #define COH_CACHING_MAP_HPP 00018 00019 #include "coherence/lang.ns" 00020 00021 #include "coherence/net/cache/CacheMap.hpp" 00022 #include "coherence/net/cache/SimpleCacheStatistics.hpp" 00023 00024 #include "coherence/util/AbstractMapListener.hpp" 00025 #include "coherence/util/Collection.hpp" 00026 #include "coherence/util/ConcurrentMap.hpp" 00027 #include "coherence/util/Filter.hpp" 00028 #include "coherence/util/List.hpp" 00029 #include "coherence/util/Map.hpp" 00030 #include "coherence/util/MapListener.hpp" 00031 #include "coherence/util/MapListenerSupport.hpp" 00032 #include "coherence/util/MultiplexingMapListener.hpp" 00033 #include "coherence/util/Set.hpp" 00034 00035 #include "coherence/util/filter/CacheEventFilter.hpp" 00036 #include "coherence/util/filter/MapEventFilter.hpp" 00037 00038 COH_OPEN_NAMESPACE3(coherence,net,cache) 00039 00040 using coherence::util::AbstractMapListener; 00041 using coherence::util::Collection; 00042 using coherence::util::ConcurrentMap; 00043 using coherence::util::Filter; 00044 using coherence::util::List; 00045 using coherence::util::Map; 00046 using coherence::util::MapListener; 00047 using coherence::util::MapListenerSupport; 00048 using coherence::util::MultiplexingMapListener; 00049 using coherence::util::Set; 00050 using coherence::util::filter::CacheEventFilter; 00051 using coherence::util::filter::MapEventFilter; 00052 00053 00054 /** 00055 * Map implementation that wraps two maps - a front map (assumed to be 00056 * "inexpensive" and probably "incomplete") and a back map (assumed to 00057 * be "complete" and "correct", but more "expensive") - using a 00058 * read-through/write-through approach. 00059 * 00060 * If the back map implements ObservableMap interface, the CachingMap provides 00061 * four different strategies of invalidating the front map entries that have 00062 * changed by other processes in the back map: 00063 * 00064 * listen_none strategy instructs the cache not to listen for invalidation 00065 * events at all. This is the best choice for raw performance and 00066 * scalability when business requirements permit the use of data which 00067 * might not be absolutely current. Freshness of data can be guaranteed 00068 * by use of a sufficiently brief eviction policy for the front map; 00069 * listen_present strategy instructs the CachingMap to listen to the 00070 * back map events related <b>only</b> to the items currently present in 00071 * the front map. This strategy works best when each instance of a front 00072 * map contains distinct subset of data relative to the other front map 00073 * instances (e.g. sticky data access patterns); 00074 * listen_all strategy instructs the CachingMap to listen to <b>all</b> 00075 * back map events. This strategy is optimal for read-heavy tiered access 00076 * patterns where there is significant overlap between the different 00077 * instances of front maps; 00078 * listen_auto strategy instructs the CachingMap implementation to switch 00079 * automatically between listen_present and listen_all strategies based 00080 * on the cache statistics. 00081 * listen_logical strategy instructs the CachingMap to listen to <b>all</b> 00082 * back map events that are <b>not synthetic</b>. A synthetic event could 00083 * be emitted as a result of eviction or expiration. With this 00084 * invalidation strategy, it is possible for the front map to contain 00085 * cache entries that have been synthetically removed from the back 00086 * (though any subsequent re-insertion will cause the corresponding 00087 * entries in the front map to be invalidated). 00088 * 00089 * The front map implementation is assumed to be thread safe; additionally 00090 * any modifications to the front map are allowed only after the corresponding 00091 * lock is acquired against the ControlMap. 00092 * 00093 * <b>Note:</b> NULL values are not cached in the front map and therefore this 00094 * implementation is not optimized for maps that allow NULL values to be 00095 * stored. 00096 * 00097 * @author tb 2008.06.12 00098 */ 00099 class COH_EXPORT CachingMap 00100 : public class_spec<CachingMap, 00101 extends<Object>, 00102 implements<Map> > 00103 { 00104 friend class factory<CachingMap>; 00105 00106 // ----- handle definitions (needed for nested classes) ----------------- 00107 00108 public: 00109 typedef this_spec::Handle Handle; 00110 typedef this_spec::View View; 00111 typedef this_spec::Holder Holder; 00112 00113 00114 // ----- enums ---------------------------------------------------------- 00115 00116 public: 00117 /** 00118 * Enum for invalidation strategies 00119 */ 00120 enum InvalidationStrategy 00121 { 00122 /** 00123 * No invalidation strategy. 00124 */ 00125 listen_none, 00126 00127 /** 00128 * Invalidation strategy that instructs the CachingMap to listen 00129 * to the back map events related <b>only</b> to the items 00130 * currently present in the front map; this strategy serves best 00131 * when the changes to the back map come mostly from the 00132 * CachingMap itself. 00133 */ 00134 listen_present, 00135 00136 /** 00137 * Invalidation strategy that instructs the CachingMap to listen 00138 * to <b>all</b> back map events; this strategy is preferred when 00139 * updates to the back map are frequent and with high probability 00140 * come from the outside of this CachingMap; for example multiple 00141 * CachingMap instances using the same back map with a large 00142 * degree of key set overlap between front maps. 00143 */ 00144 listen_all, 00145 00146 /** 00147 * Invalidation strategy that instructs the CachingMap 00148 * implementation to switch automatically between listen_present 00149 * and listen_all strategies based on the cache statistics. 00150 */ 00151 listen_auto, 00152 00153 /** 00154 * Invalidation strategy that instructs the CachingMap to listen 00155 * to <b>all</b> back map events that are <b>not synthetic</b>. A 00156 * synthetic event could be emitted as a result of eviction or 00157 * expiration. With this invalidation strategy, it is possible 00158 * for the front map to contain cache entries that have been 00159 * synthetically removed from the back (though any subsequent 00160 * re-insertion will cause the corresponding entries in the front 00161 * map to be invalidated). 00162 */ 00163 listen_logical 00164 }; 00165 00166 00167 // ----- constructors --------------------------------------------------- 00168 00169 protected: 00170 /** 00171 * Construct a CachingMap using two specified maps: 00172 * <i>FrontMap</i> (aka "cache", "near" or "shallow") and 00173 * <i>BackMap</i> (aka "actual", "real" or "deep"). 00174 * 00175 * If the BackMap implements the ObservableMap interface a listener 00176 * will be added to the BackMap to invalidate FrontMap items updated 00177 * [externally] in the back map using the listen_auto strategy. 00178 * 00179 * If no MapControl is specified then a new one is created. 00180 * 00181 * @param hMapFront front map 00182 * @param hMapBack back map 00183 * @param strategy specifies the strategy used for the front map 00184 * invalidation; valid values are LISTEN_* 00185 * constants 00186 * @param hMapControl the ConcurrentMap to keep track of front map 00187 * updates; may be NULL 00188 */ 00189 CachingMap(CacheMap::Handle hMapFront, CacheMap::Handle hMapBack, 00190 InvalidationStrategy strategy = listen_auto, 00191 ConcurrentMap::Handle hMapControl = NULL); 00192 00193 00194 // ----- life-cycle ----------------------------------------------------- 00195 00196 public: 00197 /** 00198 * Release the CachingMap. If the BackMap implements an ObservableMap 00199 * calling this method is necessary to remove the BackMap listener. 00200 * Any access to the CachingMap which has been released will cause 00201 * IllegalStateException. 00202 * 00203 * @throws IllegalStateException if accessing the CachingMap 00204 * which has been released 00205 */ 00206 virtual void release(); 00207 00208 00209 // ----- accessors ------------------------------------------------------ 00210 00211 public: 00212 /** 00213 * Obtain the front map reference. 00214 * 00215 * <b>Note:</b> direct modifications of the returned map may cause an 00216 * unpredictable behavior of the CachingMap. 00217 * 00218 * @return the front Map 00219 */ 00220 virtual CacheMap::Handle getFrontMap() const; 00221 00222 /** 00223 * Obtain the back map reference. 00224 * 00225 * <b>Note:</b> direct modifications of the returned map may cause an 00226 * unpredictable behavior of the CachingMap. 00227 * 00228 * @return the back Map 00229 */ 00230 virtual CacheMap::Handle getBackMap() const; 00231 00232 /** 00233 * Obtain the invalidation strategy used by this CachingMap. 00234 * 00235 * @return one of LISTEN_* values 00236 */ 00237 virtual InvalidationStrategy getInvalidationStrategy() const; 00238 00239 /** 00240 * Obtain the ConcurrentMap that should be used to synchronize 00241 * the front map modification access. 00242 * 00243 * @return a ConcurrentMap controlling the front map modifications 00244 */ 00245 virtual ConcurrentMap::Handle getControlMap() const; 00246 00247 /** 00248 * Obtain the CacheStatistics for this cache. 00249 * 00250 * @return a CacheStatistics object 00251 */ 00252 virtual CacheStatistics::Handle getCacheStatistics() const; 00253 00254 /** 00255 * Determine the rough number of front map invalidation hits since 00256 * the cache statistics were last reset. 00257 * 00258 * An invalidation hit is an externally induced map event for an entry 00259 * that exists in the front map. 00260 * 00261 * @return the number of cache invalidation hits 00262 */ 00263 virtual int64_t getInvalidationHits() const; 00264 00265 /** 00266 * Determine the rough number of front map invalidation misses since 00267 * the cache statistics were last reset. 00268 * 00269 * An invalidation miss is an externally induced map event for an 00270 * entry that does not exists in the front map. 00271 * 00272 * @return the number of cache invalidation misses 00273 */ 00274 virtual int64_t getInvalidationMisses() const; 00275 00276 /** 00277 * Determine the total number of registerListener(Object::View vKey) 00278 * operations since the cache statistics were last reset. 00279 * 00280 * @return the total number of listener registrations 00281 */ 00282 virtual int64_t getTotalRegisterListener() const; 00283 00284 protected: 00285 /** 00286 * Determine if changes to the back map affect the front map so that 00287 * data in the front map stays in sync. 00288 * 00289 * @return true if the front map has a means to stay in sync with the 00290 * back map so that it does not contain stale data 00291 */ 00292 virtual bool isCoherent() const; 00293 00294 00295 // ----- CachingMap interface ------------------------------------------- 00296 00297 protected: 00298 /** 00299 * Invalidate the key from the front. The caller must have the key 00300 * locked. 00301 * 00302 * @param vKey the key to invalidate 00303 */ 00304 virtual void invalidateFront(Object::View vKey) const; 00305 00306 /** 00307 * Helper method used by put() and putAll() to perform common 00308 * maintanence tasks after completing an operation against the back. 00309 * This includes removing the keys from the control map, and 00310 * evaluating if it is safe to update the front with the "new" value. 00311 * The implementation makes use of the following assumption: if 00312 * listEvents == IGNORE_LIST then oKey does not exist in the 00313 * front, and there is no key based listener for it. Any key passed 00314 * to this method must be locked in the control map by the caller. 00315 * 00316 * @param vKey the key 00317 * @param ohValue the new value 00318 * @param hlistEvents the event list associated with the key 00319 * @param cMillis the number of milliseconds until the cache entry 00320 * will expire 00321 */ 00322 virtual void finalizePut(Object::View vKey, Object::Holder ohValue, 00323 List::Handle hlistEvents, int64_t cMillis); 00324 00325 public: 00326 /** 00327 * Implementation of put method that optionally skips the return value 00328 * retrieval and allows to specify an expiry for the cache entry. 00329 * 00330 * @param vKey the key 00331 * @param ohValue the value 00332 * @param fReturn if true, the return value is required; otherwise 00333 * the return value will be ignored 00334 * @param cMillis the number of milliseconds until the cache entry 00335 * will expire 00336 * @return previous value (if required) 00337 * 00338 * @throws UnsupportedOperationException if the requested expiry is a 00339 * positive value and either the front map or the back map 00340 * implementations do not support the expiration functionality 00341 */ 00342 virtual Object::Holder put(Object::View vKey, Object::Holder ohValue, 00343 bool fReturn, int64_t cMillis); 00344 00345 /** 00346 * Get all the specified keys, if they are in the cache. For each key 00347 * that is in the cache, that key and its corresponding value will be 00348 * placed in the map that is returned by this method. The absence of 00349 * a key in the returned map indicates that it was not in the cache, 00350 * which may imply (for caches that can load behind the scenes) that 00351 * the requested data could not be loaded. 00352 * 00353 * <b>Note:</b> this implementation does not differentiate between 00354 * missing keys or NULL values stored in the back map; in both cases 00355 * the returned map will not contain the corresponding entry. 00356 * 00357 * @param vColKeys a collection of keys that may be in the named 00358 * cache 00359 * 00360 * @return a Map of keys to values for the specified keys passed in 00361 * <tt>col</tt> 00362 */ 00363 virtual Map::View getAll(Collection::View vColKeys) const; 00364 00365 00366 // ----- Map interface -------------------------------------------------- 00367 00368 public: 00369 /** 00370 * {@inheritDoc} 00371 */ 00372 virtual size32_t size() const; 00373 00374 /** 00375 * {@inheritDoc} 00376 */ 00377 virtual bool isEmpty() const; 00378 00379 /** 00380 * {@inheritDoc} 00381 */ 00382 virtual bool containsKey(Object::View vKey) const; 00383 00384 /** 00385 * {@inheritDoc} 00386 */ 00387 virtual bool containsValue(Object::View vValue) const; 00388 00389 /** 00390 * {@inheritDoc} 00391 */ 00392 virtual Object::Holder get(Object::View vKey) const; 00393 00394 /** 00395 * {@inheritDoc} 00396 */ 00397 virtual Object::Holder get(Object::View vKey); 00398 00399 /** 00400 * {@inheritDoc} 00401 */ 00402 virtual Object::Holder put(Object::View vKey, Object::Holder ohValue); 00403 00404 /** 00405 * {@inheritDoc} 00406 */ 00407 virtual Object::Holder remove(Object::View vKey); 00408 00409 /** 00410 * {@inheritDoc} 00411 */ 00412 virtual void putAll(Map::View vMap); 00413 00414 /** 00415 * {@inheritDoc} 00416 */ 00417 virtual void clear(); 00418 00419 /** 00420 * {@inheritDoc} 00421 */ 00422 virtual Set::View keySet() const; 00423 00424 /** 00425 * {@inheritDoc} 00426 */ 00427 virtual Set::Handle keySet(); 00428 00429 /** 00430 * {@inheritDoc} 00431 */ 00432 virtual Collection::View values() const; 00433 00434 /** 00435 * {@inheritDoc} 00436 */ 00437 virtual Collection::Handle values(); 00438 00439 /** 00440 * {@inheritDoc} 00441 */ 00442 virtual Set::View entrySet() const; 00443 00444 /** 00445 * {@inheritDoc} 00446 */ 00447 virtual Set::Handle entrySet(); 00448 00449 00450 // ----- Object interface ----------------------------------------------- 00451 00452 public: 00453 /** 00454 * {@inheritDoc} 00455 */ 00456 virtual void toStream(std::ostream& out) const; 00457 00458 protected: 00459 /** 00460 * {@inheritDoc} 00461 */ 00462 virtual void onInit(); 00463 00464 00465 // ----- back map listener support -------------------------------------- 00466 00467 public: 00468 /** 00469 * Register the global back map listener. 00470 */ 00471 virtual void registerListener() const; 00472 00473 /** 00474 * Unregister the global back map listener. 00475 */ 00476 virtual void unregisterListener() const; 00477 00478 /** 00479 * Register the back map listener for the specified key. 00480 * 00481 * @param vKey the key 00482 */ 00483 virtual void registerListener(Object::View vKey) const; 00484 00485 /** 00486 * Unregister the back map listener for the specified key. 00487 * 00488 * @param vKey the key 00489 */ 00490 virtual void unregisterListener(Object::View vKey) const; 00491 00492 /** 00493 * Register the global front map listener. 00494 */ 00495 virtual void registerFrontListener() const; 00496 00497 /** 00498 * Unregister the global front map listener. 00499 */ 00500 virtual void unregisterFrontListener() const; 00501 00502 /** 00503 * Ensure that a strategy has been choosen and that any appropriate 00504 * global listeners have been registered. 00505 * 00506 * @return the current strategy 00507 */ 00508 virtual InvalidationStrategy ensureInvalidationStrategy() const; 00509 00510 /** 00511 * Reset the "current invalidation strategy" flag. 00512 * 00513 * This method should be called <b>only</b> while the access to the 00514 * front map is fully synchronzied and the front map is empty to 00515 * prevent stalled data. 00516 */ 00517 virtual void resetInvalidationStrategy(); 00518 00519 00520 // ----- inner class: BackMapListener ----------------------------------- 00521 00522 protected: 00523 /** 00524 * MapListener for back map responsible for keeping the front map 00525 * coherent with the back map. This listener is registered as a 00526 * synchronous listener for lite events (carrying only a key). 00527 */ 00528 class BackMapListener 00529 : public class_spec<BackMapListener, 00530 extends<MultiplexingMapListener>, 00531 implements<MapListenerSupport::SynchronousListener> > 00532 { 00533 friend class factory<BackMapListener>; 00534 00535 // ----- constructors --------------------------------------- 00536 00537 protected: 00538 /** 00539 * Construct a BackMapListener 00540 * 00541 * @param hMap the map associated with this listener 00542 */ 00543 BackMapListener(CachingMap::Handle hMap); 00544 00545 // ----- MultiplexingMapListener interface ------------------ 00546 00547 /** 00548 * {@inheritDoc} 00549 */ 00550 virtual void onMapEvent(MapEvent::View vEvent); 00551 00552 // ---- data members ---------------------------------------- 00553 00554 protected: 00555 /** 00556 * The map associated with this listener. 00557 */ 00558 WeakHandle<CachingMap> m_whMap; 00559 }; 00560 00561 00562 // ----- inner class: FrontMapListener ---------------------------------- 00563 00564 protected: 00565 /** 00566 * MapListener for back map responsible for keeping the front map 00567 * coherent with the back map. This listener is registered as a 00568 * synchronous listener for lite events (carrying only a key). 00569 */ 00570 class FrontMapListener 00571 : public class_spec<FrontMapListener, 00572 extends<AbstractMapListener>, 00573 implements<MapListenerSupport::SynchronousListener> > 00574 { 00575 friend class factory<FrontMapListener>; 00576 00577 // ----- constructors --------------------------------------- 00578 00579 protected: 00580 /** 00581 * Construct a FrontMapListener 00582 * 00583 * @param hMap the map associated with this listener 00584 */ 00585 FrontMapListener(CachingMap::Handle hMap); 00586 00587 // ----- MapListener interface ------------------------------ 00588 00589 public: 00590 /** 00591 * {@inheritDoc} 00592 */ 00593 virtual void entryDeleted(MapEvent::View vEvent); 00594 00595 // ---- helper registration methods ------------------------- 00596 00597 public: 00598 /** 00599 * Register this listener with the "front" map. 00600 */ 00601 virtual void registerWithMap(); 00602 00603 /** 00604 * Unregister this listener with the "front" map. 00605 */ 00606 virtual void unregisterFromMap(); 00607 00608 // ---- data members ---------------------------------------- 00609 00610 protected: 00611 /** 00612 * The filter associated with this listener. 00613 */ 00614 FinalView<Filter> f_vFilter; 00615 00616 /** 00617 * The map associated with this listener. 00618 */ 00619 WeakHandle<CachingMap> m_whMap; 00620 }; 00621 00622 00623 // ----- listener support ----------------------------------------------- 00624 00625 protected: 00626 /** 00627 * Factory pattern: instantiate back map listener. 00628 * 00629 * @return an instance of back map listener responsible for keeping 00630 * the front map coherent with the back map 00631 */ 00632 virtual MapListener::Handle instantiateBackMapListener(); 00633 00634 /** 00635 * Factory pattern: instantiate front map listener. 00636 * 00637 * @return an instance of front map listener 00638 */ 00639 virtual FrontMapListener::Handle instantiateFrontMapListener(); 00640 00641 /** 00642 * Validate the front map entry for the specified back map event. 00643 * 00644 * @param vEvent the MapEvent from the back map 00645 */ 00646 virtual void validate(MapEvent::View vEvent); 00647 00648 00649 // ----- constants and data fields ------------------------------------- 00650 00651 protected : 00652 /** 00653 * The "back" map, considered to be "complete" yet "expensive" to 00654 * access. 00655 */ 00656 mutable FinalHandle<CacheMap> f_hMapBack; 00657 00658 /** 00659 * The "front" map, considered to be "incomplete" yet "inexpensive" to 00660 * access. 00661 */ 00662 mutable FinalHandle<CacheMap> f_hMapFront; 00663 00664 /** 00665 * The invalidation strategy that this map is to use. 00666 */ 00667 mutable InvalidationStrategy m_strategyTarget; 00668 00669 /** 00670 * The current invalidation strategy, which at times could be different 00671 * from the target strategy. 00672 */ 00673 mutable InvalidationStrategy m_strategyCurrent; 00674 00675 /** 00676 * An optional listener for the "back" map. 00677 */ 00678 mutable MemberHandle<MapListener> m_hListener; 00679 00680 /** 00681 * An optional listener for the "front" map. 00682 */ 00683 mutable FinalHandle<FrontMapListener> f_hListenerFront; 00684 00685 /** 00686 * A filter that selects events for the back-map listener. 00687 */ 00688 mutable MemberHandle<Filter> m_hFilterListener; 00689 00690 /** 00691 * The ConcurrentMap to keep track of front map updates. 00692 * Values are list of events received by the listener while the 00693 * corresponding key was locked. Use of LOCK_ALL is restricited to 00694 * non-blocking operations to prevent deadlock with the service thread. 00695 */ 00696 mutable FinalHandle<ConcurrentMap> f_hMapControl; 00697 00698 /** 00699 * The CacheStatistics object maintained by this cache. 00700 */ 00701 mutable FinalHandle<SimpleCacheStatistics> f_hStats; 00702 00703 /** 00704 * The rough (ie unsynchronized) number of times the front map entries 00705 * that were present in the front map were invalidated by the listener. 00706 */ 00707 mutable /*volatile stat*/ int64_t m_cInvalidationHits; 00708 00709 /** 00710 * The rough (ie unsynchronized) number of times the front map entries 00711 * that were absent in the front map received invalidation event. 00712 */ 00713 mutable /*volatile stat*/ int64_t m_cInvalidationMisses; 00714 00715 /** 00716 * The total number of registerListener(oKey) operations. 00717 */ 00718 mutable /*volatile stat*/ int64_t m_cRegisterListener; 00719 00720 /** 00721 * True if the cache has been released. 00722 */ 00723 bool m_fReleased; 00724 00725 // ----- constants ------------------------------------------------------ 00726 00727 protected : 00728 /** 00729 * A unique Object that serves as a control key for global operations 00730 * such as clear and release and synchronization point for the current 00731 * strategy change. 00732 */ 00733 FinalView<Object> f_vKeyGlobal; 00734 }; 00735 00736 COH_CLOSE_NAMESPACE3 00737 00738 #endif // COH_CACHING_MAP_HPP