Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / tools / development / InstanceStateHolder.java
blob300e4166606b18ab8363cf15fe94aeddd78b958c
1 package com.google.appengine.tools.development;
3 import com.google.common.base.Joiner;
5 import javax.annotation.concurrent.GuardedBy;
7 /**
8 * Holder for the state of a server or backend instance.
9 */
10 public class InstanceStateHolder {
11 static enum InstanceState {
12 INITIALIZING, SLEEPING, RUNNING_START_REQUEST, RUNNING, STOPPED, SHUTDOWN;
15 private static final Joiner STATE_JOINER = Joiner.on("|");
16 private final String serverOrBackendName;
17 private final int instance;
18 @GuardedBy("this")
19 private InstanceState currentState = InstanceState.SHUTDOWN;
21 /**
22 * Constructs an {@link InstanceStateHolder}.
24 * @param serverOrBackendName For server instances the server name and for backend instances the
25 * backend name.
26 * @param instance The instance number or -1 for load balancing servers and automatic servers.
28 InstanceStateHolder(String serverOrBackendName, int instance) {
29 this.serverOrBackendName = serverOrBackendName;
30 this.instance = instance;
33 /**
34 * Updates the current server state and verifies that the previous state is
35 * what is expected.
37 * @param newState The new state to change to
38 * @param acceptablePreviousStates Acceptable previous states
39 * @throws IllegalStateException If the current state is not one of the
40 * acceptable previous states
42 void testAndSet(InstanceState newState,
43 InstanceState... acceptablePreviousStates) throws IllegalStateException {
44 InstanceState invalidState =
45 testAndSetIf(newState, acceptablePreviousStates);
46 if (invalidState != null) {
47 reportInvalidStateChange(serverOrBackendName, instance, invalidState,
48 newState, acceptablePreviousStates);
52 /**
53 * Reports an invalid state change attempt.
55 static void reportInvalidStateChange(String serverOrBackendName, int instance,
56 InstanceState currentState, InstanceState newState,
57 InstanceState... acceptablePreviousStates) {
58 StringBuilder error = new StringBuilder();
59 error.append("Tried to change state to " + newState);
60 error.append(" on server " + serverOrBackendName + "." + instance);
61 error.append(" but previous state is " + currentState);
62 error.append(" and not ");
63 error.append(STATE_JOINER.join(acceptablePreviousStates));
64 throw new IllegalStateException(error.toString());
67 /**
68 * Updates the current server state to the requested value and returns
69 * null if the previous state is an acceptable value and if not leaves the
70 * current server state unchanged and returns the current invalid state.
72 synchronized InstanceState testAndSetIf(InstanceState newState,
73 InstanceState... acceptablePreviousStates) {
74 InstanceState result = currentState;
75 if (test(acceptablePreviousStates)) {
76 result = null;
77 currentState = newState;
79 return result;
82 /**
83 * Returns true if current state is one of the provided acceptable states.
85 synchronized boolean test(InstanceState... acceptableStates) {
86 for (InstanceState acceptable : acceptableStates) {
87 if (currentState == acceptable) {
88 return true;
91 return false;
94 /**
95 * Throws an IllegalStateException if the current state is not one of the
96 * acceptable states for the designated operation.
98 synchronized void requireState(String operation, InstanceState... acceptableStates) {
99 if (!test(acceptableStates)) {
100 throw new IllegalStateException("Invalid current state operation=" + operation
101 + " currentState=" + currentState
102 + " acceptableStates=" + STATE_JOINER.join(acceptableStates));
107 * Checks if the server is in a state where it can accept incoming requests.
109 * @return true if the server can accept incoming requests, false otherwise.
111 synchronized boolean acceptsConnections() {
112 return (currentState == InstanceState.RUNNING
113 || currentState == InstanceState.RUNNING_START_REQUEST
114 || currentState == InstanceState.SLEEPING);
118 * Returns the display name for the current state.
120 synchronized String getDisplayName() {
121 return currentState.name().toLowerCase();
125 * Unconditionally sets the state.
127 synchronized void set(InstanceState newState) {
128 currentState = newState;