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) {
77 Cell cell = r.getColumnLatestCell(HConstants.CATALOG_FAMILY, getServerNameColumn(replicaId));
78 if (cell == null || cell.getValueLength() == 0) {
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 private 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) {
105 Cell cell = r.getColumnLatestCell(HConstants.CATALOG_FAMILY, getStateColumn(replicaId));
106 if (cell == null || cell.getValueLength() == 0) return State.OPEN;
107 return State.valueOf(Bytes.toString(cell.getValueArray(),
108 cell.getValueOffset(), cell.getValueLength()));
109 }
110
111 private static byte[] getStateColumn(int replicaId) {
112 return replicaId == 0
113 ? HConstants.STATE_QUALIFIER
114 : Bytes.toBytes(HConstants.STATE_QUALIFIER_STR + META_REPLICA_ID_DELIMITER
115 + String.format(HRegionInfo.REPLICA_ID_FORMAT, replicaId));
116 }
117
118
119
120
121
122
123
124
125
126
127 private boolean shouldPersistStateChange(
128 HRegionInfo hri, RegionState state, RegionState oldState) {
129 return !hri.isMetaRegion() && !RegionStates.isOneOfStates(
130 state, State.MERGING_NEW, State.SPLITTING_NEW, State.MERGED)
131 && !(RegionStates.isOneOfStates(state, State.OFFLINE)
132 && RegionStates.isOneOfStates(oldState, State.MERGING_NEW,
133 State.SPLITTING_NEW, State.MERGED));
134 }
135
136 RegionStateStore(final Server server) {
137 Configuration conf = server.getConfiguration();
138
139 noPersistence = ConfigUtil.useZKForAssignment(conf)
140 && !conf.getBoolean("hbase.assignment.usezk.migrating", false);
141 this.server = server;
142 initialized = false;
143 }
144
145 void start() throws IOException {
146 if (!noPersistence) {
147 if (server instanceof RegionServerServices) {
148 metaRegion = ((RegionServerServices)server).getFromOnlineRegions(
149 HRegionInfo.FIRST_META_REGIONINFO.getEncodedName());
150 }
151 if (metaRegion == null) {
152 Configuration conf = server.getConfiguration();
153
154
155
156
157 multiHConnection =
158 new MultiHConnection(conf, conf.getInt("hbase.regionstatestore.meta.connection", 1));
159 }
160 }
161 initialized = true;
162 }
163
164 void stop() {
165 initialized = false;
166 if (multiHConnection != null) {
167 multiHConnection.close();
168 }
169 }
170
171 void updateRegionState(long openSeqNum,
172 RegionState newState, RegionState oldState) {
173
174 if (noPersistence) {
175 return;
176 }
177
178 HRegionInfo hri = newState.getRegion();
179 try {
180
181
182 if (hri.isMetaRegion()) {
183
184 try {
185 MetaTableLocator.setMetaLocation(server.getZooKeeper(),
186 newState.getServerName(), hri.getReplicaId(), newState.getState());
187 return;
188 } catch (KeeperException e) {
189 throw new IOException("Failed to update meta ZNode", e);
190 }
191 }
192
193 if (!initialized || !shouldPersistStateChange(hri, newState, oldState)) {
194 return;
195 }
196
197 ServerName oldServer = oldState != null ? oldState.getServerName() : null;
198 ServerName serverName = newState.getServerName();
199 State state = newState.getState();
200
201 int replicaId = hri.getReplicaId();
202 Put put = new Put(MetaTableAccessor.getMetaKeyForRegion(hri));
203 StringBuilder info = new StringBuilder("Updating row ");
204 info.append(hri.getRegionNameAsString()).append(" with state=").append(state);
205 if (serverName != null && !serverName.equals(oldServer)) {
206 put.addImmutable(HConstants.CATALOG_FAMILY, getServerNameColumn(replicaId),
207 Bytes.toBytes(serverName.getServerName()));
208 info.append("&sn=").append(serverName);
209 }
210 if (openSeqNum >= 0) {
211 Preconditions.checkArgument(state == State.OPEN
212 && serverName != null, "Open region should be on a server");
213 MetaTableAccessor.addLocation(put, serverName, openSeqNum, -1, replicaId);
214 info.append("&openSeqNum=").append(openSeqNum);
215 info.append("&server=").append(serverName);
216 }
217 put.addImmutable(HConstants.CATALOG_FAMILY, getStateColumn(replicaId),
218 Bytes.toBytes(state.name()));
219 LOG.info(info);
220
221
222 if (metaRegion != null) {
223 try {
224
225
226 metaRegion.put(put);
227 return;
228 } catch (Throwable t) {
229
230
231
232
233 synchronized (this) {
234 if (metaRegion != null) {
235 LOG.info("Meta region shortcut failed", t);
236 if (multiHConnection == null) {
237 multiHConnection = new MultiHConnection(server.getConfiguration(), 1);
238 }
239 metaRegion = null;
240 }
241 }
242 }
243 }
244
245 multiHConnection.processBatchCallback(Arrays.asList(put), TableName.META_TABLE_NAME, null, null);
246
247 } catch (IOException ioe) {
248 LOG.error("Failed to persist region state " + newState, ioe);
249 server.abort("Failed to update region location", ioe);
250 }
251 }
252
253 void splitRegion(HRegionInfo p,
254 HRegionInfo a, HRegionInfo b, ServerName sn, int regionReplication) throws IOException {
255 MetaTableAccessor.splitRegion(server.getConnection(), p, a, b, sn, regionReplication);
256 }
257
258 void mergeRegions(HRegionInfo p,
259 HRegionInfo a, HRegionInfo b, ServerName sn, int regionReplication) throws IOException {
260 MetaTableAccessor.mergeRegions(server.getConnection(), p, a, b, sn, regionReplication,
261 EnvironmentEdgeManager.currentTime());
262 }
263 }