@Override public String toString() { return stateMachine.getCurrentState().toString(); } }
/** * Atomically sets the state to the given updated state * if the current state equals to the expected state. * * @param expectedCurrentState an expected state * @param state a state * @return {@code true} if successful. {@code false} indicates that * the actual value was not equal to the expected value. * @throws IllegalStateTransitionException if the state is unknown state, or the transition * from the current state to the specified state is illegal */ public synchronized boolean compareAndSetState(final Enum expectedCurrentState, final Enum state) throws IllegalStateTransitionException { final boolean compared = currentState.stateEnum.equals(expectedCurrentState); if (compared) { setState(state); } else { LOG.debug("The expected current state [" + expectedCurrentState + "] is different from the actual state [" + currentState.stateEnum + "]"); } return compared; }
/** * Checks whether the current state is same as the {@code expectedCurrentState}. * * @param expectedCurrentState the expected current state * @throws RuntimeException if the expectedCurrentState is not same as the actual current state */ public synchronized void checkState(final Enum expectedCurrentState) { if (!currentState.stateEnum.equals(expectedCurrentState)) { throw new IllegalStateException(String.format("The expected state is %s but the actual state is %s\n%s", expectedCurrentState, currentState, getPossibleTransitionsFromCurrentState())); } }
/** * (PRIVATE METHOD) * Updates the state of the plan. * * @param newState of the plan. */ private void onPlanStateChanged(final PlanState.State newState) { metricStore.getOrCreateMetric(JobMetric.class, planId) .addEvent((PlanState.State) planState.getStateMachine().getCurrentState(), newState); metricStore.triggerBroadcast(JobMetric.class, planId); try { planState.getStateMachine().setState(newState); } catch (IllegalStateTransitionException e) { throw new RuntimeException(planId + " - Illegal plan state transition ", e); } if (newState == PlanState.State.EXECUTING) { LOG.debug("Executing Plan ID {}...", this.planId); } else if (newState == PlanState.State.COMPLETE || newState == PlanState.State.FAILED) { LOG.debug("Plan ID {} {}!", planId, newState); // Awake all threads waiting the finish of this plan. finishLock.lock(); try { planFinishedCondition.signalAll(); } finally { finishLock.unlock(); } } else { throw new RuntimeException("Illegal Plan State Transition"); } }
private StateMachine buildBlockStateMachine() { final StateMachine.Builder stateMachineBuilder = StateMachine.newBuilder(); // Add states stateMachineBuilder.addState(State.IN_PROGRESS, "The block is in the progress of being created."); stateMachineBuilder.addState(State.AVAILABLE, "The block is available."); stateMachineBuilder.addState(State.NOT_AVAILABLE, "The block is not available."); // From IN_PROGRESS stateMachineBuilder.addTransition(State.IN_PROGRESS, State.AVAILABLE, "The block is successfully created"); stateMachineBuilder.addTransition(State.IN_PROGRESS, State.NOT_AVAILABLE, "The block is lost before being created"); // From AVAILABLE stateMachineBuilder.addTransition(State.AVAILABLE, State.NOT_AVAILABLE, "The block is not available"); stateMachineBuilder.setInitialState(State.IN_PROGRESS); return stateMachineBuilder.build(); }
/** * Builds and returns the StateMachine. * * @return the StateMachine * @throws RuntimeException if an initial state was not set */ public StateMachine build() { if (initialState == null) { throw new RuntimeException("An initial state should be set"); } final Map<Enum, State> stateMap = new HashMap<>(); for (final Enum stateEnum : stateEnumSet) { stateMap.put(stateEnum, new State(stateEnum, stateDescriptionMap.get(stateEnum))); } for (final Enum stateEnum : stateEnumSet) { final State state = stateMap.get(stateEnum); if (transitionMap.containsKey(stateEnum)) { for (final Pair<Enum, String> transition : transitionMap.get(stateEnum)) { state.addTransition(new Transition(state, stateMap.get(transition.left()), transition.right())); } } } return new StateMachine(stateMap, initialState); } }
/** * (PRIVATE METHOD) * Updates the state of the plan. * * @param newState of the plan. */ private void onPlanStateChanged(final PlanState.State newState) { metricStore.getOrCreateMetric(JobMetric.class, planId) .addEvent((PlanState.State) planState.getStateMachine().getCurrentState(), newState); metricStore.triggerBroadcast(JobMetric.class, planId); try { planState.getStateMachine().setState(newState); } catch (IllegalStateTransitionException e) { throw new RuntimeException(planId + " - Illegal plan state transition ", e); } if (newState == PlanState.State.EXECUTING) { LOG.debug("Executing Plan ID {}...", this.planId); } else if (newState == PlanState.State.COMPLETE || newState == PlanState.State.FAILED) { LOG.debug("Plan ID {} {}!", planId, newState); // Awake all threads waiting the finish of this plan. finishLock.lock(); try { planFinishedCondition.signalAll(); } finally { finishLock.unlock(); } } else { throw new RuntimeException("Illegal Plan State Transition"); } }
private StateMachine buildBlockStateMachine() { final StateMachine.Builder stateMachineBuilder = StateMachine.newBuilder(); // Add states stateMachineBuilder.addState(State.IN_PROGRESS, "The block is in the progress of being created."); stateMachineBuilder.addState(State.AVAILABLE, "The block is available."); stateMachineBuilder.addState(State.NOT_AVAILABLE, "The block is not available."); // From IN_PROGRESS stateMachineBuilder.addTransition(State.IN_PROGRESS, State.AVAILABLE, "The block is successfully created"); stateMachineBuilder.addTransition(State.IN_PROGRESS, State.NOT_AVAILABLE, "The block is lost before being created"); // From AVAILABLE stateMachineBuilder.addTransition(State.AVAILABLE, State.NOT_AVAILABLE, "The block is not available"); stateMachineBuilder.setInitialState(State.IN_PROGRESS); return stateMachineBuilder.build(); }
/** * Builds and returns the StateMachine. * * @return the StateMachine * @throws RuntimeException if an initial state was not set */ public StateMachine build() { if (initialState == null) { throw new RuntimeException("An initial state should be set"); } final Map<Enum, State> stateMap = new HashMap<>(); for (final Enum stateEnum : stateEnumSet) { stateMap.put(stateEnum, new State(stateEnum, stateDescriptionMap.get(stateEnum))); } for (final Enum stateEnum : stateEnumSet) { final State state = stateMap.get(stateEnum); if (transitionMap.containsKey(stateEnum)) { for (final Pair<Enum, String> transition : transitionMap.get(stateEnum)) { state.addTransition(new Transition(state, stateMap.get(transition.left()), transition.right())); } } } return new StateMachine(stateMap, initialState); } }
@Nullable final String location) { final StateMachine stateMachine = blockState.getStateMachine(); final Enum oldState = stateMachine.getCurrentState(); LOG.debug("Block State Transition: id {} from {} to {}", new Object[]{blockId, oldState, newState}); stateMachine.setState(newState); } catch (IllegalStateTransitionException e) { throw new RuntimeException(blockId + " - Illegal block state transition ", e);
@Override public String toString() { return stateMachine.getCurrentState().toString(); } }
private StateMachine buildTaskStateMachine() { final StateMachine.Builder stateMachineBuilder = StateMachine.newBuilder(); // Add states stateMachineBuilder.addState(State.INCOMPLETE, "Some tasks in this stage are not complete."); stateMachineBuilder.addState(State.COMPLETE, "All of this stage's tasks have completed."); // Add transitions stateMachineBuilder.addTransition( State.INCOMPLETE, State.INCOMPLETE, "A task in the stage needs to be retried"); stateMachineBuilder.addTransition(State.INCOMPLETE, State.COMPLETE, "All tasks complete"); stateMachineBuilder.addTransition(State.COMPLETE, State.INCOMPLETE, "Completed before, but a task in this stage should be retried"); stateMachineBuilder.addTransition(State.COMPLETE, State.COMPLETE, "Completed before, but probably a cloned task has completed again"); stateMachineBuilder.setInitialState(State.INCOMPLETE); return stateMachineBuilder.build(); }
/** * Atomically sets the state to the given updated state * if the current state equals to the expected state. * * @param expectedCurrentState an expected state * @param state a state * @return {@code true} if successful. {@code false} indicates that * the actual value was not equal to the expected value. * @throws IllegalStateTransitionException if the state is unknown state, or the transition * from the current state to the specified state is illegal */ public synchronized boolean compareAndSetState(final Enum expectedCurrentState, final Enum state) throws IllegalStateTransitionException { final boolean compared = currentState.stateEnum.equals(expectedCurrentState); if (compared) { setState(state); } else { LOG.debug("The expected current state [" + expectedCurrentState + "] is different from the actual state [" + currentState.stateEnum + "]"); } return compared; }
/** * Checks whether the current state is same as the {@code expectedCurrentState}. * * @param expectedCurrentState the expected current state * @throws RuntimeException if the expectedCurrentState is not same as the actual current state */ public synchronized void checkState(final Enum expectedCurrentState) { if (!currentState.stateEnum.equals(expectedCurrentState)) { throw new IllegalStateException(String.format("The expected state is %s but the actual state is %s\n%s", expectedCurrentState, currentState, getPossibleTransitionsFromCurrentState())); } }
@Nullable final String location) { final StateMachine stateMachine = blockState.getStateMachine(); final Enum oldState = stateMachine.getCurrentState(); LOG.debug("Block State Transition: id {} from {} to {}", new Object[]{blockId, oldState, newState}); stateMachine.setState(newState); } catch (IllegalStateTransitionException e) { throw new RuntimeException(blockId + " - Illegal block state transition ", e);
@Override public String toString() { return stateMachine.getCurrentState().toString(); } }
private StateMachine buildTaskStateMachine() { final StateMachine.Builder stateMachineBuilder = StateMachine.newBuilder(); // Add states stateMachineBuilder.addState(State.INCOMPLETE, "Some tasks in this stage are not complete."); stateMachineBuilder.addState(State.COMPLETE, "All of this stage's tasks have completed."); // Add transitions stateMachineBuilder.addTransition( State.INCOMPLETE, State.INCOMPLETE, "A task in the stage needs to be retried"); stateMachineBuilder.addTransition(State.INCOMPLETE, State.COMPLETE, "All tasks complete"); stateMachineBuilder.addTransition(State.COMPLETE, State.INCOMPLETE, "Completed before, but a task in this stage should be retried"); stateMachineBuilder.addTransition(State.COMPLETE, State.COMPLETE, "Completed before, but probably a cloned task has completed again"); stateMachineBuilder.setInitialState(State.INCOMPLETE); return stateMachineBuilder.build(); }
/** * Sets the current state as a certain state. * * @param state a state * @throws IllegalStateTransitionException the state is unknown state, or the transition * from the current state to the specified state is illegal */ public synchronized void setState(final Enum state) throws IllegalStateTransitionException { if (!stateMap.containsKey(state)) { throw new RuntimeException("Unknown state " + state); } final State toState = stateMap.get(state); if (!currentState.isLegalTransition(state)) { throw new IllegalStateTransitionException(new Exception(String.format("Illegal transition from %s to %s\n%s", currentState, toState, getPossibleTransitionsFromCurrentState()))); } currentState = toState; }
/** * (PRIVATE METHOD) * Updates the state of a stage. * * @param stageId of the stage. * @param newStageState of the stage. */ private void onStageStateChanged(final String stageId, final StageState.State newStageState) { // Change stage state final StateMachine stageStateMachine = stageIdToState.get(stageId).getStateMachine(); metricStore.getOrCreateMetric(StageMetric.class, stageId) .addEvent(getStageState(stageId), newStageState); metricStore.triggerBroadcast(StageMetric.class, stageId); LOG.debug("Stage State Transition: id {} from {} to {}", new Object[]{stageId, stageStateMachine.getCurrentState(), newStageState}); try { stageStateMachine.setState(newStageState); } catch (IllegalStateTransitionException e) { throw new RuntimeException(stageId + " - Illegal stage state transition ", e); } // Change plan state if needed final boolean allStagesCompleted = stageIdToState.values().stream().allMatch(state -> state.getStateMachine().getCurrentState().equals(StageState.State.COMPLETE)); // avoid duplicate plan COMPLETE caused by cloning if (allStagesCompleted && !PlanState.State.COMPLETE.equals(getPlanState())) { onPlanStateChanged(PlanState.State.COMPLETE); } }
@Override public String toString() { return stateMachine.getCurrentState().toString(); } }