/*
* Copyright (c) 2007-2010 Concurrent, Inc. All Rights Reserved.
*
* Project and contact information: http://www.cascading.org/
*
* This file is part of the Cascading project.
*
* Cascading is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cascading is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cascading. If not, see <http://www.gnu.org/licenses/>.
*/
package cascading.stats;
import java.io.Serializable;
import java.util.Collection;
/**
* Class CascadingStats is the base class for all Cascading statistics gathering. It also reports the status of
* core elements that have state.
* <p/>
* There are five states the stats object reports; pending, running, completed, failed, stopped, and finished.
* <ul>
* <li><code>pending</code> - when the Flow or Cascade has yet to start.</li>
* <li><code>running</code> - when the Flow or Cascade is executing a workload.</li>
* <li><code>successful</code> - when the Flow or Cascade naturally completed its workload without failure.</li>
* <li><code>failed</code> - when the Flow or Cascade threw an error and failed to finish the workload.</li>
* <li><code>stopped</code> - when the user calls stop() on the Flow or Cascade.</li>
* <li><code>finished</code> - when the Flow or Cascade is no longer processing a workload and <code>completed</code>,
* <code>failed</code>, or <code>stopped</code> is true.</li>
* </ul>
*
* @see CascadeStats
* @see FlowStats
* @see StepStats
*/
public abstract class CascadingStats implements Serializable
{
public enum Status
{
PENDING, RUNNING, SUCCESSFUL, FAILED, STOPPED, SKIPPED;
}
/** Field name */
String name;
/** Field status */
Status status = Status.PENDING;
/** Field startTime */
long startTime;
/** Field finishedTime */
long finishedTime;
/** Field throwable */
Throwable throwable;
/** Constructor CascadingStats creates a new CascadingStats instance. */
CascadingStats( String name )
{
this.name = name;
}
/**
* Method getID returns the ID of this CascadingStats object.
*
* @return the ID (type Object) of this CascadingStats object.
*/
public abstract Object getID();
/**
* Method getName returns the name of this CascadingStats object.
*
* @return the name (type String) of this CascadingStats object.
*/
public String getName()
{
return name;
}
/**
* Method isFinished returns true if the current status show no work currently being executed. This method
* returns true if {@link #isSuccessful()}, {@link #isFailed()}, or {@link #isStopped()} returns true.
*
* @return the finished (type boolean) of this CascadingStats object.
*/
public boolean isFinished()
{
return status == Status.SUCCESSFUL || status == Status.FAILED || status == Status.STOPPED;
}
/**
* Method isPending returns true if no work has started.
*
* @return the pending (type boolean) of this CascadingStats object.
*/
public boolean isPending()
{
return status == Status.PENDING;
}
/**
* Method isRunning returns true when work has begun.
*
* @return the running (type boolean) of this CascadingStats object.
*/
public boolean isRunning()
{
return status == Status.RUNNING;
}
/**
* Method isSuccessful returns true when work has completed successfully.
*
* @return the completed (type boolean) of this CascadingStats object.
*/
public boolean isSuccessful()
{
return status == Status.SUCCESSFUL;
}
/**
* Method isFailed returns true when the work ended with an error.
*
* @return the failed (type boolean) of this CascadingStats object.
*/
public boolean isFailed()
{
return status == Status.FAILED;
}
/**
* Method isStopped returns true when the user stopped the work.
*
* @return the stopped (type boolean) of this CascadingStats object.
*/
public boolean isStopped()
{
return status == Status.STOPPED;
}
/**
* Method isSkipped returns true when the works was skipped.
* <p/>
* Flows are skipped if the apporpriate {@link cascading.flow.FlowSkipStrategy#skipFlow(cascading.flow.Flow)}
* returns {@code true};
*
* @return the skipped (type boolean) of this CascadingStats object.
*/
public boolean isSkipped()
{
return status == Status.SKIPPED;
}
/**
* Method getStatus returns the status of this CascadingStats object.
*
* @return the status (type Status) of this CascadingStats object.
*/
public Status getStatus()
{
return status;
}
/** Method markRunning sets the status to running. */
public void markRunning()
{
if( status != Status.PENDING )
throw new IllegalStateException( "may not mark flow as " + Status.RUNNING + ", is already " + status );
status = Status.RUNNING;
markStartTime();
}
protected void markStartTime()
{
startTime = System.currentTimeMillis();
}
/** Method markSuccessful sets the status to successful. */
public void markSuccessful()
{
if( status != Status.RUNNING )
throw new IllegalStateException( "may not mark flow as " + Status.SUCCESSFUL + ", is already " + status );
status = Status.SUCCESSFUL;
markFinishedTime();
}
private void markFinishedTime()
{
finishedTime = System.currentTimeMillis();
}
/**
* Method markFailed sets the status to failed.
*
* @param throwable of type Throwable
*/
public void markFailed( Throwable throwable )
{
if( status != Status.RUNNING )
throw new IllegalStateException( "may not mark flow as " + Status.FAILED + ", is already " + status );
status = Status.FAILED;
markFinishedTime();
this.throwable = throwable;
}
/** Method markStopped sets the status to stopped. */
public void markStopped()
{
if( status != Status.PENDING && status != Status.RUNNING )
throw new IllegalStateException( "may not mark flow as " + Status.STOPPED + ", is already " + status );
status = Status.STOPPED;
markFinishedTime();
}
/** Method markSkipped sets the status to skipped. */
public void markSkipped()
{
if( status != Status.PENDING )
throw new IllegalStateException( "may not mark flow as " + Status.SKIPPED + ", is already " + status );
status = Status.SKIPPED;
}
/**
* Method getStartTime returns the startTime of this CascadingStats object.
*
* @return the startTime (type long) of this CascadingStats object.
*/
public long getStartTime()
{
return startTime;
}
/**
* Method getFinishedTime returns the finishedTime of this CascadingStats object.
*
* @return the finishedTime (type long) of this CascadingStats object.
*/
public long getFinishedTime()
{
return finishedTime;
}
/**
* Method getDuration returns the duration the work executed before being finished.
* </p>
* This method will return zero until the work is finished. See {@link #getCurrentDuration()}
* if you wish to poll for the current duration value.
*
* @return the duration (type long) of this CascadingStats object.
*/
public long getDuration()
{
if( finishedTime != 0 )
return finishedTime - startTime;
else
return 0;
}
/**
* Method getCurrentDuration returns the current duration of the current work whether or not
* the work is finished. When finished, the return value will be the same as {@link #getDuration()}.
*
* @return the currentDuration (type long) of this CascadingStats object.
*/
public long getCurrentDuration()
{
if( finishedTime != 0 )
return finishedTime - startTime;
else
return System.currentTimeMillis() - startTime;
}
/**
* Method getCounterGroups returns all the available counter group names.
*
* @return the counterGroups (type Collection<String>) of this CascadingStats object.
*/
public abstract Collection<String> getCounterGroups();
/**
* Method getCounterGroupsMatching returns all the available counter group names that match
* the given regular expression.
*
* @param regex of type String
* @return Collection<String>
*/
public abstract Collection<String> getCounterGroupsMatching( String regex );
/**
* Method getCountersFor returns all the counter names for the give group name.
*
* @param group
* @return Collection<String>
*/
public abstract Collection<String> getCountersFor( String group );
/**
* Method getCountersFor returns all the counter names for the counter enums.
*
* @param group
* @return Collection<String>
*/
public Collection<String> getCountersFor( Class<? extends Enum> group )
{
return getCountersFor( group.getName() );
}
/**
* Method getCounter returns the current value for the given counter Enum.
*
* @param counter of type Enum
* @return the current counter value
*/
public abstract long getCounterValue( Enum counter );
/**
* Method getCounter returns the current value for the given group and counter.
*
* @param group of type String
* @param counter of type String
* @return the current counter value
*/
public abstract long getCounterValue( String group, String counter );
/**
* Method captureDetail will recursively capture details about nested systems. Use this method to persist
* statistics about a given Cascade, Flow, or FlowStep.
* <p/>
* Each CascadingStats object must be individually inspected for any system specific details.
*/
public abstract void captureDetail();
public abstract Collection getChildren();
protected String getStatsString()
{
String string = "status=" + status + ", startTime=" + startTime;
if( finishedTime != 0 )
string += ", duration=" + ( finishedTime - startTime );
return string;
}
@Override
public String toString()
{
return "Cascading{" + getStatsString() + '}';
}
}