001/*
002 * Copyright (C) 2009 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.util.concurrent;
018
019import com.google.common.annotations.Beta;
020
021import java.util.concurrent.ExecutionException;
022import java.util.concurrent.Executor;
023import java.util.concurrent.TimeUnit;
024import java.util.concurrent.TimeoutException;
025
026/**
027 * An object with an operational state, plus asynchronous {@link #startAsync()} and
028 * {@link #stopAsync()} lifecycle methods to transition between states. Example services include
029 * webservers, RPC servers and timers.
030 *
031 * <p>The normal lifecycle of a service is:
032 * <ul>
033 *   <li>{@linkplain State#NEW NEW} -&gt;
034 *   <li>{@linkplain State#STARTING STARTING} -&gt;
035 *   <li>{@linkplain State#RUNNING RUNNING} -&gt;
036 *   <li>{@linkplain State#STOPPING STOPPING} -&gt;
037 *   <li>{@linkplain State#TERMINATED TERMINATED}
038 * </ul>
039 *
040 * <p>There are deviations from this if there are failures or if {@link Service#stopAsync} is called
041 * before the {@link Service} reaches the {@linkplain State#RUNNING RUNNING} state. The set of legal
042 * transitions form a <a href="http://en.wikipedia.org/wiki/Directed_acyclic_graph">DAG</a>,
043 * therefore every method of the listener will be called at most once. N.B. The {@link State#FAILED}
044 * and {@link State#TERMINATED} states are terminal states, once a service enters either of these
045 * states it cannot ever leave them.
046 *
047 * <p>Implementors of this interface are strongly encouraged to extend one of the abstract classes
048 * in this package which implement this interface and make the threading and state management
049 * easier.
050 *
051 * @author Jesse Wilson
052 * @author Luke Sandberg
053 * @since 9.0 (in 1.0 as {@code com.google.common.base.Service})
054 */
055@Beta
056public interface Service {
057  /**
058   * If the service state is {@link State#NEW}, this initiates service startup and returns
059   * immediately. If the service has already been started, this method returns immediately without
060   * taking action. A stopped service may not be restarted.
061   *
062   * @deprecated Use {@link #startAsync()} instead of this method to start the {@link Service} or
063   * use a {@link Listener} to asynchronously wait for service startup.
064   *
065   * @return a future for the startup result, regardless of whether this call initiated startup.
066   *         Calling {@link ListenableFuture#get} will block until the service has finished
067   *         starting, and returns one of {@link State#RUNNING}, {@link State#STOPPING} or
068   *         {@link State#TERMINATED}. If the service fails to start, {@link ListenableFuture#get}
069   *         will throw an {@link ExecutionException}, and the service's state will be
070   *         {@link State#FAILED}. If it has already finished starting, {@link ListenableFuture#get}
071   *         returns immediately. Cancelling this future has no effect on the service.
072   */
073  @Deprecated
074  ListenableFuture<State> start();
075
076  /**
077   * Initiates service startup (if necessary), returning once the service has finished starting.
078   * Unlike calling {@code start().get()}, this method throws no checked exceptions, and it cannot
079   * be {@linkplain Thread#interrupt interrupted}.
080   *
081   * @deprecated Use {@link #startAsync()} and {@link #awaitRunning} instead of this method.
082   *
083   * @throws UncheckedExecutionException if startup failed
084   * @return the state of the service when startup finished.
085   */
086  @Deprecated
087  State startAndWait();
088
089  /**
090   * If the service state is {@link State#NEW}, this initiates service startup and returns
091   * immediately. A stopped service may not be restarted.
092   *
093   * @return this
094   * @throws IllegalStateException if the service is not {@link State#NEW}
095   *
096   * @since 15.0
097   */
098  Service startAsync();
099
100  /**
101   * Returns {@code true} if this service is {@linkplain State#RUNNING running}.
102   */
103  boolean isRunning();
104
105  /**
106   * Returns the lifecycle state of the service.
107   */
108  State state();
109
110  /**
111   * If the service is {@linkplain State#STARTING starting} or {@linkplain State#RUNNING running},
112   * this initiates service shutdown and returns immediately. If the service is
113   * {@linkplain State#NEW new}, it is {@linkplain State#TERMINATED terminated} without having been
114   * started nor stopped. If the service has already been stopped, this method returns immediately
115   * without taking action.
116   *
117   * @deprecated Use {@link #stopAsync} instead of this method to initiate service shutdown or use a
118   * service {@link Listener} to asynchronously wait for service shutdown.
119   *
120   * @return a future for the shutdown result, regardless of whether this call initiated shutdown.
121   *         Calling {@link ListenableFuture#get} will block until the service has finished shutting
122   *         down, and either returns {@link State#TERMINATED} or throws an
123   *         {@link ExecutionException}. If it has already finished stopping,
124   *         {@link ListenableFuture#get} returns immediately. Cancelling this future has no effect
125   *         on the service.
126   */
127  @Deprecated
128  ListenableFuture<State> stop();
129
130  /**
131   * Initiates service shutdown (if necessary), returning once the service has finished stopping. If
132   * this is {@link State#STARTING}, startup will be cancelled. If this is {@link State#NEW}, it is
133   * {@link State#TERMINATED terminated} without having been started nor stopped. Unlike calling
134   * {@code stop().get()}, this method throws no checked exceptions.
135   *
136   * @deprecated Use {@link #stopAsync} and {@link #awaitTerminated} instead of this method.
137   *
138   * @throws UncheckedExecutionException if the service has failed or fails during shutdown
139   * @return the state of the service when shutdown finished.
140   */
141  @Deprecated
142  State stopAndWait();
143
144  /**
145   * If the service is {@linkplain State#STARTING starting} or {@linkplain State#RUNNING running},
146   * this initiates service shutdown and returns immediately. If the service is
147   * {@linkplain State#NEW new}, it is {@linkplain State#TERMINATED terminated} without having been
148   * started nor stopped. If the service has already been stopped, this method returns immediately
149   * without taking action.
150   *
151   * @return this
152   * @since 15.0
153   */
154  Service stopAsync();
155
156  /**
157   * Waits for the {@link Service} to reach the {@linkplain State#RUNNING running state}.
158   *
159   * @throws IllegalStateException if the service reaches a state from which it is not possible to
160   *     enter the {@link State#RUNNING} state. e.g. if the {@code state} is
161   *     {@code State#TERMINATED} when this method is called then this will throw an
162   *     IllegalStateException.
163   *
164   * @since 15.0
165   */
166  void awaitRunning();
167
168  /**
169   * Waits for the {@link Service} to reach the {@linkplain State#RUNNING running state} for no
170   * more than the given time.
171   *
172   * @param timeout the maximum time to wait
173   * @param unit the time unit of the timeout argument
174   * @throws TimeoutException if the service has not reached the given state within the deadline
175   * @throws IllegalStateException if the service reaches a state from which it is not possible to
176   *     enter the {@link State#RUNNING RUNNING} state. e.g. if the {@code state} is
177   *     {@code State#TERMINATED} when this method is called then this will throw an
178   *     IllegalStateException.
179   *
180   * @since 15.0
181   */
182  void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException;
183
184  /**
185   * Waits for the {@link Service} to reach the {@linkplain State#TERMINATED terminated state}.
186   *
187   * @throws IllegalStateException if the service {@linkplain State#FAILED fails}.
188   *
189   * @since 15.0
190   */
191  void awaitTerminated();
192
193  /**
194   * Waits for the {@link Service} to reach a terminal state (either
195   * {@link Service.State#TERMINATED terminated} or {@link Service.State#FAILED failed}) for no
196   * more than the given time.
197   *
198   * @param timeout the maximum time to wait
199   * @param unit the time unit of the timeout argument
200   * @throws TimeoutException if the service has not reached the given state within the deadline
201   * @throws IllegalStateException if the service {@linkplain State#FAILED fails}.
202   * @since 15.0
203   */
204  void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException;
205
206  /**
207   * Returns the {@link Throwable} that caused this service to fail.
208   *
209   * @throws IllegalStateException if this service's state isn't {@linkplain State#FAILED FAILED}.
210   *
211   * @since 14.0
212   */
213  Throwable failureCause();
214
215  /**
216   * Registers a {@link Listener} to be {@linkplain Executor#execute executed} on the given
217   * executor.  The listener will have the corresponding transition method called whenever the
218   * service changes state. The listener will not have previous state changes replayed, so it is
219   * suggested that listeners are added before the service starts.
220   *
221   * <p>There is no guaranteed ordering of execution of listeners, but any listener added through
222   * this method is guaranteed to be called whenever there is a state change.
223   *
224   * <p>Exceptions thrown by a listener will be propagated up to the executor. Any exception thrown
225   * during {@code Executor.execute} (e.g., a {@code RejectedExecutionException} or an exception
226   * thrown by {@linkplain MoreExecutors#sameThreadExecutor inline execution}) will be caught and
227   * logged.
228   *
229   * @param listener the listener to run when the service changes state is complete
230   * @param executor the executor in which the listeners callback methods will be run. For fast,
231   *     lightweight listeners that would be safe to execute in any thread, consider
232   *     {@link MoreExecutors#sameThreadExecutor}.
233   * @since 13.0
234   */
235  void addListener(Listener listener, Executor executor);
236
237  /**
238   * The lifecycle states of a service.
239   *
240   * <p>The ordering of the {@link State} enum is defined such that if there is a state transition
241   * from {@code A -> B} then {@code A.compareTo(B} < 0}.  N.B. The converse is not true, i.e. if
242   * {@code A.compareTo(B} < 0} then there is <b>not</b> guaranteed to be a valid state transition
243   * {@code A -> B}.
244   *
245   * @since 9.0 (in 1.0 as {@code com.google.common.base.Service.State})
246   */
247  @Beta // should come out of Beta when Service does
248  enum State {
249    /**
250     * A service in this state is inactive. It does minimal work and consumes
251     * minimal resources.
252     */
253    NEW {
254      @Override boolean isTerminal() {
255        return false;
256      }
257    },
258
259    /**
260     * A service in this state is transitioning to {@link #RUNNING}.
261     */
262    STARTING {
263      @Override boolean isTerminal() {
264        return false;
265      }
266    },
267
268    /**
269     * A service in this state is operational.
270     */
271    RUNNING {
272      @Override boolean isTerminal() {
273        return false;
274      }
275    },
276
277    /**
278     * A service in this state is transitioning to {@link #TERMINATED}.
279     */
280    STOPPING {
281      @Override boolean isTerminal() {
282        return false;
283      }
284    },
285
286    /**
287     * A service in this state has completed execution normally. It does minimal work and consumes
288     * minimal resources.
289     */
290    TERMINATED {
291      @Override boolean isTerminal() {
292        return true;
293      }
294    },
295
296    /**
297     * A service in this state has encountered a problem and may not be operational. It cannot be
298     * started nor stopped.
299     */
300    FAILED {
301      @Override boolean isTerminal() {
302        return true;
303      }
304    };
305
306    /** Returns true if this state is terminal. */
307    abstract boolean isTerminal();
308  }
309
310  /**
311   * A listener for the various state changes that a {@link Service} goes through in its lifecycle.
312   *
313   * <p>All methods are no-ops by default, implementors should override the ones they care about.
314   *
315   * @author Luke Sandberg
316   * @since 15.0 (present as an interface in 13.0)
317   */
318  @Beta // should come out of Beta when Service does
319  abstract class Listener {
320    /**
321     * Called when the service transitions from {@linkplain State#NEW NEW} to
322     * {@linkplain State#STARTING STARTING}. This occurs when {@link Service#start} or
323     * {@link Service#startAndWait} is called the first time.
324     */
325    public void starting() {}
326
327    /**
328     * Called when the service transitions from {@linkplain State#STARTING STARTING} to
329     * {@linkplain State#RUNNING RUNNING}. This occurs when a service has successfully started.
330     */
331    public void running() {}
332
333    /**
334     * Called when the service transitions to the {@linkplain State#STOPPING STOPPING} state. The
335     * only valid values for {@code from} are {@linkplain State#STARTING STARTING} or
336     * {@linkplain State#RUNNING RUNNING}.  This occurs when {@link Service#stop} is called.
337     *
338     * @param from The previous state that is being transitioned from.
339     */
340    public void stopping(State from) {}
341
342    /**
343     * Called when the service transitions to the {@linkplain State#TERMINATED TERMINATED} state.
344     * The {@linkplain State#TERMINATED TERMINATED} state is a terminal state in the transition
345     * diagram.  Therefore, if this method is called, no other methods will be called on the
346     * {@link Listener}.
347     *
348     * @param from The previous state that is being transitioned from.  The only valid values for
349     *     this are {@linkplain State#NEW NEW}, {@linkplain State#RUNNING RUNNING} or
350     *     {@linkplain State#STOPPING STOPPING}.
351     */
352    public void terminated(State from) {}
353
354    /**
355     * Called when the service transitions to the {@linkplain State#FAILED FAILED} state. The
356     * {@linkplain State#FAILED FAILED} state is a terminal state in the transition diagram.
357     * Therefore, if this method is called, no other methods will be called on the {@link Listener}.
358     *
359     * @param from The previous state that is being transitioned from.  Failure can occur in any
360     *     state with the exception of {@linkplain State#NEW NEW} or
361     *     {@linkplain State#TERMINATED TERMINATED}.
362     * @param failure The exception that caused the failure.
363     */
364    public void failed(State from, Throwable failure) {}
365  }
366}