View Javadoc

1   package com.atlassian.cache.ehcache;
2   
3   import javax.annotation.Nonnull;
4   import javax.annotation.Nullable;
5   import javax.annotation.ParametersAreNonnullByDefault;
6   import javax.management.MBeanServer;
7   
8   import com.atlassian.cache.CacheLoader;
9   import com.atlassian.cache.CacheSettings;
10  import com.atlassian.cache.CacheSettingsBuilder;
11  import com.atlassian.cache.CacheSettingsDefaultsProvider;
12  import com.atlassian.cache.CachedReference;
13  import com.atlassian.cache.ManagedCache;
14  import com.atlassian.cache.ehcache.replication.EhCacheReplicatorConfigFactory;
15  import com.atlassian.cache.ehcache.replication.rmi.RMICacheReplicatorConfigFactory;
16  import com.atlassian.cache.impl.AbstractCacheManager;
17  import com.atlassian.cache.impl.ReferenceKey;
18  import com.atlassian.cache.impl.StrongSupplier;
19  import com.atlassian.cache.impl.WeakSupplier;
20  import com.atlassian.cache.impl.jmx.MBeanRegistrar;
21  import com.atlassian.util.concurrent.Supplier;
22  
23  import net.sf.ehcache.Ehcache;
24  import net.sf.ehcache.management.ManagementService;
25  
26  /**
27   * Maintains a mapping of name -> Cache and provides factory methods for creating ad getting caches.
28   *
29   * @since 2.0
30   */
31  @ParametersAreNonnullByDefault
32  public class EhCacheManager extends AbstractCacheManager implements MBeanRegistrar
33  {
34      private final net.sf.ehcache.CacheManager delegate;
35      private final @Nullable
36      EhCacheReplicatorConfigFactory replicatorConfigFactory;
37  
38      private boolean statisticsEnabled = true;
39  
40      /**
41       * Creates an instance backed by a new instance of {@link net.sf.ehcache.CacheManager} and a {@link com.atlassian.cache.ehcache.replication.rmi.RMICacheReplicatorConfigFactory}.
42       *
43       * @deprecated Since 5.6.9 Use {@link #EhCacheManager(net.sf.ehcache.CacheManager, EhCacheReplicatorConfigFactory, com.atlassian.cache.CacheSettingsDefaultsProvider)}
44       */
45      @Deprecated
46      public EhCacheManager()
47      {
48          this(net.sf.ehcache.CacheManager.create(), null);
49      }
50  
51      /**
52       * Creates an instance backed by the provided instance of {@link net.sf.ehcache.CacheManager} and a {@link com.atlassian.cache.ehcache.replication.rmi.RMICacheReplicatorConfigFactory}.
53       *
54       * @param delegate an Ehcache's cache manager
55       *
56       * @deprecated since 2.6.0 Use {@link com.atlassian.cache.ehcache.EhCacheManager#EhCacheManager(net.sf.ehcache.CacheManager, EhCacheReplicatorConfigFactory, com.atlassian.cache.CacheSettingsDefaultsProvider)}
57       */
58      @Deprecated
59      public EhCacheManager(net.sf.ehcache.CacheManager delegate, @Nullable CacheSettingsDefaultsProvider cacheSettingsDefaultsProvider)
60      {
61          this(delegate, new RMICacheReplicatorConfigFactory(), cacheSettingsDefaultsProvider);
62      }
63  
64      /**
65       * Creates an instance backed by the provided instance of {@link net.sf.ehcache.CacheManager}.
66       *
67       * @param delegate an Ehcache's cache manager
68       */
69      public EhCacheManager(net.sf.ehcache.CacheManager delegate, @Nullable EhCacheReplicatorConfigFactory replicatorConfigFactory, @Nullable CacheSettingsDefaultsProvider cacheSettingsDefaultsProvider)
70      {
71          super(cacheSettingsDefaultsProvider);
72          this.delegate = delegate;
73          this.replicatorConfigFactory = replicatorConfigFactory;
74      }
75  
76      net.sf.ehcache.CacheManager getEh()
77      {
78          return delegate;
79      }
80  
81      public boolean isStatisticsEnabled()
82      {
83          return statisticsEnabled;
84      }
85  
86      public void setStatisticsEnabled(final boolean statisticsEnabled)
87      {
88          this.statisticsEnabled = statisticsEnabled;
89      }
90  
91      @Nonnull
92      @SuppressWarnings("unchecked")
93      @Override
94      public <V> CachedReference<V> getCachedReference(@Nonnull final String name,
95                                                       @Nonnull final com.atlassian.cache.Supplier<V> supplier,
96                                                       @Nonnull final CacheSettings settings)
97      {
98          // Force the cache settings to be flushable and a maximum size of one.
99          final CacheSettings overridenSettings = settings.override(
100                 new CacheSettingsBuilder().flushable().maxEntries(1).build());
101 
102         return cacheCreationLocks.get(name).withLock(new com.atlassian.util.concurrent.Supplier<DelegatingCachedReference<V>>()
103             {
104                 @Override
105                 public DelegatingCachedReference<V> get()
106                 {
107                     Ehcache ehCache = getCleanCache(name, overridenSettings);
108                     final Ehcache spCache = new LoadingCache<ReferenceKey,V>(ehCache, new SupplierAdapter<V>(supplier));
109                     final DelegatingCachedReference<V> cache = DelegatingCachedReference.create(spCache, overridenSettings);
110                     caches.put(name, new WeakSupplier<ManagedCache>(cache));
111                     return cache;
112                 }
113             });
114     }
115 
116     @Override
117     protected ManagedCache createSimpleCache(@Nonnull final String name, @Nonnull final CacheSettings settings)
118     {
119         final Supplier<ManagedCache> cacheSupplier = caches.get(name);
120         if (cacheSupplier != null)
121         {
122             ManagedCache cache = cacheSupplier.get();
123             if (cache != null)
124             {
125                 return cache;
126             }
127         }
128         return cacheCreationLocks.get(name).withLock(new com.atlassian.util.concurrent.Supplier<ManagedCache>()
129             {
130                 @Override
131                 public ManagedCache get()
132                 {
133                     if (!caches.containsKey(name))
134                     {
135                         final Ehcache simpleCache = createCache(name, settings, false);
136                         DelegatingCache<?,?> cache = DelegatingCache.create(simpleCache, settings);
137                         caches.put(name,  new StrongSupplier<ManagedCache>(cache));
138                     }
139                     return caches.get(name).get();
140                 }
141             });
142 
143     }
144 
145     @SuppressWarnings("unchecked")
146     protected <K, V> ManagedCache createComputingCache(@Nonnull final String name, @Nonnull final CacheSettings settings, final CacheLoader<K, V> loader)
147     {
148         return cacheCreationLocks.get(name).withLock(new com.atlassian.util.concurrent.Supplier<ManagedCache>()
149         {
150             @Override
151             public ManagedCache get()
152             {
153                 Ehcache ehCache = getCleanCache(name, settings);
154                 Ehcache spCache = new LoadingCache(ehCache, loader);
155                 DelegatingCache<K,V> cache = DelegatingCache.create(spCache, settings);
156                 caches.put(name,  new WeakSupplier<ManagedCache>(cache));
157                 return cache;
158             }
159         });
160     }
161 
162     private Ehcache getCleanCache(final String name, final CacheSettings settings)
163     {
164         // Particularly for plugins that are reloaded the cache may already exist from earlier times.
165         // Because actually removing the old cache and recreating it breaks RMI replication we get the old one,
166         // but to avoid any class loading issues with the old plugin class loader which would be unavailable
167         // we remove all entries from the local version of the cache
168 
169         Ehcache ehCache = delegate.getCache(name);
170         if (ehCache != null)
171         {
172             // Remove all entries but do not notify replication listeners.
173             ehCache.removeAll(true);
174         }
175         else
176         {
177             ehCache = createCache(name, settings, true);
178         }
179         return ehCache;
180     }
181 
182     private Ehcache createCache(String name, CacheSettings settings, boolean selfLoading)
183     {
184         return new EhCacheHelper(replicatorConfigFactory).getEhcache(name, delegate, settings, selfLoading, statisticsEnabled);
185     }
186 
187     @Override
188     public void shutdown()
189     {
190 
191         delegate.shutdown();
192     }
193 
194     @Override
195     public void registerMBeans(@Nullable final MBeanServer mBeanServer)
196     {
197         if (mBeanServer != null)
198         {
199             ManagementService.registerMBeans(delegate, mBeanServer, true, true, true, true);
200         }
201     }
202 
203     @Override
204     public void unregisterMBeans(@Nullable final MBeanServer mBeanServer)
205     {
206         if (mBeanServer != null)
207         {
208             final ManagementService managementService = new ManagementService(delegate, mBeanServer, true, true, true, true);
209             managementService.dispose();
210         }
211     }
212 
213     static class SupplierAdapter<V> implements CacheLoader<ReferenceKey, V>
214     {
215         private final com.atlassian.cache.Supplier<V> supplier;
216 
217         SupplierAdapter(com.atlassian.cache.Supplier<V> supplier)
218         {
219             this.supplier = supplier;
220         }
221 
222         @Nonnull
223         @Override
224         public V load(@Nonnull ReferenceKey key)
225         {
226             return supplier.get();
227         }
228     }
229 }