Jelajahi Sumber

HADOOP-8050. Deadlock in metrics. Contributed by Kihwal Lee.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-1.0@1291078 13f79535-47bb-0310-9956-ffa450edef68
Matthew Foley 13 tahun lalu
induk
melakukan
b2c759b158

+ 3 - 1
CHANGES.txt

@@ -1,6 +1,6 @@
 Hadoop Change Log
 Hadoop Change Log
 
 
-Release 1.0.1 - 2012.02.12
+Release 1.0.1 - 2012.02.19
 
 
   NEW FEATURES
   NEW FEATURES
 
 
@@ -49,6 +49,8 @@ Release 1.0.1 - 2012.02.12
     HADOOP-8037. Binary tarball does not preserve platform info for native builds,
     HADOOP-8037. Binary tarball does not preserve platform info for native builds,
     and RPMs fail to provide needed symlinks for libhadoop.so.  (Matt Foley)
     and RPMs fail to provide needed symlinks for libhadoop.so.  (Matt Foley)
 
 
+    HADOOP-8050. Deadlock in metrics. (Kihwal Lee via mattf)
+
 
 
 Release 1.0.0 - 2011.12.15
 Release 1.0.0 - 2011.12.15
 
 

+ 40 - 21
src/core/org/apache/hadoop/metrics2/impl/MetricsSourceAdapter.java

@@ -92,17 +92,19 @@ class MetricsSourceAdapter implements DynamicMBean {
   }
   }
 
 
   @Override
   @Override
-  public synchronized Object getAttribute(String attribute)
+  public Object getAttribute(String attribute)
       throws AttributeNotFoundException, MBeanException, ReflectionException {
       throws AttributeNotFoundException, MBeanException, ReflectionException {
     updateJmxCache();
     updateJmxCache();
-    Attribute a = attrCache.get(attribute);
-    if (a == null) {
-      throw new AttributeNotFoundException(attribute +" not found");
-    }
-    if (LOG.isDebugEnabled()) {
-      LOG.debug(attribute +": "+ a.getName() +"="+ a.getValue());
+    synchronized(this) {
+      Attribute a = attrCache.get(attribute);
+      if (a == null) {
+        throw new AttributeNotFoundException(attribute +" not found");
+      }
+      if (LOG.isDebugEnabled()) {
+        LOG.debug(attribute +": "+ a.getName() +"="+ a.getValue());
+      }
+      return a.getValue();
     }
     }
-    return a.getValue();
   }
   }
 
 
   public void setAttribute(Attribute attribute)
   public void setAttribute(Attribute attribute)
@@ -112,17 +114,19 @@ class MetricsSourceAdapter implements DynamicMBean {
   }
   }
 
 
   @Override
   @Override
-  public synchronized AttributeList getAttributes(String[] attributes) {
+  public AttributeList getAttributes(String[] attributes) {
     updateJmxCache();
     updateJmxCache();
-    AttributeList ret = new AttributeList();
-    for (String key : attributes) {
-      Attribute attr = attrCache.get(key);
-      if (LOG.isDebugEnabled()) {
-        LOG.debug(key +": "+ attr.getName() +"="+ attr.getValue());
+    synchronized(this) {
+      AttributeList ret = new AttributeList();
+      for (String key : attributes) {
+        Attribute attr = attrCache.get(key);
+        if (LOG.isDebugEnabled()) {
+          LOG.debug(key +": "+ attr.getName() +"="+ attr.getValue());
+        }
+        ret.add(attr);
       }
       }
-      ret.add(attr);
+      return ret;
     }
     }
-    return ret;
   }
   }
 
 
   @Override
   @Override
@@ -137,17 +141,32 @@ class MetricsSourceAdapter implements DynamicMBean {
   }
   }
 
 
   @Override
   @Override
-  public synchronized MBeanInfo getMBeanInfo() {
+  public MBeanInfo getMBeanInfo() {
     updateJmxCache();
     updateJmxCache();
     return infoCache;
     return infoCache;
   }
   }
 
 
   private void updateJmxCache() {
   private void updateJmxCache() {
-    if (System.currentTimeMillis() - jmxCacheTS >= jmxCacheTTL) {
-      if (lastRecs == null) {
-        MetricsBuilderImpl builder = new MetricsBuilderImpl();
-        getMetrics(builder, true);
+    boolean getAllMetrics = false;
+    synchronized(this) {
+      if (System.currentTimeMillis() - jmxCacheTS >= jmxCacheTTL) {
+        // temporarilly advance the expiry while updating the cache
+        jmxCacheTS = System.currentTimeMillis() + jmxCacheTTL;
+        if (lastRecs == null) {
+          getAllMetrics = true;
+        }
+      }
+      else {
+        return;
       }
       }
+    }
+
+    if (getAllMetrics) {
+      MetricsBuilderImpl builder = new MetricsBuilderImpl();
+      getMetrics(builder, true);
+    }
+
+    synchronized(this) {
       int cacheSize = attrCache.size(); // because updateAttrCache changes it!
       int cacheSize = attrCache.size(); // because updateAttrCache changes it!
       int numMetrics = updateAttrCache();
       int numMetrics = updateAttrCache();
       if (cacheSize < numMetrics) {
       if (cacheSize < numMetrics) {