Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,13 @@
package org.apache.hadoop.hbase.metrics.impl;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.lang.reflect.FieldUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.metrics.MetricRegistries;
Expand All @@ -37,11 +33,8 @@
import org.apache.hadoop.metrics2.MetricsCollector;
import org.apache.hadoop.metrics2.MetricsExecutor;
import org.apache.hadoop.metrics2.MetricsSource;
import org.apache.hadoop.metrics2.MetricsSystem;
import org.apache.hadoop.metrics2.impl.JmxCacheBuster;
import org.apache.hadoop.metrics2.impl.MetricsSystemImpl;
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystemHelper;
import org.apache.hadoop.metrics2.lib.MetricsExecutorImpl;

import com.google.common.annotations.VisibleForTesting;
Expand Down Expand Up @@ -87,7 +80,6 @@ public void getMetrics(MetricsCollector collector, boolean all) {

private final MetricsExecutor executor;
private final AtomicBoolean stopped;
private final DefaultMetricsSystemHelper helper;
private final HBaseMetrics2HadoopMetricsAdapter metricsAdapter;
private final HashMap<MetricRegistryInfo, MetricsSourceAdapter> registeredSources;

Expand All @@ -96,7 +88,6 @@ private GlobalMetricRegistriesAdapter() {
this.stopped = new AtomicBoolean(false);
this.metricsAdapter = new HBaseMetrics2HadoopMetricsAdapter();
this.registeredSources = new HashMap<>();
this.helper = new DefaultMetricsSystemHelper();
executor.getExecutor().scheduleAtFixedRate(new Runnable(){
@Override
public void run() {
Expand Down Expand Up @@ -167,67 +158,13 @@ private void doRun() {
if (LOG.isDebugEnabled()) {
LOG.debug("Removing adapter for the MetricRegistry: " + info.getMetricsJmxContext());
}
synchronized(DefaultMetricsSystem.instance()) {
unregisterSource(info);
helper.removeSourceName(info.getMetricsJmxContext());
helper.removeObjectName(info.getMetricsJmxContext());
it.remove();
removed = true;
}
DefaultMetricsSystem.instance().unregisterSource(info.getMetricsJmxContext());
it.remove();
removed = true;
}
}
if (removed) {
JmxCacheBuster.clearJmxCache();
}
}

/**
* Use reflection to unregister the Hadoop metric source, since MetricsSystem#unregisterSource()
* is only available in Hadoop 2.6+ (HADOOP-10839)
*/
@VisibleForTesting
protected void unregisterSource(MetricRegistryInfo info) {
// unregisterSource is only available in Hadoop 2.6+ (HADOOP-10839). Don't unregister for now
MetricsSystem metricsSystem = DefaultMetricsSystem.instance();
if (metricsSystem instanceof MetricsSystemImpl) {
try {
// it's actually a Map<String, MetricsSourceAdapter> , but MetricsSourceAdapter isn't
// accessible
@SuppressWarnings("unchecked")
Map<String, Object> sources =
(Map<String, Object>) FieldUtils.readField(metricsSystem, "sources", true);
String sourceName = info.getMetricsJmxContext();
if (sources.containsKey(sourceName)) {
Object sourceAdapter = sources.get(sourceName);
Method method = null;
try {
method = sourceAdapter.getClass().getDeclaredMethod("stop");
} catch (NoSuchMethodException e) {
LOG.info("Stop method not found on MetricsSourceAdapter");
} catch (SecurityException e) {
LOG.info("Don't have access to call stop method not found on MetricsSourceAdapter", e);
}
if (method != null) {
method.setAccessible(true);
try {
method.invoke(sourceAdapter);
} catch (IllegalArgumentException | InvocationTargetException e) {
LOG.warn("Couldn't invoke stop on metrics source adapter: " + sourceName);
e.printStackTrace();
}
}
sources.remove(sourceName);

}
@SuppressWarnings("unchecked")
Map<String, MetricsSource> allSources =
(Map<String, MetricsSource>) FieldUtils.readField(metricsSystem, "allSources", true);
if (allSources.containsKey(sourceName)) {
allSources.remove(sourceName);
}
} catch (IllegalAccessException e) {
LOG.warn("Error unregistering metric source " + info.getMetricsJmxContext());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
*/
package org.apache.hadoop.metrics2.lib;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
Expand All @@ -28,8 +26,6 @@ public class DefaultMetricsSystemHelper {

private static final Log LOG = LogFactory.getLog(DefaultMetricsSystemHelper.class);
private final Method removeObjectMethod;
private final Field sourceNamesField;
private final Field mapField;

public DefaultMetricsSystemHelper() {
Class<? extends DefaultMetricsSystem> clazz = DefaultMetricsSystem.INSTANCE.getClass();
Expand All @@ -41,20 +37,6 @@ public DefaultMetricsSystemHelper() {
m = null;
}
removeObjectMethod = m;

Field f1, f2;
try {
f1 = clazz.getDeclaredField("sourceNames");
f1.setAccessible(true);
f2 = UniqueNames.class.getDeclaredField("map");
f2.setAccessible(true);
} catch (NoSuchFieldException e) {
LOG.trace(e);
f1 = null;
f2 = null;
}
sourceNamesField = f1;
mapField = f2;
}

public boolean removeObjectName(final String name) {
Expand All @@ -70,30 +52,4 @@ public boolean removeObjectName(final String name) {
}
return false;
}

/**
* Unfortunately Hadoop tries to be too-clever and permanently keeps track of all names registered
* so far as a Source, thus preventing further re-registration of the source with the same name.
* In case of dynamic metrics tied to region-lifecycles, this becomes a problem because we would
* like to be able to re-register and remove with the same name. Otherwise, it is resource leak.
* This ugly code manually removes the name from the UniqueNames map.
* TODO: May not be needed for Hadoop versions after YARN-5190.
*/
public void removeSourceName(String name) {
if (sourceNamesField == null || mapField == null) {
return;
}
try {
Object sourceNames = sourceNamesField.get(DefaultMetricsSystem.INSTANCE);
HashMap map = (HashMap) mapField.get(sourceNames);
synchronized (sourceNames) {
map.remove(name);
}
} catch (Exception ex) {
if (LOG.isTraceEnabled()) {
LOG.trace("Received exception while trying to access Hadoop Metrics classes via reflection.",
ex);
}
}
}
}

This file was deleted.