1   /**
2    *  Copyright 2003-2007 Greg Luck
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.distribution;
18  
19  import junit.framework.TestCase;
20  import net.sf.ehcache.AbstractCacheTest;
21  import net.sf.ehcache.Cache;
22  import net.sf.ehcache.CacheManager;
23  import net.sf.ehcache.Ehcache;
24  import net.sf.ehcache.StopWatch;
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  import java.io.IOException;
29  import java.net.InetAddress;
30  import java.net.MulticastSocket;
31  import java.rmi.RemoteException;
32  import java.util.List;
33  
34  /**
35   * Multicast tests. These require special machine configuration.
36   * <p/>
37   * Running on a single machine, as these tests do, you need to add a route command so that two multiCast sockets
38   * can be added at the same time.
39   * <ol>
40   * <li>Mac OSX: <code>route add -net 224.0.0.0 -interface lo0</code>
41   * <li>Linux (from JGroups doco, untested): <code>route add -net 224.0.0.0 netmask 224.0.0.0 dev lo</code>
42   * </ol>
43   *
44   * @author Greg Luck
45   * @version $Id: MulticastRMIPeerProviderTest.java 512 2007-07-10 09:18:45Z gregluck $
46   */
47  public class MulticastRMIPeerProviderTest extends TestCase {
48  
49      private static final Log LOG = LogFactory.getLog(MulticastRMIPeerProviderTest.class.getName());
50  
51      /**
52       * Cache Manager 1
53       */
54      protected CacheManager manager1;
55      /**
56       * Cache Manager 2
57       */
58      protected CacheManager manager2;
59      /**
60       * Cache Manager 3
61       */
62      protected CacheManager manager3;
63  
64      /**
65       * {@inheritDoc}
66       */
67      protected void setUp() throws Exception {
68          if (JVMUtil.isSingleRMIRegistryPerVM()) {
69              return;
70          }
71          MulticastKeepaliveHeartbeatSender.setHeartBeatInterval(1000);
72          manager1 = new CacheManager(AbstractCacheTest.TEST_CONFIG_DIR + "distribution/ehcache-distributed1.xml");
73          manager2 = new CacheManager(AbstractCacheTest.TEST_CONFIG_DIR + "distribution/ehcache-distributed2.xml");
74          manager3 = new CacheManager(AbstractCacheTest.TEST_CONFIG_DIR + "distribution/ehcache-distributed3.xml");
75  
76          //wait for cluster to establish
77          Thread.sleep(2000);
78      }
79  
80      /**
81       * {@inheritDoc}
82       */
83      protected void tearDown() throws Exception {
84  
85          if (JVMUtil.isSingleRMIRegistryPerVM()) {
86              return;
87          }
88  
89          manager1.shutdown();
90          manager2.shutdown();
91          manager3.shutdown();
92      }
93  
94      /**
95       * Make sure no exceptions get logged. Manual inspection.
96       */
97      public void testSolePeer() throws Exception {
98          tearDown();
99  
100         manager1 = new CacheManager(AbstractCacheTest.TEST_CONFIG_DIR
101                 + "distribution/ehcache-distributed-no-caches-replicating.xml");
102     }
103 
104     /**
105      * test remote cache peers
106      */
107     public void testProviderFromCacheManager() throws InterruptedException {
108 
109         if (JVMUtil.isSingleRMIRegistryPerVM()) {
110             return;
111         }
112 
113         Ehcache m1sampleCache1 = manager1.getCache("sampleCache1");
114         Thread.sleep(2000);
115 
116         List peerUrls = manager1.getCachePeerProvider().listRemoteCachePeers(m1sampleCache1);
117         assertEquals(expectedPeers(), peerUrls.size());
118 
119         Ehcache m2sampleCache1 = manager2.getCache("sampleCache1");
120         assertFalse(m1sampleCache1.getGuid().equals(m2sampleCache1.getGuid()));
121 
122         List peerUrls2 = manager2.getCachePeerProvider().listRemoteCachePeers(m2sampleCache1);
123         assertEquals(expectedPeers(), peerUrls2.size());
124 
125         Ehcache m3sampleCache1 = manager3.getCache("sampleCache1");
126         assertFalse(m1sampleCache1.getGuid().equals(m3sampleCache1.getGuid()));
127 
128         List peerUrls3 = manager3.getCachePeerProvider().listRemoteCachePeers(m3sampleCache1);
129         assertEquals(expectedPeers(), peerUrls3.size());
130     }
131 
132     /**
133      * The default caches for ehcache-dsitributed1-6.xml are set to replicate.
134      * We create a new cache from the default and expect it to be replicated.
135      */
136     public void testProviderCreatedFromDefaultCache() throws InterruptedException {
137 
138         if (JVMUtil.isSingleRMIRegistryPerVM()) {
139             return;
140         }
141 
142         //manual does not nor should it work this way
143         if (this.getClass() != MulticastRMIPeerProviderTest.class) {
144             return;
145         }
146 
147         manager1.addCache("fromDefaultCache");
148         RMICacheManagerPeerListener peerListener1 = (RMICacheManagerPeerListener) manager1.getCachePeerListener();
149         //peerListener1.notifyCacheAdded("fromDefaultCache");
150         manager2.addCache("fromDefaultCache");
151         RMICacheManagerPeerListener peerListener2 = (RMICacheManagerPeerListener) manager2.getCachePeerListener();
152         //peerListener2.notifyCacheAdded("fromDefaultCache");
153         manager3.addCache("fromDefaultCache");
154         RMICacheManagerPeerListener peerListener3 = (RMICacheManagerPeerListener) manager3.getCachePeerListener();
155         //peerListener3.notifyCacheAdded("fromDefaultCache");
156         Thread.sleep(2000);
157 
158         CacheManagerPeerProvider cachePeerProvider = manager1.getCachePeerProvider();
159 
160         Cache cache = manager1.getCache("fromDefaultCache");
161         List peerUrls = cachePeerProvider.listRemoteCachePeers(cache);
162         assertEquals(expectedPeers(), peerUrls.size());
163 
164     }
165 
166 
167     /**
168      * The default caches for ehcache-dsitributed1-6.xml are set to replicate.
169      * We create a new cache from the default and expect it to be replicated.
170      */
171     public void testDeleteReplicatedCache() throws InterruptedException {
172 
173         if (JVMUtil.isSingleRMIRegistryPerVM()) {
174             return;
175         }
176 
177         //manual does not nor should it work this way
178         if (this.getClass() != MulticastRMIPeerProviderTest.class) {
179             return;
180         }
181 
182         manager1.addCache("fromDefaultCache");
183         manager2.addCache("fromDefaultCache");
184         manager3.addCache("fromDefaultCache");
185         Thread.sleep(2200);
186 
187         CacheManagerPeerProvider cachePeerProvider = manager1.getCachePeerProvider();
188         Cache cache = manager1.getCache("fromDefaultCache");
189 
190         //Should be three
191         List peerUrls = cachePeerProvider.listRemoteCachePeers(cache);
192         assertEquals(expectedPeers(), peerUrls.size());
193 
194 
195         manager1.removeCache("fromDefaultCache");
196         Thread.sleep(2200);
197 
198         peerUrls = cachePeerProvider.listRemoteCachePeers(cache);
199         assertEquals(expectedPeers(), peerUrls.size());
200 
201     }
202 
203     /**
204      * There are 3 in the cluster, so there will be two others
205      */
206     protected int expectedPeers() {
207         return 2;
208     }
209 
210 
211     /**
212      * Tests the speed of remotely looking up.
213      *
214      * @throws RemoteException
215      * @throws InterruptedException .19ms
216      *                              This seems to imply a maximum of 5000 per second best case. Not bad.
217      */
218     public void testRemoteGetName() throws RemoteException, InterruptedException {
219 
220         if (JVMUtil.isSingleRMIRegistryPerVM()) {
221             return;
222         }
223 
224         Ehcache m1sampleCache1 = manager1.getCache("sampleCache1");
225         Thread.sleep(2000);
226         List peerUrls = manager1.getCachePeerProvider().listRemoteCachePeers(m1sampleCache1);
227 
228         CachePeer m1SampleCach1Peer = (CachePeer) peerUrls.get(0);
229 
230         for (int i = 0; i < 100; i++) {
231             m1SampleCach1Peer.getName();
232         }
233         Thread.sleep(2000);
234 
235         StopWatch stopWatch = new StopWatch();
236         for (int i = 0; i < 1000; i++) {
237             m1SampleCach1Peer.getName();
238         }
239         long time = stopWatch.getElapsedTime();
240 
241         LOG.info("Remote name lookup time in ms: " + time / 1000f);
242 
243     }
244 
245     /**
246      * Determines that the multicast TTL default is 1, which means that packets are restricted to the same subnet.
247      * peerDiscovery=automatic, multicastGroupAddress=230.0.0.1, multicastGroupPort=4446, multicastPacketTimeToLive=255
248      */
249     public void testMulticastTTL() throws IOException {
250         InetAddress groupAddress = InetAddress.getByName("230.0.0.1");
251         MulticastSocket socket = new MulticastSocket();
252         socket.joinGroup(groupAddress);
253         int ttl = socket.getTimeToLive();
254         assertEquals(1, ttl);
255 }
256 
257 }