00001 /* 00002 * LocalCache.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_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 00306 /** 00307 * Removes all mappings from this map. 00308 */ 00309 virtual void clear(); 00310 00311 00312 // ----- LocalCache interface ------------------------------------------- 00313 00314 public: 00315 /** 00316 * Determine the loader used by this LocalCache, if any. 00317 * 00318 * @return the loader used by this LocalCache, or null if none 00319 */ 00320 virtual CacheLoader::View getCacheLoader() const; 00321 00322 /** 00323 * Determine the loader used by this LocalCache, if any. 00324 * 00325 * @return the loader used by this LocalCache, or null if none 00326 */ 00327 virtual CacheLoader::Handle getCacheLoader(); 00328 00329 /** 00330 * Specify the loader used by this LocalCache. 00331 * 00332 * @param loader loader to use, or null 00333 */ 00334 virtual void setCacheLoader(CacheLoader::Handle hLoader); 00335 00336 /** 00337 * If the specified item is in the cache, return it. Otherwise, 00338 * load the value for the specified key and return it. 00339 * 00340 * @param vKey the key to the desired cached item 00341 * 00342 * @return the value corresponding to the specified key, otherwise null 00343 */ 00344 virtual Object::Holder get(Object::View vKey) const; 00345 00346 /** 00347 * {@inheritDoc} 00348 */ 00349 using Map::get; 00350 00351 /** 00352 * Locate an Entry in the hash map based on its key. If the Entry is not in 00353 * the cache, load the Entry for the specified key and return it. 00354 * 00355 * @param oKey the key to the desired cached Entry 00356 * 00357 * @return the Entry corresponding to the specified key, otherwise null 00358 */ 00359 SafeHashMap::Entry::View getEntry(Object::View vKey) const; 00360 00361 /** 00362 * Locate an Entry in the hash map based on its key. If the Entry is not in 00363 * the cache, load the Entry for the specified key and return it. 00364 * 00365 * @param oKey the key to the desired cached Entry 00366 * 00367 * @return the Entry corresponding to the specified key, otherwise null 00368 */ 00369 SafeHashMap::Entry::Handle getEntry(Object::View vKey); 00370 00371 /** 00372 * Get all the specified keys, if they are in the cache. For each key 00373 * that is in the cache, that key and its corresponding value will be 00374 * placed in the map that is returned by this method. The absence of 00375 * a key in the returned map indicates that it was not in the cache, 00376 * which may imply (for caches that can load behind the scenes) that 00377 * the requested data could not be loaded. 00378 * 00379 * The result of this method is defined to be semantically the same as 00380 * the following implementation, without regards to threading issues: 00381 * 00382 * <pre><tt> 00383 * Map map = new AnyMap(); // could be hash map or ... 00384 * for (Iterator iter = col.iterator(); iter.hasNext(); ) 00385 * { 00386 * Object oKey = iter.next(); 00387 * Object oVal = get(oKey); 00388 * if (oVal != null || containsKey(oKey)) 00389 * { 00390 * map.put(oKey, oVal); 00391 * } 00392 * } 00393 * return map; 00394 * </tt></pre> 00395 * 00396 * @param colKeys a collection of keys that may be in the named cache 00397 * 00398 * @return a Map of keys to values for the specified keys passed in 00399 * <tt>col</tt> 00400 */ 00401 virtual Map::View getAll(Collection::View vColKeys) const; 00402 00403 /** 00404 * Indicates to the cache that the specified key should be loaded into the 00405 * cache, if it is not already in the cache. This provides a means to 00406 * "pre-load" a single entry into the cache using the cache's loader. 00407 * 00408 * If a valid entry with the specified key already exists in the cache, 00409 * or if the cache does not have a loader, then this method has no effect. 00410 * 00411 * An implementation may perform the load operation asynchronously. 00412 * 00413 * @param oKey the key to request to be loaded 00414 */ 00415 virtual void load(Object::View vKey) 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); 00430 00431 /** 00432 * Indicates to the cache that it should load data from its loader to 00433 * fill the cache; this is sometimes referred to as "pre-loading" or 00434 * "warming" a cache. 00435 * 00436 * The specific set of data that will be loaded is unspecified. The 00437 * implementation may choose to load all data, some specific subset 00438 * of the data, or no data. An implementation may require that the 00439 * loader implement the IterableCacheLoader interface in order for 00440 * this method to load any data. 00441 * 00442 * An implementation may perform the load operation asynchronously. 00443 */ 00444 virtual void loadAll(); 00445 00446 /** 00447 * Indicates to the cache that the specified keys should be loaded into 00448 * the cache, if they are not already in the cache. This provides a means 00449 * to "pre-load" entries into the cache using the cache's loader. 00450 * 00451 * The result of this method is defined to be semantically the same as 00452 * the following implementation: 00453 * 00454 * <pre><tt> 00455 * CacheLoader loader = getCacheLoader(); 00456 * if (loader != null && !colKeys.isEmpty()) 00457 * { 00458 * Set setRequest = new HashSet(colKeys); 00459 * setRequest.removeAll(peekAll(colKeys).keySet()); 00460 * if (!setRequest.isEmpty()) 00461 * { 00462 * Map map = loader.loadAll(colKeys); 00463 * if (!map.isEmpty()) 00464 * { 00465 * putAll(map); 00466 * } 00467 * } 00468 * } 00469 * </tt></pre> 00470 * 00471 * @param colKeys a collection of keys to request to be loaded 00472 */ 00473 virtual void loadAll(Collection::View vColKeys); 00474 00475 /** 00476 * Indicates to the cache that the specified keys should be loaded into 00477 * the cache, if they are not already in the cache. This provides a means 00478 * to "pre-load" entries into the cache using the cache's loader. 00479 * 00480 * The result of this method is defined to be semantically the same as 00481 * the following implementation: 00482 * 00483 * <pre><tt> 00484 * CacheLoader loader = getCacheLoader(); 00485 * if (loader != null && !colKeys.isEmpty()) 00486 * { 00487 * Set setRequest = new HashSet(colKeys); 00488 * setRequest.removeAll(peekAll(colKeys).keySet()); 00489 * if (!setRequest.isEmpty()) 00490 * { 00491 * Map map = loader.loadAll(colKeys); 00492 * if (!map.isEmpty()) 00493 * { 00494 * putAll(map); 00495 * } 00496 * } 00497 * } 00498 * </tt></pre> 00499 * 00500 * @param colKeys a collection of keys to request to be loaded 00501 */ 00502 virtual void loadAll(Collection::View vColKeys) const; 00503 00504 /** 00505 * Checks for a valid entry corresponding to the specified key in the 00506 * cache, and returns the corresponding value if it is. If it is not in 00507 * the cache, returns null, and does not attempt to load the value using 00508 * its cache loader. 00509 * 00510 * @param oKey the key to "peek" into the cache for 00511 * 00512 * @return the value corresponding to the specified key 00513 */ 00514 virtual Object::Holder peek(Object::View vKey) const; 00515 00516 /** 00517 * Checks for a valid entry corresponding to each specified key in the 00518 * cache, and places the corresponding value in the returned map if it is. 00519 * For each key that is not in the cache, no entry is placed into the 00520 * returned map. The cache does not attempt to load any values using 00521 * its cache loader. 00522 * 00523 * The result of this method is defined to be semantically the same as 00524 * the following implementation, without regards to threading issues: 00525 * 00526 * <pre><tt> 00527 * Map::Handle hMap = HashMap::create(); 00528 * for (Iterator::Handle hIter = vColKeys->iterator(); hIter->hasNext(); ) 00529 * { 00530 * Object::View vKey = hIter->next(); 00531 * Object::Holder ohValue = peek(ohKey); 00532 * if (NULL != ohValue || containsKey(vKey)) 00533 * { 00534 * hMap->put(vKey, ohValue); 00535 * } 00536 * } 00537 * return hMap; 00538 * </tt></pre> 00539 * 00540 * @param vColKeys a collection of keys to "peek" into the cache for 00541 * 00542 * @return a Map of keys that were found in the cache and their values 00543 */ 00544 virtual Map::Handle peekAll(Collection::View vColKeys) const; 00545 00546 /** 00547 * Return the default KeyMask for a LocalCache 00548 * 00549 * @return the default KeyMask for a LocalCache 00550 */ 00551 static KeyMask::Handle getDefaultKeyMask(); 00552 00553 00554 // ----- internal ------------------------------------------------------- 00555 00556 protected: 00557 /** 00558 * Determine the store used by this LocalCache, if any. 00559 * 00560 * @return the CacheStore used by this LocalCache, or null if none 00561 */ 00562 virtual CacheStore::View getCacheStore() const; 00563 00564 /** 00565 * Determine the store used by this LocalCache, if any. 00566 * 00567 * @return the CacheStore used by this LocalCache, or null if none 00568 */ 00569 virtual CacheStore::Handle getCacheStore(); 00570 00571 /** 00572 * ThreadLocal: Get the current key mask for the current thread. 00573 * 00574 * @return the current key mask 00575 */ 00576 virtual KeyMask::View getKeyMask() const; 00577 00578 /** 00579 * ThreadLocal: Get the current key mask for the current thread. 00580 * 00581 * @return the current key mask 00582 */ 00583 virtual KeyMask::Handle getKeyMask(); 00584 00585 /** 00586 * ThreadLocal: Set the key mask for the current thread. 00587 * 00588 * @param mask the new key mask, or null to clear the mask 00589 */ 00590 virtual void setKeyMask(KeyMask::Handle hMask); 00591 00592 /** 00593 * Remove an entry because it has expired. 00594 * 00595 * @param hEntry the expired cache entry 00596 * @param fRemoveInternal true if the cache entry still needs to be 00597 * removed from the cache 00598 */ 00599 virtual void removeExpired(OldCache::Entry::Handle hEntry, 00600 bool fRemoveInternal); 00601 00602 /** 00603 * {@inheritDoc} 00604 */ 00605 using OldCache::removeExpired; 00606 00607 /** 00608 * Factory pattern: instantiate a new CacheEvent corresponding 00609 * to the specified parameters. 00610 * 00611 * @return a new instance of the CacheEvent class (or a subclass thereof) 00612 */ 00613 virtual MapEvent::Handle instantiateMapEvent(int32_t nId, 00614 Object::View vKey, Object::Holder ohValueOld, 00615 Object::Holder ohValueNew); 00616 00617 00618 // ----- data members --------------------------------------------------- 00619 00620 private: 00621 /** 00622 * The loader used by this cache for misses. 00623 */ 00624 MemberHandle<CacheLoader> m_hLoader; 00625 00626 /** 00627 * The store used by this cache for modifications. If this value is 00628 * non-null, then it is the same reference as the loader. 00629 */ 00630 MemberHandle<CacheStore> m_hStore; 00631 00632 /** 00633 * The map listener used by this cache to listen to itself in order to 00634 * pass events to the CacheStore. Only used when there is a CacheStore. 00635 */ 00636 MemberHandle<MapListener> m_hListener; 00637 00638 /** 00639 * The thread-local object to check for keys that the current thread 00640 * is supposed to ignore if those keys change. Contains KeyMask objects. 00641 */ 00642 FinalHandle<ThreadLocalReference> f_tloIgnore; 00643 }; 00644 00645 COH_CLOSE_NAMESPACE3 00646 00647 #endif // COH_LOCAL_CACHE_HPP