Repository: reef Updated Branches: refs/heads/master bdd6cbf0e -> 2ee2ca980
[REEF-1327] Creating task states and task state transitions Adding TaskStateMachine, TaskState and TaskStateEvent Adding tests for task states transitions JIRA: [REEF-1327](https://issues.apache.org/jira/browse/REEF-1327) Pull Request: This closes #963 Project: http://git-wip-us.apache.org/repos/asf/reef/repo Commit: http://git-wip-us.apache.org/repos/asf/reef/commit/2ee2ca98 Tree: http://git-wip-us.apache.org/repos/asf/reef/tree/2ee2ca98 Diff: http://git-wip-us.apache.org/repos/asf/reef/diff/2ee2ca98 Branch: refs/heads/master Commit: 2ee2ca98026a7bbcc171aaab9deabaf148e0260d Parents: bdd6cbf Author: Julia Wang <[email protected]> Authored: Thu Apr 21 20:27:57 2016 -0700 Committer: Markus Weimer <[email protected]> Committed: Tue Apr 26 09:21:52 2016 -0700 ---------------------------------------------------------------------- .../Org.Apache.REEF.IMRU.Tests.csproj | 1 + .../TestTaskStates.cs | 251 +++++++++++++++++++ .../OnREEF/Driver/IMRUSystemException.cs | 2 +- .../Driver/StateMachine/SystemStateMachine.cs | 2 +- .../SystemStateTransitionException.cs | 3 +- .../OnREEF/Driver/StateMachine/TaskState.cs | 75 ++++++ .../Driver/StateMachine/TaskStateEvent.cs | 70 ++++++ .../Driver/StateMachine/TaskStateMachine.cs | 145 +++++++++++ .../TaskStateTransitionException.cs | 48 ++++ .../Org.Apache.REEF.IMRU.csproj | 4 + 10 files changed, 597 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/reef/blob/2ee2ca98/lang/cs/Org.Apache.REEF.IMRU.Tests/Org.Apache.REEF.IMRU.Tests.csproj ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.IMRU.Tests/Org.Apache.REEF.IMRU.Tests.csproj b/lang/cs/Org.Apache.REEF.IMRU.Tests/Org.Apache.REEF.IMRU.Tests.csproj index c5120f2..d9c4668 100644 --- a/lang/cs/Org.Apache.REEF.IMRU.Tests/Org.Apache.REEF.IMRU.Tests.csproj +++ b/lang/cs/Org.Apache.REEF.IMRU.Tests/Org.Apache.REEF.IMRU.Tests.csproj @@ -48,6 +48,7 @@ under the License. <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="MapperCountTest.cs" /> <Compile Include="TestSystemStates.cs" /> + <Compile Include="TestTaskStates.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="$(SolutionDir)\Org.Apache.REEF.IMRU\Org.Apache.REEF.IMRU.csproj"> http://git-wip-us.apache.org/repos/asf/reef/blob/2ee2ca98/lang/cs/Org.Apache.REEF.IMRU.Tests/TestTaskStates.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.IMRU.Tests/TestTaskStates.cs b/lang/cs/Org.Apache.REEF.IMRU.Tests/TestTaskStates.cs new file mode 100644 index 0000000..0c858da --- /dev/null +++ b/lang/cs/Org.Apache.REEF.IMRU.Tests/TestTaskStates.cs @@ -0,0 +1,251 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using Org.Apache.REEF.IMRU.OnREEF.Driver.StateMachine; +using Xunit; + +namespace Org.Apache.REEF.IMRU.Tests +{ + /// <summary> + /// The test cases in this classes test TaskState and transitions + /// </summary> + public class TestTaskStates + { + /// <summary> + /// This is to test a successful life cycle of task state transitions. + /// For TaskNew->TaskSubmitted->TaskRunning->TaskCompleted + /// </summary> + [Fact] + public void TestNewToCompleteScenario() + { + var taskState = new TaskStateMachine(); + Assert.True(taskState.CurrentState.Equals(TaskState.TaskNew), "State of newly created task should be TaskNew"); + Assert.False(taskState.IsFinalState(), "TaskNew should not be a final state."); + Assert.True(taskState.MoveNext(TaskStateEvent.SubmittedTask).Equals(TaskState.TaskSubmitted), "Failed to move from TaskNew to TaskSubmitted state."); + Assert.False(taskState.IsFinalState(), "TaskSubmitted should not be a final state."); + Assert.True(taskState.MoveNext(TaskStateEvent.RunningTask).Equals(TaskState.TaskRunning), "Failed to move from TaskSubmitted to TaskRunning state."); + Assert.False(taskState.IsFinalState(), "TaskRunning should not be a final state."); + Assert.True(taskState.MoveNext(TaskStateEvent.CompletedTask).Equals(TaskState.TaskCompleted), "Failed to move from TaskRunning to TaskCompleted state."); + Assert.True(taskState.IsFinalState(), "TaskCompleted should be a final state."); + } + + /// <summary> + /// This is to test a scenario from task running to close. + /// </summary> + [Fact] + public void TestRunningToCloseScenario() + { + var taskState = new TaskStateMachine(); + taskState.MoveNext(TaskStateEvent.SubmittedTask); + taskState.MoveNext(TaskStateEvent.RunningTask); + Assert.True(taskState.MoveNext(TaskStateEvent.WaitingTaskToClose).Equals(TaskState.TaskWaitingForClose), "Failed to move from RunningTask to TaskWaitingForClose state."); + Assert.False(taskState.IsFinalState(), "TaskWaitingForClose should not be a final state."); + Assert.True(taskState.MoveNext(TaskStateEvent.ClosedTask).Equals(TaskState.TaskClosedByDriver), "Failed to move from TaskWaitingForClose to TaskClosedByDriver state."); + Assert.True(taskState.IsFinalState(), "TaskClosedByDriver should be a final state."); + } + + /// <summary> + /// This is to test scenario from waiting for close and then get FailedTaskCommunicationError. + /// </summary> + [Fact] + public void TestRunningToCloseToFailedTaskCommunicationErrorScenario() + { + var taskState = new TaskStateMachine(); + taskState.MoveNext(TaskStateEvent.SubmittedTask); + taskState.MoveNext(TaskStateEvent.RunningTask); + taskState.MoveNext(TaskStateEvent.WaitingTaskToClose); + Assert.True(taskState.MoveNext(TaskStateEvent.FailedTaskCommunicationError).Equals(TaskState.TaskClosedByDriver), "Failed to move from WaitingTaskToClose to TaskClosedByDriver state with FailedTaskCommunicationError."); + } + + /// <summary> + /// This is to test scenario from waiting for close and then get FailedTaskAppError. + /// </summary> + [Fact] + public void TestRunningToCloseToFailedTaskAppErrorScenario() + { + var taskState = new TaskStateMachine(); + taskState.MoveNext(TaskStateEvent.SubmittedTask); + taskState.MoveNext(TaskStateEvent.RunningTask); + taskState.MoveNext(TaskStateEvent.WaitingTaskToClose); + Assert.True(taskState.MoveNext(TaskStateEvent.FailedTaskAppError).Equals(TaskState.TaskClosedByDriver), "Failed to move from WaitingTaskToClose to TaskClosedByDriver state with FailedTaskAppError."); + } + + /// <summary> + /// This is to test scenario from waiting for close and then get FailedTaskSystemError. + /// </summary> + [Fact] + public void TestRunningToCloseToFailedTaskSystemErrorScenario() + { + var taskState = new TaskStateMachine(); + taskState.MoveNext(TaskStateEvent.SubmittedTask); + taskState.MoveNext(TaskStateEvent.RunningTask); + taskState.MoveNext(TaskStateEvent.WaitingTaskToClose); + Assert.True(taskState.MoveNext(TaskStateEvent.FailedTaskSystemError).Equals(TaskState.TaskClosedByDriver), "Failed to move from WaitingTaskToClose to TaskClosedByDriver state with FailedTaskSystemError."); + } + + /// <summary> + /// This is to test scenario from waiting for close and then get FailedTaskEvaluatorError. + /// </summary> + [Fact] + public void TestRunningToCloseToFailedTaskEvaluatorErrorScenario() + { + var taskState = new TaskStateMachine(); + taskState.MoveNext(TaskStateEvent.SubmittedTask); + taskState.MoveNext(TaskStateEvent.RunningTask); + taskState.MoveNext(TaskStateEvent.WaitingTaskToClose); + Assert.True(taskState.MoveNext(TaskStateEvent.FailedTaskEvaluatorError).Equals(TaskState.TaskClosedByDriver), "Failed to move from WaitingTaskToClose to TaskClosedByDriver state with FailedTaskEvaluatorError."); + } + + /// <summary> + /// This is to test from WaitingTaskToClose to not allowed transitions. + /// </summary> + [Fact] + public void TestRunningToWaitingTaskToCloseToNotAllowedTransitions() + { + var taskState = new TaskStateMachine(); + taskState.MoveNext(TaskStateEvent.SubmittedTask); + taskState.MoveNext(TaskStateEvent.RunningTask); + taskState.MoveNext(TaskStateEvent.WaitingTaskToClose); + + Action moveNext = () => taskState.MoveNext(TaskStateEvent.RunningTask); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.CompletedTask); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.SubmittedTask); + Assert.Throws<TaskStateTransitionException>(moveNext); + } + + /// <summary> + /// This is to test from RunningTask to TaskFailedByEvaluatorFailure. + /// </summary> + [Fact] + public void TestRunningToFailByEvaluatorScenario() + { + var taskState = new TaskStateMachine(); + taskState.MoveNext(TaskStateEvent.SubmittedTask); + taskState.MoveNext(TaskStateEvent.RunningTask); + Assert.True(taskState.MoveNext(TaskStateEvent.FailedTaskEvaluatorError).Equals(TaskState.TaskFailedByEvaluatorFailure), "Failed to move from RunningTask to TaskFailedByEvaluatorFailure state with FailedTaskEvaluatorError."); + Assert.True(taskState.IsFinalState(), "TaskFailedByEvaluatorFailure should be a final state."); + } + + /// <summary> + /// This is to test from RunningTask to TaskFailedByGroupCommunication and then TaskFailedByEvaluatorFailure. + /// </summary> + [Fact] + public void TestRunningToFailByCommunicationThenByEvaluatorScenario() + { + var taskState = new TaskStateMachine(); + taskState.MoveNext(TaskStateEvent.SubmittedTask); + taskState.MoveNext(TaskStateEvent.RunningTask); + Assert.True(taskState.MoveNext(TaskStateEvent.FailedTaskCommunicationError).Equals(TaskState.TaskFailedByGroupCommunication), "Failed to move from RunningTask to TaskFailedByGroupCommunication state with FailedTaskCommunicationError."); + Assert.True(taskState.IsFinalState(), "TaskFailedByGroupCommunication should be a final state."); + Assert.True(taskState.MoveNext(TaskStateEvent.FailedTaskEvaluatorError).Equals(TaskState.TaskFailedByEvaluatorFailure), "Failed to move from TaskFailedByGroupCommunication to TaskFailedByEvaluatorFailure state with FailedTaskEvaluatorError."); + Assert.True(taskState.IsFinalState(), "TaskFailedByEvaluatorFailure should be a final state."); + } + + /// <summary> + /// This is to test from RunningTask to TaskFailedByGroupCommunication and then TaskFailedByEvaluatorFailure. + /// </summary> + [Fact] + public void TestRunningToFailBySystemThenByEvaluatorScenario() + { + var taskState = new TaskStateMachine(); + taskState.MoveNext(TaskStateEvent.SubmittedTask); + taskState.MoveNext(TaskStateEvent.RunningTask); + Assert.True(taskState.MoveNext(TaskStateEvent.FailedTaskSystemError).Equals(TaskState.TaskFailedBySystemError), "Failed to move from RunningTask to TaskFailedBySystemError state with FailedTaskSystemError."); + Assert.True(taskState.IsFinalState(), "TaskFailedByGroupCommunication should be a final state."); + Assert.True(taskState.MoveNext(TaskStateEvent.FailedTaskEvaluatorError).Equals(TaskState.TaskFailedByEvaluatorFailure), "Failed to move from TaskFailedBySystemError to TaskFailedByEvaluatorFailure state with FailedTaskEvaluatorError."); + Assert.True(taskState.IsFinalState(), "TaskFailedByEvaluatorFailure should be a final state."); + } + + /// <summary> + /// This is to test from TaskNew to not allowed transitions + /// </summary> + [Fact] + public void TestFromNewToNotAllowedTransitions() + { + var taskState = new TaskStateMachine(); + + Action moveNext = () => taskState.MoveNext(TaskStateEvent.RunningTask); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.WaitingTaskToClose); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.CompletedTask); + Assert.Throws<TaskStateTransitionException>(moveNext); + } + + /// <summary> + /// This is to test from RunningTask to not allowed transitions + /// </summary> + [Fact] + public void TestFromRunningToNotAllowedTransitions() + { + var taskState = new TaskStateMachine(); + taskState.MoveNext(TaskStateEvent.SubmittedTask); + taskState.MoveNext(TaskStateEvent.RunningTask); + + Action moveNext = () => taskState.MoveNext(TaskStateEvent.SubmittedTask); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.ClosedTask); + Assert.Throws<TaskStateTransitionException>(moveNext); + } + + /// <summary> + /// This is to test from FailedTaskEvaluatorError to not allowed transitions + /// </summary> + [Fact] + public void TestFromFailToNotAllowedTransitions() + { + var taskState = new TaskStateMachine(); + taskState.MoveNext(TaskStateEvent.SubmittedTask); + taskState.MoveNext(TaskStateEvent.RunningTask); + + taskState.MoveNext(TaskStateEvent.FailedTaskEvaluatorError); + Assert.True(taskState.CurrentState.Equals(TaskState.TaskFailedByEvaluatorFailure), "Failed to move to TaskFailedByEvaluatorFailure state."); + + Action moveNext = () => taskState.MoveNext(TaskStateEvent.RunningTask); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.ClosedTask); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.CompletedTask); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.SubmittedTask); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.WaitingTaskToClose); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.FailedTaskAppError); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.FailedTaskCommunicationError); + Assert.Throws<TaskStateTransitionException>(moveNext); + + moveNext = () => taskState.MoveNext(TaskStateEvent.FailedTaskSystemError); + Assert.Throws<TaskStateTransitionException>(moveNext); + } + } +} http://git-wip-us.apache.org/repos/asf/reef/blob/2ee2ca98/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/IMRUSystemException.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/IMRUSystemException.cs b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/IMRUSystemException.cs index 94cf619..7815bdf 100644 --- a/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/IMRUSystemException.cs +++ b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/IMRUSystemException.cs @@ -24,7 +24,7 @@ namespace Org.Apache.REEF.IMRU.OnREEF.Driver /// Type of exception thrown when possible bugs are detected in IMRU code. /// For example, we reach forbidden region of codes, inconsistent state etc. /// </summary> - public sealed class IMRUSystemException : Exception + public class IMRUSystemException : Exception { private static readonly Logger Logger = Logger.GetLogger(typeof(IMRUSystemException)); http://git-wip-us.apache.org/repos/asf/reef/blob/2ee2ca98/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/SystemStateMachine.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/SystemStateMachine.cs b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/SystemStateMachine.cs index 00963cd..e54e104 100644 --- a/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/SystemStateMachine.cs +++ b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/SystemStateMachine.cs @@ -23,7 +23,7 @@ namespace Org.Apache.REEF.IMRU.OnREEF.Driver.StateMachine /// <summary> /// This is a state transition machine which wraps current state, defines valid state transitions and API to move to next state. /// All the system states are defined in <see cref="SystemState"></see> - /// For the system state transition diagram <see href="https://issues.apache.org/jira/browse/REEF-1335"></see> + /// For the system state transition diagram <see href="https://issues.apache.org/jira/browse/REEF-1223"></see> /// </summary> internal sealed class SystemStateMachine { http://git-wip-us.apache.org/repos/asf/reef/blob/2ee2ca98/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/SystemStateTransitionException.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/SystemStateTransitionException.cs b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/SystemStateTransitionException.cs index 741cfa0..448927a 100644 --- a/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/SystemStateTransitionException.cs +++ b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/SystemStateTransitionException.cs @@ -15,7 +15,6 @@ // specific language governing permissions and limitations // under the License. -using System; using System.Globalization; namespace Org.Apache.REEF.IMRU.OnREEF.Driver.StateMachine @@ -23,7 +22,7 @@ namespace Org.Apache.REEF.IMRU.OnREEF.Driver.StateMachine /// <summary> /// Exception for SystemState Transition /// </summary> - internal sealed class SystemStateTransitionException : Exception + internal sealed class SystemStateTransitionException : IMRUSystemException { /// <summary> /// Exception when error happens in system state transition http://git-wip-us.apache.org/repos/asf/reef/blob/2ee2ca98/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskState.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskState.cs b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskState.cs new file mode 100644 index 0000000..6cb0687 --- /dev/null +++ b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskState.cs @@ -0,0 +1,75 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +namespace Org.Apache.REEF.IMRU.OnREEF.Driver.StateMachine +{ + /// <summary> + /// Task states in task state transitions + /// </summary> + internal enum TaskState + { + /// <summary> + /// When task (task configuration) is first created and added in the task list, its state is TaskNew + /// </summary> + TaskNew, + + /// <summary> + /// After submitting a task with an IActiveContext, the task state is changed to TaskSubmittedg + /// </summary> + TaskSubmitted, + + /// <summary> + /// After receiving RunningTask event, the task state is TaskRunning + /// </summary> + TaskRunning, + + /// <summary> + /// After receiving CompletedTask event, the task state is TaskCompeleted + /// </summary> + TaskCompleted, + + /// <summary> + /// After driver sends command to close a task, the task state is set to TaskWaitingForClose + /// </summary> + TaskWaitingForClose, + + /// <summary> + /// After receiving FailedTask event and verified it is closed by driver, the state is set to TaskClosedByDriver + /// </summary> + TaskClosedByDriver, + + /// <summary> + /// After receiving FailedEvaluator event, set associated task state to TaskFailedByEvaluatorFailure + /// </summary> + TaskFailedByEvaluatorFailure, + + /// <summary> + /// After receiving FailedTask event and verified it is caused by group communication + /// </summary> + TaskFailedByGroupCommunication, + + /// <summary> + /// After receiving FailedTask event and verified it is caused by application error + /// </summary> + TaskFailedByAppError, + + /// <summary> + /// After receiving FailedTask event and verified it is caused by system error + /// </summary> + TaskFailedBySystemError + } +} http://git-wip-us.apache.org/repos/asf/reef/blob/2ee2ca98/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateEvent.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateEvent.cs b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateEvent.cs new file mode 100644 index 0000000..9668f16 --- /dev/null +++ b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateEvent.cs @@ -0,0 +1,70 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +namespace Org.Apache.REEF.IMRU.OnREEF.Driver.StateMachine +{ + /// <summary> + /// Task state events that triggers task state transition + /// </summary> + internal enum TaskStateEvent + { + /// <summary> + /// Task is submitted + /// </summary> + SubmittedTask, + + /// <summary> + /// Task is running + /// </summary> + RunningTask, + + /// <summary> + /// Task is completed + /// </summary> + CompletedTask, + + /// <summary> + /// Waiting for task to close + /// </summary> + WaitingTaskToClose, + + /// <summary> + /// Task is closed + /// </summary> + ClosedTask, + + /// <summary> + /// Received failed task with application error + /// </summary> + FailedTaskAppError, + + /// <summary> + /// Received failed task with system error + /// </summary> + FailedTaskSystemError, + + /// <summary> + /// Received failed Evaluator that caused associated task failure + /// </summary> + FailedTaskEvaluatorError, + + /// <summary> + /// Received failed task with group communication error + /// </summary> + FailedTaskCommunicationError + } +} http://git-wip-us.apache.org/repos/asf/reef/blob/2ee2ca98/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateMachine.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateMachine.cs b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateMachine.cs new file mode 100644 index 0000000..17c0764 --- /dev/null +++ b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateMachine.cs @@ -0,0 +1,145 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Org.Apache.REEF.IMRU.OnREEF.Driver.StateMachine +{ + /// <summary> + /// Task state machine which defines task state transition from creating a new task, to submitted task, to task running, until task is completed. + /// It also defines the state transition condition from one to another + /// All the task states are defined in <see cref="TaskState"></see> + /// For the task state transition diagram <see href="https://issues.apache.org/jira/browse/REEF-1223"></see> + /// This class wraps current state and provides methods to move from one state to the next state + /// </summary> + internal sealed class TaskStateMachine + { + private readonly static IDictionary<StateTransition<TaskState, TaskStateEvent>, TaskState> Transitions = new ReadOnlyDictionary<StateTransition<TaskState, TaskStateEvent>, TaskState>( + new Dictionary<StateTransition<TaskState, TaskStateEvent>, TaskState> + { + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskNew, TaskStateEvent.SubmittedTask), TaskState.TaskSubmitted }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskNew, TaskStateEvent.ClosedTask), TaskState.TaskClosedByDriver }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskSubmitted, TaskStateEvent.RunningTask), TaskState.TaskRunning }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskSubmitted, TaskStateEvent.FailedTaskAppError), TaskState.TaskFailedByAppError }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskSubmitted, TaskStateEvent.FailedTaskSystemError), TaskState.TaskFailedBySystemError }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskSubmitted, TaskStateEvent.FailedTaskEvaluatorError), TaskState.TaskFailedByEvaluatorFailure }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskSubmitted, TaskStateEvent.FailedTaskCommunicationError), TaskState.TaskFailedByGroupCommunication }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskRunning, TaskStateEvent.CompletedTask), TaskState.TaskCompleted }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskRunning, TaskStateEvent.WaitingTaskToClose), TaskState.TaskWaitingForClose }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskRunning, TaskStateEvent.FailedTaskAppError), TaskState.TaskFailedByAppError }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskRunning, TaskStateEvent.FailedTaskSystemError), TaskState.TaskFailedBySystemError }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskRunning, TaskStateEvent.FailedTaskEvaluatorError), TaskState.TaskFailedByEvaluatorFailure }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskRunning, TaskStateEvent.FailedTaskCommunicationError), TaskState.TaskFailedByGroupCommunication }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskWaitingForClose, TaskStateEvent.ClosedTask), TaskState.TaskClosedByDriver }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskWaitingForClose, TaskStateEvent.FailedTaskAppError), TaskState.TaskClosedByDriver }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskWaitingForClose, TaskStateEvent.FailedTaskSystemError), TaskState.TaskClosedByDriver }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskWaitingForClose, TaskStateEvent.FailedTaskEvaluatorError), TaskState.TaskClosedByDriver }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskWaitingForClose, TaskStateEvent.FailedTaskCommunicationError), TaskState.TaskClosedByDriver }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskFailedBySystemError, TaskStateEvent.FailedTaskEvaluatorError), TaskState.TaskFailedByEvaluatorFailure }, + { new StateTransition<TaskState, TaskStateEvent>(TaskState.TaskFailedByGroupCommunication, TaskStateEvent.FailedTaskEvaluatorError), TaskState.TaskFailedByEvaluatorFailure } + }); + + /// <summary> + /// Final state means that the task is not running and will not attempt to run. + /// When all tasks are in final states, we can proceed to recovery or fail. + /// Transitions between final states are possible if causes of task termination are clarified. For example, we might receive + /// FailedTask event first, then set the task state as TaskFailedBySystemError or TaskFailedByGroupCommunication. And later + /// received FailedEvaluator that indicates the attached task was failed is actually caused by evaluator failure. We can then + /// change the state to TaskFailedByEvaluatorFailure. + /// For the task state transition diagram <see href="https://issues.apache.org/jira/browse/REEF-1223"></see> + /// </summary> + private readonly static ISet<TaskState> FinalState = new HashSet<TaskState>() + { + TaskState.TaskFailedByAppError, + TaskState.TaskFailedBySystemError, + TaskState.TaskFailedByEvaluatorFailure, + TaskState.TaskFailedByGroupCommunication, + TaskState.TaskClosedByDriver, + TaskState.TaskCompleted + }; + + private volatile TaskState _currentState; + + /// <summary> + /// Create a new DriverTaskState with TaskNew as the task initial state + /// </summary> + internal TaskStateMachine() + { + _currentState = TaskState.TaskNew; + } + + /// <summary> + /// return the current task state + /// </summary> + internal TaskState CurrentState + { + get + { + return _currentState; + } + } + + /// <summary> + /// Get next valid state based on the current state and event given without changing the current state + /// If there is no valid next state, TaskStateTransitionException will be thrown. + /// </summary> + /// <param name="taskEvent"></param> + /// <returns></returns> + internal TaskState GetNext(TaskStateEvent taskEvent) + { + StateTransition<TaskState, TaskStateEvent> transition = new StateTransition<TaskState, TaskStateEvent>(_currentState, taskEvent); + TaskState nextState; + if (!Transitions.TryGetValue(transition, out nextState)) + { + throw new TaskStateTransitionException(_currentState, taskEvent); + } + return nextState; + } + + /// <summary> + /// Move to the next state + /// If it is not able to move to the next valid state for a given event, TaskStateTransitionException will be thrown. + /// </summary> + /// <param name="taskEvent"></param> + /// <returns></returns> + internal TaskState MoveNext(TaskStateEvent taskEvent) + { + _currentState = GetNext(taskEvent); + return _currentState; + } + + /// <summary> + /// Checks if the current state is a final state + /// </summary> + /// <returns></returns> + internal bool IsFinalState() + { + return IsFinalState(_currentState); + } + + /// <summary> + /// Checks if the given TaskState is a final state + /// </summary> + /// <param name="taskState"></param> + /// <returns></returns> + internal static bool IsFinalState(TaskState taskState) + { + return FinalState.Contains(taskState); + } + } +} http://git-wip-us.apache.org/repos/asf/reef/blob/2ee2ca98/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateTransitionException.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateTransitionException.cs b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateTransitionException.cs new file mode 100644 index 0000000..a1b6e93 --- /dev/null +++ b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/StateMachine/TaskStateTransitionException.cs @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Globalization; + +namespace Org.Apache.REEF.IMRU.OnREEF.Driver.StateMachine +{ + /// <summary> + /// Exception for TaskState Transition + /// </summary> + internal sealed class TaskStateTransitionException : IMRUSystemException + { + /// <summary> + /// Exception when error happens in task state transition + /// </summary> + /// <param name="taskState"></param> + /// <param name="taskEvent"></param> + internal TaskStateTransitionException(TaskState taskState, TaskStateEvent taskEvent) + : base(ExceptionMessage(taskState, taskEvent)) + { + } + + /// <summary> + /// Format a message + /// </summary> + /// <param name="taskState"></param> + /// <param name="taskEvent"></param> + /// <returns></returns> + private static string ExceptionMessage(TaskState taskState, TaskStateEvent taskEvent) + { + return string.Format(CultureInfo.InvariantCulture, "Unexpected event {0} in state {1}.", taskEvent, taskState); + } + } +} http://git-wip-us.apache.org/repos/asf/reef/blob/2ee2ca98/lang/cs/Org.Apache.REEF.IMRU/Org.Apache.REEF.IMRU.csproj ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.IMRU/Org.Apache.REEF.IMRU.csproj b/lang/cs/Org.Apache.REEF.IMRU/Org.Apache.REEF.IMRU.csproj index 7c6c8f3..d893d49 100644 --- a/lang/cs/Org.Apache.REEF.IMRU/Org.Apache.REEF.IMRU.csproj +++ b/lang/cs/Org.Apache.REEF.IMRU/Org.Apache.REEF.IMRU.csproj @@ -76,11 +76,15 @@ under the License. <Compile Include="OnREEF\Driver\IMRUConstants.cs" /> <Compile Include="OnREEF\Driver\IMRUDriver.cs" /> <Compile Include="OnREEF\Driver\ServiceAndContextConfigurationProvider.cs" /> + <Compile Include="OnREEF\Driver\StateMachine\TaskStateMachine.cs" /> <Compile Include="OnREEF\Driver\StateMachine\StateTransition.cs" /> <Compile Include="OnREEF\Driver\StateMachine\SystemState.cs" /> <Compile Include="OnREEF\Driver\StateMachine\SystemStateEvent.cs" /> <Compile Include="OnREEF\Driver\StateMachine\SystemStateMachine.cs" /> <Compile Include="OnREEF\Driver\StateMachine\SystemStateTransitionException.cs" /> + <Compile Include="OnREEF\Driver\StateMachine\TaskStateEvent.cs" /> + <Compile Include="OnREEF\Driver\StateMachine\TaskState.cs" /> + <Compile Include="OnREEF\Driver\StateMachine\TaskStateTransitionException.cs" /> <Compile Include="OnREEF\IMRUTasks\MapTaskHost.cs" /> <Compile Include="OnREEF\IMRUTasks\UpdateTaskHost.cs" /> <Compile Include="OnREEF\MapInputWithControlMessage\MapControlMessage.cs" />
