1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.client;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertTrue;
23 import com.google.common.base.Preconditions;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.conf.Configuration;
31 import org.apache.hadoop.hbase.HBaseTestingUtility;
32 import org.apache.hadoop.hbase.HConstants;
33 import org.apache.hadoop.hbase.HRegionLocation;
34 import org.apache.hadoop.hbase.MultithreadedTestUtil;
35 import org.apache.hadoop.hbase.RegionLocations;
36 import org.apache.hadoop.hbase.ServerName;
37 import org.apache.hadoop.hbase.Waiter;
38 import org.apache.hadoop.hbase.master.HMaster;
39 import org.apache.hadoop.hbase.master.MetaRegionLocationCache;
40 import org.apache.hadoop.hbase.master.RegionState;
41 import org.apache.hadoop.hbase.testclassification.MasterTests;
42 import org.apache.hadoop.hbase.testclassification.SmallTests;
43 import org.apache.hadoop.hbase.util.JVMClusterUtil;
44 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
45 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
46 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
47 import org.junit.AfterClass;
48 import org.junit.BeforeClass;
49 import org.junit.Test;
50 import org.junit.experimental.categories.Category;
51
52 @Category({SmallTests.class, MasterTests.class })
53 public class TestMetaRegionLocationCache {
54
55 private static final Log LOG = LogFactory.getLog(TestMetaRegionLocationCache.class.getName());
56
57 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
58 private static ConnectionRegistry REGISTRY;
59
60
61 static void waitUntilAllMetaReplicasHavingRegionLocation(Configuration conf,
62 final ConnectionRegistry registry, final int regionReplication) throws IOException {
63 Waiter.waitFor(conf, conf.getLong(
64 "hbase.client.sync.wait.timeout.msec", 60000), 200, true,
65 new Waiter.ExplainingPredicate<IOException>() {
66 @Override
67 public String explainFailure() throws IOException {
68 return "Not all meta replicas get assigned";
69 }
70
71 @Override
72 public boolean evaluate() throws IOException {
73 try {
74 RegionLocations locs = registry.getMetaRegionLocations();
75 if (locs == null || locs.size() < regionReplication) {
76 return false;
77 }
78 for (int i = 0; i < regionReplication; i++) {
79 if (locs.getRegionLocation(i) == null) {
80 return false;
81 }
82 }
83 return true;
84 } catch (Exception e) {
85 LOG.warn("Failed to get meta region locations", e);
86 return false;
87 }
88 }
89 });
90 }
91
92 @BeforeClass
93 public static void setUp() throws Exception {
94 TEST_UTIL.getConfiguration().setInt(HConstants.META_REPLICAS_NUM, 3);
95 TEST_UTIL.startMiniCluster(3);
96 REGISTRY = ConnectionRegistryFactory.getRegistry(TEST_UTIL.getConnection());
97 waitUntilAllMetaReplicasHavingRegionLocation(
98 TEST_UTIL.getConfiguration(), REGISTRY, 3);
99 TEST_UTIL.getConnection().getAdmin().setBalancerRunning(false, true);
100 }
101
102 @AfterClass
103 public static void cleanUp() throws Exception {
104 TEST_UTIL.shutdownMiniCluster();
105 }
106
107 private List<HRegionLocation> getCurrentMetaLocations(ZooKeeperWatcher zk) throws Exception {
108 List<HRegionLocation> result = new ArrayList<>();
109 for (String znode: zk.getMetaReplicaNodes()) {
110 String path = ZKUtil.joinZNode(zk.baseZNode, znode);
111 int replicaId = zk.getMetaReplicaIdFromPath(path);
112 RegionState state = MetaTableLocator.getMetaRegionState(zk, replicaId);
113 result.add(new HRegionLocation(state.getRegion(), state.getServerName()));
114 }
115 return result;
116 }
117
118
119 private void verifyCachedMetaLocations(final HMaster master) throws Exception {
120
121 ZooKeeperWatcher zk = master.getZooKeeper();
122 final List<String> metaZnodes = zk.getMetaReplicaNodes();
123 assertEquals(3, metaZnodes.size());
124 TEST_UTIL.waitFor(10000, new Waiter.Predicate<Exception>() {
125 @Override
126 public boolean evaluate() throws Exception {
127 return master.getMetaRegionLocationCache().getMetaRegionLocations().size()
128 == metaZnodes.size();
129 }
130 });
131 List<HRegionLocation> metaHRLs = master.getMetaRegionLocationCache().getMetaRegionLocations();
132 List<HRegionLocation> actualHRLs = getCurrentMetaLocations(zk);
133 Collections.sort(metaHRLs);
134 Collections.sort(actualHRLs);
135 assertEquals(actualHRLs, metaHRLs);
136 }
137
138 @Test public void testInitialMetaLocations() throws Exception {
139 verifyCachedMetaLocations(TEST_UTIL.getMiniHBaseCluster().getMaster());
140 }
141
142 @Test public void testStandByMetaLocations() throws Exception {
143 HMaster standBy = TEST_UTIL.getMiniHBaseCluster().startMaster().getMaster();
144 verifyCachedMetaLocations(standBy);
145 }
146
147 private static ServerName getOtherRS(List<ServerName> allServers, ServerName except) {
148 Preconditions.checkArgument(allServers.size() > 0);
149 allServers.remove(except);
150 ServerName ret;
151 try {
152 Collections.shuffle(allServers);
153 ret = allServers.get(0);
154 } finally {
155 allServers.add(except);
156 }
157 return ret;
158 }
159
160
161
162
163 @Test public void testMetaLocationsChange() throws Exception {
164 List<HRegionLocation> currentMetaLocs =
165 getCurrentMetaLocations(TEST_UTIL.getMiniHBaseCluster().getMaster().getZooKeeper());
166 List<ServerName> allServers = new ArrayList<>();
167 for (JVMClusterUtil.RegionServerThread rs:
168 TEST_UTIL.getMiniHBaseCluster().getRegionServerThreads()) {
169 allServers.add(rs.getRegionServer().getServerName());
170 }
171
172 for (HRegionLocation location: currentMetaLocs) {
173 TEST_UTIL.moveRegionAndWait(
174 location.getRegionInfo(), getOtherRS(allServers, location.getServerName()));
175 }
176 waitUntilAllMetaReplicasHavingRegionLocation(
177 TEST_UTIL.getConfiguration(), REGISTRY, 3);
178 for (JVMClusterUtil.MasterThread masterThread:
179 TEST_UTIL.getMiniHBaseCluster().getMasterThreads()) {
180 verifyCachedMetaLocations(masterThread.getMaster());
181 }
182 }
183
184
185
186
187
188 @Test public void testMetaRegionLocationCache() throws Exception {
189 final String parentZnodeName = "/randomznodename";
190 Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
191 conf.set(HConstants.ZOOKEEPER_ZNODE_PARENT, parentZnodeName);
192 ServerName sn = ServerName.valueOf("localhost", 1234, 5678);
193 try (ZooKeeperWatcher zkWatcher = new ZooKeeperWatcher(conf, null, null, true)) {
194
195
196 MultithreadedTestUtil.TestContext ctx = new MultithreadedTestUtil.TestContext(conf);
197 ctx.addThread(new MultithreadedTestUtil.RepeatingTestThread(ctx) {
198 @Override public void doAnAction() throws Exception {
199 final String testZnode = parentZnodeName + "/child";
200 ZKUtil.createNodeIfNotExistsAndWatch(zkWatcher, testZnode, testZnode.getBytes());
201 ZKUtil.deleteNode(zkWatcher, testZnode);
202 }
203 });
204 ctx.startThreads();
205 try {
206 MetaRegionLocationCache metaCache = new MetaRegionLocationCache(zkWatcher);
207
208 assertTrue(metaCache.getMetaRegionLocations().isEmpty());
209
210
211 for (int i = 0; i < 3; i++) {
212
213 MetaTableLocator.setMetaLocation(zkWatcher, sn, i, RegionState.State.OPEN);
214 }
215
216 int iters = 0;
217 while (iters++ < 10) {
218 if (metaCache.getMetaRegionLocations().size() == 3) {
219 break;
220 }
221 Thread.sleep(1000);
222 }
223 List<HRegionLocation> metaLocations = metaCache.getMetaRegionLocations();
224 assertNotNull(metaLocations);
225 assertEquals(3, metaLocations.size());
226 for (HRegionLocation location : metaLocations) {
227 assertEquals(sn, location.getServerName());
228 }
229 } finally {
230
231 ctx.stop();
232 ZKUtil.deleteChildrenRecursively(zkWatcher, parentZnodeName);
233 }
234 }
235 }
236 }