/** * 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.orm.dao; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.orm.RequiresSession; import org.apache.ambari.server.orm.cache.ConfigGroupHostMapping; import org.apache.ambari.server.orm.cache.ConfigGroupHostMappingImpl; import org.apache.ambari.server.orm.entities.ConfigGroupEntity; import org.apache.ambari.server.orm.entities.ConfigGroupHostMappingEntity; import org.apache.ambari.server.orm.entities.ConfigGroupHostMappingEntityPK; 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.Host; import org.apache.ambari.server.state.cluster.ClusterFactory; import org.apache.ambari.server.state.configgroup.ConfigGroup; import org.apache.ambari.server.state.configgroup.ConfigGroupFactory; import org.apache.ambari.server.state.host.HostFactory; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.persist.Transactional; @Singleton public class ConfigGroupHostMappingDAO { @Inject Provider<EntityManager> entityManagerProvider; @Inject DaoUtils daoUtils; @Inject private ConfigGroupFactory configGroupFactory; @Inject private ClusterFactory clusterFactory; @Inject private HostFactory hostFactory; @Inject Clusters clusters; private final ReadWriteLock gl = new ReentrantReadWriteLock(); private Map<Long, Set<ConfigGroupHostMapping>> configGroupHostMappingByHost; private volatile boolean cacheLoaded; private void populateCache() { if (!cacheLoaded) { gl.writeLock().lock(); try { if (!cacheLoaded) { if (configGroupHostMappingByHost == null) { configGroupHostMappingByHost = new HashMap<>(); TypedQuery<ConfigGroupHostMappingEntity> query = entityManagerProvider.get().createQuery( "SELECT entity FROM ConfigGroupHostMappingEntity entity", ConfigGroupHostMappingEntity.class); List<ConfigGroupHostMappingEntity> configGroupHostMappingEntities = daoUtils.selectList(query); for (ConfigGroupHostMappingEntity configGroupHostMappingEntity : configGroupHostMappingEntities) { Set<ConfigGroupHostMapping> setByHost = configGroupHostMappingByHost.get((configGroupHostMappingEntity.getHostId())); if (setByHost == null) { setByHost = new HashSet<>(); configGroupHostMappingByHost.put(configGroupHostMappingEntity.getHostId(), setByHost); } ConfigGroupHostMapping configGroupHostMapping = buildConfigGroupHostMapping(configGroupHostMappingEntity); setByHost.add(configGroupHostMapping); } } cacheLoaded = true; } } finally { gl.writeLock().unlock(); } } } /** * Return entity object which can be used for operations like remove * directly. * @param configGroupHostMappingEntityPK * @return */ @RequiresSession public ConfigGroupHostMappingEntity findByPK(final ConfigGroupHostMappingEntityPK configGroupHostMappingEntityPK) { return entityManagerProvider.get() .find(ConfigGroupHostMappingEntity.class, configGroupHostMappingEntityPK); } @RequiresSession public Set<ConfigGroupHostMapping> findByHostId(Long hostId) { populateCache(); if (!configGroupHostMappingByHost.containsKey(hostId)) { return null; } Set<ConfigGroupHostMapping> set = new HashSet<>(configGroupHostMappingByHost.get(hostId)); return set; } @RequiresSession public Set<ConfigGroupHostMapping> findByGroup(final Long groupId) { populateCache(); Set<ConfigGroupHostMapping> result = new HashSet<>(); for (Set<ConfigGroupHostMapping> item : configGroupHostMappingByHost.values()) { Set<ConfigGroupHostMapping> setByHost = new HashSet<>(item); CollectionUtils.filter(setByHost, new Predicate() { @Override public boolean evaluate(Object arg0) { return ((ConfigGroupHostMapping) arg0).getConfigGroupId().equals(groupId); } }); result.addAll(setByHost); } return result; } @RequiresSession public List<ConfigGroupHostMappingEntity> findAll() { return daoUtils.selectAll(entityManagerProvider.get(), ConfigGroupHostMappingEntity.class); } @Transactional public void create(ConfigGroupHostMappingEntity configGroupHostMappingEntity) { populateCache(); entityManagerProvider.get().persist(configGroupHostMappingEntity); //create in cache Set<ConfigGroupHostMapping> set = configGroupHostMappingByHost.get(configGroupHostMappingEntity.getHostId()); if (set == null){ set = new HashSet<>(); configGroupHostMappingByHost.put(configGroupHostMappingEntity.getHostId(), set); } set.add(buildConfigGroupHostMapping(configGroupHostMappingEntity)); } @Transactional public ConfigGroupHostMappingEntity merge(ConfigGroupHostMappingEntity configGroupHostMappingEntity) { populateCache(); Set<ConfigGroupHostMapping> set = configGroupHostMappingByHost.get(configGroupHostMappingEntity.getHostId()); if (set == null){ set = new HashSet<>(); configGroupHostMappingByHost.put(configGroupHostMappingEntity.getHostId(), set); } //Update object in set set.remove(buildConfigGroupHostMapping(configGroupHostMappingEntity)); set.add(buildConfigGroupHostMapping(configGroupHostMappingEntity)); return entityManagerProvider.get().merge(configGroupHostMappingEntity); } @Transactional public void refresh(ConfigGroupHostMappingEntity configGroupHostMappingEntity) { cacheLoaded = false; populateCache(); entityManagerProvider.get().refresh(configGroupHostMappingEntity); } @Transactional public void remove(final ConfigGroupHostMappingEntity configGroupHostMappingEntity) { populateCache(); entityManagerProvider.get().remove(merge(configGroupHostMappingEntity)); Set<ConfigGroupHostMapping> setByHost = configGroupHostMappingByHost.get(configGroupHostMappingEntity.getHostId()); if (setByHost != null) { CollectionUtils.filter(setByHost, new Predicate() { @Override public boolean evaluate(Object arg0) { return !((ConfigGroupHostMapping) arg0).getConfigGroupId(). equals(configGroupHostMappingEntity.getConfigGroupId()); } }); } } @Transactional public void removeByPK(final ConfigGroupHostMappingEntityPK configGroupHostMappingEntityPK) { populateCache(); entityManagerProvider.get().remove(findByPK(configGroupHostMappingEntityPK)); Set<ConfigGroupHostMapping> setByHost = configGroupHostMappingByHost.get(configGroupHostMappingEntityPK.getHostId()); if (setByHost != null) { CollectionUtils.filter(setByHost, new Predicate() { @Override public boolean evaluate(Object arg0) { return !((ConfigGroupHostMapping) arg0).getConfigGroupId(). equals(configGroupHostMappingEntityPK.getConfigGroupId()); } }); } } @Transactional public void removeAllByGroup(final Long groupId) { populateCache(); TypedQuery<Long> query = entityManagerProvider.get().createQuery ("DELETE FROM ConfigGroupHostMappingEntity confighosts WHERE " + "confighosts.configGroupId = ?1", Long.class); daoUtils.executeUpdate(query, groupId); // Flush to current transaction required in order to avoid Eclipse link // from re-ordering delete entityManagerProvider.get().flush(); for (Set<ConfigGroupHostMapping> setByHost : configGroupHostMappingByHost.values()) { CollectionUtils.filter(setByHost, new Predicate() { @Override public boolean evaluate(Object arg0) { return !((ConfigGroupHostMapping) arg0).getConfigGroupId().equals(groupId); } }); } } @Transactional public void removeAllByHost(Long hostId) { TypedQuery<String> query = entityManagerProvider.get().createQuery ("DELETE FROM ConfigGroupHostMappingEntity confighosts WHERE " + "confighosts.hostId = ?1", String.class); daoUtils.executeUpdate(query, hostId); Set<ConfigGroupHostMapping> setByHost = configGroupHostMappingByHost.get(hostId); setByHost.clear(); } private ConfigGroupHostMapping buildConfigGroupHostMapping( ConfigGroupHostMappingEntity configGroupHostMappingEntity) { ConfigGroupHostMappingImpl configGroupHostMapping = new ConfigGroupHostMappingImpl(); configGroupHostMapping.setConfigGroup(buildConfigGroup(configGroupHostMappingEntity.getConfigGroupEntity())); configGroupHostMapping.setConfigGroupId(configGroupHostMappingEntity.getConfigGroupId()); configGroupHostMapping.setHost(buildHost(configGroupHostMappingEntity.getHostEntity())); configGroupHostMapping.setHostId(configGroupHostMappingEntity.getHostId()); return configGroupHostMapping; } private ConfigGroup buildConfigGroup(ConfigGroupEntity configGroupEntity) { Cluster cluster = null; try { cluster = clusters.getClusterById(configGroupEntity.getClusterId()); } catch (AmbariException e) { //almost impossible } ConfigGroup configGroup = configGroupFactory.createExisting(cluster, configGroupEntity); return configGroup; } private Host buildHost(HostEntity hostEntity) { Host host = hostFactory.create(hostEntity); return host; } }