1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.master;
19
20 import java.io.IOException;
21 import java.util.Arrays;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.hadoop.hbase.classification.InterfaceAudience;
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.hbase.Cell;
28 import org.apache.hadoop.hbase.HConstants;
29 import org.apache.hadoop.hbase.HRegionInfo;
30 import org.apache.hadoop.hbase.HRegionLocation;
31 import org.apache.hadoop.hbase.RegionLocations;
32 import org.apache.hadoop.hbase.Server;
33 import org.apache.hadoop.hbase.ServerName;
34 import org.apache.hadoop.hbase.TableName;
35 import org.apache.hadoop.hbase.MetaTableAccessor;
36 import org.apache.hadoop.hbase.client.Put;
37 import org.apache.hadoop.hbase.client.Result;
38 import org.apache.hadoop.hbase.master.RegionState.State;
39 import org.apache.hadoop.hbase.regionserver.HRegion;
40 import org.apache.hadoop.hbase.regionserver.RegionServerServices;
41 import org.apache.hadoop.hbase.util.Bytes;
42 import org.apache.hadoop.hbase.util.ConfigUtil;
43 import org.apache.hadoop.hbase.util.MultiHConnection;
44 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
45 import org.apache.zookeeper.KeeperException;
46
47 import com.google.common.base.Preconditions;
48
49
50
51
52
53 @InterfaceAudience.Private
54 public class RegionStateStore {
55 private static final Log LOG = LogFactory.getLog(RegionStateStore.class);
56
57
58 protected static final char META_REPLICA_ID_DELIMITER = '_';
59
60 private volatile HRegion metaRegion;
61 private MultiHConnection multiHConnection;
62 private volatile boolean initialized;
63
64 private final boolean noPersistence;
65 private final Server server;
66
67
68
69
70
71
72
73
74
75 static ServerName getRegionServer(final Result r, int replicaId) {
76 Cell cell = r.getColumnLatestCell(HConstants.CATALOG_FAMILY, getServerNameColumn(replicaId));
77 if (cell == null || cell.getValueLength() == 0) {
78 RegionLocations locations = MetaTableAccessor.getRegionLocations(r);
79 if (locations != null) {
80 HRegionLocation location = locations.getRegionLocation(replicaId);
81 if (location != null) {
82 return location.getServerName();
83 }
84 }
85 return null;
86 }
87 return ServerName.parseServerName(Bytes.toString(cell.getValueArray(),
88 cell.getValueOffset(), cell.getValueLength()));
89 }
90
91 private static byte[] getServerNameColumn(int replicaId) {
92 return replicaId == 0
93 ? HConstants.SERVERNAME_QUALIFIER
94 : Bytes.toBytes(HConstants.SERVERNAME_QUALIFIER_STR + META_REPLICA_ID_DELIMITER
95 + String.format(HRegionInfo.REPLICA_ID_FORMAT, replicaId));
96 }
97
98
99
100
101
102
103 static State getRegionState(final Result r, int replicaId) {
104 Cell cell = r.getColumnLatestCell(HConstants.CATALOG_FAMILY, getStateColumn(replicaId));
105 if (cell == null || cell.getValueLength() == 0) return State.OPEN;
106 return State.valueOf(Bytes.toString(cell.getValueArray(),
107 cell.getValueOffset(), cell.getValueLength()));
108 }
109
110 private static byte[] getStateColumn(int replicaId) {
111 return replicaId == 0
112 ? HConstants.STATE_QUALIFIER
113 : Bytes.toBytes(HConstants.STATE_QUALIFIER_STR + META_REPLICA_ID_DELIMITER
114 + String.format(HRegionInfo.REPLICA_ID_FORMAT, replicaId));
115 }
116
117
118
119
120
121
122
123
124
125
126 private boolean shouldPersistStateChange(
127 HRegionInfo hri, RegionState state, RegionState oldState) {
128 return !hri.isMetaRegion() && !RegionStates.isOneOfStates(
129 state, State.MERGING_NEW, State.SPLITTING_NEW, State.MERGED)
130 && !(RegionStates.isOneOfStates(state, State.OFFLINE)
131 && RegionStates.isOneOfStates(oldState, State.MERGING_NEW,
132 State.SPLITTING_NEW, State.MERGED));
133 }
134
135 RegionStateStore(final Server server) {
136 Configuration conf = server.getConfiguration();
137
138 noPersistence = ConfigUtil.useZKForAssignment(conf)
139 && !conf.getBoolean("hbase.assignment.usezk.migrating", false);
140 this.server = server;
141 initialized = false;
142 }
143
144 void start() throws IOException {
145 if (!noPersistence) {
146 if (server instanceof RegionServerServices) {
147 metaRegion = ((RegionServerServices)server).getFromOnlineRegions(
148 HRegionInfo.FIRST_META_REGIONINFO.getEncodedName());
149 }
150 if (metaRegion == null) {
151 Configuration conf = server.getConfiguration();
152
153
154
155
156 multiHConnection =
157 new MultiHConnection(conf, conf.getInt("hbase.regionstatestore.meta.connection", 1));
158 }
159 }
160 initialized = true;
161 }
162
163 void stop() {
164 initialized = false;
165 if (multiHConnection != null) {
166 multiHConnection.close();
167 }
168 }
169
170 void updateRegionState(long openSeqNum,
171 RegionState newState, RegionState oldState) {
172
173 if (noPersistence) {
174 return;
175 }
176
177 HRegionInfo hri = newState.getRegion();
178 try {
179
180
181 if (hri.isMetaRegion()) {
182
183 try {
184 MetaTableLocator.setMetaLocation(server.getZooKeeper(),
185 newState.getServerName(), newState.getState());
186 return;
187 } catch (KeeperException e) {
188 throw new IOException("Failed to update meta ZNode", e);
189 }
190 }
191
192 if (!initialized || !shouldPersistStateChange(hri, newState, oldState)) {
193 return;
194 }
195
196 ServerName oldServer = oldState != null ? oldState.getServerName() : null;
197 ServerName serverName = newState.getServerName();
198 State state = newState.getState();
199
200 int replicaId = hri.getReplicaId();
201 Put put = new Put(MetaTableAccessor.getMetaKeyForRegion(hri));
202 StringBuilder info = new StringBuilder("Updating row ");
203 info.append(hri.getRegionNameAsString()).append(" with state=").append(state);
204 if (serverName != null && !serverName.equals(oldServer)) {
205 put.addImmutable(HConstants.CATALOG_FAMILY, getServerNameColumn(replicaId),
206 Bytes.toBytes(serverName.getServerName()));
207 info.append("&sn=").append(serverName);
208 }
209 if (openSeqNum >= 0) {
210 Preconditions.checkArgument(state == State.OPEN
211 && serverName != null, "Open region should be on a server");
212 MetaTableAccessor.addLocation(put, serverName, openSeqNum, replicaId);
213 info.append("&openSeqNum=").append(openSeqNum);
214 info.append("&server=").append(serverName);
215 }
216 put.addImmutable(HConstants.CATALOG_FAMILY, getStateColumn(replicaId),
217 Bytes.toBytes(state.name()));
218 LOG.info(info);
219
220
221 if (metaRegion != null) {
222 try {
223
224
225 metaRegion.put(put);
226 return;
227 } catch (Throwable t) {
228
229
230
231
232 synchronized (this) {
233 if (metaRegion != null) {
234 LOG.info("Meta region shortcut failed", t);
235 if (multiHConnection == null) {
236 multiHConnection = new MultiHConnection(server.getConfiguration(), 1);
237 }
238 metaRegion = null;
239 }
240 }
241 }
242 }
243
244 multiHConnection.processBatchCallback(Arrays.asList(put), TableName.META_TABLE_NAME, null, null);
245
246 } catch (IOException ioe) {
247 LOG.error("Failed to persist region state " + newState, ioe);
248 server.abort("Failed to update region location", ioe);
249 }
250 }
251
252 void splitRegion(HRegionInfo p,
253 HRegionInfo a, HRegionInfo b, ServerName sn) throws IOException {
254 MetaTableAccessor.splitRegion(server.getConnection(), p, a, b, sn);
255 }
256
257 void mergeRegions(HRegionInfo p,
258 HRegionInfo a, HRegionInfo b, ServerName sn) throws IOException {
259 MetaTableAccessor.mergeRegions(server.getConnection(), p, a, b, sn);
260 }
261 }