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-2944. Improve checking of input for JobClient.displayTasks() (XieXianshan via harsh)
MAPREDUCE-3909 Javadoc the Service interfaces (stevel)
BUG FIXES BUG FIXES
MAPREDUCE-3757. [Rumen] Fixed Rumen Folder to adjust shuffleFinished and MAPREDUCE-3757. [Rumen] Fixed Rumen Folder to adjust shuffleFinished and

View File

@ -28,14 +28,37 @@
public abstract class AbstractService implements Service { public abstract class AbstractService implements Service {
private static final Log LOG = LogFactory.getLog(AbstractService.class); private static final Log LOG = LogFactory.getLog(AbstractService.class);
/**
* Service state: initially {@link STATE#NOTINITED}.
*/
private STATE state = STATE.NOTINITED; private STATE state = STATE.NOTINITED;
/**
* Service name.
*/
private final String name; private final String name;
/**
* Service start time. Will be zero until the service is started.
*/
private long startTime; private long startTime;
/**
* The configuration. Will be null until the service is initialized.
*/
private Configuration config; private Configuration config;
/**
* List of state change listeners; it is final to ensure
* that it will never be null.
*/
private List<ServiceStateChangeListener> listeners = private List<ServiceStateChangeListener> listeners =
new ArrayList<ServiceStateChangeListener>(); new ArrayList<ServiceStateChangeListener>();
/**
* Construct the service.
* @param name service name
*/
public AbstractService(String name) { public AbstractService(String name) {
this.name = name; this.name = name;
} }
@ -45,6 +68,11 @@ public synchronized STATE getServiceState() {
return state; return state;
} }
/**
* {@inheritDoc}
* @throws IllegalStateException if the current service state does not permit
* this action
*/
@Override @Override
public synchronized void init(Configuration conf) { public synchronized void init(Configuration conf) {
ensureCurrentState(STATE.NOTINITED); ensureCurrentState(STATE.NOTINITED);
@ -53,6 +81,11 @@ public synchronized void init(Configuration conf) {
LOG.info("Service:" + getName() + " is inited."); LOG.info("Service:" + getName() + " is inited.");
} }
/**
* {@inheritDoc}
* @throws IllegalStateException if the current service state does not permit
* this action
*/
@Override @Override
public synchronized void start() { public synchronized void start() {
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
@ -61,6 +94,11 @@ public synchronized void start() {
LOG.info("Service:" + getName() + " is started."); LOG.info("Service:" + getName() + " is started.");
} }
/**
* {@inheritDoc}
* @throws IllegalStateException if the current service state does not permit
* this action
*/
@Override @Override
public synchronized void stop() { public synchronized void stop() {
if (state == STATE.STOPPED || if (state == STATE.STOPPED ||
@ -100,6 +138,12 @@ public long getStartTime() {
return startTime; 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) { private void ensureCurrentState(STATE currentState) {
if (state != currentState) { if (state != currentState) {
throw new IllegalStateException("For this operation, current State must " + throw new IllegalStateException("For this operation, current State must " +
@ -107,6 +151,14 @@ private void ensureCurrentState(STATE currentState) {
} }
} }
/**
* 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) { private void changeState(STATE newState) {
state = newState; state = newState;
//notify listeners //notify listeners

View File

@ -25,21 +25,87 @@
*/ */
public interface Service { public interface Service {
/**
* Service states
*/
public enum STATE { public enum STATE {
/** Constructed but not initialized */
NOTINITED, NOTINITED,
/** Initialized but not started or stopped */
INITED, INITED,
/** started and not stopped */
STARTED, 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); 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(); 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(); void stop();
/**
* Register an instance of the service state change events.
* @param listener a new listener
*/
void register(ServiceStateChangeListener 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); void unregister(ServiceStateChangeListener listener);
/**
* Get the name of this service.
* @return the service name
*/
String getName(); 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(); Configuration getConfig();
/**
* Get the current service state
* @return the state of the service
*/
STATE getServiceState(); 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(); long getStartTime();
} }

View File

@ -23,6 +23,23 @@
*/ */
public interface ServiceStateChangeListener { 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); void stateChanged(Service service);
} }