/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 org.apache.hadoop.yarn.server.resourcemanager.registry;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.registry.server.integration.RMRegistryOperationsService;
import org.apache.hadoop.service.CompositeService;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.event.EventHandler;
import org.apache.hadoop.yarn.server.resourcemanager.RMAppManagerEvent;
import org.apache.hadoop.yarn.server.resourcemanager.RMAppManagerEventType;
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
import org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStoreAppEvent;
import org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStoreEvent;
import org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStoreEventType;
import org.apache.hadoop.yarn.server.resourcemanager.recovery.records.ApplicationStateData;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptEvent;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptEventType;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.event.RMAppAttemptContainerFinishedEvent;
import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainerEvent;
import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainerEventType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/**
* This is the RM service which translates from RM events
* to registry actions
*/
@InterfaceAudience.Private
@InterfaceStability.Evolving
public class RMRegistryService extends CompositeService {
private static final Logger LOG =
LoggerFactory.getLogger(RMRegistryService.class);
private final RMContext rmContext;
/**
* Registry service
*/
private final RMRegistryOperationsService registryOperations;
public RMRegistryService(RMContext rmContext) {
super(RMRegistryService.class.getName());
this.rmContext = rmContext;
registryOperations =
new RMRegistryOperationsService("Registry");
addService(registryOperations);
}
public void setKerberosPrincipalAndKeytab(String principal, String keytab) {
registryOperations.setKerberosPrincipalAndKeytab(principal, keytab);
}
@Override
protected void serviceStart() throws Exception {
super.serviceStart();
LOG.info("RM registry service started : {}",
registryOperations.bindingDiagnosticDetails());
// Register self as event handler for RM Events
register(RMAppAttemptEventType.class, new AppEventHandler());
register(RMAppManagerEventType.class, new AppManagerEventHandler());
rmContext.getStateStore().registerHandler(RMStateStoreEventType.class,
new StateStoreEventHandler());
register(RMContainerEventType.class, new ContainerEventHandler());
}
/**
* register a handler
* @param eventType event type
* @param handler handler
*/
private void register(Class<? extends Enum> eventType,
EventHandler handler) {
rmContext.getDispatcher().register(eventType, handler);
}
@SuppressWarnings(
{"EnumSwitchStatementWhichMissesCases", "UnnecessaryDefault"})
protected void handleAppManagerEvent(RMAppManagerEvent event) throws
IOException {
RMAppManagerEventType eventType = event.getType();
ApplicationId appId =
event.getApplicationId();
switch (eventType) {
case APP_COMPLETED:
registryOperations.onApplicationCompleted(appId);
break;
default:
// this isn't in the enum today...just making sure for the
// future
break;
}
}
@SuppressWarnings("EnumSwitchStatementWhichMissesCases")
private void handleStateStoreEvent(RMStateStoreEvent event)
throws IOException {
RMStateStoreEventType eventType = event.getType();
switch (eventType) {
case STORE_APP:
RMStateStoreAppEvent storeAppEvent = (RMStateStoreAppEvent) event;
ApplicationStateData appState = storeAppEvent.getAppState();
ApplicationId appId =
appState.getApplicationSubmissionContext().getApplicationId();
registryOperations.onStateStoreEvent(appId, appState.getUser());
break;
default:
break;
}
}
@SuppressWarnings("EnumSwitchStatementWhichMissesCases")
protected void handleAppAttemptEvent(RMAppAttemptEvent event) throws
IOException {
RMAppAttemptEventType eventType = event.getType();
ApplicationAttemptId appAttemptId =
event.getApplicationAttemptId();
switch (eventType) {
case UNREGISTERED:
registryOperations.onApplicationAttemptUnregistered(appAttemptId);
break;
// container has finished
case CONTAINER_FINISHED:
RMAppAttemptContainerFinishedEvent cfe =
(RMAppAttemptContainerFinishedEvent) event;
ContainerId containerId = cfe.getContainerStatus().getContainerId();
registryOperations.onContainerFinished(containerId);
break;
default:
// do nothing
}
}
@SuppressWarnings("EnumSwitchStatementWhichMissesCases")
private void handleContainerEvent(RMContainerEvent event)
throws IOException {
RMContainerEventType eventType = event.getType();
switch (eventType) {
case FINISHED:
ContainerId containerId = event.getContainerId();
registryOperations.onContainerFinished(containerId);
break;
default:
break;
}
}
/**
* Handler for app events
*/
private class AppEventHandler implements
EventHandler<RMAppAttemptEvent> {
@Override
public void handle(RMAppAttemptEvent event) {
try {
handleAppAttemptEvent(event);
} catch (IOException e) {
LOG.warn("handling {}: {}", event, e, e);
}
}
}
/**
* Handler for RM-side App manager events
*/
private class AppManagerEventHandler
implements EventHandler<RMAppManagerEvent> {
@Override
public void handle(RMAppManagerEvent event) {
try {
handleAppManagerEvent(event);
} catch (IOException e) {
LOG.warn("handling {}: {}", event, e, e);
}
}
}
/**
* Handler for RM-side state store events.
* This happens early on, and as the data contains the user details,
* it is where paths can be set up in advance of being used.
*/
private class StateStoreEventHandler implements EventHandler<RMStateStoreEvent> {
@Override
public void handle(RMStateStoreEvent event) {
try {
handleStateStoreEvent(event);
} catch (IOException e) {
LOG.warn("handling {}: {}", event, e, e);
}
}
}
/**
* Handler for RM-side container events
*/
private class ContainerEventHandler implements EventHandler<RMContainerEvent> {
@Override
public void handle(RMContainerEvent event) {
try {
handleContainerEvent(event);
} catch (IOException e) {
LOG.warn("handling {}: {}", event, e, e);
}
}
}
}