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