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.resourcemanager; 020 021import org.apache.reef.annotations.audience.DriverSide; 022import org.apache.reef.annotations.audience.Private; 023import org.apache.reef.proto.ReefServiceProtos; 024import org.apache.reef.runtime.common.driver.DriverStatusManager; 025import org.apache.reef.runtime.common.driver.idle.DriverIdleManager; 026import org.apache.reef.runtime.common.driver.idle.DriverIdlenessSource; 027import org.apache.reef.runtime.common.driver.idle.IdleMessage; 028import org.apache.reef.tang.InjectionFuture; 029import org.apache.reef.wake.EventHandler; 030 031import javax.inject.Inject; 032import java.util.logging.Level; 033import java.util.logging.Logger; 034 035/** 036 * Manages the status of the Resource Manager. 037 */ 038@DriverSide 039@Private 040public final class ResourceManagerStatus implements EventHandler<RuntimeStatusEvent>, 041 DriverIdlenessSource { 042 private static final Logger LOG = Logger.getLogger(ResourceManagerStatus.class.getName()); 043 044 private static final String COMPONENT_NAME = "ResourceManager"; 045 private static final IdleMessage IDLE_MESSAGE = new IdleMessage(COMPONENT_NAME, "No outstanding requests or allocations", true); 046 047 private final ResourceManagerErrorHandler resourceManagerErrorHandler; 048 private final DriverStatusManager driverStatusManager; 049 private final InjectionFuture<DriverIdleManager> driverIdleManager; 050 051 // Mutable state. 052 private ReefServiceProtos.State state = ReefServiceProtos.State.INIT; 053 private int outstandingContainerRequests = 0; 054 private int containerAllocationCount = 0; 055 056 @Inject 057 ResourceManagerStatus(final ResourceManagerErrorHandler resourceManagerErrorHandler, 058 final DriverStatusManager driverStatusManager, 059 final InjectionFuture<DriverIdleManager> driverIdleManager) { 060 this.resourceManagerErrorHandler = resourceManagerErrorHandler; 061 this.driverStatusManager = driverStatusManager; 062 this.driverIdleManager = driverIdleManager; 063 } 064 065 @Override 066 public synchronized void onNext(final RuntimeStatusEvent runtimeStatusEvent) { 067 final ReefServiceProtos.State newState = runtimeStatusEvent.getState(); 068 LOG.log(Level.FINEST, "Runtime status " + runtimeStatusEvent); 069 this.outstandingContainerRequests = runtimeStatusEvent.getOutstandingContainerRequests().get(); 070 this.containerAllocationCount = runtimeStatusEvent.getContainerAllocationList().size(); 071 this.setState(runtimeStatusEvent.getState()); 072 073 switch (newState) { 074 case FAILED: 075 this.onRMFailure(runtimeStatusEvent); 076 break; 077 case DONE: 078 this.onRMDone(runtimeStatusEvent); 079 break; 080 case RUNNING: 081 this.onRMRunning(runtimeStatusEvent); 082 break; 083 } 084 } 085 086 /** 087 * Change the state of the Resource Manager to be RUNNING. 088 */ 089 public synchronized void setRunning() { 090 this.setState(ReefServiceProtos.State.RUNNING); 091 } 092 093 /** 094 * @return idle, if there are no outstanding requests or allocations. Not idle else. 095 */ 096 @Override 097 public synchronized IdleMessage getIdleStatus() { 098 if (this.isIdle()) { 099 return IDLE_MESSAGE; 100 } else { 101 final String message = new StringBuilder("There are ") 102 .append(this.outstandingContainerRequests) 103 .append(" outstanding container requests and ") 104 .append(this.containerAllocationCount) 105 .append(" allocated containers") 106 .toString(); 107 return new IdleMessage(COMPONENT_NAME, message, false); 108 } 109 } 110 111 112 private synchronized void onRMFailure(final RuntimeStatusEvent runtimeStatusEvent) { 113 assert (runtimeStatusEvent.getState() == ReefServiceProtos.State.FAILED); 114 this.resourceManagerErrorHandler.onNext(runtimeStatusEvent.getError().get()); 115 } 116 117 private synchronized void onRMDone(final RuntimeStatusEvent runtimeStatusEvent) { 118 assert (runtimeStatusEvent.getState() == ReefServiceProtos.State.DONE); 119 LOG.log(Level.INFO, "Resource Manager shutdown happened. Triggering Driver shutdown."); 120 this.driverStatusManager.onComplete(); 121 } 122 123 private synchronized void onRMRunning(final RuntimeStatusEvent runtimeStatusEvent) { 124 assert (runtimeStatusEvent.getState() == ReefServiceProtos.State.RUNNING); 125 if (this.isIdle()) { 126 this.driverIdleManager.get().onPotentiallyIdle(IDLE_MESSAGE); 127 } 128 } 129 130 131 private synchronized boolean isIdle() { 132 return this.hasNoOutstandingRequests() 133 && this.hasNoContainersAllocated(); 134 } 135 136 private synchronized boolean isRunning() { 137 return ReefServiceProtos.State.RUNNING.equals(this.state); 138 } 139 140 141 private synchronized void setState(ReefServiceProtos.State state) { 142 // TODO: Add state transition check 143 this.state = state; 144 } 145 146 147 private synchronized boolean hasNoOutstandingRequests() { 148 return this.outstandingContainerRequests == 0; 149 } 150 151 private synchronized boolean hasNoContainersAllocated() { 152 return this.containerAllocationCount == 0; 153 } 154 155}