/**
* 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.List;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.TypedQuery;
import org.apache.ambari.server.orm.RequiresSession;
import org.apache.ambari.server.orm.entities.ClusterEntity;
import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
import org.apache.ambari.server.state.RepositoryVersionState;
import org.apache.ambari.server.state.StackId;
import com.google.inject.Singleton;
import com.google.inject.persist.Transactional;
/**
* The {@link ClusterVersionDAO} class manages the {@link ClusterVersionEntity} instances associated with a cluster.
* Each cluster can have multiple stack versions {@link org.apache.ambari.server.state.RepositoryVersionState#INSTALLED},
* exactly one stack version that is {@link org.apache.ambari.server.state.RepositoryVersionState#CURRENT}, and at most one
* stack version that is {@link org.apache.ambari.server.state.RepositoryVersionState#UPGRADING}.
*/
@Singleton
public class ClusterVersionDAO extends CrudDAO<ClusterVersionEntity, Long>{
/**
* Constructor.
*/
public ClusterVersionDAO() {
super(ClusterVersionEntity.class);
}
/**
* Retrieve all of the cluster versions for the given stack and version.
*
* @param stackName
* the stack name (for example "HDP")
* @param stackVersion
* the stack version (for example "2.2")
* @param version
* Repository version (e.g., 2.2.0.1-995)
* @return Return a list of cluster versions that match the stack and version.
*/
@RequiresSession
public List<ClusterVersionEntity> findByStackAndVersion(String stackName,
String stackVersion, String version) {
final TypedQuery<ClusterVersionEntity> query = entityManagerProvider.get().createNamedQuery("clusterVersionByStackVersion", ClusterVersionEntity.class);
query.setParameter("stackName", stackName);
query.setParameter("stackVersion", stackVersion);
query.setParameter("version", version);
return daoUtils.selectList(query);
}
/**
* Get the cluster version for the given cluster name, stack name, and stack
* version.
*
* @param clusterName
* Cluster name
* @param stackId
* Stack id (e.g., HDP-2.2)
* @param version
* Repository version (e.g., 2.2.0.1-995)
* @return Return all of the cluster versions associated with the given
* cluster.
*/
@RequiresSession
public ClusterVersionEntity findByClusterAndStackAndVersion(
String clusterName, StackId stackId, String version) {
final TypedQuery<ClusterVersionEntity> query = entityManagerProvider.get()
.createNamedQuery("clusterVersionByClusterAndStackAndVersion", ClusterVersionEntity.class);
query.setParameter("clusterName", clusterName);
query.setParameter("stackName", stackId.getStackName());
query.setParameter("stackVersion", stackId.getStackVersion());
query.setParameter("version", version);
return daoUtils.selectSingle(query);
}
/**
* Retrieve all of the cluster versions for the given cluster.
*
* @param clusterName Cluster name
* @return Return all of the cluster versions associated with the given cluster.
*/
@RequiresSession
public List<ClusterVersionEntity> findByCluster(String clusterName) {
final TypedQuery<ClusterVersionEntity> query = entityManagerProvider.get()
.createNamedQuery("clusterVersionByCluster", ClusterVersionEntity.class);
query.setParameter("clusterName", clusterName);
return daoUtils.selectList(query);
}
/**
* Retrieve the single cluster version whose state is {@link org.apache.ambari.server.state.RepositoryVersionState#CURRENT}, of which there should be exactly one at all times
* for the given cluster.
*
* @param clusterName Cluster name
* @return Returns the single cluster version for this cluster whose state is {@link org.apache.ambari.server.state.RepositoryVersionState#CURRENT}, or {@code null} otherwise.
*/
@RequiresSession
public ClusterVersionEntity findByClusterAndStateCurrent(String clusterName) {
final TypedQuery<ClusterVersionEntity> query = entityManagerProvider.get()
.createNamedQuery("clusterVersionByClusterAndState", ClusterVersionEntity.class);
query.setParameter("clusterName", clusterName);
query.setParameter("state", RepositoryVersionState.CURRENT);
try {
List results = query.getResultList();
if (results.isEmpty()) {
return null;
} else {
if (results.size() == 1) {
return (ClusterVersionEntity) results.get(0);
}
}
throw new NonUniqueResultException();
} catch (NoResultException ignored) {
return null;
}
}
/**
* Retrieve all of the cluster versions for the cluster with the given name and a state.
*
* @param clusterName Cluster name
* @param state Cluster version state
* @return Returns a list of cluster versions for the given cluster and a state.
*/
@RequiresSession
public List<ClusterVersionEntity> findByClusterAndState(String clusterName, RepositoryVersionState state) {
final TypedQuery<ClusterVersionEntity> query = entityManagerProvider.get()
.createNamedQuery("clusterVersionByClusterAndState", ClusterVersionEntity.class);
query.setParameter("clusterName", clusterName);
query.setParameter("state", state);
return daoUtils.selectList(query);
}
/**
* Construct a Cluster Version. Additionally this will update parent connection relations without
* forcing refresh of parent entity
* @param entity entity to create
*/
@Override
@Transactional
public void create(ClusterVersionEntity entity) throws IllegalArgumentException {
// check if repository version is not missing, to avoid NPE
if (entity.getRepositoryVersion() == null) {
throw new IllegalArgumentException("RepositoryVersion argument is not set for the entity");
}
super.create(entity);
entity.getRepositoryVersion().updateClusterVersionEntityRelation(entity);
}
/**
* Construct a Cluster Version and return it. This is primarily used to be able to construct the object and mock
* the function call.
* @param cluster Cluster
* @param repositoryVersion Repository Version
* @param state Initial State
* @param startTime Start Time
* @param endTime End Time
* @param userName Username, such as "admin"
* @return Return new ClusterVersion object.
*/
@Transactional
public ClusterVersionEntity create(ClusterEntity cluster, RepositoryVersionEntity repositoryVersion,
RepositoryVersionState state, long startTime, long endTime, String userName) {
ClusterVersionEntity clusterVersionEntity = new ClusterVersionEntity(cluster,
repositoryVersion, state, startTime, endTime, userName);
this.create(clusterVersionEntity);
return clusterVersionEntity;
}
/**
* Updates the cluster version's existing CURRENT record to the INSTALLED, and the target
* becomes CURRENT. This method invokes {@code clear()} on the entity manager to force entities to be refreshed.
* @param clusterId the cluster
* @param target the repo version that will be marked as CURRENT
* @param current the cluster's current record to be marked INSTALLED
*/
@Transactional
public void updateVersions(Long clusterId, RepositoryVersionEntity target, RepositoryVersionEntity current) {
// !!! first update target to be current
StringBuilder sb = new StringBuilder("UPDATE ClusterVersionEntity cve");
sb.append(" SET cve.state = ?1 ");
sb.append(" WHERE cve.clusterId = ?2");
sb.append(" AND cve.repositoryVersion = ?3");
EntityManager em = entityManagerProvider.get();
TypedQuery<Long> query = em.createQuery(sb.toString(), Long.class);
daoUtils.executeUpdate(query, RepositoryVersionState.CURRENT, clusterId, target);
// !!! then move existing current to installed
sb = new StringBuilder("UPDATE ClusterVersionEntity cve");
sb.append(" SET cve.state = ?1 ");
sb.append(" WHERE cve.clusterId = ?2");
sb.append(" AND cve.repositoryVersion = ?3");
sb.append(" AND cve.state = ?4");
query = em.createQuery(sb.toString(), Long.class);
daoUtils.executeUpdate(query, RepositoryVersionState.INSTALLED, clusterId, current,
RepositoryVersionState.CURRENT);
em.clear();
}
}