Repository: reef Updated Branches: refs/heads/master f089f88bb -> f5fd01fc7
[REEF-1187] Support Services in REEF This addressed the issue by * Implement REEF Services and allow it to support both context and service stacking in C#. * Add unit tests for Services. JIRA: [REEF-1187](https://issues.apache.org/jira/browse/REEF-1187) This closes #834 Project: http://git-wip-us.apache.org/repos/asf/reef/repo Commit: http://git-wip-us.apache.org/repos/asf/reef/commit/f5fd01fc Tree: http://git-wip-us.apache.org/repos/asf/reef/tree/f5fd01fc Diff: http://git-wip-us.apache.org/repos/asf/reef/diff/f5fd01fc Branch: refs/heads/master Commit: f5fd01fc72f213aea027915029a16422ed0484d2 Parents: f089f88 Author: Andrew Chung <[email protected]> Authored: Mon Feb 1 17:00:11 2016 -0800 Committer: Julia Wang <[email protected]> Committed: Tue Feb 16 18:06:34 2016 -0800 ---------------------------------------------------------------------- .../Org.Apache.REEF.Common.csproj | 2 - .../Runtime/Evaluator/Context/ContextManager.cs | 6 +- .../Runtime/Evaluator/Context/ContextRuntime.cs | 88 ++++++--- .../Evaluator/Context/RootContextLauncher.cs | 35 ++-- .../Runtime/Evaluator/EvaluatorSettings.cs | 18 +- .../Org.Apache.REEF.Common/Services/IService.cs | 23 --- .../Services/ServiceConfiguration.cs | 32 +--- .../Services/ServicesConfigurationOptions.cs | 34 ---- .../Bridge/Events/AllocatedEvaluator.cs | 25 +-- .../ContextRuntimeTests.cs | 183 +++++++++++++++++-- .../EvaluatorConfigurationsTests.cs | 51 ------ .../KMeans/DataPartitionCache.cs | 2 +- .../Tasks/HelloTask/HelloService.cs | 3 +- .../GroupCommunication/GroupCommuDriverTests.cs | 16 +- .../NetworkService/INetworkService.cs | 3 +- .../NetworkService/NetworkService.cs | 2 - .../Attributes/TestingAttribute.cs | 30 +++ .../Org.Apache.Reef.Utilities.csproj | 1 + 18 files changed, 306 insertions(+), 248 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj b/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj index 35a4fee..22f5408 100644 --- a/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj +++ b/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj @@ -157,9 +157,7 @@ under the License. <Compile Include="Runtime\Evaluator\Task\TaskStopImpl.cs" /> <Compile Include="Runtime\Evaluator\Utils\NamedparameterAlias.cs" /> <Compile Include="runtime\MachineStatus.cs" /> - <Compile Include="Services\IService.cs" /> <Compile Include="Services\ServiceConfiguration.cs" /> - <Compile Include="Services\ServicesConfigurationOptions.cs" /> <Compile Include="Tasks\Defaults\DefaultDriverConnectionMessageHandler.cs" /> <Compile Include="Tasks\Defaults\DefaultDriverMessageHandler.cs" /> <Compile Include="Tasks\Defaults\DefaultTaskMessageSource.cs" /> http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextManager.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextManager.cs b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextManager.cs index 5f9b779..ef35f02 100644 --- a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextManager.cs +++ b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextManager.cs @@ -22,11 +22,9 @@ using System.Globalization; using System.Linq; using Org.Apache.REEF.Common.Protobuf.ReefProtocol; using Org.Apache.REEF.Common.Runtime.Evaluator.Task; -using Org.Apache.REEF.Common.Services; using Org.Apache.REEF.Common.Tasks; using Org.Apache.REEF.Tang.Annotations; using Org.Apache.REEF.Tang.Formats; -using Org.Apache.REEF.Tang.Interface; using Org.Apache.REEF.Utilities; using Org.Apache.REEF.Utilities.Logging; @@ -291,8 +289,8 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context ContextRuntime newTopContext; if (!string.IsNullOrWhiteSpace(addContextProto.service_configuration)) { - var serviceConfiguration = new ServiceConfiguration(addContextProto.service_configuration); - newTopContext = currentTopContext.SpawnChildContext(contextConfiguration, serviceConfiguration.TangConfig); + var serviceConfiguration = _serializer.FromString(addContextProto.service_configuration); + newTopContext = currentTopContext.SpawnChildContext(contextConfiguration, serviceConfiguration); } else { http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextRuntime.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextRuntime.cs b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextRuntime.cs index 0558c45..36566f5 100644 --- a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextRuntime.cs +++ b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextRuntime.cs @@ -21,9 +21,11 @@ using System.Globalization; using System.Linq; using Org.Apache.REEF.Common.Protobuf.ReefProtocol; using Org.Apache.REEF.Common.Runtime.Evaluator.Task; +using Org.Apache.REEF.Common.Services; using Org.Apache.REEF.Common.Tasks; using Org.Apache.REEF.Tang.Interface; using Org.Apache.REEF.Utilities; +using Org.Apache.REEF.Utilities.Attributes; using Org.Apache.REEF.Utilities.Logging; namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context @@ -47,6 +49,7 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context // Flag indicating whether the ContextRuntime was constructed with the deprecated Constructor or not.] // TODO[JIRA REEF-1167]: Remove variable. private readonly bool _deprecatedTaskStart; + private readonly Optional<ISet<object>> _injectedServices; // The child context, if any. private Optional<ContextRuntime> _childContext = Optional<ContextRuntime>.Empty(); @@ -68,6 +71,7 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context Optional<ContextRuntime> parentContext) { _serviceInjector = serviceInjector; + _injectedServices = Optional<ISet<object>>.Of(serviceInjector.GetNamedInstance<ServicesSet, ISet<object>>()); _contextInjector = serviceInjector.ForkInjector(contextConfiguration); _contextLifeCycle = _contextInjector.GetInstance<ContextLifeCycle>(); _parentContext = parentContext; @@ -93,6 +97,8 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context _contextLifeCycle = new ContextLifeCycle(id); _serviceInjector = serviceInjector; _parentContext = Optional<ContextRuntime>.Empty(); + _injectedServices = Optional<ISet<object>>.Empty(); + try { _contextInjector = serviceInjector.ForkInjector(); @@ -126,6 +132,30 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context } /// <summary> + /// For testing only! + /// </summary> + [Testing] + internal Optional<ISet<object>> Services + { + get + { + return _injectedServices; + } + } + + /// <summary> + /// For testing only! + /// </summary> + [Testing] + internal IInjector ContextInjector + { + get + { + return _contextInjector; + } + } + + /// <summary> /// Spawns a new context. /// The new context will have a serviceInjector that is created by forking the one in this object with the given /// serviceConfiguration. The contextConfiguration is used to fork the contextInjector from that new serviceInjector. @@ -139,16 +169,15 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context { if (_task.IsPresent()) { - // note: java code is putting thread id here - var e = new InvalidOperationException( - string.Format(CultureInfo.InvariantCulture, "Attempting to spawn a child context when an Task with id '{0}' is running", _task.Value.TaskId)); - Utilities.Diagnostics.Exceptions.Throw(e, LOGGER); - } - if (_childContext.IsPresent()) - { - var e = new InvalidOperationException("Attempting to instantiate a child context on a context that is not the topmost active context."); + var message = + string.Format(CultureInfo.InvariantCulture, "Attempting to spawn a child context when an Task with id '{0}' is running", _task.Value.TaskId); + + var e = new InvalidOperationException(message); Utilities.Diagnostics.Exceptions.Throw(e, LOGGER); } + + AssertChildContextNotPresent("Attempting to instantiate a child context on a context that is not the topmost active context."); + try { var childServiceInjector = _serviceInjector.ForkInjector(childServiceConfiguration); @@ -185,15 +214,15 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context { if (_task.IsPresent()) { - var e = new InvalidOperationException( - string.Format(CultureInfo.InvariantCulture, "Attempting to spawn a child context when an Task with id '{0}' is running", _task.Value.TaskId)); // note: java code is putting thread id here - Utilities.Diagnostics.Exceptions.Throw(e, LOGGER); - } - if (_childContext.IsPresent()) - { - var e = new InvalidOperationException("Attempting to instantiate a child context on a context that is not the topmost active context."); + var message = + string.Format(CultureInfo.InvariantCulture, "Attempting to spawn a child context when an Task with id '{0}' is running", _task.Value.TaskId); + + var e = new InvalidOperationException(message); Utilities.Diagnostics.Exceptions.Throw(e, LOGGER); } + + AssertChildContextNotPresent("Attempting to instantiate a child context on a context that is not the topmost active context."); + IInjector childServiceInjector = _serviceInjector.ForkInjector(); _childContext = Optional<ContextRuntime>.Of(new ContextRuntime(childServiceInjector, childContextConfiguration, Optional<ContextRuntime>.Of(this))); return _childContext.Value; @@ -231,11 +260,7 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context } } - if (_childContext.IsPresent()) - { - var e = new InvalidOperationException("Attempting to instantiate a child context on a context that is not the topmost active context."); - Utilities.Diagnostics.Exceptions.Throw(e, LOGGER); - } + AssertChildContextNotPresent("Attempting to instantiate a child context on a context that is not the topmost active context."); var taskInjector = _contextInjector.ForkInjector(taskConfiguration); @@ -299,6 +324,14 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context { ParentContext.Value.ResetChildContext(); } + + if (_injectedServices.IsPresent()) + { + foreach (var injectedService in _injectedServices.Value.OfType<IDisposable>()) + { + injectedService.Dispose(); + } + } } } @@ -359,12 +392,6 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context } } - [Obsolete("Deprecated in 0.14, please use HandleContextMessage instead.")] - public void HandleContextMessaage(byte[] message) - { - _contextLifeCycle.HandleContextMessage(message); - } - public void HandleContextMessage(byte[] message) { _contextLifeCycle.HandleContextMessage(message); @@ -478,5 +505,14 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context context = context.Value.ParentContext; } } + + private void AssertChildContextNotPresent(string message) + { + if (_childContext.IsPresent()) + { + var e = new InvalidOperationException(message); + Utilities.Diagnostics.Exceptions.Throw(e, LOGGER); + } + } } } http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/RootContextLauncher.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/RootContextLauncher.cs b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/RootContextLauncher.cs index f78e1b7..f3babd6 100644 --- a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/RootContextLauncher.cs +++ b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/RootContextLauncher.cs @@ -16,9 +16,9 @@ // under the License. using System; +using System.Collections.Generic; using System.Globalization; using Org.Apache.REEF.Common.Services; -using Org.Apache.REEF.Common.Tasks; using Org.Apache.REEF.Tang.Implementations.Tang; using Org.Apache.REEF.Tang.Interface; using Org.Apache.REEF.Tang.Util; @@ -32,16 +32,15 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context /// </summary> internal sealed class RootContextLauncher { - private static readonly Logger LOGGER = Logger.GetLogger(typeof(RootContextLauncher)); - - private readonly IInjector _rootServiceInjector = null; + private static readonly Logger Logger = Logger.GetLogger(typeof(RootContextLauncher)); + private readonly IInjector _rootServiceInjector; private readonly IConfiguration _rootContextConfiguration; - - private ContextRuntime _rootContext = null; + private ISet<object> _services; + private ContextRuntime _rootContext; public RootContextLauncher(string id, IConfiguration contextConfiguration, - Optional<ServiceConfiguration> rootServiceConfig, Optional<IConfiguration> rootTaskConfig, IHeartBeatManager heartbeatManager) + Optional<IConfiguration> rootServiceConfig, Optional<IConfiguration> rootTaskConfig, IHeartBeatManager heartbeatManager) { Id = id; _rootContextConfiguration = contextConfiguration; @@ -62,7 +61,7 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context var deprecatedContextConfiguration = _rootContextConfiguration as ContextConfiguration; if (deprecatedContextConfiguration != null) { - LOGGER.Log(Level.Info, "Using deprecated ContextConfiguration."); + Logger.Log(Level.Info, "Using deprecated ContextConfiguration."); _rootContext = new ContextRuntime(Id, _rootServiceInjector, _rootContextConfiguration); } else @@ -73,31 +72,33 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context return _rootContext; } - private static IInjector InjectServices(Optional<ServiceConfiguration> serviceConfig) + private IInjector InjectServices(Optional<IConfiguration> serviceConfig) { // TODO[JIRA REEF-217]: Use base injector for the Evaluator here instead. IInjector rootServiceInjector; if (serviceConfig.IsPresent()) { - rootServiceInjector = TangFactory.GetTang().NewInjector(serviceConfig.Value.TangConfig); - InjectedServices services = null; + rootServiceInjector = TangFactory.GetTang().NewInjector(serviceConfig.Value); try { - services = rootServiceInjector.GetInstance<InjectedServices>(); + _services = rootServiceInjector.GetNamedInstance<ServicesSet, ISet<object>>(); + Logger.Log(Level.Info, string.Format(CultureInfo.InvariantCulture, "injected service(s)")); } catch (Exception e) { - Utilities.Diagnostics.Exceptions.Caught(e, Level.Error, "Failed to instantiate service.", LOGGER); - InvalidOperationException ex = new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Failed to inject service: encoutned error {1} with message [{0}] and stack trace:[{1}]", e, e.Message, e.StackTrace)); - Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER); + var errorMessage = string.Format(CultureInfo.InvariantCulture, + "Failed to inject service: encountered error {1} with message [{0}] and stack trace:[{2}]", e, + e.Message, e.StackTrace); + Utilities.Diagnostics.Exceptions.Caught(e, Level.Error, "Failed to instantiate service.", Logger); + var ex = new InvalidOperationException(errorMessage, e); + Utilities.Diagnostics.Exceptions.Throw(ex, Logger); } - LOGGER.Log(Level.Info, string.Format(CultureInfo.InvariantCulture, "injected {0} service(s)", services.Services.Count)); } else { rootServiceInjector = TangFactory.GetTang().NewInjector(); - LOGGER.Log(Level.Info, "no service provided for injection."); + Logger.Log(Level.Info, "no service provided for injection."); } return rootServiceInjector; http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/EvaluatorSettings.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/EvaluatorSettings.cs b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/EvaluatorSettings.cs index c9b2a35..36cce11 100644 --- a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/EvaluatorSettings.cs +++ b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/EvaluatorSettings.cs @@ -22,7 +22,6 @@ using Org.Apache.REEF.Common.Io; using Org.Apache.REEF.Common.Protobuf.ReefProtocol; using Org.Apache.REEF.Common.Runtime.Evaluator.Parameters; using Org.Apache.REEF.Common.Runtime.Evaluator.Utils; -using Org.Apache.REEF.Common.Services; using Org.Apache.REEF.Tang.Annotations; using Org.Apache.REEF.Tang.Exceptions; using Org.Apache.REEF.Tang.Formats; @@ -50,7 +49,7 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator private readonly IConfiguration _rootContextConfig; private readonly AvroConfigurationSerializer _serializer; private readonly Optional<IConfiguration> _rootTaskConfiguration; - private readonly Optional<ServiceConfiguration> _rootServiceConfiguration; + private readonly Optional<IConfiguration> _rootServiceConfiguration; private EvaluatorOperationState _operationState; private INameClient _nameClient; @@ -223,7 +222,7 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator /// <summary> /// return Root Service Configuration passed from Evaluator configuration /// </summary> - public Optional<ServiceConfiguration> RootServiceConfiguration + public Optional<IConfiguration> RootServiceConfiguration { get { return _rootServiceConfiguration; } } @@ -293,7 +292,7 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator : Optional<IConfiguration>.Of(_serializer.FromString(taskConfigString)); } - private Optional<ServiceConfiguration> CreateRootServiceConfiguration() + private Optional<IConfiguration> CreateRootServiceConfiguration() { string rootServiceConfigString = null; try @@ -304,10 +303,13 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator { Logger.Log(Level.Info, "RootServiceConfiguration is not set in Evaluator.config."); } - return string.IsNullOrEmpty(rootServiceConfigString) - ? Optional<ServiceConfiguration>.Empty() - : Optional<ServiceConfiguration>.Of( - new ServiceConfiguration(rootServiceConfigString)); + + if (string.IsNullOrEmpty(rootServiceConfigString)) + { + return Optional<IConfiguration>.Empty(); + } + + return Optional<IConfiguration>.Of(_serializer.FromString(rootServiceConfigString)); } } } http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Common/Services/IService.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Services/IService.cs b/lang/cs/Org.Apache.REEF.Common/Services/IService.cs deleted file mode 100644 index a624de0..0000000 --- a/lang/cs/Org.Apache.REEF.Common/Services/IService.cs +++ /dev/null @@ -1,23 +0,0 @@ -// 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.Common.Services -{ - public interface IService - { - } -} http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Common/Services/ServiceConfiguration.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Services/ServiceConfiguration.cs b/lang/cs/Org.Apache.REEF.Common/Services/ServiceConfiguration.cs index c1a2165..2aadc97 100644 --- a/lang/cs/Org.Apache.REEF.Common/Services/ServiceConfiguration.cs +++ b/lang/cs/Org.Apache.REEF.Common/Services/ServiceConfiguration.cs @@ -19,8 +19,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Org.Apache.REEF.Tang.Annotations; using Org.Apache.REEF.Tang.Formats; -using Org.Apache.REEF.Tang.Implementations.Tang; -using Org.Apache.REEF.Tang.Interface; using Org.Apache.REEF.Tang.Util; [module: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:FieldsMustBePrivate", Justification = "static field, typical usage in configurations")] @@ -39,22 +37,7 @@ namespace Org.Apache.REEF.Common.Services /// will be made available to child context and tasks. /// </summary> [SuppressMessage("Microsoft.Security", "CA2104:Do not declare read only mutable reference types", Justification = "not applicable")] - public static readonly OptionalParameter<IService> Services = new OptionalParameter<IService>(); - - public ServiceConfiguration() - { - } - - public ServiceConfiguration(string config) - { - AvroConfigurationSerializer serializer = new AvroConfigurationSerializer(); - - string serviceConfigString = (string)TangFactory.GetTang() - .NewInjector(serializer.FromString(config)) - .GetNamedInstance(typeof(ServicesConfigurationOptions.ServiceConfigString)); - - TangConfig = serializer.FromString(serviceConfigString); - } + public static readonly OptionalParameter<object> Services = new OptionalParameter<object>(); public static ConfigurationModule ConfigurationModule { @@ -66,22 +49,13 @@ namespace Org.Apache.REEF.Common.Services } } - public IConfiguration TangConfig { get; private set; } - } - - public class InjectedServices - { - [Inject] - public InjectedServices([Parameter(typeof(ServicesSet))] ISet<IService> services) + private ServiceConfiguration() { - Services = services; } - - public ISet<IService> Services { get; set; } } [NamedParameter("Set of services", "servicesSet")] - class ServicesSet : Name<ISet<IService>> + class ServicesSet : Name<ISet<object>> { } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Common/Services/ServicesConfigurationOptions.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Services/ServicesConfigurationOptions.cs b/lang/cs/Org.Apache.REEF.Common/Services/ServicesConfigurationOptions.cs deleted file mode 100644 index c4c5165..0000000 --- a/lang/cs/Org.Apache.REEF.Common/Services/ServicesConfigurationOptions.cs +++ /dev/null @@ -1,34 +0,0 @@ -// 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 Org.Apache.REEF.Tang.Annotations; - -namespace Org.Apache.REEF.Common.Services -{ - public class ServicesConfigurationOptions - { - [NamedParameter("Services", "services", "services")] - public class Services : Name<string> - { - } - - [NamedParameter] - public class ServiceConfigString : Name<string> - { - } - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Driver/Bridge/Events/AllocatedEvaluator.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Driver/Bridge/Events/AllocatedEvaluator.cs b/lang/cs/Org.Apache.REEF.Driver/Bridge/Events/AllocatedEvaluator.cs index 9b5d402..694391c 100644 --- a/lang/cs/Org.Apache.REEF.Driver/Bridge/Events/AllocatedEvaluator.cs +++ b/lang/cs/Org.Apache.REEF.Driver/Bridge/Events/AllocatedEvaluator.cs @@ -17,19 +17,14 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Runtime.Serialization; using Org.Apache.REEF.Common.Catalog; using Org.Apache.REEF.Common.Evaluator; -using Org.Apache.REEF.Common.Services; using Org.Apache.REEF.Driver.Bridge.Clr2java; -using Org.Apache.REEF.Driver.Context; using Org.Apache.REEF.Driver.Evaluator; using Org.Apache.REEF.Tang.Formats; using Org.Apache.REEF.Tang.Implementations.Configuration; -using Org.Apache.REEF.Tang.Implementations.Tang; using Org.Apache.REEF.Tang.Interface; -using Org.Apache.REEF.Tang.Util; using Org.Apache.REEF.Utilities.Logging; namespace Org.Apache.REEF.Driver.Bridge.Events @@ -108,7 +103,7 @@ namespace Org.Apache.REEF.Driver.Bridge.Events var serviceConf = MergeWithConfigurationProviders(serviceConfiguration); string context = _serializer.ToString(contextConfiguration); - string service = _serializer.ToString(WrapServiceConfigAsString(serviceConf)); + string service = _serializer.ToString(serviceConf); LOGGER.Log(Level.Verbose, "serialized contextConfiguration: " + context); LOGGER.Log(Level.Verbose, "serialized serviceConfiguration: " + service); @@ -122,7 +117,7 @@ namespace Org.Apache.REEF.Driver.Bridge.Events var serviceConf = MergeWithConfigurationProviders(serviceConfiguration); string context = _serializer.ToString(contextConfiguration); - string service = _serializer.ToString(WrapServiceConfigAsString(serviceConf)); + string service = _serializer.ToString(serviceConf); string task = _serializer.ToString(taskConfiguration); LOGGER.Log(Level.Verbose, "serialized contextConfiguration: " + context); @@ -196,21 +191,5 @@ namespace Org.Apache.REEF.Driver.Bridge.Events } return config; } - - /// <summary> - /// This is to wrap entire service configuration in to a serialized string - /// At evaluator side, we will unwrap it to get the original Service Configuration string - /// It is to avoid issues that some C# class Node are dropped in the deserialized ClassHierarchy by Goold ProtoBuffer deserializer - /// </summary> - /// <param name="serviceConfiguration"></param> - /// <returns></returns> - private IConfiguration WrapServiceConfigAsString(IConfiguration serviceConfiguration) - { - return TangFactory.GetTang().NewConfigurationBuilder() - .BindNamedParameter<ServicesConfigurationOptions.ServiceConfigString, string>( - GenericType<ServicesConfigurationOptions.ServiceConfigString>.Class, - new AvroConfigurationSerializer().ToString(serviceConfiguration)) - .Build(); - } } } http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Evaluator.Tests/ContextRuntimeTests.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Evaluator.Tests/ContextRuntimeTests.cs b/lang/cs/Org.Apache.REEF.Evaluator.Tests/ContextRuntimeTests.cs index a462940..2adae71 100644 --- a/lang/cs/Org.Apache.REEF.Evaluator.Tests/ContextRuntimeTests.cs +++ b/lang/cs/Org.Apache.REEF.Evaluator.Tests/ContextRuntimeTests.cs @@ -16,12 +16,17 @@ // under the License. using System; +using System.Collections.Generic; +using System.Linq; using System.Text; using Org.Apache.REEF.Common.Context; using Org.Apache.REEF.Common.Events; using Org.Apache.REEF.Common.Runtime.Evaluator.Context; +using Org.Apache.REEF.Common.Services; using Org.Apache.REEF.Tang.Annotations; +using Org.Apache.REEF.Tang.Implementations.Configuration; using Org.Apache.REEF.Tang.Implementations.Tang; +using Org.Apache.REEF.Tang.Interface; using Org.Apache.REEF.Tang.Util; using Org.Apache.REEF.Utilities; using Xunit; @@ -37,17 +42,11 @@ namespace Org.Apache.REEF.Evaluator.Tests public void TestContextEvents() { const string hello = "Hello!"; - var contextConfig = ContextConfiguration.ConfigurationModule - .Set(ContextConfiguration.Identifier, "ID") - .Set(ContextConfiguration.OnContextStart, GenericType<ContextEventHandler>.Class) - .Set(ContextConfiguration.OnContextStop, GenericType<ContextEventHandler>.Class) - .Set(ContextConfiguration.OnMessage, GenericType<ContextEventHandler>.Class) - .Build(); - + var contextConfig = GetContextEventHandlerContextConfiguration(); var injector = TangFactory.GetTang().NewInjector(); - var handler = new ContextEventHandler(); - injector.BindVolatileInstance(GenericType<ContextEventHandler>.Class, handler); + var handler = new TestContextEventHandler(); + injector.BindVolatileInstance(GenericType<TestContextEventHandler>.Class, handler); using (var contextRuntime = new ContextRuntime(injector, contextConfig, Optional<ContextRuntime>.Empty())) @@ -60,11 +59,173 @@ namespace Org.Apache.REEF.Evaluator.Tests Assert.Equal(Encoding.UTF8.GetString(handler.MessageReceived), hello); } - private sealed class ContextEventHandler + [Fact] + [Trait("Priority", "0")] + [Trait("Category", "Unit")] + public void TestContextBindServiceBoundInterfaceThrowsException() + { + var boundTestServiceConfig = TangFactory.GetTang() + .NewConfigurationBuilder() + .BindImplementation(GenericType<ITestService>.Class, GenericType<TestService>.Class) + .Build(); + + var serviceConfiguration = ServiceConfiguration.ConfigurationModule.Build(); + var serviceInjector = TangFactory.GetTang().NewInjector(Configurations.Merge(serviceConfiguration, boundTestServiceConfig)); + var contextConfig = Configurations.Merge(GetContextEventHandlerContextConfiguration(), boundTestServiceConfig); + + var ex = Record.Exception(() => new ContextRuntime(serviceInjector, contextConfig, Optional<ContextRuntime>.Empty())); + + // This should throw an Exception because we are binding the interface ITestService twice, once in serviceConfiguration + // and once in contextConfiguration. The Context injector is forked from the ServiceInjector, which already has the + // interface bound. + Assert.True(ex != null); + } + + [Fact] + [Trait("Priority", "0")] + [Trait("Category", "Unit")] + public void TestServiceInstantiatedAndDisposed() + { + var serviceConfiguration = ServiceConfiguration.ConfigurationModule + .Set(ServiceConfiguration.Services, GenericType<TestService>.Class) + .Build(); + + var serviceInjector = TangFactory.GetTang().NewInjector(serviceConfiguration); + var contextConfig = GetContextEventHandlerContextConfiguration(); + + TestService testService; + using (var contextRuntime = new ContextRuntime(serviceInjector, contextConfig, Optional<ContextRuntime>.Empty())) + { + var servicesFromInjector = serviceInjector.GetNamedInstance<ServicesSet, ISet<object>>(); + testService = servicesFromInjector.Single() as TestService; + Assert.NotNull(testService); + if (testService == null) + { + // Not possible + return; + } + + var testServiceFromInjector = serviceInjector.GetInstance<TestService>(); + Assert.True(ReferenceEquals(testService, testServiceFromInjector)); + + var contextTestService = contextRuntime.ContextInjector.GetInstance<TestService>(); + Assert.True(ReferenceEquals(contextTestService, testServiceFromInjector)); + } + + Assert.True(testService.Disposed); + } + + [Fact] + [Trait("Priority", "0")] + [Trait("Category", "Unit")] + public void TestBaseServiceWithContextStacking() + { + var serviceConfiguration = ServiceConfiguration.ConfigurationModule + .Set(ServiceConfiguration.Services, GenericType<TestService>.Class) + .Build(); + + var serviceInjector = TangFactory.GetTang().NewInjector(serviceConfiguration); + var contextConfig = GetContextEventHandlerContextConfiguration(); + + using (var contextRuntime = new ContextRuntime(serviceInjector, contextConfig, Optional<ContextRuntime>.Empty())) + { + var childContextConfiguration = ContextConfiguration.ConfigurationModule + .Set(ContextConfiguration.Identifier, "Context2") + .Build(); + + using (var childContextRuntime = contextRuntime.SpawnChildContext(childContextConfiguration)) + { + var servicesFromInjector = serviceInjector.GetNamedInstance<ServicesSet, ISet<object>>(); + + // Check that parent service injector does not contain instances of SecondTestService + Assert.False(servicesFromInjector.OfType<SecondTestService>().Any()); + + var contextTestService = childContextRuntime.ContextInjector.GetInstance<TestService>(); + Assert.True(ReferenceEquals(contextTestService, serviceInjector.GetInstance<TestService>())); + } + } + } + + [Fact] + [Trait("Priority", "0")] + [Trait("Category", "Unit")] + public void TestServiceStacking() + { + var serviceConfiguration = ServiceConfiguration.ConfigurationModule + .Set(ServiceConfiguration.Services, GenericType<TestService>.Class) + .Build(); + + var serviceInjector = TangFactory.GetTang().NewInjector(serviceConfiguration); + var contextConfig = GetContextEventHandlerContextConfiguration(); + + using (var contextRuntime = new ContextRuntime(serviceInjector, contextConfig, Optional<ContextRuntime>.Empty())) + { + var childContextConfiguration = ContextConfiguration.ConfigurationModule + .Set(ContextConfiguration.Identifier, "Context2") + .Build(); + + var childServiceConfiguration = ServiceConfiguration.ConfigurationModule + .Set(ServiceConfiguration.Services, GenericType<SecondTestService>.Class) + .Build(); + + using (var childContextRuntime = contextRuntime.SpawnChildContext(childContextConfiguration, childServiceConfiguration)) + { + // Check that parent service injector does not contain instances of SecondTestService + Assert.False(contextRuntime.Services.Value.OfType<SecondTestService>().Any()); + Assert.True(childContextRuntime.Services.Value.OfType<TestService>().Count() == 1); + Assert.True(childContextRuntime.Services.Value.OfType<SecondTestService>().Count() == 1); + Assert.True(childContextRuntime.Services.Value.Count() == 2); + Assert.True(ReferenceEquals( + childContextRuntime.ContextInjector.GetInstance<TestService>(), + contextRuntime.Services.Value.OfType<TestService>().Single())); + } + } + } + + private static IConfiguration GetContextEventHandlerContextConfiguration() + { + return ContextConfiguration.ConfigurationModule + .Set(ContextConfiguration.Identifier, "ID") + .Set(ContextConfiguration.OnContextStart, GenericType<TestContextEventHandler>.Class) + .Set(ContextConfiguration.OnContextStop, GenericType<TestContextEventHandler>.Class) + .Set(ContextConfiguration.OnMessage, GenericType<TestContextEventHandler>.Class) + .Build(); + } + + private interface ITestService + { + // empty + } + + private sealed class TestService : ITestService, IDisposable + { + [Inject] + private TestService() + { + Disposed = false; + } + + public bool Disposed { get; private set; } + + public void Dispose() + { + Disposed = true; + } + } + + private sealed class SecondTestService + { + [Inject] + private SecondTestService() + { + } + } + + private sealed class TestContextEventHandler : IObserver<IContextStart>, IObserver<IContextStop>, IContextMessageHandler { [Inject] - public ContextEventHandler() + public TestContextEventHandler() { } http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Evaluator.Tests/EvaluatorConfigurationsTests.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Evaluator.Tests/EvaluatorConfigurationsTests.cs b/lang/cs/Org.Apache.REEF.Evaluator.Tests/EvaluatorConfigurationsTests.cs index 410a1dc..042752c 100644 --- a/lang/cs/Org.Apache.REEF.Evaluator.Tests/EvaluatorConfigurationsTests.cs +++ b/lang/cs/Org.Apache.REEF.Evaluator.Tests/EvaluatorConfigurationsTests.cs @@ -130,56 +130,5 @@ namespace Org.Apache.REEF.Evaluator.Tests Assert.True(taskId.StartsWith("HelloTask")); Assert.True(task is HelloTask); } - - /// <summary> - /// This test is to deserialize a evaluator configuration file using alias if the parameter cannot be - /// found in the class hierarchy. The config file used in the test was generated when running TestBroadCastReduceOperators. - /// It contains service and context configuration strings. - /// </summary> - [Fact] - [Trait("Priority", "0")] - [Trait("Category", "Unit")] - public void TestDeserializationForServiceAndContext() - { - AvroConfigurationSerializer serializer = new AvroConfigurationSerializer(); - - var classHierarchy = TangFactory.GetTang() - .GetClassHierarchy(new string[] { typeof(ApplicationIdentifier).Assembly.GetName().Name }); - var config = serializer.FromFile("evaluatorWithService.conf", classHierarchy); - - IInjector evaluatorInjector = TangFactory.GetTang().NewInjector(config); - - string contextConfigString = evaluatorInjector.GetNamedInstance<RootContextConfiguration, string>(); - string rootServiceConfigString = evaluatorInjector.GetNamedInstance<RootServiceConfiguration, string>(); - - var contextClassHierarchy = TangFactory.GetTang().GetClassHierarchy(new string[] - { - typeof(ContextConfigurationOptions.ContextIdentifier).Assembly.GetName().Name - }); - - var contextConfig = serializer.FromString(contextConfigString, contextClassHierarchy); - - var serviceClassHierarchy = TangFactory.GetTang().GetClassHierarchy(new string[] - { - typeof(ServicesConfigurationOptions).Assembly.GetName().Name, - typeof(IStreamingCodec<>).Assembly.GetName().Name - }); - var rootServiceConfig = serializer.FromString(rootServiceConfigString, serviceClassHierarchy); - - var contextInjector = evaluatorInjector.ForkInjector(contextConfig); - string contextId = contextInjector.GetNamedInstance<ContextConfigurationOptions.ContextIdentifier, string>(); - Assert.True(contextId.StartsWith("MasterTaskContext")); - - string serviceConfigString = TangFactory.GetTang().NewInjector(rootServiceConfig) - .GetNamedInstance<ServicesConfigurationOptions.ServiceConfigString, string>(); - - var serviceConfig = serializer.FromString(serviceConfigString, serviceClassHierarchy); - - var serviceInjector = contextInjector.ForkInjector(serviceConfig); - var tcpCountRange = serviceInjector.GetNamedInstance<TcpPortRangeStart, int>(); - var tcpCountCount = serviceInjector.GetNamedInstance<TcpPortRangeCount, int>(); - Assert.True(tcpCountRange > 0); - Assert.True(tcpCountCount > 0); - } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Examples/MachineLearning/KMeans/DataPartitionCache.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Examples/MachineLearning/KMeans/DataPartitionCache.cs b/lang/cs/Org.Apache.REEF.Examples/MachineLearning/KMeans/DataPartitionCache.cs index 48e1d2f..4c60a0f 100644 --- a/lang/cs/Org.Apache.REEF.Examples/MachineLearning/KMeans/DataPartitionCache.cs +++ b/lang/cs/Org.Apache.REEF.Examples/MachineLearning/KMeans/DataPartitionCache.cs @@ -25,7 +25,7 @@ using Org.Apache.REEF.Utilities.Logging; namespace Org.Apache.REEF.Examples.MachineLearning.KMeans { // TODO: we should outsource some of the functionalites to a data loader implemenation - public class DataPartitionCache : IService + public class DataPartitionCache { private static readonly Logger _Logger = Logger.GetLogger(typeof(DataPartitionCache)); http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Examples/Tasks/HelloTask/HelloService.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Examples/Tasks/HelloTask/HelloService.cs b/lang/cs/Org.Apache.REEF.Examples/Tasks/HelloTask/HelloService.cs index b0cfbd1..ab78194 100644 --- a/lang/cs/Org.Apache.REEF.Examples/Tasks/HelloTask/HelloService.cs +++ b/lang/cs/Org.Apache.REEF.Examples/Tasks/HelloTask/HelloService.cs @@ -17,12 +17,11 @@ using System; using System.Collections.Generic; -using Org.Apache.REEF.Common.Services; using Org.Apache.REEF.Tang.Annotations; namespace Org.Apache.REEF.Examples.Tasks.HelloTask { - public class HelloService : IService + public class HelloService { private readonly IList<string> _guests; http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Network.Tests/GroupCommunication/GroupCommuDriverTests.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Network.Tests/GroupCommunication/GroupCommuDriverTests.cs b/lang/cs/Org.Apache.REEF.Network.Tests/GroupCommunication/GroupCommuDriverTests.cs index 8414ff6..db4fe32 100644 --- a/lang/cs/Org.Apache.REEF.Network.Tests/GroupCommunication/GroupCommuDriverTests.cs +++ b/lang/cs/Org.Apache.REEF.Network.Tests/GroupCommunication/GroupCommuDriverTests.cs @@ -15,13 +15,9 @@ // specific language governing permissions and limitations // under the License. -using Org.Apache.REEF.Common.Services; using Org.Apache.REEF.Network.Group.Config; -using Org.Apache.REEF.Tang.Exceptions; using Org.Apache.REEF.Tang.Formats; using Org.Apache.REEF.Tang.Implementations.Configuration; -using Org.Apache.REEF.Tang.Implementations.Tang; -using Org.Apache.REEF.Tang.Interface; using Org.Apache.REEF.Tang.Util; using Org.Apache.REEF.Wake.Remote.Impl; using Xunit; @@ -52,18 +48,12 @@ namespace Org.Apache.REEF.Network.Tests.GroupCommunication var driverServiceConfig = groupCommunicationDriver.GetServiceConfiguration(); var serviceConfig = Configurations.Merge(driverServiceConfig, codecConfig); - // wrap it before serializing - var wrappedSeriveConfig = TangFactory.GetTang().NewConfigurationBuilder() - .BindNamedParameter<ServicesConfigurationOptions.ServiceConfigString, string>( - GenericType<ServicesConfigurationOptions.ServiceConfigString>.Class, - new AvroConfigurationSerializer().ToString(serviceConfig)) - .Build(); - var serviceConfigString = serializer.ToString(wrappedSeriveConfig); + var serviceConfigString = serializer.ToString(serviceConfig); // the configuration string is received at Evaluator side - var serviceConfig2 = new ServiceConfiguration(serviceConfigString); + var serviceConfig2 = new AvroConfigurationSerializer().FromString(serviceConfigString); - Assert.Equal(serializer.ToString(serviceConfig), serializer.ToString(serviceConfig2.TangConfig)); + Assert.Equal(serializer.ToString(serviceConfig), serializer.ToString(serviceConfig2)); } } } http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Network/NetworkService/INetworkService.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Network/NetworkService/INetworkService.cs b/lang/cs/Org.Apache.REEF.Network/NetworkService/INetworkService.cs index 112aefb..9536d39 100644 --- a/lang/cs/Org.Apache.REEF.Network/NetworkService/INetworkService.cs +++ b/lang/cs/Org.Apache.REEF.Network/NetworkService/INetworkService.cs @@ -17,7 +17,6 @@ using System; using Org.Apache.REEF.Common.Io; -using Org.Apache.REEF.Common.Services; using Org.Apache.REEF.Wake; namespace Org.Apache.REEF.Network.NetworkService @@ -26,7 +25,7 @@ namespace Org.Apache.REEF.Network.NetworkService /// Network service used for Reef Task communication. /// </summary> /// <typeparam name="T">The message type</typeparam> - public interface INetworkService<T> : IService, IDisposable + public interface INetworkService<T> : IDisposable { /// <summary> /// Name client for registering ids http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Network/NetworkService/NetworkService.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Network/NetworkService/NetworkService.cs b/lang/cs/Org.Apache.REEF.Network/NetworkService/NetworkService.cs index 705c551..f63782d 100644 --- a/lang/cs/Org.Apache.REEF.Network/NetworkService/NetworkService.cs +++ b/lang/cs/Org.Apache.REEF.Network/NetworkService/NetworkService.cs @@ -19,14 +19,12 @@ using System; using System.Collections.Generic; using System.Net; using Org.Apache.REEF.Common.Io; -using Org.Apache.REEF.Network.Naming; using Org.Apache.REEF.Network.NetworkService.Codec; using Org.Apache.REEF.Tang.Annotations; using Org.Apache.REEF.Tang.Exceptions; using Org.Apache.REEF.Utilities.Logging; using Org.Apache.REEF.Wake; using Org.Apache.REEF.Wake.Remote; -using Org.Apache.REEF.Wake.Remote.Impl; using Org.Apache.REEF.Wake.Util; namespace Org.Apache.REEF.Network.NetworkService http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Utilities/Attributes/TestingAttribute.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Utilities/Attributes/TestingAttribute.cs b/lang/cs/Org.Apache.REEF.Utilities/Attributes/TestingAttribute.cs new file mode 100644 index 0000000..2d2b6ae --- /dev/null +++ b/lang/cs/Org.Apache.REEF.Utilities/Attributes/TestingAttribute.cs @@ -0,0 +1,30 @@ +// 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; + +namespace Org.Apache.REEF.Utilities.Attributes +{ + /// <summary> + /// Attribute target should only be used in tests. + /// </summary> + [AttributeUsage(AttributeTargets.All)] + public sealed class TestingAttribute : Attribute + { + // Intentionally empty. + } +} http://git-wip-us.apache.org/repos/asf/reef/blob/f5fd01fc/lang/cs/Org.Apache.REEF.Utilities/Org.Apache.Reef.Utilities.csproj ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Utilities/Org.Apache.Reef.Utilities.csproj b/lang/cs/Org.Apache.REEF.Utilities/Org.Apache.Reef.Utilities.csproj index 4576cd6..5d5129c 100644 --- a/lang/cs/Org.Apache.REEF.Utilities/Org.Apache.Reef.Utilities.csproj +++ b/lang/cs/Org.Apache.REEF.Utilities/Org.Apache.Reef.Utilities.csproj @@ -45,6 +45,7 @@ under the License. <Compile Include="Attributes\InteropAttribute.cs" /> <Compile Include="Attributes\PrivateAttribute.cs" /> <Compile Include="Attributes\TaskSideAttribute.cs" /> + <Compile Include="Attributes\TestingAttribute.cs" /> <Compile Include="Attributes\UnstableAttribute.cs" /> <Compile Include="AvroUtils.cs" /> <Compile Include="ByteUtilities.cs" />
