/******************************************************************************* * Copyright 2017 Capital One Services, LLC and Bitwise, Inc. * 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 hydrograph.ui.graph.execution.tracking.utils; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.eclipse.gef.EditPart; import org.eclipse.gef.GraphicalViewer; import org.eclipse.gef.ui.parts.GraphicalEditor; import org.eclipse.swt.widgets.Display; import org.slf4j.Logger; import hydrograph.ui.common.util.Constants; import hydrograph.ui.graph.Messages; import hydrograph.ui.graph.controller.ComponentEditPart; import hydrograph.ui.graph.editor.ELTGraphicalEditor; import hydrograph.ui.graph.execution.tracking.datastructure.ComponentStatus; import hydrograph.ui.graph.execution.tracking.datastructure.ExecutionStatus; import hydrograph.ui.graph.execution.tracking.datastructure.SubjobDetails; import hydrograph.ui.graph.execution.tracking.logger.ExecutionTrackingFileLogger; import hydrograph.ui.graph.execution.tracking.replay.ViewExecutionHistoryUtility; import hydrograph.ui.graph.execution.tracking.windows.ExecutionTrackingConsole; import hydrograph.ui.graph.job.JobManager; import hydrograph.ui.graph.model.Component; import hydrograph.ui.graph.model.ComponentExecutionStatus; import hydrograph.ui.graph.model.Container; import hydrograph.ui.graph.model.Link; import hydrograph.ui.logging.factory.LogFactory; /** * The Class TrackingDisplayUtils. */ public class TrackingStatusUpdateUtils { /** The logger. */ private Logger logger = LogFactory.INSTANCE.getLogger(TrackingStatusUpdateUtils.class); /** The instance. */ public static TrackingStatusUpdateUtils INSTANCE = new TrackingStatusUpdateUtils(); private String CLONE_COMPONENT_TYPE ="CloneComponent"; /** * Instantiates a new tracking display utils. */ private TrackingStatusUpdateUtils() { } /** * Update component status and processed record * @param executionStatus * @param editor */ public void updateEditorWithCompStatus(ExecutionStatus executionStatus, ELTGraphicalEditor editor,boolean isReplay) { if (executionStatus != null) { /** * Push the tracking log in tracking console */ if(!isReplay){ pushExecutionStatusToExecutionTrackingConsole(executionStatus); ExecutionTrackingFileLogger.INSTANCE.log(executionStatus.getJobId(), executionStatus, JobManager.INSTANCE.isLocalMode()); ExecutionTrackingConsoleUtils.INSTANCE.readFile(executionStatus, null, JobManager.INSTANCE.isLocalMode()); } GraphicalViewer graphicalViewer = (GraphicalViewer) ((GraphicalEditor) editor).getAdapter(GraphicalViewer.class); for (Iterator<EditPart> ite = graphicalViewer.getEditPartRegistry().values().iterator(); ite.hasNext();) { EditPart editPart = (EditPart) ite.next(); if (editPart instanceof ComponentEditPart) { Component component = ((ComponentEditPart) editPart).getCastedModel(); if(isReplay){ Map<String, String> componentNameAndLink = new HashMap(); if(Constants.SUBJOB_COMPONENT.equals(component.getComponentName())){ ViewExecutionHistoryUtility.INSTANCE.subjobParams(componentNameAndLink, component, new StringBuilder(component.getComponentId()+"."), true); componentNameAndLink.forEach((compId, compName)->{ ViewExecutionHistoryUtility.INSTANCE.addUnusedCompLabel(compId, compName); }); } } /** * Updating status and record count of subjob * component in main job. */ if (Constants.SUBJOB_COMPONENT.equals(component.getComponentName())) { if((component.getProperties().get(Constants.TYPE).equals(Constants.INPUT)||component.getProperties().get(Constants.TYPE).equals(Constants.OPERATION))){ Map<String, SubjobDetails> componentNameAndLink = new HashMap(); StringBuilder subjobPrefix = new StringBuilder(""); populateSubjobRecordCount(componentNameAndLink, component,subjobPrefix,true); applyRecordCountOnSubjobComponent(component, componentNameAndLink, executionStatus); } updateStatusCountForSubjobComponent(executionStatus, component, isReplay); }else{ updateStatusCountForComponent(executionStatus, component, isReplay); } } } } } /** * Updating status and count for canvas component according to received status. * @param executionStatus * @param component */ private void updateStatusCountForComponent( ExecutionStatus executionStatus, Component component, boolean isReplay) { if(isReplay){ ViewExecutionHistoryUtility.INSTANCE.addUnusedCompLabel(component.getComponentId(), component.getComponentId()); } for( ComponentStatus componentStatus: executionStatus.getComponentStatus()){ if(componentStatus.getComponentId().substring(componentStatus.getComponentId().lastIndexOf(".")+1).equals(component.getComponentId())){ logger.debug("Updating normal component {} status {}",component.getComponentId(), componentStatus.getCurrentStatus()); component.updateStatus(componentStatus.getCurrentStatus()); for(Link link: component.getSourceConnections()){ if(componentStatus.getComponentId().substring(componentStatus.getComponentId().lastIndexOf(".")+1).equals(link.getSource().getComponentId())){ if(componentStatus.getProcessedRecordCount().get(link.getSourceTerminal()) == null){ ViewExecutionHistoryUtility.INSTANCE.addUnusedCompLabel(link.getSource().getComponentId()+"_"+link.getSourceTerminal(), link.getSource().getComponentId()+"_"+link.getSourceTerminal()); }else{ link.updateRecordCount(componentStatus.getProcessedRecordCount().get(link.getSourceTerminal()).toString()); } } } } } } private void updateStatusCountForSubjobComponent(ExecutionStatus executionStatus,Component component, boolean isReplay) { ComponentExecutionStatus status=component.getStatus(); if(status==null || StringUtils.equalsIgnoreCase(ComponentExecutionStatus.BLANK.value(),status.value())){ boolean isPending =applyPendingStatus(component, executionStatus); if(isPending){ component.updateStatus(ComponentExecutionStatus.PENDING.value()); } } if(status!=null && !StringUtils.equalsIgnoreCase(ComponentExecutionStatus.SUCCESSFUL.value(),status.value())){ boolean isRunning =applyRunningStatus(component, executionStatus); if(isRunning){ component.updateStatus(ComponentExecutionStatus.RUNNING.value()); } } boolean isFail =applyFailStatus(component, executionStatus); if(isFail){ component.updateStatus(ComponentExecutionStatus.FAILED.value()); } if((status!=null && (StringUtils.equalsIgnoreCase(ComponentExecutionStatus.RUNNING.value(),status.value()) || StringUtils.equalsIgnoreCase(ComponentExecutionStatus.PENDING.value(),status.value()))) || isReplay){ boolean isSuccess=applySuccessStatus(component, executionStatus); if(isSuccess) component.updateStatus(ComponentExecutionStatus.SUCCESSFUL.value()); } } private void applyRecordCountOnSubjobComponent( Component component,Map<String, SubjobDetails> componentNameAndLink, ExecutionStatus executionStatus){ if (!componentNameAndLink.isEmpty()) { for (Map.Entry<String, SubjobDetails> entry : componentNameAndLink.entrySet()) { for (ComponentStatus componentStatus : executionStatus.getComponentStatus()) { if (entry.getKey().contains(componentStatus.getComponentId())) { List<String> portList = new ArrayList(componentStatus.getProcessedRecordCount().keySet()); for (String port : portList) { if ((((SubjobDetails) entry.getValue()).getSourceTerminal()).equals(port)) { for (Link link : component.getSourceConnections()) { if (link.getSourceTerminal().toString() .equals(((SubjobDetails) entry.getValue()).getTargetTerminal())) { link.updateRecordCount(componentStatus.getProcessedRecordCount() .get(((SubjobDetails) entry.getValue()).getSourceTerminal()) .toString()); break; } } } } } else { continue; } } } } } /** * * Populate the map for subjob status and record count. * * @param componentNameAndLink map to hold port vs count * @param component * @param subjobPrefix use to identify inner subjob components */ private void populateSubjobRecordCount(Map<String, SubjobDetails> componentNameAndLink, Component component,StringBuilder subjobPrefix,boolean isParent) { Component outputSubjobComponent=(Component) component.getProperties().get(Messages.OUTPUT_SUBJOB_COMPONENT); if(outputSubjobComponent!=null){ for(Link link:outputSubjobComponent.getTargetConnections()){ Component componentPrevToOutput = link.getSource(); if(Constants.SUBJOB_COMPONENT.equals(componentPrevToOutput.getComponentName())){ subjobPrefix.append(component.getComponentId()+"."); populateSubjobRecordCount(componentNameAndLink, componentPrevToOutput,subjobPrefix,false); }else{ String portNumber = link.getTargetTerminal().replace(Messages.IN_PORT_TYPE, Messages.OUT_PORT_TYPE); SubjobDetails subjobDetails = new SubjobDetails(link.getSourceTerminal(), portNumber); if(CLONE_COMPONENT_TYPE.equalsIgnoreCase(componentPrevToOutput.getComponentName())){ componentNameAndLink.put(subjobPrefix+component.getComponentId()+"."+componentPrevToOutput.getComponentId()+"."+portNumber, subjobDetails); }else{ if(isParent) componentNameAndLink.put(component.getComponentId()+"."+componentPrevToOutput.getComponentId()+"."+portNumber, subjobDetails); else componentNameAndLink.put(subjobPrefix+component.getComponentId()+"."+componentPrevToOutput.getComponentId()+"."+portNumber, subjobDetails); } } } } } private boolean applyPendingStatus(Component component, ExecutionStatus executionStatus) { boolean isPending = false; Container container=(Container)component.getProperties().get(Constants.SUBJOB_CONTAINER); for (Component innerSubComponent : container.getUIComponentList()) { if(!(innerSubComponent.getComponentName().equals(Messages.INPUT_SUBJOB_COMPONENT)) && !(innerSubComponent.getComponentName().equals(Messages.OUTPUT_SUBJOB_COMPONENT))){ for( ComponentStatus componentStatus: executionStatus.getComponentStatus()){ if(Constants.SUBJOB_COMPONENT.equals(innerSubComponent.getComponentName())){ isPending=applyPendingStatus(innerSubComponent, executionStatus); }else{ String compName = component.getComponentId()+"."+innerSubComponent.getComponentId(); if(componentStatus.getComponentId().contains(compName) && componentStatus.getCurrentStatus().equals(ComponentExecutionStatus.PENDING.value())){ return true; } } } } } return isPending; } private boolean applyRunningStatus(Component component, ExecutionStatus executionStatus) { boolean isRunning = false; Container container = (Container) component.getProperties().get(Constants.SUBJOB_CONTAINER); for (Component innerSubComponent : container.getUIComponentList()) { for( ComponentStatus componentStatus: executionStatus.getComponentStatus()){ if (Constants.SUBJOB_COMPONENT.equals(innerSubComponent.getComponentName())) { isRunning = applyRunningStatus(innerSubComponent, executionStatus); } else { String compName = component.getComponentId() + "."+ innerSubComponent.getComponentId(); if (componentStatus.getComponentId().contains(compName)&& componentStatus.getCurrentStatus().equals(ComponentExecutionStatus.RUNNING.value())) { return true; } } } } return isRunning; } private boolean applyFailStatus(Component component, ExecutionStatus executionStatus) { boolean isFail = false; Container container = (Container) component.getProperties().get(Constants.SUBJOB_CONTAINER); for (Component innerSubComponent : container.getUIComponentList()) { for( ComponentStatus componentStatus: executionStatus.getComponentStatus()){ if (Constants.SUBJOB_COMPONENT.equals(innerSubComponent.getComponentName())) { isFail =applyFailStatus(innerSubComponent, executionStatus); } else { String compName = component.getComponentId() + "."+ innerSubComponent.getComponentId(); if (componentStatus.getComponentId().contains(compName)&& componentStatus.getCurrentStatus().equals(ComponentExecutionStatus.FAILED.value())) { return true; } } } } return isFail; } private boolean applySuccessStatus(Component component, ExecutionStatus executionStatus) { boolean isSuccess = true; Container container = (Container) component.getProperties().get(Constants.SUBJOB_CONTAINER); boolean isSubjobComponentStatusAvailable= isSubjobAllComponentsStatusAvailable(container,executionStatus,component); if(!isSubjobComponentStatusAvailable){ isSuccess = false; return isSuccess; } for (ComponentStatus componentStatus : executionStatus.getComponentStatus()) { for (Component innerSubComponent : container.getUIComponentList()) { if (Constants.SUBJOB_COMPONENT.equals(innerSubComponent.getComponentName())) { isSuccess = applySuccessStatus(innerSubComponent, executionStatus); } else { String compName = component.getComponentId() + "."+ innerSubComponent.getComponentId(); if (componentStatus.getComponentId().contains(compName)){ if(!componentStatus.getCurrentStatus().equals(ComponentExecutionStatus.SUCCESSFUL.value())){ return false; } } } } } return isSuccess; } /** * Check for received status response contains status for all subjob component *@param container *@param executionStatus *@param component */ private boolean isSubjobAllComponentsStatusAvailable(Container container,ExecutionStatus executionStatus,Component component){ int subjobSocketCount=0; int subjobComponentCount=0; for (Component innerSubComponent : container.getUIComponentList()) { if (Constants.INPUT_SUBJOB.equals(innerSubComponent.getComponentName()) || Constants.OUTPUT_SUBJOB.equals(innerSubComponent.getComponentName())) { subjobSocketCount++; } for (ComponentStatus componentStatus : executionStatus.getComponentStatus()) { String compName = component.getComponentId() + "."+ innerSubComponent.getComponentId(); if (componentStatus.getComponentId().contains(compName)){ subjobComponentCount++; break; } } } if(container.getUIComponentList().size()-subjobSocketCount==subjobComponentCount) { return true; }else{ return false; } } /** * Push execution status to execution tracking console. * * @param executionStatus the execution status */ private void pushExecutionStatusToExecutionTrackingConsole( ExecutionStatus executionStatus) { String jobId = executionStatus.getJobId(); ExecutionTrackingConsole console = JobManager.INSTANCE.getExecutionTrackingConsoles().get(jobId); if(console!=null){ updateExecutionTrackingConsole(executionStatus, console,jobId); } } /** * Update execution tracking console. * * @param executionStatus the execution status * @param console the console * @param jobId */ private void updateExecutionTrackingConsole( final ExecutionStatus executionStatus, final ExecutionTrackingConsole console, final String jobId) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { console.clearConsole(); ExecutionStatus[] status = ExecutionTrackingConsoleUtils.INSTANCE.readFile(executionStatus, null, JobManager.INSTANCE.isLocalMode()); console.setStatus(ExecutionTrackingConsoleUtils.getHeader(jobId)); for(int i=0;i<status.length;i++){ console.setStatus(ExecutionTrackingConsoleUtils.INSTANCE.getExecutionStatusInString(status[i])); } } }); } }