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
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.concurrent.atomic.AtomicInteger;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.apache.hadoop.conf.Configuration;
32 import org.apache.hadoop.hbase.Abortable;
33 import org.apache.hadoop.hbase.HBaseTestingUtility;
34 import org.apache.hadoop.hbase.HConstants;
35 import org.apache.hadoop.hbase.HRegionInfo;
36 import org.apache.hadoop.hbase.testclassification.MediumTests;
37 import org.apache.hadoop.hbase.MiniHBaseCluster;
38 import org.apache.hadoop.hbase.TableName;
39 import org.apache.hadoop.hbase.ServerLoad;
40 import org.apache.hadoop.hbase.ServerName;
41 import org.apache.hadoop.hbase.client.Admin;
42 import org.apache.hadoop.hbase.client.HTable;
43 import org.apache.hadoop.hbase.client.Put;
44 import org.apache.hadoop.hbase.client.Table;
45 import org.apache.hadoop.hbase.regionserver.HRegion;
46 import org.apache.hadoop.hbase.regionserver.Region;
47 import org.apache.hadoop.hbase.util.Bytes;
48 import org.apache.hadoop.hbase.util.JVMClusterUtil;
49 import org.apache.hadoop.hbase.zookeeper.DrainingServerTracker;
50 import org.apache.hadoop.hbase.zookeeper.RegionServerTracker;
51 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
52 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
53 import org.junit.AfterClass;
54 import org.junit.Assert;
55 import org.junit.BeforeClass;
56 import org.junit.Test;
57 import org.junit.experimental.categories.Category;
58 import org.mockito.Mockito;
59
60 @Category(MediumTests.class)
61 public class TestAssignmentListener {
62 private static final Log LOG = LogFactory.getLog(TestAssignmentListener.class);
63
64 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
65 private static final Abortable abortable = new Abortable() {
66 @Override
67 public boolean isAborted() {
68 return false;
69 }
70
71 @Override
72 public void abort(String why, Throwable e) {
73 }
74 };
75
76 static class DummyListener {
77 protected AtomicInteger modified = new AtomicInteger(0);
78
79 public void awaitModifications(int count) throws InterruptedException {
80 while (!modified.compareAndSet(count, 0)) {
81 Thread.sleep(100);
82 }
83 }
84 }
85
86 static class DummyAssignmentListener extends DummyListener implements AssignmentListener {
87 private AtomicInteger closeCount = new AtomicInteger(0);
88 private AtomicInteger openCount = new AtomicInteger(0);
89
90 public DummyAssignmentListener() {
91 }
92
93 @Override
94 public void regionOpened(final HRegionInfo regionInfo, final ServerName serverName) {
95 LOG.info("Assignment open region=" + regionInfo + " server=" + serverName);
96 openCount.incrementAndGet();
97 modified.incrementAndGet();
98 }
99
100 @Override
101 public void regionClosed(final HRegionInfo regionInfo) {
102 LOG.info("Assignment close region=" + regionInfo);
103 closeCount.incrementAndGet();
104 modified.incrementAndGet();
105 }
106
107 public void reset() {
108 openCount.set(0);
109 closeCount.set(0);
110 }
111
112 public int getLoadCount() {
113 return openCount.get();
114 }
115
116 public int getCloseCount() {
117 return closeCount.get();
118 }
119 }
120
121 static class DummyServerListener extends DummyListener implements ServerListener {
122 private AtomicInteger removedCount = new AtomicInteger(0);
123 private AtomicInteger addedCount = new AtomicInteger(0);
124
125 public DummyServerListener() {
126 }
127
128 @Override
129 public void serverAdded(final ServerName serverName) {
130 LOG.info("Server added " + serverName);
131 addedCount.incrementAndGet();
132 modified.incrementAndGet();
133 }
134
135 @Override
136 public void serverRemoved(final ServerName serverName) {
137 LOG.info("Server removed " + serverName);
138 removedCount.incrementAndGet();
139 modified.incrementAndGet();
140 }
141
142 public void reset() {
143 addedCount.set(0);
144 removedCount.set(0);
145 }
146
147 public int getAddedCount() {
148 return addedCount.get();
149 }
150
151 public int getRemovedCount() {
152 return removedCount.get();
153 }
154 }
155
156 @BeforeClass
157 public static void beforeAllTests() throws Exception {
158 TEST_UTIL.startMiniCluster(2);
159 }
160
161 @AfterClass
162 public static void afterAllTests() throws Exception {
163 TEST_UTIL.shutdownMiniCluster();
164 }
165
166 @Test(timeout=60000)
167 public void testServerListener() throws IOException, InterruptedException {
168 ServerManager serverManager = TEST_UTIL.getHBaseCluster().getMaster().getServerManager();
169
170 DummyServerListener listener = new DummyServerListener();
171 serverManager.registerListener(listener);
172 try {
173 MiniHBaseCluster miniCluster = TEST_UTIL.getMiniHBaseCluster();
174
175
176 miniCluster.startRegionServer();
177 listener.awaitModifications(1);
178 assertEquals(1, listener.getAddedCount());
179 assertEquals(0, listener.getRemovedCount());
180
181
182 listener.reset();
183 miniCluster.startRegionServer();
184 listener.awaitModifications(1);
185 assertEquals(1, listener.getAddedCount());
186 assertEquals(0, listener.getRemovedCount());
187
188 int nrs = miniCluster.getRegionServerThreads().size();
189
190
191 listener.reset();
192 miniCluster.stopRegionServer(nrs - 1);
193 listener.awaitModifications(1);
194 assertEquals(0, listener.getAddedCount());
195 assertEquals(1, listener.getRemovedCount());
196
197
198 listener.reset();
199 miniCluster.stopRegionServer(nrs - 2);
200 listener.awaitModifications(1);
201 assertEquals(0, listener.getAddedCount());
202 assertEquals(1, listener.getRemovedCount());
203 } finally {
204 serverManager.unregisterListener(listener);
205 }
206 }
207
208 @Test(timeout=60000)
209 public void testAssignmentListener() throws IOException, InterruptedException {
210 AssignmentManager am = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager();
211 Admin admin = TEST_UTIL.getHBaseAdmin();
212
213 DummyAssignmentListener listener = new DummyAssignmentListener();
214 am.registerListener(listener);
215 try {
216 final String TABLE_NAME_STR = "testtb";
217 final TableName TABLE_NAME = TableName.valueOf(TABLE_NAME_STR);
218 final byte[] FAMILY = Bytes.toBytes("cf");
219
220
221 LOG.info("Create Table");
222 TEST_UTIL.createTable(TABLE_NAME, FAMILY);
223 listener.awaitModifications(1);
224 assertEquals(1, listener.getLoadCount());
225 assertEquals(0, listener.getCloseCount());
226
227
228 Table table = new HTable(TEST_UTIL.getConfiguration(), TABLE_NAME);
229 try {
230 for (int i = 0; i < 10; ++i) {
231 byte[] key = Bytes.toBytes("row-" + i);
232 Put put = new Put(key);
233 put.add(FAMILY, null, key);
234 table.put(put);
235 }
236 } finally {
237 table.close();
238 }
239
240
241 LOG.info("Split Table");
242 listener.reset();
243 admin.split(TABLE_NAME, Bytes.toBytes("row-3"));
244 listener.awaitModifications(3);
245 assertEquals(2, listener.getLoadCount());
246 assertEquals(1, listener.getCloseCount());
247
248
249 MiniHBaseCluster miniCluster = TEST_UTIL.getMiniHBaseCluster();
250 int mergeable = 0;
251 while (mergeable < 2) {
252 Thread.sleep(100);
253 admin.majorCompact(TABLE_NAME);
254 mergeable = 0;
255 for (JVMClusterUtil.RegionServerThread regionThread: miniCluster.getRegionServerThreads()) {
256 for (Region region: regionThread.getRegionServer().getOnlineRegions(TABLE_NAME)) {
257 mergeable += ((HRegion)region).isMergeable() ? 1 : 0;
258 }
259 }
260 }
261
262
263 LOG.info("Merge Regions");
264 listener.reset();
265 List<HRegionInfo> regions = admin.getTableRegions(TABLE_NAME);
266 assertEquals(2, regions.size());
267 admin.mergeRegions(regions.get(0).getEncodedNameAsBytes(),
268 regions.get(1).getEncodedNameAsBytes(), true);
269 listener.awaitModifications(3);
270 assertEquals(1, admin.getTableRegions(TABLE_NAME).size());
271 assertEquals(1, listener.getLoadCount());
272 assertEquals(2, listener.getCloseCount());
273
274
275 LOG.info("Drop Table");
276 listener.reset();
277 TEST_UTIL.deleteTable(TABLE_NAME);
278 listener.awaitModifications(1);
279 assertEquals(0, listener.getLoadCount());
280 assertEquals(1, listener.getCloseCount());
281 } finally {
282 am.unregisterListener(listener);
283 }
284 }
285
286 @Test
287 public void testAddNewServerThatExistsInDraining() throws Exception {
288
289
290
291
292
293
294 Configuration conf = TEST_UTIL.getConfiguration();
295 ZooKeeperWatcher zooKeeper = new ZooKeeperWatcher(conf,
296 "zkWatcher-NewServerDrainTest", abortable, true);
297 String baseZNode = conf.get(HConstants.ZOOKEEPER_ZNODE_PARENT,
298 HConstants.DEFAULT_ZOOKEEPER_ZNODE_PARENT);
299 String drainingZNode = ZKUtil.joinZNode(baseZNode,
300 conf.get("zookeeper.znode.draining.rs", "draining"));
301
302 MasterServices services = Mockito.mock(MasterServices.class);
303 HMaster master = Mockito.mock(HMaster.class);
304 Mockito.when(master.getConfiguration()).thenReturn(conf);
305
306 ServerName SERVERNAME_A = ServerName.valueOf("mockserverbulk_a.org", 1000, 8000);
307 ServerName SERVERNAME_B = ServerName.valueOf("mockserverbulk_b.org", 1001, 8000);
308 ServerName SERVERNAME_C = ServerName.valueOf("mockserverbulk_c.org", 1002, 8000);
309
310
311
312 ArrayList<ServerName> drainingServers = new ArrayList<ServerName>();
313 drainingServers.add(SERVERNAME_A);
314 drainingServers.add(SERVERNAME_B);
315
316
317
318
319 HashMap<ServerName, ServerLoad> onlineServers = new HashMap<ServerName, ServerLoad>();
320 onlineServers.put(SERVERNAME_A, ServerLoad.EMPTY_SERVERLOAD);
321 onlineServers.put(SERVERNAME_C, ServerLoad.EMPTY_SERVERLOAD);
322
323
324
325 for (ServerName sn : drainingServers) {
326 String znode = ZKUtil.joinZNode(drainingZNode, sn.getServerName());
327 ZKUtil.createAndFailSilent(zooKeeper, znode);
328 }
329
330
331
332 ServerManager serverManager = new ServerManager(master, services);
333
334 RegionServerTracker regionServerTracker = new RegionServerTracker(
335 zooKeeper, master, serverManager);
336 regionServerTracker.start();
337
338 DrainingServerTracker drainingServerTracker = new DrainingServerTracker(
339 zooKeeper, master, serverManager);
340 drainingServerTracker.start();
341
342
343 Assert.assertEquals(serverManager.getOnlineServers(),
344 new HashMap<ServerName, ServerLoad>());
345 Assert.assertEquals(serverManager.getDrainingServersList(),
346 new ArrayList<ServerName>());
347
348
349 ArrayList<ServerName> onlineDrainingServers = new ArrayList<ServerName>();
350 for (ServerName sn : onlineServers.keySet()){
351
352 serverManager.checkAndRecordNewServer(sn, onlineServers.get(sn));
353 if (drainingServers.contains(sn)){
354 onlineDrainingServers.add(sn);
355 }
356 }
357
358
359 Assert.assertEquals(serverManager.getOnlineServers(), onlineServers);
360 Assert.assertEquals(serverManager.getDrainingServersList(),
361 onlineDrainingServers);
362 }
363 }