1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.master;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertTrue;
25
26 import java.io.IOException;
27 import java.io.InterruptedIOException;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.concurrent.Semaphore;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.conf.Configuration;
35 import org.apache.hadoop.hbase.ChoreService;
36 import org.apache.hadoop.hbase.CoordinatedStateManager;
37 import org.apache.hadoop.hbase.HBaseTestingUtility;
38 import org.apache.hadoop.hbase.Waiter;
39 import org.apache.hadoop.hbase.testclassification.MediumTests;
40 import org.apache.hadoop.hbase.Server;
41 import org.apache.hadoop.hbase.ServerName;
42 import org.apache.hadoop.hbase.client.ClusterConnection;
43 import org.apache.hadoop.hbase.monitoring.MonitoredTask;
44 import org.apache.hadoop.hbase.zookeeper.ClusterStatusTracker;
45 import org.apache.hadoop.hbase.zookeeper.MasterAddressTracker;
46 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
47 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
48 import org.apache.hadoop.hbase.zookeeper.ZooKeeperListener;
49 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
50 import org.apache.zookeeper.KeeperException;
51 import org.junit.AfterClass;
52 import org.junit.BeforeClass;
53 import org.junit.Test;
54 import org.junit.experimental.categories.Category;
55 import org.mockito.Mockito;
56
57
58
59
60 @Category(MediumTests.class)
61 public class TestActiveMasterManager {
62 private final static Log LOG = LogFactory.getLog(TestActiveMasterManager.class);
63 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
64
65 @BeforeClass
66 public static void setUpBeforeClass() throws Exception {
67 TEST_UTIL.startMiniZKCluster();
68 }
69
70 @AfterClass
71 public static void tearDownAfterClass() throws Exception {
72 TEST_UTIL.shutdownMiniZKCluster();
73 }
74
75 @Test public void testRestartMaster() throws IOException, KeeperException {
76 try (ZooKeeperWatcher zk = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
77 "testActiveMasterManagerFromZK", null, true)) {
78 try {
79 ZKUtil.deleteNode(zk, zk.getMasterAddressZNode());
80 ZKUtil.deleteNode(zk, zk.clusterStateZNode);
81 } catch (KeeperException.NoNodeException nne) {
82 }
83
84
85 ServerName master = ServerName.valueOf("localhost", 1, System.currentTimeMillis());
86
87 DummyMaster dummyMaster = new DummyMaster(zk, master);
88 ClusterStatusTracker clusterStatusTracker =
89 dummyMaster.getClusterStatusTracker();
90 ActiveMasterManager activeMasterManager =
91 dummyMaster.getActiveMasterManager();
92 assertFalse(activeMasterManager.clusterHasActiveMaster.get());
93
94
95 MonitoredTask status = Mockito.mock(MonitoredTask.class);
96 clusterStatusTracker.setClusterUp();
97
98 activeMasterManager.blockUntilBecomingActiveMaster(100, status);
99 assertTrue(activeMasterManager.clusterHasActiveMaster.get());
100 assertMaster(zk, master);
101
102
103 DummyMaster secondDummyMaster = new DummyMaster(zk, master);
104 ActiveMasterManager secondActiveMasterManager =
105 secondDummyMaster.getActiveMasterManager();
106 assertFalse(secondActiveMasterManager.clusterHasActiveMaster.get());
107 activeMasterManager.blockUntilBecomingActiveMaster(100, status);
108 assertTrue(activeMasterManager.clusterHasActiveMaster.get());
109 assertMaster(zk, master);
110 }
111 }
112
113
114
115
116
117
118 @Test
119 public void testActiveMasterManagerFromZK() throws Exception {
120 try (ZooKeeperWatcher zk = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
121 "testActiveMasterManagerFromZK", null, true)) {
122 try {
123 ZKUtil.deleteNode(zk, zk.getMasterAddressZNode());
124 ZKUtil.deleteNode(zk, zk.clusterStateZNode);
125 } catch (KeeperException.NoNodeException nne) {
126 }
127
128
129 ServerName firstMasterAddress =
130 ServerName.valueOf("localhost", 1, System.currentTimeMillis());
131 ServerName secondMasterAddress =
132 ServerName.valueOf("localhost", 2, System.currentTimeMillis());
133
134
135 DummyMaster ms1 = new DummyMaster(zk, firstMasterAddress);
136 ActiveMasterManager activeMasterManager =
137 ms1.getActiveMasterManager();
138 assertFalse(activeMasterManager.clusterHasActiveMaster.get());
139
140
141 ClusterStatusTracker clusterStatusTracker =
142 ms1.getClusterStatusTracker();
143 clusterStatusTracker.setClusterUp();
144 activeMasterManager.blockUntilBecomingActiveMaster(100,
145 Mockito.mock(MonitoredTask.class));
146 assertTrue(activeMasterManager.clusterHasActiveMaster.get());
147 assertMaster(zk, firstMasterAddress);
148
149
150 WaitToBeMasterThread t = new WaitToBeMasterThread(zk, secondMasterAddress);
151 t.start();
152
153
154 int sleeps = 0;
155 while (!t.manager.clusterHasActiveMaster.get() && sleeps < 100) {
156 Thread.sleep(10);
157 sleeps++;
158 }
159
160
161 assertTrue(activeMasterManager.clusterHasActiveMaster.get());
162 assertTrue(t.manager.clusterHasActiveMaster.get());
163
164 assertFalse(t.isActiveMaster);
165
166
167 ms1.stop("stopping first server");
168
169
170 NodeDeletionListener listener = new NodeDeletionListener(zk, zk.getMasterAddressZNode());
171 zk.registerListener(listener);
172
173 LOG.info("Deleting master node");
174 ZKUtil.deleteNode(zk, zk.getMasterAddressZNode());
175
176
177 LOG.info("Waiting for active master manager to be notified");
178 listener.waitForDeletion();
179 LOG.info("Master node deleted");
180
181
182
183 sleeps = 0;
184 while (!t.isActiveMaster && sleeps < 100) {
185 Thread.sleep(10);
186 sleeps++;
187 }
188 LOG.debug("Slept " + sleeps + " times");
189
190 assertTrue(t.manager.clusterHasActiveMaster.get());
191 assertTrue(t.isActiveMaster);
192
193 LOG.info("Deleting master node");
194
195 ZKUtil.deleteNode(zk, zk.getMasterAddressZNode());
196 }
197 }
198
199 @Test
200 public void testBackupMasterUpdates() throws Exception {
201 Configuration conf = TEST_UTIL.getConfiguration();
202 try (ZooKeeperWatcher zk = new ZooKeeperWatcher(
203 conf, "testBackupMasterUpdates", null, true)) {
204 ServerName sn1 = ServerName.valueOf("localhost", 1, -1);
205 DummyMaster master1 = new DummyMaster(zk, sn1);
206 final ActiveMasterManager activeMasterManager = master1.getActiveMasterManager();
207 activeMasterManager.blockUntilBecomingActiveMaster(100,
208 Mockito.mock(MonitoredTask.class));
209 assertEquals(sn1, activeMasterManager.getActiveMasterServerName());
210 assertEquals(0, activeMasterManager.getBackupMasters().size());
211
212 final List<String> backupZNodes = new ArrayList<>();
213 for (int i = 1; i <= 10; i++) {
214 ServerName backupSn = ServerName.valueOf("localhost", 1000 + i, -1);
215 String backupZn = ZKUtil.joinZNode(zk.backupMasterAddressesZNode, backupSn.toString());
216 backupZNodes.add(backupZn);
217 MasterAddressTracker.setMasterAddress(zk, backupZn, backupSn, 1234);
218 TEST_UTIL.waitFor(10000,
219 new Waiter.Predicate<Exception>() {
220 @Override
221 public boolean evaluate() throws Exception {
222 return activeMasterManager.getBackupMasters().size() == backupZNodes.size();
223 }
224 });
225 }
226
227 int numBackups = backupZNodes.size();
228 for (String backupZNode: backupZNodes) {
229 ZKUtil.deleteNode(zk, backupZNode);
230 final int currentBackups = --numBackups;
231 TEST_UTIL.waitFor(10000,
232 new Waiter.Predicate<Exception>() {
233 @Override
234 public boolean evaluate() throws Exception {
235 return activeMasterManager.getBackupMasters().size() == currentBackups;
236 }
237 });
238 }
239 }
240 }
241
242
243
244
245
246
247
248
249 private void assertMaster(ZooKeeperWatcher zk,
250 ServerName expectedAddress)
251 throws KeeperException, IOException {
252 ServerName readAddress = MasterAddressTracker.getMasterAddress(zk);
253 assertNotNull(readAddress);
254 assertTrue(expectedAddress.equals(readAddress));
255 }
256
257 public static class WaitToBeMasterThread extends Thread {
258
259 ActiveMasterManager manager;
260 DummyMaster dummyMaster;
261 boolean isActiveMaster;
262
263 public WaitToBeMasterThread(ZooKeeperWatcher zk, ServerName address)
264 throws InterruptedIOException {
265 this.dummyMaster = new DummyMaster(zk,address);
266 this.manager = this.dummyMaster.getActiveMasterManager();
267 isActiveMaster = false;
268 }
269
270 @Override
271 public void run() {
272 manager.blockUntilBecomingActiveMaster(100,
273 Mockito.mock(MonitoredTask.class));
274 LOG.info("Second master has become the active master!");
275 isActiveMaster = true;
276 }
277 }
278
279 public static class NodeDeletionListener extends ZooKeeperListener {
280 private static final Log LOG = LogFactory.getLog(NodeDeletionListener.class);
281
282 private Semaphore lock;
283 private String node;
284
285 public NodeDeletionListener(ZooKeeperWatcher watcher, String node) {
286 super(watcher);
287 lock = new Semaphore(0);
288 this.node = node;
289 }
290
291 @Override
292 public void nodeDeleted(String path) {
293 if(path.equals(node)) {
294 LOG.debug("nodeDeleted(" + path + ")");
295 lock.release();
296 }
297 }
298
299 public void waitForDeletion() throws InterruptedException {
300 lock.acquire();
301 }
302 }
303
304
305
306
307 public static class DummyMaster implements Server {
308 private volatile boolean stopped;
309 private ClusterStatusTracker clusterStatusTracker;
310 private ActiveMasterManager activeMasterManager;
311
312 public DummyMaster(ZooKeeperWatcher zk, ServerName master) throws InterruptedIOException {
313 this.clusterStatusTracker =
314 new ClusterStatusTracker(zk, this);
315 clusterStatusTracker.start();
316
317 this.activeMasterManager =
318 new ActiveMasterManager(zk, master, this);
319 zk.registerListener(activeMasterManager);
320 }
321
322 @Override
323 public void abort(final String msg, final Throwable t) {}
324
325 @Override
326 public boolean isAborted() {
327 return false;
328 }
329
330 @Override
331 public Configuration getConfiguration() {
332 return null;
333 }
334
335 @Override
336 public ZooKeeperWatcher getZooKeeper() {
337 return null;
338 }
339
340 @Override
341 public CoordinatedStateManager getCoordinatedStateManager() {
342 return null;
343 }
344
345 @Override
346 public ServerName getServerName() {
347 return null;
348 }
349
350 @Override
351 public boolean isStopped() {
352 return this.stopped;
353 }
354
355 @Override
356 public void stop(String why) {
357 this.stopped = true;
358 }
359
360 @Override
361 public ClusterConnection getConnection() {
362 return null;
363 }
364
365 @Override
366 public MetaTableLocator getMetaTableLocator() {
367 return null;
368 }
369
370 public ClusterStatusTracker getClusterStatusTracker() {
371 return clusterStatusTracker;
372 }
373
374 public ActiveMasterManager getActiveMasterManager() {
375 return activeMasterManager;
376 }
377
378 @Override
379 public ChoreService getChoreService() {
380 return null;
381 }
382 }
383 }