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