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} -> 034 * <li>{@linkplain State#STARTING STARTING} -> 035 * <li>{@linkplain State#RUNNING RUNNING} -> 036 * <li>{@linkplain State#STOPPING STOPPING} -> 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 ListenableFuture<State> start(); 074 075 /** 076 * Initiates service startup (if necessary), returning once the service has finished starting. 077 * Unlike calling {@code start().get()}, this method throws no checked exceptions, and it cannot 078 * be {@linkplain Thread#interrupt interrupted}. 079 * 080 * @deprecated Use {@link #startAsync()} and {@link #awaitRunning} instead of this method. 081 * 082 * @throws UncheckedExecutionException if startup failed 083 * @return the state of the service when startup finished. 084 */ 085 @Deprecated State startAndWait(); 086 087 /** 088 * If the service state is {@link State#NEW}, this initiates service startup and returns 089 * immediately. A stopped service may not be restarted. 090 * 091 * @return this 092 * @throws IllegalStateException if the service is not {@link State#NEW} 093 * 094 * @since 15.0 095 */ 096 Service startAsync(); 097 098 /** 099 * Returns {@code true} if this service is {@linkplain State#RUNNING running}. 100 */ 101 boolean isRunning(); 102 103 /** 104 * Returns the lifecycle state of the service. 105 */ 106 State state(); 107 108 /** 109 * If the service is {@linkplain State#STARTING starting} or {@linkplain State#RUNNING running}, 110 * this initiates service shutdown and returns immediately. If the service is 111 * {@linkplain State#NEW new}, it is {@linkplain State#TERMINATED terminated} without having been 112 * started nor stopped. If the service has already been stopped, this method returns immediately 113 * without taking action. 114 * 115 * @deprecated Use {@link #stopAsync} instead of this method to initiate service shutdown or use a 116 * service {@link Listener} to asynchronously wait for service shutdown. 117 * 118 * @return a future for the shutdown result, regardless of whether this call initiated shutdown. 119 * Calling {@link ListenableFuture#get} will block until the service has finished shutting 120 * down, and either returns {@link State#TERMINATED} or throws an 121 * {@link ExecutionException}. If it has already finished stopping, 122 * {@link ListenableFuture#get} returns immediately. Cancelling this future has no effect 123 * on the service. 124 */ 125 @Deprecated ListenableFuture<State> stop(); 126 127 /** 128 * Initiates service shutdown (if necessary), returning once the service has finished stopping. If 129 * this is {@link State#STARTING}, startup will be cancelled. If this is {@link State#NEW}, it is 130 * {@link State#TERMINATED terminated} without having been started nor stopped. Unlike calling 131 * {@code stop().get()}, this method throws no checked exceptions. 132 * 133 * @deprecated Use {@link #stopAsync} and {@link #awaitTerminated} instead of this method. 134 * 135 * @throws UncheckedExecutionException if the service has failed or fails during shutdown 136 * @return the state of the service when shutdown finished. 137 */ 138 @Deprecated State stopAndWait(); 139 140 /** 141 * If the service is {@linkplain State#STARTING starting} or {@linkplain State#RUNNING running}, 142 * this initiates service shutdown and returns immediately. If the service is 143 * {@linkplain State#NEW new}, it is {@linkplain State#TERMINATED terminated} without having been 144 * started nor stopped. If the service has already been stopped, this method returns immediately 145 * without taking action. 146 * 147 * @return this 148 * @since 15.0 149 */ 150 Service stopAsync(); 151 152 /** 153 * Waits for the {@link Service} to reach the {@linkplain State#RUNNING running state}. 154 * 155 * @throws IllegalStateException if the service reaches a state from which it is not possible to 156 * enter the {@link State#RUNNING} state. e.g. if the {@code state} is 157 * {@code State#TERMINATED} when this method is called then this will throw an 158 * IllegalStateException. 159 * 160 * @since 15.0 161 */ 162 void awaitRunning(); 163 164 /** 165 * Waits for the {@link Service} to reach the {@linkplain State#RUNNING running state} for no 166 * more than the given time. 167 * 168 * @param timeout the maximum time to wait 169 * @param unit the time unit of the timeout argument 170 * @throws TimeoutException if the service has not reached the given state within the deadline 171 * @throws IllegalStateException if the service reaches a state from which it is not possible to 172 * enter the {@link State#RUNNING RUNNING} state. e.g. if the {@code state} is 173 * {@code State#TERMINATED} when this method is called then this will throw an 174 * IllegalStateException. 175 * 176 * @since 15.0 177 */ 178 void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException; 179 180 /** 181 * Waits for the {@link Service} to reach the {@linkplain State#TERMINATED terminated state}. 182 * 183 * @throws IllegalStateException if the service {@linkplain State#FAILED fails}. 184 * 185 * @since 15.0 186 */ 187 void awaitTerminated(); 188 189 /** 190 * Waits for the {@link Service} to reach a terminal state (either 191 * {@link Service.State#TERMINATED terminated} or {@link Service.State#FAILED failed}) for no 192 * more than the given time. 193 * 194 * @param timeout the maximum time to wait 195 * @param unit the time unit of the timeout argument 196 * @throws TimeoutException if the service has not reached the given state within the deadline 197 * @throws IllegalStateException if the service {@linkplain State#FAILED fails}. 198 * @since 15.0 199 */ 200 void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException; 201 202 /** 203 * Returns the {@link Throwable} that caused this service to fail. 204 * 205 * @throws IllegalStateException if this service's state isn't {@linkplain State#FAILED FAILED}. 206 * 207 * @since 14.0 208 */ 209 Throwable failureCause(); 210 211 /** 212 * Registers a {@link Listener} to be {@linkplain Executor#execute executed} on the given 213 * executor. The listener will have the corresponding transition method called whenever the 214 * service changes state. The listener will not have previous state changes replayed, so it is 215 * suggested that listeners are added before the service starts. 216 * 217 * <p>There is no guaranteed ordering of execution of listeners, but any listener added through 218 * this method is guaranteed to be called whenever there is a state change. 219 * 220 * <p>Exceptions thrown by a listener will be propagated up to the executor. Any exception thrown 221 * during {@code Executor.execute} (e.g., a {@code RejectedExecutionException} or an exception 222 * thrown by {@linkplain MoreExecutors#sameThreadExecutor inline execution}) will be caught and 223 * logged. 224 * 225 * @param listener the listener to run when the service changes state is complete 226 * @param executor the executor in which the listeners callback methods will be run. For fast, 227 * lightweight listeners that would be safe to execute in any thread, consider 228 * {@link MoreExecutors#sameThreadExecutor}. 229 * @since 13.0 230 */ 231 void addListener(Listener listener, Executor executor); 232 233 /** 234 * The lifecycle states of a service. 235 * 236 * <p>The ordering of the {@link State} enum is defined such that if there is a state transition 237 * from {@code A -> B} then {@code A.compareTo(B} < 0}. N.B. The converse is not true, i.e. if 238 * {@code A.compareTo(B} < 0} then there is <b>not</b> guaranteed to be a valid state transition 239 * {@code A -> B}. 240 * 241 * @since 9.0 (in 1.0 as {@code com.google.common.base.Service.State}) 242 */ 243 @Beta // should come out of Beta when Service does 244 enum State { 245 /** 246 * A service in this state is inactive. It does minimal work and consumes 247 * minimal resources. 248 */ 249 NEW { 250 @Override boolean isTerminal() { 251 return false; 252 } 253 }, 254 255 /** 256 * A service in this state is transitioning to {@link #RUNNING}. 257 */ 258 STARTING { 259 @Override boolean isTerminal() { 260 return false; 261 } 262 }, 263 264 /** 265 * A service in this state is operational. 266 */ 267 RUNNING { 268 @Override boolean isTerminal() { 269 return false; 270 } 271 }, 272 273 /** 274 * A service in this state is transitioning to {@link #TERMINATED}. 275 */ 276 STOPPING { 277 @Override boolean isTerminal() { 278 return false; 279 } 280 }, 281 282 /** 283 * A service in this state has completed execution normally. It does minimal work and consumes 284 * minimal resources. 285 */ 286 TERMINATED { 287 @Override boolean isTerminal() { 288 return true; 289 } 290 }, 291 292 /** 293 * A service in this state has encountered a problem and may not be operational. It cannot be 294 * started nor stopped. 295 */ 296 FAILED { 297 @Override boolean isTerminal() { 298 return true; 299 } 300 }; 301 302 /** Returns true if this state is terminal. */ 303 abstract boolean isTerminal(); 304 } 305 306 /** 307 * A listener for the various state changes that a {@link Service} goes through in its lifecycle. 308 * 309 * <p>All methods are no-ops by default, implementors should override the ones they care about. 310 * 311 * @author Luke Sandberg 312 * @since 15.0 (present as an interface in 13.0) 313 */ 314 @Beta // should come out of Beta when Service does 315 abstract class Listener { 316 /** 317 * Called when the service transitions from {@linkplain State#NEW NEW} to 318 * {@linkplain State#STARTING STARTING}. This occurs when {@link Service#start} or 319 * {@link Service#startAndWait} is called the first time. 320 */ 321 public void starting() {} 322 323 /** 324 * Called when the service transitions from {@linkplain State#STARTING STARTING} to 325 * {@linkplain State#RUNNING RUNNING}. This occurs when a service has successfully started. 326 */ 327 public void running() {} 328 329 /** 330 * Called when the service transitions to the {@linkplain State#STOPPING STOPPING} state. The 331 * only valid values for {@code from} are {@linkplain State#STARTING STARTING} or 332 * {@linkplain State#RUNNING RUNNING}. This occurs when {@link Service#stop} is called. 333 * 334 * @param from The previous state that is being transitioned from. 335 */ 336 public void stopping(State from) {} 337 338 /** 339 * Called when the service transitions to the {@linkplain State#TERMINATED TERMINATED} state. 340 * The {@linkplain State#TERMINATED TERMINATED} state is a terminal state in the transition 341 * diagram. Therefore, if this method is called, no other methods will be called on the 342 * {@link Listener}. 343 * 344 * @param from The previous state that is being transitioned from. The only valid values for 345 * this are {@linkplain State#NEW NEW}, {@linkplain State#RUNNING RUNNING} or 346 * {@linkplain State#STOPPING STOPPING}. 347 */ 348 public void terminated(State from) {} 349 350 /** 351 * Called when the service transitions to the {@linkplain State#FAILED FAILED} state. The 352 * {@linkplain State#FAILED FAILED} state is a terminal state in the transition diagram. 353 * Therefore, if this method is called, no other methods will be called on the {@link Listener}. 354 * 355 * @param from The previous state that is being transitioned from. Failure can occur in any 356 * state with the exception of {@linkplain State#NEW NEW} or 357 * {@linkplain State#TERMINATED TERMINATED}. 358 * @param failure The exception that caused the failure. 359 */ 360 public void failed(State from, Throwable failure) {} 361 } 362}