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

io.druid.indexing.overlord.supervisor.SupervisorManager Maven / Gradle / Ivy

There is a newer version: 0.12.3
Show newest version
/*
 * Licensed to Metamarkets Group Inc. (Metamarkets) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. Metamarkets 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 io.druid.indexing.overlord.supervisor;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.inject.Inject;
import io.druid.java.util.emitter.EmittingLogger;
import io.druid.indexing.overlord.DataSourceMetadata;
import io.druid.java.util.common.Pair;
import io.druid.java.util.common.lifecycle.LifecycleStart;
import io.druid.java.util.common.lifecycle.LifecycleStop;
import io.druid.metadata.MetadataSupervisorManager;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Manages the creation and lifetime of {@link Supervisor}.
 */
public class SupervisorManager
{
  private static final EmittingLogger log = new EmittingLogger(SupervisorManager.class);

  private final MetadataSupervisorManager metadataSupervisorManager;
  private final ConcurrentHashMap> supervisors = new ConcurrentHashMap<>();
  private final Object lock = new Object();

  private volatile boolean started = false;

  @Inject
  public SupervisorManager(MetadataSupervisorManager metadataSupervisorManager)
  {
    this.metadataSupervisorManager = metadataSupervisorManager;
  }

  public Set getSupervisorIds()
  {
    return supervisors.keySet();
  }

  public Optional getSupervisorSpec(String id)
  {
    Pair supervisor = supervisors.get(id);
    return supervisor == null ? Optional.absent() : Optional.fromNullable(supervisor.rhs);
  }

  public boolean createOrUpdateAndStartSupervisor(SupervisorSpec spec)
  {
    Preconditions.checkState(started, "SupervisorManager not started");
    Preconditions.checkNotNull(spec, "spec");
    Preconditions.checkNotNull(spec.getId(), "spec.getId()");

    synchronized (lock) {
      Preconditions.checkState(started, "SupervisorManager not started");
      possiblyStopAndRemoveSupervisorInternal(spec.getId(), false);
      return createAndStartSupervisorInternal(spec, true);
    }
  }

  public boolean stopAndRemoveSupervisor(String id)
  {
    Preconditions.checkState(started, "SupervisorManager not started");
    Preconditions.checkNotNull(id, "id");

    synchronized (lock) {
      Preconditions.checkState(started, "SupervisorManager not started");
      return possiblyStopAndRemoveSupervisorInternal(id, true);
    }
  }

  @LifecycleStart
  public void start()
  {
    Preconditions.checkState(!started, "SupervisorManager already started");
    log.info("Loading stored supervisors from database");

    synchronized (lock) {
      Map supervisors = metadataSupervisorManager.getLatest();
      for (String id : supervisors.keySet()) {
        SupervisorSpec spec = supervisors.get(id);
        if (!(spec instanceof NoopSupervisorSpec)) {
          createAndStartSupervisorInternal(spec, false);
        }
      }

      started = true;
    }
  }

  @LifecycleStop
  public void stop()
  {
    Preconditions.checkState(started, "SupervisorManager not started");

    synchronized (lock) {
      for (String id : supervisors.keySet()) {
        try {
          supervisors.get(id).lhs.stop(false);
        }
        catch (Exception e) {
          log.warn(e, "Caught exception while stopping supervisor [%s]", id);
        }
      }
      supervisors.clear();
      started = false;
    }

    log.info("SupervisorManager stopped.");
  }

  public Map> getSupervisorHistory()
  {
    return metadataSupervisorManager.getAll();
  }

  public Optional getSupervisorStatus(String id)
  {
    Pair supervisor = supervisors.get(id);
    return supervisor == null ? Optional.absent() : Optional.fromNullable(supervisor.lhs.getStatus());
  }

  public boolean resetSupervisor(String id, @Nullable DataSourceMetadata dataSourceMetadata)
  {
    Preconditions.checkState(started, "SupervisorManager not started");
    Preconditions.checkNotNull(id, "id");

    Pair supervisor = supervisors.get(id);

    if (supervisor == null) {
      return false;
    }

    supervisor.lhs.reset(dataSourceMetadata);
    return true;
  }

  public boolean checkPointDataSourceMetadata(
      String supervisorId,
      @Nullable String sequenceName,
      @Nullable DataSourceMetadata previousDataSourceMetadata,
      @Nullable DataSourceMetadata currentDataSourceMetadata
  )
  {
    try {
      Preconditions.checkState(started, "SupervisorManager not started");
      Preconditions.checkNotNull(supervisorId, "supervisorId cannot be null");

      Pair supervisor = supervisors.get(supervisorId);

      Preconditions.checkNotNull(supervisor, "supervisor could not be found");

      supervisor.lhs.checkpoint(sequenceName, previousDataSourceMetadata, currentDataSourceMetadata);
      return true;
    }
    catch (Exception e) {
      log.error(e, "Checkpoint request failed");
    }
    return false;
  }


  /**
   * Stops a supervisor with a given id and then removes it from the list.
   * 

* Caller should have acquired [lock] before invoking this method to avoid contention with other threads that may be * starting and stopping supervisors. * * @return true if a supervisor was stopped, false if there was no supervisor with this id */ private boolean possiblyStopAndRemoveSupervisorInternal(String id, boolean writeTombstone) { Pair pair = supervisors.get(id); if (pair == null) { return false; } if (writeTombstone) { metadataSupervisorManager.insert(id, new NoopSupervisorSpec()); // where NoopSupervisorSpec is a tombstone } pair.lhs.stop(true); supervisors.remove(id); return true; } /** * Creates a supervisor from the provided spec and starts it if there is not already a supervisor with that id. *

* Caller should have acquired [lock] before invoking this method to avoid contention with other threads that may be * starting and stopping supervisors. * * @return true if a new supervisor was created, false if there was already an existing supervisor with this id */ private boolean createAndStartSupervisorInternal(SupervisorSpec spec, boolean persistSpec) { String id = spec.getId(); if (supervisors.containsKey(id)) { return false; } if (persistSpec) { metadataSupervisorManager.insert(id, spec); } Supervisor supervisor = null; try { supervisor = spec.createSupervisor(); supervisor.start(); } catch (Exception e) { // Supervisor creation or start failed write tombstone only when trying to start a new supervisor if (persistSpec) { metadataSupervisorManager.insert(id, new NoopSupervisorSpec()); } Throwables.propagate(e); } supervisors.put(id, Pair.of(supervisor, spec)); return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy