Package org.apache.ambari.server.state

Source Code of org.apache.ambari.server.state.ServiceImpl

/**
* 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.state;

import java.util.*;
import java.util.Map.Entry;

import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.ServiceComponentNotFoundException;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.controller.ServiceResponse;
import org.apache.ambari.server.orm.dao.*;
import org.apache.ambari.server.orm.entities.*;
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 ServiceImpl implements Service {

  private ClusterServiceEntity serviceEntity;
  private ServiceDesiredStateEntity serviceDesiredStateEntity;

  private static final Logger LOG =
      LoggerFactory.getLogger(ServiceImpl.class);

  private boolean persisted = false;
  private final Cluster cluster;
  // [ String type -> Config Tag ], no need to hold the direct reference to the config
  private Map<String, String> desiredConfigs;
  private Map<String, ServiceComponent> components;
  private final boolean isClientOnlyService;

  @Inject
  Gson gson;
  @Inject
  private ClusterServiceDAO clusterServiceDAO;
  @Inject
  private Clusters clusters;
  @Inject
  private ServiceDesiredStateDAO serviceDesiredStateDAO;
  @Inject
  private ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO;
  @Inject
  private ClusterDAO clusterDAO;
  @Inject
  private ServiceConfigMappingDAO serviceConfigMappingDAO;
  @Inject
  private ServiceComponentFactory serviceComponentFactory;
  @Inject
  private AmbariMetaInfo ambariMetaInfo;

  private void init() {
    // TODO load from DB during restart?
  }

  @AssistedInject
  public ServiceImpl(@Assisted Cluster cluster, @Assisted String serviceName,
      Injector injector) throws AmbariException {
    injector.injectMembers(this);
    serviceEntity = new ClusterServiceEntity();
    serviceEntity.setServiceName(serviceName);
    serviceDesiredStateEntity = new ServiceDesiredStateEntity();

    serviceDesiredStateEntity.setClusterServiceEntity(serviceEntity);
    serviceEntity.setServiceDesiredStateEntity(serviceDesiredStateEntity);

    this.cluster = cluster;
    this.desiredConfigs = new HashMap<String, String>();

    this.components = new HashMap<String, ServiceComponent>();

    StackId stackId = cluster.getDesiredStackVersion();
    setDesiredStackVersion(stackId);

    ServiceInfo sInfo = ambariMetaInfo.getServiceInfo(stackId.getStackName(),
        stackId.getStackVersion(), serviceName);
    this.isClientOnlyService = sInfo.isClientOnlyService();

    init();
  }

  @AssistedInject
  public ServiceImpl(@Assisted Cluster cluster, @Assisted ClusterServiceEntity
      serviceEntity, Injector injector) throws AmbariException {
    injector.injectMembers(this);
    this.serviceEntity = serviceEntity;
    this.cluster = cluster;

    //TODO check for null states?
    this.serviceDesiredStateEntity = serviceEntity.getServiceDesiredStateEntity();

    this.desiredConfigs = new HashMap<String, String>();

    this.components = new HashMap<String, ServiceComponent>();

    if (!serviceEntity.getServiceComponentDesiredStateEntities().isEmpty()) {
      for (ServiceComponentDesiredStateEntity serviceComponentDesiredStateEntity
          : serviceEntity.getServiceComponentDesiredStateEntities()) {
        components.put(serviceComponentDesiredStateEntity.getComponentName(),
            serviceComponentFactory.createExisting(this,
                serviceComponentDesiredStateEntity));
      }
    }

    for (ServiceConfigMappingEntity mappingEntity :
        serviceEntity.getServiceConfigMappings()) {
      desiredConfigs.put(mappingEntity.getConfigType(),
          mappingEntity.getVersionTag());
    }

    StackId stackId = getDesiredStackVersion();
    ServiceInfo sInfo = ambariMetaInfo.getServiceInfo(stackId.getStackName(),
        stackId.getStackVersion(), getName());
    this.isClientOnlyService = sInfo.isClientOnlyService();

    persisted = true;
  }

  @Override
  public String getName() {
      return serviceEntity.getServiceName();
  }

  @Override
  public long getClusterId() {
    return cluster.getClusterId();
  }

  @Override
  public synchronized Map<String, ServiceComponent> getServiceComponents() {
    return Collections.unmodifiableMap(components);
  }

  @Override
  public synchronized void addServiceComponents(
      Map<String, ServiceComponent> components) throws AmbariException {
    for (ServiceComponent sc : components.values()) {
      addServiceComponent(sc);
    }
  }

  @Override
  public synchronized void addServiceComponent(ServiceComponent component)
      throws AmbariException {
    // TODO validation
    if (LOG.isDebugEnabled()) {
      LOG.debug("Adding a ServiceComponent to Service"
          + ", clusterName=" + cluster.getClusterName()
          + ", clusterId=" + cluster.getClusterId()
          + ", serviceName=" + getName()
          + ", serviceComponentName=" + component.getName());
    }
    if (components.containsKey(component.getName())) {
      throw new AmbariException("Cannot add duplicate ServiceComponent"
          + ", clusterName=" + cluster.getClusterName()
          + ", clusterId=" + cluster.getClusterId()
          + ", serviceName=" + getName()
          + ", serviceComponentName=" + component.getName());
    }
    this.components.put(component.getName(), component);
  }

  @Override
  public synchronized ServiceComponent addServiceComponent(
      String serviceComponentName) throws AmbariException {
    if (LOG.isDebugEnabled()) {
      LOG.debug("Adding a ServiceComponent to Service"
          + ", clusterName=" + cluster.getClusterName()
          + ", clusterId=" + cluster.getClusterId()
          + ", serviceName=" + getName()
          + ", serviceComponentName=" + serviceComponentName);
    }
    if (components.containsKey(serviceComponentName)) {
      throw new AmbariException("Cannot add duplicate ServiceComponent"
          + ", clusterName=" + cluster.getClusterName()
          + ", clusterId=" + cluster.getClusterId()
          + ", serviceName=" + getName()
          + ", serviceComponentName=" + serviceComponentName);
    }
    ServiceComponent component = serviceComponentFactory.createNew(this, serviceComponentName);
    this.components.put(component.getName(), component);
    return component;
  }

  @Override
  public ServiceComponent getServiceComponent(String componentName)
      throws AmbariException {
    if (!components.containsKey(componentName)) {
      throw new ServiceComponentNotFoundException(cluster.getClusterName(),
          getName(),
          componentName);
    }
    return this.components.get(componentName);
  }

  @Override
  public synchronized State getDesiredState() {
    return this.serviceDesiredStateEntity.getDesiredState();
  }

  @Override
  public synchronized void setDesiredState(State state) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("Setting DesiredState of Service"
          + ", clusterName=" + cluster.getClusterName()
          + ", clusterId=" + cluster.getClusterId()
          + ", serviceName=" + getName()
          + ", oldDesiredState=" + this.getDesiredState()
          + ", newDesiredState=" + state);
    }
    this.serviceDesiredStateEntity.setDesiredState(state);
    saveIfPersisted();
  }

  @Override
  public synchronized Map<String, Config> getDesiredConfigs() {
    Map<String, Config> map = new HashMap<String, Config>();
    for (Entry<String, String> entry : desiredConfigs.entrySet()) {
      Config config = cluster.getConfig(entry.getKey(), entry.getValue());
      if (null != config) {
        map.put(entry.getKey(), config);
      } else {
        // FIXME this is an error - should throw a proper exception
        throw new RuntimeException("Found an invalid config"
            + ", clusterName=" + getCluster().getClusterName()
            + ", serviceName=" + getName()
            + ", configType=" + entry.getKey()
            + ", configVersionTag=" + entry.getValue());
      }
    }
    return Collections.unmodifiableMap(map);
  }

  @Override
  public synchronized void updateDesiredConfigs(Map<String, Config> configs) {

    for (Entry<String,Config> entry : configs.entrySet()) {
      boolean contains = false;

      for (ServiceConfigMappingEntity serviceConfigMappingEntity : serviceEntity.getServiceConfigMappings()) {
        if (entry.getKey().equals(serviceConfigMappingEntity.getConfigType())) {
          contains = true;
          serviceConfigMappingEntity.setTimestamp(new Date().getTime());
          serviceConfigMappingEntity.setVersionTag(entry.getValue().getVersionTag());
        }
      }

      if (!contains) {
        ServiceConfigMappingEntity newEntity = new ServiceConfigMappingEntity();
        newEntity.setClusterId(serviceEntity.getClusterId());
        newEntity.setServiceName(serviceEntity.getServiceName());
        newEntity.setConfigType(entry.getKey());
        newEntity.setVersionTag(entry.getValue().getVersionTag());
        newEntity.setTimestamp(new Date().getTime());
        newEntity.setServiceEntity(serviceEntity);
        serviceEntity.getServiceConfigMappings().add(newEntity);

      }


      this.desiredConfigs.put(entry.getKey(), entry.getValue().getVersionTag());
    }

    saveIfPersisted();

  }

  @Override
  public synchronized StackId getDesiredStackVersion() {
    return gson.fromJson(serviceDesiredStateEntity.getDesiredStackVersion(), StackId.class);
  }

  @Override
  public synchronized void setDesiredStackVersion(StackId stackVersion) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("Setting DesiredStackVersion of Service"
          + ", clusterName=" + cluster.getClusterName()
          + ", clusterId=" + cluster.getClusterId()
          + ", serviceName=" + getName()
          + ", oldDesiredStackVersion=" + getDesiredStackVersion()
          + ", newDesiredStackVersion=" + stackVersion);
    }
    serviceDesiredStateEntity.setDesiredStackVersion(gson.toJson(stackVersion));
    saveIfPersisted();
  }

  @Override
  public synchronized ServiceResponse convertToResponse() {
    ServiceResponse r = new ServiceResponse(cluster.getClusterId(),
        cluster.getClusterName(),
        getName(),
        desiredConfigs,
        getDesiredStackVersion().getStackId(),
        getDesiredState().toString());
    return r;
  }

  @Override
  public Cluster getCluster() {
    return cluster;
  }

  @Override
  public synchronized void debugDump(StringBuilder sb) {
    sb.append("Service={ serviceName=" + getName()
        + ", clusterName=" + cluster.getClusterName()
        + ", clusterId=" + cluster.getClusterId()
        + ", desiredStackVersion=" + getDesiredStackVersion()
        + ", desiredState=" + getDesiredState().toString()
        + ", configs=[");
    boolean first = true;
    if (desiredConfigs != null) {
      for (Entry<String, String> entry : desiredConfigs.entrySet()) {
        if (!first) {
          sb.append(" , ");
        }
        first = false;
        sb.append("{ Config type=" + entry.getKey()
            + ", versionTag=" + entry.getValue() + "}");
      }
    }
    sb.append("], components=[ ");

    first = true;
    for(ServiceComponent sc : components.values()) {
      if (!first) {
        sb.append(" , ");
      }
      first = false;
      sb.append("\n      ");
      sc.debugDump(sb);
      sb.append(" ");
    }
    sb.append(" ] }");
  }

  @Override
  public synchronized boolean isPersisted() {
      return persisted;
  }

  @Override
  public synchronized void persist() {
    if (!persisted) {
      persistEntities();
      refresh();
      cluster.refresh();
      persisted = true;
    } else {
      saveIfPersisted();
    }
  }

  @Transactional
  protected void persistEntities() {
    ClusterEntity clusterEntity = clusterDAO.findById(cluster.getClusterId());
    serviceEntity.setClusterEntity(clusterEntity);
    clusterServiceDAO.create(serviceEntity);
    serviceDesiredStateDAO.create(serviceDesiredStateEntity);
    clusterEntity.getClusterServiceEntities().add(serviceEntity);
    clusterDAO.merge(clusterEntity);
//    serviceEntity =
        clusterServiceDAO.merge(serviceEntity);
//    serviceDesiredStateEntity =
        serviceDesiredStateDAO.merge(serviceDesiredStateEntity);
  }

  @Transactional
  private void saveIfPersisted() {
    if (isPersisted()) {
      clusterServiceDAO.merge(serviceEntity);
      serviceDesiredStateDAO.merge(serviceDesiredStateEntity);
    }
  }

  @Override
  @Transactional
  public synchronized void refresh() {
    if (isPersisted()) {
      ClusterServiceEntityPK pk = new ClusterServiceEntityPK();
      pk.setClusterId(getClusterId());
      pk.setServiceName(getName());
      serviceEntity = clusterServiceDAO.findByPK(pk);
      serviceDesiredStateEntity = serviceEntity.getServiceDesiredStateEntity();
      clusterServiceDAO.refresh(serviceEntity);
      serviceDesiredStateDAO.refresh(serviceDesiredStateEntity);
    }
  }

  @Override
  public synchronized boolean canBeRemoved() {
    if (!getDesiredState().isRemovableState()) {
      return false;
    }

    for (ServiceComponent sc : components.values()) {
      if (!sc.canBeRemoved()) {
        LOG.warn("Found non removable component when trying to delete service"
            + ", clusterName=" + cluster.getClusterName()
            + ", serviceName=" + getName()
            + ", componentName=" + sc.getName());
        return false;
      }
    }
    return true;
  }

  @Override
  @Transactional
  public synchronized void deleteAllComponents() throws AmbariException {
    LOG.info("Deleting all components for service"
        + ", clusterName=" + cluster.getClusterName()
        + ", serviceName=" + getName());
    // FIXME check dependencies from meta layer
    for (ServiceComponent component : components.values()) {
      if (!component.canBeRemoved()) {
        throw new AmbariException("Found non removable component when trying to"
            + " delete all components from service"
            + ", clusterName=" + cluster.getClusterName()
            + ", serviceName=" + getName()
            + ", componentName=" + component.getName());
      }
    }

    for (ServiceComponent serviceComponent : components.values()) {
      serviceComponent.delete();
    }

    components.clear();
  }

  @Override
  public synchronized void deleteServiceComponent(String componentName)
      throws AmbariException {
    ServiceComponent component = getServiceComponent(componentName);
    LOG.info("Deleting servicecomponent for cluster"
        + ", clusterName=" + cluster.getClusterName()
        + ", serviceName=" + getName()
        + ", componentName=" + componentName);
    // FIXME check dependencies from meta layer
    if (!component.canBeRemoved()) {
      throw new AmbariException("Could not delete component from cluster"
          + ", clusterName=" + cluster.getClusterName()
          + ", serviceName=" + getName()
          + ", componentName=" + componentName);
    }

    component.delete();
    components.remove(componentName);
  }

  @Override
  public boolean isClientOnlyService() {
    return isClientOnlyService;
  }

  @Override
  @Transactional
  public synchronized void delete() throws AmbariException {
    deleteAllComponents();

    if (persisted) {
      removeEntities();
      persisted = false;
    }

    desiredConfigs.clear();
  }

  @Transactional
  protected void removeEntities() throws AmbariException {
    ClusterServiceEntityPK pk = new ClusterServiceEntityPK();
    pk.setClusterId(getClusterId());
    pk.setServiceName(getName());

    clusterServiceDAO.removeByPK(pk);
  }

}
TOP

Related Classes of org.apache.ambari.server.state.ServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.