From 4d5bf5f130aa22126e2d259282a5bf47cbf9318b Mon Sep 17 00:00:00 2001 From: Alejandro Abdelnur Date: Mon, 24 Jun 2013 21:43:01 +0000 Subject: [PATCH] HADOOP-9661. Allow metrics sources to be extended. (sandyr via tucu) git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1496228 13f79535-47bb-0310-9956-ffa450edef68 --- .../hadoop-common/CHANGES.txt | 2 + .../metrics2/lib/MetricsSourceBuilder.java | 7 +-- .../apache/hadoop/util/ReflectionUtils.java | 35 ++++++++++++++ .../hadoop/util/TestReflectionUtils.java | 48 +++++++++++++++++++ 4 files changed, 89 insertions(+), 3 deletions(-) diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 93426e1dfa6..e36f92ce2f5 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -23,6 +23,8 @@ Release 2.2.0 - UNRELEASED IMPROVEMENTS + HADOOP-9661. Allow metrics sources to be extended. (sandyr via tucu) + OPTIMIZATIONS BUG FIXES diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsSourceBuilder.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsSourceBuilder.java index 9430260da19..b44a471b364 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsSourceBuilder.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsSourceBuilder.java @@ -33,6 +33,7 @@ import org.apache.hadoop.metrics2.MetricsInfo; import org.apache.hadoop.metrics2.MetricsSource; import org.apache.hadoop.metrics2.annotation.Metric; import org.apache.hadoop.metrics2.annotation.Metrics; +import org.apache.hadoop.util.ReflectionUtils; /** * Helper class to build metrics source object from annotations @@ -54,10 +55,10 @@ public class MetricsSourceBuilder { Class cls = source.getClass(); registry = initRegistry(source); - for (Field field : cls.getDeclaredFields()) { + for (Field field : ReflectionUtils.getDeclaredFieldsIncludingInherited(cls)) { add(source, field); } - for (Method method : cls.getDeclaredMethods()) { + for (Method method : ReflectionUtils.getDeclaredMethodsIncludingInherited(cls)) { add(source, method); } } @@ -88,7 +89,7 @@ public class MetricsSourceBuilder { Class cls = source.getClass(); MetricsRegistry r = null; // Get the registry if it already exists. - for (Field field : cls.getDeclaredFields()) { + for (Field field : ReflectionUtils.getDeclaredFieldsIncludingInherited(cls)) { if (field.getType() != MetricsRegistry.class) continue; try { field.setAccessible(true); diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/ReflectionUtils.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/ReflectionUtils.java index bf12de633fb..4fee5f4f952 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/ReflectionUtils.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/ReflectionUtils.java @@ -25,7 +25,10 @@ import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -302,4 +305,36 @@ public class ReflectionUtils { buffer.moveData(); dst.readFields(buffer.inBuffer); } + + /** + * Gets all the declared fields of a class including fields declared in + * superclasses. + */ + public static List getDeclaredFieldsIncludingInherited(Class clazz) { + List fields = new ArrayList(); + while (clazz != null) { + for (Field field : clazz.getDeclaredFields()) { + fields.add(field); + } + clazz = clazz.getSuperclass(); + } + + return fields; + } + + /** + * Gets all the declared methods of a class including methods declared in + * superclasses. + */ + public static List getDeclaredMethodsIncludingInherited(Class clazz) { + List methods = new ArrayList(); + while (clazz != null) { + for (Method method : clazz.getDeclaredMethods()) { + methods.add(method); + } + clazz = clazz.getSuperclass(); + } + + return methods; + } } diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestReflectionUtils.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestReflectionUtils.java index cb7ea38beb6..56e86ef9ff1 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestReflectionUtils.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestReflectionUtils.java @@ -18,9 +18,12 @@ package org.apache.hadoop.util; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.HashMap; +import java.util.List; import static org.junit.Assert.*; import org.junit.Before; @@ -109,6 +112,51 @@ public class TestReflectionUtils { System.gc(); assertTrue(cacheSize()+" too big", cacheSize() fields = ReflectionUtils.getDeclaredFieldsIncludingInherited( + child.getClass()); + boolean containsParentField = false; + boolean containsChildField = false; + for (Field field : fields) { + if (field.getName().equals("parentField")) { + containsParentField = true; + } else if (field.getName().equals("childField")) { + containsChildField = true; + } + } + + List methods = ReflectionUtils.getDeclaredMethodsIncludingInherited( + child.getClass()); + boolean containsParentMethod = false; + boolean containsChildMethod = false; + for (Method method : methods) { + if (method.getName().equals("getParentField")) { + containsParentMethod = true; + } else if (method.getName().equals("getChildField")) { + containsChildMethod = true; + } + } + + assertTrue("Missing parent field", containsParentField); + assertTrue("Missing child field", containsChildField); + assertTrue("Missing parent method", containsParentMethod); + assertTrue("Missing child method", containsChildMethod); + } + + // Used for testGetDeclaredFieldsIncludingInherited + private class Parent { + private int parentField; + @SuppressWarnings("unused") + public int getParentField() { return parentField; } + } private static class LoadedInChild { }