View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.regionserver;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertFalse;
23  import static org.junit.Assert.assertNull;
24  import static org.junit.Assert.assertTrue;
25  
26  import java.util.List;
27  import java.util.concurrent.Semaphore;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.hadoop.hbase.*;
32  import org.apache.hadoop.hbase.testclassification.MediumTests;
33  import org.apache.hadoop.hbase.zookeeper.MasterAddressTracker;
34  import org.apache.hadoop.hbase.zookeeper.ZKUtil;
35  import org.apache.hadoop.hbase.zookeeper.ZooKeeperListener;
36  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
37  import org.junit.After;
38  import org.junit.AfterClass;
39  import org.junit.BeforeClass;
40  import org.junit.Test;
41  import org.junit.Rule;
42  import org.junit.rules.TestName;
43  import org.junit.experimental.categories.Category;
44  
45  @Category(MediumTests.class)
46  public class TestMasterAddressTracker {
47    private static final Log LOG = LogFactory.getLog(TestMasterAddressTracker.class);
48  
49    private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
50    // Cleaned up after each unit test.
51    private static ZooKeeperWatcher zk;
52  
53    @Rule
54    public TestName name = new TestName();
55  
56    @After
57    public void cleanUp() {
58      if (zk != null) {
59        zk.close();
60      }
61    }
62  
63    @BeforeClass
64    public static void setUpBeforeClass() throws Exception {
65      TEST_UTIL.startMiniZKCluster();
66    }
67  
68    @AfterClass
69    public static void tearDownAfterClass() throws Exception {
70      TEST_UTIL.shutdownMiniZKCluster();
71    }
72  
73    @Test
74    public void testDeleteIfEquals() throws Exception {
75      final ServerName sn = ServerName.valueOf("localhost", 1234, System.currentTimeMillis());
76      final MasterAddressTracker addressTracker = setupMasterTracker(sn, 1772);
77      try {
78        assertFalse("shouldn't have deleted wrong master server.",
79            MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), "some other string."));
80      } finally {
81        assertTrue("Couldn't clean up master",
82            MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), sn.toString()));
83      }
84    }
85  
86    /**
87     * create an address tracker instance
88     * @param sn if not-null set the active master
89     * @param infoPort if there is an active master, set its info port.
90     */
91    private MasterAddressTracker setupMasterTracker(final ServerName sn, final int infoPort)
92        throws Exception {
93      zk = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
94          name.getMethodName(), null);
95      ZKUtil.createAndFailSilent(zk, zk.baseZNode);
96      ZKUtil.createAndFailSilent(zk, zk.backupMasterAddressesZNode);
97  
98      // Should not have a master yet
99      MasterAddressTracker addressTracker = new MasterAddressTracker(zk, null);
100     addressTracker.start();
101     assertFalse(addressTracker.hasMaster());
102     zk.registerListener(addressTracker);
103 
104     // Use a listener to capture when the node is actually created
105     NodeCreationListener listener = new NodeCreationListener(zk, zk.getMasterAddressZNode());
106     zk.registerListener(listener);
107 
108     if (sn != null) {
109       LOG.info("Creating master node");
110       MasterAddressTracker.setMasterAddress(zk, zk.getMasterAddressZNode(), sn, infoPort);
111 
112       // Wait for the node to be created
113       LOG.info("Waiting for master address manager to be notified");
114       listener.waitForCreation();
115       LOG.info("Master node created");
116     }
117     return addressTracker;
118   }
119 
120   /**
121    * Unit tests that uses ZooKeeper but does not use the master-side methods
122    * but rather acts directly on ZK.
123    * @throws Exception
124    */
125   @Test
126   public void testMasterAddressTrackerFromZK() throws Exception {
127     // Create the master node with a dummy address
128     final int infoPort = 1235;
129     final ServerName sn = ServerName.valueOf("localhost", 1234, System.currentTimeMillis());
130     final MasterAddressTracker addressTracker = setupMasterTracker(sn, infoPort);
131     try {
132       assertTrue(addressTracker.hasMaster());
133       ServerName pulledAddress = addressTracker.getMasterAddress();
134       assertTrue(pulledAddress.equals(sn));
135       assertEquals(infoPort, addressTracker.getMasterInfoPort());
136     } finally {
137       assertTrue("Couldn't clean up master",
138           MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), sn.toString()));
139     }
140   }
141 
142 
143   @Test
144   public void testParsingNull() throws Exception {
145     assertNull("parse on null data should return null.", MasterAddressTracker.parse(null));
146   }
147 
148   @Test
149   public void testNoBackups() throws Exception {
150     final ServerName sn = ServerName.valueOf("localhost", 1234, System.currentTimeMillis());
151     final MasterAddressTracker addressTracker = setupMasterTracker(sn, 1772);
152     try {
153       assertEquals("Should receive 0 for backup not found.", 0,
154           addressTracker.getBackupMasterInfoPort(
155               ServerName.valueOf("doesnotexist.example.com", 1234, System.currentTimeMillis())));
156     } finally {
157       assertTrue("Couldn't clean up master",
158           MasterAddressTracker.deleteIfEquals(addressTracker.getWatcher(), sn.toString()));
159     }
160   }
161 
162   @Test
163   public void testNoMaster() throws Exception {
164     final MasterAddressTracker addressTracker = setupMasterTracker(null, 1772);
165     assertFalse(addressTracker.hasMaster());
166     assertNull("should get null master when none active.", addressTracker.getMasterAddress());
167     assertEquals("Should receive 0 for backup not found.", 0, addressTracker.getMasterInfoPort());
168   }
169 
170   @Test
171   public void testBackupMasters() throws Exception {
172     final ServerName sn = ServerName.valueOf("localhost", 5678, System.currentTimeMillis());
173     final MasterAddressTracker addressTracker = setupMasterTracker(sn, 1111);
174     assertTrue(addressTracker.hasMaster());
175     ServerName activeMaster = addressTracker.getMasterAddress();
176     assertEquals(activeMaster, sn);
177     // No current backup masters
178     List<ServerName> backupMasters = MasterAddressTracker.getBackupMastersAndRenewWatch(zk);
179     assertEquals(0, backupMasters.size());
180     ServerName backupMaster1 = ServerName.valueOf("localhost", 2222, -1);
181     ServerName backupMaster2 = ServerName.valueOf("localhost", 3333, -1);
182     String backupZNode1 = ZKUtil.joinZNode(zk.backupMasterAddressesZNode, backupMaster1.toString());
183     String backupZNode2 = ZKUtil.joinZNode(zk.backupMasterAddressesZNode, backupMaster2.toString());
184     // Add a backup master
185     MasterAddressTracker.setMasterAddress(zk, backupZNode1, backupMaster1, 2222);
186     MasterAddressTracker.setMasterAddress(zk, backupZNode2, backupMaster2, 3333);
187     backupMasters = MasterAddressTracker.getBackupMastersAndRenewWatch(zk);
188     assertEquals(2, backupMasters.size());
189     assertTrue(backupMasters.contains(backupMaster1));
190     assertTrue(backupMasters.contains(backupMaster2));
191   }
192 
193   public static class NodeCreationListener extends ZooKeeperListener {
194     private static final Log LOG = LogFactory.getLog(NodeCreationListener.class);
195 
196     private Semaphore lock;
197     private String node;
198 
199     public NodeCreationListener(ZooKeeperWatcher watcher, String node) {
200       super(watcher);
201       lock = new Semaphore(0);
202       this.node = node;
203     }
204 
205     @Override
206     public void nodeCreated(String path) {
207       if(path.equals(node)) {
208         LOG.debug("nodeCreated(" + path + ")");
209         lock.release();
210       }
211     }
212 
213     public void waitForCreation() throws InterruptedException {
214       lock.acquire();
215     }
216   }
217 
218 }
219