/* * Copyright 2016 Apache Software Foundation. * * Licensed 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.hops.util; import com.google.protobuf.InvalidProtocolBufferException; import io.hops.metadata.yarn.entity.ContainerStatus; import io.hops.metadata.yarn.entity.PendingEvent; import io.hops.metadata.yarn.entity.PendingEventID; import io.hops.metadata.yarn.entity.RMNodeComps; import io.hops.metadata.yarn.entity.Resource; import io.hops.metadata.yarn.entity.UpdatedContainerInfo; import io.hops.streaming.ContainerStatusEvent; import io.hops.streaming.DBEvent; import io.hops.streaming.PendingEventEvent; import io.hops.streaming.ResourceEvent; import io.hops.streaming.UpdatedContainerInfoEvent; import org.apache.hadoop.net.NetUtils; import org.apache.hadoop.yarn.api.records.NodeState; import org.apache.hadoop.yarn.server.resourcemanager.RMContext; import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.NodeAddedSchedulerEvent; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.NodeRemovedSchedulerEvent; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.event.NodeUpdateSchedulerEvent; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class RmStreamingProcessor extends StreamingReceiver { private final ExecutorService exec; public RmStreamingProcessor(RMContext rmContext) { super(rmContext, "RM Event retriever"); setRetrievingRunnable(new RetrievingThread()); exec = Executors.newCachedThreadPool(); } private void updateRMContext(RMNode rmNode) { if (LOG.isDebugEnabled()) { LOG.debug("HOP :: PendingEventRetrieval rmNode " + rmNode + ", state: " + rmNode.getState()); } if (rmNode.getState() == NodeState.DECOMMISSIONED || rmNode.getState() == NodeState.REBOOTED || rmNode.getState() == NodeState.LOST) { rmContext.getInactiveRMNodes().put(rmNode.getNodeID().getHost(), rmNode); rmContext.getRMNodes().remove(rmNode.getNodeID(), rmNode); } else { rmContext.getInactiveRMNodes(). remove(rmNode.getNodeID().getHost(), rmNode); rmContext.getRMNodes().put(rmNode.getNodeID(), rmNode); } } private void triggerEvent(final RMNode rmNode, PendingEvent pendingEvent) { if (LOG.isDebugEnabled()) { LOG.debug("NodeUpdate event_pending event trigger event: " + pendingEvent. getId().getEventId() + " : " + pendingEvent.getId().getNodeId()); } // TODO Maybe we should put back Hops Global Thread pool exec.submit(new Runnable() { @Override public void run() { NetUtils.normalizeHostName(rmNode.getHostName()); } }); if (pendingEvent.getType().equals(PendingEvent.Type.NODE_ADDED)) { LOG.debug("HOP :: PendingEventRetrieval event NodeAdded: " + pendingEvent); rmContext.getDispatcher().getEventHandler().handle( new NodeAddedSchedulerEvent(rmNode)); } else if (pendingEvent.getType().equals(PendingEvent.Type.NODE_REMOVED)) { LOG.debug("HOP :: PendingEventRetrieval event NodeRemoved: " + pendingEvent); rmContext.getDispatcher().getEventHandler().handle( new NodeRemovedSchedulerEvent(rmNode)); } else if (pendingEvent.getType().equals(PendingEvent.Type.NODE_UPDATED)) { if (pendingEvent.getStatus().equals( PendingEvent.Status.SCHEDULER_FINISHED_PROCESSING)) { LOG.debug( "HOP :: NodeUpdate event - event_scheduler - finished_processing RMNode: " + rmNode.getNodeID() + " pending event: " + pendingEvent.getId().getEventId()); rmContext.getDispatcher().getEventHandler().handle( new NodeUpdateSchedulerEvent(rmNode)); } else if (pendingEvent.getStatus().equals( PendingEvent.Status.SCHEDULER_NOT_FINISHED_PROCESSING)) { LOG.debug( "NodeUpdate event - event_scheduler - NOT_finished_processing RMNode: " + rmNode.getNodeID() + " pending event: " + pendingEvent.getId().getEventId()); } } } Map<PendingEventID, RMNodeComps> partialRMNodeComps = new HashMap<>(); private RMNodeComps getRMNodeComps(PendingEventID id) { RMNodeComps comps = partialRMNodeComps.get(id); if (comps == null) { comps = new RMNodeComps(); partialRMNodeComps.put(id, comps); } return comps; } private class RetrievingThread implements Runnable { @Override public void run() { while (running) { try { DBEvent event = DBEvent.receivedEvents.take(); RMNodeComps comps; if (event instanceof PendingEventEvent) { PendingEvent pendingEvent = ((PendingEventEvent) event). getPendingEvent(); comps = getRMNodeComps(pendingEvent.getId()); comps.setPendingEvent(pendingEvent); } else if (event instanceof io.hops.streaming.RMNodeEvent) { io.hops.metadata.yarn.entity.RMNode rmNode = ((io.hops.streaming.RMNodeEvent) event).getRmNode(); comps = getRMNodeComps( new PendingEventID(rmNode.getPendingEventId(), rmNode. getNodeId())); comps.setRMNode(rmNode); } else if (event instanceof ResourceEvent) { Resource resource = ((ResourceEvent) event).getResource(); comps = getRMNodeComps(new PendingEventID(resource. getPendingEventId(), resource.getId())); comps.setResource(resource); } else if (event instanceof UpdatedContainerInfoEvent) { UpdatedContainerInfo uci = ((UpdatedContainerInfoEvent) event). getUpdatedContainerInfo(); comps = getRMNodeComps(new PendingEventID(uci.getPendingEventId(), uci.getRmnodeid())); comps.addUpdatedContainerInfo(uci); } else if (event instanceof ContainerStatusEvent) { ContainerStatus containerStatus = ((ContainerStatusEvent) event). getContainerStatus(); comps = getRMNodeComps(new PendingEventID(containerStatus. getPendingEventId(), containerStatus.getRMNodeId())); comps.addContainersStatus(containerStatus); } else { LOG.error("should not receive events of type " + event.getClass(). getCanonicalName()); continue; } if (comps.isComplet()) { partialRMNodeComps.remove(comps.getPendingEvent().getId()); if (comps != null) { if (rmContext.isDistributed()) { RMNode rmNode = null; try { rmNode = DBUtility.processHopRMNodeCompsForScheduler(comps, rmContext); LOG.debug("HOP :: RetrievingThread RMNode: " + rmNode); if (rmNode != null) { updateRMContext(rmNode); triggerEvent(rmNode, comps.getPendingEvent()); } DBUtility.removePendingEvent(comps.getPendingEvent().getId(). getNodeId(), comps.getPendingEvent().getType(), comps.getPendingEvent().getStatus(), comps.getPendingEvent().getId().getEventId(), comps.getPendingEvent().getContains()); } catch (InvalidProtocolBufferException ex) { LOG.error("HOP :: Error retrieving RMNode: " + ex, ex); } catch (IOException ex) { LOG.error("HOP :: Error removing from DB: " + ex, ex); } } } } } catch (InterruptedException ex) { LOG.error(ex, ex); } } exec.shutdown(); LOG.info("HOP :: RM Event retriever interrupted"); } } }