MAPREDUCE-3909

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1294219 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Steve Loughran 2012-02-27 16:53:06 +00:00
parent acf8e6f1b5
commit 008cf6a11d
4 changed files with 139 additions and 2 deletions

View File

@ -56,6 +56,8 @@ Trunk (unreleased changes)
MAPREDUCE-2944. Improve checking of input for JobClient.displayTasks() (XieXianshan via harsh)
MAPREDUCE-3909 Javadoc the Service interfaces (stevel)
BUG FIXES
MAPREDUCE-3757. [Rumen] Fixed Rumen Folder to adjust shuffleFinished and

View File

@ -28,14 +28,37 @@ import org.apache.hadoop.conf.Configuration;
public abstract class AbstractService implements Service {
private static final Log LOG = LogFactory.getLog(AbstractService.class);
/**
* Service state: initially {@link STATE#NOTINITED}.
*/
private STATE state = STATE.NOTINITED;
/**
* Service name.
*/
private final String name;
/**
* Service start time. Will be zero until the service is started.
*/
private long startTime;
/**
* The configuration. Will be null until the service is initialized.
*/
private Configuration config;
/**
* List of state change listeners; it is final to ensure
* that it will never be null.
*/
private List<ServiceStateChangeListener> listeners =
new ArrayList<ServiceStateChangeListener>();
/**
* Construct the service.
* @param name service name
*/
public AbstractService(String name) {
this.name = name;
}
@ -45,6 +68,11 @@ public abstract class AbstractService implements Service {
return state;
}
/**
* {@inheritDoc}
* @throws IllegalStateException if the current service state does not permit
* this action
*/
@Override
public synchronized void init(Configuration conf) {
ensureCurrentState(STATE.NOTINITED);
@ -53,6 +81,11 @@ public abstract class AbstractService implements Service {
LOG.info("Service:" + getName() + " is inited.");
}
/**
* {@inheritDoc}
* @throws IllegalStateException if the current service state does not permit
* this action
*/
@Override
public synchronized void start() {
startTime = System.currentTimeMillis();
@ -61,6 +94,11 @@ public abstract class AbstractService implements Service {
LOG.info("Service:" + getName() + " is started.");
}
/**
* {@inheritDoc}
* @throws IllegalStateException if the current service state does not permit
* this action
*/
@Override
public synchronized void stop() {
if (state == STATE.STOPPED ||
@ -100,6 +138,12 @@ public abstract class AbstractService implements Service {
return startTime;
}
/**
* Verify that that a service is in a given state.
* @param currentState the desired state
* @throws IllegalStateException if the service state is different from
* the desired state
*/
private void ensureCurrentState(STATE currentState) {
if (state != currentState) {
throw new IllegalStateException("For this operation, current State must " +
@ -107,6 +151,14 @@ public abstract class AbstractService implements Service {
}
}
/**
* Change to a new state and notify all listeners.
* This is a private method that is only invoked from synchronized methods,
* which avoid having to clone the listener list. It does imply that
* the state change listener methods should be short lived, as they
* will delay the state transition.
* @param newState new service state
*/
private void changeState(STATE newState) {
state = newState;
//notify listeners

View File

@ -25,21 +25,87 @@ import org.apache.hadoop.conf.Configuration;
*/
public interface Service {
/**
* Service states
*/
public enum STATE {
/** Constructed but not initialized */
NOTINITED,
/** Initialized but not started or stopped */
INITED,
/** started and not stopped */
STARTED,
STOPPED;
/** stopped. No further state transitions are permitted */
STOPPED
}
/**
* Initialize the service.
*
* The transition must be from {@link STATE#NOTINITED} to {@link STATE#INITED}
* unless the operation failed and an exception was raised.
* @param config the configuration of the service
*/
void init(Configuration config);
/**
* Start the service.
*
* The transition should be from {@link STATE#INITED} to {@link STATE#STARTED}
* unless the operation failed and an exception was raised.
*/
void start();
/**
* Stop the service.
*
* This operation must be designed to complete regardless of the initial state
* of the service, including the state of all its internal fields.
*/
void stop();
/**
* Register an instance of the service state change events.
* @param listener a new listener
*/
void register(ServiceStateChangeListener listener);
/**
* Unregister a previously instance of the service state change events.
* @param listener the listener to unregister.
*/
void unregister(ServiceStateChangeListener listener);
/**
* Get the name of this service.
* @return the service name
*/
String getName();
/**
* Get the configuration of this service.
* This is normally not a clone and may be manipulated, though there are no
* guarantees as to what the consequences of such actions may be
* @return the current configuration, unless a specific implentation chooses
* otherwise.
*/
Configuration getConfig();
/**
* Get the current service state
* @return the state of the service
*/
STATE getServiceState();
/**
* Get the service start time
* @return the start time of the service. This will be zero if the service
* has not yet been started.
*/
long getStartTime();
}

View File

@ -23,6 +23,23 @@ package org.apache.hadoop.yarn.service;
*/
public interface ServiceStateChangeListener {
/**
* Callback to notify of a state change. The service will already
* have changed state before this callback is invoked.
*
* This operation is invoked on the thread that initiated the state change,
* while the service itself in in a sychronized section.
* <ol>
* <li>Any long-lived operation here will prevent the service state
* change from completing in a timely manner.</li>
* <li>If another thread is somehow invoked from the listener, and
* that thread invokes the methods of the service (including
* subclass-specific methods), there is a risk of a deadlock.</li>
* </ol>
*
*
* @param service the service that has changed.
*/
void stateChanged(Service service);
}