1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.zookeeper;
19
20 import org.apache.hadoop.hbase.classification.InterfaceAudience;
21 import org.apache.hadoop.hbase.Abortable;
22 import org.apache.hadoop.hbase.HConstants;
23 import org.apache.hadoop.hbase.HRegionInfo;
24 import org.apache.hadoop.hbase.exceptions.DeserializationException;
25 import org.apache.hadoop.hbase.ServerName;
26 import org.apache.hadoop.hbase.master.RegionState;
27 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
28 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
29 import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
30 import org.apache.zookeeper.KeeperException;
31
32 import com.google.common.base.Stopwatch;
33 import com.google.protobuf.InvalidProtocolBufferException;
34
35
36
37
38
39
40 @InterfaceAudience.Private
41 public class MetaRegionTracker extends ZooKeeperNodeTracker {
42
43
44
45
46
47
48
49
50 public MetaRegionTracker(ZooKeeperWatcher watcher, Abortable abortable) {
51 super(watcher, watcher.metaServerZNode, abortable);
52 }
53
54
55
56
57
58 public boolean isLocationAvailable() {
59 return getMetaRegionLocation() != null;
60 }
61
62
63
64
65
66
67 public ServerName getMetaRegionLocation() {
68 RegionState regionState = getMetaRegionState();
69 return regionState.isOpened() ? regionState.getServerName() : null;
70 }
71
72
73
74
75
76
77
78
79 public static ServerName getMetaRegionLocation(final ZooKeeperWatcher zkw) throws KeeperException {
80 byte[] data = ZKUtil.getData(zkw, zkw.metaServerZNode);
81 RegionState regionState = getMetaRegionState(data);
82 return regionState.isOpened() ? regionState.getServerName() : null;
83 }
84
85
86
87
88
89
90
91
92
93
94
95 public ServerName waitMetaRegionLocation(long timeout)
96 throws InterruptedException {
97 if (false == checkIfBaseNodeAvailable()) {
98 String errorMsg = "Check the value configured in 'zookeeper.znode.parent'. "
99 + "There could be a mismatch with the one configured in the master.";
100 LOG.error(errorMsg);
101 throw new IllegalArgumentException(errorMsg);
102 }
103 return blockUntilAvailable(timeout);
104
105 }
106
107
108
109
110
111
112
113
114 private ServerName blockUntilAvailable(final long timeout) throws InterruptedException {
115 if (timeout < 0) throw new IllegalArgumentException("Timeout shouldn't be less than zero");
116 Stopwatch sw = new Stopwatch().start();
117 ServerName sn = null;
118 try {
119 while (true) {
120 sn = getMetaRegionLocation();
121 if (sn != null || sw.elapsedMillis() > timeout - HConstants.SOCKET_RETRY_WAIT_MS) {
122 break;
123 }
124 Thread.sleep(HConstants.SOCKET_RETRY_WAIT_MS);
125 }
126 } finally {
127 sw.stop();
128 }
129 return sn;
130 }
131
132
133
134
135
136
137
138
139 public static void setMetaLocation(ZooKeeperWatcher zookeeper,
140 final ServerName location, final RegionState.State regionState)
141 throws KeeperException {
142 LOG.info("Setting hbase:meta region location in ZooKeeper as " + location);
143
144
145 byte [] data = toByteArray(location, regionState);
146 try {
147 ZKUtil.createAndWatch(zookeeper, zookeeper.metaServerZNode, data);
148 } catch(KeeperException.NodeExistsException nee) {
149 LOG.debug("META region location already existed, updated location");
150 ZKUtil.setData(zookeeper, zookeeper.metaServerZNode, data);
151 }
152 }
153
154
155
156
157
158
159 static byte [] toByteArray(final ServerName sn, final RegionState.State regionState) {
160
161 HBaseProtos.ServerName pbsn =
162 HBaseProtos.ServerName.newBuilder()
163 .setHostName(sn.getHostname())
164 .setPort(sn.getPort())
165 .setStartCode(sn.getStartcode())
166 .build();
167
168 ZooKeeperProtos.MetaRegionServer pbrsr =
169 ZooKeeperProtos.MetaRegionServer.newBuilder()
170 .setServer(pbsn)
171 .setRpcVersion(HConstants.RPC_CURRENT_VERSION)
172 .setState(regionState.convert())
173 .build();
174 return ProtobufUtil.prependPBMagic(pbrsr.toByteArray());
175 }
176
177
178
179
180
181
182 public static void deleteMetaLocation(ZooKeeperWatcher zookeeper)
183 throws KeeperException {
184 LOG.info("Unsetting hbase:meta region location in ZooKeeper");
185 try {
186
187 ZKUtil.deleteNode(zookeeper, zookeeper.metaServerZNode);
188 } catch(KeeperException.NoNodeException nne) {
189
190 }
191 }
192
193
194
195
196
197
198
199
200 public static ServerName blockUntilAvailable(final ZooKeeperWatcher zkw,
201 final long timeout)
202 throws InterruptedException {
203 byte [] data = ZKUtil.blockUntilAvailable(zkw, zkw.metaServerZNode, timeout);
204 RegionState regionState = getMetaRegionState(data);
205 return regionState.isOpened() ? regionState.getServerName() : null;
206 }
207
208
209 private static RegionState getMetaRegionState(byte[] data) {
210 RegionState.State state = RegionState.State.OPEN;
211 ServerName serverName = null;
212 try {
213 if (data != null && data.length > 0 && ProtobufUtil.isPBMagicPrefix(data)) {
214 try {
215 int prefixLen = ProtobufUtil.lengthOfPBMagic();
216 ZooKeeperProtos.MetaRegionServer rl =
217 ZooKeeperProtos.MetaRegionServer.PARSER.parseFrom(data, prefixLen, data.length
218 - prefixLen);
219 if (rl.hasState()) {
220 state = RegionState.State.convert(rl.getState());
221 }
222 HBaseProtos.ServerName sn = rl.getServer();
223 serverName = ServerName.valueOf(sn.getHostName(), sn.getPort(), sn.getStartCode());
224 } catch (InvalidProtocolBufferException e) {
225 throw new DeserializationException("Unable to parse root region location");
226 }
227 } else {
228
229 serverName = ServerName.parseFrom(data);
230 }
231 } catch (DeserializationException e) {
232 LOG.warn("Failed parse", e);
233 return null;
234 }
235 if (serverName == null) {
236 state = RegionState.State.OFFLINE;
237 }
238 return new RegionState(HRegionInfo.FIRST_META_REGIONINFO, state, serverName);
239 }
240
241
242
243
244
245 public RegionState getMetaRegionState() {
246 byte[] data = super.getData(true);
247 return getMetaRegionState(data);
248 }
249 }