/** * 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.ArrayList; import java.util.Collection; 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.concurrent.ConcurrentHashMap; 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.orm.RequiresSession; import org.apache.ambari.server.orm.cache.HostConfigMapping; import org.apache.ambari.server.orm.cache.HostConfigMappingImpl; import org.apache.ambari.server.orm.entities.HostConfigMappingEntity; import org.apache.ambari.server.orm.entities.HostEntity; 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; /** * Used for host configuration mapping operations. */ @Singleton public class HostConfigMappingDAO { @Inject private Provider<EntityManager> entityManagerProvider; @Inject private DaoUtils daoUtils; @Inject private HostDAO hostDAO; private final ReadWriteLock gl = new ReentrantReadWriteLock(); private ConcurrentHashMap<Long, Set<HostConfigMapping>> hostConfigMappingByHost; private volatile boolean cacheLoaded; private void populateCache() { if (!cacheLoaded) { if (hostConfigMappingByHost == null) { hostConfigMappingByHost = new ConcurrentHashMap<>(); TypedQuery<HostConfigMappingEntity> query = entityManagerProvider.get().createNamedQuery( "HostConfigMappingEntity.findAll", HostConfigMappingEntity.class); List<HostConfigMappingEntity> hostConfigMappingEntities = daoUtils.selectList(query); for (HostConfigMappingEntity hostConfigMappingEntity : hostConfigMappingEntities) { Long hostId = hostConfigMappingEntity.getHostId(); if (hostId == null) { continue; } Set<HostConfigMapping> setByHost; if (hostConfigMappingByHost.containsKey(hostId)) { setByHost = hostConfigMappingByHost.get(hostId); } else { setByHost = new HashSet<>(); hostConfigMappingByHost.put(hostId, setByHost); } HostConfigMapping hostConfigMapping = buildHostConfigMapping(hostConfigMappingEntity); setByHost.add(hostConfigMapping); } } cacheLoaded = true; } } @Transactional public void create(HostConfigMapping hostConfigMapping) { populateCache(); //create in db entityManagerProvider.get().persist(buildHostConfigMappingEntity(hostConfigMapping)); //create in cache Long hostId = hostConfigMapping.getHostId(); if (hostId != null) { Set<HostConfigMapping> set; if (hostConfigMappingByHost.containsKey(hostId)) { set = hostConfigMappingByHost.get(hostId); } else { set = new HashSet<>(); hostConfigMappingByHost.put(hostId, set); } set.add(hostConfigMapping); } } @Transactional public HostConfigMapping merge(HostConfigMapping hostConfigMapping) { populateCache(); Long hostId = hostConfigMapping.getHostId(); if (hostId != null) { Set<HostConfigMapping> set; if (hostConfigMappingByHost.containsKey(hostId)) { set = hostConfigMappingByHost.get(hostId); } else { set = new HashSet<>(); hostConfigMappingByHost.put(hostId, set); } //Update object in set set.remove(hostConfigMapping); set.add(hostConfigMapping); entityManagerProvider.get().merge(buildHostConfigMappingEntity(hostConfigMapping)); } return hostConfigMapping; } @RequiresSession public Set<HostConfigMapping> findByType(final long clusterId, Long hostId, final String type) { populateCache(); if (!hostConfigMappingByHost.containsKey(hostId)) return Collections.emptySet(); Set<HostConfigMapping> set = new HashSet<>(hostConfigMappingByHost.get(hostId)); CollectionUtils.filter(set, new Predicate() { @Override public boolean evaluate(Object arg0) { return ((HostConfigMapping) arg0).getClusterId().equals(clusterId) && ((HostConfigMapping) arg0).getType().equals(type); } }); return set; } @RequiresSession public HostConfigMapping findSelectedByType(final long clusterId, Long hostId, final String type) { populateCache(); if (!hostConfigMappingByHost.containsKey(hostId)) return null; Set<HostConfigMapping> set = new HashSet<>(hostConfigMappingByHost.get(hostId)); HostConfigMapping result = (HostConfigMapping) CollectionUtils.find(set, new Predicate() { @Override public boolean evaluate(Object arg0) { return ((HostConfigMapping) arg0).getClusterId().equals(clusterId) && ((HostConfigMapping) arg0).getType().equals(type) && ((HostConfigMapping) arg0).getSelected() > 0; } }); return result; } @RequiresSession public Set<HostConfigMapping> findSelected(final long clusterId, Long hostId) { populateCache(); if (!hostConfigMappingByHost.containsKey(hostId)) return Collections.emptySet(); Set<HostConfigMapping> set = new HashSet<>(hostConfigMappingByHost.get(hostId)); CollectionUtils.filter(set, new Predicate() { @Override public boolean evaluate(Object arg0) { return ((HostConfigMapping) arg0).getClusterId().equals(clusterId) && ((HostConfigMapping) arg0).getSelected() > 0; } }); return set; } @RequiresSession public Set<HostConfigMapping> findSelectedByHosts(Collection<Long> hostIds) { populateCache(); if (hostIds == null || hostIds.isEmpty()) { return Collections.emptySet(); } HashSet<HostConfigMapping> result = new HashSet<>(); for (final Long hostId : hostIds) { if (!hostConfigMappingByHost.containsKey(hostId)) continue; Set<HostConfigMapping> set = new HashSet<>(hostConfigMappingByHost.get(hostId)); CollectionUtils.filter(set, new Predicate() { @Override public boolean evaluate(Object arg0) { return ((HostConfigMapping) arg0).getHostId().equals(hostId) && ((HostConfigMapping) arg0).getSelected() > 0; } }); result.addAll(set); } return result; } @RequiresSession public Map<String, List<HostConfigMapping>> findSelectedHostsByTypes(final long clusterId, Collection<String> types) { populateCache(); Map<String, List<HostConfigMapping>> mappingsByType = new HashMap<>(); for (String type : types) { if (!mappingsByType.containsKey(type)) { mappingsByType.put(type, new ArrayList<HostConfigMapping>()); } } if (!types.isEmpty()) { List<HostConfigMapping> mappings = new ArrayList<>(); for (Set<HostConfigMapping> entries : hostConfigMappingByHost.values()) { for (HostConfigMapping entry : entries) { if (types.contains(entry.getType()) && entry.getClusterId().equals(clusterId)) mappings.add(new HostConfigMappingImpl(entry)); } } for (HostConfigMapping mapping : mappings) { mappingsByType.get(mapping.getType()).add(mapping); } } return mappingsByType; } @RequiresSession public List<HostConfigMappingEntity> findAll() { return daoUtils.selectAll(entityManagerProvider.get(), HostConfigMappingEntity.class); } /** * @param hostId */ @Transactional public void removeByHostId(Long hostId) { populateCache(); HostEntity hostEntity = hostDAO.findById(hostId); if (hostEntity != null) { if (hostConfigMappingByHost.containsKey(hostEntity.getHostId())) { // Delete from db TypedQuery<HostConfigMappingEntity> query = entityManagerProvider.get().createNamedQuery( "HostConfigMappingEntity.findByHostId", HostConfigMappingEntity.class); query.setParameter("hostId", hostId); List<HostConfigMappingEntity> hostConfigMappingEntities = daoUtils.selectList(query); for (HostConfigMappingEntity entity : hostConfigMappingEntities) { entityManagerProvider.get().remove(entity); } // Update the cache hostConfigMappingByHost.remove(hostEntity.getHostId()); } } } /** * @param clusterId * @param hostName */ @Transactional public void removeByClusterAndHostName(final long clusterId, String hostName) { populateCache(); HostEntity hostEntity = hostDAO.findByName(hostName); if (hostEntity != null) { if (hostConfigMappingByHost.containsKey(hostName)) { // Delete from db TypedQuery<HostConfigMappingEntity> query = entityManagerProvider.get().createQuery( "SELECT entity FROM HostConfigMappingEntity entity " + "WHERE entity.clusterId = ?1 AND entity.hostId=?2", HostConfigMappingEntity.class); List<HostConfigMappingEntity> list = daoUtils.selectList(query, clusterId, hostEntity.getHostId()); for (HostConfigMappingEntity entity : list) { entityManagerProvider.get().remove(entity); } // Remove from cache items with given clusterId Set<HostConfigMapping> set = hostConfigMappingByHost.get(hostEntity.getHostId()); CollectionUtils.filter(set, new Predicate() { @Override public boolean evaluate(Object arg0) { return !((HostConfigMapping) arg0).getClusterId().equals(clusterId); } }); } } } public HostConfigMappingEntity buildHostConfigMappingEntity(HostConfigMapping hostConfigMapping) { HostEntity hostEntity = hostDAO.findById(hostConfigMapping.getHostId()); HostConfigMappingEntity hostConfigMappingEntity = new HostConfigMappingEntity(); hostConfigMappingEntity.setClusterId(hostConfigMapping.getClusterId()); hostConfigMappingEntity.setCreateTimestamp(hostConfigMapping.getCreateTimestamp()); hostConfigMappingEntity.setHostId(hostEntity.getHostId()); hostConfigMappingEntity.setSelected(hostConfigMapping.getSelected()); hostConfigMappingEntity.setServiceName(hostConfigMapping.getServiceName()); hostConfigMappingEntity.setType(hostConfigMapping.getType()); hostConfigMappingEntity.setUser(hostConfigMapping.getUser()); hostConfigMappingEntity.setVersion(hostConfigMapping.getVersion()); return hostConfigMappingEntity; } public HostConfigMapping buildHostConfigMapping( HostConfigMappingEntity hostConfigMappingEntity) { HostConfigMapping hostConfigMapping = new HostConfigMappingImpl(); hostConfigMapping.setClusterId(hostConfigMappingEntity.getClusterId()); hostConfigMapping.setCreateTimestamp(hostConfigMappingEntity.getCreateTimestamp()); hostConfigMapping.setHostId(hostConfigMappingEntity.getHostId()); hostConfigMapping.setServiceName(hostConfigMappingEntity.getServiceName()); hostConfigMapping.setType(hostConfigMappingEntity.getType()); hostConfigMapping.setUser(hostConfigMappingEntity.getUser()); hostConfigMapping.setSelected(hostConfigMappingEntity.isSelected()); hostConfigMapping.setVersion(hostConfigMappingEntity.getVersion()); return hostConfigMapping; } }