Sfoglia il codice sorgente

AMBARI-1465. Minimize Read and Write locks for createHosts. (Siddharth Wagle via mahadev)

git-svn-id: https://svn.apache.org/repos/asf/incubator/ambari/trunk@1448905 13f79535-47bb-0310-9956-ffa450edef68
Mahadev Konar 12 anni fa
parent
commit
2c05a7edae

+ 3 - 0
CHANGES.txt

@@ -320,6 +320,9 @@ Trunk (unreleased changes):
 
  AMBARI-1343. Service Check fails after secure install due to wrong kinit
  path. (Siddharth Wagle via mahadev) 
+ 
+ AMBARI-1465. Minimize Read and Write locks for createHosts. (Siddharth Wagle
+ via mahadev)
 
  BUG FIXES
 

+ 11 - 7
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java

@@ -22,6 +22,7 @@ import java.net.InetAddress;
 import java.util.*;
 import java.util.Map.Entry;
 
+import com.google.inject.persist.Transactional;
 import org.apache.ambari.server.*;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.actionmanager.HostRoleCommand;
@@ -594,16 +595,19 @@ public class AmbariManagementControllerImpl implements
           "These hosts have not been registered with the server: " + names.toString());
     }
 
+    Map<String, Set<String>> hostClustersMap = new HashMap<String, Set<String>>();
+    Map<String, Map<String, String>> hostAttributes = new HashMap<String, Map<String, String>>();
     for (HostRequest request : requests) {
-      if (request.getClusterName() != null) {
-        clusters.mapHostToCluster(request.getHostname(), request.getClusterName());
-      }
-
-      if (request.getHostAttributes() != null) {
-        clusters.getHost(request.getHostname()).
-            setHostAttributes(request.getHostAttributes());
+      if (request.getHostname() != null) {
+        Set<String> clusters = new HashSet<String>();
+        clusters.add(request.getClusterName());
+        hostClustersMap.put(request.getHostname(), clusters);
+        if (request.getHostAttributes() != null) {
+          hostAttributes.put(request.getHostname(), request.getHostAttributes());
+        }
       }
     }
+    clusters.updateHostWithClusterAndAttributes(hostClustersMap, hostAttributes);
   }
 
   @Override

+ 3 - 0
ambari-server/src/main/java/org/apache/ambari/server/state/Clusters.java

@@ -105,4 +105,7 @@ public interface Clusters {
 
   public void deleteCluster(String clusterName) throws AmbariException;
 
+  public void updateHostWithClusterAndAttributes(Map<String, Set<String>> hostsClusters, Map<String,
+    Map<String, String>> hostAttributes)
+    throws AmbariException;
 }

+ 107 - 8
ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java

@@ -18,13 +18,7 @@
 
 package org.apache.ambari.server.state.cluster;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -46,7 +40,6 @@ import org.apache.ambari.server.orm.entities.HostEntity;
 import org.apache.ambari.server.state.*;
 import org.apache.ambari.server.state.HostHealthStatus.HealthStatus;
 import org.apache.ambari.server.state.host.HostFactory;
-import org.apache.ambari.server.state.host.HostImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -287,6 +280,112 @@ public class ClustersImpl implements Clusters {
     return repos.containsKey(h.getOsType());
   }
 
+  @Override
+  @Transactional
+  public void updateHostWithClusterAndAttributes(Map<String, Set<String>> hostClusters, Map<String,
+      Map<String, String>> hostAttributes)
+      throws AmbariException {
+    loadClustersAndHosts();
+    w.lock();
+    try {
+      if (hostClusters != null) {
+        Map<String, Host> hostMap = getHostsMap(hostClusters.keySet());
+        Set<String> clusterNames = new HashSet<String>();
+        for (Set<String> cSet : hostClusters.values()) {
+          clusterNames.addAll(cSet);
+        }
+        Map<String, Cluster> clusterMap = getClustersMap(clusterNames);
+
+        for (String hostname : hostClusters.keySet()) {
+          Host host = hostMap.get(hostname);
+          Map<String, String>  attributes = hostAttributes.get(hostname);
+          if (attributes != null && !attributes.isEmpty()){
+            host.setHostAttributes(attributes);
+          }
+
+          Set<String> hostClusterNames = hostClusters.get(hostname);
+          for (String clusterName : hostClusterNames) {
+            if (clusterName != null && !clusterName.isEmpty()) {
+              Cluster cluster = clusterMap.get(clusterName);
+
+              for (Cluster c : hostClusterMap.get(hostname)) {
+                if (c.getClusterName().equals(clusterName)) {
+                  throw new DuplicateResourceException("Attempted to create a host which already exists: clusterName=" +
+                      clusterName + ", hostName=" + hostname);
+                }
+              }
+
+              if (!isOsSupportedByClusterStack(cluster, host)) {
+                String message = "Trying to map host to cluster where stack does not"
+                    + " support host's os type"
+                    + ", clusterName=" + clusterName
+                    + ", clusterStackId=" + cluster.getDesiredStackVersion().getStackId()
+                    + ", hostname=" + hostname
+                    + ", hostOsType=" + host.getOsType();
+                LOG.warn(message);
+                throw new AmbariException(message);
+              }
+
+              mapHostClusterEntities(hostname, cluster.getClusterId());
+
+              hostClusterMap.get(hostname).add(cluster);
+              clusterHostMap.get(clusterName).add(host);
+
+              if (LOG.isDebugEnabled()) {
+                LOG.debug("Mapping a host to a cluster"
+                    + ", clusterName=" + clusterName
+                    + ", clusterId=" + cluster.getClusterId()
+                    + ", hostname=" + hostname);
+              }
+            }
+          }
+        }
+      }
+    } finally {
+      w.unlock();
+    }
+  }
+
+  @Transactional
+  private Map<String, Host> getHostsMap(Collection<String> hostSet) throws
+      HostNotFoundException {
+    loadClustersAndHosts();
+    Map<String, Host> hostMap = new HashMap<String, Host>();
+    r.lock();
+    try {
+      for (String host : hostSet) {
+        if (!hosts.containsKey(host))
+          throw new HostNotFoundException(host);
+        else
+          hostMap.put(host, hosts.get(host));
+      }
+    } finally {
+      r.unlock();
+    }
+    return hostMap;
+  }
+
+  @Transactional
+  private Map<String, Cluster> getClustersMap(Collection<String> clusterSet) throws
+      ClusterNotFoundException {
+    loadClustersAndHosts();
+    Map<String, Cluster> clusterMap = new HashMap<String, Cluster>();
+    r.lock();
+    try {
+      for (String c : clusterSet) {
+        if (c != null) {
+          if (!clusters.containsKey(c))
+            throw new ClusterNotFoundException(c);
+          else
+            clusterMap.put(c, clusters.get(c));
+        }
+      }
+    } finally {
+      r.unlock();
+    }
+    return clusterMap;
+  }
+
   @Override
   public void mapHostToCluster(String hostname,
                                String clusterName) throws AmbariException {