瀏覽代碼

HADOOP-4838. Added a registry to automate metrics and mbeans management. Contributed by Sanjay Radia.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/core/trunk@726900 13f79535-47bb-0310-9956-ffa450edef68
Arun Murthy 16 年之前
父節點
當前提交
26deef22ad
共有 31 個文件被更改,包括 985 次插入1383 次删除
  1. 3 0
      CHANGES.txt
  2. 7 10
      src/core/org/apache/hadoop/ipc/RPC.java
  3. 80 0
      src/core/org/apache/hadoop/ipc/metrics/RpcActivityMBean.java
  4. 27 29
      src/core/org/apache/hadoop/ipc/metrics/RpcMetrics.java
  5. 5 0
      src/core/org/apache/hadoop/metrics/MetricsContext.java
  6. 1 1
      src/core/org/apache/hadoop/metrics/MetricsUtil.java
  7. 3 3
      src/core/org/apache/hadoop/metrics/util/MBeanUtil.java
  8. 47 0
      src/core/org/apache/hadoop/metrics/util/MetricsBase.java
  9. 226 0
      src/core/org/apache/hadoop/metrics/util/MetricsDynamicMBeanBase.java
  10. 20 43
      src/core/org/apache/hadoop/metrics/util/MetricsIntValue.java
  11. 17 43
      src/core/org/apache/hadoop/metrics/util/MetricsLongValue.java
  12. 88 0
      src/core/org/apache/hadoop/metrics/util/MetricsRegistry.java
  13. 36 9
      src/core/org/apache/hadoop/metrics/util/MetricsTimeVaryingInt.java
  14. 124 0
      src/core/org/apache/hadoop/metrics/util/MetricsTimeVaryingLong.java
  15. 20 8
      src/core/org/apache/hadoop/metrics/util/MetricsTimeVaryingRate.java
  16. 8 6
      src/hdfs/org/apache/hadoop/hdfs/server/datanode/FSDataset.java
  17. 76 0
      src/hdfs/org/apache/hadoop/hdfs/server/datanode/metrics/DataNodeActivityMBean.java
  18. 33 49
      src/hdfs/org/apache/hadoop/hdfs/server/datanode/metrics/DataNodeMetrics.java
  19. 0 371
      src/hdfs/org/apache/hadoop/hdfs/server/datanode/metrics/DataNodeStatistics.java
  20. 0 320
      src/hdfs/org/apache/hadoop/hdfs/server/datanode/metrics/DataNodeStatisticsMBean.java
  21. 4 0
      src/hdfs/org/apache/hadoop/hdfs/server/datanode/metrics/FSDatasetMBean.java
  22. 8 2
      src/hdfs/org/apache/hadoop/hdfs/server/namenode/FSEditLog.java
  23. 4 3
      src/hdfs/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java
  24. 6 2
      src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/FSNamesystemMBean.java
  25. 25 27
      src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/FSNamesystemMetrics.java
  26. 67 0
      src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/NameNodeActivtyMBean.java
  27. 36 36
      src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/NameNodeMetrics.java
  28. 0 220
      src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/NameNodeStatistics.java
  29. 0 187
      src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/NameNodeStatisticsMBean.java
  30. 13 10
      src/test/org/apache/hadoop/hdfs/server/datanode/SimulatedFSDataset.java
  31. 1 4
      src/test/org/apache/hadoop/hdfs/server/datanode/TestDataNodeMetrics.java

+ 3 - 0
CHANGES.txt

@@ -258,6 +258,9 @@ Trunk (unreleased changes)
 
 
     HADOOP-4699. Remove checksum validation from map output servlet. (cdouglas)
     HADOOP-4699. Remove checksum validation from map output servlet. (cdouglas)
 
 
+    HADOOP-4838. Added a registry to automate metrics and mbeans management.
+    (Sanjay Radia via acmurthy) 
+
   OPTIMIZATIONS
   OPTIMIZATIONS
 
 
     HADOOP-3293. Fixes FileInputFormat to do provide locations for splits
     HADOOP-3293. Fixes FileInputFormat to do provide locations for splits

+ 7 - 10
src/core/org/apache/hadoop/ipc/RPC.java

@@ -516,16 +516,13 @@ public class RPC {
         rpcMetrics.rpcQueueTime.inc(qTime);
         rpcMetrics.rpcQueueTime.inc(qTime);
         rpcMetrics.rpcProcessingTime.inc(processingTime);
         rpcMetrics.rpcProcessingTime.inc(processingTime);
 
 
-	MetricsTimeVaryingRate m = rpcMetrics.metricsList.get(call.getMethodName());
-
-	if (m != null) {
-		m.inc(processingTime);
-	}
-	else {
-		rpcMetrics.metricsList.put(call.getMethodName(), new MetricsTimeVaryingRate(call.getMethodName()));
-		m = rpcMetrics.metricsList.get(call.getMethodName());
-		m.inc(processingTime);
-	}
+        MetricsTimeVaryingRate m =
+         (MetricsTimeVaryingRate) rpcMetrics.registry.get(call.getMethodName());
+      	if (m == null) {
+      	  m = new MetricsTimeVaryingRate(call.getMethodName(),
+      	                                        rpcMetrics.registry);
+      	}
+        m.inc(processingTime);
 
 
         if (verbose) log("Return: "+value);
         if (verbose) log("Return: "+value);
 
 

+ 80 - 0
src/core/org/apache/hadoop/ipc/metrics/RpcActivityMBean.java

@@ -0,0 +1,80 @@
+/**
+ * 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.ipc.metrics;
+
+import javax.management.ObjectName;
+
+import org.apache.hadoop.metrics.util.MBeanUtil;
+import org.apache.hadoop.metrics.util.MetricsDynamicMBeanBase;
+import org.apache.hadoop.metrics.util.MetricsRegistry;
+
+
+
+/**
+ * 
+ * This is the JMX MBean for reporting the RPC layer Activity.
+ * The MBean is register using the name
+ *        "hadoop:service=<RpcServiceName>,name=RpcActivityForPort<port>"
+ * 
+ * Many of the activity metrics are sampled and averaged on an interval 
+ * which can be specified in the metrics config file.
+ * <p>
+ * For the metrics that are sampled and averaged, one must specify 
+ * a metrics context that does periodic update calls. Most metrics contexts do.
+ * The default Null metrics context however does NOT. So if you aren't
+ * using any other metrics context then you can turn on the viewing and averaging
+ * of sampled metrics by  specifying the following two lines
+ *  in the hadoop-meterics.properties file:
+ *  <pre>
+ *        rpc.class=org.apache.hadoop.metrics.spi.NullContextWithUpdateThread
+ *        rpc.period=10
+ *  </pre>
+ *<p>
+ * Note that the metrics are collected regardless of the context used.
+ * The context with the update thread is used to average the data periodically
+ *
+ *
+ *
+ * Impl details: We use a dynamic mbean that gets the list of the metrics
+ * from the metrics registry passed as an argument to the constructor
+ */
+
+public class RpcActivityMBean extends MetricsDynamicMBeanBase {
+  final private ObjectName mbeanName;
+
+  /**
+   * 
+   * @param mr - the metrics registry that has all the metrics
+   * @param serviceName - the service name for the rpc service 
+   * @param port - the rpc port.
+   */
+  public RpcActivityMBean(final MetricsRegistry mr, final String serviceName, final String port) {
+
+    
+    super(mr, "Rpc layer statistics");
+    mbeanName = MBeanUtil.registerMBean(serviceName,
+          "RpcActivityForPort" + port, this);
+  }
+  
+
+  public void shutdown() {
+    if (mbeanName != null)
+      MBeanUtil.unregisterMBean(mbeanName);
+  }
+
+}

+ 27 - 29
src/core/org/apache/hadoop/ipc/metrics/RpcMetrics.java

@@ -24,12 +24,11 @@ import org.apache.hadoop.metrics.MetricsContext;
 import org.apache.hadoop.metrics.MetricsRecord;
 import org.apache.hadoop.metrics.MetricsRecord;
 import org.apache.hadoop.metrics.MetricsUtil;
 import org.apache.hadoop.metrics.MetricsUtil;
 import org.apache.hadoop.metrics.Updater;
 import org.apache.hadoop.metrics.Updater;
-import org.apache.hadoop.metrics.jvm.JvmMetrics;
+import org.apache.hadoop.metrics.util.MetricsBase;
+import org.apache.hadoop.metrics.util.MetricsIntValue;
+import org.apache.hadoop.metrics.util.MetricsRegistry;
 import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
 import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
 
 
-import java.util.HashMap;
-import java.util.*;
-
 /**
 /**
  * 
  * 
  * This class is for maintaining  the various RPC statistics
  * This class is for maintaining  the various RPC statistics
@@ -43,11 +42,14 @@ import java.util.*;
  *
  *
  */
  */
 public class RpcMetrics implements Updater {
 public class RpcMetrics implements Updater {
+  public MetricsRegistry registry = new MetricsRegistry();
   private MetricsRecord metricsRecord;
   private MetricsRecord metricsRecord;
+  private Server myServer;
   private static Log LOG = LogFactory.getLog(RpcMetrics.class);
   private static Log LOG = LogFactory.getLog(RpcMetrics.class);
-  RpcMgt rpcMgt;
+  RpcActivityMBean rpcMBean;
   
   
   public RpcMetrics(String hostName, String port, Server server) {
   public RpcMetrics(String hostName, String port, Server server) {
+    myServer = server;
     MetricsContext context = MetricsUtil.getContext("rpc");
     MetricsContext context = MetricsUtil.getContext("rpc");
     metricsRecord = MetricsUtil.createRecord(context, "metrics");
     metricsRecord = MetricsUtil.createRecord(context, "metrics");
 
 
@@ -59,7 +61,7 @@ public class RpcMetrics implements Updater {
     context.registerUpdater(this);
     context.registerUpdater(this);
     
     
     // Need to clean up the interface to RpcMgt - don't need both metrics and server params
     // Need to clean up the interface to RpcMgt - don't need both metrics and server params
-    rpcMgt = new RpcMgt(hostName, port, this, server);
+    rpcMBean = new RpcActivityMBean(registry, hostName, port);
   }
   }
   
   
   
   
@@ -68,39 +70,35 @@ public class RpcMetrics implements Updater {
    *  - they can be set directly by calling their set/inc methods
    *  - they can be set directly by calling their set/inc methods
    *  -they can also be read directly - e.g. JMX does this.
    *  -they can also be read directly - e.g. JMX does this.
    */
    */
-  
-  public MetricsTimeVaryingRate rpcQueueTime = new MetricsTimeVaryingRate("RpcQueueTime");
-  public MetricsTimeVaryingRate rpcProcessingTime = new MetricsTimeVaryingRate("RpcProcessingTime");
-
-  public Map <String, MetricsTimeVaryingRate> metricsList = Collections.synchronizedMap(new HashMap<String, MetricsTimeVaryingRate>());
 
 
-  
+  public MetricsTimeVaryingRate rpcQueueTime =
+          new MetricsTimeVaryingRate("RpcQueueTime", registry);
+  public MetricsTimeVaryingRate rpcProcessingTime =
+          new MetricsTimeVaryingRate("RpcProcessingTime", registry);
+  public MetricsIntValue numOpenConnections = 
+          new MetricsIntValue("NumOpenConnections", registry);
+  public MetricsIntValue callQueueLen = 
+          new MetricsIntValue("callQueueLen", registry);
   
   
   /**
   /**
    * Push the metrics to the monitoring subsystem on doUpdate() call.
    * Push the metrics to the monitoring subsystem on doUpdate() call.
    */
    */
   public void doUpdates(MetricsContext context) {
   public void doUpdates(MetricsContext context) {
-    rpcQueueTime.pushMetric(metricsRecord);
-    rpcProcessingTime.pushMetric(metricsRecord);
-
-    synchronized (metricsList) {
-	// Iterate through the rpcMetrics hashmap to propogate the different rpc metrics.
-	Set keys = metricsList.keySet();
-
-	Iterator keyIter = keys.iterator();
-
-	while (keyIter.hasNext()) {
-		Object key = keyIter.next();
-		MetricsTimeVaryingRate value = metricsList.get(key);
-
-		value.pushMetric(metricsRecord);
-	}
+    
+    synchronized (this) {
+      // ToFix - fix server to use the following two metrics directly so
+      // the metrics do not have be copied here.
+      numOpenConnections.set(myServer.getNumOpenConnections());
+      callQueueLen.set(myServer.getCallQueueLen());
+      for (MetricsBase m : registry.getMetricsList()) {
+        m.pushMetric(metricsRecord);
+      }
     }
     }
     metricsRecord.update();
     metricsRecord.update();
   }
   }
 
 
   public void shutdown() {
   public void shutdown() {
-    if (rpcMgt != null) 
-      rpcMgt.shutdown();
+    if (rpcMBean != null) 
+      rpcMBean.shutdown();
   }
   }
 }
 }

+ 5 - 0
src/core/org/apache/hadoop/metrics/MetricsContext.java

@@ -98,5 +98,10 @@ public interface MetricsContext {
    * @param updater object to be removed from the callback list
    * @param updater object to be removed from the callback list
    */
    */
   public abstract void unregisterUpdater(Updater updater);
   public abstract void unregisterUpdater(Updater updater);
+  
+  /**
+   * Returns the timer period.
+   */
+  public abstract int getPeriod();
     
     
 }
 }

+ 1 - 1
src/core/org/apache/hadoop/metrics/MetricsUtil.java

@@ -33,7 +33,7 @@ import org.apache.commons.logging.LogFactory;
  */
  */
 public class MetricsUtil {
 public class MetricsUtil {
     
     
-  private static final Log LOG =
+  public static final Log LOG =
     LogFactory.getLog(MetricsUtil.class);
     LogFactory.getLog(MetricsUtil.class);
 
 
   /**
   /**

+ 3 - 3
src/core/org/apache/hadoop/metrics/util/MBeanUtil.java

@@ -35,8 +35,8 @@ import javax.management.InstanceAlreadyExistsException;
 public class MBeanUtil {
 public class MBeanUtil {
 	
 	
   /**
   /**
-   * Register the mbean using out standard MBeanName format
-   * "hadoop.dfs:service=<serviceName>,name=<nameName>"
+   * Register the MBean using our standard MBeanName format
+   * "hadoop:service=<serviceName>,name=<nameName>"
    * Where the <serviceName> and <nameName> are the supplied parameters
    * Where the <serviceName> and <nameName> are the supplied parameters
    *    
    *    
    * @param serviceName
    * @param serviceName
@@ -77,7 +77,7 @@ public class MBeanUtil {
 		  								 final String nameName) {
 		  								 final String nameName) {
     ObjectName name = null;
     ObjectName name = null;
     try {
     try {
-      name = new ObjectName("hadoop.dfs:" +
+      name = new ObjectName("hadoop:" +
                   "service=" + serviceName + ",name=" + nameName);
                   "service=" + serviceName + ",name=" + nameName);
     } catch (MalformedObjectNameException e) {
     } catch (MalformedObjectNameException e) {
       e.printStackTrace();
       e.printStackTrace();

+ 47 - 0
src/core/org/apache/hadoop/metrics/util/MetricsBase.java

@@ -0,0 +1,47 @@
+/**
+ * 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.metrics.util;
+
+import org.apache.hadoop.metrics.MetricsRecord;
+
+/**
+ * 
+ * This is base class for all metrics
+ *
+ */
+public abstract class MetricsBase {
+  public static final String NO_DESCRIPTION = "NoDescription";
+  final private String name;
+  final private String description;
+  
+  protected MetricsBase(final String nam) {
+    name = nam;
+    description = NO_DESCRIPTION;
+  }
+  
+  protected MetricsBase(final String nam, final String desc) {
+    name = nam;
+    description = desc;
+  }
+  
+  public abstract void pushMetric(final MetricsRecord mr);
+  
+  public String getName() { return name; }
+  public String getDescription() { return description; };
+
+}

+ 226 - 0
src/core/org/apache/hadoop/metrics/util/MetricsDynamicMBeanBase.java

@@ -0,0 +1,226 @@
+/**
+ * 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.metrics.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.ReflectionException;
+
+import org.apache.hadoop.metrics.MetricsUtil;
+
+
+
+/**
+ * This abstract base class facilitates creating dynamic mbeans automatically from
+ * metrics. 
+ * The metrics constructors registers metrics in a registry. 
+ * Different categories of metrics should be in differnt classes with their own
+ * registry (as in NameNodeMetrics and DataNodeMetrics).
+ * Then the MBean can be created passing the registry to the constructor.
+ * The MBean should be then registered using a mbean name (example):
+ *  MetricsHolder myMetrics = new MetricsHolder(); // has metrics and registry
+ *  MetricsTestMBean theMBean = new MetricsTestMBean(myMetrics.mregistry);
+ *  ObjectName mbeanName = MBeanUtil.registerMBean("ServiceFoo",
+ *                "TestStatistics", theMBean);
+ * 
+ *
+ */
+public abstract class MetricsDynamicMBeanBase implements DynamicMBean {
+  private final static String AVG_TIME = "AvgTime";
+  private final static String MIN_TIME = "MinTime";
+  private final static String MAX_TIME = "MaxTime";
+  private final static String NUM_OPS = "NumOps";
+  private final static String RESET_ALL_MIN_MAX_OP = "resetAllMinMax";
+  private MetricsRegistry metricsRegistry;
+  private MBeanInfo mbeanInfo;
+  private Map<String, MetricsBase> metricsRateAttributeMod;
+  private int numEntriesInRegistry = 0;
+  private String mbeanDescription;
+  
+  protected MetricsDynamicMBeanBase(final MetricsRegistry mr, final String aMBeanDescription) {
+    metricsRegistry = mr;
+    mbeanDescription = aMBeanDescription;
+    createMBeanInfo();
+  }
+  
+  private void updateMbeanInfoIfMetricsListChanged()  {
+    if (numEntriesInRegistry != metricsRegistry.size())
+      createMBeanInfo();
+  }
+  
+  private void createMBeanInfo() {
+    metricsRateAttributeMod = new HashMap<String, MetricsBase>();
+    boolean needsMinMaxResetOperation = false;
+    List<MBeanAttributeInfo> attributesInfo = new ArrayList<MBeanAttributeInfo>();
+    MBeanOperationInfo[] operationsInfo = null;
+    numEntriesInRegistry = metricsRegistry.size();
+    
+    for (MetricsBase o : metricsRegistry.getMetricsList()) {
+
+      if (MetricsTimeVaryingRate.class.isInstance(o)) {
+        // For each of the metrics there are 3 different attributes
+        attributesInfo.add(new MBeanAttributeInfo(o.getName() + NUM_OPS, "java.lang.Integer",
+            o.getDescription(), true, false, false));
+        attributesInfo.add(new MBeanAttributeInfo(o.getName() + AVG_TIME, "java.lang.Long",
+            o.getDescription(), true, false, false));
+        attributesInfo.add(new MBeanAttributeInfo(o.getName() + MIN_TIME, "java.lang.Long",
+            o.getDescription(), true, false, false));
+        attributesInfo.add(new MBeanAttributeInfo(o.getName() + MAX_TIME, "java.lang.Long",
+            o.getDescription(), true, false, false));
+        needsMinMaxResetOperation = true;  // the min and max can be reset.
+        
+        // Note the special attributes (AVG_TIME, MIN_TIME, ..) are derived from metrics 
+        // Rather than check for the suffix we store them in a map.
+        metricsRateAttributeMod.put(o.getName() + NUM_OPS, o);
+        metricsRateAttributeMod.put(o.getName() + AVG_TIME, o);
+        metricsRateAttributeMod.put(o.getName() + MIN_TIME, o);
+        metricsRateAttributeMod.put(o.getName() + MAX_TIME, o);
+        
+      }  else if ( MetricsIntValue.class.isInstance(o) || MetricsTimeVaryingInt.class.isInstance(o) ) {
+        attributesInfo.add(new MBeanAttributeInfo(o.getName(), "java.lang.Integer",
+            o.getDescription(), true, false, false)); 
+      } else if ( MetricsLongValue.class.isInstance(o) || MetricsTimeVaryingLong.class.isInstance(o) ) {
+        attributesInfo.add(new MBeanAttributeInfo(o.getName(), "java.lang.Long",
+            o.getDescription(), true, false, false));     
+      } else {
+        MetricsUtil.LOG.error("unknown metrics type: " + o.getClass().getName());
+      }
+
+      if (needsMinMaxResetOperation) {
+        operationsInfo = new MBeanOperationInfo[] {
+            new MBeanOperationInfo(RESET_ALL_MIN_MAX_OP, "Reset (zero) All Min Max",
+                    null, "void", MBeanOperationInfo.ACTION) };
+      }
+    }
+    MBeanAttributeInfo[] attrArray = new MBeanAttributeInfo[attributesInfo.size()];
+    mbeanInfo =  new MBeanInfo(this.getClass().getName(), mbeanDescription, 
+        attributesInfo.toArray(attrArray), null, operationsInfo, null);
+  }
+  
+  @Override
+  public Object getAttribute(String attributeName) throws AttributeNotFoundException,
+      MBeanException, ReflectionException {
+    if (attributeName == null || attributeName.equals("")) 
+      throw new IllegalArgumentException();
+    
+    updateMbeanInfoIfMetricsListChanged();
+    
+    Object o = metricsRateAttributeMod.get(attributeName);
+    if (o == null) {
+      o = metricsRegistry.get(attributeName);
+    }
+    if (o == null)
+      throw new AttributeNotFoundException();
+    
+    if (o instanceof MetricsIntValue)
+      return ((MetricsIntValue) o).get();
+    else if (o instanceof MetricsLongValue)
+      return ((MetricsLongValue) o).get();
+    else if (o instanceof MetricsTimeVaryingInt)
+      return ((MetricsTimeVaryingInt) o).getPreviousIntervalValue();
+    else if (o instanceof MetricsTimeVaryingLong)
+      return ((MetricsTimeVaryingLong) o).getPreviousIntervalValue();
+    else if (o instanceof MetricsTimeVaryingRate) {
+      MetricsTimeVaryingRate or = (MetricsTimeVaryingRate) o;
+      if (attributeName.endsWith(NUM_OPS))
+        return or.getPreviousIntervalNumOps();
+      else if (attributeName.endsWith(AVG_TIME))
+        return or.getPreviousIntervalAverageTime();
+      else if (attributeName.endsWith(MIN_TIME))
+        return or.getMinTime();
+      else if (attributeName.endsWith(MAX_TIME))
+        return or.getMaxTime();
+      else {
+        MetricsUtil.LOG.error("Unexpected attrubute suffix");
+        throw new AttributeNotFoundException();
+      }
+    } else {
+        MetricsUtil.LOG.error("unknown metrics type: " + o.getClass().getName());
+        throw new AttributeNotFoundException();
+    }
+  }
+
+  @Override
+  public AttributeList getAttributes(String[] attributeNames) {
+    if (attributeNames == null || attributeNames.length == 0) 
+      throw new IllegalArgumentException();
+    
+    updateMbeanInfoIfMetricsListChanged();
+    
+    AttributeList result = new AttributeList(attributeNames.length);
+    for (String iAttributeName : attributeNames) {
+      try {
+        Object value = getAttribute(iAttributeName);
+        result.add(new Attribute(iAttributeName, value));
+      } catch (Exception e) {
+        continue;
+      } 
+    }
+    return result;
+  }
+
+  @Override
+  public MBeanInfo getMBeanInfo() {
+    return mbeanInfo;
+  }
+
+  @Override
+  public Object invoke(String actionName, Object[] parms, String[] signature)
+      throws MBeanException, ReflectionException {
+    
+    if (actionName == null || actionName.equals("")) 
+      throw new IllegalArgumentException();
+    
+    
+    // Right now we support only one fixed operation (if it applies)
+    if (!(actionName.equals(RESET_ALL_MIN_MAX_OP)) || 
+        mbeanInfo.getOperations().length != 1) {
+      throw new ReflectionException(new NoSuchMethodException(actionName));
+    }
+    for (MetricsBase m : metricsRegistry.getMetricsList())  {
+      if ( MetricsTimeVaryingRate.class.isInstance(m) ) {
+        MetricsTimeVaryingRate.class.cast(m).resetMinMax();
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public void setAttribute(Attribute attribute)
+      throws AttributeNotFoundException, InvalidAttributeValueException,
+      MBeanException, ReflectionException {
+    throw new ReflectionException(new NoSuchMethodException("set" + attribute));
+  }
+
+  @Override
+  public AttributeList setAttributes(AttributeList attributes) {
+    return null;
+  }
+}

+ 20 - 43
src/core/org/apache/hadoop/metrics/util/MetricsIntValue.java

@@ -30,25 +30,39 @@ import org.apache.commons.logging.LogFactory;
  * call.
  * call.
  *
  *
  */
  */
-public class MetricsIntValue {  
+public class MetricsIntValue extends MetricsBase {  
 
 
   private static final Log LOG =
   private static final Log LOG =
     LogFactory.getLog("org.apache.hadoop.metrics.util");
     LogFactory.getLog("org.apache.hadoop.metrics.util");
 
 
-  private String name;
   private int value;
   private int value;
   private boolean changed;
   private boolean changed;
   
   
+  
   /**
   /**
    * Constructor - create a new metric
    * Constructor - create a new metric
    * @param nam the name of the metrics to be used to publish the metric
    * @param nam the name of the metrics to be used to publish the metric
+   * @param registry - where the metrics object will be registered
    */
    */
-  public MetricsIntValue(final String nam) {
-    name = nam;
+  public MetricsIntValue(final String nam, final MetricsRegistry registry, final String description) {
+    super(nam, description);
     value = 0;
     value = 0;
     changed = false;
     changed = false;
+    registry.add(nam, this);
+  }
+  
+  /**
+   * Constructor - create a new metric
+   * @param nam the name of the metrics to be used to publish the metric
+   * @param registry - where the metrics object will be registered
+   * A description of {@link #NO_DESCRIPTION} is used
+   */
+  public MetricsIntValue(final String nam, MetricsRegistry registry) {
+    this(nam, registry, NO_DESCRIPTION);
   }
   }
   
   
+  
+  
   /**
   /**
    * Set the value
    * Set the value
    * @param newValue
    * @param newValue
@@ -65,44 +79,7 @@ public class MetricsIntValue {
   public synchronized int get() { 
   public synchronized int get() { 
     return value;
     return value;
   } 
   } 
-
-  /**
-   * Inc metrics for incr vlaue
-   * @param incr - value to be added
-   */
-  public synchronized void inc(final int incr) {
-    value += incr;
-    changed = true;
-  }
   
   
-  /**
-   * Inc metrics by one
-   */
-  public synchronized void inc() {
-    value++;
-    changed = true;
-  }
-
-  /**
-   * Inc metrics for incr vlaue
-   * @param decr - value to subtract
-   */
-  public synchronized void dec(final int decr) {
-    value -= decr;
-    if (value < 0)
-      value = 0;
-    changed = true;
-  }
-  
-  /**
-   * Dec metrics by one
-   */
-  public synchronized void dec() {
-    value--;
-    if (value < 0)
-      value = 0;
-    changed = true;
-  }
 
 
   /**
   /**
    * Push the metric to the mr.
    * Push the metric to the mr.
@@ -116,9 +93,9 @@ public class MetricsIntValue {
   public synchronized void pushMetric(final MetricsRecord mr) {
   public synchronized void pushMetric(final MetricsRecord mr) {
     if (changed) {
     if (changed) {
       try {
       try {
-        mr.setMetric(name, value);
+        mr.setMetric(getName(), value);
       } catch (Exception e) {
       } catch (Exception e) {
-        LOG.info("pushMetric failed for " + name + "\n" +
+        LOG.info("pushMetric failed for " + getName() + "\n" +
             StringUtils.stringifyException(e));
             StringUtils.stringifyException(e));
       }
       }
     }
     }

+ 17 - 43
src/core/org/apache/hadoop/metrics/util/MetricsLongValue.java

@@ -27,19 +27,30 @@ import org.apache.hadoop.metrics.MetricsRecord;
  * call.
  * call.
  *
  *
  */
  */
-public class MetricsLongValue {  
-  private String name;
+public class MetricsLongValue extends MetricsBase{  
   private long value;
   private long value;
   private boolean changed;
   private boolean changed;
   
   
   /**
   /**
    * Constructor - create a new metric
    * Constructor - create a new metric
    * @param nam the name of the metrics to be used to publish the metric
    * @param nam the name of the metrics to be used to publish the metric
+   * @param registry - where the metrics object will be registered
    */
    */
-  public MetricsLongValue(final String nam) {
-    name = nam;
+  public MetricsLongValue(final String nam, final MetricsRegistry registry, final String description) {
+    super(nam, description);
     value = 0;
     value = 0;
     changed = false;
     changed = false;
+    registry.add(nam, this);
+  }
+  
+  /**
+   * Constructor - create a new metric
+   * @param nam the name of the metrics to be used to publish the metric
+   * @param registry - where the metrics object will be registered
+   * A description of {@link #NO_DESCRIPTION} is used
+   */
+  public MetricsLongValue(final String nam, MetricsRegistry registry) {
+    this(nam, registry, NO_DESCRIPTION);
   }
   }
   
   
   /**
   /**
@@ -58,44 +69,7 @@ public class MetricsLongValue {
   public synchronized long get() { 
   public synchronized long get() { 
     return value;
     return value;
   } 
   } 
-  
-  /**
-   * Inc metrics for incr vlaue
-   * @param incr - value to be added
-   */
-  public synchronized void inc(final long incr) {
-    value += incr;
-    changed = true;
-  }
-  
-  /**
-   * Inc metrics by one
-   */
-  public synchronized void inc() {
-    value++;
-    changed = true;
-  }
-
-  /**
-   * Inc metrics for incr vlaue
-   * @param decr - value to subtract
-   */
-  public synchronized void dec(final long decr) {
-    value -= decr;
-    if (value < 0)
-      value = 0;
-    changed = true;
-  }
-  
-  /**
-   * Dec metrics by one
-   */
-  public synchronized void dec() {
-    value--;
-    if (value < 0)
-      value = 0;
-    changed = true;
-  }
+ 
 
 
   /**
   /**
    * Push the metric to the mr.
    * Push the metric to the mr.
@@ -108,7 +82,7 @@ public class MetricsLongValue {
    */
    */
   public synchronized void pushMetric(final MetricsRecord mr) {
   public synchronized void pushMetric(final MetricsRecord mr) {
     if (changed) 
     if (changed) 
-      mr.setMetric(name, value);
+      mr.setMetric(getName(), value);
     changed = false;
     changed = false;
   }
   }
 }
 }

+ 88 - 0
src/core/org/apache/hadoop/metrics/util/MetricsRegistry.java

@@ -0,0 +1,88 @@
+/**
+ * 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.metrics.util;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+
+/**
+ * 
+ * This is the registry for metrics.
+ * Related set of metrics should be declared in a holding class and registered
+ * in a registry for those metrics which is also stored in the the holding class.
+ *
+ */
+public class MetricsRegistry {
+  private Map<String, MetricsBase> metricsList = new HashMap<String, MetricsBase>();
+
+  public MetricsRegistry() {
+  }
+  
+  /**
+   * 
+   * @return number of metrics in the registry
+   */
+  public int size() {
+    return metricsList.size();
+  }
+  
+  /**
+   * Add a new metrics to the registry
+   * @param metricsName - the name
+   * @param theMetricsObj - the metrics
+   * @throws IllegalArgumentException if a name is already registered
+   */
+  public synchronized void add(final String metricsName, final MetricsBase theMetricsObj) {
+    if (metricsList.containsKey(metricsName)) {
+      throw new IllegalArgumentException("Duplicate metricsName:" + metricsName);
+    }
+    metricsList.put(metricsName, theMetricsObj);
+  }
+
+  
+  /**
+   * 
+   * @param metricsName
+   * @return the metrics if there is one registered by the supplied name.
+   *         Returns null if none is registered
+   */
+  public synchronized MetricsBase get(final String metricsName) {
+    return metricsList.get(metricsName);
+  }
+  
+  
+  /**
+   * 
+   * @return the list of metrics names
+   */
+  public synchronized Collection<String> getKeyList() {
+    return metricsList.keySet();
+  }
+  
+  /**
+   * 
+   * @return the list of metrics
+   */
+  public synchronized Collection<MetricsBase> getMetricsList() {
+    return metricsList.values();
+  }
+}

+ 36 - 9
src/core/org/apache/hadoop/metrics/util/MetricsTimeVaryingInt.java

@@ -25,32 +25,51 @@ import org.apache.commons.logging.LogFactory;
 
 
 /**
 /**
  * The MetricsTimeVaryingInt class is for a metric that naturally
  * The MetricsTimeVaryingInt class is for a metric that naturally
- * varies over time (e.g. number of files created).
- * The metric is is published at interval heart beat (the interval
- * is set in the metrics config file).
+ * varies over time (e.g. number of files created). The metrics is accumulated
+ * over an interval (set in the metrics config file); the metrics is
+ *  published at the end of each interval and then 
+ * reset to zero. Hence the counter has the value in the current interval. 
+ * 
  * Note if one wants a time associated with the metric then use
  * Note if one wants a time associated with the metric then use
  * @see org.apache.hadoop.metrics.util.MetricsTimeVaryingRate
  * @see org.apache.hadoop.metrics.util.MetricsTimeVaryingRate
  *
  *
  */
  */
-public class MetricsTimeVaryingInt {
+public class MetricsTimeVaryingInt extends MetricsBase {
 
 
   private static final Log LOG =
   private static final Log LOG =
     LogFactory.getLog("org.apache.hadoop.metrics.util");
     LogFactory.getLog("org.apache.hadoop.metrics.util");
   
   
-  private String name;
   private int currentValue;
   private int currentValue;
   private int previousIntervalValue;
   private int previousIntervalValue;
   
   
+  
   /**
   /**
    * Constructor - create a new metric
    * Constructor - create a new metric
    * @param nam the name of the metrics to be used to publish the metric
    * @param nam the name of the metrics to be used to publish the metric
+   * @param registry - where the metrics object will be registered
+   * @param description - the description
    */
    */
-  public MetricsTimeVaryingInt(final String nam) {
-    name = nam;
+  public MetricsTimeVaryingInt(final String nam,
+                               final MetricsRegistry registry,
+                               final String description) {
+    super(nam, description);
     currentValue = 0;
     currentValue = 0;
     previousIntervalValue = 0;
     previousIntervalValue = 0;
+    registry.add(nam, this);
+  }
+  
+  /**
+   * Constructor - create a new metric
+   * @param nam the name of the metrics to be used to publish the metric
+   * @param registry - where the metrics object will be registered
+   * A description of {@link #NO_DESCRIPTION} is used
+   */
+  public MetricsTimeVaryingInt(final String nam, final MetricsRegistry registry) {
+    this(nam, registry, NO_DESCRIPTION);
   }
   }
   
   
+
+  
   /**
   /**
    * Inc metrics for incr vlaue
    * Inc metrics for incr vlaue
    * @param incr - number of operations
    * @param incr - number of operations
@@ -83,9 +102,9 @@ public class MetricsTimeVaryingInt {
   public synchronized void pushMetric(final MetricsRecord mr) {
   public synchronized void pushMetric(final MetricsRecord mr) {
     intervalHeartBeat();
     intervalHeartBeat();
     try {
     try {
-      mr.incrMetric(name, getPreviousIntervalValue());
+      mr.incrMetric(getName(), getPreviousIntervalValue());
     } catch (Exception e) {
     } catch (Exception e) {
-      LOG.info("pushMetric failed for " + name + "\n" +
+      LOG.info("pushMetric failed for " + getName() + "\n" +
           StringUtils.stringifyException(e));
           StringUtils.stringifyException(e));
     }
     }
   }
   }
@@ -97,5 +116,13 @@ public class MetricsTimeVaryingInt {
    */
    */
   public synchronized int getPreviousIntervalValue() { 
   public synchronized int getPreviousIntervalValue() { 
     return previousIntervalValue;
     return previousIntervalValue;
+  }
+  
+  /**
+   * The Value at the current interval
+   * @return prev interval value
+   */
+  public synchronized int getCurrentIntervalValue() { 
+    return currentValue;
   } 
   } 
 }
 }

+ 124 - 0
src/core/org/apache/hadoop/metrics/util/MetricsTimeVaryingLong.java

@@ -0,0 +1,124 @@
+package org.apache.hadoop.metrics.util;
+
+/**
+ * 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.
+ */
+
+import org.apache.hadoop.metrics.MetricsRecord;
+import org.apache.hadoop.util.StringUtils;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * The MetricsTimeVaryingLong class is for a metric that naturally
+ * varies over time (e.g. number of files created). The metrics is accumulated
+ * over an interval (set in the metrics config file); the metrics is
+ *  published at the end of each interval and then 
+ * reset to zero. Hence the counter has the value in the current interval. 
+ * 
+ * Note if one wants a time associated with the metric then use
+ * @see org.apache.hadoop.metrics.util.MetricsTimeVaryingRate
+ *
+ */
+public class MetricsTimeVaryingLong extends MetricsBase{
+
+  private static final Log LOG =
+    LogFactory.getLog("org.apache.hadoop.metrics.util");
+ 
+  private long currentValue;
+  private long previousIntervalValue;
+  
+  /**
+   * Constructor - create a new metric
+   * @param nam the name of the metrics to be used to publish the metric
+   * @param registry - where the metrics object will be registered
+   */
+  public MetricsTimeVaryingLong(final String nam, MetricsRegistry registry, final String description) {
+    super(nam, description);
+    currentValue = 0;
+    previousIntervalValue = 0;
+    registry.add(nam, this);
+  }
+  
+  
+  /**
+   * Constructor - create a new metric
+   * @param nam the name of the metrics to be used to publish the metric
+   * @param registry - where the metrics object will be registered
+   * A description of {@link #NO_DESCRIPTION} is used
+   */
+  public MetricsTimeVaryingLong(final String nam, MetricsRegistry registry) {
+    this(nam, registry, NO_DESCRIPTION);
+  }
+  
+  /**
+   * Inc metrics for incr vlaue
+   * @param incr - number of operations
+   */
+  public synchronized void inc(final long incr) {
+    currentValue += incr;
+  }
+  
+  /**
+   * Inc metrics by one
+   */
+  public synchronized void inc() {
+    currentValue++;
+  }
+
+  private synchronized void intervalHeartBeat() {
+     previousIntervalValue = currentValue;
+     currentValue = 0;
+  }
+  
+  /**
+   * Push the delta  metrics to the mr.
+   * The delta is since the last push/interval.
+   * 
+   * Note this does NOT push to JMX
+   * (JMX gets the info via {@link #previousIntervalValue}
+   *
+   * @param mr
+   */
+  public synchronized void pushMetric(final MetricsRecord mr) {
+    intervalHeartBeat();
+    try {
+      mr.incrMetric(getName(), getPreviousIntervalValue());
+    } catch (Exception e) {
+      LOG.info("pushMetric failed for " + getName() + "\n" +
+          StringUtils.stringifyException(e));
+    }
+  }
+  
+  
+  /**
+   * The Value at the Previous interval
+   * @return prev interval value
+   */
+  public synchronized long getPreviousIntervalValue() { 
+    return previousIntervalValue;
+  } 
+  
+  /**
+   * The Value at the current interval
+   * @return prev interval value
+   */
+  public synchronized long getCurrentIntervalValue() { 
+    return currentValue;
+  } 
+}

+ 20 - 8
src/core/org/apache/hadoop/metrics/util/MetricsTimeVaryingRate.java

@@ -32,7 +32,7 @@ import org.apache.commons.logging.LogFactory;
  * a method to reset the min-max.
  * a method to reset the min-max.
  *
  *
  */
  */
-public class MetricsTimeVaryingRate {
+public class MetricsTimeVaryingRate extends MetricsBase {
 
 
   private static final Log LOG =
   private static final Log LOG =
     LogFactory.getLog("org.apache.hadoop.metrics.util");
     LogFactory.getLog("org.apache.hadoop.metrics.util");
@@ -71,7 +71,6 @@ public class MetricsTimeVaryingRate {
       maxTime = Math.max(maxTime, time);
       maxTime = Math.max(maxTime, time);
     }
     }
   }
   }
-  private String name;
   private Metrics currentData;
   private Metrics currentData;
   private Metrics previousIntervalData;
   private Metrics previousIntervalData;
   private MinMax minMax;
   private MinMax minMax;
@@ -79,13 +78,26 @@ public class MetricsTimeVaryingRate {
   
   
   /**
   /**
    * Constructor - create a new metric
    * Constructor - create a new metric
-   * @param n the name of the metrics to be used to publish the metric
+   * @param nam the name of the metrics to be used to publish the metric
+   * @param registry - where the metrics object will be registered
    */
    */
-  public MetricsTimeVaryingRate(final String n) {
-    name = n;
+  public MetricsTimeVaryingRate(final String nam, final MetricsRegistry registry, final String description) {
+    super(nam, description);
     currentData = new Metrics();
     currentData = new Metrics();
     previousIntervalData = new Metrics();
     previousIntervalData = new Metrics();
     minMax = new MinMax();
     minMax = new MinMax();
+    registry.add(nam, this);
+  }
+  
+  /**
+   * Constructor - create a new metric
+   * @param nam the name of the metrics to be used to publish the metric
+   * @param registry - where the metrics object will be registered
+   * A description of {@link #NO_DESCRIPTION} is used
+   */
+  public MetricsTimeVaryingRate(final String nam, MetricsRegistry registry) {
+    this(nam, registry, NO_DESCRIPTION);
+
   }
   }
   
   
   
   
@@ -133,10 +145,10 @@ public class MetricsTimeVaryingRate {
   public synchronized void pushMetric(final MetricsRecord mr) {
   public synchronized void pushMetric(final MetricsRecord mr) {
     intervalHeartBeat();
     intervalHeartBeat();
     try {
     try {
-      mr.incrMetric(name + "_num_ops", getPreviousIntervalNumOps());
-      mr.setMetric(name + "_avg_time", getPreviousIntervalAverageTime());
+      mr.incrMetric(getName() + "_num_ops", getPreviousIntervalNumOps());
+      mr.setMetric(getName() + "_avg_time", getPreviousIntervalAverageTime());
     } catch (Exception e) {
     } catch (Exception e) {
-      LOG.info("pushMetric failed for " + name + "\n" +
+      LOG.info("pushMetric failed for " + getName() + "\n" +
           StringUtils.stringifyException(e));
           StringUtils.stringifyException(e));
     }
     }
   }
   }

+ 8 - 6
src/hdfs/org/apache/hadoop/hdfs/server/datanode/FSDataset.java

@@ -1383,23 +1383,25 @@ public class FSDataset implements FSConstants, FSDatasetInterface {
 
 
   private ObjectName mbeanName;
   private ObjectName mbeanName;
   private Random rand = new Random();
   private Random rand = new Random();
+  
   /**
   /**
-   * Register the FSDataset MBean
+   * Register the FSDataset MBean using the name
+   *        "hadoop:service=DataNode,name=FSDatasetState-<storageid>"
    */
    */
   void registerMBean(final String storageId) {
   void registerMBean(final String storageId) {
     // We wrap to bypass standard mbean naming convetion.
     // We wrap to bypass standard mbean naming convetion.
     // This wraping can be removed in java 6 as it is more flexible in 
     // This wraping can be removed in java 6 as it is more flexible in 
     // package naming for mbeans and their impl.
     // package naming for mbeans and their impl.
     StandardMBean bean;
     StandardMBean bean;
-    String serverName;
-    if (storageId.equals("")) {// Temp fix for the uninitialized storage
-      serverName = "DataNode-UndefinedStorageId" + rand.nextInt();
+    String storageName;
+    if (storageId == null || storageId.equals("")) {// Temp fix for the uninitialized storage
+      storageName = "UndefinedStorageId" + rand.nextInt();
     } else {
     } else {
-      serverName = "DataNode-" + storageId;
+      storageName = storageId;
     }
     }
     try {
     try {
       bean = new StandardMBean(this,FSDatasetMBean.class);
       bean = new StandardMBean(this,FSDatasetMBean.class);
-      mbeanName = MBeanUtil.registerMBean(serverName, "FSDatasetStatus", bean);
+      mbeanName = MBeanUtil.registerMBean("DataNode", "FSDatasetState-" + storageName, bean);
     } catch (NotCompliantMBeanException e) {
     } catch (NotCompliantMBeanException e) {
       e.printStackTrace();
       e.printStackTrace();
     }
     }

+ 76 - 0
src/hdfs/org/apache/hadoop/hdfs/server/datanode/metrics/DataNodeActivityMBean.java

@@ -0,0 +1,76 @@
+/**
+ * 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.hdfs.server.datanode.metrics;
+import java.util.Random;
+
+import javax.management.ObjectName;
+import org.apache.hadoop.metrics.util.MBeanUtil;
+import org.apache.hadoop.metrics.util.MetricsDynamicMBeanBase;
+import org.apache.hadoop.metrics.util.MetricsRegistry;
+
+/**
+ * 
+ * This is the JMX MBean for reporting the DataNode Activity.
+ * The MBean is register using the name
+ *        "hadoop:service=DataNode,name=DataNodeActivity-<storageid>"
+ * 
+ * Many of the activity metrics are sampled and averaged on an interval 
+ * which can be specified in the metrics config file.
+ * <p>
+ * For the metrics that are sampled and averaged, one must specify 
+ * a metrics context that does periodic update calls. Most metrics contexts do.
+ * The default Null metrics context however does NOT. So if you aren't
+ * using any other metrics context then you can turn on the viewing and averaging
+ * of sampled metrics by  specifying the following two lines
+ *  in the hadoop-meterics.properties file:
+*  <pre>
+ *        dfs.class=org.apache.hadoop.metrics.spi.NullContextWithUpdateThread
+ *        dfs.period=10
+ *  </pre>
+ *<p>
+ * Note that the metrics are collected regardless of the context used.
+ * The context with the update thread is used to average the data periodically
+ *
+ *
+ *
+ * Impl details: We use a dynamic mbean that gets the list of the metrics
+ * from the metrics registry passed as an argument to the constructor
+ */
+
+public class DataNodeActivityMBean extends MetricsDynamicMBeanBase {
+  final private ObjectName mbeanName;
+  private Random rand = new Random(); 
+
+  public DataNodeActivityMBean(final MetricsRegistry mr, final String storageId) {
+    super(mr, "Activity statistics at the DataNode");
+    String storageName;
+    if (storageId.equals("")) {// Temp fix for the uninitialized storage
+      storageName = "UndefinedStorageId" + rand.nextInt();
+    } else {
+      storageName = storageId;
+    }
+    mbeanName = MBeanUtil.registerMBean("DataNode", "DataNodeActivity-" + storageName, this);
+  }
+  
+
+  public void shutdown() {
+    if (mbeanName != null)
+      MBeanUtil.unregisterMBean(mbeanName);
+  }
+}

+ 33 - 49
src/hdfs/org/apache/hadoop/hdfs/server/datanode/metrics/DataNodeMetrics.java

@@ -23,8 +23,10 @@ import org.apache.hadoop.metrics.MetricsRecord;
 import org.apache.hadoop.metrics.MetricsUtil;
 import org.apache.hadoop.metrics.MetricsUtil;
 import org.apache.hadoop.metrics.Updater;
 import org.apache.hadoop.metrics.Updater;
 import org.apache.hadoop.metrics.jvm.JvmMetrics;
 import org.apache.hadoop.metrics.jvm.JvmMetrics;
+import org.apache.hadoop.metrics.util.MetricsBase;
+import org.apache.hadoop.metrics.util.MetricsRegistry;
 import org.apache.hadoop.metrics.util.MetricsTimeVaryingInt;
 import org.apache.hadoop.metrics.util.MetricsTimeVaryingInt;
-import org.apache.hadoop.metrics.util.MetricsLongValue;
+import org.apache.hadoop.metrics.util.MetricsTimeVaryingLong;
 import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
 import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
 
 
 
 
@@ -42,51 +44,52 @@ import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
  */
  */
 public class DataNodeMetrics implements Updater {
 public class DataNodeMetrics implements Updater {
   private final MetricsRecord metricsRecord;
   private final MetricsRecord metricsRecord;
-  private DataNodeStatistics datanodeStats;
+  private DataNodeActivityMBean datanodeActivityMBean;
+  public MetricsRegistry registry = new MetricsRegistry();
   
   
   
   
-  public MetricsLongValue bytesWritten = 
-                      new MetricsLongValue("bytes_written");
-  public MetricsLongValue bytesRead = 
-                      new MetricsLongValue("bytes_read");
+  public MetricsTimeVaryingLong bytesWritten = 
+                      new MetricsTimeVaryingLong("bytes_written", registry);
+  public MetricsTimeVaryingLong bytesRead = 
+                      new MetricsTimeVaryingLong("bytes_read", registry);
   public MetricsTimeVaryingInt blocksWritten = 
   public MetricsTimeVaryingInt blocksWritten = 
-                      new MetricsTimeVaryingInt("blocks_written");
+                      new MetricsTimeVaryingInt("blocks_written", registry);
   public MetricsTimeVaryingInt blocksRead = 
   public MetricsTimeVaryingInt blocksRead = 
-                      new MetricsTimeVaryingInt("blocks_read");
+                      new MetricsTimeVaryingInt("blocks_read", registry);
   public MetricsTimeVaryingInt blocksReplicated =
   public MetricsTimeVaryingInt blocksReplicated =
-                      new MetricsTimeVaryingInt("blocks_replicated");
+                      new MetricsTimeVaryingInt("blocks_replicated", registry);
   public MetricsTimeVaryingInt blocksRemoved =
   public MetricsTimeVaryingInt blocksRemoved =
-                       new MetricsTimeVaryingInt("blocks_removed");
+                       new MetricsTimeVaryingInt("blocks_removed", registry);
   public MetricsTimeVaryingInt blocksVerified = 
   public MetricsTimeVaryingInt blocksVerified = 
-                        new MetricsTimeVaryingInt("blocks_verified");
+                        new MetricsTimeVaryingInt("blocks_verified", registry);
   public MetricsTimeVaryingInt blockVerificationFailures =
   public MetricsTimeVaryingInt blockVerificationFailures =
-                       new MetricsTimeVaryingInt("block_verification_failures");
+                       new MetricsTimeVaryingInt("block_verification_failures", registry);
   
   
   public MetricsTimeVaryingInt readsFromLocalClient = 
   public MetricsTimeVaryingInt readsFromLocalClient = 
-                new MetricsTimeVaryingInt("reads_from_local_client");
+                new MetricsTimeVaryingInt("reads_from_local_client", registry);
   public MetricsTimeVaryingInt readsFromRemoteClient = 
   public MetricsTimeVaryingInt readsFromRemoteClient = 
-                new MetricsTimeVaryingInt("reads_from_remote_client");
+                new MetricsTimeVaryingInt("reads_from_remote_client", registry);
   public MetricsTimeVaryingInt writesFromLocalClient = 
   public MetricsTimeVaryingInt writesFromLocalClient = 
-              new MetricsTimeVaryingInt("writes_from_local_client");
+              new MetricsTimeVaryingInt("writes_from_local_client", registry);
   public MetricsTimeVaryingInt writesFromRemoteClient = 
   public MetricsTimeVaryingInt writesFromRemoteClient = 
-              new MetricsTimeVaryingInt("writes_from_remote_client");
+              new MetricsTimeVaryingInt("writes_from_remote_client", registry);
   
   
   public MetricsTimeVaryingRate readBlockOp = 
   public MetricsTimeVaryingRate readBlockOp = 
-                new MetricsTimeVaryingRate("readBlockOp");
+                new MetricsTimeVaryingRate("readBlockOp", registry);
   public MetricsTimeVaryingRate writeBlockOp = 
   public MetricsTimeVaryingRate writeBlockOp = 
-                new MetricsTimeVaryingRate("writeBlockOp");
+                new MetricsTimeVaryingRate("writeBlockOp", registry);
   public MetricsTimeVaryingRate readMetadataOp = 
   public MetricsTimeVaryingRate readMetadataOp = 
-                new MetricsTimeVaryingRate("readMetadataOp");
+                new MetricsTimeVaryingRate("readMetadataOp", registry);
   public MetricsTimeVaryingRate blockChecksumOp = 
   public MetricsTimeVaryingRate blockChecksumOp = 
-                new MetricsTimeVaryingRate("blockChecksumOp");
+                new MetricsTimeVaryingRate("blockChecksumOp", registry);
   public MetricsTimeVaryingRate copyBlockOp = 
   public MetricsTimeVaryingRate copyBlockOp = 
-                new MetricsTimeVaryingRate("copyBlockOp");
+                new MetricsTimeVaryingRate("copyBlockOp", registry);
   public MetricsTimeVaryingRate replaceBlockOp = 
   public MetricsTimeVaryingRate replaceBlockOp = 
-                new MetricsTimeVaryingRate("replaceBlockOp");
+                new MetricsTimeVaryingRate("replaceBlockOp", registry);
   public MetricsTimeVaryingRate heartbeats = 
   public MetricsTimeVaryingRate heartbeats = 
-                    new MetricsTimeVaryingRate("heartBeats");
+                    new MetricsTimeVaryingRate("heartBeats", registry);
   public MetricsTimeVaryingRate blockReports = 
   public MetricsTimeVaryingRate blockReports = 
-                    new MetricsTimeVaryingRate("blockReports");
+                    new MetricsTimeVaryingRate("blockReports", registry);
 
 
     
     
   public DataNodeMetrics(Configuration conf, String storageId) {
   public DataNodeMetrics(Configuration conf, String storageId) {
@@ -96,7 +99,7 @@ public class DataNodeMetrics implements Updater {
     
     
 
 
     // Now the MBean for the data node
     // Now the MBean for the data node
-    datanodeStats = new DataNodeStatistics(this, storageId);
+    datanodeActivityMBean = new DataNodeActivityMBean(registry, storageId);
     
     
     // Create record for DataNode metrics
     // Create record for DataNode metrics
     MetricsContext context = MetricsUtil.getContext("dfs");
     MetricsContext context = MetricsUtil.getContext("dfs");
@@ -106,8 +109,8 @@ public class DataNodeMetrics implements Updater {
   }
   }
   
   
   public void shutdown() {
   public void shutdown() {
-    if (datanodeStats != null) 
-      datanodeStats.shutdown();
+    if (datanodeActivityMBean != null) 
+      datanodeActivityMBean.shutdown();
   }
   }
     
     
   /**
   /**
@@ -116,28 +119,9 @@ public class DataNodeMetrics implements Updater {
    */
    */
   public void doUpdates(MetricsContext unused) {
   public void doUpdates(MetricsContext unused) {
     synchronized (this) {
     synchronized (this) {
-            
-      bytesWritten.pushMetric(metricsRecord);
-      bytesRead.pushMetric(metricsRecord);
-      blocksWritten.pushMetric(metricsRecord);
-      blocksRead.pushMetric(metricsRecord);
-      blocksReplicated.pushMetric(metricsRecord);
-      blocksRemoved.pushMetric(metricsRecord);
-      blocksVerified.pushMetric(metricsRecord);
-      blockVerificationFailures.pushMetric(metricsRecord);
-      readsFromLocalClient.pushMetric(metricsRecord);
-      writesFromLocalClient.pushMetric(metricsRecord);
-      readsFromRemoteClient.pushMetric(metricsRecord);
-      writesFromRemoteClient.pushMetric(metricsRecord);
-      
-      readBlockOp.pushMetric(metricsRecord);
-      writeBlockOp.pushMetric(metricsRecord);
-      readMetadataOp.pushMetric(metricsRecord);
-      blockChecksumOp.pushMetric(metricsRecord);
-      copyBlockOp.pushMetric(metricsRecord);
-      replaceBlockOp.pushMetric(metricsRecord);
-      heartbeats.pushMetric(metricsRecord);
-      blockReports.pushMetric(metricsRecord);
+      for (MetricsBase m : registry.getMetricsList()) {
+        m.pushMetric(metricsRecord);
+      }
     }
     }
     metricsRecord.update();
     metricsRecord.update();
   }
   }

+ 0 - 371
src/hdfs/org/apache/hadoop/hdfs/server/datanode/metrics/DataNodeStatistics.java

@@ -1,371 +0,0 @@
-/**
- * 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.hdfs.server.datanode.metrics;
-
-import java.util.Random;
-
-import javax.management.ObjectName;
-
-import org.apache.hadoop.metrics.util.MBeanUtil;
-
-public class DataNodeStatistics implements DataNodeStatisticsMBean {
-  private DataNodeMetrics myMetrics;
-  private ObjectName mbeanName;
-  private Random rand = new Random(); 
-  
-  
-
-  /**
-   * This constructs and registers the DataNodeStatisticsMBean
-   * @param dataNodeMetrics - the metrics from which the mbean gets its info
-   */
-  public DataNodeStatistics(DataNodeMetrics dataNodeMetrics, String storageId) {
-    myMetrics = dataNodeMetrics;
-    String serverName;
-    if (storageId.equals("")) {// Temp fix for the uninitialized storage
-      serverName = "DataNode-UndefinedStorageId" + rand.nextInt();
-    } else {
-      serverName = "DataNode-" + storageId;
-    }
-    mbeanName = MBeanUtil.registerMBean(serverName, "DataNodeStatistics", this);
-  }
-  
-  /**
-   * Shuts down the statistics
-   *   - unregisters the mbean
-   */
-  public void shutdown() {
-    if (mbeanName != null)
-      MBeanUtil.unregisterMBean(mbeanName);
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public void resetAllMinMax() {
-    myMetrics.resetAllMinMax();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getBlocksRead() {
-    return myMetrics.blocksRead.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getBlocksRemoved() {
-    return myMetrics.blocksRemoved.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getBlocksReplicated() {
-    return myMetrics.blocksReplicated.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getBlocksWritten() {
-    return myMetrics.blocksWritten.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getBytesRead() {
-    return myMetrics.bytesRead.get();
-  }
-
-  /**
-   *   {@inheritDoc}
-   */
-  public long getBytesWritten() {
-    return myMetrics.bytesWritten.get();
-  }
-  
-  /**
-   * @inheritDoc
-   */
-  public int getBlockVerificationFailures() {
-    return myMetrics.blockVerificationFailures.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getBlocksVerified() {
-    return myMetrics.blocksVerified.getPreviousIntervalValue();
-  }
-  
-  /**
-   * @inheritDoc
-   */
-  public int getReadsFromLocalClient() {
-    return myMetrics.readsFromLocalClient.getPreviousIntervalValue();
-  }
-  
-  /**
-   * @inheritDoc
-   */
-  public int getReadsFromRemoteClient() {
-    return myMetrics.readsFromRemoteClient.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getWritesFromLocalClient() {
-    return myMetrics.writesFromLocalClient.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getWritesFromRemoteClient() {
-    return myMetrics.writesFromRemoteClient.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getReadBlockOpAverageTime() {
-    return myMetrics.readBlockOp.getPreviousIntervalAverageTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getReadBlockOpMaxTime() {
-    return myMetrics.readBlockOp.getMaxTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getReadBlockOpMinTime() {
-    return myMetrics.readBlockOp.getMinTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getReadBlockOpNum() {
-    return myMetrics.readBlockOp.getPreviousIntervalNumOps();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getReadMetadataOpAverageTime() {
-    return myMetrics.readMetadataOp.getPreviousIntervalAverageTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getReadMetadataOpMaxTime() {
-    return myMetrics.readMetadataOp.getMaxTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getReadMetadataOpMinTime() {
-    return myMetrics.readMetadataOp.getMinTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getReadMetadataOpNum() {
-    return myMetrics.readMetadataOp.getPreviousIntervalNumOps();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getBlockChecksumOpAverageTime() {
-    return myMetrics.blockChecksumOp.getPreviousIntervalAverageTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getBlockChecksumOpMaxTime() {
-    return myMetrics.blockChecksumOp.getMaxTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getBlockChecksumOpMinTime() {
-    return myMetrics.blockChecksumOp.getMinTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getBlockChecksumOpNum() {
-    return myMetrics.blockChecksumOp.getPreviousIntervalNumOps();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getReplaceBlockOpAverageTime() {
-    return myMetrics.replaceBlockOp.getPreviousIntervalAverageTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getReplaceBlockOpMaxTime() {
-    return myMetrics.replaceBlockOp.getMaxTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getReplaceBlockOpMinTime() {
-    return myMetrics.replaceBlockOp.getMinTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getReplaceBlockOpNum() {
-    return myMetrics.replaceBlockOp.getPreviousIntervalNumOps();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getWriteBlockOpAverageTime() {
-    return myMetrics.writeBlockOp.getPreviousIntervalAverageTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getWriteBlockOpMaxTime() {
-    return myMetrics.writeBlockOp.getMaxTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getWriteBlockOpMinTime() {
-    return myMetrics.writeBlockOp.getMinTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getWriteBlockOpNum() {
-    return myMetrics.writeBlockOp.getPreviousIntervalNumOps();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getCopyBlockOpAverageTime() {
-    return myMetrics.copyBlockOp.getPreviousIntervalAverageTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getCopyBlockOpMaxTime() {
-    return myMetrics.copyBlockOp.getMaxTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getCopyBlockOpMinTime() {
-    return myMetrics.copyBlockOp.getMinTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getCopyBlockOpNum() {
-    return myMetrics.copyBlockOp.getPreviousIntervalNumOps();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getBlockReportsAverageTime() {
-    return myMetrics.blockReports.getPreviousIntervalAverageTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getBlockReportsMaxTime() {
-    return myMetrics.blockReports.getMaxTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getBlockReportsMinTime() {
-    return myMetrics.blockReports.getMinTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getBlockReportsNum() {
-    return myMetrics.blockReports.getPreviousIntervalNumOps();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getHeartbeatsAverageTime() {
-    return myMetrics.heartbeats.getPreviousIntervalAverageTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getHeartbeatsMaxTime() {
-    return myMetrics.heartbeats.getMaxTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getHeartbeatsMinTime() {
-    return myMetrics.heartbeats.getMinTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getHeartbeatsNum() {
-    return myMetrics.heartbeats.getPreviousIntervalNumOps();
-  }
-}

+ 0 - 320
src/hdfs/org/apache/hadoop/hdfs/server/datanode/metrics/DataNodeStatisticsMBean.java

@@ -1,320 +0,0 @@
-/**
- * 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.hdfs.server.datanode.metrics;
-
-/**
- * 
- * This is the JMX  interface for the runtime statistics for the data node.
- * Many of the statistics are sampled and averaged on an interval 
- * which can be specified in the config file.
- * <p>
- * For the statistics that are sampled and averaged, one must specify 
- * a metrics context that does periodic update calls. Most do.
- * The default Null metrics context however does NOT. So if you aren't
- * using any other metrics context then you can turn on the viewing and averaging
- * of sampled metrics by  specifying the following two lines
- *  in the hadoop-meterics.properties file:
- *  <pre>
- *        dfs.class=org.apache.hadoop.metrics.spi.NullContextWithUpdateThread
- *        dfs.period=10
- *  </pre>
- *<p>
- * Note that the metrics are collected regardless of the context used.
- * The context with the update thread is used to average the data periodically.
- * <p>
- * Name Node Status info is reported in another MBean
- * @see org.apache.hadoop.hdfs.server.datanode.metrics.FSDatasetMBean
- *
- */
-public interface DataNodeStatisticsMBean {
-  
-  /**
-   *   Number of bytes written in the last interval
-   * @return number of bytes written
-   */
-  long getBytesWritten();
-  
-  /**
-   *   Number of bytes read in the last interval
-   * @return number of bytes read
-   */
-  long getBytesRead();
-  
-  /**
-   *   Number of blocks written in the last interval
-   * @return number of blocks written
-   */
-  int getBlocksWritten(); 
-  
-  /**
-   *   Number of blocks read in the last interval
-   * @return number of blocks read
-   */
-  int getBlocksRead(); 
-  
-  /**
-   *   Number of blocks replicated in the last interval
-   * @return number of blocks replicated
-   */
-  int getBlocksReplicated();
-  
-  /**
-   *   Number of blocks removed in the last interval
-   * @return number of blocks removed
-   */
-  int getBlocksRemoved();
-  
-  /**
-   *   Number of blocks verified in the last interval
-   * @return number of blocks verified
-   */
-  int getBlocksVerified();
-  
-  /**
-   *   Number of block verification failures in the last interval
-   * @return number of block verification failures
-   */
-  int getBlockVerificationFailures();
-  
-  /**
-   * Number of reads from local clients in the last interval
-   * @return number of reads from local clients
-   */
-  int getReadsFromLocalClient();
-  
-  
-  /**
-   * Number of reads from remote clients in the last interval
-   * @return number of reads from remote clients
-   */
-  int getReadsFromRemoteClient();
-  
-  
-  /**
-   * Number of writes from local clients in the last interval
-   * @return number of writes from local clients
-   */
-  int getWritesFromLocalClient();
-  
-  
-  /**
-   * Number of writes from remote clients in the last interval
-   * @return number of writes from remote clients
-   */
-  int getWritesFromRemoteClient();
-
-  /**
-   * Number of ReadBlock Operation in last interval
-   * @return number of operations
-   */
-  int getReadBlockOpNum();  
-
-  /**
-   * Average time for ReadBlock Operation in last interval
-   * @return time in msec
-   */
-  long getReadBlockOpAverageTime();
-  
-  /**
-   *   The Minimum ReadBlock Operation Time since reset was called
-   * @return time in msec
-   */
-  long getReadBlockOpMinTime();
-  
-  /**
-   *   The Maximum ReadBlock Operation Time since reset was called
-   * @return time in msec
-   */
-  long getReadBlockOpMaxTime();
-  
-  /**
-   * Number of WriteBlock Operation in last interval
-   * @return number of operations
-   */
-  int getWriteBlockOpNum();
-
-  /**
-   * Average time for WriteBlock Operation in last interval
-   * @return time in msec
-   */
-  long getWriteBlockOpAverageTime();
-  
-  /**
-   *   The Minimum WriteBlock Operation Time since reset was called
-   * @return time in msec
-   */
-  long getWriteBlockOpMinTime();
-  
-  /**
-   *   The Maximum WriteBlock Operation Time since reset was called
-   * @return time in msec
-   */
-  long getWriteBlockOpMaxTime(); 
-  
-  /**
-   * Number of ReadMetadata Operation in last interval
-   * @return number of operations
-   */
-  int getReadMetadataOpNum(); 
-
-  /**
-   * Average time for ReadMetadata Operation in last interval
-   * @return time in msec
-   */
-  long getReadMetadataOpAverageTime();
-  
-  /**
-   *   The Minimum ReadMetadata Operation Time since reset was called
-   * @return time in msec
-   */
-  long getReadMetadataOpMinTime();
-  
-  /**
-   *   The Maximum ReadMetadata Operation Time since reset was called
-   * @return time in msec
-   */
-  long getReadMetadataOpMaxTime();
-  
-  /**
-   * Number of block BlockChecksum in last interval
-   * @return number of operations
-   */
-  int getBlockChecksumOpNum(); 
-
-  /**
-   * Average time for BlockChecksum Operation in last interval
-   * @return time in msec
-   */
-  long getBlockChecksumOpAverageTime();
-  
-  /**
-   *   The Minimum BlockChecksum Operation Time since reset was called
-   * @return time in msec
-   */
-  long getBlockChecksumOpMinTime();
-  
-  /**
-   *   The Maximum BlockChecksum Operation Time since reset was called
-   * @return time in msec
-   */
-  long getBlockChecksumOpMaxTime();
-  
-  /**
-   * Number of CopyBlock Operation in last interval
-   * @return number of operations
-   */
-  int getCopyBlockOpNum();
-
-  /**
-   * Average time for CopyBlock Operation in last interval
-   * @return time in msec
-   */
-  long getCopyBlockOpAverageTime();
-  
-  /**
-   *   The Minimum CopyBlock Operation Time since reset was called
-   * @return time in msec
-   */
-  long getCopyBlockOpMinTime();
-  
-  /**
-   *   The Maximum CopyBlock Operation Time since reset was called
-   * @return time in msec
-   */
-  long getCopyBlockOpMaxTime();
-
-  /**
-   * Number of ReplaceBlock Operation in last interval
-   * @return number of operations
-   */
-  int getReplaceBlockOpNum();
-  
-
-  /**
-   * Average time for ReplaceBlock Operation in last interval
-   * @return time in msec
-   */
-  long getReplaceBlockOpAverageTime();
-  
-  /**
-   *   The Minimum ReplaceBlock Operation Time since reset was called
-   * @return time in msec
-   */
-  long getReplaceBlockOpMinTime();
-  
-  /**
-   *   The Maximum ReplaceBlock Operation Time since reset was called
-   * @return time in msec
-   */
-  long getReplaceBlockOpMaxTime();
-  
-  /**
-   * Number of Block Reports sent in last interval
-   * @return number of operations
-   */
-  int getBlockReportsNum();
-
-  /**
-   * Average time for Block Reports Operation in last interval
-   * @return time in msec
-   */
-  long getBlockReportsAverageTime();
-  
-  /**
-   *   The Minimum Block Reports Operation Time since reset was called
-   * @return time in msec
-   */
-  long getBlockReportsMinTime();
-  
-  /**
-   *   The Maximum Block Reports Operation Time since reset was called
-   * @return time in msec
-   */
-  long getBlockReportsMaxTime();
-
-  /**
-   * Number of Heartbeat Operation in last interval
-   * @return number of operations
-   */
-  int getHeartbeatsNum();
-
-  /**
-   * Average time for Heartbeat Operation in last interval
-   * @return time in msec
-   */
-  long getHeartbeatsAverageTime();
-  
-  /**
-   *   The Minimum Heartbeat Operation Time since reset was called
-   * @return time in msec
-   */
-  long getHeartbeatsMinTime();
-  
-  /**
-   *   The Maximum Heartbeat Operation Time since reset was called
-   * @return time in msec
-   */
-  long getHeartbeatsMaxTime();
-  
-  
-  /**
-   * Reset all min max times
-   */
-  public void resetAllMinMax();
-}

+ 4 - 0
src/hdfs/org/apache/hadoop/hdfs/server/datanode/metrics/FSDatasetMBean.java

@@ -25,6 +25,10 @@ import java.io.IOException;
  * a data node.
  * a data node.
  * It is also used for publishing via JMX (hence we follow the JMX naming
  * It is also used for publishing via JMX (hence we follow the JMX naming
  * convention.) 
  * convention.) 
+ *  * Note we have not used the MetricsDynamicMBeanBase to implement this
+ * because the interface for the FSDatasetMBean is stable and should
+ * be published as an interface.
+ * 
  * <p>
  * <p>
  * Data Node runtime statistic  info is report in another MBean
  * Data Node runtime statistic  info is report in another MBean
  * @see org.apache.hadoop.hdfs.server.datanode.metrics.DataNodeStatisticsMBean
  * @see org.apache.hadoop.hdfs.server.datanode.metrics.DataNodeStatisticsMBean

+ 8 - 2
src/hdfs/org/apache/hadoop/hdfs/server/namenode/FSEditLog.java

@@ -87,6 +87,7 @@ public class FSEditLog {
 
 
   // these are statistics counters.
   // these are statistics counters.
   private long numTransactions;        // number of transactions
   private long numTransactions;        // number of transactions
+  private long numTransactionsBatchedInSync;
   private long totalTimeTransactions;  // total time for all transactions
   private long totalTimeTransactions;  // total time for all transactions
   private NameNodeMetrics metrics;
   private NameNodeMetrics metrics;
 
 
@@ -326,7 +327,7 @@ public class FSEditLog {
    * @throws IOException
    * @throws IOException
    */
    */
   public synchronized void open() throws IOException {
   public synchronized void open() throws IOException {
-    numTransactions = totalTimeTransactions = 0;
+    numTransactions = totalTimeTransactions = numTransactionsBatchedInSync = 0;
     if (editStreams == null)
     if (editStreams == null)
       editStreams = new ArrayList<EditLogOutputStream>();
       editStreams = new ArrayList<EditLogOutputStream>();
     for (Iterator<StorageDirectory> it = 
     for (Iterator<StorageDirectory> it = 
@@ -376,7 +377,7 @@ public class FSEditLog {
       return;
       return;
     }
     }
     printStatistics(true);
     printStatistics(true);
-    numTransactions = totalTimeTransactions = 0;
+    numTransactions = totalTimeTransactions = numTransactionsBatchedInSync = 0;
 
 
     for (int idx = 0; idx < editStreams.size(); idx++) {
     for (int idx = 0; idx < editStreams.size(); idx++) {
       EditLogOutputStream eStream = editStreams.get(idx);
       EditLogOutputStream eStream = editStreams.get(idx);
@@ -896,6 +897,9 @@ public class FSEditLog {
       // If this transaction was already flushed, then nothing to do
       // If this transaction was already flushed, then nothing to do
       //
       //
       if (mytxid <= synctxid) {
       if (mytxid <= synctxid) {
+        numTransactionsBatchedInSync++;
+        if (metrics != null) // Metrics is non-null only when used inside name node
+          metrics.transactionsBatchedInSync.inc();
         return;
         return;
       }
       }
    
    
@@ -957,6 +961,8 @@ public class FSEditLog {
     buf.append(numTransactions);
     buf.append(numTransactions);
     buf.append(" Total time for transactions(ms): ");
     buf.append(" Total time for transactions(ms): ");
     buf.append(totalTimeTransactions);
     buf.append(totalTimeTransactions);
+    buf.append("Number of transactions batched in Syncs: ");
+    buf.append(numTransactionsBatchedInSync);
     buf.append(" Number of syncs: ");
     buf.append(" Number of syncs: ");
     buf.append(editStreams.get(0).getNumSync());
     buf.append(editStreams.get(0).getNumSync());
     buf.append(" SyncTimes(ms): ");
     buf.append(" SyncTimes(ms): ");

+ 4 - 3
src/hdfs/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java

@@ -4354,17 +4354,18 @@ public class FSNamesystem implements FSConstants, FSNamesystemMBean {
   
   
   private ObjectName mbeanName;
   private ObjectName mbeanName;
   /**
   /**
-   * Register the FSNamesystem MBean
+   * Register the FSNamesystem MBean using the name
+   *        "hadoop:service=NameNode,name=FSNamesystemState"
    */
    */
   void registerMBean(Configuration conf) {
   void registerMBean(Configuration conf) {
-    // We wrap to bypass standard mbean naming convetion.
+    // We wrap to bypass standard mbean naming convention.
     // This wraping can be removed in java 6 as it is more flexible in 
     // This wraping can be removed in java 6 as it is more flexible in 
     // package naming for mbeans and their impl.
     // package naming for mbeans and their impl.
     StandardMBean bean;
     StandardMBean bean;
     try {
     try {
       myFSMetrics = new FSNamesystemMetrics(conf);
       myFSMetrics = new FSNamesystemMetrics(conf);
       bean = new StandardMBean(this,FSNamesystemMBean.class);
       bean = new StandardMBean(this,FSNamesystemMBean.class);
-      mbeanName = MBeanUtil.registerMBean("NameNode", "FSNamesystemStatus", bean);
+      mbeanName = MBeanUtil.registerMBean("NameNode", "FSNamesystemState", bean);
     } catch (NotCompliantMBeanException e) {
     } catch (NotCompliantMBeanException e) {
       e.printStackTrace();
       e.printStackTrace();
     }
     }

+ 6 - 2
src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/FSNamesystemMBean.java

@@ -24,9 +24,13 @@ package org.apache.hadoop.hdfs.server.namenode.metrics;
  * It is also used for publishing via JMX (hence we follow the JMX naming
  * It is also used for publishing via JMX (hence we follow the JMX naming
  * convention.)
  * convention.)
  * 
  * 
+ * Note we have not used the MetricsDynamicMBeanBase to implement this
+ * because the interface for the NameNodeStateMBean is stable and should
+ * be published as an interface.
+ * 
  * <p>
  * <p>
- * Name Node runtime statistic  info is report in another MBean
- * @see org.apache.hadoop.hdfs.server.namenode.metrics.NameNodeStatisticsMBean
+ * Name Node runtime activity statistic  info is report in another MBean
+ * @see org.apache.hadoop.hdfs.server.namenode.metrics.NameNodeActivityMBean
  *
  *
  */
  */
 public interface FSNamesystemMBean {
 public interface FSNamesystemMBean {

+ 25 - 27
src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/FSNamesystemMetrics.java

@@ -17,18 +17,22 @@
  */
  */
 package org.apache.hadoop.hdfs.server.namenode.metrics;
 package org.apache.hadoop.hdfs.server.namenode.metrics;
 
 
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
 import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
 import org.apache.hadoop.metrics.*;
 import org.apache.hadoop.metrics.*;
+import org.apache.hadoop.metrics.util.MetricsBase;
 import org.apache.hadoop.metrics.util.MetricsIntValue;
 import org.apache.hadoop.metrics.util.MetricsIntValue;
+import org.apache.hadoop.metrics.util.MetricsLongValue;
+import org.apache.hadoop.metrics.util.MetricsRegistry;
 
 
 /**
 /**
  * 
  * 
  * This class is for maintaining  the various FSNamesystem status metrics
  * This class is for maintaining  the various FSNamesystem status metrics
  * and publishing them through the metrics interfaces.
  * and publishing them through the metrics interfaces.
- * This also registers the JMX MBean for RPC.
+ * The SNamesystem creates and registers the JMX MBean.
  * <p>
  * <p>
  * This class has a number of metrics variables that are publicly accessible;
  * This class has a number of metrics variables that are publicly accessible;
  * these variables (objects) have methods to update their values;
  * these variables (objects) have methods to update their values;
@@ -39,16 +43,18 @@ import org.apache.hadoop.metrics.util.MetricsIntValue;
 public class FSNamesystemMetrics implements Updater {
 public class FSNamesystemMetrics implements Updater {
   private static Log log = LogFactory.getLog(FSNamesystemMetrics.class);
   private static Log log = LogFactory.getLog(FSNamesystemMetrics.class);
   private final MetricsRecord metricsRecord;
   private final MetricsRecord metricsRecord;
+  public MetricsRegistry registry = new MetricsRegistry();
+
    
    
-  public MetricsIntValue filesTotal = new MetricsIntValue("FilesTotal");
-  public MetricsIntValue blocksTotal = new MetricsIntValue("BlocksTotal");
-  public MetricsIntValue capacityTotalGB = new MetricsIntValue("CapacityTotalGB");
-  public MetricsIntValue capacityUsedGB = new MetricsIntValue("CapacityUsedGB");
-  public MetricsIntValue capacityRemainingGB = new MetricsIntValue("CapacityRemainingGB");
-  public MetricsIntValue totalLoad = new MetricsIntValue("TotalLoad");
-  public MetricsIntValue pendingReplicationBlocks = new MetricsIntValue("PendingReplicationBlocks");
-  public MetricsIntValue underReplicatedBlocks = new MetricsIntValue("UnderReplicatedBlocks");
-  public MetricsIntValue scheduledReplicationBlocks = new MetricsIntValue("ScheduledReplicationBlocks");
+  public MetricsIntValue filesTotal = new MetricsIntValue("FilesTotal", registry);
+  public MetricsLongValue blocksTotal = new MetricsLongValue("BlocksTotal", registry);
+  public MetricsIntValue capacityTotalGB = new MetricsIntValue("CapacityTotalGB", registry);
+  public MetricsIntValue capacityUsedGB = new MetricsIntValue("CapacityUsedGB", registry);
+  public MetricsIntValue capacityRemainingGB = new MetricsIntValue("CapacityRemainingGB", registry);
+  public MetricsIntValue totalLoad = new MetricsIntValue("TotalLoad", registry);
+  public MetricsIntValue pendingReplicationBlocks = new MetricsIntValue("PendingReplicationBlocks", registry);
+  public MetricsIntValue underReplicatedBlocks = new MetricsIntValue("UnderReplicatedBlocks", registry);
+  public MetricsIntValue scheduledReplicationBlocks = new MetricsIntValue("ScheduledReplicationBlocks", registry);
   public FSNamesystemMetrics(Configuration conf) {
   public FSNamesystemMetrics(Configuration conf) {
     String sessionId = conf.get("session.id");
     String sessionId = conf.get("session.id");
      
      
@@ -79,37 +85,29 @@ public class FSNamesystemMetrics implements Updater {
    * int, so they are rounded to GB
    * int, so they are rounded to GB
    */
    */
   public void doUpdates(MetricsContext unused) {
   public void doUpdates(MetricsContext unused) {
+    /** 
+     * ToFix
+     * If the metrics counter were instead stored in the metrics objects themselves
+     * we could avoid copying the values on each update.
+     */
     synchronized (this) {
     synchronized (this) {
       FSNamesystem fsNameSystem = FSNamesystem.getFSNamesystem();
       FSNamesystem fsNameSystem = FSNamesystem.getFSNamesystem();
       filesTotal.set((int)fsNameSystem.getFilesTotal());
       filesTotal.set((int)fsNameSystem.getFilesTotal());
-      filesTotal.pushMetric(metricsRecord);
-
       blocksTotal.set((int)fsNameSystem.getBlocksTotal());
       blocksTotal.set((int)fsNameSystem.getBlocksTotal());
-      blocksTotal.pushMetric(metricsRecord);
-      
       capacityTotalGB.set(roundBytesToGBytes(fsNameSystem.getCapacityTotal()));
       capacityTotalGB.set(roundBytesToGBytes(fsNameSystem.getCapacityTotal()));
-      capacityTotalGB.pushMetric(metricsRecord);
-      
       capacityUsedGB.set(roundBytesToGBytes(fsNameSystem.getCapacityUsed()));
       capacityUsedGB.set(roundBytesToGBytes(fsNameSystem.getCapacityUsed()));
-      capacityUsedGB.pushMetric(metricsRecord);
-      
       capacityRemainingGB.set(roundBytesToGBytes(fsNameSystem.
       capacityRemainingGB.set(roundBytesToGBytes(fsNameSystem.
                                                getCapacityRemaining()));
                                                getCapacityRemaining()));
-      capacityRemainingGB.pushMetric(metricsRecord);
-      
       totalLoad.set(fsNameSystem.getTotalLoad());
       totalLoad.set(fsNameSystem.getTotalLoad());
-      totalLoad.pushMetric(metricsRecord);
-      
       pendingReplicationBlocks.set((int)fsNameSystem.
       pendingReplicationBlocks.set((int)fsNameSystem.
                                    getPendingReplicationBlocks());
                                    getPendingReplicationBlocks());
-      pendingReplicationBlocks.pushMetric(metricsRecord);
-
       underReplicatedBlocks.set((int)fsNameSystem.getUnderReplicatedBlocks());
       underReplicatedBlocks.set((int)fsNameSystem.getUnderReplicatedBlocks());
-      underReplicatedBlocks.pushMetric(metricsRecord);
-
       scheduledReplicationBlocks.set((int)fsNameSystem.
       scheduledReplicationBlocks.set((int)fsNameSystem.
                                       getScheduledReplicationBlocks());
                                       getScheduledReplicationBlocks());
-      scheduledReplicationBlocks.pushMetric(metricsRecord);
+
+      for (MetricsBase m : registry.getMetricsList()) {
+        m.pushMetric(metricsRecord);
+      }
     }
     }
     metricsRecord.update();
     metricsRecord.update();
   }
   }

+ 67 - 0
src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/NameNodeActivtyMBean.java

@@ -0,0 +1,67 @@
+/**
+ * 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.hdfs.server.namenode.metrics;
+
+import javax.management.ObjectName;
+
+import org.apache.hadoop.metrics.util.MBeanUtil;
+import org.apache.hadoop.metrics.util.MetricsDynamicMBeanBase;
+import org.apache.hadoop.metrics.util.MetricsRegistry;
+
+/**
+ * 
+ * This is the JMX MBean for reporting the NameNode Activity.
+ * The MBean is register using the name
+ *        "hadoop:service=NameNode,name=NameNodeActivity"
+ * 
+ * Many of the activity metrics are sampled and averaged on an interval 
+ * which can be specified in the metrics config file.
+ * <p>
+ * For the metrics that are sampled and averaged, one must specify 
+ * a metrics context that does periodic update calls. Most metrics contexts do.
+ * The default Null metrics context however does NOT. So if you aren't
+ * using any other metrics context then you can turn on the viewing and averaging
+ * of sampled metrics by  specifying the following two lines
+ *  in the hadoop-meterics.properties file:
+*  <pre>
+ *        dfs.class=org.apache.hadoop.metrics.spi.NullContextWithUpdateThread
+ *        dfs.period=10
+ *  </pre>
+ *<p>
+ * Note that the metrics are collected regardless of the context used.
+ * The context with the update thread is used to average the data periodically
+ *
+ *
+ *
+ * Impl details: We use a dynamic mbean that gets the list of the metrics
+ * from the metrics registry passed as an argument to the constructor
+ */
+
+public class NameNodeActivtyMBean extends MetricsDynamicMBeanBase {
+  final private ObjectName mbeanName;
+
+  protected NameNodeActivtyMBean(final MetricsRegistry mr) {
+    super(mr, "Activity statistics at the NameNode");
+    mbeanName = MBeanUtil.registerMBean("NameNode", "NameNodeActivity", this);
+  }
+
+  public void shutdown() {
+    if (mbeanName != null)
+      MBeanUtil.unregisterMBean(mbeanName);
+  }
+}

+ 36 - 36
src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/NameNodeMetrics.java

@@ -21,16 +21,17 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hdfs.server.namenode.NameNode;
 import org.apache.hadoop.hdfs.server.namenode.NameNode;
-import org.apache.hadoop.hdfs.server.namenode.metrics.NameNodeStatistics;
 import org.apache.hadoop.metrics.*;
 import org.apache.hadoop.metrics.*;
 import org.apache.hadoop.metrics.jvm.JvmMetrics;
 import org.apache.hadoop.metrics.jvm.JvmMetrics;
+import org.apache.hadoop.metrics.util.MetricsBase;
 import org.apache.hadoop.metrics.util.MetricsIntValue;
 import org.apache.hadoop.metrics.util.MetricsIntValue;
+import org.apache.hadoop.metrics.util.MetricsRegistry;
 import org.apache.hadoop.metrics.util.MetricsTimeVaryingInt;
 import org.apache.hadoop.metrics.util.MetricsTimeVaryingInt;
 import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
 import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
 
 
 /**
 /**
  * 
  * 
- * This class is for maintaining  the various NameNode statistics
+ * This class is for maintaining  the various NameNode activity statistics
  * and publishing them through the metrics interfaces.
  * and publishing them through the metrics interfaces.
  * This also registers the JMX MBean for RPC.
  * This also registers the JMX MBean for RPC.
  * <p>
  * <p>
@@ -43,29 +44,41 @@ import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
 public class NameNodeMetrics implements Updater {
 public class NameNodeMetrics implements Updater {
     private static Log log = LogFactory.getLog(NameNodeMetrics.class);
     private static Log log = LogFactory.getLog(NameNodeMetrics.class);
     private final MetricsRecord metricsRecord;
     private final MetricsRecord metricsRecord;
+    public MetricsRegistry registry = new MetricsRegistry();
     
     
-    private NameNodeStatistics namenodeStats;
+    private NameNodeActivtyMBean namenodeActivityMBean;
     
     
-    public MetricsTimeVaryingInt numFilesCreated = new MetricsTimeVaryingInt("FilesCreated");
-    public MetricsTimeVaryingInt numFilesAppended = new MetricsTimeVaryingInt("FilesAppended");
-    public MetricsTimeVaryingInt numGetBlockLocations = new MetricsTimeVaryingInt("GetBlockLocations");
-    public MetricsTimeVaryingInt numFilesRenamed = new MetricsTimeVaryingInt("FilesRenamed");
+    public MetricsTimeVaryingInt numFilesCreated =
+                          new MetricsTimeVaryingInt("FilesCreated", registry);
+    public MetricsTimeVaryingInt numFilesAppended =
+                          new MetricsTimeVaryingInt("FilesAppended", registry);
+    public MetricsTimeVaryingInt numGetBlockLocations = 
+                    new MetricsTimeVaryingInt("GetBlockLocations", registry);
+    public MetricsTimeVaryingInt numFilesRenamed =
+                    new MetricsTimeVaryingInt("FilesRenamed", registry);
     public MetricsTimeVaryingInt numGetListingOps = 
     public MetricsTimeVaryingInt numGetListingOps = 
-                                   new MetricsTimeVaryingInt("GetListingOps");
+                    new MetricsTimeVaryingInt("GetListingOps", registry);
     public MetricsTimeVaryingInt numCreateFileOps = 
     public MetricsTimeVaryingInt numCreateFileOps = 
-                                   new MetricsTimeVaryingInt("CreateFileOps");
+                    new MetricsTimeVaryingInt("CreateFileOps", registry);
     public MetricsTimeVaryingInt numDeleteFileOps = 
     public MetricsTimeVaryingInt numDeleteFileOps = 
-                                   new MetricsTimeVaryingInt("DeleteFileOps");
+                          new MetricsTimeVaryingInt("DeleteFileOps", registry);
     public MetricsTimeVaryingInt numAddBlockOps = 
     public MetricsTimeVaryingInt numAddBlockOps = 
-                                   new MetricsTimeVaryingInt("AddBlockOps");
+                          new MetricsTimeVaryingInt("AddBlockOps", registry);
 
 
-    public MetricsTimeVaryingRate transactions = new MetricsTimeVaryingRate("Transactions");
-    public MetricsTimeVaryingRate syncs = new MetricsTimeVaryingRate("Syncs");
-    public MetricsTimeVaryingRate blockReport = new MetricsTimeVaryingRate("blockReport");
-    public MetricsIntValue safeModeTime = new MetricsIntValue("SafemodeTime");
+    public MetricsTimeVaryingRate transactions =
+                    new MetricsTimeVaryingRate("Transactions", registry, "Journal Transaction");
+    public MetricsTimeVaryingRate syncs =
+                    new MetricsTimeVaryingRate("Syncs", registry, "Journal Sync");
+    public MetricsTimeVaryingInt transactionsBatchedInSync = 
+                    new MetricsTimeVaryingInt("JournalTransactionsBatchedInSync", registry, "Journal Transactions Batched In Sync");
+    public MetricsTimeVaryingRate blockReport =
+                    new MetricsTimeVaryingRate("blockReport", registry, "Block Report");
+    public MetricsIntValue safeModeTime =
+                    new MetricsIntValue("SafemodeTime", registry, "Duration in SafeMode at Startup");
     public MetricsIntValue fsImageLoadTime = 
     public MetricsIntValue fsImageLoadTime = 
-                                        new MetricsIntValue("fsImageLoadTime");
-    public MetricsIntValue numBlocksCorrupted = new MetricsIntValue("BlocksCorrupted");
+                    new MetricsIntValue("fsImageLoadTime", registry, "Time loading FS Image at Startup");
+    public MetricsIntValue numBlocksCorrupted =
+                    new MetricsIntValue("BlocksCorrupted", registry);
 
 
       
       
     public NameNodeMetrics(Configuration conf, NameNode nameNode) {
     public NameNodeMetrics(Configuration conf, NameNode nameNode) {
@@ -75,7 +88,7 @@ public class NameNodeMetrics implements Updater {
 
 
       
       
       // Now the Mbean for the name node - this alos registers the MBean
       // Now the Mbean for the name node - this alos registers the MBean
-      namenodeStats = new NameNodeStatistics(this);
+      namenodeActivityMBean = new NameNodeActivtyMBean(registry);
       
       
       // Create a record for NameNode metrics
       // Create a record for NameNode metrics
       MetricsContext metricsContext = MetricsUtil.getContext("dfs");
       MetricsContext metricsContext = MetricsUtil.getContext("dfs");
@@ -89,8 +102,8 @@ public class NameNodeMetrics implements Updater {
 
 
     
     
     public void shutdown() {
     public void shutdown() {
-      if (namenodeStats != null) 
-        namenodeStats.shutdown();
+      if (namenodeActivityMBean != null) 
+        namenodeActivityMBean.shutdown();
     }
     }
       
       
     /**
     /**
@@ -99,21 +112,9 @@ public class NameNodeMetrics implements Updater {
      */
      */
     public void doUpdates(MetricsContext unused) {
     public void doUpdates(MetricsContext unused) {
       synchronized (this) {
       synchronized (this) {
-        numFilesCreated.pushMetric(metricsRecord);
-        numFilesAppended.pushMetric(metricsRecord);
-        numGetBlockLocations.pushMetric(metricsRecord);
-        numFilesRenamed.pushMetric(metricsRecord);
-        numGetListingOps.pushMetric(metricsRecord);
-        numCreateFileOps.pushMetric(metricsRecord);
-        numDeleteFileOps.pushMetric(metricsRecord);
-        numAddBlockOps.pushMetric(metricsRecord);
-
-        transactions.pushMetric(metricsRecord);
-        syncs.pushMetric(metricsRecord);
-        blockReport.pushMetric(metricsRecord);
-        safeModeTime.pushMetric(metricsRecord);
-        fsImageLoadTime.pushMetric(metricsRecord);
-        numBlocksCorrupted.pushMetric(metricsRecord);
+        for (MetricsBase m : registry.getMetricsList()) {
+          m.pushMetric(metricsRecord);
+        }
       }
       }
       metricsRecord.update();
       metricsRecord.update();
     }
     }
@@ -123,5 +124,4 @@ public class NameNodeMetrics implements Updater {
       syncs.resetMinMax();
       syncs.resetMinMax();
       blockReport.resetMinMax();
       blockReport.resetMinMax();
     }
     }
-
 }
 }

+ 0 - 220
src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/NameNodeStatistics.java

@@ -1,220 +0,0 @@
-/**
- * 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.hdfs.server.namenode.metrics;
-
-import javax.management.ObjectName;
-
-import org.apache.hadoop.hdfs.server.namenode.metrics.NameNodeMetrics;
-import org.apache.hadoop.metrics.util.MBeanUtil;
-
-/**
- * 
- * This is the implementation of the Name Node JMX MBean
- *
- */
-public class NameNodeStatistics implements NameNodeStatisticsMBean {
-  private NameNodeMetrics myMetrics;
-  private ObjectName mbeanName;
-
-  /**
-   * This constructs and registers the NameNodeStatisticsMBean
-   * @param nameNodeMetrics - the metrics from which the mbean gets its info
-   */
-  public NameNodeStatistics(NameNodeMetrics nameNodeMetrics) {
-    myMetrics = nameNodeMetrics;
-    mbeanName = MBeanUtil.registerMBean("NameNode", "NameNodeStatistics", this);
-  }
-  
-  /**
-   * Shuts down the statistics
-   *   - unregisters the mbean
-   */
-  public void shutdown() {
-    if (mbeanName != null)
-      MBeanUtil.unregisterMBean(mbeanName);
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long  getBlockReportAverageTime() {
-    return myMetrics.blockReport.getPreviousIntervalAverageTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getBlockReportMaxTime() {
-    return myMetrics.blockReport.getMaxTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getBlockReportMinTime() {
-    return myMetrics.blockReport.getMinTime();
-  }
- 
-  /**
-   * @inheritDoc
-   */
-  public int getBlockReportNum() {
-    return myMetrics.blockReport.getPreviousIntervalNumOps();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long  getJournalTransactionAverageTime() {
-    return myMetrics.transactions.getPreviousIntervalAverageTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getJournalTransactionNum() {
-    return myMetrics.transactions.getPreviousIntervalNumOps();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getJournalTransactionMaxTime() {
-    return myMetrics.transactions.getMaxTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public long getJournalTransactionMinTime() {
-    return myMetrics.transactions.getMinTime();
-  }
-
-  /**
-   * @inheritDoc
-   */  
-  public long getJournalSyncAverageTime() {
-    return myMetrics.syncs.getPreviousIntervalAverageTime();
-  }
- 
-  /**
-   * @inheritDoc
-   */
-  public long getJournalSyncMaxTime() {
-    return myMetrics.syncs.getMaxTime();
-  }
-
-  
-  /**
-   * @inheritDoc
-   */
-  public long getJournalSyncMinTime() {
-    return myMetrics.syncs.getMinTime();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getJournalSyncNum() {
-    return myMetrics.syncs.getPreviousIntervalNumOps();
-  }
-
- 
-  /**
-   * @inheritDoc
-   */
-  public int getSafemodeTime() {
-    return myMetrics.safeModeTime.get();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getFSImageLoadTime() {
-    return myMetrics.fsImageLoadTime.get();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public void resetAllMinMax() {
-    myMetrics.resetAllMinMax();
-  }
-  
-  /**
-   * @inheritDoc
-   */
-  public int getNumFilesCreated() {
-    return myMetrics.numFilesCreated.getPreviousIntervalValue();
-  }
-
-  /** 
-   *@deprecated call getNumGetListingOps() instead
-   */
-  @Deprecated
-  public int getNumFilesListed() {
-    return getNumGetListingOps();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getNumGetListingOps() {
-    return myMetrics.numGetListingOps.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getNumCreateFileOps() {
-    return myMetrics.numCreateFileOps.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getNumDeleteFileOps() {
-    return myMetrics.numDeleteFileOps.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getNumAddBlockOps() {
-    return myMetrics.numAddBlockOps.getPreviousIntervalValue();
-  }
-
-  /** @inheritDoc */
-  public int getNumGetBlockLocations() {
-    return myMetrics.numGetBlockLocations.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getNumFilesRenamed() {
-    return myMetrics.numFilesRenamed.getPreviousIntervalValue();
-  }
-
-  /**
-   * @inheritDoc
-   */
-  public int getNumFilesAppended() {
-    return myMetrics.numFilesAppended.getPreviousIntervalValue();
-  }
-}

+ 0 - 187
src/hdfs/org/apache/hadoop/hdfs/server/namenode/metrics/NameNodeStatisticsMBean.java

@@ -1,187 +0,0 @@
-/**
- * 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.hdfs.server.namenode.metrics;
-
-/**
- * 
- * This is the JMX management interface for getting runtime statistics of
- * the name node.
- * Many of the statistics are sampled and averaged on an interval 
- * which can be specified in the config file.
- * <p>
- * For the statistics that are sampled and averaged, one must specify 
- * a metrics context that does periodic update calls. Most do.
- * The default Null metrics context however does NOT. So if you aren't
- * using any other metrics context then you can turn on the viewing and averaging
- * of sampled metrics by  specifying the following two lines
- *  in the hadoop-meterics.properties file:
- *  <pre>
- *        dfs.class=org.apache.hadoop.metrics.spi.NullContextWithUpdateThread
- *        dfs.period=10
- *  </pre>
- *<p>
- * Note that the metrics are collected regardless of the context used.
- * The context with the update thread is used to average the data periodically.
- * <p>
- * Name Node Status info is report in another MBean
- * @see org.apache.hadoop.hdfs.server.namenode.metrics.FSNamesystemMBean
- *
- */
-public interface NameNodeStatisticsMBean {
-  
-  /**
-   * The time spent in the Safemode at startup
-   * @return time in msec
-   */
-  int getSafemodeTime();
-  
-  /**
-   * Time spent loading the FS Image at startup
-   * @return time in msec
-   */
-  int getFSImageLoadTime();
-  
-  /**
-   * Number of Journal Transactions in the last interval
-   * @return number of operations
-   */
-  int getJournalTransactionNum();
-  
-  /**
-   * Average time for Journal transactions in last interval
-   * @return time in msec
-   */
-  long getJournalTransactionAverageTime();
-  
-  /**
-   * The Minimum Journal Transaction Time since reset was called
-   * @return time in msec
-   */
-  long getJournalTransactionMinTime();
-  
-  /**
-   *  The Maximum Journal Transaction Time since reset was called
-   * @return time in msec
-   */
-  long getJournalTransactionMaxTime();
-  
-  /**
-   *  Number of block Reports processed in the last interval
-   * @return number of operations
-   */
-  int getBlockReportNum();
-  
-  /**
-   * Average time for Block Report Processing in last interval
-   * @return time in msec
-   */
-  long getBlockReportAverageTime();
-  
-  /**
-   *  The Minimum Block Report Processing Time since reset was called
-   * @return time in msec
-   */
-  long getBlockReportMinTime();
-  
-  /**
-   *  The Maximum Block Report Processing Time since reset was called
-   * @return time in msec
-   */
-  long getBlockReportMaxTime();
-  
-  /**
-   *  Number of Journal Syncs in the last interval
-   * @return number of operations
-   */
-  int getJournalSyncNum();
-  
-  /**
-   * Average time for Journal Sync in last interval
-   * @return time in msec
-   */
-  long getJournalSyncAverageTime();
-  
-  /**
-   *  The Minimum Journal Sync Time since reset was called
-   * @return time in msec
-   */
-  long getJournalSyncMinTime();
-  
-  /**
-   *   The Maximum Journal Sync Time since reset was called
-   * @return time in msec
-   */
-  long getJournalSyncMaxTime();
-  
-  /**
-   * Reset all min max times
-   */
-  void resetAllMinMax();
-  
-  /**
-   *  Number of files created in the last interval
-   * @return  number of operations
-   */
-  int getNumFilesCreated();
-  
-  /**
-   * Number of
-   * {@link org.apache.hadoop.hdfs.server.namenode.NameNode#getBlockLocations(String,long,long)}
-   * @return  number of operations
-   */
-  int getNumGetBlockLocations();
-
-  /**
-   *   Number of files renamed in the last interval
-   * @return number of operations
-   */
-  int getNumFilesRenamed();
-  
-  /**
-   *   Number of files listed in the last interval
-   * @return number of operations
-   * @deprecated Use getNumGetListingOps() instead
-   */
-  @Deprecated
-  int getNumFilesListed();
-
-  /**
-   *   Number of files listed in the last interval
-   * @return number of operations
-   */
-  int getNumGetListingOps();
-
-  /**
-   *   Number of file creation operations in the last interval
-   * @return number of file creation operations
-   */
-  int getNumCreateFileOps();
-
-  /**
-   *   Number of file deletion operations in the last interval
-   * @return number of file deletion operations
-   */
-  int getNumDeleteFileOps();
-
-  /**
-   *   Number of add block operations in the last interval
-   * @return number of add block operations
-   */
-  int getNumAddBlockOps();
-}

+ 13 - 10
src/test/org/apache/hadoop/hdfs/server/datanode/SimulatedFSDataset.java

@@ -606,26 +606,29 @@ public class SimulatedFSDataset  implements FSConstants, FSDatasetInterface, Con
   }
   }
   
   
   private ObjectName mbeanName;
   private ObjectName mbeanName;
+
+
+  
   /**
   /**
-   * Register the FSDataset MBean
-   * @param storageId 
-   * 
-   * We use storage id for MBean name since a minicluster within a single
+   * Register the FSDataset MBean using the name
+   *        "hadoop:service=DataNode,name=FSDatasetState-<storageid>"
+   *  We use storage id for MBean name since a minicluster within a single
    * Java VM may have multiple Simulated Datanodes.
    * Java VM may have multiple Simulated Datanodes.
    */
    */
-  void registerMBean(String storageId) {
-    // We wrap to bypass standard mbean naming convention.
-    // This wrapping can be removed in java 6 as Java6 is more flexible in 
+  void registerMBean(final String storageId) {
+    // We wrap to bypass standard mbean naming convetion.
+    // This wraping can be removed in java 6 as it is more flexible in 
     // package naming for mbeans and their impl.
     // package naming for mbeans and their impl.
     StandardMBean bean;
     StandardMBean bean;
+
     try {
     try {
       bean = new StandardMBean(this,FSDatasetMBean.class);
       bean = new StandardMBean(this,FSDatasetMBean.class);
-      mbeanName = MBeanUtil.registerMBean("DataNode-"+ storageId,
-                                          "FSDatasetStatus", bean);
+      mbeanName = MBeanUtil.registerMBean("DataNode",
+          "FSDatasetState-" + storageId, bean);
     } catch (NotCompliantMBeanException e) {
     } catch (NotCompliantMBeanException e) {
       e.printStackTrace();
       e.printStackTrace();
     }
     }
-
+ 
     DataNode.LOG.info("Registered FSDatasetStatusMBean");
     DataNode.LOG.info("Registered FSDatasetStatusMBean");
   }
   }
 
 

+ 1 - 4
src/test/org/apache/hadoop/hdfs/server/datanode/TestDataNodeMetrics.java

@@ -24,7 +24,6 @@ import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hdfs.DFSTestUtil;
 import org.apache.hadoop.hdfs.DFSTestUtil;
 import org.apache.hadoop.hdfs.MiniDFSCluster;
 import org.apache.hadoop.hdfs.MiniDFSCluster;
 import org.apache.hadoop.hdfs.server.datanode.metrics.DataNodeMetrics;
 import org.apache.hadoop.hdfs.server.datanode.metrics.DataNodeMetrics;
-import org.apache.hadoop.hdfs.server.datanode.metrics.DataNodeStatistics;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.conf.Configuration;
 import junit.framework.TestCase;
 import junit.framework.TestCase;
 
 
@@ -43,9 +42,7 @@ public class TestDataNodeMetrics extends TestCase {
       assertEquals(datanodes.size(), 1);
       assertEquals(datanodes.size(), 1);
       DataNode datanode = datanodes.get(0);
       DataNode datanode = datanodes.get(0);
       DataNodeMetrics metrics = datanode.getMetrics();
       DataNodeMetrics metrics = datanode.getMetrics();
-      DataNodeStatistics statistics = new DataNodeStatistics(
-          metrics, datanode.dnRegistration.storageID);
-      assertEquals(LONG_FILE_LEN, statistics.getBytesWritten());
+      assertEquals(LONG_FILE_LEN, metrics.bytesWritten.getCurrentIntervalValue());
     } finally {
     } finally {
       if (cluster != null) {cluster.shutdown();}
       if (cluster != null) {cluster.shutdown();}
     }
     }