diff --git hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/metrics/BaseSource.java hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/metrics/BaseSource.java index 652aae1..0100674 100644 --- hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/metrics/BaseSource.java +++ hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/metrics/BaseSource.java @@ -1,3 +1,4 @@ + /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file diff --git hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsAssignmentManagerSourceImpl.java hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsAssignmentManagerSourceImpl.java index ab504f5..5bb110d 100644 --- hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsAssignmentManagerSourceImpl.java +++ hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsAssignmentManagerSourceImpl.java @@ -80,4 +80,5 @@ public class MetricsAssignmentManagerSourceImpl public void updateRitDuration(long duration) { ritDurationHisto.add(duration); } + } diff --git hbase-hadoop2-compat/src/main/resources/META-INF/services/org.apache.hadoop.hbase.master.MetricsRegionStatesSource hbase-hadoop2-compat/src/main/resources/META-INF/services/org.apache.hadoop.hbase.master.MetricsRegionStatesSource new file mode 100644 index 0000000..e40a15b --- /dev/null +++ hbase-hadoop2-compat/src/main/resources/META-INF/services/org.apache.hadoop.hbase.master.MetricsRegionStatesSource @@ -0,0 +1,18 @@ +# 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. +# +org.apache.hadoop.hbase.master.MetricsRegionStatesSourceImpl diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java index 69ebd97..288542b 100644 --- hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java @@ -112,6 +112,7 @@ public class AssignmentManager { private LoadBalancer balancer; private final MetricsAssignmentManager metricsAssignmentManager; + private final MetricsRegionStates metricsRegionStates; private AtomicInteger numRegionsOpened = new AtomicInteger(0); @@ -252,6 +253,7 @@ public class AssignmentManager { conf.getInt("hbase.bulk.assignment.perregion.open.time", 10000); this.metricsAssignmentManager = new MetricsAssignmentManager(); + this.metricsRegionStates = new MetricsRegionStates(); // Configurations for retrying opening a region on receiving a FAILED_OPEN this.retryConfig = new RetryCounter.RetryConfig(); @@ -798,7 +800,7 @@ public class AssignmentManager { List>> regionOpenInfos = new ArrayList<>(states.size()); for (RegionState state: states) { HRegionInfo region = state.getRegion(); - regionStates.updateRegionState( + updateState( region, State.PENDING_OPEN, destination); List favoredNodes = ServerName.EMPTY_SERVER_LIST; if (shouldAssignFavoredNodes(region)) { @@ -941,7 +943,7 @@ public class AssignmentManager { if (!serverManager.isServerOnline(server)) { LOG.debug("Offline " + region.getRegionNameAsString() + ", no need to unassign since it's on a dead server: " + server); - regionStates.updateRegionState(region, State.OFFLINE); + updateState(region, State.OFFLINE); return; } try { @@ -972,7 +974,7 @@ public class AssignmentManager { } else if (t instanceof NotServingRegionException) { LOG.debug("Offline " + region.getRegionNameAsString() + ", it's not any more on " + server, t); - regionStates.updateRegionState(region, State.OFFLINE); + updateState(region, State.OFFLINE); return; } else if (t instanceof FailedServerException && i < maximumAttempts) { // In case the server is in the failed server list, no point to @@ -990,7 +992,7 @@ public class AssignmentManager { } catch (InterruptedException ie) { LOG.warn("Interrupted unassign " + region.getRegionNameAsString(), ie); Thread.currentThread().interrupt(); - regionStates.updateRegionState(region, State.FAILED_CLOSE); + updateState(region, State.FAILED_CLOSE); return; } LOG.info("Server " + server + " returned " + t + " for " @@ -999,7 +1001,7 @@ public class AssignmentManager { } } // Run out of attempts - regionStates.updateRegionState(region, State.FAILED_CLOSE); + updateState(region, State.FAILED_CLOSE); } /** @@ -1030,7 +1032,7 @@ public class AssignmentManager { } case FAILED_CLOSE: case FAILED_OPEN: - regionStates.updateRegionState(region, State.PENDING_CLOSE); + updateState(region, State.PENDING_CLOSE); unassign(region, state.getServerName(), null); state = regionStates.getRegionState(region); if (!state.isOffline() && !state.isClosed()) { @@ -1094,13 +1096,13 @@ public class AssignmentManager { continue; } - regionStates.updateRegionState(region, State.FAILED_OPEN); + updateState(region, State.FAILED_OPEN); return; } LOG.info("Assigning " + region.getRegionNameAsString() + " to " + plan.getDestination()); // Transition RegionState to PENDING_OPEN - regionStates.updateRegionState(region, + updateState(region, State.PENDING_OPEN, plan.getDestination()); boolean needNewPlan = false; @@ -1154,7 +1156,7 @@ public class AssignmentManager { } catch (InterruptedException ie) { LOG.warn("Failed to assign " + region.getRegionNameAsString() + " since interrupted", ie); - regionStates.updateRegionState(region, State.FAILED_OPEN); + updateState(region, State.FAILED_OPEN); Thread.currentThread().interrupt(); return; } @@ -1201,7 +1203,7 @@ public class AssignmentManager { LOG.warn("Failed to get region plan", e); } if (newPlan == null) { - regionStates.updateRegionState(region, State.FAILED_OPEN); + updateState(region, State.FAILED_OPEN); LOG.warn("Unable to find a viable location to assign region " + region.getRegionNameAsString()); return; @@ -1211,7 +1213,7 @@ public class AssignmentManager { // Clean out plan we failed execute and one that doesn't look like it'll // succeed anyways; we need a new plan! // Transition back to OFFLINE - regionStates.updateRegionState(region, State.OFFLINE); + updateState(region, State.OFFLINE); plan = newPlan; } else if(plan.getDestination().equals(newPlan.getDestination()) && previousException instanceof FailedServerException) { @@ -1223,7 +1225,7 @@ public class AssignmentManager { } catch (InterruptedException ie) { LOG.warn("Failed to assign " + region.getRegionNameAsString() + " since interrupted", ie); - regionStates.updateRegionState(region, State.FAILED_OPEN); + updateState(region, State.FAILED_OPEN); Thread.currentThread().interrupt(); return; } @@ -1231,12 +1233,23 @@ public class AssignmentManager { } } // Run out of attempts - regionStates.updateRegionState(region, State.FAILED_OPEN); + updateState(region, State.FAILED_OPEN); } finally { metricsAssignmentManager.updateAssignmentTime(EnvironmentEdgeManager.currentTime() - startTime); } } + private RegionState updateState(HRegionInfo region, State state) { + metricsRegionStates.updateRegionState(region.getEncodedName(), state.toString()); + return regionStates.updateRegionState(region, state); + } + + private RegionState updateState(HRegionInfo region, State state, ServerName destination) { + metricsRegionStates.updateRegionState(region.getEncodedName(), state.toString()); + return regionStates.updateRegionState(region, state, destination); + } + + private boolean isDisabledorDisablingRegionInRIT(final HRegionInfo region) { if (this.tableStateManager.isTableState(region.getTable(), TableState.State.DISABLED, @@ -1394,7 +1407,7 @@ public class AssignmentManager { return; } } - state = regionStates.updateRegionState( + state = updateState( region, State.PENDING_CLOSE); } else if (state.isFailedOpen()) { // The region is not open yet @@ -1503,7 +1516,7 @@ public class AssignmentManager { * @param hri TODO */ public void assignMeta(HRegionInfo hri) throws KeeperException { - regionStates.updateRegionState(hri, State.OFFLINE); + updateState(hri, State.OFFLINE); assign(hri); } @@ -1879,7 +1892,7 @@ public class AssignmentManager { } catch (InterruptedException ie) { LOG.warn("Failed to assign " + hri.getRegionNameAsString() + " since interrupted", ie); - regionStates.updateRegionState(hri, State.FAILED_OPEN); + updateState(hri, State.FAILED_OPEN); Thread.currentThread().interrupt(); return; } @@ -1895,7 +1908,7 @@ public class AssignmentManager { } } // Run out of attempts - regionStates.updateRegionState(hri, State.FAILED_OPEN); + updateState(hri, State.FAILED_OPEN); } finally { lock.unlock(); } @@ -1947,7 +1960,7 @@ public class AssignmentManager { } catch (InterruptedException ie) { LOG.warn("Failed to unassign " + hri.getRegionNameAsString() + " since interrupted", ie); - regionStates.updateRegionState(hri, RegionState.State.FAILED_CLOSE); + updateState(hri, RegionState.State.FAILED_CLOSE); Thread.currentThread().interrupt(); return; } @@ -1963,7 +1976,7 @@ public class AssignmentManager { } } // Run out of attempts - regionStates.updateRegionState(hri, State.FAILED_CLOSE); + updateState(hri, State.FAILED_CLOSE); } finally { lock.unlock(); } @@ -2146,7 +2159,7 @@ public class AssignmentManager { continue; } // Mark the region offline and assign it again by SSH - regionStates.updateRegionState(hri, State.OFFLINE); + updateState(hri, State.OFFLINE); } } finally { lock.unlock(); @@ -2235,7 +2248,7 @@ public class AssignmentManager { failedOpenTracker.put(encodedName, failedOpenCount); } if (failedOpenCount.incrementAndGet() >= maximumAttempts && !hri.isMetaRegion()) { - regionStates.updateRegionState(hri, State.FAILED_OPEN); + updateState(hri, State.FAILED_OPEN); // remove the tracking info to save memory, also reset // the count for next open initiative failedOpenTracker.remove(encodedName); @@ -2249,7 +2262,7 @@ public class AssignmentManager { } // Handle this the same as if it were opened and then closed. - RegionState regionState = regionStates.updateRegionState(hri, State.CLOSED); + RegionState regionState = updateState(hri, State.CLOSED); if (regionState != null) { // When there are more than one region server a new RS is selected as the // destination and the same is updated in the region plan. (HBASE-5546) @@ -2259,7 +2272,7 @@ public class AssignmentManager { offlineDisabledRegion(hri); return null; } - regionStates.updateRegionState(hri, RegionState.State.CLOSED); + updateState(hri, RegionState.State.CLOSED); // This below has to do w/ online enable/disable of a table removeClosedRegion(hri); try { @@ -2329,7 +2342,7 @@ public class AssignmentManager { return null; } - regionStates.updateRegionState(hri, RegionState.State.CLOSED); + updateState(hri, RegionState.State.CLOSED); sendRegionClosedNotification(hri); // This below has to do w/ online enable/disable of a table removeClosedRegion(hri); @@ -2367,7 +2380,7 @@ public class AssignmentManager { // Server holding is not updated at this stage. // It is done after PONR. - regionStates.updateRegionState(hri, State.SPLITTING); + updateState(hri, State.SPLITTING); regionStates.createRegionState( a, State.SPLITTING_NEW, serverName, null); regionStates.createRegionState( @@ -2567,8 +2580,8 @@ public class AssignmentManager { + ", a=" + rs_a + ", b=" + rs_b; } - regionStates.updateRegionState(a, State.MERGING); - regionStates.updateRegionState(b, State.MERGING); + updateState(a, State.MERGING); + updateState(b, State.MERGING); regionStates.createRegionState( hri, State.MERGING_NEW, serverName, null); return null; @@ -3017,7 +3030,7 @@ public class AssignmentManager { if (bulkPlan.containsKey(LoadBalancer.BOGUS_SERVER_NAME)) { // Found no plan for some regions, put those regions in RIT for (HRegionInfo hri : bulkPlan.get(LoadBalancer.BOGUS_SERVER_NAME)) { - regionStates.updateRegionState(hri, State.FAILED_OPEN); + updateState(hri, State.FAILED_OPEN); } bulkPlan.remove(LoadBalancer.BOGUS_SERVER_NAME); } diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetricsRegionStates.java hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetricsRegionStates.java new file mode 100644 index 0000000..6089089 --- /dev/null +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetricsRegionStates.java @@ -0,0 +1,25 @@ +package org.apache.hadoop.hbase.master; + +import org.apache.hadoop.hbase.CompatibilitySingletonFactory; + +public class MetricsRegionStates { + + private final MetricsRegionStatesSource regionStatesSource; + + public MetricsRegionStates() { + regionStatesSource = CompatibilitySingletonFactory.getInstance( + MetricsRegionStatesSource.class); + } + + public MetricsRegionStatesSource getMetricsProcSource() { + return regionStatesSource; + } + + public void updateRegionState(String encodedName, String state) { + regionStatesSource.updateRegionState(encodedName, state); + } + + public void deleteRegionState(String encodedName) { + regionStatesSource.deleteRegionState(encodedName); + } +} diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetricsRegionStatesSource.java hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetricsRegionStatesSource.java new file mode 100644 index 0000000..ff69dee --- /dev/null +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetricsRegionStatesSource.java @@ -0,0 +1,27 @@ +package org.apache.hadoop.hbase.master; + +public interface MetricsRegionStatesSource { + /** + * The name of the metrics + */ + String METRICS_NAME = "RegionStates"; + + /** + * The context metrics will be under. + */ + String METRICS_CONTEXT = "master"; + + /** + * The name of the metrics context that metrics will be under in jmx + */ + String METRICS_JMX_CONTEXT = "Master,sub=" + METRICS_NAME; + + /** + * Description + */ + String METRICS_DESCRIPTION = "Metrics about HBase regions."; + + public void updateRegionState(String encodedName, String state); + + public void deleteRegionState(String encodedName); +} diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetricsRegionStatesSourceImpl.java hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetricsRegionStatesSourceImpl.java new file mode 100644 index 0000000..8c90e65 --- /dev/null +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetricsRegionStatesSourceImpl.java @@ -0,0 +1,58 @@ +package org.apache.hadoop.hbase.master; + +import org.apache.hadoop.hbase.metrics.BaseSourceImpl; +import org.apache.hadoop.hbase.metrics.Interns; +import org.apache.hadoop.metrics2.MetricsCollector; +import org.apache.hadoop.metrics2.MetricsRecordBuilder; + +import java.util.HashMap; +import java.util.Map; + + +public class MetricsRegionStatesSourceImpl extends BaseSourceImpl + implements MetricsRegionStatesSource { + + private Map regionStates; + + public MetricsRegionStatesSourceImpl() { + this(METRICS_NAME, METRICS_DESCRIPTION, METRICS_CONTEXT, METRICS_JMX_CONTEXT); + } + + public MetricsRegionStatesSourceImpl(String metricsName, + String metricsDescription, + String metricsContext, String metricsJmxContext) { + super(metricsName, metricsDescription, metricsContext, metricsJmxContext); + } + + public void init() { + regionStates = new HashMap<>(); + } + + @Override + public void updateRegionState(String encodedName, String state) { + regionStates.put(encodedName, state); + } + + @Override + public void deleteRegionState(String encodedName) { + if (regionStates.containsKey(encodedName)) regionStates.remove("encodedName"); + } + + /** + * Yes this is a get function that doesn't return anything. Thanks Hadoop for breaking all + * expectations of java programmers. Instead of returning anything Hadoop metrics expects + * getMetrics to push the metrics into the collector. + *s + * @param collector the collector + * @param all get all the metrics regardless of when they last changed. + */ + @Override + public void getMetrics(MetricsCollector collector, boolean all) { + super.getMetrics(collector, all); + MetricsRecordBuilder mrb = collector.addRecord("RegionState"); + + for (String key : regionStates.keySet()) { + mrb.tag(Interns.info(key, key), regionStates.get(key)); + } + } +}