HBASE-3837 Show regions in transition on the master web page
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1099199 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
46d64afcd9
commit
7d5d1fe752
|
@ -236,6 +236,7 @@ Release 0.91.0 - Unreleased
|
|||
(Prakash Khemani)
|
||||
HBASE-3836 Add facility to track currently progressing actions and
|
||||
workflows. (todd)
|
||||
HBASE-3837 Show regions in transition on the master web page (todd)
|
||||
|
||||
Release 0.90.3 - Unreleased
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<%doc>
|
||||
Copyright 2011 The Apache Software Foundation
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
</%doc>
|
||||
<%import>
|
||||
org.apache.hadoop.hbase.master.AssignmentManager;
|
||||
org.apache.hadoop.hbase.master.AssignmentManager.RegionState;
|
||||
java.util.Map;
|
||||
</%import>
|
||||
<%args>
|
||||
AssignmentManager assignmentManager;
|
||||
</%args>
|
||||
<%java>
|
||||
Map<String, RegionState> rit = assignmentManager.getRegionsInTransition();
|
||||
</%java>
|
||||
|
||||
<h2>Regions in Transition</h2>
|
||||
<%if rit.isEmpty() %>
|
||||
No regions in transition.
|
||||
<%else>
|
||||
<table>
|
||||
<tr><th>Region</th><th>State</th></tr>
|
||||
<%for Map.Entry<String, RegionState> entry : rit.entrySet() %>
|
||||
<tr><td><% entry.getKey() %></td><td><% entry.getValue() %></td>
|
||||
</%for>
|
||||
</table>
|
||||
</%if>
|
|
@ -97,6 +97,9 @@ org.apache.hadoop.hbase.HTableDescriptor;
|
|||
<%if (servers != null) %>
|
||||
<& regionServers &>
|
||||
</%if>
|
||||
|
||||
<& AssignmentManagerStatusTmpl; assignmentManager=master.getAssignmentManager()&>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -332,20 +332,23 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
// Just insert region into RIT.
|
||||
// If this never updates the timeout will trigger new assignment
|
||||
regionsInTransition.put(encodedRegionName, new RegionState(
|
||||
regionInfo, RegionState.State.CLOSING, data.getStamp()));
|
||||
regionInfo, RegionState.State.CLOSING,
|
||||
data.getStamp(), data.getOrigin()));
|
||||
break;
|
||||
|
||||
case RS_ZK_REGION_CLOSED:
|
||||
// Region is closed, insert into RIT and handle it
|
||||
regionsInTransition.put(encodedRegionName, new RegionState(
|
||||
regionInfo, RegionState.State.CLOSED, data.getStamp()));
|
||||
regionInfo, RegionState.State.CLOSED,
|
||||
data.getStamp(), data.getOrigin()));
|
||||
new ClosedRegionHandler(master, this, regionInfo).process();
|
||||
break;
|
||||
|
||||
case M_ZK_REGION_OFFLINE:
|
||||
// Region is offline, insert into RIT and handle it like a closed
|
||||
regionsInTransition.put(encodedRegionName, new RegionState(
|
||||
regionInfo, RegionState.State.OFFLINE, data.getStamp()));
|
||||
regionInfo, RegionState.State.OFFLINE,
|
||||
data.getStamp(), data.getOrigin()));
|
||||
new ClosedRegionHandler(master, this, regionInfo).process();
|
||||
break;
|
||||
|
||||
|
@ -353,13 +356,15 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
// Just insert region into RIT
|
||||
// If this never updates the timeout will trigger new assignment
|
||||
regionsInTransition.put(encodedRegionName, new RegionState(
|
||||
regionInfo, RegionState.State.OPENING, data.getStamp()));
|
||||
regionInfo, RegionState.State.OPENING,
|
||||
data.getStamp(), data.getOrigin()));
|
||||
break;
|
||||
|
||||
case RS_ZK_REGION_OPENED:
|
||||
// Region is opened, insert into RIT and handle it
|
||||
regionsInTransition.put(encodedRegionName, new RegionState(
|
||||
regionInfo, RegionState.State.OPENING, data.getStamp()));
|
||||
regionInfo, RegionState.State.OPENING,
|
||||
data.getStamp(), data.getOrigin()));
|
||||
ServerName sn =
|
||||
data.getOrigin() == null? null: data.getOrigin();
|
||||
// hsi could be null if this server is no longer online. If
|
||||
|
@ -422,7 +427,7 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
|
||||
case RS_ZK_REGION_SPLITTING:
|
||||
if (!isInStateForSplitting(regionState)) break;
|
||||
addSplittingToRIT(sn.toString(), encodedName);
|
||||
addSplittingToRIT(sn, encodedName);
|
||||
break;
|
||||
|
||||
case RS_ZK_REGION_SPLIT:
|
||||
|
@ -433,7 +438,7 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
LOG.info("Received SPLIT for region " + prettyPrintedRegionName +
|
||||
" from server " + sn +
|
||||
" but region was not first in SPLITTING state; continuing");
|
||||
addSplittingToRIT(sn.toString(), encodedName);
|
||||
addSplittingToRIT(sn, encodedName);
|
||||
}
|
||||
// Check it has daughters.
|
||||
byte [] payload = data.getPayload();
|
||||
|
@ -468,7 +473,8 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
return;
|
||||
}
|
||||
// Transition to CLOSING (or update stamp if already CLOSING)
|
||||
regionState.update(RegionState.State.CLOSING, data.getStamp());
|
||||
regionState.update(RegionState.State.CLOSING,
|
||||
data.getStamp(), data.getOrigin());
|
||||
break;
|
||||
|
||||
case RS_ZK_REGION_CLOSED:
|
||||
|
@ -484,7 +490,8 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
// Handle CLOSED by assigning elsewhere or stopping if a disable
|
||||
// If we got here all is good. Need to update RegionState -- else
|
||||
// what follows will fail because not in expected state.
|
||||
regionState.update(RegionState.State.CLOSED, data.getStamp());
|
||||
regionState.update(RegionState.State.CLOSED,
|
||||
data.getStamp(), data.getOrigin());
|
||||
this.executorService.submit(new ClosedRegionHandler(master,
|
||||
this, regionState.getRegion()));
|
||||
break;
|
||||
|
@ -502,7 +509,8 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
return;
|
||||
}
|
||||
// Transition to OPENING (or update stamp if already OPENING)
|
||||
regionState.update(RegionState.State.OPENING, data.getStamp());
|
||||
regionState.update(RegionState.State.OPENING,
|
||||
data.getStamp(), data.getOrigin());
|
||||
break;
|
||||
|
||||
case RS_ZK_REGION_OPENED:
|
||||
|
@ -517,7 +525,8 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
return;
|
||||
}
|
||||
// Handle OPENED by removing from transition and deleted zk node
|
||||
regionState.update(RegionState.State.OPEN, data.getStamp());
|
||||
regionState.update(RegionState.State.OPEN,
|
||||
data.getStamp(), data.getOrigin());
|
||||
this.executorService.submit(
|
||||
new OpenedRegionHandler(master, this, regionState.getRegion(),
|
||||
data.getOrigin()));
|
||||
|
@ -564,12 +573,13 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
* @return The SPLITTING RegionState we added to RIT for the passed region
|
||||
* <code>encodedName</code>
|
||||
*/
|
||||
private RegionState addSplittingToRIT(final String serverName,
|
||||
private RegionState addSplittingToRIT(final ServerName serverName,
|
||||
final String encodedName) {
|
||||
RegionState regionState = null;
|
||||
synchronized (this.regions) {
|
||||
regionState = findHRegionInfoThenAddToRIT(serverName, encodedName);
|
||||
regionState.update(RegionState.State.SPLITTING);
|
||||
regionState.update(RegionState.State.SPLITTING,
|
||||
System.currentTimeMillis(), serverName);
|
||||
}
|
||||
return regionState;
|
||||
}
|
||||
|
@ -580,7 +590,7 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
* @param encodedName
|
||||
* @return The instance of RegionState that was added to RIT or null if error.
|
||||
*/
|
||||
private RegionState findHRegionInfoThenAddToRIT(final String serverName,
|
||||
private RegionState findHRegionInfoThenAddToRIT(final ServerName serverName,
|
||||
final String encodedName) {
|
||||
HRegionInfo hri = findHRegionInfo(serverName, encodedName);
|
||||
if (hri == null) {
|
||||
|
@ -598,9 +608,8 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
* @param encodedName
|
||||
* @return Found HRegionInfo or null.
|
||||
*/
|
||||
private HRegionInfo findHRegionInfo(final String serverName,
|
||||
private HRegionInfo findHRegionInfo(final ServerName sn,
|
||||
final String encodedName) {
|
||||
ServerName sn = new ServerName(serverName);
|
||||
if (!this.serverManager.isServerOnline(sn)) return null;
|
||||
List<HRegionInfo> hris = this.servers.get(sn);
|
||||
HRegionInfo foundHri = null;
|
||||
|
@ -824,7 +833,7 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
}
|
||||
if (rs == null) continue;
|
||||
synchronized (rs) {
|
||||
rs.update(rs.getState());
|
||||
rs.updateTimestampToNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1028,7 +1037,7 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
// Async exists to set a watcher so we'll get triggered when
|
||||
// unassigned node changes.
|
||||
this.zkw.getZooKeeper().exists(path, this.zkw,
|
||||
new ExistsUnassignedAsyncCallback(this.counter), ctx);
|
||||
new ExistsUnassignedAsyncCallback(this.counter, destination), ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1039,9 +1048,11 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
static class ExistsUnassignedAsyncCallback implements AsyncCallback.StatCallback {
|
||||
private final Log LOG = LogFactory.getLog(ExistsUnassignedAsyncCallback.class);
|
||||
private final AtomicInteger counter;
|
||||
private ServerName destination;
|
||||
|
||||
ExistsUnassignedAsyncCallback(final AtomicInteger counter) {
|
||||
ExistsUnassignedAsyncCallback(final AtomicInteger counter, ServerName destination) {
|
||||
this.counter = counter;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1059,7 +1070,7 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
// yet sent out the actual open but putting this state change after the
|
||||
// call to open risks our writing PENDING_OPEN after state has been moved
|
||||
// to OPENING by the regionserver.
|
||||
state.update(RegionState.State.PENDING_OPEN);
|
||||
state.update(RegionState.State.PENDING_OPEN, System.currentTimeMillis(), destination);
|
||||
this.counter.addAndGet(1);
|
||||
}
|
||||
}
|
||||
|
@ -1113,7 +1124,8 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
LOG.debug("Assigning region " + state.getRegion().getRegionNameAsString() +
|
||||
" to " + plan.getDestination().toString());
|
||||
// Transition RegionState to PENDING_OPEN
|
||||
state.update(RegionState.State.PENDING_OPEN);
|
||||
state.update(RegionState.State.PENDING_OPEN, System.currentTimeMillis(),
|
||||
plan.getDestination());
|
||||
// Send OPEN RPC. This can fail if the server on other end is is not up.
|
||||
serverManager.sendRegionOpen(plan.getDestination(), state.getRegion());
|
||||
break;
|
||||
|
@ -2151,27 +2163,35 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
|
||||
private State state;
|
||||
private long stamp;
|
||||
private ServerName serverName;
|
||||
|
||||
public RegionState() {}
|
||||
|
||||
RegionState(HRegionInfo region, State state) {
|
||||
this(region, state, System.currentTimeMillis());
|
||||
this(region, state, System.currentTimeMillis(), null);
|
||||
}
|
||||
|
||||
RegionState(HRegionInfo region, State state, long stamp) {
|
||||
RegionState(HRegionInfo region, State state, long stamp, ServerName serverName) {
|
||||
this.region = region;
|
||||
this.state = state;
|
||||
this.stamp = stamp;
|
||||
this.serverName = serverName;
|
||||
}
|
||||
|
||||
public void update(State state, long stamp) {
|
||||
public void update(State state, long stamp, ServerName serverName) {
|
||||
this.state = state;
|
||||
this.stamp = stamp;
|
||||
this.serverName = serverName;
|
||||
}
|
||||
|
||||
public void update(State state) {
|
||||
this.state = state;
|
||||
this.stamp = System.currentTimeMillis();
|
||||
this.serverName = null;
|
||||
}
|
||||
|
||||
public void updateTimestampToNow() {
|
||||
this.stamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
|
@ -2224,8 +2244,10 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return region.getRegionNameAsString() + " state=" + state +
|
||||
", ts=" + stamp;
|
||||
return region.getRegionNameAsString()
|
||||
+ " state=" + state
|
||||
+ ", ts=" + stamp
|
||||
+ ", server=" + serverName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -808,13 +808,13 @@ public class TestMasterFailover {
|
|||
region = enabledRegions.remove(0);
|
||||
regionsThatShouldBeOnline.add(region);
|
||||
master.assignmentManager.regionsInTransition.put(region.getEncodedName(),
|
||||
new RegionState(region, RegionState.State.PENDING_OPEN, 0));
|
||||
new RegionState(region, RegionState.State.PENDING_OPEN, 0, null));
|
||||
ZKAssign.createNodeOffline(zkw, region, master.getServerName());
|
||||
// PENDING_OPEN and disabled
|
||||
region = disabledRegions.remove(0);
|
||||
regionsThatShouldBeOffline.add(region);
|
||||
master.assignmentManager.regionsInTransition.put(region.getEncodedName(),
|
||||
new RegionState(region, RegionState.State.PENDING_OPEN, 0));
|
||||
new RegionState(region, RegionState.State.PENDING_OPEN, 0, null));
|
||||
ZKAssign.createNodeOffline(zkw, region, master.getServerName());
|
||||
// This test is bad. It puts up a PENDING_CLOSE but doesn't say what
|
||||
// server we were PENDING_CLOSE against -- i.e. an entry in
|
||||
|
|
|
@ -22,14 +22,18 @@ package org.apache.hadoop.hbase.master;
|
|||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
import java.util.NavigableMap;
|
||||
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.hbase.HBaseConfiguration;
|
||||
import org.apache.hadoop.hbase.HRegionInfo;
|
||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||
import org.apache.hadoop.hbase.ServerName;
|
||||
import org.apache.hadoop.hbase.client.HBaseAdmin;
|
||||
import org.apache.hadoop.hbase.master.AssignmentManager.RegionState;
|
||||
import org.apache.hadoop.hbase.master.HMaster;
|
||||
import org.apache.hadoop.hbase.master.ServerManager;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
|
||||
import org.apache.hbase.tmpl.master.MasterStatusTmpl;
|
||||
import org.junit.Before;
|
||||
|
@ -37,6 +41,7 @@ import org.junit.Test;
|
|||
import org.mockito.Mockito;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* Tests for the master status page and its template.
|
||||
|
@ -47,13 +52,19 @@ public class TestMasterStatusServlet {
|
|||
private Configuration conf;
|
||||
private HBaseAdmin admin;
|
||||
|
||||
static final ServerName FAKE_HOST =
|
||||
new ServerName("fakehost", 12345, 1234567890);
|
||||
static final HTableDescriptor FAKE_TABLE =
|
||||
new HTableDescriptor("mytable");
|
||||
static final HRegionInfo FAKE_REGION =
|
||||
new HRegionInfo(FAKE_TABLE, Bytes.toBytes("a"), Bytes.toBytes("b"));
|
||||
|
||||
@Before
|
||||
public void setupBasicMocks() {
|
||||
conf = HBaseConfiguration.create();
|
||||
|
||||
master = Mockito.mock(HMaster.class);
|
||||
Mockito.doReturn(new ServerName("fakehost", 12345, 1234567890))
|
||||
.when(master).getServerName();
|
||||
Mockito.doReturn(FAKE_HOST).when(master).getServerName();
|
||||
Mockito.doReturn(conf).when(master).getConfiguration();
|
||||
|
||||
// Fake serverManager
|
||||
|
@ -61,6 +72,15 @@ public class TestMasterStatusServlet {
|
|||
Mockito.doReturn(1.0).when(serverManager).getAverageLoad();
|
||||
Mockito.doReturn(serverManager).when(master).getServerManager();
|
||||
|
||||
// Fake AssignmentManager and RIT
|
||||
AssignmentManager am = Mockito.mock(AssignmentManager.class);
|
||||
NavigableMap<String, RegionState> regionsInTransition =
|
||||
Maps.newTreeMap();
|
||||
regionsInTransition.put("r1",
|
||||
new RegionState(FAKE_REGION, RegionState.State.CLOSING, 12345L, FAKE_HOST));
|
||||
Mockito.doReturn(regionsInTransition).when(am).getRegionsInTransition();
|
||||
Mockito.doReturn(am).when(master).getAssignmentManager();
|
||||
|
||||
// Fake ZKW
|
||||
ZooKeeperWatcher zkw = Mockito.mock(ZooKeeperWatcher.class);
|
||||
Mockito.doReturn("fakequorum").when(zkw).getQuorum();
|
||||
|
|
Loading…
Reference in New Issue