001/*
002 * Copyright (c) 2016-2017 Chris K Wensel <chris@wensel.net>. All Rights Reserved.
003 * Copyright (c) 2007-2017 Xplenty, Inc. All Rights Reserved.
004 *
005 * Project and contact information: http://www.cascading.org/
006 *
007 * This file is part of the Cascading project.
008 *
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *     http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 */
021
022package cascading.stats;
023
024import java.util.ArrayList;
025import java.util.Collection;
026import java.util.LinkedHashMap;
027import java.util.List;
028import java.util.Map;
029
030import cascading.flow.FlowStep;
031import cascading.management.state.ClientState;
032import cascading.util.ProcessLogger;
033
034/** Class FlowStepStats collects {@link cascading.flow.FlowStep} specific statistics. */
035public abstract class FlowStepStats extends CascadingStats<FlowNodeStats>
036  {
037  private final FlowStep flowStep;
038  private Map<String, FlowNodeStats> flowNodeStatsMap = new LinkedHashMap<>(); // topologically ordered
039
040  protected FlowStepStats( FlowStep flowStep, ClientState clientState )
041    {
042    super( flowStep.getName(), clientState );
043    this.flowStep = flowStep;
044    this.flowStep.setFlowStepStats( this );
045    }
046
047  @Override
048  protected ProcessLogger getProcessLogger()
049    {
050    if( flowStep != null && flowStep instanceof ProcessLogger )
051      return (ProcessLogger) flowStep;
052
053    return ProcessLogger.NULL;
054    }
055
056  @Override
057  public String getID()
058    {
059    return flowStep.getID();
060    }
061
062  @Override
063  public Type getType()
064    {
065    return Type.STEP;
066    }
067
068  public FlowStep getFlowStep()
069    {
070    return flowStep;
071    }
072
073  public void addNodeStats( FlowNodeStats flowNodeStats )
074    {
075    flowNodeStatsMap.put( flowNodeStats.getID(), flowNodeStats );
076    }
077
078  protected Map<String, FlowNodeStats> getFlowNodeStatsMap()
079    {
080    return flowNodeStatsMap;
081    }
082
083  public List<FlowNodeStats> getFlowNodeStats()
084    {
085    return new ArrayList<>( flowNodeStatsMap.values() );
086    }
087
088  public int getNodesCount()
089    {
090    return flowNodeStatsMap.size();
091    }
092
093  protected Collection<String> getFlowNodeIDs()
094    {
095    return flowNodeStatsMap.keySet();
096    }
097
098  @Override
099  public Collection<FlowNodeStats> getChildren()
100    {
101    return flowNodeStatsMap.values();
102    }
103
104  @Override
105  public FlowNodeStats getChildWith( String id )
106    {
107    return flowNodeStatsMap.get( id );
108    }
109
110  @Override
111  public synchronized void recordInfo()
112    {
113    clientState.recordFlowStep( flowStep );
114    }
115
116  @Override
117  public String toString()
118    {
119    return "Step{" + getStatsString() + '}';
120    }
121
122  public boolean hasCapturedFinalDetail()
123    {
124    Collection<FlowNodeStats> values = flowNodeStatsMap.values();
125
126    for( FlowNodeStats nodeStats : values )
127      {
128      if( !nodeStats.getChildren().isEmpty() && !nodeStats.hasCapturedFinalDetail() )
129        return false;
130      }
131
132    return true;
133    }
134
135  /**
136   * An internal method that will refresh current counters and, if a clientState client is enabled, the child details
137   * including node and slice statistics.
138   * <p>
139   * All results will be then recorded by the clientState implementation.
140   * <p>
141   * See {@link #captureDetail()} to force all statistics to be cached and locally accessible.
142   */
143  public abstract void recordChildStats();
144
145  /**
146   * Method getProcessStepID returns the ID representing the under platform process.
147   * <p>
148   * A FlowStep represents a unit of work on a remote platform, in the case of MapReduce, a
149   * MapReduce job. The step ID would be the job id.
150   *
151   * @return a String or null if unavailable
152   */
153  public abstract String getProcessStepID();
154
155  public String getProcessStatusURL()
156    {
157    return null;
158    }
159  }