00001 /* 00002 * Copyright (c) 2000, 2022, Oracle and/or its affiliates. 00003 * 00004 * Licensed under the Universal Permissive License v 1.0 as shown at 00005 * http://oss.oracle.com/licenses/upl. 00006 */ 00007 #ifndef COH_LOCAL_CACHE_HPP 00008 #define COH_LOCAL_CACHE_HPP 00009 00010 #include "coherence/lang.ns" 00011 00012 #include "coherence/net/cache/CacheLoader.hpp" 00013 #include "coherence/net/cache/CacheMap.hpp" 00014 #include "coherence/net/cache/CacheStore.hpp" 00015 #include "coherence/net/cache/OldCache.hpp" 00016 00017 #include "coherence/util/MapListener.hpp" 00018 00019 COH_OPEN_NAMESPACE3(coherence,net,cache) 00020 00021 using coherence::util::MapListener; 00022 00023 00024 /** 00025 * A LocalCache implementation that supports CacheLoader and CacheStore 00026 * objects. 00027 * 00028 * @author nsa 2008.08.01 00029 */ 00030 class COH_EXPORT LocalCache 00031 : public class_spec<LocalCache, 00032 extends<OldCache>, 00033 implements<CacheMap> > 00034 { 00035 friend class factory<LocalCache>; 00036 00037 // ----- handle definitions (needed for nested classes) ----------------- 00038 00039 public: 00040 typedef this_spec::Handle Handle; 00041 typedef this_spec::View View; 00042 typedef this_spec::Holder Holder; 00043 00044 00045 // ----- constants ------------------------------------------------------ 00046 public: 00047 /** 00048 * Max number of units this cache can hold 00049 */ 00050 static const size32_t max_units = 0x7FFFFFFF; 00051 00052 /** 00053 * By default, the cache size (in units) is infinite. 00054 */ 00055 static const size32_t default_units = max_units; 00056 00057 /** 00058 * Never expire entries from the cache 00059 */ 00060 static const int32_t never_expire = 0; 00061 00062 /** 00063 * By default, the cache entries never expire. 00064 */ 00065 static const int32_t default_expire = never_expire; 00066 00067 00068 // ----- constructors --------------------------------------------------- 00069 00070 protected: 00071 /** 00072 * Construct an instance of LocalCache 00073 * 00074 * @param cUnits the number of units that the cache manager 00075 * will cache before pruning the cache 00076 * @param cExpiryMillis the number of milliseconds that each cache 00077 * entry lives before being automatically 00078 * expired 00079 * @param dflPruneLevel the percentage of the total number of units 00080 * that will remain after the cache manager 00081 * prunes the cache (i.e. this is the 00082 * "low water mark" value); this value is in 00083 * the range 0.0 to 1.0 00084 * @param cInitialBuckets the initial number of hash buckets, 00085 * 0 < n 00086 * @param flLoadFactor the acceptable load factor before resizing 00087 * occurs, 0 < n, such that a load factor 00088 * of 1.0 causes resizing when the number of 00089 * entries exceeds the number of buckets 00090 * @param flGrowthRate the rate of bucket growth when a resize 00091 * occurs, 0 < n, such that a growth rate 00092 * of 1.0 will double the number of buckets: 00093 * bucketcount = bucketcount * (1 + growthrate) 00094 */ 00095 LocalCache(int32_t cUnits = default_units, 00096 int32_t cExpiryMillis = default_expire, 00097 float64_t dflPruneLevel = 0.75F, 00098 size32_t cInitialBuckets = 17, 00099 float32_t flLoadFactory = 1.0F, 00100 float32_t flGrowthRate = 3.0F); 00101 00102 00103 // ----- inner class: InternalListener ---------------------------------- 00104 00105 protected: 00106 /** 00107 * Factory pattern: Instantiate an internal MapListener to listen to 00108 * this cache and report changes to the CacheStore. 00109 * 00110 * @return a new MapListener instance 00111 */ 00112 MapListener::Handle instantiateInternalListener(); 00113 00114 /** 00115 * An internal MapListener that listens to this cache and reports 00116 * changes to the CacheStore. 00117 */ 00118 class InternalListener 00119 : public class_spec<InternalListener, 00120 extends<Object>, 00121 implements<MapListener> > 00122 { 00123 friend class factory<InternalListener>; 00124 00125 // ----- constructors --------------------------------------- 00126 00127 protected: 00128 /** 00129 * Construct a new InternalListener 00130 */ 00131 InternalListener(LocalCache::Handle hCache); 00132 00133 // ----- MapListener interface ------------------------------ 00134 00135 public: 00136 /** 00137 * Invoked when a map entry has been inserted. 00138 * 00139 * @param vEvt the MapEvent carrying the insert information 00140 */ 00141 virtual void entryInserted(MapEvent::View vEvt); 00142 00143 /** 00144 * Invoked when a map entry has been updated. 00145 * 00146 * @param vEvt the MapEvent carrying the update information 00147 */ 00148 virtual void entryUpdated(MapEvent::View vEvt); 00149 00150 /** 00151 * Invoked when a map entry has been removed. 00152 * 00153 * @param vEvt the MapEvent carrying the delete information 00154 */ 00155 virtual void entryDeleted(MapEvent::View vEvt); 00156 00157 // ----- helper methods ------------------------------------- 00158 00159 protected: 00160 /** 00161 * A value modification event (insert or update) has occurred. 00162 * 00163 * @param vEvt the MapEvent object 00164 */ 00165 virtual void onModify(MapEvent::View vEvt); 00166 00167 // ----- Data members --------------------------------------- 00168 00169 protected: 00170 /** 00171 * Reference back to the containing cache 00172 */ 00173 WeakHandle<LocalCache> m_hCache; 00174 }; 00175 00176 00177 // ----- inner class: KeyMask ------------------------------------------- 00178 00179 public: 00180 /** 00181 * A class that masks certain changes so that they are not reported back 00182 * to the CacheStore. 00183 */ 00184 class COH_EXPORT KeyMask 00185 : public class_spec<KeyMask> 00186 { 00187 friend class factory<KeyMask>; 00188 00189 // ----- constructors --------------------------------------- 00190 00191 protected: 00192 /** 00193 * Construct a new KeyMask instance 00194 */ 00195 KeyMask(); 00196 00197 // ----- KeyMask interface ---------------------------------- 00198 00199 public: 00200 /** 00201 * Check if a key should be ignored. 00202 * 00203 * @param vKey the key that a change event has occurred for 00204 * 00205 * @return true if change events for the key should be ignored 00206 */ 00207 virtual bool isIgnored(Object::View vKey); 00208 00209 /** 00210 * Check whether or not the currently performed operation is 00211 * internally initiated. 00212 * 00213 * @return true iff the the current operation is internal 00214 */ 00215 virtual bool isSynthetic(); 00216 00217 /** 00218 * Specify whether or not the currently performed operation is 00219 * internally initiated. 00220 * 00221 * @param fSynthetic true iff the the current operation is 00222 * internal 00223 */ 00224 virtual void setSynthetic(bool fSynthetic); 00225 00226 /** 00227 * Check whether or not the currently performed operation has been initiated 00228 * because the entry expired. 00229 * 00230 * @return true iff the entry has expired 00231 * @since 14.1.1.0.10 00232 */ 00233 virtual bool isExpired(); 00234 00235 /** 00236 * Specify whether or not the currently performed operation concerns an 00237 * expired entry 00238 * 00239 * @param fExpired true iff the current operation is an expiration one 00240 * @since 14.1.1.0.10 00241 */ 00242 virtual void setExpired(bool fExpired); 00243 00244 /** 00245 * Ensure that the synthetic operation flag is set. 00246 * 00247 * @return the previous value of the flag 00248 */ 00249 virtual bool ensureSynthetic(); 00250 00251 /** 00252 * Ensure that the expired operation flag is set. 00253 * 00254 * @return the previous value of the flag 00255 * @since 14.1.1.0.10 00256 */ 00257 virtual bool ensureExpired(); 00258 }; 00259 00260 00261 // ----- inner class: Entry --------------------------------------------- 00262 00263 protected: 00264 /** 00265 * {@inheritDoc} 00266 */ 00267 virtual SafeHashMap::Entry::Handle instantiateEntry(Object::View vKey, 00268 Object::Holder ohValue, size32_t nHash); 00269 00270 /** 00271 * {@inheritDoc} 00272 */ 00273 virtual SafeHashMap::Entry::Handle instantiateEntry( 00274 SafeHashMap::Entry::View vEntry); 00275 00276 public: 00277 /** 00278 * A holder for a cached value. 00279 */ 00280 class COH_EXPORT Entry 00281 : public cloneable_spec<Entry, 00282 extends<OldCache::Entry> > 00283 { 00284 friend class factory<Entry>; 00285 00286 // ----- constructors --------------------------------------- 00287 protected: 00288 /** 00289 * {@internal} 00290 */ 00291 Entry(Object::View vKey, Object::Holder ohValue, 00292 size32_t nHash, LocalCache::Handle hCache); 00293 00294 /** 00295 * {@internal} 00296 */ 00297 Entry(const Entry& that); 00298 00299 /** 00300 * {@internal} 00301 */ 00302 Entry(Entry::View vThat); 00303 }; 00304 00305 00306 // ----- Map interface -------------------------------------------------- 00307 00308 public: 00309 00310 /** 00311 * Removes the mapping for this key from this map if present. 00312 * 00313 * @param oKey key whose mapping is to be removed from the map 00314 * 00315 * @return previous value associated with specified key, or <tt>null</tt> 00316 * if there was no mapping for key. A <tt>null</tt> return can 00317 * also indicate that the map previously associated <tt>null</tt> 00318 * with the specified key, if the implementation supports 00319 * <tt>null</tt> values 00320 */ 00321 virtual Object::Holder remove(Object::View vKey); 00322 using Map::remove; 00323 00324 /** 00325 * Removes all mappings from this map. 00326 */ 00327 virtual void clear(); 00328 00329 00330 // ----- LocalCache interface ------------------------------------------- 00331 00332 public: 00333 /** 00334 * Determine the loader used by this LocalCache, if any. 00335 * 00336 * @return the loader used by this LocalCache, or null if none 00337 */ 00338 virtual CacheLoader::View getCacheLoader() const; 00339 00340 /** 00341 * Determine the loader used by this LocalCache, if any. 00342 * 00343 * @return the loader used by this LocalCache, or null if none 00344 */ 00345 virtual CacheLoader::Handle getCacheLoader(); 00346 00347 /** 00348 * Specify the loader used by this LocalCache. 00349 * 00350 * @param loader loader to use, or null 00351 */ 00352 virtual void setCacheLoader(CacheLoader::Handle hLoader); 00353 00354 /** 00355 * If the specified item is in the cache, return it. Otherwise, 00356 * load the value for the specified key and return it. 00357 * 00358 * @param vKey the key to the desired cached item 00359 * 00360 * @return the value corresponding to the specified key, otherwise null 00361 */ 00362 virtual Object::Holder get(Object::View vKey) const; 00363 using Map::get; 00364 00365 /** 00366 * Locate an Entry in the hash map based on its key. If the Entry is not in 00367 * the cache, load the Entry for the specified key and return it. 00368 * 00369 * @param oKey the key to the desired cached Entry 00370 * 00371 * @return the Entry corresponding to the specified key, otherwise null 00372 */ 00373 SafeHashMap::Entry::View getEntry(Object::View vKey) const; 00374 00375 /** 00376 * Locate an Entry in the hash map based on its key. If the Entry is not in 00377 * the cache, load the Entry for the specified key and return it. 00378 * 00379 * @param oKey the key to the desired cached Entry 00380 * 00381 * @return the Entry corresponding to the specified key, otherwise null 00382 */ 00383 SafeHashMap::Entry::Handle getEntry(Object::View vKey); 00384 00385 /** 00386 * Get all the specified keys, if they are in the cache. For each key 00387 * that is in the cache, that key and its corresponding value will be 00388 * placed in the map that is returned by this method. The absence of 00389 * a key in the returned map indicates that it was not in the cache, 00390 * which may imply (for caches that can load behind the scenes) that 00391 * the requested data could not be loaded. 00392 * 00393 * The result of this method is defined to be semantically the same as 00394 * the following implementation, without regards to threading issues: 00395 * 00396 * <pre><tt> 00397 * Map map = new AnyMap(); // could be hash map or ... 00398 * for (Iterator iter = col.iterator(); iter.hasNext(); ) 00399 * { 00400 * Object oKey = iter.next(); 00401 * Object oVal = get(oKey); 00402 * if (oVal != null || containsKey(oKey)) 00403 * { 00404 * map.put(oKey, oVal); 00405 * } 00406 * } 00407 * return map; 00408 * </tt></pre> 00409 * 00410 * @param colKeys a collection of keys that may be in the named cache 00411 * 00412 * @return a Map of keys to values for the specified keys passed in 00413 * <tt>col</tt> 00414 */ 00415 virtual Map::View getAll(Collection::View vColKeys) const; 00416 00417 /** 00418 * Indicates to the cache that the specified key should be loaded into the 00419 * cache, if it is not already in the cache. This provides a means to 00420 * "pre-load" a single entry into the cache using the cache's loader. 00421 * 00422 * If a valid entry with the specified key already exists in the cache, 00423 * or if the cache does not have a loader, then this method has no effect. 00424 * 00425 * An implementation may perform the load operation asynchronously. 00426 * 00427 * @param oKey the key to request to be loaded 00428 */ 00429 virtual void load(Object::View vKey) const; 00430 00431 /** 00432 * Indicates to the cache that the specified key should be loaded into the 00433 * cache, if it is not already in the cache. This provides a means to 00434 * "pre-load" a single entry into the cache using the cache's loader. 00435 * 00436 * If a valid entry with the specified key already exists in the cache, 00437 * or if the cache does not have a loader, then this method has no effect. 00438 * 00439 * An implementation may perform the load operation asynchronously. 00440 * 00441 * @param oKey the key to request to be loaded 00442 */ 00443 virtual void load(Object::View vKey); 00444 00445 /** 00446 * Indicates to the cache that it should load data from its loader to 00447 * fill the cache; this is sometimes referred to as "pre-loading" or 00448 * "warming" a cache. 00449 * 00450 * The specific set of data that will be loaded is unspecified. The 00451 * implementation may choose to load all data, some specific subset 00452 * of the data, or no data. An implementation may require that the 00453 * loader implement the IterableCacheLoader interface in order for 00454 * this method to load any data. 00455 * 00456 * An implementation may perform the load operation asynchronously. 00457 */ 00458 virtual void loadAll(); 00459 00460 /** 00461 * Indicates to the cache that the specified keys should be loaded into 00462 * the cache, if they are not already in the cache. This provides a means 00463 * to "pre-load" entries into the cache using the cache's loader. 00464 * 00465 * The result of this method is defined to be semantically the same as 00466 * the following implementation: 00467 * 00468 * <pre><tt> 00469 * CacheLoader loader = getCacheLoader(); 00470 * if (loader != null && !colKeys.isEmpty()) 00471 * { 00472 * Set setRequest = new HashSet(colKeys); 00473 * setRequest.removeAll(peekAll(colKeys).keySet()); 00474 * if (!setRequest.isEmpty()) 00475 * { 00476 * Map map = loader.loadAll(colKeys); 00477 * if (!map.isEmpty()) 00478 * { 00479 * putAll(map); 00480 * } 00481 * } 00482 * } 00483 * </tt></pre> 00484 * 00485 * @param colKeys a collection of keys to request to be loaded 00486 */ 00487 virtual void loadAll(Collection::View vColKeys); 00488 00489 /** 00490 * Indicates to the cache that the specified keys should be loaded into 00491 * the cache, if they are not already in the cache. This provides a means 00492 * to "pre-load" entries into the cache using the cache's loader. 00493 * 00494 * The result of this method is defined to be semantically the same as 00495 * the following implementation: 00496 * 00497 * <pre><tt> 00498 * CacheLoader loader = getCacheLoader(); 00499 * if (loader != null && !colKeys.isEmpty()) 00500 * { 00501 * Set setRequest = new HashSet(colKeys); 00502 * setRequest.removeAll(peekAll(colKeys).keySet()); 00503 * if (!setRequest.isEmpty()) 00504 * { 00505 * Map map = loader.loadAll(colKeys); 00506 * if (!map.isEmpty()) 00507 * { 00508 * putAll(map); 00509 * } 00510 * } 00511 * } 00512 * </tt></pre> 00513 * 00514 * @param colKeys a collection of keys to request to be loaded 00515 */ 00516 virtual void loadAll(Collection::View vColKeys) const; 00517 00518 /** 00519 * Checks for a valid entry corresponding to the specified key in the 00520 * cache, and returns the corresponding value if it is. If it is not in 00521 * the cache, returns null, and does not attempt to load the value using 00522 * its cache loader. 00523 * 00524 * @param oKey the key to "peek" into the cache for 00525 * 00526 * @return the value corresponding to the specified key 00527 */ 00528 virtual Object::Holder peek(Object::View vKey) const; 00529 00530 /** 00531 * Checks for a valid entry corresponding to each specified key in the 00532 * cache, and places the corresponding value in the returned map if it is. 00533 * For each key that is not in the cache, no entry is placed into the 00534 * returned map. The cache does not attempt to load any values using 00535 * its cache loader. 00536 * 00537 * The result of this method is defined to be semantically the same as 00538 * the following implementation, without regards to threading issues: 00539 * 00540 * <pre><tt> 00541 * Map::Handle hMap = HashMap::create(); 00542 * for (Iterator::Handle hIter = vColKeys->iterator(); hIter->hasNext(); ) 00543 * { 00544 * Object::View vKey = hIter->next(); 00545 * Object::Holder ohValue = peek(ohKey); 00546 * if (NULL != ohValue || containsKey(vKey)) 00547 * { 00548 * hMap->put(vKey, ohValue); 00549 * } 00550 * } 00551 * return hMap; 00552 * </tt></pre> 00553 * 00554 * @param vColKeys a collection of keys to "peek" into the cache for 00555 * 00556 * @return a Map of keys that were found in the cache and their values 00557 */ 00558 virtual Map::Handle peekAll(Collection::View vColKeys) const; 00559 00560 /** 00561 * Return the default KeyMask for a LocalCache 00562 * 00563 * @return the default KeyMask for a LocalCache 00564 */ 00565 static KeyMask::Handle getDefaultKeyMask(); 00566 00567 00568 // ----- internal ------------------------------------------------------- 00569 00570 protected: 00571 /** 00572 * Determine the store used by this LocalCache, if any. 00573 * 00574 * @return the CacheStore used by this LocalCache, or null if none 00575 */ 00576 virtual CacheStore::View getCacheStore() const; 00577 00578 /** 00579 * Determine the store used by this LocalCache, if any. 00580 * 00581 * @return the CacheStore used by this LocalCache, or null if none 00582 */ 00583 virtual CacheStore::Handle getCacheStore(); 00584 00585 /** 00586 * ThreadLocal: Get the current key mask for the current thread. 00587 * 00588 * @return the current key mask 00589 */ 00590 virtual KeyMask::View getKeyMask() const; 00591 00592 /** 00593 * ThreadLocal: Get the current key mask for the current thread. 00594 * 00595 * @return the current key mask 00596 */ 00597 virtual KeyMask::Handle getKeyMask(); 00598 00599 /** 00600 * ThreadLocal: Set the key mask for the current thread. 00601 * 00602 * @param mask the new key mask, or null to clear the mask 00603 */ 00604 virtual void setKeyMask(KeyMask::Handle hMask); 00605 00606 /** 00607 * Remove an entry because it has expired. 00608 * 00609 * @param hEntry the expired cache entry 00610 * @param fRemoveInternal true if the cache entry still needs to be 00611 * removed from the cache 00612 */ 00613 virtual void removeExpired(OldCache::Entry::Handle hEntry, 00614 bool fRemoveInternal); 00615 00616 /** 00617 * {@inheritDoc} 00618 */ 00619 using OldCache::removeExpired; 00620 00621 /** 00622 * Factory pattern: instantiate a new CacheEvent corresponding 00623 * to the specified parameters. 00624 * 00625 * @return a new instance of the CacheEvent class (or a subclass thereof) 00626 */ 00627 virtual MapEvent::Handle instantiateMapEvent(int32_t nId, 00628 Object::View vKey, Object::Holder ohValueOld, 00629 Object::Holder ohValueNew); 00630 00631 00632 // ----- data members --------------------------------------------------- 00633 00634 private: 00635 /** 00636 * The loader used by this cache for misses. 00637 */ 00638 MemberHandle<CacheLoader> m_hLoader; 00639 00640 /** 00641 * The store used by this cache for modifications. If this value is 00642 * non-null, then it is the same reference as the loader. 00643 */ 00644 MemberHandle<CacheStore> m_hStore; 00645 00646 /** 00647 * The map listener used by this cache to listen to itself in order to 00648 * pass events to the CacheStore. Only used when there is a CacheStore. 00649 */ 00650 MemberHandle<MapListener> m_hListener; 00651 00652 /** 00653 * The thread-local object to check for keys that the current thread 00654 * is supposed to ignore if those keys change. Contains KeyMask objects. 00655 */ 00656 FinalHandle<ThreadLocalReference> f_tloIgnore; 00657 }; 00658 00659 COH_CLOSE_NAMESPACE3 00660 00661 #endif // COH_LOCAL_CACHE_HPP