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

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

package com.hubspot.singularity.data;

import java.util.List;

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

import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.hubspot.singularity.SingularityCreateResult;
import com.hubspot.singularity.SingularityDeleteResult;
import com.hubspot.singularity.SingularityMachineAbstraction;
import com.hubspot.singularity.SingularityMachineAbstraction.SingularityMachineState;
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 ACTIVE_PATH = "active";
  private static final String DECOMISSIONING_PATH = "decomissioning";
  private static final String DEAD_PATH = "dead";

  private final Transcoder transcoder;

  public AbstractMachineManager(CuratorFramework curator, long zkAsyncTimeout, Transcoder transcoder) {
    super(curator, zkAsyncTimeout);

    this.transcoder = transcoder;
  }

  public abstract String getRoot();

  protected String getActiveRoot() {
    return ZKPaths.makePath(getRoot(), ACTIVE_PATH);
  }

  protected String getActivePath(String objectId) {
    return ZKPaths.makePath(getActiveRoot(), objectId);
  }

  protected String getDeadRoot() {
    return ZKPaths.makePath(getRoot(), DEAD_PATH);
  }

  protected String getDeadPath(String objectId) {
    return ZKPaths.makePath(getDeadRoot(), objectId);
  }

  protected String getDecomissioningRoot() {
    return ZKPaths.makePath(getRoot(), DECOMISSIONING_PATH);
  }

  protected String getDecomissioningPath(String objectId) {
    return ZKPaths.makePath(getDecomissioningRoot(), objectId);
  }

  public List getActiveObjects() {
    return getObjects(getActiveRoot());
  }

  public List getDeadObjects() {
    return getObjects(getDeadRoot());
  }

  public List getDecomissioningObjects() {
    return getObjects(getDecomissioningRoot());
  }

  public List getDecomissioningObjectsFiltered(List decomissioning) {
    List filtered = Lists.newArrayListWithCapacity(decomissioning.size());

    for (T object : decomissioning) {
      if (object.getState() == SingularityMachineState.DECOMISSIONING) {
        filtered.add(object);
      }
    }

    return filtered;
  }

  private Optional getObject(String path) {
    return getData(path, transcoder);
  }

  public Optional getActiveObject(String objectId) {
    return getObject(getActivePath(objectId));
  }

  public Optional getDeadObject(String objectId) {
    return getObject(getDeadPath(objectId));
  }

  public Optional getDecomissioning(String objectId) {
    return getObject(getDecomissioningPath(objectId));
  }

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

  public List getActive() {
    return getChildren(getActiveRoot());
  }

  public List getDecomissioning() {
    return getChildren(getDecomissioningRoot());
  }

  public List getDead() {
    return getChildren(getDeadRoot());
  }

  public int getNumActive() {
    return getNumChildren(getActiveRoot());
  }

  public int getNumDecomissioning() {
    return getNumChildren(getDecomissioningRoot());
  }

  public int getNumDead() {
    return getNumChildren(getDeadRoot());
  }

  public void markAsDead(String objectId) {
    Optional objectHolder = getActiveObject(objectId);

    if (!objectHolder.isPresent()) {
      LOG.warn(String.format("Marking an object %s as dead - but it wasn't active", objectId));
      return;
    }

    if (delete(getActivePath(objectId)) != SingularityDeleteResult.DELETED) {
      LOG.warn(String.format("Deleting active object at %s failed", getActivePath(objectId)));
    }

    T object = objectHolder.get();

    object.setState(SingularityMachineState.DEAD);
    object.setDeadAt(Optional.of(System.currentTimeMillis()));

    if (create(getDeadPath(objectId), Optional.of(transcoder.toBytes(object))) != SingularityCreateResult.CREATED) {
      LOG.warn(String.format("Creating dead object at %s failed", getDeadPath(objectId)));
    }
  }

  private void mark(T object, String path, SingularityMachineState state) {
    object.setState(state);

    final byte[] data = transcoder.toBytes(object);

    try {
      curator.setData().forPath(path, data);
    } catch (NoNodeException nne) {
      LOG.warn(String.format("Unexpected no node exception while storing decomissioned state for %s on path %s", object, path));
    } catch (Exception e) {
      throw Throwables.propagate(e);
    }
  }

  public void markAsDecomissioned(T object) {
    object.setDecomissionedAt(Optional.of(System.currentTimeMillis()));
    mark(object, getDecomissioningPath(object.getId()), SingularityMachineState.DECOMISSIONED);
  }

  public SingularityDeleteResult removeDecomissioning(String objectId) {
    return delete(getDecomissioningPath(objectId));
  }

  public SingularityDeleteResult removeDead(String objectId) {
    return delete(getDeadPath(objectId));
  }

  public enum DecomissionResult {
    SUCCESS_DECOMISSIONING, FAILURE_NOT_FOUND, FAILURE_ALREADY_DECOMISSIONING, FAILURE_DEAD;
  }

  public DecomissionResult decomission(String objectId, Optional user) {
    Optional objectHolder = getActiveObject(objectId);

    if (!objectHolder.isPresent()) {
      if (isDecomissioning(objectId)) {
        return DecomissionResult.FAILURE_ALREADY_DECOMISSIONING;
      } else if (isDead(objectId)) {
        return DecomissionResult.FAILURE_DEAD;
      }
      return DecomissionResult.FAILURE_NOT_FOUND;
    }

    final T object = objectHolder.get();

    object.setState(SingularityMachineState.DECOMISSIONING);
    object.setDecomissioningAt(Optional.of(System.currentTimeMillis()));
    object.setDecomissioningBy(user);

    create(getDecomissioningPath(objectId), Optional.of(transcoder.toBytes(object)));

    delete(getActivePath(objectId));

    return DecomissionResult.SUCCESS_DECOMISSIONING;
  }

  public boolean isActive(String objectId) {
    return exists(getActivePath(objectId));
  }

  public boolean isDead(String objectId) {
    return exists(getDeadPath(objectId));
  }

  public boolean isDecomissioning(String objectId) {
    return exists(getDecomissioningPath(objectId));
  }

  public int clearActive() {
    int numCleared = 0;

    for (String active : getActive()) {
      numCleared += 1;
      delete(getActivePath(active));
    }

    return numCleared;
  }

  public SingularityCreateResult save(T object) {
    return create(getActivePath(object.getId()), Optional.of(transcoder.toBytes(object)));
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy