View Javadoc

1   package com.atlassian.cache.memory;
2   
3   import com.atlassian.cache.CacheLoader;
4   import com.atlassian.cache.CacheSettings;
5   import com.atlassian.cache.CacheSettingsBuilder;
6   import com.atlassian.cache.CachedReference;
7   import com.atlassian.cache.ManagedCache;
8   import com.atlassian.cache.impl.AbstractCacheManager;
9   import com.atlassian.cache.impl.ReferenceKey;
10  import com.atlassian.cache.impl.StrongSupplier;
11  import com.atlassian.cache.impl.WeakSupplier;
12  import com.atlassian.util.concurrent.Supplier;
13  import com.google.common.cache.Cache;
14  import com.google.common.cache.CacheBuilder;
15  import com.google.common.cache.LoadingCache;
16  
17  import static java.util.concurrent.TimeUnit.MILLISECONDS;
18  
19  /**
20   * Maintains a mapping of name -> Cache and provides factory methods for creating and getting caches.
21   *
22   * @since 2.0
23   */
24  public class MemoryCacheManager extends AbstractCacheManager
25  {
26      @SuppressWarnings("unchecked")
27      @Override
28      public <V> CachedReference<V> getCachedReference(final String name,
29                                                       final com.atlassian.cache.Supplier<V> supplier,
30                                                       final CacheSettings settings)
31      {
32          // Force the cache settings to be flushable and a maximum size of one.
33          final CacheSettings overridenSettings = settings.override(
34                  new CacheSettingsBuilder().flushable().maxEntries(1).build());
35  
36  
37          return cacheCreationLocks.get(name).withLock(new com.atlassian.util.concurrent.Supplier<DelegatingCachedReference<V>>()
38              {
39              @Override
40              public DelegatingCachedReference<V> get()
41              {
42                  LoadingCache<ReferenceKey, V> computingCache = createCacheBuilder(overridenSettings).build(
43                          new com.google.common.cache.CacheLoader<ReferenceKey, V>()
44                          {
45                              @Override
46                              public V load(final ReferenceKey key) throws Exception
47                              {
48                                  return supplier.get();
49                              }
50                          });
51                  DelegatingCachedReference cache = DelegatingCachedReference.create(computingCache, name, overridenSettings);
52                  caches.put(name, new WeakSupplier<ManagedCache>(cache));
53                  return cache;
54              }
55          });
56      }
57  
58      @SuppressWarnings("unchecked")
59      protected ManagedCache createSimpleCache(final String name, final CacheSettings settings)
60      {
61  
62          Supplier<ManagedCache> cacheSupplier = caches.get(name);
63          if (cacheSupplier != null)
64          {
65              ManagedCache cache = cacheSupplier.get();
66              if (cache != null)
67              {
68                  return cache;
69              }
70          }
71          return cacheCreationLocks.get(name).withLock(new com.atlassian.util.concurrent.Supplier<ManagedCache>()
72              {
73                  @Override
74                  public ManagedCache get()
75                  {
76                      if (!caches.containsKey(name))
77                      {
78                          final Cache<Object, Object> simpleCache = createCacheBuilder(settings).build();
79                          DelegatingCache cache = DelegatingCache.create(simpleCache, name, settings);
80                          caches.put(name, new StrongSupplier<ManagedCache>(cache));
81                      }
82                      return caches.get(name).get();
83                  }
84              });
85      }
86  
87      @SuppressWarnings("unchecked")
88      protected <K, V> ManagedCache createComputingCache(final String name, final CacheSettings settings, final CacheLoader<K, V> loader)
89      {
90          return cacheCreationLocks.get(name).withLock(new com.atlassian.util.concurrent.Supplier<DelegatingCache<K, V>>()
91          {
92              @Override
93              public DelegatingCache<K, V> get()
94              {
95                  LoadingCache<K, V> computingCache = createCacheBuilder(settings)
96                          .build(new com.google.common.cache.CacheLoader<K, V>()
97                          {
98                              @Override
99                              public V load(final K key) throws Exception
100                             {
101                                 return loader.load(key);
102                             }
103                         });
104                 DelegatingCache cache = DelegatingCache.create(computingCache, name, settings);
105                 if (!caches.containsKey(name))
106                 {
107                     caches.put(name, new WeakSupplier<ManagedCache>(cache));
108                 }
109                 return cache;
110             }
111         });
112     }
113 
114     private CacheBuilder createCacheBuilder(CacheSettings settings)
115     {
116         final CacheBuilder cacheBuilder = CacheBuilder.newBuilder();
117         if (null != settings.getMaxEntries())
118         {
119             cacheBuilder.maximumSize(settings.getMaxEntries());
120         }
121 
122         if (null != settings.getExpireAfterAccess())
123         {
124             cacheBuilder.expireAfterAccess(settings.getExpireAfterAccess(), MILLISECONDS);
125         }
126         else if (null != settings.getExpireAfterWrite())
127         {
128             cacheBuilder.expireAfterWrite(settings.getExpireAfterWrite(), MILLISECONDS);
129         }
130         return cacheBuilder;
131     }
132 }