All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hubspot.singularity.data.AbstractMachineManager Maven / Gradle / Ivy

There is a newer version: 1.5.0
Show newest version
package com.hubspot.singularity.data;

import java.util.List;
import java.util.Map;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.utils.ZKPaths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.codahale.metrics.MetricRegistry;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hubspot.singularity.MachineState;
import com.hubspot.singularity.SingularityCreateResult;
import com.hubspot.singularity.SingularityDeleteResult;
import com.hubspot.singularity.SingularityMachineAbstraction;
import com.hubspot.singularity.SingularityMachineStateHistoryUpdate;
import com.hubspot.singularity.config.SingularityConfiguration;
import com.hubspot.singularity.data.transcoders.Transcoder;

public abstract class AbstractMachineManager> extends CuratorAsyncManager {

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

  private static final String HISTORY_PATH = "history";

  private final Transcoder transcoder;
  private final Transcoder historyTranscoder;

  public AbstractMachineManager(CuratorFramework curator, SingularityConfiguration configuration, MetricRegistry metricRegistry, Transcoder transcoder,
      Transcoder historyTranscoder) {
    super(curator, configuration, metricRegistry);

    this.transcoder = transcoder;
    this.historyTranscoder = historyTranscoder;
  }

  protected abstract String getRoot();

  private String getHistoryPath(String objectId) {
    return ZKPaths.makePath(getObjectPath(objectId), HISTORY_PATH);
  }

  public List getHistory(String objectId) {
    return getAsyncChildren(getHistoryPath(objectId), historyTranscoder);
  }

  public List getObjects() {
    return getObjects(getRoot());
  }

  public int getNumObjectsAtState(MachineState state) {
    return getObjectsFiltered(state).size();
  }

  public Map getObjectsByIdForState(MachineState state) {
    List filteredObjects = getObjectsFiltered(state);

    Map filteredObjectIds = Maps.newHashMapWithExpectedSize(filteredObjects.size());

    for (T filteredObject : filteredObjects) {
      filteredObjectIds.put(filteredObject.getId(), filteredObject);
    }

    return filteredObjectIds;
  }

  public List getObjectsFiltered(MachineState state) {
    return getObjectsFiltered(Optional.of(state));
  }

  public List getObjectsFiltered(Optional state) {
    List objects = getObjects();

    if (!state.isPresent()) {
      return objects;
    }

    return getObjectsFiltered(objects, state.get());
  }

  private List getObjectsFiltered(List objects, MachineState state) {
    List filtered = Lists.newArrayListWithCapacity(objects.size());

    for (T object : objects) {
      if (object.getCurrentState().getState() == state) {
        filtered.add(object);
      }
    }

    return filtered;
  }

  private String getObjectPath(String objectId) {
    return ZKPaths.makePath(getRoot(), objectId);
  }

  public Optional getObject(String objectId) {
    return getData(getObjectPath(objectId), transcoder);
  }

  protected List getObjects(String root) {
    return getAsyncChildren(root, transcoder);
  }

  public SingularityDeleteResult removed(String objectId) {
    return delete(getObjectPath(objectId));
  }

  public enum StateChangeResult {
    FAILURE_NOT_FOUND, FAILURE_ALREADY_AT_STATE, FAILURE_ILLEGAL_TRANSITION, SUCCESS;
  }

  public StateChangeResult changeState(String objectId, MachineState newState, Optional message, Optional user) {
    Optional maybeObject = getObject(objectId);

    if (!maybeObject.isPresent()) {
      return StateChangeResult.FAILURE_NOT_FOUND;
    }

    final T object = maybeObject.get();

    return changeState(object, newState, message, user);
  }

  public StateChangeResult changeState(T object, MachineState newState, Optional message, Optional user) {
    if (object.getCurrentState().getState() == newState) {
      return StateChangeResult.FAILURE_ALREADY_AT_STATE;
    }

    if (newState == MachineState.STARTING_DECOMMISSION && object.getCurrentState().getState().isDecommissioning()) {
      return StateChangeResult.FAILURE_ILLEGAL_TRANSITION;
    }

    // can't jump from FROZEN to DECOMMISSIONING or DECOMMISSIONED
    if (((newState == MachineState.DECOMMISSIONING) || (newState == MachineState.DECOMMISSIONED)) && (object.getCurrentState().getState() == MachineState.FROZEN)) {
      return StateChangeResult.FAILURE_ILLEGAL_TRANSITION;
    }

    // can't jump from a decommissioning state to FROZEN
    if ((newState == MachineState.FROZEN) && object.getCurrentState().getState().isDecommissioning()) {
      return StateChangeResult.FAILURE_ILLEGAL_TRANSITION;
    }

    SingularityMachineStateHistoryUpdate newStateUpdate = new SingularityMachineStateHistoryUpdate(object.getId(), newState, System.currentTimeMillis(), user, message);

    LOG.debug("{} changing state from {} to {} by {}", object.getId(), object.getCurrentState().getState(), newState, user);

    saveObject(object.changeState(newStateUpdate));

    return StateChangeResult.SUCCESS;
  }

  private String getHistoryUpdatePath(SingularityMachineStateHistoryUpdate historyUpdate) {
    final String historyChildPath = String.format("%s-%s", historyUpdate.getState().name(), historyUpdate.getTimestamp());

    return ZKPaths.makePath(getHistoryPath(historyUpdate.getObjectId()), historyChildPath);
  }

  private SingularityCreateResult saveHistoryUpdate(SingularityMachineStateHistoryUpdate historyUpdate) {
    return create(getHistoryUpdatePath(historyUpdate), historyUpdate, historyTranscoder);
  }

  public SingularityDeleteResult deleteObject(String objectId) {
    return delete(getObjectPath(objectId));
  }

  public SingularityCreateResult saveObject(T object) {
    saveHistoryUpdate(object.getCurrentState());

    return save(getObjectPath(object.getId()), object, transcoder);
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy