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 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}