|
@@ -17,18 +17,22 @@
|
|
|
*/
|
|
|
package org.apache.ambari.server.state.configgroup;
|
|
|
|
|
|
+import java.util.Collection;
|
|
|
import java.util.Collections;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.HashSet;
|
|
|
import java.util.Map;
|
|
|
+import java.util.Map.Entry;
|
|
|
import java.util.Set;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
+import java.util.concurrent.ConcurrentMap;
|
|
|
import java.util.concurrent.locks.ReadWriteLock;
|
|
|
-import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
|
|
|
|
import org.apache.ambari.server.AmbariException;
|
|
|
import org.apache.ambari.server.DuplicateResourceException;
|
|
|
import org.apache.ambari.server.controller.ConfigGroupResponse;
|
|
|
import org.apache.ambari.server.controller.internal.ConfigurationResourceProvider;
|
|
|
+import org.apache.ambari.server.logging.LockFactory;
|
|
|
import org.apache.ambari.server.orm.dao.ClusterDAO;
|
|
|
import org.apache.ambari.server.orm.dao.ConfigGroupConfigMappingDAO;
|
|
|
import org.apache.ambari.server.orm.dao.ConfigGroupDAO;
|
|
@@ -44,213 +48,195 @@ import org.apache.ambari.server.orm.entities.HostEntity;
|
|
|
import org.apache.ambari.server.state.Cluster;
|
|
|
import org.apache.ambari.server.state.Clusters;
|
|
|
import org.apache.ambari.server.state.Config;
|
|
|
+import org.apache.ambari.server.state.ConfigFactory;
|
|
|
import org.apache.ambari.server.state.Host;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
-import com.google.gson.Gson;
|
|
|
-import com.google.inject.Inject;
|
|
|
-import com.google.inject.Injector;
|
|
|
import com.google.inject.assistedinject.Assisted;
|
|
|
import com.google.inject.assistedinject.AssistedInject;
|
|
|
import com.google.inject.persist.Transactional;
|
|
|
|
|
|
public class ConfigGroupImpl implements ConfigGroup {
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(ConfigGroupImpl.class);
|
|
|
- private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
|
|
|
|
|
|
private Cluster cluster;
|
|
|
- private ConfigGroupEntity configGroupEntity;
|
|
|
- private Map<Long, Host> hosts;
|
|
|
- private Map<String, Config> configurations;
|
|
|
- private volatile boolean isPersisted = false;
|
|
|
-
|
|
|
- @Inject
|
|
|
- private Gson gson;
|
|
|
- @Inject
|
|
|
- private ConfigGroupDAO configGroupDAO;
|
|
|
- @Inject
|
|
|
- private ConfigGroupConfigMappingDAO configGroupConfigMappingDAO;
|
|
|
- @Inject
|
|
|
- private ConfigGroupHostMappingDAO configGroupHostMappingDAO;
|
|
|
- @Inject
|
|
|
- private HostDAO hostDAO;
|
|
|
- @Inject
|
|
|
- private ClusterDAO clusterDAO;
|
|
|
- @Inject
|
|
|
- Clusters clusters;
|
|
|
+ private ConcurrentMap<Long, Host> m_hosts;
|
|
|
+ private ConcurrentMap<String, Config> m_configurations;
|
|
|
+ private String configGroupName;
|
|
|
+ private long configGroupId;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This lock is required to prevent inconsistencies in internal state between
|
|
|
+ * {@link #m_hosts} and the entities stored by the {@link ConfigGroupEntity}.
|
|
|
+ */
|
|
|
+ private final ReadWriteLock hostLock;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * A label for {@link #hostLock} to use with the {@link LockFactory}.
|
|
|
+ */
|
|
|
+ private static final String hostLockLabel = "configurationGroupHostLock";
|
|
|
+
|
|
|
+ private final ConfigGroupDAO configGroupDAO;
|
|
|
+
|
|
|
+ private final ConfigGroupConfigMappingDAO configGroupConfigMappingDAO;
|
|
|
+
|
|
|
+ private final ConfigGroupHostMappingDAO configGroupHostMappingDAO;
|
|
|
+
|
|
|
+ private final HostDAO hostDAO;
|
|
|
+
|
|
|
+ private final ClusterDAO clusterDAO;
|
|
|
+
|
|
|
+ private final ConfigFactory configFactory;
|
|
|
|
|
|
@AssistedInject
|
|
|
- public ConfigGroupImpl(@Assisted("cluster") Cluster cluster,
|
|
|
- @Assisted("name") String name,
|
|
|
- @Assisted("tag") String tag,
|
|
|
- @Assisted("description") String description,
|
|
|
- @Assisted("configs") Map<String, Config> configs,
|
|
|
- @Assisted("hosts") Map<Long, Host> hosts,
|
|
|
- Injector injector) {
|
|
|
- injector.injectMembers(this);
|
|
|
+ public ConfigGroupImpl(@Assisted("cluster") Cluster cluster, @Assisted("name") String name,
|
|
|
+ @Assisted("tag") String tag, @Assisted("description") String description,
|
|
|
+ @Assisted("configs") Map<String, Config> configurations,
|
|
|
+ @Assisted("hosts") Map<Long, Host> hosts, Clusters clusters, ConfigFactory configFactory,
|
|
|
+ ClusterDAO clusterDAO, HostDAO hostDAO, ConfigGroupDAO configGroupDAO,
|
|
|
+ ConfigGroupConfigMappingDAO configGroupConfigMappingDAO,
|
|
|
+ ConfigGroupHostMappingDAO configGroupHostMappingDAO, LockFactory lockFactory) {
|
|
|
+
|
|
|
+ this.configFactory = configFactory;
|
|
|
+ this.clusterDAO = clusterDAO;
|
|
|
+ this.hostDAO = hostDAO;
|
|
|
+ this.configGroupDAO = configGroupDAO;
|
|
|
+ this.configGroupConfigMappingDAO = configGroupConfigMappingDAO;
|
|
|
+ this.configGroupHostMappingDAO = configGroupHostMappingDAO;
|
|
|
+
|
|
|
+ hostLock = lockFactory.newReadWriteLock(hostLockLabel);
|
|
|
+
|
|
|
this.cluster = cluster;
|
|
|
+ configGroupName = name;
|
|
|
|
|
|
- configGroupEntity = new ConfigGroupEntity();
|
|
|
+ ConfigGroupEntity configGroupEntity = new ConfigGroupEntity();
|
|
|
configGroupEntity.setClusterId(cluster.getClusterId());
|
|
|
configGroupEntity.setGroupName(name);
|
|
|
configGroupEntity.setTag(tag);
|
|
|
configGroupEntity.setDescription(description);
|
|
|
|
|
|
- if (hosts != null) {
|
|
|
- this.hosts = hosts;
|
|
|
- } else {
|
|
|
- this.hosts = new HashMap<Long, Host>();
|
|
|
- }
|
|
|
+ m_hosts = hosts == null ? new ConcurrentHashMap<Long, Host>()
|
|
|
+ : new ConcurrentHashMap<>(hosts);
|
|
|
|
|
|
- if (configs != null) {
|
|
|
- configurations = configs;
|
|
|
- } else {
|
|
|
- configurations = new HashMap<String, Config>();
|
|
|
- }
|
|
|
+ m_configurations = configurations == null ? new ConcurrentHashMap<String, Config>()
|
|
|
+ : new ConcurrentHashMap<>(configurations);
|
|
|
+
|
|
|
+ // save the entity and grab the ID
|
|
|
+ persist(configGroupEntity);
|
|
|
+ configGroupId = configGroupEntity.getGroupId();
|
|
|
}
|
|
|
|
|
|
@AssistedInject
|
|
|
- public ConfigGroupImpl(@Assisted Cluster cluster,
|
|
|
- @Assisted ConfigGroupEntity configGroupEntity,
|
|
|
- Injector injector) {
|
|
|
- injector.injectMembers(this);
|
|
|
+ public ConfigGroupImpl(@Assisted Cluster cluster, @Assisted ConfigGroupEntity configGroupEntity,
|
|
|
+ Clusters clusters, ConfigFactory configFactory,
|
|
|
+ ClusterDAO clusterDAO, HostDAO hostDAO, ConfigGroupDAO configGroupDAO,
|
|
|
+ ConfigGroupConfigMappingDAO configGroupConfigMappingDAO,
|
|
|
+ ConfigGroupHostMappingDAO configGroupHostMappingDAO, LockFactory lockFactory) {
|
|
|
+
|
|
|
+ this.configFactory = configFactory;
|
|
|
+ this.clusterDAO = clusterDAO;
|
|
|
+ this.hostDAO = hostDAO;
|
|
|
+ this.configGroupDAO = configGroupDAO;
|
|
|
+ this.configGroupConfigMappingDAO = configGroupConfigMappingDAO;
|
|
|
+ this.configGroupHostMappingDAO = configGroupHostMappingDAO;
|
|
|
+
|
|
|
+ hostLock = lockFactory.newReadWriteLock(hostLockLabel);
|
|
|
+
|
|
|
this.cluster = cluster;
|
|
|
+ configGroupId = configGroupEntity.getGroupId();
|
|
|
+ configGroupName = configGroupEntity.getGroupName();
|
|
|
|
|
|
- this.configGroupEntity = configGroupEntity;
|
|
|
- configurations = new HashMap<String, Config>();
|
|
|
- hosts = new HashMap<Long, Host>();
|
|
|
+ m_configurations = new ConcurrentHashMap<String, Config>();
|
|
|
+ m_hosts = new ConcurrentHashMap<Long, Host>();
|
|
|
|
|
|
// Populate configs
|
|
|
- for (ConfigGroupConfigMappingEntity configMappingEntity : configGroupEntity
|
|
|
- .getConfigGroupConfigMappingEntities()) {
|
|
|
-
|
|
|
+ for (ConfigGroupConfigMappingEntity configMappingEntity : configGroupEntity.getConfigGroupConfigMappingEntities()) {
|
|
|
Config config = cluster.getConfig(configMappingEntity.getConfigType(),
|
|
|
configMappingEntity.getVersionTag());
|
|
|
|
|
|
if (config != null) {
|
|
|
- configurations.put(config.getType(), config);
|
|
|
+ m_configurations.put(config.getType(), config);
|
|
|
} else {
|
|
|
- LOG.warn("Unable to find config mapping for config group"
|
|
|
- + ", clusterName = " + cluster.getClusterName()
|
|
|
- + ", type = " + configMappingEntity.getConfigType()
|
|
|
- + ", tag = " + configMappingEntity.getVersionTag());
|
|
|
+ LOG.warn("Unable to find config mapping {}/{} for config group in cluster {}",
|
|
|
+ configMappingEntity.getConfigType(), configMappingEntity.getVersionTag(),
|
|
|
+ cluster.getClusterName());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Populate Hosts
|
|
|
- for (ConfigGroupHostMappingEntity hostMappingEntity : configGroupEntity
|
|
|
- .getConfigGroupHostMappingEntities()) {
|
|
|
-
|
|
|
+ for (ConfigGroupHostMappingEntity hostMappingEntity : configGroupEntity.getConfigGroupHostMappingEntities()) {
|
|
|
try {
|
|
|
Host host = clusters.getHost(hostMappingEntity.getHostname());
|
|
|
HostEntity hostEntity = hostMappingEntity.getHostEntity();
|
|
|
if (host != null && hostEntity != null) {
|
|
|
- hosts.put(hostEntity.getHostId(), host);
|
|
|
+ m_hosts.put(hostEntity.getHostId(), host);
|
|
|
}
|
|
|
} catch (AmbariException e) {
|
|
|
- String msg = "Host seems to be deleted but Config group mapping still " +
|
|
|
- "exists !";
|
|
|
- LOG.warn(msg);
|
|
|
- LOG.debug(msg, e);
|
|
|
+ LOG.warn("Host seems to be deleted but Config group mapping still exists !");
|
|
|
+ LOG.debug("Host seems to be deleted but Config group mapping still exists !", e);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- isPersisted = true;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public Long getId() {
|
|
|
- return configGroupEntity.getGroupId();
|
|
|
+ return configGroupId;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public String getName() {
|
|
|
- readWriteLock.readLock().lock();
|
|
|
- try {
|
|
|
- return configGroupEntity.getGroupName();
|
|
|
- } finally {
|
|
|
- readWriteLock.readLock().unlock();
|
|
|
- }
|
|
|
+ return configGroupName;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void setName(String name) {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
- try {
|
|
|
- configGroupEntity.setGroupName(name);
|
|
|
- } finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
- }
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+ configGroupEntity.setGroupName(name);
|
|
|
+ configGroupDAO.merge(configGroupEntity);
|
|
|
|
|
|
+ configGroupName = name;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public String getClusterName() {
|
|
|
- return configGroupEntity.getClusterEntity().getClusterName();
|
|
|
+ return cluster.getClusterName();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public String getTag() {
|
|
|
- readWriteLock.readLock().lock();
|
|
|
- try {
|
|
|
- return configGroupEntity.getTag();
|
|
|
- } finally {
|
|
|
- readWriteLock.readLock().unlock();
|
|
|
- }
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+ return configGroupEntity.getTag();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void setTag(String tag) {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
- try {
|
|
|
- configGroupEntity.setTag(tag);
|
|
|
- } finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
- }
|
|
|
-
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+ configGroupEntity.setTag(tag);
|
|
|
+ configGroupDAO.merge(configGroupEntity);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public String getDescription() {
|
|
|
- readWriteLock.readLock().lock();
|
|
|
- try {
|
|
|
- return configGroupEntity.getDescription();
|
|
|
- } finally {
|
|
|
- readWriteLock.readLock().unlock();
|
|
|
- }
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+ return configGroupEntity.getDescription();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void setDescription(String description) {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
- try {
|
|
|
- configGroupEntity.setDescription(description);
|
|
|
- } finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
- }
|
|
|
-
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+ configGroupEntity.setDescription(description);
|
|
|
+ configGroupDAO.merge(configGroupEntity);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public Map<Long, Host> getHosts() {
|
|
|
- readWriteLock.readLock().lock();
|
|
|
- try {
|
|
|
- return Collections.unmodifiableMap(hosts);
|
|
|
- } finally {
|
|
|
- readWriteLock.readLock().unlock();
|
|
|
- }
|
|
|
+ return Collections.unmodifiableMap(m_hosts);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public Map<String, Config> getConfigurations() {
|
|
|
- readWriteLock.readLock().lock();
|
|
|
- try {
|
|
|
- return Collections.unmodifiableMap(configurations);
|
|
|
- } finally {
|
|
|
- readWriteLock.readLock().unlock();
|
|
|
- }
|
|
|
-
|
|
|
+ return Collections.unmodifiableMap(m_configurations);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -259,13 +245,14 @@ public class ConfigGroupImpl implements ConfigGroup {
|
|
|
*/
|
|
|
@Override
|
|
|
public void setHosts(Map<Long, Host> hosts) {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
+ hostLock.writeLock().lock();
|
|
|
try {
|
|
|
- this.hosts = hosts;
|
|
|
+ // persist enitites in a transaction first, then update internal state
|
|
|
+ replaceHostMappings(hosts);
|
|
|
+ m_hosts = new ConcurrentHashMap<>(hosts);
|
|
|
} finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
+ hostLock.writeLock().unlock();
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -273,115 +260,140 @@ public class ConfigGroupImpl implements ConfigGroup {
|
|
|
* @param configs
|
|
|
*/
|
|
|
@Override
|
|
|
- public void setConfigurations(Map<String, Config> configs) {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
- try {
|
|
|
- configurations = configs;
|
|
|
- } finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
- }
|
|
|
-
|
|
|
+ public void setConfigurations(Map<String, Config> configurations) {
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+ ClusterEntity clusterEntity = configGroupEntity.getClusterEntity();
|
|
|
+
|
|
|
+ // only update the internal state after the configurations have been
|
|
|
+ // persisted
|
|
|
+ persistConfigMapping(clusterEntity, configGroupEntity, configurations);
|
|
|
+ m_configurations = new ConcurrentHashMap<>(configurations);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- @Transactional
|
|
|
public void removeHost(Long hostId) throws AmbariException {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
+ hostLock.writeLock().lock();
|
|
|
try {
|
|
|
- if (hosts.containsKey(hostId)) {
|
|
|
- String hostName = hosts.get(hostId).getHostName();
|
|
|
- LOG.info("Removing host from config group, hostid = " + hostId + ", hostname = " + hostName);
|
|
|
- hosts.remove(hostId);
|
|
|
- try {
|
|
|
- ConfigGroupHostMappingEntityPK hostMappingEntityPK = new
|
|
|
- ConfigGroupHostMappingEntityPK();
|
|
|
- hostMappingEntityPK.setHostId(hostId);
|
|
|
- hostMappingEntityPK.setConfigGroupId(configGroupEntity.getGroupId());
|
|
|
- configGroupHostMappingDAO.removeByPK(hostMappingEntityPK);
|
|
|
- } catch (Exception e) {
|
|
|
- LOG.error("Failed to delete config group host mapping"
|
|
|
- + ", clusterName = " + getClusterName()
|
|
|
- + ", id = " + getId()
|
|
|
- + ", hostid = " + hostId
|
|
|
- + ", hostname = " + hostName, e);
|
|
|
- throw new AmbariException(e.getMessage());
|
|
|
- }
|
|
|
+ Host host = m_hosts.get(hostId);
|
|
|
+ if (null == host) {
|
|
|
+ return;
|
|
|
}
|
|
|
- } finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- @Override
|
|
|
- public void persist() {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
- try {
|
|
|
- if (!isPersisted) {
|
|
|
- persistEntities();
|
|
|
- refresh();
|
|
|
- cluster.refresh();
|
|
|
- isPersisted = true;
|
|
|
- } else {
|
|
|
- saveIfPersisted();
|
|
|
+ String hostName = host.getHostName();
|
|
|
+ LOG.info("Removing host (id={}, name={}) from config group", host.getHostId(), hostName);
|
|
|
+
|
|
|
+ try {
|
|
|
+ // remove the entities first, then update internal state
|
|
|
+ removeConfigGroupHostEntity(host);
|
|
|
+ m_hosts.remove(hostId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ LOG.error("Failed to delete config group host mapping for cluster {} and host {}",
|
|
|
+ cluster.getClusterName(), hostName, e);
|
|
|
+
|
|
|
+ throw new AmbariException(e.getMessage());
|
|
|
}
|
|
|
} finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
+ hostLock.writeLock().unlock();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Removes the {@link ConfigGroupHostMappingEntity} for the specified host
|
|
|
+ * from this configuration group.
|
|
|
+ *
|
|
|
+ * @param host
|
|
|
+ * the host to remove.
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ void removeConfigGroupHostEntity(Host host) {
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+ ConfigGroupHostMappingEntityPK hostMappingEntityPK = new ConfigGroupHostMappingEntityPK();
|
|
|
+ hostMappingEntityPK.setHostId(host.getHostId());
|
|
|
+ hostMappingEntityPK.setConfigGroupId(configGroupId);
|
|
|
+
|
|
|
+ ConfigGroupHostMappingEntity configGroupHostMapping = configGroupHostMappingDAO.findByPK(
|
|
|
+ hostMappingEntityPK);
|
|
|
+
|
|
|
+ configGroupHostMappingDAO.remove(configGroupHostMapping);
|
|
|
+
|
|
|
+ configGroupEntity.getConfigGroupHostMappingEntities().remove(configGroupHostMapping);
|
|
|
+ configGroupEntity = configGroupDAO.merge(getConfigGroupEntity());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param configGroupEntity
|
|
|
+ */
|
|
|
+ private void persist(ConfigGroupEntity configGroupEntity) {
|
|
|
+ persistEntities(configGroupEntity);
|
|
|
+ cluster.refresh();
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Persist Config group with host mapping and configurations
|
|
|
*
|
|
|
* @throws Exception
|
|
|
*/
|
|
|
@Transactional
|
|
|
- void persistEntities() {
|
|
|
+ void persistEntities(ConfigGroupEntity configGroupEntity) {
|
|
|
ClusterEntity clusterEntity = clusterDAO.findById(cluster.getClusterId());
|
|
|
configGroupEntity.setClusterEntity(clusterEntity);
|
|
|
configGroupEntity.setTimestamp(System.currentTimeMillis());
|
|
|
configGroupDAO.create(configGroupEntity);
|
|
|
|
|
|
- persistConfigMapping(clusterEntity);
|
|
|
- persistHostMapping();
|
|
|
- }
|
|
|
+ configGroupId = configGroupEntity.getGroupId();
|
|
|
|
|
|
- // TODO: Test rollback scenario
|
|
|
+ persistConfigMapping(clusterEntity, configGroupEntity, m_configurations);
|
|
|
+ replaceHostMappings(m_hosts);
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
- * Persist host mapping
|
|
|
+ * Replaces all existing host mappings with the new collection of hosts.
|
|
|
*
|
|
|
+ * @param the
|
|
|
+ * new hosts
|
|
|
* @throws Exception
|
|
|
*/
|
|
|
- @Override
|
|
|
@Transactional
|
|
|
- public void persistHostMapping() {
|
|
|
- if (isPersisted) {
|
|
|
- // Delete existing mappings and create new ones
|
|
|
- configGroupHostMappingDAO.removeAllByGroup(configGroupEntity.getGroupId());
|
|
|
- configGroupEntity.setConfigGroupHostMappingEntities(new HashSet<ConfigGroupHostMappingEntity>());
|
|
|
- }
|
|
|
+ void replaceHostMappings(Map<Long, Host> hosts) {
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+
|
|
|
+ // Delete existing mappings and create new ones
|
|
|
+ configGroupHostMappingDAO.removeAllByGroup(configGroupEntity.getGroupId());
|
|
|
+ configGroupEntity.setConfigGroupHostMappingEntities(
|
|
|
+ new HashSet<ConfigGroupHostMappingEntity>());
|
|
|
|
|
|
if (hosts != null && !hosts.isEmpty()) {
|
|
|
- for (Host host : hosts.values()) {
|
|
|
- HostEntity hostEntity = hostDAO.findById(host.getHostId());
|
|
|
- if (hostEntity != null) {
|
|
|
- ConfigGroupHostMappingEntity hostMappingEntity = new
|
|
|
- ConfigGroupHostMappingEntity();
|
|
|
- hostMappingEntity.setHostId(hostEntity.getHostId());
|
|
|
- hostMappingEntity.setHostEntity(hostEntity);
|
|
|
- hostMappingEntity.setConfigGroupEntity(configGroupEntity);
|
|
|
- hostMappingEntity.setConfigGroupId(configGroupEntity.getGroupId());
|
|
|
- configGroupEntity.getConfigGroupHostMappingEntities().add
|
|
|
- (hostMappingEntity);
|
|
|
- configGroupHostMappingDAO.create(hostMappingEntity);
|
|
|
- } else {
|
|
|
- LOG.warn("Host seems to be deleted, cannot create host to config " +
|
|
|
- "group mapping, host = " + host.getHostName());
|
|
|
- }
|
|
|
+ configGroupEntity = persistHostMapping(hosts.values(), configGroupEntity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Adds the collection of hosts to the configuration group.
|
|
|
+ *
|
|
|
+ * @param hostEntity
|
|
|
+ * @param configGroupEntity
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ ConfigGroupEntity persistHostMapping(Collection<Host> hosts,
|
|
|
+ ConfigGroupEntity configGroupEntity) {
|
|
|
+ for (Host host : hosts) {
|
|
|
+ HostEntity hostEntity = hostDAO.findById(host.getHostId());
|
|
|
+ if (hostEntity != null) {
|
|
|
+ ConfigGroupHostMappingEntity hostMappingEntity = new ConfigGroupHostMappingEntity();
|
|
|
+ hostMappingEntity.setHostId(hostEntity.getHostId());
|
|
|
+ hostMappingEntity.setHostEntity(hostEntity);
|
|
|
+ hostMappingEntity.setConfigGroupEntity(configGroupEntity);
|
|
|
+ hostMappingEntity.setConfigGroupId(configGroupEntity.getGroupId());
|
|
|
+ configGroupEntity.getConfigGroupHostMappingEntities().add(hostMappingEntity);
|
|
|
+ configGroupHostMappingDAO.create(hostMappingEntity);
|
|
|
+ } else {
|
|
|
+ LOG.warn(
|
|
|
+ "The host {} has been removed from the cluster and cannot be added to the configuration group {}",
|
|
|
+ host.getHostName(), configGroupName);
|
|
|
}
|
|
|
}
|
|
|
- // TODO: Make sure this does not throw Nullpointer based on JPA docs
|
|
|
- configGroupEntity = configGroupDAO.merge(configGroupEntity);
|
|
|
+
|
|
|
+ return configGroupDAO.merge(configGroupEntity);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -391,42 +403,31 @@ public class ConfigGroupImpl implements ConfigGroup {
|
|
|
* @throws Exception
|
|
|
*/
|
|
|
@Transactional
|
|
|
- void persistConfigMapping(ClusterEntity clusterEntity) {
|
|
|
- if (isPersisted) {
|
|
|
- configGroupConfigMappingDAO.removeAllByGroup(configGroupEntity.getGroupId());
|
|
|
- configGroupEntity.setConfigGroupConfigMappingEntities(new HashSet<ConfigGroupConfigMappingEntity>());
|
|
|
- }
|
|
|
+ void persistConfigMapping(ClusterEntity clusterEntity,
|
|
|
+ ConfigGroupEntity configGroupEntity, Map<String, Config> configurations) {
|
|
|
+ configGroupConfigMappingDAO.removeAllByGroup(configGroupEntity.getGroupId());
|
|
|
+ configGroupEntity.setConfigGroupConfigMappingEntities(
|
|
|
+ new HashSet<ConfigGroupConfigMappingEntity>());
|
|
|
|
|
|
if (configurations != null && !configurations.isEmpty()) {
|
|
|
- for (Config config : configurations.values()) {
|
|
|
+ for (Entry<String, Config> entry : configurations.entrySet()) {
|
|
|
+ Config config = entry.getValue();
|
|
|
ClusterConfigEntity clusterConfigEntity = clusterDAO.findConfig
|
|
|
(cluster.getClusterId(), config.getType(), config.getTag());
|
|
|
|
|
|
if (clusterConfigEntity == null) {
|
|
|
- config.setVersion(cluster.getNextConfigVersion(config.getType()));
|
|
|
- config.setStackId(cluster.getDesiredStackVersion());
|
|
|
- // Create configuration
|
|
|
- clusterConfigEntity = new ClusterConfigEntity();
|
|
|
- clusterConfigEntity.setClusterId(clusterEntity.getClusterId());
|
|
|
- clusterConfigEntity.setClusterEntity(clusterEntity);
|
|
|
- clusterConfigEntity.setStack(clusterEntity.getDesiredStack());
|
|
|
- clusterConfigEntity.setType(config.getType());
|
|
|
- clusterConfigEntity.setVersion(config.getVersion());
|
|
|
- clusterConfigEntity.setTag(config.getTag());
|
|
|
- clusterConfigEntity.setData(gson.toJson(config.getProperties()));
|
|
|
- if (null != config.getPropertiesAttributes()) {
|
|
|
- clusterConfigEntity.setAttributes(gson.toJson(config.getPropertiesAttributes()));
|
|
|
- }
|
|
|
- clusterConfigEntity.setTimestamp(System.currentTimeMillis());
|
|
|
- clusterDAO.createConfig(clusterConfigEntity);
|
|
|
- clusterEntity.getClusterConfigEntities().add(clusterConfigEntity);
|
|
|
- cluster.addConfig(config);
|
|
|
- clusterDAO.merge(clusterEntity);
|
|
|
- cluster.refresh();
|
|
|
+ config = configFactory.createNew(cluster, config.getType(), config.getTag(),
|
|
|
+ config.getProperties(), config.getPropertiesAttributes());
|
|
|
+
|
|
|
+ entry.setValue(config);
|
|
|
+
|
|
|
+ clusterConfigEntity = clusterDAO.findConfig(cluster.getClusterId(), config.getType(),
|
|
|
+ config.getTag());
|
|
|
}
|
|
|
|
|
|
ConfigGroupConfigMappingEntity configMappingEntity =
|
|
|
new ConfigGroupConfigMappingEntity();
|
|
|
+
|
|
|
configMappingEntity.setTimestamp(System.currentTimeMillis());
|
|
|
configMappingEntity.setClusterId(clusterEntity.getClusterId());
|
|
|
configMappingEntity.setClusterConfigEntity(clusterConfigEntity);
|
|
@@ -443,142 +444,84 @@ public class ConfigGroupImpl implements ConfigGroup {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- void saveIfPersisted() {
|
|
|
- if (isPersisted) {
|
|
|
- save(clusterDAO.findById(cluster.getClusterId()));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Transactional
|
|
|
- void save(ClusterEntity clusterEntity) {
|
|
|
- persistHostMapping();
|
|
|
- persistConfigMapping(clusterEntity);
|
|
|
- }
|
|
|
-
|
|
|
@Override
|
|
|
+ @Transactional
|
|
|
public void delete() {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
- try {
|
|
|
- configGroupConfigMappingDAO.removeAllByGroup(configGroupEntity.getGroupId());
|
|
|
- configGroupHostMappingDAO.removeAllByGroup(configGroupEntity.getGroupId());
|
|
|
- configGroupDAO.removeByPK(configGroupEntity.getGroupId());
|
|
|
- cluster.refresh();
|
|
|
- isPersisted = false;
|
|
|
- } finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
- }
|
|
|
+ configGroupConfigMappingDAO.removeAllByGroup(configGroupId);
|
|
|
+ configGroupHostMappingDAO.removeAllByGroup(configGroupId);
|
|
|
+ configGroupDAO.removeByPK(configGroupId);
|
|
|
+ cluster.refresh();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void addHost(Host host) throws AmbariException {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
+ hostLock.writeLock().lock();
|
|
|
try {
|
|
|
- if (hosts != null && !hosts.isEmpty()) {
|
|
|
- for (Host h : hosts.values()) {
|
|
|
- if (h.getHostName().equals(host.getHostName())) {
|
|
|
- throw new DuplicateResourceException("Host " + h.getHostName() +
|
|
|
- "is already associated with Config Group " +
|
|
|
- configGroupEntity.getGroupName());
|
|
|
- }
|
|
|
- }
|
|
|
- HostEntity hostEntity = hostDAO.findByName(host.getHostName());
|
|
|
- if (hostEntity != null) {
|
|
|
- hosts.put(hostEntity.getHostId(), host);
|
|
|
- }
|
|
|
- }
|
|
|
- } finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
- }
|
|
|
- }
|
|
|
+ if (m_hosts.containsKey(host.getHostId())) {
|
|
|
+ String message = String.format(
|
|
|
+ "Host %s is already associated with the configuration group %s", host.getHostName(),
|
|
|
+ configGroupName);
|
|
|
|
|
|
- @Override
|
|
|
- public void addConfiguration(Config config) throws AmbariException {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
- try {
|
|
|
- if (configurations != null && !configurations.isEmpty()) {
|
|
|
- for (Config c : configurations.values()) {
|
|
|
- if (c.getType().equals(config.getType()) && c.getTag().equals
|
|
|
- (config.getTag())) {
|
|
|
- throw new DuplicateResourceException("Config " + config.getType() +
|
|
|
- " with tag " + config.getTag() + " is already associated " +
|
|
|
- "with Config Group " + configGroupEntity.getGroupName());
|
|
|
- }
|
|
|
- }
|
|
|
- configurations.put(config.getType(), config);
|
|
|
+ throw new DuplicateResourceException(message);
|
|
|
}
|
|
|
+
|
|
|
+ // ensure that we only update the in-memory structure if the merge was
|
|
|
+ // successful
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+ persistHostMapping(Collections.singletonList(host), configGroupEntity);
|
|
|
+ m_hosts.putIfAbsent(host.getHostId(), host);
|
|
|
} finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
+ hostLock.writeLock().unlock();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public ConfigGroupResponse convertToResponse() throws AmbariException {
|
|
|
- readWriteLock.readLock().lock();
|
|
|
- try {
|
|
|
- Set<Map<String, Object>> hostnames = new HashSet<Map<String, Object>>();
|
|
|
- for (Host host : hosts.values()) {
|
|
|
- Map<String, Object> hostMap = new HashMap<String, Object>();
|
|
|
- hostMap.put("host_name", host.getHostName());
|
|
|
- hostnames.add(hostMap);
|
|
|
- }
|
|
|
-
|
|
|
- Set<Map<String, Object>> configObjMap = new HashSet<Map<String, Object>>();
|
|
|
+ Set<Map<String, Object>> hostnames = new HashSet<Map<String, Object>>();
|
|
|
+ for (Host host : m_hosts.values()) {
|
|
|
+ Map<String, Object> hostMap = new HashMap<String, Object>();
|
|
|
+ hostMap.put("host_name", host.getHostName());
|
|
|
+ hostnames.add(hostMap);
|
|
|
+ }
|
|
|
|
|
|
- for (Config config : configurations.values()) {
|
|
|
- Map<String, Object> configMap = new HashMap<String, Object>();
|
|
|
- configMap.put(ConfigurationResourceProvider.CONFIGURATION_CONFIG_TYPE_PROPERTY_ID,
|
|
|
- config.getType());
|
|
|
- configMap.put(ConfigurationResourceProvider.CONFIGURATION_CONFIG_TAG_PROPERTY_ID,
|
|
|
- config.getTag());
|
|
|
- configObjMap.add(configMap);
|
|
|
- }
|
|
|
+ Set<Map<String, Object>> configObjMap = new HashSet<Map<String, Object>>();
|
|
|
|
|
|
- ConfigGroupResponse configGroupResponse = new ConfigGroupResponse(
|
|
|
- configGroupEntity.getGroupId(), cluster.getClusterName(),
|
|
|
- configGroupEntity.getGroupName(), configGroupEntity.getTag(),
|
|
|
- configGroupEntity.getDescription(), hostnames, configObjMap);
|
|
|
- return configGroupResponse;
|
|
|
- } finally {
|
|
|
- readWriteLock.readLock().unlock();
|
|
|
+ for (Config config : m_configurations.values()) {
|
|
|
+ Map<String, Object> configMap = new HashMap<String, Object>();
|
|
|
+ configMap.put(ConfigurationResourceProvider.CONFIGURATION_CONFIG_TYPE_PROPERTY_ID,
|
|
|
+ config.getType());
|
|
|
+ configMap.put(ConfigurationResourceProvider.CONFIGURATION_CONFIG_TAG_PROPERTY_ID,
|
|
|
+ config.getTag());
|
|
|
+ configObjMap.add(configMap);
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- @Override
|
|
|
- @Transactional
|
|
|
- public void refresh() {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
- try {
|
|
|
- if (isPersisted) {
|
|
|
- ConfigGroupEntity groupEntity = configGroupDAO.findById
|
|
|
- (configGroupEntity.getGroupId());
|
|
|
- configGroupDAO.refresh(groupEntity);
|
|
|
- // TODO What other entities should refresh?
|
|
|
- }
|
|
|
- } finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
- }
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+ ConfigGroupResponse configGroupResponse = new ConfigGroupResponse(
|
|
|
+ configGroupEntity.getGroupId(), cluster.getClusterName(),
|
|
|
+ configGroupEntity.getGroupName(), configGroupEntity.getTag(),
|
|
|
+ configGroupEntity.getDescription(), hostnames, configObjMap);
|
|
|
+ return configGroupResponse;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
@Override
|
|
|
public String getServiceName() {
|
|
|
- readWriteLock.readLock().lock();
|
|
|
- try {
|
|
|
- return configGroupEntity.getServiceName();
|
|
|
- } finally {
|
|
|
- readWriteLock.readLock().unlock();
|
|
|
- }
|
|
|
-
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+ return configGroupEntity.getServiceName();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void setServiceName(String serviceName) {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
- try {
|
|
|
- configGroupEntity.setServiceName(serviceName);
|
|
|
- } finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
- }
|
|
|
+ ConfigGroupEntity configGroupEntity = getConfigGroupEntity();
|
|
|
+ configGroupEntity.setServiceName(serviceName);
|
|
|
+ configGroupDAO.merge(configGroupEntity);
|
|
|
+ }
|
|
|
|
|
|
+ /**
|
|
|
+ * Gets the {@link ConfigGroupEntity} by it's ID from the JPA cache.
|
|
|
+ *
|
|
|
+ * @return the entity.
|
|
|
+ */
|
|
|
+ private ConfigGroupEntity getConfigGroupEntity() {
|
|
|
+ return configGroupDAO.findById(configGroupId);
|
|
|
}
|
|
|
}
|