diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java index 726595b..6c804c2 100644 --- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java +++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java @@ -679,6 +679,7 @@ public class HttpServer implements FilterContainer { addServlet("jmx", "/jmx", JMXJsonServlet.class); addServlet("conf", "/conf", ConfServlet.class); + addServlet("regionstates", "/regionstates", RegionStatesJsonServlet.class); } /** diff --git a/hbase-server/src/main/resources/hbase-webapps/master/table.jsp b/hbase-server/src/main/resources/hbase-webapps/master/table.jsp index 6856781..c191482 100644 --- a/hbase-server/src/main/resources/hbase-webapps/master/table.jsp +++ b/hbase-server/src/main/resources/hbase-webapps/master/table.jsp @@ -24,6 +24,7 @@ import="java.util.Collection" import="java.util.Collections" import="java.util.Comparator" + import="java.util.HashMap" import="java.util.LinkedHashMap" import="java.util.List" import="java.util.Map" @@ -47,6 +48,8 @@ import="org.apache.hadoop.hbase.client.RegionReplicaUtil" import="org.apache.hadoop.hbase.client.Table" import="org.apache.hadoop.hbase.master.HMaster" + import="org.apache.hadoop.hbase.master.assignment.RegionStates" + import="org.apache.hadoop.hbase.master.RegionState" import="org.apache.hadoop.hbase.quotas.QuotaTableUtil" import="org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot" import="org.apache.hadoop.hbase.util.Bytes" @@ -294,6 +297,14 @@ if ( fqtn != null ) { <%} else { Admin admin = master.getConnection().getAdmin(); + RegionStates states = master.getAssignmentManager().getRegionStates(); + Map> regionStates = states.getRegionByStateOfTable(table.getName()); + Map stateMap = new HashMap<>(); + for (RegionState.State regionState : regionStates.keySet()) { + for (HRegionInfo regionInfo : regionStates.get(regionState)) { + stateMap.put(regionInfo, regionState); + } + } RegionLocator r = master.getClusterConnection().getRegionLocator(table.getName()); try { %>

Table Attributes

@@ -481,6 +492,7 @@ Sort As + Ascending ShowDetailName&Start/End Key @@ -499,6 +511,7 @@ ShowDetailName&Start/End Key>() { + public int compare( + Map.Entry entry1, + Map.Entry entry2) { + if (entry1 == null || entry1.getKey()==null) { + return -1; + } else if (entry2 == null || entry2.getKey()==null) { + return 1; + } + int result = 0; + result = stateMap.get(entry1.getKey()).compareTo(stateMap.get(entry2.getKey())); + if (reverseOrder) { + result = -1 * result; + } + return result; + } + }); } } numRegions = regions.size(); @@ -677,6 +709,7 @@ ShowDetailName&Start/End Key <%= escapeXml(showWhole?Bytes.toStringBinary(regionInfo.getEndKey()):"-")%> + <%= state%> <% if (withReplica) { %> diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/RegionStatesJsonServlet.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/RegionStatesJsonServlet.java new file mode 100644 index 0000000..e74c1e9 --- /dev/null +++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/RegionStatesJsonServlet.java @@ -0,0 +1,100 @@ +/* + * 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. + */ + +package org.apache.hadoop.hbase.http; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.classification.InterfaceAudience; +import org.apache.hadoop.hbase.master.HMaster; +import org.apache.hadoop.hbase.master.RegionState; +import org.apache.hadoop.hbase.master.assignment.RegionStates; +import org.apache.hadoop.hbase.util.JsonMapper; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.*; + +@InterfaceAudience.Public +/** + * Provides Read only web access to the states of the regions. + * + * This servlet can be accessed under the /regionstates URL in master. It provides read only + * access to the states of all tables. With an optional parameter "table", the states could be + * filtered to a specific table. + */ +public class RegionStatesJsonServlet extends HttpServlet { + private static final Log LOG = LogFactory.getLog(RegionStatesJsonServlet.class); + + private static final long serialVersionUID = 1L; + + /** + * Initialize this servlet. + */ + @Override + public void init() throws ServletException { + } + + /** + * Process a GET request for the specified resource. + * + * @param request + * The servlet request we are processing + * @param response + * The servlet response we are creating + */ + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + if (!HttpServer.hasAdministratorAccess(getServletContext(), request, response)) return; + PrintWriter writer = response.getWriter(); + HMaster master = (HMaster)getServletContext().getAttribute(HMaster.MASTER); + if (master.getAssignmentManager() == null) { + writer.write("Still initializing, please wait.".intern()); + return; + } + RegionStates regionStates = master.getAssignmentManager().getRegionStates(); + Map>> regions = new HashMap<>(); + + String qry = request.getParameter("table"); + if (qry != null) { + // querying for a certain table + TableName table = TableName.valueOf(qry); + regions.put(table, regionStates.getRegionByStateOfTable(table)); + } else { + // no query for certain table so returning all + List assignedRegions = regionStates.getAssignedRegions(); + + for (HRegionInfo regionInfo : assignedRegions) { + TableName tableOfRegion = regionInfo.getTable(); + if (!regions.keySet().contains(tableOfRegion)) { + regions.put(tableOfRegion, regionStates.getRegionByStateOfTable(tableOfRegion)); + } + } + } + + writer.write(JsonMapper.writeObjectAsString(regions)); + writer.close(); + + response.setStatus(HttpServletResponse.SC_OK); + } +}