Repository: reef
Updated Branches:
  refs/heads/master a304daac9 -> 4f786095d


[REEF-1340] Creating Context manager for Fault Tolerant

Adding ContextManager which manages IActiveContext Add/Remove, etc operations
Adding test cases for it

JIRA: [REEF-1340](https://issues.apache.org/jira/browse/REEF-1340)
This closes #977


Project: http://git-wip-us.apache.org/repos/asf/reef/repo
Commit: http://git-wip-us.apache.org/repos/asf/reef/commit/4f786095
Tree: http://git-wip-us.apache.org/repos/asf/reef/tree/4f786095
Diff: http://git-wip-us.apache.org/repos/asf/reef/diff/4f786095

Branch: refs/heads/master
Commit: 4f786095d4f54a7016b4a9df61e05a904f129732
Parents: a304daa
Author: Julia Wang <[email protected]>
Authored: Thu Apr 28 14:26:24 2016 -0700
Committer: Andrew Chung <[email protected]>
Committed: Mon May 2 17:03:20 2016 -0700

----------------------------------------------------------------------
 .../Org.Apache.REEF.IMRU.Tests.csproj           |  17 ++
 .../TestActiveContextManager.cs                 | 175 +++++++++++++++++++
 .../Org.Apache.REEF.IMRU.Tests/packages.config  |   1 +
 .../OnREEF/Driver/ActiveContextManager.cs       | 152 ++++++++++++++++
 .../Org.Apache.REEF.IMRU.csproj                 |   1 +
 5 files changed, 346 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/reef/blob/4f786095/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 d9c4668..5c50039 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
@@ -42,11 +42,16 @@ under the License.
     <Reference Include="Microsoft.CSharp" />
     <Reference Include="System.Data" />
     <Reference Include="System.Xml" />
+    <Reference Include="NSubstitute, Version=$(NSubstituteVersion), 
Culture=neutral, PublicKeyToken=92dd2e9066daa5ca, processorArchitecture=MSIL">
+      
<HintPath>$(PackagesDir)\NSubstitute.$(NSubstituteVersion)\lib\net45\NSubstitute.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="MapInputWithControlMessageTests.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="MapperCountTest.cs" />
+    <Compile Include="TestActiveContextManager.cs" />
     <Compile Include="TestSystemStates.cs" />
     <Compile Include="TestTaskStates.cs" />
   </ItemGroup>
@@ -71,6 +76,18 @@ under the License.
       <Project>{6dc3b04e-2b99-4fda-bd23-2c7864f4c477}</Project>
       <Name>Org.Apache.REEF.IMRU.Examples</Name>
     </ProjectReference>
+    <ProjectReference 
Include="$(SolutionDir)\Org.Apache.REEF.Common\Org.Apache.REEF.Common.csproj">
+      <Project>{545a0582-4105-44ce-b99c-b1379514a630}</Project>
+      <Name>Org.Apache.REEF.Common</Name>
+    </ProjectReference>
+    <ProjectReference 
Include="$(SolutionDir)\Org.Apache.REEF.Driver\Org.Apache.REEF.Driver.csproj">
+      <Project>{a6baa2a7-f52f-4329-884e-1bcf711d6805}</Project>
+      <Name>Org.Apache.REEF.Driver</Name>
+    </ProjectReference>
+    <ProjectReference 
Include="$(SolutionDir)\Org.Apache.REEF.Utilities\Org.Apache.REEF.Utilities.csproj">
+      <Project>{79e7f89a-1dfb-45e1-8d43-d71a954aeb98}</Project>
+      <Name>Org.Apache.REEF.Utilities</Name>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />

http://git-wip-us.apache.org/repos/asf/reef/blob/4f786095/lang/cs/Org.Apache.REEF.IMRU.Tests/TestActiveContextManager.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.IMRU.Tests/TestActiveContextManager.cs 
b/lang/cs/Org.Apache.REEF.IMRU.Tests/TestActiveContextManager.cs
new file mode 100644
index 0000000..f2c01ad
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.IMRU.Tests/TestActiveContextManager.cs
@@ -0,0 +1,175 @@
+// 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 System.Collections.Generic;
+using NSubstitute;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.IMRU.OnREEF.Driver;
+using Xunit;
+
+namespace Org.Apache.REEF.IMRU.Tests
+{
+    /// <summary>
+    /// Test methods in ActiveContextManager
+    /// </summary>
+    public class TestActiveContextManager
+    {
+        private const string EvaluatorIdPrefix = "EvaluatorId";
+        private const string ContextIdPrefix = "ContextId";
+
+        /// <summary>
+        /// Create a ActiveContextManager and add some IActiveContexts to it.
+        /// </summary>
+        /// <returns></returns>
+        private ActiveContextManager InitializeActiveContextManager()
+        {
+            const int totalEvaluators = 5;
+            var activeContextManager = new 
ActiveContextManager(totalEvaluators);
+            for (int i = 0; i < totalEvaluators; i++)
+            {
+                activeContextManager.Add(CreateMockActiveContext(i));
+            }
+            Assert.True(activeContextManager.AreAllContextsReceived);
+            Assert.Equal(totalEvaluators, 
activeContextManager.NumberOfActiveContexts);
+
+            return activeContextManager;
+        }
+
+        /// <summary>
+        /// Test add, Remove, RemovedFailedContextInFailedEvaluator, 
NumberOfMissingContexts and NumberOfActiveContext
+        /// in ActiveContexManager
+        /// </summary>
+        [Fact]
+        public void TestValidAddRemoveCases()
+        {
+            var activeContextManager = InitializeActiveContextManager();
+            
activeContextManager.RemoveFailedContextInFailedEvaluator(CreateMockFailedEvaluator(new
 List<int> { 3 }));
+            Assert.Equal(1, activeContextManager.NumberOfMissingContexts);
+
+            activeContextManager.Remove(ContextIdPrefix + 4);
+            Assert.Equal(3, activeContextManager.NumberOfActiveContexts);
+        }
+
+        /// <summary>
+        /// Test invalid Add and Remove
+        /// </summary>
+        public void TestInvalidAddRemoveCases()
+        {
+            var activeContextManager = new ActiveContextManager(3);
+            activeContextManager.Add(CreateMockActiveContext(1));
+
+            Action add = () => 
activeContextManager.Add(CreateMockActiveContext(1));
+            Assert.Throws<IMRUSystemException>(add);
+
+            Action remove = () => activeContextManager.Remove(ContextIdPrefix 
+ 2);
+            Assert.Throws<IMRUSystemException>(remove);
+
+            activeContextManager.Add(CreateMockActiveContext(2));
+            activeContextManager.Add(CreateMockActiveContext(3));
+
+            add = () => activeContextManager.Add(CreateMockActiveContext(4));
+            Assert.Throws<IMRUSystemException>(add);
+        }
+
+        /// <summary>
+        /// Test removing a failed evaluator which has two contexts associated.
+        /// In current IMRU driver, assume there is only one context 
associated to the IFailedEvalutor
+        /// </summary>
+        [Fact]
+        public void TestRemoveFailedEvaluatorWithTwoContexts()
+        {
+            var activeContextManager = InitializeActiveContextManager();
+
+            Action remove = () => 
activeContextManager.RemoveFailedContextInFailedEvaluator(CreateMockFailedEvaluator(new
 List<int> { 3, 4 }));
+            Assert.Throws<IMRUSystemException>(remove);
+        }
+
+        /// <summary>
+        /// Test removing a failed evaluator which has a context but it 
doesn't exist.
+        /// </summary>
+        [Fact]
+        public void TestRemoveFailedEvaluatorWithNoExistsContexts()
+        {
+            var activeContextManager = InitializeActiveContextManager();
+
+            Action remove = () => 
activeContextManager.RemoveFailedContextInFailedEvaluator(CreateMockFailedEvaluator(new
 List<int> { 5 }));
+            Assert.Throws<IMRUSystemException>(remove);
+        }
+
+        /// <summary>
+        /// Test removing a failed evaluator which has no context associated.
+        /// The scenario may happen when an evaluator failed but context has 
not created yet. 
+        /// </summary>
+        [Fact]
+        public void TestRemoveFailedEvaluatorWithNoContext()
+        {
+            var activeContextManager = InitializeActiveContextManager();
+
+            
activeContextManager.RemoveFailedContextInFailedEvaluator(CreateMockFailedEvaluator(null));
+            Assert.Equal(0, activeContextManager.NumberOfMissingContexts);
+        }
+
+        /// <summary>
+        /// Create a mock IActiveContext
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        private static IActiveContext CreateMockActiveContext(int id)
+        {
+            IActiveContext mockActiveContext = 
Substitute.For<IActiveContext>();
+            mockActiveContext.Id.Returns(ContextIdPrefix + id);
+            mockActiveContext.EvaluatorId.Returns(EvaluatorIdPrefix + 
ContextIdPrefix + id);
+            return mockActiveContext;
+        }
+
+        /// <summary>
+        /// Create a mock IFailedContext
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        private static IFailedContext CreateMockFailedContext(int id)
+        {
+            IFailedContext mockFailedContext = 
Substitute.For<IFailedContext>();
+            mockFailedContext.Id.Returns(ContextIdPrefix + id);
+            mockFailedContext.EvaluatorId.Returns(EvaluatorIdPrefix + 
ContextIdPrefix + id);
+            return mockFailedContext;
+        }
+
+        /// <summary>
+        /// Create a mock IFailedEvaluator
+        /// </summary>
+        /// <param name="ids"></param>
+        /// <returns></returns>
+        private static IFailedEvaluator CreateMockFailedEvaluator(IList<int> 
ids)
+        {
+            IFailedEvaluator mockFailedEvalutor = 
Substitute.For<IFailedEvaluator>();
+            IList<IFailedContext> failedContexts = null;
+            if (ids != null)
+            {
+                failedContexts = new List<IFailedContext>();
+                foreach (var id in ids)
+                {
+                    failedContexts.Add(CreateMockFailedContext(id));
+                }
+            }
+            mockFailedEvalutor.FailedContexts.Returns(failedContexts);
+            return mockFailedEvalutor;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/reef/blob/4f786095/lang/cs/Org.Apache.REEF.IMRU.Tests/packages.config
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.IMRU.Tests/packages.config 
b/lang/cs/Org.Apache.REEF.IMRU.Tests/packages.config
index df4e5ea..a57dabf 100644
--- a/lang/cs/Org.Apache.REEF.IMRU.Tests/packages.config
+++ b/lang/cs/Org.Apache.REEF.IMRU.Tests/packages.config
@@ -18,6 +18,7 @@ specific language governing permissions and limitations
 under the License.
 -->
 <packages>
+  <package id="NSubstitute" version="1.8.2.0" targetFramework="net45" />
   <package id="StyleCop.MSBuild" version="4.7.49.1" targetFramework="net45" 
developmentDependency="true" />
   <package id="xunit" version="2.1.0" targetFramework="net45" />
   <package id="xunit.abstractions" version="2.0.0" targetFramework="net45" />

http://git-wip-us.apache.org/repos/asf/reef/blob/4f786095/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/ActiveContextManager.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/ActiveContextManager.cs 
b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/ActiveContextManager.cs
new file mode 100644
index 0000000..36c54ce
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.IMRU/OnREEF/Driver/ActiveContextManager.cs
@@ -0,0 +1,152 @@
+// 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;
+using System.Globalization;
+using System.Linq;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Utilities.Attributes;
+using Org.Apache.REEF.Utilities.Diagnostics;
+using Org.Apache.REEF.Utilities.Logging;
+
+namespace Org.Apache.REEF.IMRU.OnREEF.Driver
+{
+    /// <summary>
+    /// Manages active contexts for the driver
+    /// </summary>
+    [NotThreadSafe]
+    internal sealed class ActiveContextManager
+    {
+        private static readonly Logger Logger = 
Logger.GetLogger(typeof(ActiveContextManager));
+        private readonly IDictionary<string, IActiveContext> _activeContexts = 
new Dictionary<string, IActiveContext>();
+        private readonly int _totalExpectedContexts;
+
+        /// <summary>
+        /// Constructor of ActiveContextManager
+        /// totalContexts specify the total number of expected active contexts 
that driver needs
+        /// </summary>
+        /// <param name="totalContexts"></param>
+        internal ActiveContextManager(int totalContexts)
+        {
+            _totalExpectedContexts = totalContexts;
+        }
+
+        /// <summary>
+        /// Returns the collection of IActiveContext
+        /// </summary>
+        internal IReadOnlyCollection<IActiveContext> ActiveContexts
+        {
+            get { return new 
ReadOnlyCollection<IActiveContext>(_activeContexts.Values.ToList()); }
+        }
+
+        /// <summary>
+        /// Returns the difference between the number of expected 
IActiveContext and actually number of IActiveContext. 
+        /// </summary>
+        internal int NumberOfMissingContexts
+        {
+            get { return _totalExpectedContexts - NumberOfActiveContexts; }
+        }
+
+        /// <summary>
+        /// Checks if all the requested contexts are received. 
+        /// </summary>
+        internal bool AreAllContextsReceived
+        {
+            get { return _totalExpectedContexts == NumberOfActiveContexts; }
+        }
+
+        /// <summary>
+        /// Adding an IActiveContext to the ActiveContext collection
+        /// Throw IMRUSystemException if the IActiveContext already exists or 
NumberOfActiveContexts has exceeded the total expected contexts
+        /// </summary>
+        /// <param name="activeContext"></param>
+        internal void Add(IActiveContext activeContext)
+        {
+            if (_activeContexts.ContainsKey(activeContext.Id))
+            {
+                var msg = string.Format(CultureInfo.InvariantCulture, "The 
context [{0}] received already exists.", activeContext.Id);
+                Exceptions.Throw(new IMRUSystemException(msg), Logger);
+            }
+
+            if (NumberOfActiveContexts >= _totalExpectedContexts)
+            {
+                var msg = string.Format(CultureInfo.InvariantCulture, "Trying 
to add an extra active context {0}. The total number of the active contexts has 
reached to the expected number {1}.", activeContext.Id, _totalExpectedContexts);
+                Exceptions.Throw(new IMRUSystemException(msg), Logger);
+            }
+
+            _activeContexts.Add(activeContext.Id, activeContext);
+        }
+
+        /// <summary>
+        /// Remove an IActiveContext from the ActiveContext collection
+        /// Throw IMRUSystemException if the IActiveContext doesn't exist.
+        /// </summary>
+        /// <param name="activeContextId"></param>
+        internal void Remove(string activeContextId)
+        {
+            if (!_activeContexts.ContainsKey(activeContextId))
+            {
+                var msg = string.Format(CultureInfo.InvariantCulture, "The 
context [{0}] to be removed does not exist.", activeContextId);
+                Exceptions.Throw(new IMRUSystemException(msg), Logger);
+            }
+            _activeContexts.Remove(activeContextId);
+        }
+
+        /// <summary>
+        /// Returns the current number of IActiveContext in the ActiveContext 
collection
+        /// </summary>
+        internal int NumberOfActiveContexts
+        {
+            get { return _activeContexts.Count; }
+        }
+
+        /// <summary>
+        /// Given an IFailedEvaluator, remove associated IActiveContext from 
the collection
+        /// Throw IMRUSystemException if associated IActiveContext doesn't 
exist or
+        /// if more than one IActiveContexts are associated with the 
IFailedEvaluator
+        /// as current IMRU driver assumes that there is only one context 
associated with the IFailedEvalutor
+        /// </summary>
+        /// <param name="value"></param>
+        internal void RemoveFailedContextInFailedEvaluator(IFailedEvaluator 
value)
+        {
+            if (value.FailedContexts != null && value.FailedContexts.Count > 0)
+            {
+                if (value.FailedContexts.Count == 1)
+                {
+                    var failedContextId = value.FailedContexts[0].Id;
+                    if (!_activeContexts.Remove(failedContextId))
+                    {
+                        var msg = string.Format(CultureInfo.InvariantCulture,
+                            "The active context [{0}] attached in 
IFailedEvaluator [{1}] is not in the Active Contexts collection.",
+                            failedContextId,
+                            value.Id);
+                        Exceptions.Throw(new IMRUSystemException(msg), Logger);
+                    }
+                }
+                else
+                {
+                    var msg = string.Format(CultureInfo.InvariantCulture,
+                        "There are [{0}] contexts attached in the failed 
evaluator. Expected number is 1.",
+                        value.FailedContexts.Count);
+                    Exceptions.Throw(new IMRUSystemException(msg), Logger);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/reef/blob/4f786095/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 d893d49..958040a 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
@@ -70,6 +70,7 @@ under the License.
     <Compile Include="OnREEF\Client\REEFIMRUClient.cs" />
     <Compile Include="OnREEF\Driver\ConfigurationManager.cs" />
     <Compile Include="OnREEF\Driver\ContextAndServiceConfiguration.cs" />
+    <Compile Include="OnREEF\Driver\ActiveContextManager.cs" />
     <Compile Include="OnREEF\Driver\DataLoadingContext.cs" />
     <Compile 
Include="OnREEF\Driver\MaximumNumberOfEvalutorFailuresExceededException.cs" />
     <Compile Include="OnREEF\Driver\IMRUSystemException.cs" />

Reply via email to