View Javadoc
1   package com.atlassian.cache.ehcache.cluster;
2   
3   import java.util.List;
4   import java.util.concurrent.atomic.AtomicInteger;
5   
6   import com.atlassian.cache.Cache;
7   import com.atlassian.cache.CachedReference;
8   import com.atlassian.cache.ManagedCache;
9   import com.atlassian.cache.ehcache.EhCacheManager;
10  
11  import com.google.common.base.Function;
12  import com.google.common.base.Throwables;
13  import com.google.common.collect.ImmutableList;
14  import com.google.common.collect.Iterables;
15  
16  import org.junit.rules.ExternalResource;
17  
18  import net.sf.ehcache.CacheManager;
19  import net.sf.ehcache.config.Configuration;
20  
21  import static com.atlassian.cache.ehcache.cluster.EhCacheConfigurationFactory.newConfiguration;
22  
23  /**
24   * JUnit rule to set up an Ehcache cluster for testing
25   */
26  public class EhCacheCluster extends ExternalResource
27  {
28      private final AtomicInteger activeCount = new AtomicInteger();
29      private final int count;
30  
31      private volatile List<CacheManager> rawNodes = ImmutableList.of();
32      private volatile List<EhCacheManager> decoratedNodes = ImmutableList.of();
33  
34      public EhCacheCluster(final int count)
35      {
36          this.count = count;
37      }
38  
39      @Override
40      protected void after()
41      {
42          try
43          {
44              if (activeCount.decrementAndGet() == 0)
45              {
46                  // only truly shut down when the active count reaches zero
47                  final List<CacheManager> nodes = rawNodes;
48                  decoratedNodes = null;
49                  rawNodes = null;
50                  for (CacheManager instance : nodes)
51                  {
52                      instance.shutdown();
53                  }
54              }
55          }
56          finally
57          {
58              super.after();
59          }
60      }
61  
62      @Override
63      protected void before() throws Throwable
64      {
65          super.before();
66  
67          if (activeCount.getAndIncrement() == 0)
68          {
69              // only initialize when the active count is at zero
70              rawNodes = EhCacheCluster.newCluster(count);
71              decoratedNodes = ImmutableList.copyOf(Iterables.transform(rawNodes,
72                      new Function<CacheManager, EhCacheManager>()
73                      {
74                          @Override
75                          public EhCacheManager apply(CacheManager rawNode)
76                          {
77                              return new EhCacheManager(rawNode, null);
78                          }
79                      }));
80          }
81      }
82  
83      public EhCacheManager getNode(int index)
84      {
85          return decoratedNodes.get(index);
86      }
87  
88      public void reset()
89      {
90          if (size() > 0)
91          {
92              final EhCacheManager node = decoratedNodes.get(0);
93              for (ManagedCache cache : node.getManagedCaches())
94              {
95                  if (cache instanceof Cache<?,?>)
96                  {
97                      ((Cache<?,?>)cache).removeAll();
98                  }
99                  else
100                 {
101                     ((CachedReference<?>)cache).reset();
102                 }
103             }
104         }
105     }
106 
107     public int size()
108     {
109         return decoratedNodes.size();
110     }
111 
112     public static EhCacheCluster createCluster(int count)
113     {
114         return new EhCacheCluster(count);
115     }
116 
117     public static List<CacheManager> newCluster(final int maxNodeId)
118     {
119         final ImmutableList.Builder<CacheManager> nodes = new ImmutableList.Builder<CacheManager>();
120         for (int thisNodeId = 1; thisNodeId <= maxNodeId; ++thisNodeId)
121         {
122             final Configuration config = newConfiguration(thisNodeId, maxNodeId);
123             final CacheManager ehcache = CacheManager.newInstance(config);
124             nodes.add(ehcache);
125         }
126         return nodes.build();
127     }
128 
129     public static void clusteredTest(int nodeCount, ClusteredTest test) throws Exception
130     {
131         final EhCacheCluster cluster = new EhCacheCluster(nodeCount);
132         try
133         {
134             cluster.before();
135             try
136             {
137                 test.runTest(cluster);
138             }
139             finally
140             {
141                 cluster.after();
142             }
143         }
144         catch (Throwable e)
145         {
146             Throwables.propagate(e);
147         }
148     }
149 
150     public interface ClusteredTest
151     {
152         void runTest(EhCacheCluster cluster) throws Exception;
153     }
154 }