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 <[email protected]>
Authored: Thu Jun 18 16:58:15 2015 -0400
Committer: John Speidel <[email protected]>
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");
+ }
+}