View Javadoc

1   package com.atlassian.cache.memory;
2   
3   import java.util.SortedMap;
4   
5   import javax.annotation.Nonnull;
6   import javax.annotation.Nullable;
7   
8   import com.atlassian.cache.CacheException;
9   import com.atlassian.cache.CacheSettings;
10  import com.atlassian.cache.CacheStatisticsKey;
11  import com.atlassian.cache.CachedReference;
12  import com.atlassian.cache.CachedReferenceListener;
13  import com.atlassian.cache.impl.CachedReferenceListenerSupport;
14  import com.atlassian.cache.impl.DefaultCachedReferenceListenerSupport;
15  import com.atlassian.cache.impl.ReferenceKey;
16  import com.atlassian.util.concurrent.Supplier;
17  
18  import com.google.common.cache.LoadingCache;
19  import com.google.common.cache.RemovalListener;
20  import com.google.common.cache.RemovalNotification;
21  import com.google.common.util.concurrent.UncheckedExecutionException;
22  
23  import static com.atlassian.cache.memory.DelegatingCacheStatistics.toStatistics;
24  
25  /**
26   * A Lazy Reference that delegates Concurrent Map.
27   *
28   * @since 2.0
29   */
30  class DelegatingCachedReference<V> extends ManagedCacheSupport implements CachedReference<V>
31  {
32      private final LoadingCache<ReferenceKey, V> internalCache;
33      private final CachedReferenceListenerSupport<V> listenerSupport;
34  
35      private DelegatingCachedReference(final LoadingCache<ReferenceKey, V> internalCache,
36              String name, CacheSettings settings)
37      {
38          super(name, settings);
39          this.internalCache = internalCache;
40  
41          this.listenerSupport = new DefaultCachedReferenceListenerSupport<V>();
42      }
43  
44      static <V> DelegatingCachedReference<V> create(final LoadingCache<ReferenceKey, V> internalCache,
45              String name, CacheSettings settings)
46      {
47          return new DelegatingCachedReference<V>(internalCache, name, settings);
48      }
49  
50      @Nonnull
51      @Override
52      public V get()
53      {
54          try
55          {
56              return internalCache.get(ReferenceKey.KEY);
57          }
58          catch (UncheckedExecutionException e)
59          {
60              throw new CacheException(e.getCause());
61          }
62          catch (Exception e)
63          {
64              throw new CacheException(e);
65          }
66      }
67  
68      @Override
69      public void reset()
70      {
71          try
72          {
73              internalCache.invalidate(ReferenceKey.KEY);
74          }
75          catch (Exception e)
76          {
77              throw new CacheException(e);
78          }
79      }
80  
81      @Override
82      public void clear()
83      {
84          reset();
85      }
86  
87      @Override
88      public boolean equals(@Nullable final Object other)
89      {
90          if (other instanceof DelegatingCachedReference)
91          {
92              DelegatingCachedReference<?> otherDelegatingReference = (DelegatingCachedReference<?>) other;
93              if (internalCache.equals(otherDelegatingReference.internalCache))
94              {
95                  return true;
96              }
97          }
98          return false;
99      }
100 
101     @Override
102     public int hashCode()
103     {
104         return 3 + internalCache.hashCode();
105     }
106 
107     @Nonnull
108     @Override
109     public SortedMap<CacheStatisticsKey,Supplier<Long>> getStatistics()
110     {
111         return toStatistics(internalCache);
112     }
113 
114     @Override
115     public void addListener(@Nonnull CachedReferenceListener<V> listener, boolean includeValues)
116     {
117         listenerSupport.add(listener, includeValues);
118     }
119 
120     @Override
121     public void removeListener(@Nonnull CachedReferenceListener<V> listener)
122     {
123         listenerSupport.remove(listener);
124     }
125 
126     protected static class DelegatingReferenceRemovalListener<V> implements RemovalListener<ReferenceKey, V>
127     {
128         private DelegatingCachedReference<V> cachedReference;
129 
130         protected void onSupply(V value)
131         {
132             cachedReference.listenerSupport.notifySet(value);
133         }
134 
135         @Override
136         public void onRemoval(RemovalNotification<ReferenceKey, V> notification)
137         {
138             switch (notification.getCause())
139             {
140                 case COLLECTED:
141                 case EXPIRED:
142                     cachedReference.listenerSupport.notifyEvict(notification.getValue());
143                     break;
144                 case EXPLICIT:
145                     cachedReference.listenerSupport.notifyReset(notification.getValue());
146                     break;
147                 case REPLACED:
148                     V value = cachedReference.internalCache.getIfPresent(ReferenceKey.KEY);
149                     cachedReference.listenerSupport.notifySet(value);
150                     break;
151             }
152         }
153 
154         public void setCachedReference(DelegatingCachedReference<V> cachedReference)
155         {
156             this.cachedReference = cachedReference;
157         }
158     }
159 }