diff --git a/hadoop-mapreduce-project/CHANGES.txt b/hadoop-mapreduce-project/CHANGES.txt index 29c5840b524..bada68a308c 100644 --- a/hadoop-mapreduce-project/CHANGES.txt +++ b/hadoop-mapreduce-project/CHANGES.txt @@ -23,6 +23,8 @@ Release 0.23.3 - UNRELEASED MAPREDUCE-3740. Fixed broken mapreduce compilation after the patch for HADOOP-7965. (Devaraj K via vinodkv) + MAPREDUCE-3909 Javadoc the Service interfaces (stevel) + OPTIMIZATIONS BUG FIXES diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/AbstractService.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/AbstractService.java index 60bab5d0481..317a5289b20 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/AbstractService.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/AbstractService.java @@ -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 listeners = new ArrayList(); + /** + * 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 diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/Service.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/Service.java index 722dd5538e7..8b8b1837dd4 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/Service.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/Service.java @@ -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(); } diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/ServiceStateChangeListener.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/ServiceStateChangeListener.java index cf10a6c90ab..f80a4e688a5 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/ServiceStateChangeListener.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/ServiceStateChangeListener.java @@ -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. + *
    + *
  1. Any long-lived operation here will prevent the service state + * change from completing in a timely manner.
  2. + *
  3. 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.
  4. + *
+ * + * + * @param service the service that has changed. + */ void stateChanged(Service service); }