ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jspei...@apache.org
Subject ambari git commit: AMBARI-12009. Fix occasional ConcurrentModificationException when provisioning large clusters via blueprints
Date Thu, 18 Jun 2015 22:50:25 GMT
Repository: ambari
Updated Branches:
  refs/heads/branch-2.1 48c02a12a -> 527e75c19


AMBARI-12009. Fix occasional ConcurrentModificationException when provisioning
              large clusters via blueprints


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/527e75c1
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/527e75c1
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/527e75c1

Branch: refs/heads/branch-2.1
Commit: 527e75c1985b068e54e18f6480536a4ed6cb574f
Parents: 48c02a1
Author: John Speidel <jspeidel@hortonworks.com>
Authored: Thu Jun 18 16:58:15 2015 -0400
Committer: John Speidel <jspeidel@hortonworks.com>
Committed: Thu Jun 18 18:48:39 2015 -0400

----------------------------------------------------------------------
 .../ambari/server/topology/HostGroupInfo.java   | 112 ++++++++++++++++--
 .../server/topology/HostGroupInfoTest.java      | 116 +++++++++++++++++++
 2 files changed, 219 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/527e75c1/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java
b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java
index a48f331..8ff3971 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java
@@ -29,71 +29,165 @@ import java.util.HashSet;
  * Host Group information specific to a cluster instance.
  */
 public class HostGroupInfo {
-
+  /**
+   * predicate compiler
+   */
   private static PredicateCompiler predicateCompiler = new PredicateCompiler();
 
+  /**
+   * host group name
+   */
   private String hostGroupName;
   /**
-   * Hosts contained associated with the host group
+   * hosts contained associated with the host group
    */
-  private Collection<String> hostNames = new HashSet<String>();
+  private final Collection<String> hostNames = new HashSet<String>();
 
+  /**
+   * explicitly specified host count
+   */
   private int requested_count = 0;
 
+  /**
+   * host group scoped configuration
+   */
   Configuration configuration;
 
+  /**
+   * explicitly specified host predicate string
+   */
   String predicateString;
+
+  /**
+   * compiled host predicate
+   */
   Predicate predicate;
 
 
+  /**
+   * Constructor
+   *
+   * @param hostGroupName  host group name
+   */
   public HostGroupInfo(String hostGroupName) {
     this.hostGroupName = hostGroupName;
   }
 
+  /**
+   * Get the host group name.
+   *
+   * @return host group name
+   */
   public String getHostGroupName() {
     return hostGroupName;
   }
 
+  /**
+   * Get the collection of user specified host names for the host group.
+   * If the user specified a count instead of host names then an empty
+   * collection is returned.
+   *
+   * @return collection of user specified host names; will never be null
+   */
   public Collection<String> getHostNames() {
-    return new HashSet<String>(hostNames);
+    // needs to be an exclusive lock, not a read lock because collection
+    // shouldn't change while copying elements into the new set instance
+    synchronized (hostNames) {
+      return new HashSet<String>(hostNames);
+    }
   }
 
+  /**
+   * Get the requested host count.
+   * This is either the user specified value or
+   * the number of explicitly specified host names specified by the user.
+   *
+   * @return number of requested hosts for the group
+   */
   public int getRequestedHostCount() {
-    return requested_count == 0 ? hostNames.size() : requested_count;
+    synchronized (hostNames) {
+      return requested_count == 0 ? hostNames.size() : requested_count;
+    }
   }
 
+  /**
+   * Associate a single host name to the host group.
+   *
+   * @param hostName  the host name to associate with the host group
+   */
   public void addHost(String hostName) {
-    hostNames.add(hostName);
+    synchronized(hostNames) {
+      hostNames.add(hostName);
+    }
   }
 
+  /**
+   * Associate multiple host names to the host group.
+   *
+   * @param hosts  collection of host names to associate with the host group
+   */
   public void addHosts(Collection<String> hosts) {
-    for (String host : hosts) {
-      addHost(host);
+    synchronized (hostNames) {
+      for (String host : hosts) {
+        addHost(host);
+      }
     }
   }
 
+  /**
+   * Set the requested host count for the host group.
+   *
+   * @param num  requested host count
+   */
   public void setRequestedCount(int num) {
     requested_count = num;
   }
 
-  //todo: constructor?
+  /**
+   * Set host group configuration for the host group.
+   *
+   * @param configuration configuration instance
+   */
   public void setConfiguration(Configuration configuration) {
     this.configuration = configuration;
   }
 
+  /**
+   * Get the host group configuration associated with the host group.
+   *
+   * @return associated host group scoped configuration or null if no configuration
+   *         is specified for the host group
+   */
   public Configuration getConfiguration() {
     return configuration;
   }
 
+  /**
+   * Set the host predicate for the host group.
+   *
+   * @param predicateString  host predicate as a string
+   *
+   * @throws InvalidQueryException if compilation of the predicate fails
+   */
   public void setPredicate(String predicateString) throws InvalidQueryException {
     this.predicate = predicateCompiler.compile(predicateString);
     this.predicateString = predicateString;
   }
 
+  /**
+   * Get the compiled host predicate for the host group.
+   *
+   * @return the compiled host predicate or null if no predicate was specified
+   */
   public Predicate getPredicate() {
     return predicate;
   }
 
+  /**
+   * Get the host predicate string for the host group.
+   *
+   * @return the host predicate string or null if no predicate was specified
+   */
   public String getPredicateString() {
     return predicateString;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/527e75c1/ambari-server/src/test/java/org/apache/ambari/server/topology/HostGroupInfoTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/HostGroupInfoTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/topology/HostGroupInfoTest.java
new file mode 100644
index 0000000..3b15684
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/HostGroupInfoTest.java
@@ -0,0 +1,116 @@
+/**
+ * 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.ambari.server.topology;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.ambari.server.api.predicate.InvalidQueryException;
+import org.apache.ambari.server.api.predicate.PredicateCompiler;
+import org.apache.ambari.server.controller.predicate.EqualsPredicate;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * HostGroupInfo unit tests
+ */
+public class HostGroupInfoTest {
+
+  @Test
+  public void testGetHostGroupName() {
+    HostGroupInfo group = new HostGroupInfo("test-name");
+    assertEquals("test-name", group.getHostGroupName());
+  }
+
+  @Test
+  public void testSetGetHostNames() {
+    HostGroupInfo group = new HostGroupInfo("test-name");
+    // single host add
+    group.addHost("host1");
+    assertEquals(1, group.getHostNames().size());
+    assertTrue(group.getHostNames().contains("host1"));
+
+    // add collection of hosts and duplicate host1
+    group.addHosts(Arrays.asList("host2", "host3", "host1"));
+    Collection<String> hostNames = group.getHostNames();
+    assertEquals(3, hostNames.size());
+    assertTrue(hostNames.contains("host1"));
+    assertTrue(hostNames.contains("host2"));
+    assertTrue(hostNames.contains("host3"));
+
+    // ensure that a copy was returned
+    hostNames.clear();
+    hostNames = group.getHostNames();
+    assertEquals(3, hostNames.size());
+    assertTrue(hostNames.contains("host1"));
+    assertTrue(hostNames.contains("host2"));
+    assertTrue(hostNames.contains("host3"));
+
+  }
+
+  @Test
+  public void testSetGetRequestedHostCount_explicit() {
+    HostGroupInfo group = new HostGroupInfo("test-name");
+    assertEquals(0, group.getRequestedHostCount());
+    group.setRequestedCount(5);
+    assertEquals(5, group.getRequestedHostCount());
+  }
+
+  @Test
+  public void testSetGetRequestedHostCount_hostNamesSpecified() {
+    HostGroupInfo group = new HostGroupInfo("test-name");
+    assertEquals(0, group.getRequestedHostCount());
+    group.addHosts(Arrays.asList("host2", "host3", "host1"));
+    assertEquals(3, group.getRequestedHostCount());
+  }
+
+  @Test
+  public void testSetGetGetConfiguration() {
+    Configuration configuration = createNiceMock(Configuration.class);
+    HostGroupInfo group = new HostGroupInfo("test-name");
+    assertNull(group.getConfiguration());
+    group.setConfiguration(configuration);
+    assertSame(configuration, group.getConfiguration());
+  }
+
+  @Test
+  public void testSetGetPredicate() throws Exception {
+    HostGroupInfo group = new HostGroupInfo("test-name");
+    assertNull(group.getPredicateString());
+    assertNull(group.getPredicate());
+
+    group.setPredicate("Hosts/host_name=awesome.host.com");
+    assertEquals("Hosts/host_name=awesome.host.com", group.getPredicateString());
+    assertEquals(new EqualsPredicate("Hosts/host_name", "awesome.host.com"), group.getPredicate());
+  }
+
+  @Test(expected=InvalidQueryException.class)
+  public void testSetPredicate_invalid() throws Exception {
+    HostGroupInfo group = new HostGroupInfo("test-name");
+    group.setPredicate("=thisIsNotAPredicate");
+  }
+}


Mime
View raw message