001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.reef.runtime.common.driver.idle;
020
021import org.apache.reef.driver.parameters.DriverIdleSources;
022import org.apache.reef.runtime.common.driver.DriverStatusManager;
023import org.apache.reef.tang.InjectionFuture;
024import org.apache.reef.tang.annotations.Parameter;
025
026import javax.inject.Inject;
027import java.util.Set;
028import java.util.logging.Level;
029import java.util.logging.Logger;
030
031/**
032 * Handles the various sources for driver idleness and forwards decisions to DriverStatusManager.
033 */
034public final class DriverIdleManager {
035
036  private static final Logger LOG = Logger.getLogger(DriverIdleManager.class.getName());
037  private static final Level IDLE_REASONS_LEVEL = Level.FINEST;
038
039  private final Set<DriverIdlenessSource> idlenessSources;
040  private final InjectionFuture<DriverStatusManager> driverStatusManager;
041
042  @Inject
043  private DriverIdleManager(
044      @Parameter(DriverIdleSources.class) final Set<DriverIdlenessSource> idlenessSources,
045      final InjectionFuture<DriverStatusManager> driverStatusManager) {
046
047    this.idlenessSources = idlenessSources;
048    this.driverStatusManager = driverStatusManager;
049  }
050
051  /**
052   * Check whether all Driver components are idle, and initiate driver shutdown if they are.
053   * @param reason An indication whether the component is idle, along with a descriptive message.
054   */
055  public synchronized void onPotentiallyIdle(final IdleMessage reason) {
056
057    final DriverStatusManager driverStatusManagerImpl = this.driverStatusManager.get();
058
059    if (driverStatusManagerImpl.isClosing()) {
060      LOG.log(IDLE_REASONS_LEVEL, "Ignoring idle call from [{0}] for reason [{1}]",
061          new Object[] {reason.getComponentName(), reason.getReason()});
062      return;
063    }
064
065    LOG.log(IDLE_REASONS_LEVEL, "Checking for idle because {0} reported idleness for reason [{1}]",
066        new Object[] {reason.getComponentName(), reason.getReason()});
067
068    boolean isIdle = true;
069    for (final DriverIdlenessSource idlenessSource : this.idlenessSources) {
070
071      final IdleMessage idleMessage = idlenessSource.getIdleStatus();
072
073      LOG.log(IDLE_REASONS_LEVEL, "[{0}] is reporting {1} because [{2}].",
074          new Object[] {idleMessage.getComponentName(),
075              idleMessage.isIdle() ? "idle" : "not idle", idleMessage.getReason()});
076
077      isIdle &= idleMessage.isIdle();
078    }
079
080    LOG.log(IDLE_REASONS_LEVEL, "onPotentiallyIdle: isIdle: " + isIdle);
081
082    if (isIdle) {
083      LOG.log(Level.INFO, "All components indicated idle. Initiating Driver shutdown.");
084      driverStatusManagerImpl.onComplete();
085    }
086  }
087}