From 4ee8de76cf209284543685df1e3fe0fde27db51a Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Fri, 7 Aug 2015 15:42:05 -0700 Subject: [PATCH 001/105] placeholder for next maintenance release --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 05d54cfef9a..ad90545c6f4 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,5 @@ +#### 1.0.5 August 07 2015 #### + #### 1.0.4 August 07 2015 #### **Maintenance release for Akka.NET v1.0.3** From 75f966cb7d2f2c0d859e0e3a90a38d251a10c5e5 Mon Sep 17 00:00:00 2001 From: Suhas Chatekar Date: Sat, 8 Aug 2015 10:36:36 +0100 Subject: [PATCH 002/105] #1088 MultiNode tests can now be skipped by specifying a SkipReason --- src/core/Akka.MultiNodeTestRunner.Shared/NodeTest.cs | 1 + src/core/Akka.MultiNodeTestRunner/Discovery.cs | 3 ++- src/core/Akka.MultiNodeTestRunner/Program.cs | 6 ++++++ src/core/Akka.MultiNodeTests/MultiNodeFact.cs | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/NodeTest.cs b/src/core/Akka.MultiNodeTestRunner.Shared/NodeTest.cs index 8c30218f9eb..509f763aa6e 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared/NodeTest.cs +++ b/src/core/Akka.MultiNodeTestRunner.Shared/NodeTest.cs @@ -13,6 +13,7 @@ public class NodeTest public string TestName { get; set; } public string TypeName { get; set; } public string MethodName { get; set; } + public string SkipReason { get; set; } } } diff --git a/src/core/Akka.MultiNodeTestRunner/Discovery.cs b/src/core/Akka.MultiNodeTestRunner/Discovery.cs index 1e482e2fc1c..3dc0021f962 100644 --- a/src/core/Akka.MultiNodeTestRunner/Discovery.cs +++ b/src/core/Akka.MultiNodeTestRunner/Discovery.cs @@ -65,7 +65,8 @@ private NodeTest GetTestDetails(ITestCaseDiscoveryMessage nodeTest) Node = Convert.ToInt32(matches.Groups[2].Value), TestName = matches.Groups[1].Value, TypeName = nodeTest.TestClass.Class.Name, - MethodName = nodeTest.TestCase.TestMethod.Method.Name + MethodName = nodeTest.TestCase.TestMethod.Method.Name, + SkipReason = nodeTest.TestCase.SkipReason }; } diff --git a/src/core/Akka.MultiNodeTestRunner/Program.cs b/src/core/Akka.MultiNodeTestRunner/Program.cs index ed550daf0e2..9a1cb74a6b2 100644 --- a/src/core/Akka.MultiNodeTestRunner/Program.cs +++ b/src/core/Akka.MultiNodeTestRunner/Program.cs @@ -75,6 +75,12 @@ static void Main(string[] args) foreach (var test in discovery.Tests.Reverse()) { + if (!string.IsNullOrEmpty(test.Value.First().SkipReason)) + { + PublishRunnerMessage(string.Format("Skipping test {0}. Reason - {1}", test.Value.First().MethodName, test.Value.First().SkipReason)); + continue; + } + PublishRunnerMessage(string.Format("Starting test {0}", test.Value.First().MethodName)); var processes = new List(); diff --git a/src/core/Akka.MultiNodeTests/MultiNodeFact.cs b/src/core/Akka.MultiNodeTests/MultiNodeFact.cs index d8a0d8cbb82..1f21a7fcffc 100644 --- a/src/core/Akka.MultiNodeTests/MultiNodeFact.cs +++ b/src/core/Akka.MultiNodeTests/MultiNodeFact.cs @@ -27,7 +27,7 @@ public override string Skip get { return ExecutedByMultiNodeRunner.Value - ? null + ? base.Skip : "Must be executed by multi-node test runner"; } set { base.Skip = value; } From 2ed1d574f76491707deac236db3fd7c1e5af5757 Mon Sep 17 00:00:00 2001 From: evertmulder Date: Sat, 8 Aug 2015 15:02:25 +0200 Subject: [PATCH 003/105] Bugfix: Make the Put on the SimpleDnsCache idempotent Bugfix for the exception: itemwith the same key has already been added. Make the Put on the SimpleDnsCache idempotent when a same host is resolved. --- src/core/Akka.Tests/IO/SimpleDnsCacheSpec.cs | 14 ++++++++++++++ src/core/Akka/IO/SimpleDnsCache.cs | 5 ++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/core/Akka.Tests/IO/SimpleDnsCacheSpec.cs b/src/core/Akka.Tests/IO/SimpleDnsCacheSpec.cs index bc003ba9112..9a518b3572f 100644 --- a/src/core/Akka.Tests/IO/SimpleDnsCacheSpec.cs +++ b/src/core/Akka.Tests/IO/SimpleDnsCacheSpec.cs @@ -65,5 +65,19 @@ public void Cache_should_sweep_out_expired_entries_on_cleanup() cache.Cached("test.local").ShouldBe(null); } + + [Fact] + public void Cache_should_be_updated_with_the_latest_resolved() + { + var localClock = new AtomicReference(0); + var cache = new SimpleDnsCacheTestDouble(localClock); + var cacheEntryOne = Dns.Resolved.Create("test.local", System.Net.Dns.GetHostEntry("127.0.0.1").AddressList); + var cacheEntryTwo = Dns.Resolved.Create("test.local", System.Net.Dns.GetHostEntry("127.0.0.1").AddressList); + long ttl = 500; + cache.Put(cacheEntryOne, ttl); + cache.Cached("test.local").ShouldBe(cacheEntryOne); + cache.Put(cacheEntryTwo, ttl); + cache.Cached("test.local").ShouldBe(cacheEntryTwo); + } } } diff --git a/src/core/Akka/IO/SimpleDnsCache.cs b/src/core/Akka/IO/SimpleDnsCache.cs index 71e4bc67f1b..38b517e9028 100644 --- a/src/core/Akka/IO/SimpleDnsCache.cs +++ b/src/core/Akka/IO/SimpleDnsCache.cs @@ -80,7 +80,10 @@ public Cache Put(Dns.Resolved answer, long ttl) { var until = _clock() + ttl; _queue.Add(new ExpiryEntry(answer.Name, until)); - _cache.Add(answer.Name, new CacheEntry(answer, until)); + if (_cache.ContainsKey(answer.Name)) + _cache[answer.Name] = new CacheEntry(answer, until); + else + _cache.Add(answer.Name, new CacheEntry(answer, until)); return this; } From 7e16834ef0ff8551cdd3530eacb1016d40cb1cb8 Mon Sep 17 00:00:00 2001 From: moliver Date: Wed, 22 Jul 2015 01:39:08 -0400 Subject: [PATCH 004/105] Add CircuitBreaker Initial based on akka 2.0.5 - Add passing tests from akka 2.0.5 - Add CircuitBreakerState.cs with Open, HalfOpen, and Closed states - Add AtomicState which extends AtomicLong (mirrors functionality of State trait) - Add OpenCircuitException - Add CircuitBreaker documentation - Remove Scheduler from current implementation - Remove inappropriate xmldoc on illegalstateexception - Update flow on AtomicState::CallThrough method to be clearer and more closely match original - Add clarifying comments on "Fire and forget" NotifyTransitionListeners --- src/Akka.sln | 6 + src/core/Akka.TestKit/Akka.TestKit.csproj | 1 + src/core/Akka.TestKit/TestBreaker.cs | 30 ++ src/core/Akka.Tests/Akka.Tests.csproj | 1 + .../Akka.Tests/Pattern/CircuitBreakerSpec.cs | 351 ++++++++++++++++++ src/core/Akka/Akka.csproj | 4 + src/core/Akka/Pattern/CircuitBreaker.cs | 261 +++++++++++++ src/core/Akka/Pattern/CircuitBreakerState.cs | 226 +++++++++++ .../Akka/Pattern/IllegalStateException.cs | 4 + src/core/Akka/Pattern/OpenCircuitException.cs | 36 ++ src/core/Akka/Util/Internal/AtomicState.cs | 198 ++++++++++ 11 files changed, 1118 insertions(+) create mode 100644 src/core/Akka.TestKit/TestBreaker.cs create mode 100644 src/core/Akka.Tests/Pattern/CircuitBreakerSpec.cs create mode 100644 src/core/Akka/Pattern/CircuitBreaker.cs create mode 100644 src/core/Akka/Pattern/CircuitBreakerState.cs create mode 100644 src/core/Akka/Pattern/OpenCircuitException.cs create mode 100644 src/core/Akka/Util/Internal/AtomicState.cs diff --git a/src/Akka.sln b/src/Akka.sln index 8e8d1546a30..240dd07079f 100644 --- a/src/Akka.sln +++ b/src/Akka.sln @@ -2,6 +2,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.22823.1 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{69279534-1DBA-4115-BF8B-03F77FC8125E}" EndProject @@ -211,6 +213,10 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.MultiNodeTests", "core\Akka.MultiNodeTests\Akka.MultiNodeTests.csproj", "{F0781BEA-5BA0-4AF0-BB15-E3F209B681F5}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PersistenceBenchmark", "benchmark\PersistenceBenchmark\PersistenceBenchmark.csproj", "{39E6F51F-FA1E-4C62-B8F8-19065DE6D55D}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A59BAE84-70E2-46A0-9E26-7413C103E2D7}" + ProjectSection(SolutionItems) = preProject + WebEssentials-Settings.json = WebEssentials-Settings.json + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/core/Akka.TestKit/Akka.TestKit.csproj b/src/core/Akka.TestKit/Akka.TestKit.csproj index edc98f4d41f..21e25311a7b 100644 --- a/src/core/Akka.TestKit/Akka.TestKit.csproj +++ b/src/core/Akka.TestKit/Akka.TestKit.csproj @@ -111,6 +111,7 @@ + diff --git a/src/core/Akka.TestKit/TestBreaker.cs b/src/core/Akka.TestKit/TestBreaker.cs new file mode 100644 index 00000000000..ac188f853e4 --- /dev/null +++ b/src/core/Akka.TestKit/TestBreaker.cs @@ -0,0 +1,30 @@ +using System; +using System.Linq; +using System.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; +using Akka.Pattern; + +namespace Akka.TestKit +{ + public class TestBreaker + { + public CountdownEvent HalfOpenLatch { get; private set; } + public CountdownEvent OpenLatch { get; private set; } + public CountdownEvent ClosedLatch { get; private set; } + public CircuitBreaker Instance { get; private set; } + + public TestBreaker( CircuitBreaker instance ) + { + HalfOpenLatch = new CountdownEvent( 1 ); + OpenLatch = new CountdownEvent( 1 ); + ClosedLatch = new CountdownEvent( 1 ); + Instance = instance; + Instance.OnClose( ( ) => { if ( !ClosedLatch.IsSet ) ClosedLatch.Signal( ); } ) + .OnHalfOpen( ( ) => { if ( !HalfOpenLatch.IsSet ) HalfOpenLatch.Signal( ); } ) + .OnOpen( ( ) => { if ( !OpenLatch.IsSet ) OpenLatch.Signal( ); } ); + } + + + } +} \ No newline at end of file diff --git a/src/core/Akka.Tests/Akka.Tests.csproj b/src/core/Akka.Tests/Akka.Tests.csproj index 16e21f4965a..b9519bf9740 100644 --- a/src/core/Akka.Tests/Akka.Tests.csproj +++ b/src/core/Akka.Tests/Akka.Tests.csproj @@ -150,6 +150,7 @@ + diff --git a/src/core/Akka.Tests/Pattern/CircuitBreakerSpec.cs b/src/core/Akka.Tests/Pattern/CircuitBreakerSpec.cs new file mode 100644 index 00000000000..c4d5a56b692 --- /dev/null +++ b/src/core/Akka.Tests/Pattern/CircuitBreakerSpec.cs @@ -0,0 +1,351 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; +using Akka.Pattern; +using Akka.TestKit; +using Xunit; + +namespace Akka.Tests.Pattern +{ + public class ASynchronousCircuitBreakerThatIsClosed : CircuitBreakerSpecBase + { + [Fact(DisplayName = "A synchronous circuit breaker that is closed should allow call through")] + public void Should_Allow_Call_Through( ) + { + var breaker = LongCallTimeoutCb( ); + var result = breaker.Instance.WithSyncCircuitBreaker( ( ) => "Test" ); + + Assert.Equal( "Test", result ); + } + + [Fact( DisplayName = "A synchronous circuit breaker that is closed should increment failure count when call fails" )] + public void Should_Increment_FailureCount_When_Call_Fails( ) + { + var breaker = LongCallTimeoutCb( ); + + Assert.Equal( breaker.Instance.CurrentFailureCount, 0 ); + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithSyncCircuitBreaker( ThrowException ) ) ); + Assert.True( CheckLatch( breaker.OpenLatch ) ); + Assert.Equal( 1, breaker.Instance.CurrentFailureCount ); + } + + [Fact( DisplayName = "A synchronous circuit breaker that is closed should reset failure count when call succeeds" )] + public void Should_Reset_FailureCount_When_Call_Succeeds( ) + { + var breaker = MultiFailureCb( ); + + Assert.Equal( breaker.Instance.CurrentFailureCount, 0 ); + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithSyncCircuitBreaker( ThrowException ) ) ); + Assert.Equal( breaker.Instance.CurrentFailureCount, 1 ); + + breaker.Instance.WithSyncCircuitBreaker( ( ) => "Test" ); + + Assert.Equal( 0, breaker.Instance.CurrentFailureCount ); + } + + [Fact(DisplayName = "A synchronous circuit breaker that is closed should increment failure count when call times out")] + public void Should_Increment_FailureCount_When_Call_Times_Out( ) + { + var breaker = ShortCallTimeoutCb( ); + + breaker.Instance.WithSyncCircuitBreaker( ( ) => Thread.Sleep( 500 ) ); + + Assert.True( CheckLatch( breaker.OpenLatch ) ); + Assert.Equal( 1, breaker.Instance.CurrentFailureCount ); + } + } + + public class ASynchronousCircuitBreakerThatIsHalfOpen : CircuitBreakerSpecBase + { + [Fact(DisplayName = "A synchronous circuit breaker that is half open should pass call and transition to close on success")] + public void Should_Pass_Call_And_Transition_To_Close_On_Success( ) + { + var breaker = ShortResetTimeoutCb( ); + InterceptExceptionType( ( ) => breaker.Instance.WithSyncCircuitBreaker( ThrowException ) ); + Assert.True( CheckLatch( breaker.HalfOpenLatch ) ); + + var result = breaker.Instance.WithSyncCircuitBreaker( ( ) => SayTest( ) ); + + Assert.True( CheckLatch( breaker.ClosedLatch ) ); + Assert.Equal( SayTest( ), result ); + } + + [Fact(DisplayName = "A synchronous circuit breaker that is half open should pass call and transition to open on exception")] + public void Should_Pass_Call_And_Transition_To_Open_On_Exception( ) + { + var breaker = ShortResetTimeoutCb( ); + + + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithSyncCircuitBreaker( ThrowException ) ) ); + Assert.True( CheckLatch( breaker.HalfOpenLatch ) ); + + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithSyncCircuitBreaker( ThrowException ) ) ); + Assert.True( CheckLatch( breaker.OpenLatch ) ); + } + } + + public class ASynchronousCircuitBreakerThatIsOpen : CircuitBreakerSpecBase + { + [Fact(DisplayName = "A synchronous circuit breaker that is open should throw exceptions before reset timeout")] + public void Should_Throw_Exceptions_Before_Reset_Timeout( ) + { + var breaker = LongResetTimeoutCb( ); + + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithSyncCircuitBreaker( ThrowException ) ) ); + Assert.True( CheckLatch( breaker.OpenLatch ) ); + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithSyncCircuitBreaker( ThrowException ) ) ); + } + + [Fact(DisplayName = "A synchronous circuit breaker that is open should transition to half open when reset times out")] + public void Should_Transition_To_Half_Open_When_Reset_Times_Out( ) + { + var breaker = ShortResetTimeoutCb( ); + + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithSyncCircuitBreaker( ThrowException ) ) ); + Assert.True( CheckLatch( breaker.HalfOpenLatch ) ); + } + } + + public class AnAsynchronousCircuitBreakerThatIsClosed : CircuitBreakerSpecBase + { + [Fact(DisplayName = "An asynchronous circuit breaker that is closed should allow call through")] + public void Should_Allow_Call_Through( ) + { + var breaker = LongCallTimeoutCb( ); + var result = breaker.Instance.WithCircuitBreaker( Task.Run( ( ) => SayTest( ) ) ); + + Assert.Equal( SayTest( ), result.Result ); + } + + [Fact(DisplayName = "An asynchronous circuit breaker that is closed should increment failure count when call fails")] + public void Should_Increment_Failure_Count_When_Call_Fails( ) + { + var breaker = LongCallTimeoutCb( ); + + Assert.Equal( breaker.Instance.CurrentFailureCount, 0 ); + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithCircuitBreaker( Task.Run( ( ) => ThrowException( ) ) ).Wait( AwaitTimeout ) ) ); + Assert.True( CheckLatch( breaker.OpenLatch ) ); + Assert.Equal( 1, breaker.Instance.CurrentFailureCount ); + } + + [Fact(DisplayName = "An asynchronous circuit breaker that is closed should reset failure count when call succeeds after failure")] + public void Should_Reset_Failure_Count_When_Call_Succeeds_After_Failure( ) + { + var breaker = MultiFailureCb( ); + + Assert.Equal( breaker.Instance.CurrentFailureCount, 0 ); + + var whenall = Task.WhenAll( + breaker.Instance.WithCircuitBreaker(Task.Factory.StartNew(ThrowException)) + , breaker.Instance.WithCircuitBreaker(Task.Factory.StartNew(ThrowException)) + , breaker.Instance.WithCircuitBreaker(Task.Factory.StartNew(ThrowException)) + , breaker.Instance.WithCircuitBreaker(Task.Factory.StartNew(ThrowException))); + + Assert.True( InterceptExceptionType( ( ) => whenall.Wait( AwaitTimeout ) ) ); + + Assert.Equal( breaker.Instance.CurrentFailureCount, 4 ); + + var result = breaker.Instance.WithCircuitBreaker( Task.Run( ( ) => SayTest( ) ) ).Result; + + Assert.Equal( SayTest( ), result ); + Assert.Equal( 0, breaker.Instance.CurrentFailureCount ); + } + + [Fact(DisplayName = "An asynchronous circuit breaker that is closed should increment failure count when call times out")] + public void Should_Increment_Failure_Count_When_Call_Times_Out( ) + { + var breaker = ShortCallTimeoutCb( ); + + breaker.Instance.WithCircuitBreaker( Task.Factory.StartNew( ( ) => + { + Thread.Sleep( 500 ); + return SayTest( ); + } ) ); + + Assert.True( CheckLatch( breaker.OpenLatch ) ); + Assert.Equal( 1, breaker.Instance.CurrentFailureCount ); + } + } + + public class AnAsynchronousCircuitBreakerThatIsHalfOpen : CircuitBreakerSpecBase + { + [Fact(DisplayName = "An asynchronous circuit breaker that is half open should pass call and transition to close on success")] + public void Should_Pass_Call_And_Transition_To_Close_On_Success( ) + { + var breaker = ShortResetTimeoutCb( ); + InterceptExceptionType( ( ) => breaker.Instance.WithCircuitBreaker( Task.Factory.StartNew( ThrowException ) ) ); + Assert.True( CheckLatch( breaker.HalfOpenLatch ) ); + + var result = breaker.Instance.WithCircuitBreaker( Task.Factory.StartNew( ( ) => SayTest( ) ) ); + + Assert.True( CheckLatch( breaker.ClosedLatch ) ); + Assert.Equal( SayTest( ), result.Result ); + } + + [Fact(DisplayName = "An asynchronous circuit breaker that is half open should pass call and transition to open on exception")] + public void Should_Pass_Call_And_Transition_To_Open_On_Exception( ) + { + var breaker = ShortResetTimeoutCb( ); + + + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithCircuitBreaker( Task.Factory.StartNew( ThrowException ) ).Wait( ) ) ); + Assert.True( CheckLatch( breaker.HalfOpenLatch ) ); + + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithCircuitBreaker( Task.Factory.StartNew( ThrowException ) ).Wait( ) ) ); + Assert.True( CheckLatch( breaker.OpenLatch ) ); + } + + [Fact(DisplayName = "An asynchronous circuit breaker that is half open should pass call and transition to open on async failure")] + public void Should_Pass_Call_And_Transition_To_Open_On_Async_Failure( ) + { + var breaker = ShortResetTimeoutCb( ); + + breaker.Instance.WithCircuitBreaker( Task.Factory.StartNew( ThrowException ) ); + Assert.True( CheckLatch( breaker.HalfOpenLatch ) ); + + breaker.Instance.WithCircuitBreaker( Task.Factory.StartNew( ThrowException ) ); + Assert.True( CheckLatch( breaker.OpenLatch ) ); + } + } + + public class AnAsynchronousCircuitBreakerThatIsOpen : CircuitBreakerSpecBase + { + [Fact(DisplayName = "An asynchronous circuit breaker that is open should throw exceptions when called before reset timeout")] + public void Should_Throw_Exceptions_When_Called_Before_Reset_Timeout( ) + { + var breaker = LongResetTimeoutCb( ); + + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithCircuitBreaker( Task.Factory.StartNew( ThrowException ) ).Wait( ) ) ); + Assert.True( CheckLatch( breaker.OpenLatch ) ); + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithCircuitBreaker( Task.Factory.StartNew( ThrowException ) ).Wait( ) ) ); + } + + [Fact(DisplayName = "An asynchronous circuit breaker that is open should transition to half open when reset timeout")] + public void Should_Transition_To_Half_Open_When_Reset_Timeout( ) + { + var breaker = ShortResetTimeoutCb( ); + + Assert.True( InterceptExceptionType( ( ) => breaker.Instance.WithCircuitBreaker( Task.Factory.StartNew( ThrowException ) ).Wait( ) ) ); + Assert.True( CheckLatch( breaker.HalfOpenLatch ) ); + } + } + + public class CircuitBreakerSpecBase : AkkaSpec + { + private readonly TimeSpan _awaitTimeout = TimeSpan.FromSeconds(2); + public TimeSpan AwaitTimeout { get { return _awaitTimeout; } } + + public bool CheckLatch( CountdownEvent latch ) + { + return latch.Wait( AwaitTimeout ); + } + + public Task Delay( TimeSpan toDelay, CancellationToken? token ) + { + return token.HasValue ? Task.Delay( toDelay, token.Value ) : Task.Delay( toDelay ); + } + + public void ThrowException( ) + { + throw new TestException( "Test Exception" ); + } + + public string SayTest( ) + { + return "Test"; + } + + [SuppressMessage( "Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter" )] + public bool InterceptExceptionType( Action action ) where T : Exception + { + try + { + action.Invoke( ); + return false; + } + catch ( Exception ex ) + { + var aggregate = ex as AggregateException; + if ( aggregate != null ) + { + + // ReSharper disable once UnusedVariable + foreach ( var temp in aggregate.InnerExceptions.Select( innerException => innerException as T ).Where( temp => temp == null ) ) + { + throw; + } + } + else + { + var temp = ex as T; + + if ( temp == null ) + { + throw; + } + } + + } + return true; + } + + public TestBreaker ShortCallTimeoutCb( ) + { + return new TestBreaker( new CircuitBreaker( 1, TimeSpan.FromMilliseconds( 50 ), TimeSpan.FromMilliseconds( 500 ) ) ); + } + + public TestBreaker ShortResetTimeoutCb( ) + { + return new TestBreaker( new CircuitBreaker( 1, TimeSpan.FromMilliseconds( 1000 ), TimeSpan.FromMilliseconds( 50 ) ) ); + } + + public TestBreaker LongCallTimeoutCb( ) + { + return new TestBreaker( new CircuitBreaker( 1, TimeSpan.FromMilliseconds( 5000 ), TimeSpan.FromMilliseconds( 500 ) ) ); + } + + public TestBreaker LongResetTimeoutCb( ) + { + return new TestBreaker( new CircuitBreaker( 1, TimeSpan.FromMilliseconds( 100 ), TimeSpan.FromMilliseconds( 5000 ) ) ); + } + + public TestBreaker MultiFailureCb( ) + { + return new TestBreaker( new CircuitBreaker( 5, TimeSpan.FromMilliseconds( 200 ), TimeSpan.FromMilliseconds( 500 ) ) ); + } + } + + + internal class TestException : ApplicationException + { + public TestException( ) + { + } + + public TestException( string message ) + : base( message ) + { + } + + public TestException( string message, Exception innerException ) + : base( message, innerException ) + { + } + + protected TestException( SerializationInfo info, StreamingContext context ) + : base( info, context ) + { + } + } + +} \ No newline at end of file diff --git a/src/core/Akka/Akka.csproj b/src/core/Akka/Akka.csproj index 908f24e3b17..30969346257 100644 --- a/src/core/Akka/Akka.csproj +++ b/src/core/Akka/Akka.csproj @@ -248,6 +248,9 @@ + + + @@ -266,6 +269,7 @@ + diff --git a/src/core/Akka/Pattern/CircuitBreaker.cs b/src/core/Akka/Pattern/CircuitBreaker.cs new file mode 100644 index 00000000000..15b88af307b --- /dev/null +++ b/src/core/Akka/Pattern/CircuitBreaker.cs @@ -0,0 +1,261 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Akka.Util.Internal; + +namespace Akka.Pattern +{ + /// + /// Provides circuit breaker functionality to provide stability when working with + /// "dangerous" operations, e.g. calls to remote systems + /// + /// + /// + /// Transitions through three states: + /// + /// + /// In *Closed* state, + /// calls pass through until the maxFailures count is reached. + /// This causes the circuit breaker to open. Both exceptions and calls exceeding + /// callTimeout are considered failures. + /// + /// + /// In *Open* state, + /// calls fail-fast with an exception. After resetTimeout, + /// circuit breaker transitions to half-open state. + /// + /// + /// In *Half-Open* state, + /// the first call will be allowed through, if it succeeds + /// the circuit breaker will reset to closed state. If it fails, the circuit + /// breaker will re-open to open state. All calls beyond the first that execute + /// while the first is running will fail-fast with an exception. + /// + /// + /// + public class CircuitBreaker + { + /// + /// The current state of the breaker -- Closed, Half-Open, or Closed -- *access only via helper methods* + /// + private AtomicState _currentState; + + /// + /// Helper method for access to the underlying state via Interlocked + /// + /// Previous state on transition + /// Next state on transition + /// Whether the previous state matched correctly + private bool SwapState( AtomicState oldState, AtomicState newState ) + { + return Interlocked.CompareExchange( ref _currentState, newState, oldState ) == oldState; + } + + /// + /// Helper method for access to the underlying state via Interlocked + /// + private AtomicState CurrentState + { + get + { + Interlocked.MemoryBarrier( ); + return _currentState; + } + } + + public int MaxFailures { get; private set; } + + public TimeSpan CallTimeout { get; private set; } + public TimeSpan ResetTimeout { get; private set; } + + //akka.io implementation is to use nested static classes and access parent member variables + //.Net static nested classes do not have access to parent member variables -- so we configure the states here and + //swap them above + private AtomicState Closed { get; set; } + private AtomicState Open { get; set; } + private AtomicState HalfOpen { get; set; } + + /// + /// Create a new CircuitBreaker + /// + /// Maximum number of failures before opening the circuit + /// of time after which to consider a call a failure + /// of time after which to attempt to close the circuit + /// + public static CircuitBreaker Create( int maxFailures, TimeSpan callTimeout, TimeSpan resetTimeout ) + { + return new CircuitBreaker( maxFailures, callTimeout, resetTimeout ); + } + + /// + /// Create a new CircuitBreaker + /// + /// Maximum number of failures before opening the circuit + /// of time after which to consider a call a failure + /// of time after which to attempt to close the circuit + /// + public CircuitBreaker( int maxFailures, TimeSpan callTimeout, TimeSpan resetTimeout ) + { + MaxFailures = maxFailures; + CallTimeout = callTimeout; + ResetTimeout = resetTimeout; + Closed = new Closed( this ); + Open = new Open( this ); + HalfOpen = new HalfOpen( this ); + _currentState = Closed; + //_failures = new AtomicInteger(); + } + + /// + /// Retrieves current failure count. + /// + public long CurrentFailureCount + { + get { return Closed.Current; } + } + + /// + /// Wraps invocation of asynchronous calls that need to be protected + /// + /// + /// Call needing protected + /// containing the call result + public async Task WithCircuitBreaker( Task body ) + { + return await CurrentState.Invoke( body ); + } + + /// + /// Wraps invocation of asynchronous calls that need to be protected + /// + /// Call needing protected + /// + public async Task WithCircuitBreaker( Task body ) + { + await CurrentState.Invoke( body ); + } + + /// + /// The failure will be recorded farther down. + /// + /// + public void WithSyncCircuitBreaker( Action body ) + { + var cbTask = WithCircuitBreaker( Task.Factory.StartNew( body ) ); + if ( !cbTask.Wait( CallTimeout ) ) + { + //throw new TimeoutException( string.Format( "Execution did not complete within the time alotted {0} ms", CallTimeout.TotalMilliseconds ) ); + } + if ( cbTask.Exception != null ) + { + throw cbTask.Exception; + } + } + + /// + /// Wraps invocations of asynchronous calls that need to be protected + /// If this does not complete within the time allotted, it should return default() + /// + /// + /// Await.result( + /// withCircuitBreaker(try Future.successful(body) catch { case NonFatal(t) ⇒ Future.failed(t) }), + /// callTimeout) + /// + /// + /// + /// + /// + /// or default() + public T WithSyncCircuitBreaker( Func body ) + { + var cbTask = WithCircuitBreaker( Task.Factory.StartNew( body ) ); + return cbTask.Wait( CallTimeout ) ? cbTask.Result : default(T); + } + + /// + /// Adds a callback to execute when circuit breaker opens + /// + /// Handler to be invoked on state change + /// CircuitBreaker for fluent usage + public CircuitBreaker OnOpen( Action callback ) + { + Open.AddListener( callback ); + return this; + } + + /// + /// Adds a callback to execute when circuit breaker transitions to half-open + /// + /// Handler to be invoked on state change + /// CircuitBreaker for fluent usage + public CircuitBreaker OnHalfOpen( Action callback ) + { + HalfOpen.AddListener( callback ); + return this; + } + + /// + /// Adds a callback to execute when circuit breaker state closes + /// + /// Handler to be invoked on state change + /// CircuitBreaker for fluent usage + public CircuitBreaker OnClose( Action callback ) + { + Closed.AddListener( callback ); + return this; + } + + /// + /// Implements consistent transition between states. Throws IllegalStateException if an invalid transition is attempted. + /// + /// State being transitioning from + /// State being transitioned to + private void Transition( AtomicState fromState, AtomicState toState ) + { + if ( SwapState( fromState, toState ) ) + { + Debug.WriteLine( "Successful transition from {0} to {1}", fromState, toState ); + toState.Enter( ); + } + else + { + throw new IllegalStateException( string.Format( "Illegal transition attempted from {0} to {1}", fromState, toState ) ); + } + } + + /// + /// Trips breaker to an open state. This is valid from Closed or Half-Open states + /// + /// State we're coming from (Closed or Half-Open) + internal void TripBreaker( AtomicState fromState ) + { + Transition( fromState, Open ); + } + + /// + /// Resets breaker to a closed state. This is valid from an Half-Open state only. + /// + internal void ResetBreaker( ) + { + Transition( HalfOpen, Closed ); + } + + /// + /// Attempts to reset breaker by transitioning to a half-open state. This is valid from an Open state only. + /// + internal void AttemptReset( ) + { + Transition( Open, HalfOpen ); + } + + //private readonly Task timeoutTask = Task.FromResult(new TimeoutException("Circuit Breaker Timed out.")); + } +} diff --git a/src/core/Akka/Pattern/CircuitBreakerState.cs b/src/core/Akka/Pattern/CircuitBreakerState.cs new file mode 100644 index 00000000000..833d72b7b21 --- /dev/null +++ b/src/core/Akka/Pattern/CircuitBreakerState.cs @@ -0,0 +1,226 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System.Globalization; +using System.Threading.Tasks; +using Akka.Util; +using Akka.Util.Internal; + +namespace Akka.Pattern +{ + /// + /// Concrete implementation of Open state + /// + internal class Open : AtomicState + { + private readonly CircuitBreaker _breaker; + + public Open( CircuitBreaker breaker ) + : base( breaker.CallTimeout, 0 ) + { + _breaker = breaker; + } + + /// + /// Fail-fast on any invocation + /// + /// + /// Implementation of the call that needs protected + /// containing result of protected call + public override Task Invoke( Task body ) + { + throw new OpenCircuitException( ); + } + + /// + /// Implementation of invoke, which simply attempts the call + /// + /// Implementation of the call that needs protected + /// containing result of protected call + public override Task Invoke( Task body ) + { + throw new OpenCircuitException( ); + } + + /// + /// No-op for open, calls are never executed so cannot succeed or fail + /// + protected override void CallFails( ) + { + //throw new NotImplementedException(); + } + + /// + /// No-op for open, calls are never executed so cannot succeed or fail + /// + protected override void CallSucceeds( ) + { + //throw new NotImplementedException(); + } + + /// + /// On entering this state, schedule an attempted reset and store the entry time to + /// calculate remaining time before attempted reset. + /// + protected override void EnterInternal( ) + { + Task.Delay( _breaker.ResetTimeout ).ContinueWith( task => _breaker.AttemptReset( ) ); + } + } + + /// + /// Concrete implementation of half-open state + /// + internal class HalfOpen : AtomicState + { + private readonly CircuitBreaker _breaker; + private readonly AtomicBoolean _lock; + + public HalfOpen( CircuitBreaker breaker ) + : base( breaker.CallTimeout, 0 ) + { + _breaker = breaker; + _lock = new AtomicBoolean(); + } + + /// + /// Allows a single call through, during which all other callers fail-fast. If the call fails, the breaker reopens. + /// If the call succeeds, the breaker closes. + /// + /// + /// Implementation of the call that needs protected + /// containing result of protected call + public override async Task Invoke( Task body ) + { + if ( !_lock.CompareAndSet( true, false) ) + { + throw new OpenCircuitException( ); + } + return await CallThrough( body ); + } + + /// + /// Allows a single call through, during which all other callers fail-fast. If the call fails, the breaker reopens. + /// If the call succeeds, the breaker closes. + /// + /// Implementation of the call that needs protected + /// containing result of protected call + public override async Task Invoke( Task body ) + { + if ( !_lock.CompareAndSet( true, false ) ) + { + throw new OpenCircuitException( ); + } + await CallThrough( body ); + } + + /// + /// Reopen breaker on failed call. + /// + protected override void CallFails( ) + { + _breaker.TripBreaker( this ); + } + + /// + /// Reset breaker on successful call. + /// + protected override void CallSucceeds( ) + { + _breaker.ResetBreaker( ); + } + + /// + /// On entry, guard should be reset for that first call to get in + /// + protected override void EnterInternal( ) + { + _lock.Value = true ; + } + + /// + /// Override for more descriptive toString + /// + /// + public override string ToString( ) + { + return string.Format( CultureInfo.InvariantCulture, "Half-Open currently testing call for success = {0}", ( _lock == true ) ); + } + } + + /// + /// Concrete implementation of Closed state + /// + internal class Closed : AtomicState + { + private readonly CircuitBreaker _breaker; + + public Closed( CircuitBreaker breaker ) + : base( breaker.CallTimeout, 0 ) + { + _breaker = breaker; + } + + /// + /// Implementation of invoke, which simply attempts the call + /// + /// + /// Implementation of the call that needs protected + /// containing result of protected call + public override async Task Invoke( Task body ) + { + return await CallThrough( body ); + } + + /// + /// Implementation of invoke, which simply attempts the call + /// + /// Implementation of the call that needs protected + /// containing result of protected call + public override async Task Invoke( Task body ) + { + await CallThrough( body ); + } + + /// + /// On failed call, the failure count is incremented. The count is checked against the configured maxFailures, and + /// the breaker is tripped if we have reached maxFailures. + /// + protected override void CallFails( ) + { + if ( IncrementAndGet( ) == _breaker.MaxFailures ) + { + _breaker.TripBreaker( this ); + } + } + + /// + /// On successful call, the failure count is reset to 0 + /// + protected override void CallSucceeds( ) + { + Reset(); + } + + /// + /// On entry of this state, failure count is reset. + /// + protected override void EnterInternal( ) + { + Reset(); + } + + /// + /// Override for more descriptive toString + /// + /// + public override string ToString( ) + { + return string.Format( "Closed with failure count = {0}", Current ); + } + } +} \ No newline at end of file diff --git a/src/core/Akka/Pattern/IllegalStateException.cs b/src/core/Akka/Pattern/IllegalStateException.cs index b27a95958c1..f1a4c684170 100644 --- a/src/core/Akka/Pattern/IllegalStateException.cs +++ b/src/core/Akka/Pattern/IllegalStateException.cs @@ -10,6 +10,10 @@ namespace Akka.Pattern { + /// + /// Signals that a method has been invoked at an illegal or + /// inappropriate time. + /// public class IllegalStateException : AkkaException { diff --git a/src/core/Akka/Pattern/OpenCircuitException.cs b/src/core/Akka/Pattern/OpenCircuitException.cs new file mode 100644 index 00000000000..8cc7d68fd0a --- /dev/null +++ b/src/core/Akka/Pattern/OpenCircuitException.cs @@ -0,0 +1,36 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Runtime.Serialization; +using Akka.Actor; + +namespace Akka.Pattern +{ + /// + /// Exception throws when CircuitBreaker is open + /// + public class OpenCircuitException : AkkaException + { + public OpenCircuitException( ) : base( "Circuit Breaker is open; calls are failing fast" ) { } + + public OpenCircuitException( string message ) + : base( message ) + { + } + + public OpenCircuitException( string message, Exception innerException ) + : base( message, innerException ) + { + } + + protected OpenCircuitException( SerializationInfo info, StreamingContext context ) + : base( info, context ) + { + } + } +} \ No newline at end of file diff --git a/src/core/Akka/Util/Internal/AtomicState.cs b/src/core/Akka/Util/Internal/AtomicState.cs new file mode 100644 index 00000000000..3b9f01d9ddc --- /dev/null +++ b/src/core/Akka/Util/Internal/AtomicState.cs @@ -0,0 +1,198 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Concurrent; +using System.Runtime.ExceptionServices; +using System.Threading.Tasks; + +namespace Akka.Util.Internal +{ + /// + /// Internal state abstraction + /// + internal abstract class AtomicState : AtomicCounterLong, IAtomicState + { + private readonly ConcurrentQueue _listeners; + private readonly TimeSpan _callTimeout; + + protected AtomicState( TimeSpan callTimeout, long startingCount ) + : base( startingCount ) + { + _listeners = new ConcurrentQueue( ); + _callTimeout = callTimeout; + } + + /// + /// Add a listener function which is invoked on state entry + /// + /// listener implementation + public void AddListener( Action listener ) + { + _listeners.Enqueue( listener ); + } + + /// + /// Test for whether listeners exist + /// + public bool HasListeners + { + get { return !_listeners.IsEmpty; } + } + + /// + /// Notifies the listeners of the transition event via a + /// + protected async Task NotifyTransitionListeners( ) + { + if ( !HasListeners ) return; + await Task + .Factory + .StartNew + ( + ( ) => + { + foreach ( var listener in _listeners ) + { + listener.Invoke( ); + } + } + ); + } + + /// + /// Shared implementation of call across all states. Thrown exception or execution of the call beyond the allowed + /// call timeout is counted as a failed call, otherwise a successful call + /// + /// NOTE: In .Net there is no way to cancel an uncancellable task. We are merely cancelling the wait and marking this + /// as a failure. + /// + /// see http://blogs.msdn.com/b/pfxteam/archive/2011/11/10/10235834.aspx + /// + /// + /// Implementation of the call + /// result of the call + public async Task CallThrough( Task task ) + { + var deadline = DateTime.UtcNow.Add( _callTimeout ); + ExceptionDispatchInfo capturedException = null; + T result = default(T); + try + { + result = await task; + } + catch ( Exception ex ) + { + capturedException = ExceptionDispatchInfo.Capture( ex ); + } + + bool throwException = capturedException != null; + if ( throwException || DateTime.UtcNow.CompareTo( deadline ) >= 0 ) + { + CallFails( ); + if ( throwException ) + capturedException.Throw( ); + } + else + { + CallSucceeds( ); + } + return result; + } + + /// + /// Shared implementation of call across all states. Thrown exception or execution of the call beyond the allowed + /// call timeout is counted as a failed call, otherwise a successful call + /// + /// NOTE: In .Net there is no way to cancel an uncancellable task. We are merely cancelling the wait and marking this + /// as a failure. + /// + /// see http://blogs.msdn.com/b/pfxteam/archive/2011/11/10/10235834.aspx + /// + /// Implementation of the call + /// + public async Task CallThrough( Task task ) + { + var deadline = DateTime.UtcNow.Add( _callTimeout ); + ExceptionDispatchInfo capturedException = null; + + try + { + await task; + } + catch ( Exception ex ) + { + capturedException = ExceptionDispatchInfo.Capture( ex ); + } + + bool throwException = capturedException != null; + if (throwException || DateTime.UtcNow.CompareTo(deadline) >= 0) + { + CallFails(); + if (throwException) capturedException.Throw(); + } + else + { + CallSucceeds(); + } + + + } + + /// + /// Abstract entry point for all states + /// + /// + /// Implementation of the call that needs protected + /// containing result of protected call + public abstract Task Invoke( Task body ); + + /// + /// Abstract entry point for all states + /// + /// Implementation of the call that needs protected + /// containing result of protected call + public abstract Task Invoke( Task body ); + + /// + /// Invoked when call fails + /// + protected abstract void CallFails( ); + + /// + /// Invoked when call succeeds + /// + protected abstract void CallSucceeds( ); + + /// + /// Invoked on the transitioned-to state during transition. Notifies listeners after invoking subclass template method _enter + /// + protected abstract void EnterInternal( ); + + /// + /// Enter the state. NotifyTransitionListeners is not awaited -- its "fire and forget". + /// It is up to the user to handle any errors that occur in this state. + /// + public void Enter( ) + { + EnterInternal( ); + NotifyTransitionListeners( ); + } + + } + + /// + /// This interface represents the parts of the internal circuit breaker state; the behavior stack, watched by, watching and termination queue + /// + public interface IAtomicState + { + void AddListener( Action listener ); + bool HasListeners { get; } + Task Invoke( Task body ); + void Enter( ); + } +} From 6474bd7dc3d27756e255d12ef21f331108d9922d Mon Sep 17 00:00:00 2001 From: rogeralsing Date: Mon, 10 Aug 2015 13:57:57 +0200 Subject: [PATCH 005/105] Fix for 1185 receive timeout in async await actor --- .../Akka.Tests/Dispatch/AsyncAwaitSpec.cs | 28 +++++++++++++++++++ src/core/Akka/Dispatch/ActorTaskScheduler.cs | 1 + 2 files changed, 29 insertions(+) diff --git a/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs b/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs index 47d23ce82fb..53d49d538ed 100644 --- a/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs +++ b/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs @@ -13,6 +13,24 @@ namespace Akka.Tests.Dispatch { + class ReceiveTimeoutAsyncActor : ReceiveActor + { + private IActorRef _replyTo; + public ReceiveTimeoutAsyncActor() + { + Receive(t => + { + _replyTo.Tell("GotIt"); + }); + Receive(async s => + { + _replyTo = Sender; + + await Task.Delay(TimeSpan.FromMilliseconds(100)); + SetReceiveTimeout(TimeSpan.FromMilliseconds(100)); + }); + } + } class AsyncActor : ReceiveActor { public AsyncActor() @@ -325,6 +343,16 @@ public async Task Actor_should_be_able_to_resume_suspend() var res = await asker.Ask("stop", TimeSpan.FromSeconds(5)); res.ShouldBe("done"); } + + + [Fact] + public void Actor_should_be_able_to_ReceiveTimeout_after_async_operation() + { + var actor = Sys.ActorOf(); + + actor.Tell("hello"); + ExpectMsg(m => m == "GotIt"); + } } } diff --git a/src/core/Akka/Dispatch/ActorTaskScheduler.cs b/src/core/Akka/Dispatch/ActorTaskScheduler.cs index 659b9481080..550d664c496 100644 --- a/src/core/Akka/Dispatch/ActorTaskScheduler.cs +++ b/src/core/Akka/Dispatch/ActorTaskScheduler.cs @@ -128,6 +128,7 @@ await action() //if mailbox was suspended, make sure we re-enable message processing again mailbox.Resume(MailboxSuspendStatus.AwaitingTask); + context.CheckReceiveTimeout(); }, Outer, CancellationToken.None, From 9c04c83fb19250b0124b06619a32cbb5e1b3b247 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Mon, 10 Aug 2015 08:12:15 -0400 Subject: [PATCH 006/105] make Received and Connected inherit from Tcp.Event --- src/core/Akka/IO/Tcp.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/Akka/IO/Tcp.cs b/src/core/Akka/IO/Tcp.cs index 8cdd1d41357..f314046e243 100644 --- a/src/core/Akka/IO/Tcp.cs +++ b/src/core/Akka/IO/Tcp.cs @@ -484,7 +484,7 @@ public class Event : Message /// Whenever data are read from a socket they will be transferred within this /// class to the handler actor which was designated in the message. /// - public sealed class Received + public sealed class Received : Event { public Received(ByteString data) { @@ -500,7 +500,7 @@ public Received(ByteString data) /// in the message. The connection is characterized by the `remoteAddress` /// and `localAddress` TCP endpoints. /// - public sealed class Connected + public sealed class Connected : Event { public Connected(EndPoint remoteAddress, EndPoint localAddress) { From 7ddbbbadc05012911f8c0813dca9ff2598512a74 Mon Sep 17 00:00:00 2001 From: willieferguson Date: Tue, 11 Aug 2015 09:23:39 +0200 Subject: [PATCH 007/105] akka-io: Ported a few tests in ByteStringSpec with bug fixes --- src/core/Akka.Tests/Akka.Tests.csproj | 9 ++ src/core/Akka.Tests/Util/ByteStringSpec.cs | 97 ++++++++++++++++++++++ src/core/Akka.Tests/packages.config | 2 + src/core/Akka/Util/ByteIterator.cs | 69 ++++++++------- src/core/Akka/Util/ByteString.cs | 13 ++- 5 files changed, 159 insertions(+), 31 deletions(-) create mode 100644 src/core/Akka.Tests/Util/ByteStringSpec.cs diff --git a/src/core/Akka.Tests/Akka.Tests.csproj b/src/core/Akka.Tests/Akka.Tests.csproj index b9519bf9740..4b0175a5767 100644 --- a/src/core/Akka.Tests/Akka.Tests.csproj +++ b/src/core/Akka.Tests/Akka.Tests.csproj @@ -61,6 +61,14 @@ ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.Core.dll + + ..\..\packages\FsCheck.2.0.5\lib\net45\FsCheck.dll + True + + + ..\..\packages\FSharp.Core.3.1.2.5\lib\net40\FSharp.Core.dll + True + @@ -166,6 +174,7 @@ + diff --git a/src/core/Akka.Tests/Util/ByteStringSpec.cs b/src/core/Akka.Tests/Util/ByteStringSpec.cs new file mode 100644 index 00000000000..7ce6cace1c6 --- /dev/null +++ b/src/core/Akka.Tests/Util/ByteStringSpec.cs @@ -0,0 +1,97 @@ +using System.Linq; +using System.Text; +using Akka.IO; +using FsCheck; +using Xunit; + +namespace Akka.Tests.Util +{ + + /// + /// TODO: Should we use the FsCheck.XUnit integration when they upgrade to xUnit 2 + /// + public class ByteStringSpec + { + class Generators + { + + // TODO: Align with JVM Akka Generator + public static Arbitrary ByteStrings() + { + return Arb.From(Arb.Generate().Select(ByteString.Create)); + } + } + + public ByteStringSpec() + { + Arb.Register(); + } + + [Fact] + public void A_ByteString_must_have_correct_size_when_concatenating() + { + Prop.ForAll((ByteString a, ByteString b) => (a + b).Count == a.Count + b.Count) + .QuickCheckThrowOnFailure(); + } + + [Fact] + public void A_ByteString_must_have_correct_size_when_dropping() + { + Prop.ForAll((ByteString a, ByteString b) => (a + b).Drop(b.Count).Count == a.Count) + .QuickCheckThrowOnFailure(); + } + + [Fact] + public void A_ByteString_must_be_sequential_when_taking() + { + Prop.ForAll((ByteString a, ByteString b) => (a + b).Take(a.Count).SequenceEqual(a)) + .QuickCheckThrowOnFailure(); + } + [Fact] + public void A_ByteString_must_be_sequential_when_dropping() + { + Prop.ForAll((ByteString a, ByteString b) => (a + b).Drop(a.Count).SequenceEqual(b)) + .QuickCheckThrowOnFailure(); + } + + [Fact] + public void A_ByteString_must_be_equal_to_the_original_when_compacting() + { + Prop.ForAll((ByteString xs) => + { + var ys = xs.Compact(); + return xs.SequenceEqual(ys) && ys.IsCompact(); + }).QuickCheckThrowOnFailure(); + } + [Fact] + public void A_ByteString_must_be_equal_to_the_original_when_recombining() + { + Prop.ForAll((ByteString xs, int from, int until) => + { + var tmp1 = xs.SplitAt(until); + var tmp2 = tmp1.Item1.SplitAt(until); + return (tmp2.Item1 + tmp2.Item2 + tmp1.Item2).SequenceEqual(xs); + }).QuickCheckThrowOnFailure(); + } + + [Fact] + public void A_ByteString_must_behave_as_expected_when_created_from_and_decoding_to_String() + { + Prop.ForAll((string s) => ByteString.FromString(s, Encoding.UTF8).DecodeString(Encoding.UTF8) == (s ?? "")) // TODO: What should we do with null string? + .QuickCheckThrowOnFailure(); + } + [Fact] + public void A_ByteString_must_behave_as_expected_when_compacting() + { + Prop.ForAll((ByteString a) => + { + var wasCompact = a.IsCompact(); + var b = a.Compact(); + return ((!wasCompact) || (b == a)) && + b.SequenceEqual(a) && + b.IsCompact() && + b.Compact() == b; + }).QuickCheckThrowOnFailure(); + } + } +} diff --git a/src/core/Akka.Tests/packages.config b/src/core/Akka.Tests/packages.config index 011a76f37f0..09bb0a85065 100644 --- a/src/core/Akka.Tests/packages.config +++ b/src/core/Akka.Tests/packages.config @@ -2,6 +2,8 @@ + + diff --git a/src/core/Akka/Util/ByteIterator.cs b/src/core/Akka/Util/ByteIterator.cs index 85eed113ab3..76bf806ce98 100644 --- a/src/core/Akka/Util/ByteIterator.cs +++ b/src/core/Akka/Util/ByteIterator.cs @@ -149,8 +149,7 @@ public override int CopyToBuffer(ByteBuffer buffer) internal class MultiByteIterator : ByteIterator { private ILinearSeq _iterators; - private ByteArrayIterator _current; - private static readonly ByteArrayIterator[] ClearedList = new ByteArrayIterator[0]; + private static readonly ILinearSeq ClearedList = new ArrayLinearSeq(new ByteArrayIterator[0]); public MultiByteIterator(params ByteArrayIterator[] iterators) { @@ -166,18 +165,26 @@ public MultiByteIterator(ILinearSeq iterators) private MultiByteIterator Normalize() { - Func, IEnumerable> norm = null; + Func, ILinearSeq> norm = null; norm = xs => { - if (!xs.Any()) return ClearedList; - if (!xs.First().HasNext) return norm(xs.Skip(1)); + if (xs.IsEmpty) return ClearedList; + if (!xs.Head.HasNext) return norm(xs.Tail()); return xs; }; - _iterators = new ArrayLinearSeq(norm(_iterators).ToArray()); + _iterators = norm(_iterators); return this; } + + private ByteArrayIterator Current + { + get + { + return _iterators.Head; + } + } private void DropCurrent() { _iterators = _iterators.Tail(); @@ -190,17 +197,17 @@ protected override void Clear() public override bool HasNext { - get { return _current.HasNext; } + get { return Current.HasNext; } } public override byte Head { - get { return _current.Head; } + get { return Current.Head; } } public override byte Next() { - var result = _current.Next(); + var result = Current.Next(); Normalize(); return result; } @@ -217,11 +224,11 @@ public override ByteIterator Take(int n) var builder = new List(); while (rest > 0 && !_iterators.IsEmpty) { - _current.Take(rest); - if (_current.HasNext) + Current.Take(rest); + if (Current.HasNext) { - rest -= _current.Len; - builder.Add(_current); + rest -= Current.Len; + builder.Add(Current); } _iterators = _iterators.Tail(); } @@ -233,8 +240,8 @@ public override ByteIterator Drop(int n) { if (n > 0 && Len > 0) { - var nCurrent = Math.Min(n, _current.Len); - _current.Drop(n); + var nCurrent = Math.Min(n, Current.Len); + Current.Drop(n); var rest = n - nCurrent; Normalize(); return Drop(rest); @@ -248,10 +255,10 @@ public override ByteIterator TakeWhile(Func p) var builder = new List(); while (!stop && !_iterators.IsEmpty) { - var lastLen = _current.Len; - _current.TakeWhile(p); - if (_current.HasNext) builder.Add(_current); - if (_current.Len < lastLen) stop = true; + var lastLen = Current.Len; + Current.TakeWhile(p); + if (Current.HasNext) builder.Add(Current); + if (Current.Len < lastLen) stop = true; DropCurrent(); } _iterators = new ArrayLinearSeq(builder.ToArray()); @@ -262,8 +269,8 @@ public override ByteIterator DropWhile(Func p) { if (Len > 0) { - _current.DropWhile(p); - var dropMore = _current.Len == 0; + Current.DropWhile(p); + var dropMore = Current.Len == 0; Normalize(); if (dropMore) return DropWhile(p); } @@ -280,12 +287,12 @@ public override ByteString ToByteString() protected MultiByteIterator GetToArray(T[] xs, int offset, int n, int elemSize, Func getSingle, Action getMulti) { - if(n >= 0) return this; + if(n <= 0) return this; Func nDoneF = () => { - if (_current.Len >= elemSize) + if (Current.Len >= elemSize) { - var nCurrent = Math.Min(n, _current.Len/elemSize); + var nCurrent = Math.Min(n, Current.Len/elemSize); getMulti(xs, offset, nCurrent); return nCurrent; } @@ -302,13 +309,13 @@ protected MultiByteIterator GetToArray(T[] xs, int offset, int n, int elemSiz public override ByteIterator GetBytes(byte[] xs, int offset, int n) { - return GetToArray(xs, offset, n, 1, GetByte, (a, b, c) => _current.GetBytes(a, b, c)); + return GetToArray(xs, offset, n, 1, GetByte, (a, b, c) => Current.GetBytes(a, b, c)); } public override byte[] ToArray() { - throw new NotImplementedException(); + return GetBytes(Len); } public override int CopyToBuffer(ByteBuffer buffer) @@ -484,7 +491,7 @@ private ArrayLinearSeq(T[] array, int offset, int length) public bool IsEmpty { - get { return _length > 0; } + get { return _length == 0; } } public T Head @@ -516,6 +523,7 @@ private class Enumerator : IEnumerator { private readonly ILinearSeq _orig; private ILinearSeq _seq; + private T _current; public Enumerator(ILinearSeq seq) { @@ -530,8 +538,11 @@ public void Dispose() public bool MoveNext() { + if (_seq.IsEmpty) + return false; + _current = _seq.Head; _seq = _seq.Tail(); - return !_seq.IsEmpty; + return true; } public void Reset() @@ -541,7 +552,7 @@ public void Reset() public T Current { - get { return _seq.Head; } + get { return _current; } } object IEnumerator.Current diff --git a/src/core/Akka/Util/ByteString.cs b/src/core/Akka/Util/ByteString.cs index e4985a6f7b7..5cf6d722fbf 100644 --- a/src/core/Akka/Util/ByteString.cs +++ b/src/core/Akka/Util/ByteString.cs @@ -81,7 +81,7 @@ public static ByteString FromByteBuffer(ByteBuffer buffer) return Create(buffer); } - public static readonly ByteString Empty = new ByteString1C(new byte[0]); + public static readonly ByteString Empty = CompactByteString.EmptyCompactByteString; public static ByteStringBuilder NewBuilder() { @@ -225,6 +225,11 @@ public override string DecodeString(Encoding charset) { return charset.GetString(_length == _bytes.Length ? _bytes : ToArray()); } + + public override IEnumerator GetEnumerator() + { + return _bytes.Skip(_startIndex).Take(_length).GetEnumerator(); + } } internal class ByteStrings : ByteString @@ -499,9 +504,13 @@ public static ByteString Create(byte[] buffer) partial /*object*/ class CompactByteString { + internal static readonly CompactByteString EmptyCompactByteString = new ByteString1C(new byte[0]); + public static CompactByteString FromString(string str, Encoding encoding) { - return new ByteString1C(encoding.GetBytes(str)); + return string.IsNullOrEmpty(str) + ? EmptyCompactByteString + : new ByteString1C(encoding.GetBytes(str)); } public static ByteString FromArray(byte[] array, int offset, int length) From a36cdb128064ee0d6b459a7a23690115cade14c4 Mon Sep 17 00:00:00 2001 From: Filip Malachowicz Date: Tue, 11 Aug 2015 17:47:48 +0200 Subject: [PATCH 008/105] Issue #1226 implemented Both Put() and CleanUp() methods in class SimpleDnsCache.Cache is now immutable. --- src/core/Akka/IO/SimpleDnsCache.cs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/core/Akka/IO/SimpleDnsCache.cs b/src/core/Akka/IO/SimpleDnsCache.cs index 38b517e9028..7d1a3d665f4 100644 --- a/src/core/Akka/IO/SimpleDnsCache.cs +++ b/src/core/Akka/IO/SimpleDnsCache.cs @@ -19,8 +19,8 @@ internal interface IPeriodicCacheCleanup public class SimpleDnsCache : DnsBase, IPeriodicCacheCleanup { - private AtomicReference _cache; - private long _ticksBase; + private readonly AtomicReference _cache; + private readonly long _ticksBase; public SimpleDnsCache() { @@ -58,10 +58,10 @@ public void CleanUp() class Cache { private readonly SortedSet _queue; - private readonly IDictionary _cache; + private readonly Dictionary _cache; private readonly Func _clock; - public Cache(SortedSet queue, IDictionary cache, Func clock) + public Cache(SortedSet queue, Dictionary cache, Func clock) { _queue = queue; _cache = cache; @@ -79,12 +79,11 @@ public Dns.Resolved Get(string name) public Cache Put(Dns.Resolved answer, long ttl) { var until = _clock() + ttl; - _queue.Add(new ExpiryEntry(answer.Name, until)); - if (_cache.ContainsKey(answer.Name)) - _cache[answer.Name] = new CacheEntry(answer, until); - else - _cache.Add(answer.Name, new CacheEntry(answer, until)); - return this; + + return new Cache( + queue: new SortedSet(_queue) { new ExpiryEntry(answer.Name, until) }, + cache: new Dictionary(_cache) { { answer.Name, new CacheEntry(answer, until) } }, + clock: _clock); } public Cache Cleanup() @@ -98,7 +97,7 @@ public Cache Cleanup() if (_cache.ContainsKey(name) && !_cache[name].IsValid(now)) _cache.Remove(name); } - return new Cache(_queue, _cache, _clock); + return new Cache(new SortedSet(), new Dictionary(_cache), _clock); } } From 4af2cfbcaafa33ea04a1a8b1aa6486e78bd6f821 Mon Sep 17 00:00:00 2001 From: willieferguson Date: Tue, 11 Aug 2015 17:59:42 +0200 Subject: [PATCH 009/105] akka-io: fixed #1225 - High CPU load using the Akka.IO TCP server --- src/core/Akka/IO/SelectionHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Akka/IO/SelectionHandler.cs b/src/core/Akka/IO/SelectionHandler.cs index 7438c8f4c64..07ea19ebcb2 100644 --- a/src/core/Akka/IO/SelectionHandler.cs +++ b/src/core/Akka/IO/SelectionHandler.cs @@ -212,7 +212,7 @@ private void Select() var writeable = _write.Keys.ToList(); try { - Socket.Select(readable, writeable, null, 0); + Socket.Select(readable, writeable, null, 1); foreach (var socket in readable) { var channel = _read[socket]; From 984a0b8e269a08dc39267c8e2b932daef2b9495a Mon Sep 17 00:00:00 2001 From: Filip Malachowicz Date: Tue, 11 Aug 2015 18:40:39 +0200 Subject: [PATCH 010/105] Fixed failing SimpleDnsCacheSpec Changed SimpleDnsCache.Put() to pass SimpleDnsCacheSpec.Cache_should_be_updated_with_the_latest_resolved --- src/core/Akka/IO/SimpleDnsCache.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/core/Akka/IO/SimpleDnsCache.cs b/src/core/Akka/IO/SimpleDnsCache.cs index 7d1a3d665f4..5a295417e1c 100644 --- a/src/core/Akka/IO/SimpleDnsCache.cs +++ b/src/core/Akka/IO/SimpleDnsCache.cs @@ -79,10 +79,16 @@ public Dns.Resolved Get(string name) public Cache Put(Dns.Resolved answer, long ttl) { var until = _clock() + ttl; - + + var cache = new Dictionary(_cache); + if (cache.ContainsKey(answer.Name)) + cache[answer.Name] = new CacheEntry(answer, until); + else + cache.Add(answer.Name, new CacheEntry(answer, until)); + return new Cache( - queue: new SortedSet(_queue) { new ExpiryEntry(answer.Name, until) }, - cache: new Dictionary(_cache) { { answer.Name, new CacheEntry(answer, until) } }, + queue: new SortedSet(_queue, new ExpiryEntryComparer()) { new ExpiryEntry(answer.Name, until) }, + cache: cache, clock: _clock); } From 6171eb176fa202b5e75d96b5655cc2cb36cfe505 Mon Sep 17 00:00:00 2001 From: willieferguson Date: Tue, 11 Aug 2015 18:41:30 +0200 Subject: [PATCH 011/105] akka-io: Temporarily ignore TcpConnectionSpec until intermittent test failures can be resolved --- src/core/Akka.Tests/IO/TcpConnectionSpec.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Akka.Tests/IO/TcpConnectionSpec.cs b/src/core/Akka.Tests/IO/TcpConnectionSpec.cs index 2378fab1d4b..978b01a319d 100644 --- a/src/core/Akka.Tests/IO/TcpConnectionSpec.cs +++ b/src/core/Akka.Tests/IO/TcpConnectionSpec.cs @@ -25,7 +25,7 @@ namespace Akka.Tests.IO { - public class TcpConnectionSpec : AkkaSpec + class TcpConnectionSpec : AkkaSpec { internal class Ack : Tcp.Event { From 39e400b601009ec50b12b532f8599f98c8a8e936 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 11 Aug 2015 00:00:00 +0000 Subject: [PATCH 012/105] Akka.Remote.TestKit multi-node test tool fixes. Run multi-node tests from any directory. Akka.Remote multi-node test project. System.Collections.Immutable NuGet package upgrade. --- build.fsx | 21 ++- src/Akka.sln | 16 +- src/SharedAssemblyInfo.cs | 4 +- .../PersistenceBenchmark.csproj | 9 + .../Akka.Cluster.Tests.MultiNode.csproj} | 10 +- .../ClusterDeathWatchSpec.cs | 2 +- .../ConvergenceSpec.cs | 3 +- .../FailureDetectorPuppet.cs | 2 +- .../InitialHeartbeatSpec.cs | 3 +- .../JoinInProgressSpec.cs | 2 +- .../JoinSeedNodeSpec.cs | 2 +- .../LeaderLeavingSpec.cs | 3 +- .../MultiNodeClusterSpec.cs | 6 +- .../MultiNodeLoggingConfig.cs | 4 +- .../Properties/AssemblyInfo.cs | 4 +- .../ClusterConsistentHashingGroupSpec.cs | 2 +- .../ClusterConsistentHashingRouterSpec.cs | 2 +- .../packages.config | 2 +- .../Akka.Cluster.Tests.csproj | 7 +- .../ClusterDomainEventPublisherSpec.cs | 1 - src/core/Akka.Cluster.Tests/ClusterSpec.cs | 1 - src/core/Akka.Cluster.Tests/packages.config | 2 +- src/core/Akka.Cluster/Akka.Cluster.csproj | 7 +- .../Akka.Cluster/Properties/AssemblyInfo.cs | 2 +- src/core/Akka.Cluster/packages.config | 2 +- .../Akka.FSharp/Properties/AssemblyInfo.fs | 6 +- .../Akka.MultiNodeTestRunner.csproj | 32 +++- src/core/Akka.MultiNodeTestRunner/Program.cs | 9 +- .../Akka.MultiNodeTestRunner/packages.config | 2 + .../Akka.NodeTestRunner.csproj | 4 - src/core/Akka.NodeTestRunner/Program.cs | 12 +- .../Akka.Remote.TestKit.Tests.csproj | 7 +- .../Akka.Remote.TestKit.Tests/packages.config | 2 +- .../Akka.Remote.TestKit.csproj | 15 +- .../MultiNodeFact.cs | 2 +- src/core/Akka.Remote.TestKit/packages.config | 5 +- .../Akka.Remote.Tests.MultiNode.csproj | 108 +++++++++++ .../NewRemoteActorSpec.cs | 171 ++++++++++++++++++ .../Properties/AssemblyInfo.cs | 36 ++++ .../packages.config | 9 + .../Akka.Remote/Properties/AssemblyInfo.cs | 2 +- src/core/Akka/Properties/AssemblyInfo.cs | 2 +- .../Samples.Cluster.Transformation.csproj | 2 +- .../packages.config | 2 +- ...mples.Cluster.ConsistentHashRouting.csproj | 3 +- .../packages.config | 2 +- .../Samples.Cluster.Simple.csproj | 5 +- .../Samples.Cluster.Simple/packages.config | 2 +- .../Stocks/SymbolLookup/SymbolLookup.csproj | 5 +- .../Stocks/SymbolLookup/packages.config | 2 +- 50 files changed, 480 insertions(+), 86 deletions(-) rename src/core/{Akka.MultiNodeTests/Akka.MultiNodeTests.csproj => Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj} (93%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/ClusterDeathWatchSpec.cs (99%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/ConvergenceSpec.cs (99%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/FailureDetectorPuppet.cs (98%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/InitialHeartbeatSpec.cs (99%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/JoinInProgressSpec.cs (98%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/JoinSeedNodeSpec.cs (98%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/LeaderLeavingSpec.cs (99%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/MultiNodeClusterSpec.cs (98%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/MultiNodeLoggingConfig.cs (92%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/Properties/AssemblyInfo.cs (91%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/Routing/ClusterConsistentHashingGroupSpec.cs (99%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/Routing/ClusterConsistentHashingRouterSpec.cs (99%) rename src/core/{Akka.MultiNodeTests => Akka.Cluster.Tests.MultiNode}/packages.config (82%) rename src/core/{Akka.MultiNodeTests => Akka.Remote.TestKit}/MultiNodeFact.cs (97%) create mode 100644 src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj create mode 100644 src/core/Akka.Remote.Tests.MultiNode/NewRemoteActorSpec.cs create mode 100644 src/core/Akka.Remote.Tests.MultiNode/Properties/AssemblyInfo.cs create mode 100644 src/core/Akka.Remote.Tests.MultiNode/packages.config diff --git a/build.fsx b/build.fsx index 09b32b0e406..a273eabc90a 100644 --- a/build.fsx +++ b/build.fsx @@ -249,21 +249,26 @@ Target "RunTestsMono" <| fun _ -> Target "MultiNodeTests" <| fun _ -> let multiNodeTestPath = findToolInSubPath "Akka.MultiNodeTestRunner.exe" "bin/core/Akka.MultiNodeTestRunner*" + let multiNodeTestAssemblies = !! "src/**/bin/Release/*.Tests.MultiNode.dll" printfn "Using MultiNodeTestRunner: %s" multiNodeTestPath - let spec = getBuildParam "spec" + let runMultiNodeSpec assembly = + let spec = getBuildParam "spec" - let args = new StringBuilder() - |> append "Akka.MultiNodeTests.dll" + let args = new StringBuilder() + |> append assembly |> append "-Dmultinode.enable-filesink=on" |> appendIfNotNullOrEmpty spec "-Dmultinode.test-spec=" |> toText - let result = ExecProcess(fun info -> - info.FileName <- multiNodeTestPath - info.WorkingDirectory <- (Path.GetDirectoryName (FullName multiNodeTestPath)) - info.Arguments <- args) (System.TimeSpan.FromMinutes 60.0) (* This is a VERY long running task. *) - if result <> 0 then failwithf "MultiNodeTestRunner failed. %s %s" multiNodeTestPath args + let result = ExecProcess(fun info -> + info.FileName <- multiNodeTestPath + info.WorkingDirectory <- (Path.GetDirectoryName (FullName multiNodeTestPath)) + info.Arguments <- args) (System.TimeSpan.FromMinutes 60.0) (* This is a VERY long running task. *) + if result <> 0 then failwithf "MultiNodeTestRunner failed. %s %s" multiNodeTestPath args + + multiNodeTestAssemblies |> Seq.iter (runMultiNodeSpec) + //-------------------------------------------------------------------------------- // Nuget targets diff --git a/src/Akka.sln b/src/Akka.sln index 240dd07079f..5d26116d625 100644 --- a/src/Akka.sln +++ b/src/Akka.sln @@ -1,7 +1,5 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 # Visual Studio 2013 VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 @@ -210,14 +208,17 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.DI.StructureMap.Tests" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.DI.Unity.Tests", "contrib\dependencyInjection\Akka.DI.Unity.Tests\Akka.DI.Unity.Tests.csproj", "{54C76459-D93B-4FF5-A051-4D9329EF4201}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.MultiNodeTests", "core\Akka.MultiNodeTests\Akka.MultiNodeTests.csproj", "{F0781BEA-5BA0-4AF0-BB15-E3F209B681F5}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Tests.MultiNode", "core\Akka.Cluster.Tests.MultiNode\Akka.Cluster.Tests.MultiNode.csproj", "{F0781BEA-5BA0-4AF0-BB15-E3F209B681F5}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PersistenceBenchmark", "benchmark\PersistenceBenchmark\PersistenceBenchmark.csproj", "{39E6F51F-FA1E-4C62-B8F8-19065DE6D55D}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A59BAE84-70E2-46A0-9E26-7413C103E2D7}" ProjectSection(SolutionItems) = preProject WebEssentials-Settings.json = WebEssentials-Settings.json EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Remote.Tests.MultiNode", "core\Akka.Remote.Tests.MultiNode\Akka.Remote.Tests.MultiNode.csproj", "{C9105C76-B084-4DA1-9348-1C74A8F22F6B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug Mono|Any CPU = Debug Mono|Any CPU @@ -783,6 +784,14 @@ Global {39E6F51F-FA1E-4C62-B8F8-19065DE6D55D}.Release Mono|Any CPU.Build.0 = Release|Any CPU {39E6F51F-FA1E-4C62-B8F8-19065DE6D55D}.Release|Any CPU.ActiveCfg = Release|Any CPU {39E6F51F-FA1E-4C62-B8F8-19065DE6D55D}.Release|Any CPU.Build.0 = Release|Any CPU + {C9105C76-B084-4DA1-9348-1C74A8F22F6B}.Debug Mono|Any CPU.ActiveCfg = Debug|Any CPU + {C9105C76-B084-4DA1-9348-1C74A8F22F6B}.Debug Mono|Any CPU.Build.0 = Debug|Any CPU + {C9105C76-B084-4DA1-9348-1C74A8F22F6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C9105C76-B084-4DA1-9348-1C74A8F22F6B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C9105C76-B084-4DA1-9348-1C74A8F22F6B}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {C9105C76-B084-4DA1-9348-1C74A8F22F6B}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {C9105C76-B084-4DA1-9348-1C74A8F22F6B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C9105C76-B084-4DA1-9348-1C74A8F22F6B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -878,5 +887,6 @@ Global {54C76459-D93B-4FF5-A051-4D9329EF4201} = {B1D10183-8FAE-4506-B935-403FCED89BDB} {F0781BEA-5BA0-4AF0-BB15-E3F209B681F5} = {01167D3C-49C4-4CDE-9787-C176D139ACDD} {39E6F51F-FA1E-4C62-B8F8-19065DE6D55D} = {73108242-625A-4D7B-AA09-63375DBAE464} + {C9105C76-B084-4DA1-9348-1C74A8F22F6B} = {01167D3C-49C4-4CDE-9787-C176D139ACDD} EndGlobalSection EndGlobal diff --git a/src/SharedAssemblyInfo.cs b/src/SharedAssemblyInfo.cs index 42a94a0fe1a..fcb5f369368 100644 --- a/src/SharedAssemblyInfo.cs +++ b/src/SharedAssemblyInfo.cs @@ -4,5 +4,5 @@ [assembly: AssemblyCompanyAttribute("Akka.NET Team")] [assembly: AssemblyCopyrightAttribute("Copyright © 2013-2015 Akka.NET Team")] [assembly: AssemblyTrademarkAttribute("")] -[assembly: AssemblyVersionAttribute("1.0.4.0")] -[assembly: AssemblyFileVersionAttribute("1.0.4.0")] +[assembly: AssemblyVersionAttribute("1.0.5.0")] +[assembly: AssemblyFileVersionAttribute("1.0.5.0")] diff --git a/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj b/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj index 9a6a870ba41..11b1a369112 100644 --- a/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj +++ b/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj @@ -11,6 +11,8 @@ PersistenceBenchmark v4.5 512 + ..\..\ + true AnyCPU @@ -74,6 +76,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests.MultiNode/NewRemoteActorSpec.cs b/src/core/Akka.Remote.Tests.MultiNode/NewRemoteActorSpec.cs new file mode 100644 index 00000000000..208db3b0983 --- /dev/null +++ b/src/core/Akka.Remote.Tests.MultiNode/NewRemoteActorSpec.cs @@ -0,0 +1,171 @@ +using System; +using Akka.Actor; +using Akka.Configuration; +using Akka.Remote.TestKit; +using Akka.TestKit; +using Xunit; + +namespace Akka.Remote.Tests.MultiNode +{ + public class NewRemoteActorMultiNodeSpecConfig : MultiNodeConfig + { + #region Internal actor classes + + public class SomeActor : UntypedActor + { + protected override void OnReceive(object message) + { + if(message.Equals("identify")) + Sender.Tell(Self); + } + } + + public class SomeActorWithParam : UntypedActor + { + private string _ignored; + + public SomeActorWithParam(string ignored) + { + _ignored = ignored; + } + + + protected override void OnReceive(object message) + { + if (message.Equals("identify")) + Sender.Tell(Self); + } + } + + #endregion + + readonly RoleName _master; + public RoleName Master { get { return _master; } } + readonly RoleName _slave; + public RoleName Slave { get { return _slave; } } + + public NewRemoteActorMultiNodeSpecConfig() + { + _master = Role("master"); + _slave = Role("slave"); + + CommonConfig = + DebugConfig(false) + .WithFallback(ConfigurationFactory.ParseString("akka.remote.log-remote-lifecycle-events = off")); + + DeployOn(Master, @" + /service-hello.remote = ""@slave@"" + /service-hello-null.remote = ""@slave@"" + /service-hello3.remote = ""@slave@"" + "); + + DeployOnAll(@"/service-hello2.remote = ""@slave@"""); + } + } + + public class NewRemoteActorSpecNode1 : NewRemoteActorSpec { } + public class NewRemoteActorSpecNode2 : NewRemoteActorSpec { } + + public class NewRemoteActorSpec : MultiNodeSpec + { + private NewRemoteActorMultiNodeSpecConfig _config; + + public NewRemoteActorSpec() + : this(new NewRemoteActorMultiNodeSpecConfig()) + { + } + + public NewRemoteActorSpec(NewRemoteActorMultiNodeSpecConfig config) : base(config) + { + _config = config; + } + + protected override int InitialParticipantsValueFactory + { + get { return Roles.Count; } + } + + protected override bool VerifySystemShutdown + { + get { return true; } + } + + [MultiNodeFact] + public void NewRemoteActorSpecs() + { + ANewRemoteActorMustBeLocallyInstantiatedOnARemoteNodeAndBeAbleToCommunicateThroughItsRemoteActorRef(); + ANewRemoteActorMustBeLocallyInstantiatedOnARemoteNodeWithNullParameterAndBeAbleToCommunicateThroughItsRemoteActorRef(); + ANewRemoteActorMustBeAbleToShutdownSystemWhenUsingRemoteDeployedActor(); + } + + public void ANewRemoteActorMustBeLocallyInstantiatedOnARemoteNodeAndBeAbleToCommunicateThroughItsRemoteActorRef() + { + RunOn(() => + { + var actor = Sys.ActorOf(Props.Create(() => new NewRemoteActorMultiNodeSpecConfig.SomeActor()), + "service-hello"); + var foo = Assert.IsType(actor); + actor.Path.Address.ShouldBe(Node(_config.Slave).Address); + + var slaveAddress = TestConductor.GetAddressFor(_config.Slave).Result; + actor.Tell("identify"); + ExpectMsg().Path.Address.ShouldBe(slaveAddress); + }, _config.Master); + + EnterBarrier("done"); + } + + public void ANewRemoteActorMustBeLocallyInstantiatedOnARemoteNodeWithNullParameterAndBeAbleToCommunicateThroughItsRemoteActorRef() + { + RunOn(() => + { + var actor = Sys.ActorOf(Props.Create(() => new NewRemoteActorMultiNodeSpecConfig.SomeActorWithParam(null)), + "service-hello2"); + var foo = Assert.IsType(actor); + actor.Path.Address.ShouldBe(Node(_config.Slave).Address); + + var slaveAddress = TestConductor.GetAddressFor(_config.Slave).Result; + actor.Tell("identify"); + ExpectMsg().Path.Address.ShouldBe(slaveAddress); + }, _config.Master); + + EnterBarrier("done"); + } + + public void ANewRemoteActorMustBeAbleToShutdownSystemWhenUsingRemoteDeployedActor() + { + Within(TimeSpan.FromSeconds(20), () => + { + RunOn(() => + { + var actor = Sys.ActorOf(Props.Create(() => new NewRemoteActorMultiNodeSpecConfig.SomeActor()), + "service-hello3"); + var foo = Assert.IsType(actor); + actor.Path.Address.ShouldBe(Node(_config.Slave).Address); + + // This watch is in race with the shutdown of the watched system. This race should remain, as the test should + // handle both cases: + // - remote system receives watch, replies with DeathWatchNotification + // - remote system never gets watch, but DeathWatch heartbeats time out, and AddressTerminated is generated + // (this needs some time to happen) + Watch(actor); + EnterBarrier("deployed"); + + // master system is supposed to be shutdown after slave + // this should be triggered by slave system shutdown + ExpectTerminated(actor); + }, _config.Master); + + RunOn(() => + { + EnterBarrier("deployed"); + }, _config.Slave); + + // Important that this is the last test. + // It should not be any barriers here. + // verifySystemShutdown = true will ensure that system shutdown is successful + VerifySystemShutdown.ShouldBeTrue("Shutdown should be verified!"); + }); + } + } +} diff --git a/src/core/Akka.Remote.Tests.MultiNode/Properties/AssemblyInfo.cs b/src/core/Akka.Remote.Tests.MultiNode/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..f27b1862c05 --- /dev/null +++ b/src/core/Akka.Remote.Tests.MultiNode/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Akka.Remote.Tests.MultiNode")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Akka.Remote.Tests.MultiNode")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8b3e94f7-0f92-4955-93ab-93bdd9d2fa34")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/core/Akka.Remote.Tests.MultiNode/packages.config b/src/core/Akka.Remote.Tests.MultiNode/packages.config new file mode 100644 index 00000000000..15502b4d7f9 --- /dev/null +++ b/src/core/Akka.Remote.Tests.MultiNode/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote/Properties/AssemblyInfo.cs b/src/core/Akka.Remote/Properties/AssemblyInfo.cs index f35e64af12a..ab3139f94c8 100644 --- a/src/core/Akka.Remote/Properties/AssemblyInfo.cs +++ b/src/core/Akka.Remote/Properties/AssemblyInfo.cs @@ -31,4 +31,4 @@ [assembly: InternalsVisibleTo("Akka.Remote.Tests")] [assembly: InternalsVisibleTo("Akka.Cluster")] [assembly: InternalsVisibleTo("Akka.Cluster.Tests")] -[assembly: InternalsVisibleTo("Akka.MultiNodeTests")] +[assembly: InternalsVisibleTo("Akka.Cluster.Tests.MultiNode")] diff --git a/src/core/Akka/Properties/AssemblyInfo.cs b/src/core/Akka/Properties/AssemblyInfo.cs index b407a191e1c..e0550a65f0a 100644 --- a/src/core/Akka/Properties/AssemblyInfo.cs +++ b/src/core/Akka/Properties/AssemblyInfo.cs @@ -35,4 +35,4 @@ [assembly: InternalsVisibleTo("Akka.Cluster")] [assembly: InternalsVisibleTo("Akka.Cluster.Tests")] [assembly: InternalsVisibleTo("Akka.MultiNodeTestRunner.Shared.Tests")] -[assembly: InternalsVisibleTo("Akka.MultiNodeTests")] +[assembly: InternalsVisibleTo("Akka.Cluster.Tests.MultiNode")] diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj index 49d217bedbe..06f0af15eb1 100644 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj @@ -36,7 +36,7 @@ - ..\..\..\..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + ..\..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/packages.config b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/packages.config index 0b3cc3386bd..8a2bcdbc2dd 100644 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/packages.config +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj index a1067e6b236..52fc6b8538a 100644 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj @@ -36,7 +36,8 @@ - ..\..\..\..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + ..\..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/packages.config b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/packages.config index 0b3cc3386bd..8a2bcdbc2dd 100644 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/packages.config +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj b/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj index 8582dee911a..a231e642bad 100644 --- a/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj +++ b/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj @@ -35,8 +35,9 @@ - - ..\..\..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + False + ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll diff --git a/src/examples/Cluster/Samples.Cluster.Simple/packages.config b/src/examples/Cluster/Samples.Cluster.Simple/packages.config index 0b3cc3386bd..8a2bcdbc2dd 100644 --- a/src/examples/Cluster/Samples.Cluster.Simple/packages.config +++ b/src/examples/Cluster/Samples.Cluster.Simple/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/src/examples/Stocks/SymbolLookup/SymbolLookup.csproj b/src/examples/Stocks/SymbolLookup/SymbolLookup.csproj index 1e6f5632e71..d8fbe31e2b1 100644 --- a/src/examples/Stocks/SymbolLookup/SymbolLookup.csproj +++ b/src/examples/Stocks/SymbolLookup/SymbolLookup.csproj @@ -61,8 +61,9 @@ ..\..\..\packages\qdfeed.1.1.0\lib\net45\QDFeedParser.dll - - ..\..\..\packages\Microsoft.Bcl.Immutable.1.0.30\lib\portable-net45+win8+wp8\System.Collections.Immutable.dll + + False + ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll diff --git a/src/examples/Stocks/SymbolLookup/packages.config b/src/examples/Stocks/SymbolLookup/packages.config index 6c19783cbfb..6aa2a478aed 100644 --- a/src/examples/Stocks/SymbolLookup/packages.config +++ b/src/examples/Stocks/SymbolLookup/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file From e545780d36cfb805b2014746a2e97006894c2e00 Mon Sep 17 00:00:00 2001 From: willieferguson Date: Wed, 12 Aug 2015 08:53:35 +0200 Subject: [PATCH 013/105] akka-io: Stop select loop on idle --- src/core/Akka/IO/SelectionHandler.cs | 86 +++++++++++++++------------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/src/core/Akka/IO/SelectionHandler.cs b/src/core/Akka/IO/SelectionHandler.cs index 07ea19ebcb2..b3753d3f39e 100644 --- a/src/core/Akka/IO/SelectionHandler.cs +++ b/src/core/Akka/IO/SelectionHandler.cs @@ -196,7 +196,6 @@ public ChannelRegistryImpl(ILoggingAdapter log) { _log = log; _executionContext = new SingleThreadExecutionContext(); - Execute(Select); } private void Execute(Action action) @@ -206,40 +205,39 @@ private void Execute(Action action) private void Select() { - if (_read.Count > 0 || _write.Count > 0) + if (_read.Count == 0 && _write.Count == 0) return; // Stop select loop when no more interested sockets. It will be started again once a socket is registered + + var readable = _read.Keys.ToList(); + var writeable = _write.Keys.ToList(); + try { - var readable = _read.Keys.ToList(); - var writeable = _write.Keys.ToList(); - try + Socket.Select(readable, writeable, null, 1); + foreach (var socket in readable) { - Socket.Select(readable, writeable, null, 1); - foreach (var socket in readable) - { - var channel = _read[socket]; - if (channel.IsOpen()) - channel.Connection.Tell(ChannelReadable.Instance); - else - channel.Connection.Tell(ChannelAcceptable.Instance); - _read.Remove(socket); - } - foreach (var socket in writeable) - { - var channel = _write[socket]; - if (channel.IsOpen()) - channel.Connection.Tell(ChannelWritable.Instance); - else - channel.Connection.Tell(ChannelConnectable.Instance); - _write.Remove(socket); - } + var channel = _read[socket]; + if (channel.IsOpen()) + channel.Connection.Tell(ChannelReadable.Instance); + else + channel.Connection.Tell(ChannelAcceptable.Instance); + _read.Remove(socket); } - catch (SocketException ex) + foreach (var socket in writeable) { - if (ex.SocketErrorCode == SocketError.NotSocket) - { - // One of the sockets has been closed - readable.Where(x => !x.Connected).ForEach(x =>_read.Remove(x)); - writeable.Where(x => !x.Connected).ForEach(x => _write.Remove(x)); - } + var channel = _write[socket]; + if (channel.IsOpen()) + channel.Connection.Tell(ChannelWritable.Instance); + else + channel.Connection.Tell(ChannelConnectable.Instance); + _write.Remove(socket); + } + } + catch (SocketException ex) + { + if (ex.SocketErrorCode == SocketError.NotSocket) + { + // One of the sockets has been closed + readable.Where(x => !x.Connected).ForEach(x =>_read.Remove(x)); + writeable.Where(x => !x.Connected).ForEach(x => _write.Remove(x)); } } Execute(Select); @@ -262,14 +260,24 @@ private void EnableInterest(SocketChannel channel, SocketAsyncOperation op) { switch (op) { - case SocketAsyncOperation.Accept: - case SocketAsyncOperation.Receive: - Execute(() => _read.Add(channel.Socket, channel)); - break; - case SocketAsyncOperation.Connect: - case SocketAsyncOperation.Send: - Execute(() => _write.Add(channel.Socket, channel)); - break; + case SocketAsyncOperation.Accept: + case SocketAsyncOperation.Receive: + Execute(() => + { + _read.Add(channel.Socket, channel); + if (_read.Count == 1 && _write.Count == 0) // Start the select loop on initial enable interest + Select(); // The select loop will stop itself if no more interested sockets + }); + break; + case SocketAsyncOperation.Connect: + case SocketAsyncOperation.Send: + Execute(() => + { + _write.Add(channel.Socket, channel); // Start the select loop on initial enable interest + if (_read.Count == 0 && _write.Count == 1) // The select loop will stop itself if no more interested sockets + Select(); + }); + break; } } private void DisableInterest(SocketChannel channel, SocketAsyncOperation op) From 2404afd83860d59bdab4b696e0a9ce0ec265eab8 Mon Sep 17 00:00:00 2001 From: Graeme Bradbury Date: Tue, 11 Aug 2015 20:40:36 +0100 Subject: [PATCH 014/105] Upgrade FAKE to version 4.1.0 Altered build command to install 4.1.0 Added .fake/ directory to .gitignore. Directory contains build artifacts. Removed Fake 3.17.0 from packages.config as build.cmd dicates version. --- .gitignore | 3 +++ build.cmd | 6 +++--- src/.nuget/packages.config | 3 +-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index d5983cb5512..a68c4f06cab 100644 --- a/.gitignore +++ b/.gitignore @@ -214,3 +214,6 @@ FakesAssemblies/ /src/.Akka.boltdata/TestResults.json resetdev.bat /src/packages/repositories.config + +# FAKE build folder +.fake/ diff --git a/build.cmd b/build.cmd index 1ab7b81ac20..55899b04fdf 100644 --- a/build.cmd +++ b/build.cmd @@ -4,12 +4,12 @@ pushd %~dp0 src\.nuget\NuGet.exe update -self -src\.nuget\NuGet.exe install FAKE -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion -Version 3.28.8 +src\.nuget\NuGet.exe install FAKE -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion -Version 4.1.0 src\.nuget\NuGet.exe install xunit.runner.console -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages\FAKE -ExcludeVersion -Version 2.0.0 src\.nuget\NuGet.exe install nunit.runners -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages\FAKE -ExcludeVersion -Version 2.6.4 -if not exist src\packages\SourceLink.Fake\tools\SourceLink.fsx ( +if not exist src\packages\SourceLink.Fake\tools\SourceLink.fsx ( src\.nuget\nuget.exe install SourceLink.Fake -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion ) rem cls @@ -17,4 +17,4 @@ rem cls set encoding=utf-8 src\packages\FAKE\tools\FAKE.exe build.fsx %* -popd \ No newline at end of file +popd diff --git a/src/.nuget/packages.config b/src/.nuget/packages.config index 086897c3cb9..569e1bea867 100644 --- a/src/.nuget/packages.config +++ b/src/.nuget/packages.config @@ -1,4 +1,3 @@  - - \ No newline at end of file + From 894815cc5b36343c930aa9b1cf45d4f419b115ca Mon Sep 17 00:00:00 2001 From: Bartosz Sypytkowski Date: Tue, 11 Aug 2015 21:18:16 +0200 Subject: [PATCH 015/105] implemented event adapters implemented event adapters update journal proxy logic event adapters - 2 specs remaining fixed configuration mapping for event adapters --- .../Journal/QueryMapper.cs | 8 +- .../Journal/JournalSpec.cs | 2 +- .../Akka.Persistence.Tests.csproj | 2 + .../EndToEndEventAdapterSpec.cs | 392 ++++++++++++++++++ .../MemoryEventAdapterSpec.cs | 386 +++++++++++++++++ .../Akka.Persistence/Akka.Persistence.csproj | 2 + .../Akka.Persistence/InternalExtensions.cs | 2 + .../Journal/AsyncWriteJournal.cs | 35 +- .../Journal/AsyncWriteProxy.cs | 28 +- .../Akka.Persistence/Journal/EventAdapters.cs | 282 +++++++++++++ .../Journal/EventSequences.cs | 106 +++++ .../Akka.Persistence/Journal/MemoryJournal.cs | 42 +- .../Journal/SyncWriteJournal.cs | 8 +- .../Akka.Persistence/Journal/WriteJournal.cs | 39 +- src/core/Akka.Persistence/Persistence.cs | 81 +++- src/core/Akka.Persistence/Persistent.cs | 31 +- src/core/Akka.Persistence/persistence.conf | 3 + src/examples/TcpEchoService.Server/Actors.cs | 4 +- 18 files changed, 1383 insertions(+), 70 deletions(-) create mode 100644 src/core/Akka.Persistence.Tests/EndToEndEventAdapterSpec.cs create mode 100644 src/core/Akka.Persistence.Tests/MemoryEventAdapterSpec.cs create mode 100644 src/core/Akka.Persistence/Journal/EventAdapters.cs create mode 100644 src/core/Akka.Persistence/Journal/EventSequences.cs diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/QueryMapper.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/QueryMapper.cs index b713e7cdea9..2bc8f3a9861 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/QueryMapper.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/QueryMapper.cs @@ -41,14 +41,14 @@ public IPersistentRepresentation Map(DbDataReader reader, IActorRef sender = nul var persistenceId = reader.GetString(0); var sequenceNr = reader.GetInt64(1); var isDeleted = reader.GetBoolean(2); - var payload = GetPayload(reader); + var payloadType = reader.GetString(3); + var payload = GetPayload(reader, payloadType); - return new Persistent(payload, sequenceNr, persistenceId, isDeleted, sender); + return new Persistent(payload, sequenceNr, payloadType, persistenceId, isDeleted, sender); } - private object GetPayload(DbDataReader reader) + private object GetPayload(DbDataReader reader, string payloadType) { - var payloadType = reader.GetString(3); var type = Type.GetType(payloadType, true); var binary = (byte[]) reader[4]; diff --git a/src/core/Akka.Persistence.TestKit/Journal/JournalSpec.cs b/src/core/Akka.Persistence.TestKit/Journal/JournalSpec.cs index 9585dd20f74..17fe4f0ba2a 100644 --- a/src/core/Akka.Persistence.TestKit/Journal/JournalSpec.cs +++ b/src/core/Akka.Persistence.TestKit/Journal/JournalSpec.cs @@ -75,7 +75,7 @@ protected bool IsReplayedMessage(ReplayedMessage message, long seqNr, bool isDel private Persistent[] WriteMessages(int from, int to, string pid, IActorRef sender) { - var messages = Enumerable.Range(from, to).Select(i => new Persistent("a-" + i, i, pid, false, sender)).ToArray(); + var messages = Enumerable.Range(from, to).Select(i => new Persistent("a-" + i, i, string.Empty, pid, false, sender)).ToArray(); var probe = CreateTestProbe(); Journal.Tell(new WriteMessages(messages, probe.Ref, ActorInstanceId)); diff --git a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj index 03471c551af..ef31b854a22 100644 --- a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj +++ b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj @@ -62,7 +62,9 @@ + + diff --git a/src/core/Akka.Persistence.Tests/EndToEndEventAdapterSpec.cs b/src/core/Akka.Persistence.Tests/EndToEndEventAdapterSpec.cs new file mode 100644 index 00000000000..939632dd91e --- /dev/null +++ b/src/core/Akka.Persistence.Tests/EndToEndEventAdapterSpec.cs @@ -0,0 +1,392 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using Akka.Actor; +using Akka.Configuration; +using Akka.Persistence.Journal; +using Akka.TestKit; +using Akka.TestKit.Xunit2; +using Xunit; + +namespace Akka.Persistence.Tests +{ + public class MemoryEndToEndAdapterSpec : EndToEndEventAdapterSpec + { + private static readonly Config Config = ConfigurationFactory.ParseString(@"akka.persistence.journal.inmem.shared = true"); + public MemoryEndToEndAdapterSpec() : base("inmem", PersistenceSpec.Configuration("inmem", "MemoryEndToEndAdapterSpec").WithFallback(Config)) + { + } + } + + internal class InternalTestKit : TestKitBase + { + public InternalTestKit(string actorSystemName, Config config) : base(new XunitAssertions(), config, actorSystemName) + { + } + } + + public abstract class EndToEndEventAdapterSpec : PersistenceSpec + { + private readonly string _journalName; + private readonly Config _journalConfig; + + #region Internal test classes + + internal interface IAppModel + { + object Payload { get; } + } + + [Serializable] + public sealed class A : IAppModel + { + public A(object payload) + { + Payload = payload; + } + + public object Payload { get; private set; } + } + + [Serializable] + public sealed class B : IAppModel + { + public B(object payload) + { + Payload = payload; + } + + public object Payload { get; private set; } + } + + [Serializable] + public sealed class NewA : IAppModel + { + public NewA(object payload) + { + Payload = payload; + } + + public object Payload { get; private set; } + } + + [Serializable] + public sealed class NewB : IAppModel + { + public NewB(object payload) + { + Payload = payload; + } + + public object Payload { get; private set; } + } + + [Serializable] + public sealed class Json + { + public readonly object Payload; + + public Json(object payload) + { + Payload = payload; + } + } + + public class AEndToEndAdapter : IEventAdapter + { + public AEndToEndAdapter(ExtendedActorSystem system) + { + } + + public string Manifest(object evt) + { + return evt.GetType().Name; + } + + public object ToJournal(object evt) + { + if (evt is IAppModel) return new Json((evt as IAppModel).Payload); + return null; + } + + public IEventSequence FromJournal(object evt, string manifest) + { + Json m; + if ((m = evt as Json) != null && m.Payload.ToString().StartsWith("a")) + return EventSequence.Single(new A(m.Payload)); + else + return EventSequence.Empty; + } + } + + public class NewAEndToEndAdapter : IEventAdapter + { + public NewAEndToEndAdapter(ExtendedActorSystem system) + { + } + + public string Manifest(object evt) + { + return evt.GetType().Name; + } + + public object ToJournal(object evt) + { + if (evt is IAppModel) return new Json((evt as IAppModel).Payload); + return null; + } + + public IEventSequence FromJournal(object evt, string manifest) + { + Json m; + if ((m = evt as Json) != null && m.Payload.ToString().StartsWith("a")) + return EventSequence.Single(new NewA(m.Payload)); + else + return EventSequence.Empty; + } + } + + public class BEndToEndAdapter : IEventAdapter + { + public BEndToEndAdapter(ExtendedActorSystem system) + { + } + + public string Manifest(object evt) + { + return evt.GetType().Name; + } + + public object ToJournal(object evt) + { + if (evt is IAppModel) return new Json((evt as IAppModel).Payload); + return null; + } + + public IEventSequence FromJournal(object evt, string manifest) + { + Json m; + if ((m = evt as Json) != null && m.Payload.ToString().StartsWith("b")) + return EventSequence.Single(new B(m.Payload)); + else + return EventSequence.Empty; + } + } + + public class NewBEndToEndAdapter : IEventAdapter + { + public NewBEndToEndAdapter(ExtendedActorSystem system) + { + } + + public string Manifest(object evt) + { + return evt.GetType().Name; + } + + public object ToJournal(object evt) + { + if (evt is IAppModel) return new Json((evt as IAppModel).Payload); + return null; + } + + public IEventSequence FromJournal(object evt, string manifest) + { + Json m; + if ((m = evt as Json) != null && m.Payload.ToString().StartsWith("b")) + return EventSequence.Single(new NewB(m.Payload)); + else + return EventSequence.Empty; + } + } + + public class EndToEndAdapterActor : NamedPersistentActor + { + private readonly LinkedList _state = new LinkedList(); + + private readonly IActorRef _probe; + public EndToEndAdapterActor(string name, string journalPluginId, IActorRef probe) : base(name) + { + _probe = probe; + JournalPluginId = journalPluginId; + } + + protected bool PersistIncomming(object message) + { + if (message is GetState) + { + foreach (var e in _state) + { + Sender.Tell(e); + } + } + else + { + var sender = Sender; + Persist(message, e => + { + _state.AddLast(e); + sender.Tell(e); + }); + } + return true; + } + + protected override bool ReceiveRecover(object message) + { + if (message is RecoveryCompleted) ; + else _state.AddLast(message); + return true; + } + + protected override bool ReceiveCommand(object message) + { + return PersistIncomming(message); + } + } + + #endregion + + protected readonly Config NoAdaptersConfig = ConfigurationFactory.Empty; + protected readonly Config AdaptersConfig; + private static readonly string AdaptersConfigFormat = @" + akka.persistence.journal {{ + {0} {{ + event-adapters {{ + a = ""{1}+AEndToEndAdapter, Akka.Persistence.Tests"" + b = ""{1}+BEndToEndAdapter, Akka.Persistence.Tests"" + }} + event-adapter-bindings {{ + # to journal + ""{1}+A, Akka.Persistence.Tests"" = a + ""{1}+B, Akka.Persistence.Tests"" = b + + # from journal + ""{1}+Json, Akka.Persistence.Tests"" = [a,b] + }} + }} + }}"; + protected readonly Config NewAdaptersConfig; + private static readonly string NewAdaptersConfigFormat = @" + akka.persistence.journal {{ + {0} {{ + event-adapters {{ + a = ""{1}+NewAEndToEndAdapter, Akka.Persistence.Tests"" + b = ""{1}+NewBEndToEndAdapter, Akka.Persistence.Tests"" + }} + event-adapter-bindings {{ + # to journal + ""{1}+A, Akka.Persistence.Tests"" = a + ""{1}+B, Akka.Persistence.Tests"" = b + + # from journal + ""{1}+Json, Akka.Persistence.Tests"" = [a,b] + }} + }} + }}"; + + protected EndToEndEventAdapterSpec(string journalName, Config journalConfig) + : base(PersistenceSpec.Configuration("inmem", "EndToEndEventAdapterSpec")) + { + _journalName = journalName; + _journalConfig = journalConfig; + + AdaptersConfig = string.Format(AdaptersConfigFormat, journalName, typeof(EndToEndEventAdapterSpec).FullName); + NewAdaptersConfig = string.Format(NewAdaptersConfigFormat, journalName, typeof(EndToEndEventAdapterSpec).FullName); + } + + private IActorRef Persister(string name, IActorRef probe, ActorSystem system) + { + return (system ?? Sys).ActorOf(Props.Create(() => new EndToEndAdapterActor(name, "akka.persistence.journal." + _journalName, probe)), name); + } + + private T WithActorSystem(string name, Config config, Func block) + { + var testKit = new InternalTestKit(name, _journalConfig.WithFallback(config)); + using (var system = testKit.Sys) + { + return block(system); + } + } + + [Fact] + public void EventAdapters_in_end_to_end_scenarios_should_use_the_same_adapter_when_reading_as_was_used_when_writing_to_journal() + { + WithActorSystem("SimpleSystem", AdaptersConfig, system => + { + var probe = new TestProbe(system, Assertions); + + var p1 = Persister("p1", probe, system); + var a = new A("a1"); + var b = new B("b1"); + p1.Tell(a, probe.Ref); + p1.Tell(b, probe.Ref); + + probe.ExpectMsg(x => x.Payload.Equals("a1")); + probe.ExpectMsg(x => x.Payload.Equals("b1")); + + probe.Watch(p1); + p1.Tell(PoisonPill.Instance); + probe.ExpectTerminated(p1); + + var p11 = Persister("p1", probe, system); + p11.Tell(GetState.Instance, probe.Ref); + + probe.ExpectMsg(x => x.Payload.Equals("a1")); + probe.ExpectMsg(x => x.Payload.Equals("b1")); + + return true; + }); + } + + [Fact] + public void EventAdapters_in_end_to_end_scenarios_should_allow_using_an_adapter_when_write_was_performed_without_an_adapter() + { + var pid = "p2"; + WithActorSystem("NoAdapterSystem", AdaptersConfig, system => + { + var probe = new TestProbe(system, Assertions); + + var p2 = Persister(pid, probe, system); + var a = new A("a1"); + var b = new B("b1"); + p2.Tell(a, probe.Ref); + p2.Tell(b, probe.Ref); + + probe.ExpectMsg(x => x.Payload.Equals("a1")); + probe.ExpectMsg(x => x.Payload.Equals("b1")); + + probe.Watch(p2); + p2.Tell(PoisonPill.Instance); + probe.ExpectTerminated(p2); + + var p21 = Persister(pid, probe, system); + p21.Tell(GetState.Instance, probe.Ref); + + probe.ExpectMsg(x => x.Payload.Equals("a1")); + probe.ExpectMsg(x => x.Payload.Equals("b1")); + + return true; + }); + + WithActorSystem("NoAdaptersAdded", NewAdaptersConfig, system => + { + var probe = new TestProbe(system, Assertions); + var p22 = Persister(pid, probe, system); + p22.Tell(GetState.Instance, probe.Ref); + + probe.ExpectMsg(x => x.Payload.Equals("a1")); + probe.ExpectMsg(x => x.Payload.Equals("b1")); + + return true; + }); + } + } +} \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/MemoryEventAdapterSpec.cs b/src/core/Akka.Persistence.Tests/MemoryEventAdapterSpec.cs new file mode 100644 index 00000000000..908a60f00c9 --- /dev/null +++ b/src/core/Akka.Persistence.Tests/MemoryEventAdapterSpec.cs @@ -0,0 +1,386 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Akka.Actor; +using Akka.Configuration; +using Akka.Event; +using Akka.Persistence.Journal; +using Akka.TestKit; +using Xunit; + +namespace Akka.Persistence.Tests +{ + public class MemoryEventAdapterSpec : PersistenceSpec + { + #region Internal test classes + + public interface IJournalModel + { + object Payload { get; } + ISet Tags { get; } + } + + [Serializable] + public sealed class Tagged : IJournalModel, IEquatable + { + public object Payload { get; private set; } + public ISet Tags { get; private set; } + + public Tagged(object payload, ISet tags) + { + Payload = payload; + Tags = tags; + } + + public bool Equals(IJournalModel other) + { + return other != null && Payload.Equals(other.Payload) && Tags.SetEquals(other.Tags); + } + + public override bool Equals(object obj) + { + return Equals(obj as IJournalModel); + } + } + + [Serializable] + public sealed class NotTagged : IJournalModel, IEquatable + { + public object Payload { get; private set; } + public ISet Tags { get { return new HashSet(); } } + + public NotTagged(object payload) + { + Payload = payload; + } + + public bool Equals(IJournalModel other) + { + return other != null && Payload.Equals(other.Payload) && Tags.SetEquals(other.Tags); + } + + public override bool Equals(object obj) + { + return Equals(obj as IJournalModel); + } + } + + public interface IDomainEvent { } + + [Serializable] + public sealed class TaggedDataChanged : IDomainEvent, IEquatable + { + public readonly ISet Tags; + public readonly int Value; + + public TaggedDataChanged(ISet tags, int value) + { + Tags = tags; + Value = value; + } + + public bool Equals(TaggedDataChanged other) + { + return other != null && Tags.SetEquals(other.Tags) && Value == other.Value; + } + + public override bool Equals(object obj) + { + return Equals(obj as TaggedDataChanged); + } + } + + [Serializable] + public sealed class UserDataChanged : IDomainEvent, IEquatable + { + public readonly string CountryCode; + public readonly int Age; + + public UserDataChanged(string countryCode, int age) + { + CountryCode = countryCode; + Age = age; + } + + public bool Equals(UserDataChanged other) + { + return other != null && Age == other.Age && CountryCode.Equals(other.CountryCode); + } + + public override bool Equals(object obj) + { + return Equals(obj as UserDataChanged); + } + } + + public class UserAgeTaggingAdapter : IEventAdapter + { + public readonly ISet Adult = new HashSet { "adult" }; + public readonly ISet Minor = new HashSet { "minor" }; + + public string Manifest(object evt) + { + return string.Empty; + } + + public object ToJournal(object evt) + { + var e = evt as UserDataChanged; + if (e == null) return new NotTagged(evt); + return new Tagged(e, e.Age > 18 ? Adult : Minor); + } + + public virtual IEventSequence FromJournal(object evt, string manifest) + { + IJournalModel m; + return EventSequence.Single((m = evt as IJournalModel) != null ? m.Payload : null); + } + } + + public class ReplayPassThroughAdapter : UserAgeTaggingAdapter + { + public override IEventSequence FromJournal(object evt, string manifest) + { + // don't unpack, just pass through the JournalModel + return EventSequence.Single(evt); + } + } + + public class LoggingAdapter : IEventAdapter + { + public readonly ILoggingAdapter Log; + public LoggingAdapter(ExtendedActorSystem system) + { + Log = system.Log; + } + + public string Manifest(object evt) + { + return string.Empty; + } + + public object ToJournal(object evt) + { + Log.Info("On it's way to the journal: {0}", evt); + return evt; + } + + public IEventSequence FromJournal(object evt, string manifest) + { + Log.Info("On it's way from the journal: {0}", evt); + return EventSequence.Single(evt); + } + } + + public class PersistAllIncommingActor : NamedPersistentActor + { + public readonly LinkedList State = new LinkedList(); + + public PersistAllIncommingActor(string name, string journalPluginId) : base(name) + { + JournalPluginId = journalPluginId; + } + + private bool PersistIncoming(object message) + { + if (message is GetState) + foreach (var e in State) + { + Sender.Tell(e); + } + else + { + var sender = Sender; + Persist(message, e => + { + State.AddLast(e); + sender.Tell(e); + }); + } + return true; + } + + protected override bool ReceiveRecover(object message) + { + if (message is RecoveryCompleted) ; + else + { + State.AddLast(message); + } + return true; + } + + protected override bool ReceiveCommand(object message) + { + return PersistIncoming(message); + } + } + + #endregion + + private readonly string _journalName; + private static readonly string JournalModelTypeName = typeof(IJournalModel).FullName + ", Akka.Persistence.Tests"; + private static readonly string DomainEventTypeName = typeof(IDomainEvent).FullName + ", Akka.Persistence.Tests"; + + private static readonly string _configFormat = @" + akka.persistence.journal {{ + common-event-adapters {{ + age = ""{0}"" + replay-pass-through = ""{1}"" + }} + inmem {{ + # change to path reference $akka.persistence.journal.common-event-adapters + event-adapters {{ + age = ""{0}"" + replay-pass-through = ""{1}"" + }} + event-adapter-bindings {{ + ""{2}"" = age + ""{3}"" = age + }} + }} + with-actor-system {{ + class = ""Akka.Persistence.Journal.MemoryJournal, Akka.Persistence"" + dispatcher = default-dispatcher + dir = ""journal-1"" + + event-adapters {{ + logging = ""{4}"" + }} + event-adapters-bindings {{ + ""System.Object"" = logging + }} + }} + replay-pass-through-adapter-journal {{ + class = ""Akka.Persistence.Journal.MemoryJournal, Akka.Persistence"" + dispatcher = default-dispatcher + dir = ""journal-2"" + + # change to path reference $akka.persistence.journal.common-event-adapters + event-adapters {{ + age = ""{0}"" + replay-pass-through = ""{1}"" + }} + event-adapter-bindings {{ + ""{2}"" = replay-pass-through + ""{3}"" = replay-pass-through + }} + }} + no-adapter {{ + class = ""Akka.Persistence.Journal.MemoryJournal, Akka.Persistence"" + dispatcher = default-dispatcher + dir = ""journal-3"" + }} + }}"; + + public static readonly string AdapterSpecConfig = string.Format(_configFormat, + typeof(UserAgeTaggingAdapter).FullName + ", Akka.Persistence.Tests", + typeof(ReplayPassThroughAdapter).FullName + ", Akka.Persistence.Tests", + DomainEventTypeName, + JournalModelTypeName, + typeof(LoggingAdapter).FullName + ", Akka.Persistence.Tests"); + + public MemoryEventAdapterSpec() + : this("inmem", PersistenceSpec.Configuration("inmem", "MemoryEventAdapterSpec"), ConfigurationFactory.ParseString(AdapterSpecConfig)) + { + + } + + protected MemoryEventAdapterSpec(string journalName, Config journalConfig, Config adapterConfig) + : base(journalConfig.WithFallback(adapterConfig)) + { + _journalName = journalName; + } + + private IActorRef Persister(string name, string journalName = null) + { + return Sys.ActorOf(Props.Create(() => new PersistAllIncommingActor(name, "akka.persistence.journal." + (journalName ?? _journalName))), name); + } + + private object ToJournal(object message, string journalName = null) + { + journalName = string.IsNullOrEmpty(journalName) ? _journalName : journalName; + return Persistence.Instance.Apply(Sys).AdaptersFor("akka.persistence.journal." + journalName).Get(message.GetType()).ToJournal(message); + } + + private object FromJournal(object message, string journalName = null) + { + journalName = string.IsNullOrEmpty(journalName) ? _journalName : journalName; + return Persistence.Instance.Apply(Sys).AdaptersFor("akka.persistence.journal." + journalName).Get(message.GetType()).FromJournal(message, string.Empty); + } + + [Fact] + public void EventAdapter_should_wrap_with_tags() + { + var e = new UserDataChanged("name", 42); + ToJournal(e).ShouldBe(new Tagged(e, new HashSet { "adult" })); + } + + [Fact] + public void EventAdapter_should_unwrap_when_reading() + { + var e = new UserDataChanged("name", 42); + var tagged = new Tagged(e, new HashSet { "adult" }); + + ToJournal(e).ShouldBe(tagged); + FromJournal(tagged, string.Empty).ShouldBe(new SingleEventSequence(e)); + } + + [Fact] + public void EventAdapter_should_create_adapter_requiring_actor_system() + { + var e = new UserDataChanged("name", 42); + + ToJournal(e, "with-actor-system").ShouldBe(e); + FromJournal(e, "with-actor-system").ShouldBe(new SingleEventSequence(e)); + } + + [Fact] + public void EventAdapter_should_store_events_after_applying_adapter() + { + var replayPassThroughJournalId = "replay-pass-through-adapter-journal"; + + var p1 = Persister("p1", replayPassThroughJournalId); + var m1 = new UserDataChanged("name", 64); + var m2 = "hello"; + + p1.Tell(m1); + p1.Tell(m2); + ExpectMsg(m1); + ExpectMsg(m2); + + Watch(p1); + p1.Tell(PoisonPill.Instance); + ExpectTerminated(p1); + + var p11 = Persister("p1", replayPassThroughJournalId); + p11.Tell(GetState.Instance); + ExpectMsg(new Tagged(m1, new HashSet { "adult" })); + ExpectMsg(m2); + } + + [Fact] + public void EventAdapter_should_work_when_plugin_defines_no_adapter() + { + var noAdapter = "no-adapter"; + + var p1 = Persister("p1", noAdapter); + var m1 = new UserDataChanged("name", 64); + var m2 = "hello"; + + p1.Tell(m1); + p1.Tell(m2); + ExpectMsg(m1); + ExpectMsg(m2); + + Watch(p1); + p1.Tell(PoisonPill.Instance); + ExpectTerminated(p1); + + var p11 = Persister("p1", noAdapter); + p11.Tell(GetState.Instance); + ExpectMsg(m1); + ExpectMsg(m2); + } + } +} \ No newline at end of file diff --git a/src/core/Akka.Persistence/Akka.Persistence.csproj b/src/core/Akka.Persistence/Akka.Persistence.csproj index b3f95017ef5..3939835af65 100644 --- a/src/core/Akka.Persistence/Akka.Persistence.csproj +++ b/src/core/Akka.Persistence/Akka.Persistence.csproj @@ -59,6 +59,8 @@ + + diff --git a/src/core/Akka.Persistence/InternalExtensions.cs b/src/core/Akka.Persistence/InternalExtensions.cs index 505e3a154fd..8c73294e15b 100644 --- a/src/core/Akka.Persistence/InternalExtensions.cs +++ b/src/core/Akka.Persistence/InternalExtensions.cs @@ -5,8 +5,10 @@ // //----------------------------------------------------------------------- +using System.Collections.Generic; using System.Threading.Tasks; using Akka.Actor; +using Akka.Configuration.Hocon; using Akka.Dispatch; using Akka.Dispatch.MessageQueues; diff --git a/src/core/Akka.Persistence/Journal/AsyncWriteJournal.cs b/src/core/Akka.Persistence/Journal/AsyncWriteJournal.cs index 589ca90d1b6..02e2559600f 100644 --- a/src/core/Akka.Persistence/Journal/AsyncWriteJournal.cs +++ b/src/core/Akka.Persistence/Journal/AsyncWriteJournal.cs @@ -89,7 +89,13 @@ private void HandleReplayMessages(ReplayMessages message) // to resequence replayed messages relative to written and looped messages. ReplayMessagesAsync(message.PersistenceId, message.FromSequenceNr, message.ToSequenceNr, message.Max, p => { - if (!p.IsDeleted || message.ReplayDeleted) message.PersistentActor.Tell(new ReplayedMessage(p), p.Sender); + if (!p.IsDeleted || message.ReplayDeleted) + { + foreach (var adaptedRepresentation in AdaptFromJournal(p)) + { + message.PersistentActor.Tell(new ReplayedMessage(adaptedRepresentation), p.Sender); + } + } }) .NotifyAboutReplayCompletion(message.PersistentActor) .ContinueWith(t => @@ -127,21 +133,22 @@ private void HandleWriteMessages(WriteMessages message) * execution context. */ var self = Self; - WriteMessagesAsync(CreatePersistentBatch(message.Messages)).ContinueWith(t => - { - if (!t.IsFaulted) - { - _resequencer.Tell(new Desequenced(WriteMessagesSuccessful.Instance, counter, message.PersistentActor, self)); - resequence(x => new WriteMessageSuccess(x, message.ActorInstanceId)); - } - else - { - _resequencer.Tell(new Desequenced(new WriteMessagesFailed(t.Exception), counter, message.PersistentActor, self)); - resequence(x => new WriteMessageFailure(x, t.Exception, message.ActorInstanceId)); - } - }, _continuationOptions); var resequencablesLength = message.Messages.Count(); _resequencerCounter += resequencablesLength + 1; + WriteMessagesAsync(CreatePersistentBatch(message.Messages).ToArray()) + .ContinueWith(t => + { + if (!t.IsFaulted) + { + _resequencer.Tell(new Desequenced(WriteMessagesSuccessful.Instance, counter, message.PersistentActor, self)); + resequence(x => new WriteMessageSuccess(x, message.ActorInstanceId)); + } + else + { + _resequencer.Tell(new Desequenced(new WriteMessagesFailed(t.Exception), counter, message.PersistentActor, self)); + resequence(x => new WriteMessageFailure(x, t.Exception, message.ActorInstanceId)); + } + }, _continuationOptions); } internal sealed class Desequenced diff --git a/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs b/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs index b7bca4b2301..b38199d3f23 100644 --- a/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs +++ b/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs @@ -56,7 +56,7 @@ public sealed class ReplayFailure { public ReplayFailure(Exception cause) { - if(cause == null) + if (cause == null) throw new ArgumentNullException("cause", "AsyncWriteTarget.ReplayFailure cause exception cannot be null"); Cause = cause; @@ -134,7 +134,7 @@ public bool Equals(ReadHighestSequenceNr other) } [Serializable] - public sealed class DeleteMessagesTo: IEquatable + public sealed class DeleteMessagesTo : IEquatable { public DeleteMessagesTo(string persistenceId, long toSequenceNr, bool isPermanent) { @@ -160,29 +160,26 @@ public bool Equals(DeleteMessagesTo other) public abstract class AsyncWriteProxy : AsyncWriteJournal, IWithUnboundedStash { - private readonly Receive _initialized; + private bool _isInitialized = false; private IActorRef _store; - public IStash Stash { get; set; } - public TimeSpan ReplayTimeout { get; private set; } - protected AsyncWriteProxy() { ReplayTimeout = Context.System.Settings.Config.GetTimeSpan("akka.persistence.journal.async-proxy-replay-timeout"); - _initialized = base.Receive; } - protected override bool Receive(object message) + public TimeSpan ReplayTimeout { get; private set; } + + protected override bool AroundReceive(Receive receive, object message) { - if (message is SetStore) + if (_isInitialized) return base.AroundReceive(receive, message); + else if (message is SetStore) { - var setStore = message as SetStore; - _store = setStore.Store; + _store = ((SetStore) message).Store; Stash.UnstashAll(); - Context.Become(_initialized); + _isInitialized = true; } else Stash.Stash(); - return true; } @@ -198,8 +195,7 @@ public override Task ReplayMessagesAsync(string persistenceId, long fromSequence public override Task ReadHighestSequenceNrAsync(string persistenceId, long fromSequenceNr) { - return _store.Ask(new AsyncWriteTarget.ReadHighestSequenceNr(persistenceId, fromSequenceNr)) - .ContinueWith(t => (long)t.Result); + return _store.Ask(new AsyncWriteTarget.ReadHighestSequenceNr(persistenceId, fromSequenceNr)); } protected override Task WriteMessagesAsync(IEnumerable messages) @@ -211,6 +207,8 @@ protected override Task DeleteMessagesToAsync(string persistenceId, long toSeque { return _store.Ask(new AsyncWriteTarget.DeleteMessagesTo(persistenceId, toSequenceNr, isPermanent)); } + + public IStash Stash { get; set; } } internal class ReplayMediator : ActorBase diff --git a/src/core/Akka.Persistence/Journal/EventAdapters.cs b/src/core/Akka.Persistence/Journal/EventAdapters.cs new file mode 100644 index 00000000000..c1357681ea2 --- /dev/null +++ b/src/core/Akka.Persistence/Journal/EventAdapters.cs @@ -0,0 +1,282 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using Akka.Actor; +using Akka.Configuration; +using Akka.Configuration.Hocon; +using Akka.Event; +using Akka.Pattern; + +namespace Akka.Persistence.Journal +{ + /// + /// Facility to convert from and to specialised data models, as may be required by specialized persistence Journals. + /// + /// Typical use cases include(but are not limited to): + /// - adding metadata, a.k.a. "tagging" - by wrapping objects into tagged counterparts + /// - manually converting to the Journals storage format, such as JSON, BSON or any specialised binary format + /// - adapting incoming events in any way before persisting them by the journal + /// + public interface IEventAdapter + { + /// + /// Return the manifest (type hint) that will be provided in the method. Use empty string if not needed. + /// + /// + /// + string Manifest(object evt); + + /// + /// Convert domain event to journal event type. + /// + /// Some journal may require a specific type to be returned to them, + /// for example if a primary key has to be associated with each event then a journal + /// may require adapters to return "EventWithPrimaryKey(event, key)". + /// + /// The adaptation must be an 1-to-1 transformation. + /// It is not allowed to drop incoming events during the `toJournal` adaptation. + /// + /// the application-side domain event to be adapted to the journal model + /// the adapted event object, possibly the same object if no adaptation was performed + object ToJournal(object evt); + + /// + /// Convert a event from its journal model to the applications domain model. + /// + /// One event may be adapter into multiple(or none) events which should be delivered to the . + /// Use the specialised method to emit exactly one event, + /// or in case the adapter is not handling this event. Multiple instances are + /// applied in order as defined in configuration and their emitted event seqs are concatenated and delivered in order + /// to the PersistentActor. + /// + /// event to be adapted before delivering to the PersistentActor + /// optionally provided manifest(type hint) in case the Adapter has stored one for this event. Use empty string if none. + /// sequence containing the adapted events (possibly zero) which will be delivered to the PersistentActor + IEventSequence FromJournal(object evt, string manifest); + } + + [Serializable] + public class IdentityEventAdapter : IEventAdapter + { + public static readonly IdentityEventAdapter Instance = new IdentityEventAdapter(); + + private IdentityEventAdapter() { } + + public string Manifest(object evt) + { + return string.Empty; + } + + public object ToJournal(object evt) + { + return evt; + } + + public IEventSequence FromJournal(object evt, string manifest) + { + return EventSequence.Single(evt); + } + } + + [Serializable] + public sealed class CombinedReadEventAdapter : IEventAdapter + { + private static readonly Exception OnlyReadSideException = new IllegalStateException( + "CombinedReadEventAdapter must not be used when writing (creating manifests) events!"); + + private readonly IEventAdapter[] _adapters; + + public IEnumerable Adapters { get { return _adapters; } } + + public CombinedReadEventAdapter(IEnumerable adapters) + { + _adapters = adapters.ToArray(); + } + + public string Manifest(object evt) + { + throw OnlyReadSideException; + } + + public object ToJournal(object evt) + { + throw OnlyReadSideException; + } + + public IEventSequence FromJournal(object evt, string manifest) + { + return EventSequence.Create(_adapters.SelectMany(adapter => adapter.FromJournal(evt, manifest).Events)); + } + } + + internal class IdentityEventAdapters : EventAdapters + { + public static readonly EventAdapters Instance = new IdentityEventAdapters(); + + private IdentityEventAdapters() : base(null, null, null) + { + } + + public override IEventAdapter Get(Type type) + { + return IdentityEventAdapter.Instance; + } + } + + public class EventAdapters + { + private readonly ConcurrentDictionary _map; + private readonly IEnumerable> _bindings; + private readonly ILoggingAdapter _log; + + public static EventAdapters Create(ExtendedActorSystem system, Config config) + { + var adapters = ConfigToMap(config, "event-adapters"); + var adapterBindings = ConfigToListMap(config, "event-adapter-bindings"); + + return Create(system, adapters, adapterBindings); + } + + private static EventAdapters Create(ExtendedActorSystem system, IDictionary adapters, IDictionary adapterBindings) + { + var adapterNames = new HashSet(adapters.Keys); + foreach (var kv in adapterBindings) + { + foreach (var boundAdapter in kv.Value) + { + if (!adapterNames.Contains(boundAdapter)) + throw new ArgumentException(string.Format("{0} was bound to undefined event-adapter: {1} (bindings: [{2}], known adapters: [{3}])", + kv.Key, boundAdapter, string.Join(", ", kv.Value), string.Join(", ", adapters.Keys))); + } + } + + // A Map of handler from alias to implementation (i.e. class implementing Akka.Serialization.ISerializer) + // For example this defines a handler named 'country': `"country" -> com.example.comain.CountryTagsAdapter` + var handlers = adapters.ToDictionary(kv => kv.Key, kv => Instantiate(kv.Value, system)); + + // bindings is a enumerable of key-val representing the mapping from Type to handler. + // It is primarily ordered by the most specific classes first, and secondly in the configured order. + var bindings = Sort(adapterBindings.Select(kv => + { + var type = Type.GetType(kv.Key); + var adapter = kv.Value.Length == 1 + ? handlers[kv.Value[0]] + : new CombinedReadEventAdapter(kv.Value.Select(h => handlers[h])); + return new KeyValuePair(type, adapter); + }).ToList()); + + var backing = new ConcurrentDictionary(); + + foreach (var pair in bindings) + { + backing.AddOrUpdate(pair.Key, pair.Value, (type, adapter) => pair.Value); + } + + return new EventAdapters(backing, bindings, system.Log); + } + + private static List> Sort(List> bindings) + { + return bindings.Aggregate(new List>(bindings.Count), (buf, ca) => + { + + var idx = IndexWhere(buf, x => x.Key.IsAssignableFrom(ca.Key)); + + if (idx == -1) + buf.Add(ca); + else + buf.Insert(idx, ca); + + return buf; + }); + } + + private static int IndexWhere(IList list, Predicate predicate) + { + for (int i = 0; i < list.Count; i++) + if (predicate(list[i])) return i; + + return -1; + } + + protected EventAdapters(ConcurrentDictionary map, IEnumerable> bindings, ILoggingAdapter log) + { + _map = map; + _bindings = bindings; + _log = log; + } + + public IEventAdapter Get() + { + return Get(typeof(T)); + } + + public virtual IEventAdapter Get(Type type) + { + IEventAdapter adapter; + if (_map.TryGetValue(type, out adapter)) + return adapter; + + // bindings are ordered from most specific to least specific + var pair = _bindings.FirstOrDefault(kv => kv.Key.IsAssignableFrom(type)); + var value = !pair.Equals(default(KeyValuePair)) ? pair.Value : IdentityEventAdapter.Instance; + + adapter = _map.GetOrAdd(type, value); + return adapter; + } + + private static T Instantiate(string qualifiedName, ExtendedActorSystem system) + { + var instanceType = Type.GetType(qualifiedName); + if (!typeof(T).IsAssignableFrom(instanceType)) + throw new ArgumentException(string.Format("Couldn't create instance of [{0}] from provided qualified type name [{1}], because it's not assignable from it", + typeof(T), qualifiedName)); + + try + { + return (T)Activator.CreateInstance(instanceType, system); + } + catch (MissingMethodException) + { + return (T)Activator.CreateInstance(instanceType); + } + } + + private static IDictionary ConfigToMap(Config config, string path) + { + if (config.HasPath(path)) + { + var hoconObject = config.GetConfig(path).Root.GetObject(); + return hoconObject.Unwrapped.ToDictionary(kv => kv.Key, kv => kv.Value.ToString().Trim('"')); + } + else return new Dictionary { }; + } + + private static IDictionary ConfigToListMap(Config config, string path) + { + if (config.HasPath(path)) + { + var hoconObject = config.GetConfig(path).Root.GetObject(); + return hoconObject.Unwrapped.ToDictionary(kv => kv.Key, kv => + { + var hoconValue = kv.Value as HoconValue; + if (hoconValue != null) + { + var str = hoconValue.GetString(); + return str != null ? new[] { str } : hoconValue.GetStringList().ToArray(); + } + else return new[] { kv.Value.ToString().Trim('"') }; + }); + } + else return new Dictionary { }; + } + } +} \ No newline at end of file diff --git a/src/core/Akka.Persistence/Journal/EventSequences.cs b/src/core/Akka.Persistence/Journal/EventSequences.cs new file mode 100644 index 00000000000..41cc69a4b97 --- /dev/null +++ b/src/core/Akka.Persistence/Journal/EventSequences.cs @@ -0,0 +1,106 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Akka.Persistence.Journal +{ + public interface IEventSequence + { + IEnumerable Events { get; } + } + + public interface IEmptyEventSequence : IEventSequence { } + + [Serializable] + public sealed class EmptyEventSequence : IEmptyEventSequence, IEquatable + { + public static readonly EmptyEventSequence Instance = new EmptyEventSequence(); + + private EmptyEventSequence() { } + + public IEnumerable Events { get { return Enumerable.Empty(); } } + + public bool Equals(IEventSequence other) + { + return other is EmptyEventSequence; + } + + public override bool Equals(object obj) + { + return Equals(obj as IEventSequence); + } + } + + [Serializable] + public class EventSequence : IEventSequence, IEquatable + { + private readonly ISet _events; + public EventSequence(IEnumerable events) + { + _events = new HashSet(events); + } + + public IEnumerable Events { get { return _events; } } + + public bool Equals(IEventSequence other) + { + return other != null && _events.SetEquals(other.Events); + } + + public override bool Equals(object obj) + { + return Equals(obj as IEventSequence); + } + } + + [Serializable] + public struct SingleEventSequence : IEventSequence, IEquatable + { + private readonly object[] _events; + public SingleEventSequence(object e) : this() + { + _events = new[] { e }; + } + + public IEnumerable Events { get { return _events; } } + + public bool Equals(IEventSequence other) + { + if (other == null) return false; + var e = other.Events.FirstOrDefault(); + return e != null && e.Equals(_events[0]) && other.Events.Count() == 1; + } + + public override bool Equals(object obj) + { + return Equals(obj as IEventSequence); + } + } + + public static class EventSequence + { + public static IEventSequence Empty = EmptyEventSequence.Instance; + + public static IEventSequence Single(object e) + { + return new SingleEventSequence(e); + } + + public static IEventSequence Create(params object[] events) + { + return new EventSequence(events); + } + + public static IEventSequence Create(IEnumerable events) + { + return new EventSequence(events); + } + } +} \ No newline at end of file diff --git a/src/core/Akka.Persistence/Journal/MemoryJournal.cs b/src/core/Akka.Persistence/Journal/MemoryJournal.cs index 6117add8164..b742d8a7085 100644 --- a/src/core/Akka.Persistence/Journal/MemoryJournal.cs +++ b/src/core/Akka.Persistence/Journal/MemoryJournal.cs @@ -34,14 +34,28 @@ public class MemoryJournal : AsyncWriteProxy protected override void PreStart() { base.PreStart(); - Self.Tell(new SetStore(Context.ActorOf(Props.Create()))); + var config = Context.System.Settings.Config; + var storeProps = config.HasPath("akka.persistence.journal.inmem.shared") && + config.GetBoolean("akka.persistence.journal.inmem.shared") + ? Props.Create() + : Props.Create(); + Self.Tell(new SetStore(Context.ActorOf(storeProps))); } } - public class MemoryStore : ActorBase, IMemoryMessages + public class SharedMemoryStore : MemoryStore + { + private static readonly ConcurrentDictionary> SharedMessages = new ConcurrentDictionary>(); + + protected override ConcurrentDictionary> Messages { get { return SharedMessages; } } + } + + public class MemoryStore : WriteJournalBase, IMemoryMessages { private readonly ConcurrentDictionary> _messages = new ConcurrentDictionary>(); + protected virtual ConcurrentDictionary> Messages { get { return _messages; } } + protected override bool Receive(object message) { if (message is AsyncWriteTarget.WriteMessages) Add(message as AsyncWriteTarget.WriteMessages); @@ -55,7 +69,7 @@ protected override bool Receive(object message) private void GetHighestSequenceNumber(AsyncWriteTarget.ReadHighestSequenceNr rhsn) { LinkedList list; - Sender.Tell(_messages.TryGetValue(rhsn.PersistenceId, out list) + Sender.Tell(Messages.TryGetValue(rhsn.PersistenceId, out list) ? list.Last.Value.SequenceNr : 0L); } @@ -63,7 +77,7 @@ private void GetHighestSequenceNumber(AsyncWriteTarget.ReadHighestSequenceNr rhs private void Read(AsyncWriteTarget.ReplayMessages replay) { LinkedList list; - if (_messages.TryGetValue(replay.PersistenceId, out list)) + if (Messages.TryGetValue(replay.PersistenceId, out list)) { var filtered = list .Where(x => x.SequenceNr >= replay.FromSequenceNr && x.SequenceNr <= replay.ToSequenceNr) @@ -81,7 +95,7 @@ private void Read(AsyncWriteTarget.ReplayMessages replay) private void Delete(AsyncWriteTarget.DeleteMessagesTo deleteCommand) { LinkedList list; - if (_messages.TryGetValue(deleteCommand.PersistenceId, out list)) + if (Messages.TryGetValue(deleteCommand.PersistenceId, out list)) { var node = list.First; if (deleteCommand.IsPermanent) @@ -134,7 +148,7 @@ private void Add(AsyncWriteTarget.WriteMessages writeMessages) { foreach (var persistent in writeMessages.Messages) { - var list = _messages.GetOrAdd(persistent.PersistenceId, new LinkedList()); + var list = Messages.GetOrAdd(persistent.PersistenceId, new LinkedList()); list.AddLast(persistent); } @@ -145,15 +159,15 @@ private void Add(AsyncWriteTarget.WriteMessages writeMessages) public Messages Add(IPersistentRepresentation persistent) { - var list = _messages.GetOrAdd(persistent.PersistenceId, new LinkedList()); + var list = Messages.GetOrAdd(persistent.PersistenceId, new LinkedList()); list.AddLast(persistent); - return _messages; + return Messages; } public Messages Update(string pid, long seqNr, Func updater) { LinkedList persistents; - if (_messages.TryGetValue(pid, out persistents)) + if (Messages.TryGetValue(pid, out persistents)) { var node = persistents.First; while (node != null) @@ -171,7 +185,7 @@ public Messages Update(string pid, long seqNr, Func persistents; - if (_messages.TryGetValue(pid, out persistents)) + if (Messages.TryGetValue(pid, out persistents)) { var node = persistents.First; while (node != null) @@ -183,17 +197,17 @@ public Messages Delete(string pid, long seqNr) } } - return _messages; + return Messages; } public IEnumerable Read(string pid, long fromSeqNr, long toSeqNr, long max) { LinkedList persistents; - if (_messages.TryGetValue(pid, out persistents)) + if (Messages.TryGetValue(pid, out persistents)) { return persistents .Where(x => x.SequenceNr >= fromSeqNr && x.SequenceNr <= toSeqNr) - .Take(max > int.MaxValue ? int.MaxValue : (int) max); + .Take(max > int.MaxValue ? int.MaxValue : (int)max); } return Enumerable.Empty(); @@ -202,7 +216,7 @@ public IEnumerable Read(string pid, long fromSeqNr, l public long HighestSequenceNr(string pid) { LinkedList persistents; - if (_messages.TryGetValue(pid, out persistents)) + if (Messages.TryGetValue(pid, out persistents)) { var last = persistents.LastOrDefault(); return last != null ? last.SequenceNr : 0L; diff --git a/src/core/Akka.Persistence/Journal/SyncWriteJournal.cs b/src/core/Akka.Persistence/Journal/SyncWriteJournal.cs index 896414bf114..2c45ab27e4f 100644 --- a/src/core/Akka.Persistence/Journal/SyncWriteJournal.cs +++ b/src/core/Akka.Persistence/Journal/SyncWriteJournal.cs @@ -81,7 +81,13 @@ private void HandleReplayMessages(ReplayMessages msg) var sender = Sender; ReplayMessagesAsync(msg.PersistenceId, msg.FromSequenceNr, msg.ToSequenceNr, msg.Max, persistent => { - if (!persistent.IsDeleted || msg.ReplayDeleted) msg.PersistentActor.Tell(new ReplayedMessage(persistent), sender); + if (!persistent.IsDeleted || msg.ReplayDeleted) + { + foreach (var adapterRepresentation in AdaptFromJournal(persistent)) + { + msg.PersistentActor.Tell(new ReplayedMessage(adapterRepresentation), sender); + } + } }) .NotifyAboutReplayCompletion(msg.PersistentActor) .ContinueWith(t => diff --git a/src/core/Akka.Persistence/Journal/WriteJournal.cs b/src/core/Akka.Persistence/Journal/WriteJournal.cs index 5b27be87a3f..76dc3f1ec05 100644 --- a/src/core/Akka.Persistence/Journal/WriteJournal.cs +++ b/src/core/Akka.Persistence/Journal/WriteJournal.cs @@ -13,22 +13,55 @@ namespace Akka.Persistence.Journal { public abstract class WriteJournalBase : ActorBase { - protected IEnumerable CreatePersistentBatch(IEnumerable resequencables) + private readonly PersistenceExtension _persistence; + private readonly EventAdapters _eventAdapters; + + protected WriteJournalBase() { - return resequencables.Where(PreparePersistentWrite).Cast(); + _persistence = Persistence.Instance.Apply(Context.System); + _eventAdapters = _persistence.AdaptersFor(Self); } + //protected IEnumerable CreatePersistentBatch(IEnumerable resequencables) + //{ + // return resequencables.Where(PreparePersistentWrite).Cast(); + //} + protected bool PreparePersistentWrite(IPersistentEnvelope persistentEnvelope) { if (persistentEnvelope is IPersistentRepresentation) { - var repr = persistentEnvelope as IPersistentRepresentation; + var repr = AdaptToJournal(persistentEnvelope as IPersistentRepresentation); repr.PrepareWrite(Context); return true; } return false; } + + protected IEnumerable CreatePersistentBatch(IEnumerable resequencables) + { + return resequencables + .Where(e => e is IPersistentRepresentation) + .Select(e => AdaptToJournal(e as IPersistentRepresentation).PrepareWrite(Context)); + } + + protected IEnumerable AdaptFromJournal(IPersistentRepresentation representation) + { + return _eventAdapters.Get(representation.Payload.GetType()) + .FromJournal(representation.Payload, representation.Manifest) + .Events + .Select(representation.WithPayload); + } + + protected IPersistentRepresentation AdaptToJournal(IPersistentRepresentation representation) + { + var payload = representation.Payload; + var adapter = _eventAdapters.Get(payload.GetType()); + var manifest = adapter.Manifest(payload); + + return representation.WithPayload(adapter.ToJournal(payload)).WithManifest(manifest); + } } } diff --git a/src/core/Akka.Persistence/Persistence.cs b/src/core/Akka.Persistence/Persistence.cs index fc253837290..8da992c2035 100644 --- a/src/core/Akka.Persistence/Persistence.cs +++ b/src/core/Akka.Persistence/Persistence.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Concurrent; +using System.Linq; using Akka.Actor; using Akka.Configuration; using Akka.Dispatch; @@ -14,6 +15,18 @@ namespace Akka.Persistence { + internal struct PluginHolder + { + public readonly IActorRef Ref; + public readonly EventAdapters Adapters; + + public PluginHolder(IActorRef @ref, EventAdapters adapters) + { + Ref = @ref; + Adapters = adapters; + } + } + public class PersistenceExtension : IExtension { private const string DefaultPluginDispatcherId = "akka.persistence.dispatchers.default-plugin-dispatcher"; @@ -25,8 +38,8 @@ public class PersistenceExtension : IExtension private readonly Lazy _defaultJournalPluginId; private readonly Lazy _defaultSnapshotPluginId; - private readonly ConcurrentDictionary> _journalPluginExtensionIds = new ConcurrentDictionary>(); - private readonly ConcurrentDictionary> _snapshotPluginExtensionIds = new ConcurrentDictionary>(); + private readonly ConcurrentDictionary> _journalPluginExtensionIds = new ConcurrentDictionary>(); + private readonly ConcurrentDictionary> _snapshotPluginExtensionIds = new ConcurrentDictionary>(); public PersistenceExtension(ExtendedActorSystem system) { @@ -65,13 +78,14 @@ public string PersistenceId(IActorRef actor) public IActorRef SnapshotStoreFor(string snapshotPluginId) { var configPath = string.IsNullOrEmpty(snapshotPluginId) ? _defaultSnapshotPluginId.Value : snapshotPluginId; - Lazy pluginContainer; + Lazy pluginContainer; if (!_snapshotPluginExtensionIds.TryGetValue(configPath, out pluginContainer)) { - pluginContainer = _snapshotPluginExtensionIds.AddOrUpdate(configPath, new Lazy(() => CreatePlugin(configPath, _ => DefaultPluginDispatcherId)), (key, old) => old); + var plugin = new Lazy(() => CreatePlugin(configPath, _ => DefaultPluginDispatcherId)); + pluginContainer = _snapshotPluginExtensionIds.AddOrUpdate(configPath, plugin, (key, old) => plugin); } - return pluginContainer.Value; + return pluginContainer.Value.Ref; } /// @@ -81,17 +95,56 @@ public IActorRef SnapshotStoreFor(string snapshotPluginId) public IActorRef JournalFor(string journalPluginId) { var configPath = string.IsNullOrEmpty(journalPluginId) ? _defaultJournalPluginId.Value : journalPluginId; - Lazy pluginContainer; + Lazy pluginContainer; if (!_journalPluginExtensionIds.TryGetValue(configPath, out pluginContainer)) { - pluginContainer = _journalPluginExtensionIds.AddOrUpdate(configPath, new Lazy(() => CreatePlugin(configPath, type => - typeof(AsyncWriteJournal).IsAssignableFrom(type) ? Dispatchers.DefaultDispatcherId : DefaultPluginDispatcherId)), (key, old) => old); + var plugin = new Lazy(() => CreatePlugin(configPath, type => + typeof (AsyncWriteJournal).IsAssignableFrom(type) + ? Dispatchers.DefaultDispatcherId + : DefaultPluginDispatcherId)); + pluginContainer = _journalPluginExtensionIds.AddOrUpdate(configPath, plugin, (key, old) => plugin); } - return pluginContainer.Value; + return pluginContainer.Value.Ref; } - private IActorRef CreatePlugin(string configPath, Func dispatcherSelector) + /// + /// Returns an object which serves as a per-journal collection of bound event adapters. + /// If no adapters are registered for a given journal the EventAdapters object will simply return the identity adapter for each + /// class, otherwise the most specific adapter matching a given class will be returned. + /// + /// + /// + public EventAdapters AdaptersFor(string journalPluginId) + { + var configPath = string.IsNullOrEmpty(journalPluginId) ? _defaultJournalPluginId.Value : journalPluginId; + Lazy pluginContainer; + if (!_journalPluginExtensionIds.TryGetValue(configPath, out pluginContainer)) + { + var plugin = new Lazy(() => + CreatePlugin(configPath, type => typeof (AsyncWriteJournal).IsAssignableFrom(type) + ? Dispatchers.DefaultDispatcherId + : DefaultPluginDispatcherId)); + pluginContainer = _journalPluginExtensionIds.AddOrUpdate(configPath, plugin, (key, old) => plugin); + } + + return pluginContainer.Value.Adapters; + } + + /// + /// + /// + /// + /// + internal EventAdapters AdaptersFor(IActorRef journalRef) + { + return _journalPluginExtensionIds.Values + .Select(ext => Equals(ext.Value.Ref, journalRef) ? ext.Value.Adapters : null) + .FirstOrDefault(r => r != null) + ?? IdentityEventAdapters.Instance; + } + + private PluginHolder CreatePlugin(string configPath, Func dispatcherSelector) { if (string.IsNullOrEmpty(configPath) || !_system.Settings.Config.HasPath(configPath)) { @@ -110,7 +163,13 @@ private IActorRef CreatePlugin(string configPath, Func dispatcherS var pluginActorProps = new Props(pluginType, pluginActorArgs).WithDispatcher(pluginDispatcherId); var pluginRef = _system.SystemActorOf(pluginActorProps, configPath); - return pluginRef; + return new PluginHolder(pluginRef, CreateAdapters(configPath)); + } + + private EventAdapters CreateAdapters(string configPath) + { + var pluginConfig = _system.Settings.Config.GetConfig(configPath); + return EventAdapters.Create(_system, pluginConfig); } } diff --git a/src/core/Akka.Persistence/Persistent.cs b/src/core/Akka.Persistence/Persistent.cs index 24a4e26e11d..2cbab424e46 100644 --- a/src/core/Akka.Persistence/Persistent.cs +++ b/src/core/Akka.Persistence/Persistent.cs @@ -83,11 +83,21 @@ public interface IPersistentRepresentation : IPersistentEnvelope, IWithPersisten /// long SequenceNr { get; } + /// + /// Returns the persistent payload's manifest if available. + /// + string Manifest { get; } + /// /// Creates a new persistent message with the specified . /// IPersistentRepresentation WithPayload(object payload); + /// + /// Creates a new persistent message with the specified . + /// + IPersistentRepresentation WithManifest(string manifest); + /// /// Creates a new deep copy of this message. /// @@ -105,12 +115,15 @@ public interface IPersistentRepresentation : IPersistentEnvelope, IWithPersisten [Serializable] public class Persistent : IPersistentRepresentation { - public Persistent(object payload, long sequenceNr = 0L, string persistenceId = null, bool isDeleted = false, IActorRef sender = null) + public readonly string Undefined = string.Empty; + + public Persistent(object payload, long sequenceNr = 0L, string manifest = null, string persistenceId = null, bool isDeleted = false, IActorRef sender = null) { Payload = payload; SequenceNr = sequenceNr; IsDeleted = isDeleted; - PersistenceId = persistenceId ?? string.Empty; + Manifest = manifest ?? Undefined; + PersistenceId = persistenceId ?? Undefined; Sender = sender; } @@ -119,20 +132,28 @@ public Persistent(object payload, long sequenceNr = 0L, string persistenceId = n public string PersistenceId { get; private set; } public bool IsDeleted { get; private set; } public long SequenceNr { get; private set; } + public string Manifest { get; private set; } public IPersistentRepresentation WithPayload(object payload) { - return new Persistent(payload, SequenceNr, PersistenceId, IsDeleted, Sender); + return new Persistent(payload, sequenceNr: SequenceNr, manifest: Manifest, persistenceId: PersistenceId, isDeleted: IsDeleted, sender: Sender); + } + + public IPersistentRepresentation WithManifest(string manifest) + { + return Manifest == manifest ? + this : + new Persistent(payload: Payload, sequenceNr: SequenceNr, manifest: manifest, persistenceId: PersistenceId, isDeleted: IsDeleted, sender: Sender); } public IPersistentRepresentation Update(long sequenceNr, string persistenceId, bool isDeleted, IActorRef sender) { - return new Persistent(Payload, sequenceNr, persistenceId, isDeleted, sender); + return new Persistent(payload: Payload, sequenceNr: sequenceNr, manifest: Manifest, persistenceId: persistenceId, isDeleted: isDeleted, sender: sender); } public IPersistentRepresentation PrepareWrite(IActorRef sender) { - return new Persistent(Payload, SequenceNr, PersistenceId, IsDeleted, sender); + return new Persistent(payload: Payload, sequenceNr: SequenceNr, manifest: Manifest, persistenceId: PersistenceId, isDeleted: IsDeleted, sender: sender); } public IPersistentRepresentation PrepareWrite(IActorContext context) diff --git a/src/core/Akka.Persistence/persistence.conf b/src/core/Akka.Persistence/persistence.conf index 6eaa294621c..db16f1b1072 100644 --- a/src/core/Akka.Persistence/persistence.conf +++ b/src/core/Akka.Persistence/persistence.conf @@ -47,6 +47,9 @@ akka { # Dispatcher for the plugin actor. plugin-dispatcher = "akka.actor.default-dispatcher" + + # Determines if journal state should be globaly shared between different actor instances + # shared = false } } diff --git a/src/examples/TcpEchoService.Server/Actors.cs b/src/examples/TcpEchoService.Server/Actors.cs index 1072c52f2f2..5a9d128ef46 100644 --- a/src/examples/TcpEchoService.Server/Actors.cs +++ b/src/examples/TcpEchoService.Server/Actors.cs @@ -15,11 +15,11 @@ namespace TcpEchoService.Server { public class EchoService : ReceiveActor { - private readonly TcpExt _extension = Tcp.Instance.Apply(Context.System); + private readonly IActorRef _manager = Context.System.Tcp(); public EchoService(EndPoint endpoint) { - _extension.Manager.Tell(new Tcp.Bind(Self, endpoint)); + _manager.Tell(new Tcp.Bind(Self, endpoint)); // To behave as TCP listener, actor should be able to handle Tcp.Connected messages Receive(connected => From 05f57b9b1ff256145bc085f94d49a591e51e1304 Mon Sep 17 00:00:00 2001 From: Christian Palmstierna Date: Sat, 8 Aug 2015 20:16:22 +0200 Subject: [PATCH 016/105] Discard msg if payload size > max allowed. Fixes #879 - Added property MaximumPayloadBytes to Transport. For HeliosTransport this is the same as MaxFrameSize. - If incoming or outgoing payload size > maximum-payload-bytes, log OversizedPayloadException and discard message. Corresponding Akka Scala code: https://github.com/akka/akka/blob/master/akka-remote/src/main/scala/akka/remote/Endpoint.scala#L745 https://github.com/akka/akka/blob/master/akka-remote/src/main/scala/akka/remote/Endpoint.scala#L934 https://github.com/akka/akka/blob/master/akka-remote/src/main/scala/akka/remote/transport/AbstractTransportAdapter.scala#L80 https://github.com/akka/akka/blob/master/akka-remote/src/main/scala/akka/remote/transport/Transport.scala#L92 https://github.com/akka/akka/blob/master/akka-remote/src/main/scala/akka/remote/transport/netty/NettyTransport.scala#L268 https://github.com/akka/akka/blob/master/akka-remote/src/main/scala/akka/remote/transport/TestTransport.scala#L29 https://github.com/akka/akka/blob/master/akka-remote/src/test/scala/akka/remote/RemotingSpec.scala#L527 --- .../Akka.MultiNodeTestRunner.csproj | 22 ------ src/core/Akka.Remote.Tests/RemotingSpec.cs | 34 ++++++++-- src/core/Akka.Remote/Endpoint.cs | 67 +++++++++++++------ .../Transport/Helios/HeliosTransport.cs | 8 +++ .../Akka.Remote/Transport/TestTransport.cs | 10 ++- src/core/Akka.Remote/Transport/Transport.cs | 1 + .../Transport/TransportAdapters.cs | 8 +++ 7 files changed, 98 insertions(+), 52 deletions(-) diff --git a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj index f4aff8d447b..dd8a6c268d4 100644 --- a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj +++ b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj @@ -94,28 +94,6 @@ - - echo PREBUILDSTEP for $(ProjectName) - -echo Copying files from $(SolutionDir)core\Akka.Remote.Tests.MultiNode\$(OutDir) to $(ProjectDir)bin\$(Configuration)\Akka.Remote - -if not exist "$(ProjectDir)bin\$(Configuration)\Akka.Remote" mkdir "$(ProjectDir)bin\$(Configuration)\Akka.Remote" - -xcopy "$(SolutionDir)core\Akka.Remote.Tests.MultiNode\$(OutDir)*.dll" "$(ProjectDir)bin\$(Configuration)\Akka.Remote" /i /d /y -if errorlevel 1 goto BuildEventFailed - -if errorlevel 1 goto BuildEventFailed - -REM Exit properly because the build will not fail -REM unless the final step exits with an error code - -goto BuildEventOK -:BuildEventFailed -echo PREBUILDSTEP for $(ProjectName) FAILED -exit 1 -:BuildEventOK -echo PREBUILDSTEP for $(ProjectName) COMPLETED OK - + true + + true + $(MSBuildThisFileDirectory) + $(MSBuildThisFileDirectory)..\ + + + + $(PaketToolsPath)paket.exe + $(PaketToolsPath)paket.bootstrapper.exe + "$(PaketExePath)" + mono --runtime=v4.0.30319 "$(PaketExePath)" + "$(PaketBootStrapperExePath)" + mono --runtime=v4.0.30319 $(PaketBootStrapperExePath) + + $(MSBuildProjectDirectory)\paket.references + $(MSBuildProjectFullPath).paket.references + $(PaketCommand) restore --references-files "$(PaketReferences)" + $(PaketBootStrapperCommand) + + RestorePackages; $(BuildDependsOn); + + + + + + + + + + + + + diff --git a/build.cmd b/build.cmd index 55899b04fdf..cd4d166978f 100644 --- a/build.cmd +++ b/build.cmd @@ -1,20 +1,14 @@ @echo off +cls -pushd %~dp0 - -src\.nuget\NuGet.exe update -self - -src\.nuget\NuGet.exe install FAKE -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion -Version 4.1.0 - -src\.nuget\NuGet.exe install xunit.runner.console -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages\FAKE -ExcludeVersion -Version 2.0.0 -src\.nuget\NuGet.exe install nunit.runners -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages\FAKE -ExcludeVersion -Version 2.6.4 - -if not exist src\packages\SourceLink.Fake\tools\SourceLink.fsx ( - src\.nuget\nuget.exe install SourceLink.Fake -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion +.paket\paket.bootstrapper.exe +if errorlevel 1 ( + exit /b %errorlevel% ) -rem cls -set encoding=utf-8 -src\packages\FAKE\tools\FAKE.exe build.fsx %* +.paket\paket.exe restore +if errorlevel 1 ( + exit /b %errorlevel% +) -popd +packages\build\FAKE\tools\FAKE.exe build.fsx %* diff --git a/build.fsx b/build.fsx index a7a3075593a..e82966c7213 100644 --- a/build.fsx +++ b/build.fsx @@ -1,4 +1,4 @@ -#I @"src/packages/FAKE/tools" +#I @"packages/build/FAKE/tools" #r "FakeLib.dll" #r "System.Xml.Linq" @@ -59,14 +59,6 @@ let libDir = workingDir @@ @"lib\net45\" let nugetExe = FullName @"src\.nuget\NuGet.exe" let docDir = "bin" @@ "doc" -open Fake.RestorePackageHelper -Target "RestorePackages" (fun _ -> - "./src/Akka.sln" - |> RestoreMSSolutionPackages (fun p -> - { p with - OutputPath = "./src/packages" - Retries = 4 }) - ) //-------------------------------------------------------------------------------- // Clean build results @@ -229,22 +221,22 @@ Target "RunTests" <| fun _ -> {p with DisableShadowCopy = true; OutputFile = testOutput + @"\NUnitTestResults.xml"}) - let xunitToolPath = findToolInSubPath "xunit.console.exe" "src/packages/xunit.runner.console*/tools" - printfn "Using XUnit runner: %s" xunitToolPath + xUnit2 (fun p -> { p with XmlOutputPath = Some (testOutput + @"\XUnitTestResults.xml"); HtmlOutputPath = Some (testOutput + @"\XUnitTestResults.HTML"); ToolPath = xunitToolPath; TimeOut = System.TimeSpan.FromMinutes 30.0; Parallel = ParallelMode.NoParallelization }) + xunitTestAssemblies Target "RunTestsMono" <| fun _ -> let xunitTestAssemblies = !! "src/**/bin/Release Mono/*.Tests.dll" mkdir testOutput - let xunitToolPath = findToolInSubPath "xunit.console.exe" "src/packages/xunit.runner.console*/tools" - printfn "Using XUnit runner: %s" xunitToolPath + xUnit2 (fun p -> { p with XmlOutputPath = Some (testOutput + @"\XUnitTestResults.xml"); HtmlOutputPath = Some (testOutput + @"\XUnitTestResults.HTML"); ToolPath = xunitToolPath; TimeOut = System.TimeSpan.FromMinutes 30.0; Parallel = ParallelMode.NoParallelization }) + xunitTestAssemblies Target "MultiNodeTests" <| fun _ -> @@ -323,15 +315,18 @@ let createNugetPackages _ = ensureDirectory nugetDir for nuspec in !! "src/**/*.nuspec" do printfn "Creating nuget packages for %s" nuspec + + let project = Path.GetFileNameWithoutExtension nuspec + let workingDir = workingDir project + CleanDir workingDir - let project = Path.GetFileNameWithoutExtension nuspec let projectDir = Path.GetDirectoryName nuspec let projectFile = (!! (projectDir @@ project + ".*sproj")) |> Seq.head let releaseDir = projectDir @@ @"bin\Release" - let packages = projectDir @@ "packages.config" - let packageDependencies = if (fileExists packages) then (getDependencies packages) else [] + let packages = projectDir @@ "paket.references" + let packageDependencies = if (fileExists packages) then (Paket.GetDependenciesForReferencesFile packages |> Seq.toList) else [] let dependencies = packageDependencies @ getAkkaDependency project let releaseVersion = getProjectVersion project @@ -378,8 +373,6 @@ let createNugetPackages _ = // Create both normal nuget package and symbols nuget package. // Uses the files we copied to workingDir and outputs to nugetdir pack nugetDir NugetSymbolPackage.Nuspec - - removeDir workingDir let publishNugetPackages _ = let rec publishPackage url accessKey trialsLeft packageFile = @@ -548,7 +541,7 @@ Target "HelpMultiNodeTests" <| fun _ -> //-------------------------------------------------------------------------------- // build dependencies -"Clean" ==> "AssemblyInfo" ==> "RestorePackages" ==> "Build" ==> "CopyOutput" ==> "BuildRelease" +"Clean" ==> "AssemblyInfo" ==> "Build" ==> "CopyOutput" ==> "BuildRelease" // tests dependencies "CleanTests" ==> "RunTests" diff --git a/build.sh b/build.sh index 16e418d34b2..ae147e64169 100755 --- a/build.sh +++ b/build.sh @@ -1,26 +1,33 @@ -#!/bin/bash - -SCRIPT_PATH="${BASH_SOURCE[0]}"; -if ([ -h "${SCRIPT_PATH}" ]) then - while([ -h "${SCRIPT_PATH}" ]) do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done +#!/usr/bin/env bash +if test "$OS" = "Windows_NT" +then + # use .Net + + .paket/paket.bootstrapper.exe + exit_code=$? + if [ $exit_code -ne 0 ]; then + exit $exit_code + fi + + .paket/paket.exe restore + exit_code=$? + if [ $exit_code -ne 0 ]; then + exit $exit_code + fi + + packages/build/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx +else + # use mono + mono .paket/paket.bootstrapper.exe + exit_code=$? + if [ $exit_code -ne 0 ]; then + exit $exit_code + fi + + mono .paket/paket.exe restore + exit_code=$? + if [ $exit_code -ne 0 ]; then + exit $exit_code + fi + mono packages/build/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx fi -pushd . > /dev/null -cd `dirname ${SCRIPT_PATH}` > /dev/null -SCRIPT_PATH=`pwd`; -popd > /dev/null - -mono $SCRIPT_PATH/src/.nuget/NuGet.exe update -self - -mono $SCRIPT_PATH/src/.nuget/NuGet.exe install FAKE -OutputDirectory $SCRIPT_PATH/src/packages -ExcludeVersion -Version 3.28.8 - -mono $SCRIPT_PATH/src/.nuget/NuGet.exe install xunit.runners -OutputDirectory $SCRIPT_PATH/src/packages/FAKE -ExcludeVersion -Version 2.0.0 -mono $SCRIPT_PATH/src/.nuget/NuGet.exe install nunit.runners -OutputDirectory $SCRIPT_PATH/src/packages/FAKE -ExcludeVersion -Version 2.6.4 - -if ! [ -e $SCRIPT_PATH/src/packages/SourceLink.Fake/tools/SourceLink.fsx ] ; then - mono $SCRIPT_PATH/src/.nuget/NuGet.exe install SourceLink.Fake -OutputDirectory $SCRIPT_PATH/src/packages -ExcludeVersion - -fi - -export encoding=utf-8 - -mono $SCRIPT_PATH/src/packages/FAKE/tools/FAKE.exe build.fsx "$@" diff --git a/paket.dependencies b/paket.dependencies new file mode 100644 index 00000000000..ff0268f8c9f --- /dev/null +++ b/paket.dependencies @@ -0,0 +1,41 @@ +source https://www.nuget.org/api/v2/ + +nuget Autofac +nuget Castle.Windsor +nuget faker-csharp +nuget fastJSON +nuget FsPickler +nuget FSPowerPack.Linq.Community +nuget Google.ProtocolBuffers +nuget Google.ProtocolBuffersLite +nuget Helios +nuget Microsoft.Bcl.Immutable +nuget Newtonsoft.Json +nuget Ninject +nuget NLog +nuget qdfeed +nuget Serilog +nuget slf4net +nuget structuremap +nuget Unity + +group Test +source https://www.nuget.org/api/v2/ +nuget NUnit +nuget NUnit.Runners +nuget FluentAssertions ~> 3 +nuget FsCheck.Xunit +nuget xunit.extensions +nuget xunit.runner.console +nuget xunit.runner.utility +nuget xunit.runner.visualstudio + +group Build +source https://www.nuget.org/api/v2/ +nuget Nuget.CommandLine +nuget FAKE +nuget SourceLink.Fake + +group Legacy +source https://www.nuget.org/api/v2/ +nuget xunit 1.9.2 \ No newline at end of file diff --git a/paket.lock b/paket.lock new file mode 100644 index 00000000000..61e774091b8 --- /dev/null +++ b/paket.lock @@ -0,0 +1,70 @@ +NUGET + remote: https://www.nuget.org/api/v2 + specs: + Autofac (3.5.2) + Castle.Core (3.3.3) + Castle.Windsor (3.3.0) + Castle.Core (>= 3.3.0) + CommonServiceLocator (1.3) - framework: monoandroid, winv4.5 + faker-csharp (1.2.0) + fastJSON (2.1.14.0) + FsPickler (1.4.0) + FSPowerPack.Core.Community (3.0.0.0) + FSPowerPack.Linq.Community (3.0.0.0) + FSPowerPack.Core.Community + Google.ProtocolBuffers (2.4.1.555) + Google.ProtocolBuffersLite (2.4.1.555) + Helios (1.4.1) + Microsoft.Bcl.Immutable (1.0.34) + Newtonsoft.Json (7.0.1) + Ninject (3.2.2.0) + NLog (4.1.1) + qdfeed (1.1.0) + Serilog (1.5.11) + slf4net (0.1.32.1) + structuremap (3.1.6.186) + Unity (3.5.1404.0) + CommonServiceLocator (>= 1.2.0) - framework: monoandroid, winv4.5 + +GROUP Build +NUGET + remote: https://www.nuget.org/api/v2 + specs: + FAKE (4.4.2) + NuGet.CommandLine (2.8.6) + SourceLink.Fake (1.1.0) + +GROUP Legacy +NUGET + remote: https://www.nuget.org/api/v2 + specs: + xunit (1.9.2) + +GROUP Test +NUGET + remote: https://www.nuget.org/api/v2 + specs: + FluentAssertions (3.5.0) + FsCheck (2.0.7) + FSharp.Core (>= 3.1.2.5) + FsCheck.Xunit (2.0.7) + FsCheck (>= 2.0.7) + xunit (>= 1.9.2) + FSharp.Core (4.0.0.1) + NUnit (2.6.4) + NUnit.Runners (2.6.4) + xunit (2.0.0) + xunit.assert (2.0.0) + xunit.core (2.0.0) + xunit.abstractions (2.0.0) + xunit.assert (2.0.0) + xunit.core (2.0.0) + xunit.extensibility.core (2.0.0) + xunit.extensibility.core (2.0.0) + xunit.abstractions (2.0.0) + xunit.extensions (2.0.0) + xunit (2.0.0) + xunit.runner.console (2.0.0) + xunit.runner.utility (2.0.0) + xunit.abstractions (2.0.0) + xunit.runner.visualstudio (2.0.1) diff --git a/src/.nuget/NuGet.Config b/src/.nuget/NuGet.Config deleted file mode 100644 index 58b08e6dd81..00000000000 --- a/src/.nuget/NuGet.Config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/.nuget/NuGet.exe b/src/.nuget/NuGet.exe deleted file mode 100644 index 324daa842c51a9936d8baeabbc21da1e01bc9a4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1686528 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 J|995F{{fUW9S8sb diff --git a/src/.nuget/NuGet.targets b/src/.nuget/NuGet.targets deleted file mode 100644 index 3f8c37b22cd..00000000000 --- a/src/.nuget/NuGet.targets +++ /dev/null @@ -1,144 +0,0 @@ - - - - $(MSBuildProjectDirectory)\..\ - - - false - - - false - - - true - - - false - - - - - - - - - - - $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) - - - - - $(SolutionDir).nuget - - - - $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config - $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config - - - - $(MSBuildProjectDirectory)\packages.config - $(PackagesProjectConfig) - - - - - $(NuGetToolsPath)\NuGet.exe - @(PackageSource) - - "$(NuGetExePath)" - mono --runtime=v4.0.30319 "$(NuGetExePath)" - - $(TargetDir.Trim('\\')) - - -RequireConsent - -NonInteractive - - "$(SolutionDir) " - "$(SolutionDir)" - - - $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) - $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols - - - - RestorePackages; - $(BuildDependsOn); - - - - - $(BuildDependsOn); - BuildPackage; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/.nuget/packages.config b/src/.nuget/packages.config deleted file mode 100644 index 569e1bea867..00000000000 --- a/src/.nuget/packages.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/Akka.sln b/src/Akka.sln index 5d26116d625..5d7d0cbb657 100644 --- a/src/Akka.sln +++ b/src/Akka.sln @@ -3,6 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{00569E53-0F1E-4ECC-BAEE-8DFF37AB007A}" + ProjectSection(SolutionItems) = preProject + ..\paket.dependencies = ..\paket.dependencies + EndProjectSection +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{69279534-1DBA-4115-BF8B-03F77FC8125E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Chat", "Chat", "{3AA1E79A-F641-4115-BF84-96ECE552EC95}" @@ -132,13 +137,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Protobuf", "Protobuf", "{98 core\protobuf\WireFormats.proto = core\protobuf\WireFormats.proto EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{8A15341C-5596-4F4D-949D-2CD9A0006E12}" - ProjectSection(SolutionItems) = preProject - .nuget\NuGet.Config = .nuget\NuGet.Config - .nuget\NuGet.exe = .nuget\NuGet.exe - .nuget\NuGet.targets = .nuget\NuGet.targets - EndProjectSection -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{10C5B1E8-15B5-4EB3-81AE-1FC054FE1305}" ProjectSection(SolutionItems) = preProject ..\build.fsx = ..\build.fsx diff --git a/src/benchmark/PersistenceBenchmark/App.config b/src/benchmark/PersistenceBenchmark/App.config index 8e15646352e..fde80ced889 100644 --- a/src/benchmark/PersistenceBenchmark/App.config +++ b/src/benchmark/PersistenceBenchmark/App.config @@ -1,6 +1,155 @@ - + - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj b/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj index 11b1a369112..f95e1a9e4a0 100644 --- a/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj +++ b/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj @@ -1,4 +1,4 @@ - + @@ -34,18 +34,6 @@ 4 - - ..\..\packages\Google.ProtocolBuffersLite.2.4.1.555\lib\net40\Google.ProtocolBuffersLite.dll - True - - - ..\..\packages\Google.ProtocolBuffersLite.2.4.1.555\lib\net40\Google.ProtocolBuffersLite.Serialization.dll - True - - - ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - @@ -63,7 +51,7 @@ - + @@ -76,13 +64,7 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\net35\Google.ProtocolBuffersLite.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\net35\Google.ProtocolBuffersLite.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\net20\Google.ProtocolBuffersLite.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\net20\Google.ProtocolBuffersLite.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\net40\Google.ProtocolBuffersLite.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\net40\Google.ProtocolBuffersLite.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\sl30\Google.ProtocolBuffersLite.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\sl30\Google.ProtocolBuffersLite.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\sl40\Google.ProtocolBuffersLite.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\sl40\Google.ProtocolBuffersLite.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffersLite.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffersLite\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffersLite.dll + True + True + + + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll + True + True + + + + \ No newline at end of file diff --git a/src/benchmark/PersistenceBenchmark/packages.config b/src/benchmark/PersistenceBenchmark/packages.config deleted file mode 100644 index 2b3a26f2d02..00000000000 --- a/src/benchmark/PersistenceBenchmark/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/benchmark/PersistenceBenchmark/paket.references b/src/benchmark/PersistenceBenchmark/paket.references new file mode 100644 index 00000000000..73c061bddbc --- /dev/null +++ b/src/benchmark/PersistenceBenchmark/paket.references @@ -0,0 +1,2 @@ +Google.ProtocolBuffersLite +Newtonsoft.Json \ No newline at end of file diff --git a/src/benchmark/PingPong/App.config b/src/benchmark/PingPong/App.config index 3523773e4ca..39e73226ebf 100644 --- a/src/benchmark/PingPong/App.config +++ b/src/benchmark/PingPong/App.config @@ -5,5 +5,154 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/Akka.DI.AutoFac.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/Akka.DI.AutoFac.Tests.csproj index 7c114dd0a26..cdd9860cf18 100644 --- a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/Akka.DI.AutoFac.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/Akka.DI.AutoFac.Tests.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true 90620b22 @@ -33,9 +32,6 @@ 4 - - ..\..\..\packages\Autofac.3.5.2\lib\net40\Autofac.dll - @@ -75,16 +71,9 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\Autofac\lib\net40\Autofac.dll + True + True + + + + + + + ..\..\..\..\packages\Autofac\lib\portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\Autofac.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/packages.config b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/packages.config deleted file mode 100644 index f94275189e5..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/paket.references b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/paket.references new file mode 100644 index 00000000000..4ab2ac0970e --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/paket.references @@ -0,0 +1 @@ +Autofac \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac/Akka.DI.AutoFac.csproj b/src/contrib/dependencyInjection/Akka.DI.AutoFac/Akka.DI.AutoFac.csproj index 8629834eb56..6f277e0f3f3 100644 --- a/src/contrib/dependencyInjection/Akka.DI.AutoFac/Akka.DI.AutoFac.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.AutoFac/Akka.DI.AutoFac.csproj @@ -13,7 +13,6 @@ 512 ..\..\..\ - true true @@ -36,9 +35,6 @@ bin\Release\Akka.DI.AutoFac.xml - - ..\..\..\packages\Autofac.3.5.2\lib\net40\Autofac.dll - @@ -62,17 +58,10 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\Autofac\lib\net40\Autofac.dll + True + True + + + + + + + ..\..\..\..\packages\Autofac\lib\portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\Autofac.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac/packages.config b/src/contrib/dependencyInjection/Akka.DI.AutoFac/packages.config deleted file mode 100644 index f94275189e5..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.AutoFac/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac/paket.references b/src/contrib/dependencyInjection/Akka.DI.AutoFac/paket.references new file mode 100644 index 00000000000..4ab2ac0970e --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.AutoFac/paket.references @@ -0,0 +1 @@ +Autofac \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/Akka.DI.CastleWindsor.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/Akka.DI.CastleWindsor.Tests.csproj index e1b388c58a9..4bf22c25821 100644 --- a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/Akka.DI.CastleWindsor.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/Akka.DI.CastleWindsor.Tests.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true 661b9909 @@ -33,12 +32,6 @@ 4 - - ..\..\..\packages\Castle.Core.3.3.0\lib\net45\Castle.Core.dll - - - ..\..\..\packages\Castle.Windsor.3.3.0\lib\net45\Castle.Windsor.dll - @@ -78,16 +71,9 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\Castle.Core\lib\net35\Castle.Core.dll + True + True + + + + + + + ..\..\..\..\packages\Castle.Core\lib\net40-client\Castle.Core.dll + True + True + + + + + + + ..\..\..\..\packages\Castle.Core\lib\net45\Castle.Core.dll + True + True + + + + + + + ..\..\..\..\packages\Castle.Core\lib\sl4\Castle.Core.dll + True + True + + + + + + + ..\..\..\..\packages\Castle.Core\lib\sl5\Castle.Core.dll + True + True + + + + + + + + + ..\..\..\..\packages\Castle.Windsor\lib\net35\Castle.Windsor.dll + True + True + + + + + + + ..\..\..\..\packages\Castle.Windsor\lib\net40\Castle.Windsor.dll + True + True + + + + + + + ..\..\..\..\packages\Castle.Windsor\lib\net45\Castle.Windsor.dll + True + True + + + + + + + ..\..\..\..\packages\Castle.Windsor\lib\sl4\Castle.Windsor.dll + True + True + + + True + + + + + + + ..\..\..\..\packages\Castle.Windsor\lib\sl5\Castle.Windsor.dll + True + True + + + True + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/packages.config b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/packages.config deleted file mode 100644 index 010612fa8b0..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/paket.references b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/paket.references new file mode 100644 index 00000000000..5957c632f29 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/paket.references @@ -0,0 +1 @@ +Castle.Windsor \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/Akka.DI.CastleWindsor.csproj b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/Akka.DI.CastleWindsor.csproj index d8ae7d05c70..c2855776332 100644 --- a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/Akka.DI.CastleWindsor.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/Akka.DI.CastleWindsor.csproj @@ -13,7 +13,6 @@ 512 ..\..\..\ - true true @@ -36,12 +35,6 @@ bin\Release\Akka.DI.CastleWindsor.xml - - ..\..\..\packages\Castle.Core.3.3.0\lib\net45\Castle.Core.dll - - - ..\..\..\packages\Castle.Windsor.3.3.0\lib\net45\Castle.Windsor.dll - @@ -65,17 +58,10 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\Castle.Core\lib\net35\Castle.Core.dll + True + True + + + + + + + ..\..\..\..\packages\Castle.Core\lib\net40-client\Castle.Core.dll + True + True + + + + + + + ..\..\..\..\packages\Castle.Core\lib\net45\Castle.Core.dll + True + True + + + + + + + ..\..\..\..\packages\Castle.Core\lib\sl4\Castle.Core.dll + True + True + + + + + + + ..\..\..\..\packages\Castle.Core\lib\sl5\Castle.Core.dll + True + True + + + + + + + + + ..\..\..\..\packages\Castle.Windsor\lib\net35\Castle.Windsor.dll + True + True + + + True + + + + + + + ..\..\..\..\packages\Castle.Windsor\lib\net40\Castle.Windsor.dll + True + True + + + True + + + + + + + ..\..\..\..\packages\Castle.Windsor\lib\net45\Castle.Windsor.dll + True + True + + + True + + + + + + + ..\..\..\..\packages\Castle.Windsor\lib\sl4\Castle.Windsor.dll + True + True + + + True + + + + + + + ..\..\..\..\packages\Castle.Windsor\lib\sl5\Castle.Windsor.dll + True + True + + + True + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/packages.config b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/packages.config deleted file mode 100644 index 010612fa8b0..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/paket.references b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/paket.references new file mode 100644 index 00000000000..5957c632f29 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/paket.references @@ -0,0 +1 @@ +Castle.Windsor \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/Akka.DI.Ninject.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/Akka.DI.Ninject.Tests.csproj index bbf08c22602..493c8dd6c86 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/Akka.DI.Ninject.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/Akka.DI.Ninject.Tests.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true 42a2ce59 @@ -33,10 +32,6 @@ 4 - - ..\..\..\packages\Ninject.3.2.2.0\lib\net45-full\Ninject.dll - True - @@ -76,16 +71,9 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\Ninject\lib\net35\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\net40\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\net45-full\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\sl3\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\sl4\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\sl5\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\sl4-windowsphone71\Ninject.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/packages.config b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/packages.config deleted file mode 100644 index 32203c61ad6..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/paket.references b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/paket.references new file mode 100644 index 00000000000..a04c4b923f7 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/paket.references @@ -0,0 +1 @@ +Ninject \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject/Akka.DI.Ninject.csproj b/src/contrib/dependencyInjection/Akka.DI.Ninject/Akka.DI.Ninject.csproj index 93dc1bce87b..16b3354ac0e 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Ninject/Akka.DI.Ninject.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Ninject/Akka.DI.Ninject.csproj @@ -13,7 +13,6 @@ 512 ..\..\..\ - true true @@ -36,9 +35,6 @@ bin\Release\Akka.DI.Ninject.xml - - ..\..\..\packages\Ninject.3.2.2.0\lib\net45-full\Ninject.dll - @@ -62,17 +58,10 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\Ninject\lib\net35\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\net40\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\net45-full\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\sl3\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\sl4\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\sl5\Ninject.dll + True + True + + + + + + + ..\..\..\..\packages\Ninject\lib\sl4-windowsphone71\Ninject.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject/packages.config b/src/contrib/dependencyInjection/Akka.DI.Ninject/packages.config deleted file mode 100644 index 32203c61ad6..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.Ninject/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject/paket.references b/src/contrib/dependencyInjection/Akka.DI.Ninject/paket.references new file mode 100644 index 00000000000..a04c4b923f7 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.Ninject/paket.references @@ -0,0 +1 @@ +Ninject \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/Akka.DI.StructureMap.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/Akka.DI.StructureMap.Tests.csproj index e0d7686af39..57accfe4343 100644 --- a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/Akka.DI.StructureMap.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/Akka.DI.StructureMap.Tests.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true true @@ -32,13 +31,6 @@ 4 - - ..\..\..\packages\structuremap.3.1.5.154\lib\net40\StructureMap.dll - True - - - ..\..\..\packages\structuremap.3.1.5.154\lib\net40\StructureMap.Net4.dll - @@ -78,16 +70,9 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\structuremap\lib\net40\StructureMap.Net4.dll + True + True + + + ..\..\..\..\packages\structuremap\lib\net40\StructureMap.dll + True + True + + + + + + + ..\..\..\..\packages\structuremap\lib\wp80\StructureMap.dll + True + True + + + + + + + ..\..\..\..\packages\structuremap\lib\portable-net45+win+wp81\StructureMap.dll + True + True + + + + + + + ..\..\..\..\packages\structuremap\lib\portable-net4+netcore45+MonoAndroid1+MonoTouch1\StructureMap.dll + True + True + + + + + + + ..\..\..\..\packages\structuremap\lib\portable-win+net40+wp8\StructureMap.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/packages.config b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/packages.config deleted file mode 100644 index 0374f33be6e..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/paket.references b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/paket.references new file mode 100644 index 00000000000..cfcfcec02d0 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/paket.references @@ -0,0 +1 @@ +structuremap \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap/Akka.DI.StructureMap.csproj b/src/contrib/dependencyInjection/Akka.DI.StructureMap/Akka.DI.StructureMap.csproj index 6c4863922dc..93bcb308fc6 100644 --- a/src/contrib/dependencyInjection/Akka.DI.StructureMap/Akka.DI.StructureMap.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.StructureMap/Akka.DI.StructureMap.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true true @@ -32,14 +31,6 @@ 4 - - ..\..\..\packages\structuremap.3.1.5.154\lib\net40\StructureMap.dll - True - - - ..\..\..\packages\structuremap.3.1.5.154\lib\net40\StructureMap.Net4.dll - True - @@ -63,17 +54,10 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\structuremap\lib\net40\StructureMap.Net4.dll + True + True + + + ..\..\..\..\packages\structuremap\lib\net40\StructureMap.dll + True + True + + + + + + + ..\..\..\..\packages\structuremap\lib\wp80\StructureMap.dll + True + True + + + + + + + ..\..\..\..\packages\structuremap\lib\portable-net45+win+wp81\StructureMap.dll + True + True + + + + + + + ..\..\..\..\packages\structuremap\lib\portable-net4+netcore45+MonoAndroid1+MonoTouch1\StructureMap.dll + True + True + + + + + + + ..\..\..\..\packages\structuremap\lib\portable-win+net40+wp8\StructureMap.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap/packages.config b/src/contrib/dependencyInjection/Akka.DI.StructureMap/packages.config deleted file mode 100644 index 0374f33be6e..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.StructureMap/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap/paket.references b/src/contrib/dependencyInjection/Akka.DI.StructureMap/paket.references new file mode 100644 index 00000000000..cfcfcec02d0 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.StructureMap/paket.references @@ -0,0 +1 @@ +structuremap \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj b/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj index fdd7bd68528..b622b41b12d 100644 --- a/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ v4.5 512 ..\..\..\ - true ac72c8df @@ -41,19 +39,6 @@ - - ..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - True - - - False - ..\..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - False - ..\..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - True - @@ -82,17 +67,9 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.TestKit/packages.config b/src/contrib/dependencyInjection/Akka.DI.TestKit/packages.config deleted file mode 100644 index 3109db107fb..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.TestKit/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.TestKit/paket.references b/src/contrib/dependencyInjection/Akka.DI.TestKit/paket.references new file mode 100644 index 00000000000..4bf78cf8fea --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.TestKit/paket.references @@ -0,0 +1,2 @@ +group Test +xunit \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj index db8bb33809f..049189d1204 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true true @@ -32,16 +31,6 @@ 4 - - ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.dll - True - - - ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.Configuration.dll - - - ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll - @@ -81,16 +70,9 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\CommonServiceLocator\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll + True + True + + + + + + + + + ..\..\..\..\packages\Unity\lib\win8\Microsoft.Practices.Unity.RegistrationByConvention.dll + True + True + + + ..\..\..\..\packages\Unity\lib\win8\Microsoft.Practices.Unity.dll + True + True + + + + + + + ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.Configuration.dll + True + True + + + ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll + True + True + + + ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.dll + True + True + + + + + + + ..\..\..\..\packages\Unity\lib\wp80\Microsoft.Practices.Unity.RegistrationByConvention.dll + True + True + + + ..\..\..\..\packages\Unity\lib\wp80\Microsoft.Practices.Unity.dll + True + True + + + + + + + ..\..\..\..\packages\Unity\lib\portable-net45+wp80+win8+MonoAndroid10+MonoTouch10\Microsoft.Practices.Unity.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/packages.config b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/packages.config deleted file mode 100644 index 75adcfb3762..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/paket.references b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/paket.references new file mode 100644 index 00000000000..f3ae0350f80 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/paket.references @@ -0,0 +1 @@ +Unity \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj b/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj index 7f802562a1b..b4eabaf3d0e 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\ - true true @@ -32,16 +31,6 @@ 4 - - ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.dll - - - ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.Configuration.dll - - - ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll - True - @@ -65,17 +54,10 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\CommonServiceLocator\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll + True + True + + + + + + + + + ..\..\..\..\packages\Unity\lib\win8\Microsoft.Practices.Unity.RegistrationByConvention.dll + True + True + + + ..\..\..\..\packages\Unity\lib\win8\Microsoft.Practices.Unity.dll + True + True + + + + + + + ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.Configuration.dll + True + True + + + ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll + True + True + + + ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.dll + True + True + + + + + + + ..\..\..\..\packages\Unity\lib\wp80\Microsoft.Practices.Unity.RegistrationByConvention.dll + True + True + + + ..\..\..\..\packages\Unity\lib\wp80\Microsoft.Practices.Unity.dll + True + True + + + + + + + ..\..\..\..\packages\Unity\lib\portable-net45+wp80+win8+MonoAndroid10+MonoTouch10\Microsoft.Practices.Unity.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity/packages.config b/src/contrib/dependencyInjection/Akka.DI.Unity/packages.config deleted file mode 100644 index 75adcfb3762..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.Unity/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity/paket.references b/src/contrib/dependencyInjection/Akka.DI.Unity/paket.references new file mode 100644 index 00000000000..f3ae0350f80 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.Unity/paket.references @@ -0,0 +1 @@ +Unity \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.NLog/Akka.Logger.NLog.csproj b/src/contrib/loggers/Akka.Logger.NLog/Akka.Logger.NLog.csproj index 7b08686e5e5..42b643d4475 100644 --- a/src/contrib/loggers/Akka.Logger.NLog/Akka.Logger.NLog.csproj +++ b/src/contrib/loggers/Akka.Logger.NLog/Akka.Logger.NLog.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\ - true true @@ -33,9 +32,6 @@ bin\Release\Akka.Logger.NLog.xml - - ..\..\..\packages\NLog.3.0.0.0\lib\net45\NLog.dll - @@ -58,10 +54,9 @@ Always - + - + + + + + + ..\..\..\..\packages\NLog\lib\net35\NLog.dll + True + True + + + + + + + ..\..\..\..\packages\NLog\lib\net40\NLog.dll + True + True + + + + + + + ..\..\..\..\packages\NLog\lib\net45\NLog.dll + True + True + + + + + + + ..\..\..\..\packages\NLog\lib\sl4\NLog.dll + True + True + + + + + + + ..\..\..\..\packages\NLog\lib\sl5\NLog.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.NLog/packages.config b/src/contrib/loggers/Akka.Logger.NLog/packages.config deleted file mode 100644 index e017f470208..00000000000 --- a/src/contrib/loggers/Akka.Logger.NLog/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.NLog/paket.references b/src/contrib/loggers/Akka.Logger.NLog/paket.references new file mode 100644 index 00000000000..0178a2ad4b8 --- /dev/null +++ b/src/contrib/loggers/Akka.Logger.NLog/paket.references @@ -0,0 +1 @@ +NLog \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.Serilog/Akka.Logger.Serilog.csproj b/src/contrib/loggers/Akka.Logger.Serilog/Akka.Logger.Serilog.csproj index 4798be337d2..379df9397b0 100644 --- a/src/contrib/loggers/Akka.Logger.Serilog/Akka.Logger.Serilog.csproj +++ b/src/contrib/loggers/Akka.Logger.Serilog/Akka.Logger.Serilog.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true true @@ -33,12 +32,6 @@ bin\Release\Akka.Logger.Serilog.xml - - ..\..\..\packages\Serilog.1.3.43\lib\net45\Serilog.dll - - - ..\..\..\packages\Serilog.1.3.43\lib\net45\Serilog.FullNetFx.dll - @@ -61,16 +54,9 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\Serilog\lib\net40\Serilog.FullNetFx.dll + True + True + + + ..\..\..\..\packages\Serilog\lib\net40\Serilog.dll + True + True + + + + + + + ..\..\..\..\packages\Serilog\lib\net45\Serilog.FullNetFx.dll + True + True + + + ..\..\..\..\packages\Serilog\lib\net45\Serilog.dll + True + True + + + + + + + ..\..\..\..\packages\Serilog\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+MonoTouch10\Serilog.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.Serilog/packages.config b/src/contrib/loggers/Akka.Logger.Serilog/packages.config deleted file mode 100644 index d6ccb175dae..00000000000 --- a/src/contrib/loggers/Akka.Logger.Serilog/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.Serilog/paket.references b/src/contrib/loggers/Akka.Logger.Serilog/paket.references new file mode 100644 index 00000000000..55deb233588 --- /dev/null +++ b/src/contrib/loggers/Akka.Logger.Serilog/paket.references @@ -0,0 +1 @@ +Serilog \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.slf4net/Akka.Logger.slf4net.csproj b/src/contrib/loggers/Akka.Logger.slf4net/Akka.Logger.slf4net.csproj index 1db2a92deca..78b01059f88 100644 --- a/src/contrib/loggers/Akka.Logger.slf4net/Akka.Logger.slf4net.csproj +++ b/src/contrib/loggers/Akka.Logger.slf4net/Akka.Logger.slf4net.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\ - true true @@ -54,9 +53,6 @@ false - - ..\..\..\packages\slf4net.0.1.32.1\lib\net35\slf4net.dll - @@ -70,7 +66,7 @@ - + @@ -79,7 +75,6 @@ - + + + + + + ..\..\..\..\packages\slf4net\lib\net35\slf4net.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.slf4net/packages.config b/src/contrib/loggers/Akka.Logger.slf4net/packages.config deleted file mode 100644 index 492f7656a1b..00000000000 --- a/src/contrib/loggers/Akka.Logger.slf4net/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.slf4net/paket.references b/src/contrib/loggers/Akka.Logger.slf4net/paket.references new file mode 100644 index 00000000000..b0b617e8486 --- /dev/null +++ b/src/contrib/loggers/Akka.Logger.slf4net/paket.references @@ -0,0 +1 @@ +slf4net \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit.Tests/Akka.TestKit.NUnit.Tests.csproj b/src/contrib/testkits/Akka.TestKit.NUnit.Tests/Akka.TestKit.NUnit.Tests.csproj index a5f010ce778..d0e87adeb32 100644 --- a/src/contrib/testkits/Akka.TestKit.NUnit.Tests/Akka.TestKit.NUnit.Tests.csproj +++ b/src/contrib/testkits/Akka.TestKit.NUnit.Tests/Akka.TestKit.NUnit.Tests.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true true @@ -32,9 +31,6 @@ 4 - - ..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll - @@ -50,7 +46,7 @@ - + @@ -70,13 +66,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + ..\..\..\..\packages\test\NUnit\lib\nunit.framework.dll + True + True + + \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit.Tests/packages.config b/src/contrib/testkits/Akka.TestKit.NUnit.Tests/packages.config deleted file mode 100644 index c714ef3a23e..00000000000 --- a/src/contrib/testkits/Akka.TestKit.NUnit.Tests/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit.Tests/paket.references b/src/contrib/testkits/Akka.TestKit.NUnit.Tests/paket.references new file mode 100644 index 00000000000..9e41999fc79 --- /dev/null +++ b/src/contrib/testkits/Akka.TestKit.NUnit.Tests/paket.references @@ -0,0 +1,2 @@ +group Test +NUnit \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit/Akka.TestKit.NUnit.csproj b/src/contrib/testkits/Akka.TestKit.NUnit/Akka.TestKit.NUnit.csproj index 366fcd95e1e..2790c745467 100644 --- a/src/contrib/testkits/Akka.TestKit.NUnit/Akka.TestKit.NUnit.csproj +++ b/src/contrib/testkits/Akka.TestKit.NUnit/Akka.TestKit.NUnit.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true true @@ -33,9 +32,6 @@ bin\Release\Akka.TestKit.NUnit.xml - - ..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll - @@ -53,7 +49,7 @@ - + @@ -66,13 +62,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + ..\..\..\..\packages\test\NUnit\lib\nunit.framework.dll + True + True + + \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit/packages.config b/src/contrib/testkits/Akka.TestKit.NUnit/packages.config deleted file mode 100644 index c714ef3a23e..00000000000 --- a/src/contrib/testkits/Akka.TestKit.NUnit/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit/paket.references b/src/contrib/testkits/Akka.TestKit.NUnit/paket.references new file mode 100644 index 00000000000..9e41999fc79 --- /dev/null +++ b/src/contrib/testkits/Akka.TestKit.NUnit/paket.references @@ -0,0 +1,2 @@ +group Test +NUnit \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit/Akka.TestKit.Xunit.csproj b/src/contrib/testkits/Akka.TestKit.Xunit/Akka.TestKit.Xunit.csproj index 646d9db3556..67fed050be7 100644 --- a/src/contrib/testkits/Akka.TestKit.Xunit/Akka.TestKit.Xunit.csproj +++ b/src/contrib/testkits/Akka.TestKit.Xunit/Akka.TestKit.Xunit.csproj @@ -1,4 +1,4 @@ - + @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true a4af550d @@ -37,10 +36,6 @@ - - ..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll - True - @@ -53,6 +48,9 @@ + + + {0D3CBAD0-BBDB-43E5-AFC4-ED1D3ECDC224} @@ -63,17 +61,7 @@ Akka - - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + ..\..\..\..\packages\legacy\xunit\lib\net20\xunit.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit/packages.config b/src/contrib/testkits/Akka.TestKit.Xunit/packages.config deleted file mode 100644 index 3eb1f079098..00000000000 --- a/src/contrib/testkits/Akka.TestKit.Xunit/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit/paket.references b/src/contrib/testkits/Akka.TestKit.Xunit/paket.references new file mode 100644 index 00000000000..81437c4a85e --- /dev/null +++ b/src/contrib/testkits/Akka.TestKit.Xunit/paket.references @@ -0,0 +1,2 @@ +group Legacy +xunit \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj b/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj index 622c9c386fe..2981609dc99 100644 --- a/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj +++ b/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ v4.5 512 ..\..\..\ - true 6577902d @@ -36,15 +34,6 @@ - - ..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -59,7 +48,7 @@ - + @@ -72,14 +61,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/packages.config b/src/contrib/testkits/Akka.TestKit.Xunit2/packages.config deleted file mode 100644 index 3109db107fb..00000000000 --- a/src/contrib/testkits/Akka.TestKit.Xunit2/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/paket.references b/src/contrib/testkits/Akka.TestKit.Xunit2/paket.references new file mode 100644 index 00000000000..4bf78cf8fea --- /dev/null +++ b/src/contrib/testkits/Akka.TestKit.Xunit2/paket.references @@ -0,0 +1,2 @@ +group Test +xunit \ No newline at end of file diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj b/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj index cecc6c6aa1d..24b9941da27 100644 --- a/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true true @@ -32,12 +31,6 @@ 4 - - ..\..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - - - ..\..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll - @@ -61,16 +54,9 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll + True + True + + + + + \ No newline at end of file diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/packages.config b/src/contrib/transports/Akka.Remote.AkkaIOTransport/packages.config deleted file mode 100644 index 5948219c6c9..00000000000 --- a/src/contrib/transports/Akka.Remote.AkkaIOTransport/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/paket.references b/src/contrib/transports/Akka.Remote.AkkaIOTransport/paket.references new file mode 100644 index 00000000000..07508816865 --- /dev/null +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/paket.references @@ -0,0 +1 @@ +Google.ProtocolBuffers \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj b/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj index cef187f5378..2c793274535 100644 --- a/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj +++ b/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ v4.5 512 ..\..\ - true 1a218765 @@ -35,25 +33,12 @@ - - False - ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -69,6 +54,9 @@ + + + {7dbd5c17-5e9d-40c4-9201-d092751532a7} @@ -100,20 +88,12 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests.MultiNode/packages.config b/src/core/Akka.Cluster.Tests.MultiNode/packages.config deleted file mode 100644 index 15502b4d7f9..00000000000 --- a/src/core/Akka.Cluster.Tests.MultiNode/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests.MultiNode/paket.references b/src/core/Akka.Cluster.Tests.MultiNode/paket.references new file mode 100644 index 00000000000..26d1c8e78f3 --- /dev/null +++ b/src/core/Akka.Cluster.Tests.MultiNode/paket.references @@ -0,0 +1,3 @@ +Microsoft.Bcl.Immutable +group Test +xunit \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj b/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj index ce22025ac9b..8324eee71bb 100644 --- a/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj +++ b/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj @@ -1,6 +1,5 @@  - Debug AnyCPU @@ -12,7 +11,6 @@ v4.5 512 ..\..\ - true d8ea7d64 @@ -33,34 +31,9 @@ 4 - - ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.dll - - - ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.Core.dll - - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll - - - False - ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -68,7 +41,6 @@ - @@ -127,12 +99,11 @@ - + - @@ -153,14 +124,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll + True + True + + + + + + + + + ..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\win8\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\win8\FluentAssertions.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\net40\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\net40\FluentAssertions.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\net45\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\net45\FluentAssertions.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\sl5\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\sl5\FluentAssertions.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\sl5\Microsoft.CSharp.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\sl5\Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\wp8\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\wp8\FluentAssertions.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\portable-monotouch+monoandroid+xamarin.ios\FluentAssertions.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\portable-win81+wpa81\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\portable-win81+wpa81\FluentAssertions.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\portable-net40+sl5+win8+wp8+wpa81\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\portable-net40+sl5+win8+wp8+wpa81\FluentAssertions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/packages.config b/src/core/Akka.Cluster.Tests/packages.config deleted file mode 100644 index b603d1619c6..00000000000 --- a/src/core/Akka.Cluster.Tests/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/paket.references b/src/core/Akka.Cluster.Tests/paket.references new file mode 100644 index 00000000000..a2040d828c0 --- /dev/null +++ b/src/core/Akka.Cluster.Tests/paket.references @@ -0,0 +1,5 @@ +Google.ProtocolBuffers +Microsoft.Bcl.Immutable +group Test +FluentAssertions +xunit \ No newline at end of file diff --git a/src/core/Akka.Cluster/Akka.Cluster.csproj b/src/core/Akka.Cluster/Akka.Cluster.csproj index 015e1796fc3..439d679c039 100644 --- a/src/core/Akka.Cluster/Akka.Cluster.csproj +++ b/src/core/Akka.Cluster/Akka.Cluster.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\ - true true @@ -50,20 +49,10 @@ bin\Release\Akka.Cluster.xml - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll - - - False - ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - @@ -103,17 +92,9 @@ - + - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll + True + True + + + + + + + + + ..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Cluster/packages.config b/src/core/Akka.Cluster/packages.config deleted file mode 100644 index 9a9d74d4213..00000000000 --- a/src/core/Akka.Cluster/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/core/Akka.Cluster/paket.references b/src/core/Akka.Cluster/paket.references new file mode 100644 index 00000000000..c56b0b9850c --- /dev/null +++ b/src/core/Akka.Cluster/paket.references @@ -0,0 +1,2 @@ +Google.ProtocolBuffers +Microsoft.Bcl.Immutable \ No newline at end of file diff --git a/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj b/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj index 86a2da95bb7..d8b51df80f3 100644 --- a/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj +++ b/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ 4.3.1.0 Akka.FSharp.Tests ..\..\ - true 802fc494 @@ -41,7 +39,6 @@ - 11 @@ -59,29 +56,17 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + - - ..\..\packages\FsCheck.0.9.4.0\lib\net40-Client\FsCheck.dll - - - ..\..\packages\FsCheck.Xunit.0.4.1.0\lib\net40-Client\FsCheck.Xunit.dll - @@ -107,21 +92,6 @@ Akka {5DEDDF90-37F0-48D3-A0B0-A5CBD8A7E377} - - True - - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - True - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - True - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - True - + + + + + + ..\..\..\packages\test\FsCheck\lib\net45\FsCheck.dll + True + True + + + + + + + ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45\FsCheck.dll + True + True + + + + + + + ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45+wp8\FsCheck.dll + True + True + + + + + + + ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45+wpa81+wp8\FsCheck.dll + True + True + + + + + + + + + ..\..\..\packages\test\FsCheck.Xunit\lib\net45\FsCheck.Xunit.dll + True + True + + + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\net20\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\net40\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\portable-net45+monoandroid10+monotouch10+xamarinios10\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\portable-net45+sl5+netcore45\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45+wp8\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45+wpa81+wp8\FSharp.Core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.FSharp.Tests/app.config b/src/core/Akka.FSharp.Tests/app.config index d3bd7964d53..f6c76d955c4 100644 --- a/src/core/Akka.FSharp.Tests/app.config +++ b/src/core/Akka.FSharp.Tests/app.config @@ -15,11 +15,155 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.FSharp.Tests/packages.config b/src/core/Akka.FSharp.Tests/packages.config deleted file mode 100644 index 5a0f41a0faf..00000000000 --- a/src/core/Akka.FSharp.Tests/packages.config +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.FSharp.Tests/paket.references b/src/core/Akka.FSharp.Tests/paket.references new file mode 100644 index 00000000000..419d69c953c --- /dev/null +++ b/src/core/Akka.FSharp.Tests/paket.references @@ -0,0 +1,2 @@ +group Test +FsCheck.Xunit \ No newline at end of file diff --git a/src/core/Akka.FSharp/Akka.FSharp.fsproj b/src/core/Akka.FSharp/Akka.FSharp.fsproj index 5c9f8051acf..be6288d9c5a 100644 --- a/src/core/Akka.FSharp/Akka.FSharp.fsproj +++ b/src/core/Akka.FSharp/Akka.FSharp.fsproj @@ -12,7 +12,6 @@ 4.3.1.0 Akka.FSharp ..\..\ - true true @@ -68,33 +67,16 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + - - ..\..\packages\FSPowerPack.Core.Community.3.0.0.0\Lib\Net40\FSharp.PowerPack.dll - - - ..\..\packages\FSPowerPack.Linq.Community.3.0.0.0\Lib\Net40\FSharp.PowerPack.Linq.dll - - - ..\..\packages\FsPickler.1.2.21\lib\net45\FsPickler.dll - True - @@ -116,4 +98,135 @@ --> + + + + + + ..\..\..\packages\FsPickler\lib\net35\FsPickler.dll + True + True + + + + + + + ..\..\..\packages\FsPickler\lib\net40\FsPickler.dll + True + True + + + + + + + ..\..\..\packages\FsPickler\lib\net45\FsPickler.dll + True + True + + + + + + + + + ..\..\..\packages\FSPowerPack.Core.Community\Lib\Net20\FSharp.PowerPack.dll + True + True + + + + + + + ..\..\..\packages\FSPowerPack.Core.Community\Lib\Net40\FSharp.PowerPack.dll + True + True + + + + + + + ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl3\FSharp.PowerPack.Compatibility.dll + True + True + + + ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl3\FSharp.PowerPack.dll + True + True + + + + + + + ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl4\FSharp.PowerPack.Compatibility.dll + True + True + + + ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl4\FSharp.PowerPack.dll + True + True + + + + + + + ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl5\FSharp.PowerPack.Compatibility.dll + True + True + + + ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl5\FSharp.PowerPack.Linq.dll + True + True + + + ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl5\FSharp.PowerPack.dll + True + True + + + + + + + ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl4-windowsphone71\FSharp.PowerPack.Compatibility.dll + True + True + + + ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl4-windowsphone71\FSharp.PowerPack.dll + True + True + + + + + + + + + ..\..\..\packages\FSPowerPack.Linq.Community\Lib\Net20\FSharp.PowerPack.Linq.dll + True + True + + + + + + + ..\..\..\packages\FSPowerPack.Linq.Community\Lib\Net40\FSharp.PowerPack.Linq.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.FSharp/FsApi.fs b/src/core/Akka.FSharp/FsApi.fs index e22338f11db..d0c15f0ace9 100644 --- a/src/core/Akka.FSharp/FsApi.fs +++ b/src/core/Akka.FSharp/FsApi.fs @@ -435,7 +435,7 @@ and ExprDecider (expr: Expr<(exn->Directive)>) = member this.Decide (e: exn): Directive = this.Compiled.Value (e) interface ISurrogated with member this.ToSurrogate _ = - let fsp = Nessos.FsPickler.FsPickler.CreateBinary() + let fsp = Nessos.FsPickler.FsPickler.CreateBinary() ExprDeciderSurrogate(Serialization.serializeToBinary fsp this.Expr) :> ISurrogate type Strategy = diff --git a/src/core/Akka.FSharp/app.config b/src/core/Akka.FSharp/app.config index bb9b825d392..480973c5631 100644 --- a/src/core/Akka.FSharp/app.config +++ b/src/core/Akka.FSharp/app.config @@ -1,11 +1,155 @@  - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.FSharp/packages.config b/src/core/Akka.FSharp/packages.config deleted file mode 100644 index 7b95c7adab6..00000000000 --- a/src/core/Akka.FSharp/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/core/Akka.FSharp/paket.references b/src/core/Akka.FSharp/paket.references new file mode 100644 index 00000000000..a70343f1d50 --- /dev/null +++ b/src/core/Akka.FSharp/paket.references @@ -0,0 +1,2 @@ +FsPickler +FSPowerPack.Linq.Community \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj index 7de85e8c081..e16fa009554 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj +++ b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ v4.5 512 ..\..\ - true 46f5f680 @@ -34,23 +32,9 @@ 4 - - ..\..\packages\faker-csharp.1.2.0\lib\net4\Faker.dll - - - False - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - False - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -89,21 +73,12 @@ - + - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\packages\faker-csharp\lib\net35\Faker.Net35.dll + True + True + + + + + + + ..\..\..\packages\faker-csharp\lib\net4\Faker.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/packages.config b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/packages.config deleted file mode 100644 index b7134ca0954..00000000000 --- a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/paket.references b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/paket.references new file mode 100644 index 00000000000..deaf88e37f2 --- /dev/null +++ b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/paket.references @@ -0,0 +1,3 @@ +faker-csharp +group Test +xunit \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj b/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj index 90ed00dbd8c..7d25c8ef0d1 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj +++ b/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\ - true true @@ -32,10 +31,6 @@ 4 - - False - ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - @@ -78,7 +73,7 @@ - + @@ -90,13 +85,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/packages.config b/src/core/Akka.MultiNodeTestRunner.Shared/packages.config deleted file mode 100644 index 505e58836ba..00000000000 --- a/src/core/Akka.MultiNodeTestRunner.Shared/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/paket.references b/src/core/Akka.MultiNodeTestRunner.Shared/paket.references new file mode 100644 index 00000000000..1063d003b92 --- /dev/null +++ b/src/core/Akka.MultiNodeTestRunner.Shared/paket.references @@ -0,0 +1 @@ +Newtonsoft.Json \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj index dd8a6c268d4..556d1354051 100644 --- a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj +++ b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj @@ -1,4 +1,4 @@ - + @@ -38,17 +38,9 @@ - - False - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - - False - ..\..\packages\xunit.runner.utility.2.1.0-beta2-build2981\lib\net35\xunit.runner.utility.desktop.dll - @@ -60,7 +52,7 @@ - + @@ -84,16 +76,8 @@ Akka - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\win8\xunit.runner.utility.win8.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\net35\xunit.runner.utility.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\monoandroid\xunit.runner.utility.MonoAndroid.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\monotouch\xunit.runner.utility.MonoTouch.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\wp8\xunit.runner.utility.wp8.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\Xamarin.iOS\xunit.runner.utility.iOS-Universal.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\portable-wpa81+win81\xunit.runner.utility.universal.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/App.config b/src/core/Akka.MultiNodeTestRunner/App.config index 8e15646352e..fde80ced889 100644 --- a/src/core/Akka.MultiNodeTestRunner/App.config +++ b/src/core/Akka.MultiNodeTestRunner/App.config @@ -1,6 +1,155 @@ - + - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/packages.config b/src/core/Akka.MultiNodeTestRunner/packages.config deleted file mode 100644 index ea90325cbbf..00000000000 --- a/src/core/Akka.MultiNodeTestRunner/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/paket.references b/src/core/Akka.MultiNodeTestRunner/paket.references new file mode 100644 index 00000000000..e16c8c54501 --- /dev/null +++ b/src/core/Akka.MultiNodeTestRunner/paket.references @@ -0,0 +1,2 @@ +group Test +xunit.runner.utility \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTests/paket.references b/src/core/Akka.MultiNodeTests/paket.references new file mode 100644 index 00000000000..26d1c8e78f3 --- /dev/null +++ b/src/core/Akka.MultiNodeTests/paket.references @@ -0,0 +1,3 @@ +Microsoft.Bcl.Immutable +group Test +xunit \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj index e3721881d32..ce9853fcdc8 100644 --- a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj +++ b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\ - true publish\ true Disk @@ -51,14 +50,6 @@ - - False - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - False - ..\..\packages\xunit.runner.utility.2.1.0-beta2-build2981\lib\net35\xunit.runner.utility.desktop.dll - @@ -68,7 +59,7 @@ - + @@ -98,13 +89,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\win8\xunit.runner.utility.win8.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\net35\xunit.runner.utility.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\monoandroid\xunit.runner.utility.MonoAndroid.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\monotouch\xunit.runner.utility.MonoTouch.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\wp8\xunit.runner.utility.wp8.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\Xamarin.iOS\xunit.runner.utility.iOS-Universal.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\portable-wpa81+win81\xunit.runner.utility.universal.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/App.config b/src/core/Akka.NodeTestRunner/App.config index 393b6e01b31..09fc8e52b2d 100644 --- a/src/core/Akka.NodeTestRunner/App.config +++ b/src/core/Akka.NodeTestRunner/App.config @@ -1,4 +1,4 @@ - +
@@ -12,4 +12,153 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/packages.config b/src/core/Akka.NodeTestRunner/packages.config deleted file mode 100644 index b4605234264..00000000000 --- a/src/core/Akka.NodeTestRunner/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/paket.references b/src/core/Akka.NodeTestRunner/paket.references new file mode 100644 index 00000000000..e16c8c54501 --- /dev/null +++ b/src/core/Akka.NodeTestRunner/paket.references @@ -0,0 +1,2 @@ +group Test +xunit.runner.utility \ No newline at end of file diff --git a/src/core/Akka.Persistence.FSharp/app.config b/src/core/Akka.Persistence.FSharp/app.config index bb9b825d392..480973c5631 100644 --- a/src/core/Akka.Persistence.FSharp/app.config +++ b/src/core/Akka.Persistence.FSharp/app.config @@ -1,11 +1,155 @@  - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj b/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj index a37e7151954..aab37b55df7 100644 --- a/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj +++ b/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ v4.5 512 ..\..\ - true b3f6fdc7 @@ -40,15 +38,6 @@ - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -75,20 +64,12 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit.Tests/packages.config b/src/core/Akka.Persistence.TestKit.Tests/packages.config deleted file mode 100644 index 3109db107fb..00000000000 --- a/src/core/Akka.Persistence.TestKit.Tests/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit.Tests/paket.references b/src/core/Akka.Persistence.TestKit.Tests/paket.references new file mode 100644 index 00000000000..4bf78cf8fea --- /dev/null +++ b/src/core/Akka.Persistence.TestKit.Tests/paket.references @@ -0,0 +1,2 @@ +group Test +xunit \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj b/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj index 406a554938d..d785ee52887 100644 --- a/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj +++ b/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ v4.5 512 ..\..\ - true f8afe7eb @@ -41,15 +39,6 @@ - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -80,17 +69,9 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit/packages.config b/src/core/Akka.Persistence.TestKit/packages.config deleted file mode 100644 index 3109db107fb..00000000000 --- a/src/core/Akka.Persistence.TestKit/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit/paket.references b/src/core/Akka.Persistence.TestKit/paket.references new file mode 100644 index 00000000000..4bf78cf8fea --- /dev/null +++ b/src/core/Akka.Persistence.TestKit/paket.references @@ -0,0 +1,2 @@ +group Test +xunit \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj index ef31b854a22..ee4cc7e5e76 100644 --- a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj +++ b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ v4.5 512 ..\ - true fb9ab2f3 @@ -34,29 +32,12 @@ 4 - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - True - - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -100,25 +81,12 @@ - + - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/CHANGES.txt b/src/core/Akka.Persistence.Tests/CHANGES.txt deleted file mode 100644 index d80368c78f2..00000000000 --- a/src/core/Akka.Persistence.Tests/CHANGES.txt +++ /dev/null @@ -1,99 +0,0 @@ -=============================================================================== -Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet -(skeet@pobox.com) based on the work of many talented people. - -For more information about this port, visit its homepage: -http://protobuf-csharp-port.googlecode.com - -For more information about Protocol Buffers in general, visit the project page -for the C++, Java and Python project: -http://protobuf.googlecode.com -=============================================================================== -RELEASE NOTES - Version 2.4.1.473 -=============================================================================== - -Features: -- Added option service_generator_type to control service generation with - NONE, GENERIC, INTERFACE, or IRPCDISPATCH -- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking - services and implementations. -- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the - location of protoc.exe. -- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow - custom implementation of writers with both speed and size optimizations. -- Addition of the "Google.ProtoBuffers.Serialization" assembly to support - reading and writing messages to/from XML, JSON, IDictionary<,> and others. -- Several performance related fixes and tweeks -- Issue 3: Add option to mark generated code with attribute -- Issue 20: Support for decorating classes [Serializable] -- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] -- Issue 22: Reusable Builder classes -- Issue 24: Support for using Json/Xml formats with ICodedInputStream -- Issue 25: Added support for NuGet packages -- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 - -Fixes: -- Issue 13: Message with Field same name as message causes uncompilable .cs -- Issue 16: Does not integrate well with other tooling -- Issue 19: Support for negative enum values -- Issue 26: AddRange in GeneratedBuilder iterates twice. -- Issue 27: Remove XML documentation output from test projects to clear - warnings/errors. -- Issue 28: Circular message dependencies result in null default values for - Message fields. -- Issue 29: Message classes generated have a public default constructor. You - can disable private ctor generation with the option generate_private_ctor. -- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ -- Big-endian support for float, and double on Silverlight -- Packed and Unpacked parsing allow for all repeated, as per version 2.3 -- Fix for leaving Builder a public ctor on internal classes for use with - generic "where T: new()" constraints. - -Other: -- Changed the code signing key to a privately held key -- Reformatted all code and line-endings to C# defaults -- Reworking of performance benchmarks to produce reliable results, option /v2 -- Issue 34: Silverlight assemblies are now unit tested - -=============================================================================== -RELEASE NOTES - Version 2.3.0.277 -=============================================================================== - -Features: -- Added cls_compliance option to generate attributes indicating - non-CLS-compliance. -- Added file_extension option to control the generated output file's extension. -- Added umbrella_namespace option to place the umbrella class into a nested - namespace to address issues with proto files having the same name as a - message it contains. -- Added output_directory option to set the output path for the source file(s). -- Added ignore_google_protobuf option to avoid generating code for includes - from the google.protobuf package. -- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to - generate code with "option optimize_for = LITE_RUNTIME;". -- Added ability to invoke protoc.exe from within ProtoGen.exe. -- Upgraded to protoc.exe (2.3) compiler. - -Fixes: -- Issue 9: Class cannot be static and sealed error -- Issue 12: default value for enumerate fields must be filled out - -Other: -- Rewrite of build using MSBbuild instead of NAnt -- Moved to NUnit Version 2.2.8.0 -- Changed to using secure .snk for releases - -=============================================================================== -RELEASE NOTES - Version 0.9.1 -=============================================================================== - -Fixes: -- issue 10: Incorrect encoding of packed fields when serialized - -=============================================================================== -RELEASE NOTES - Version 0.9.0 -=============================================================================== - -- Initial release - -=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/licenses/license.txt b/src/core/Akka.Persistence.Tests/licenses/license.txt deleted file mode 100644 index b8e773b2e05..00000000000 --- a/src/core/Akka.Persistence.Tests/licenses/license.txt +++ /dev/null @@ -1,31 +0,0 @@ -Protocol Buffers - Google's data interchange format -Copyright 2008-2010 Google Inc. All rights reserved. -http://github.com/jskeet/dotnet-protobufs/ -Original C++/Java/Python code: -http://code.google.com/p/protobuf/ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Persistence.Tests/licenses/protoc-license.txt b/src/core/Akka.Persistence.Tests/licenses/protoc-license.txt deleted file mode 100644 index c779cb0e1ed..00000000000 --- a/src/core/Akka.Persistence.Tests/licenses/protoc-license.txt +++ /dev/null @@ -1,36 +0,0 @@ -protoc.exe was built from the original source at http://code.google.com/p/protobuf/ -The licence for this code is as follows: - -Copyright 2008, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Code generated by the Protocol Buffer compiler is owned by the owner -of the input file used when generating it. This code is not -standalone and requires a support library to be linked with it. This -support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/packages.config b/src/core/Akka.Persistence.Tests/packages.config deleted file mode 100644 index 769769641c3..00000000000 --- a/src/core/Akka.Persistence.Tests/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/paket.references b/src/core/Akka.Persistence.Tests/paket.references new file mode 100644 index 00000000000..83a51faaffe --- /dev/null +++ b/src/core/Akka.Persistence.Tests/paket.references @@ -0,0 +1,3 @@ +Google.ProtocolBuffers +group Test +xunit \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Persistence.Tests/protos/google/protobuf/csharp_options.proto deleted file mode 100644 index 152df766f03..00000000000 --- a/src/core/Akka.Persistence.Tests/protos/google/protobuf/csharp_options.proto +++ /dev/null @@ -1,115 +0,0 @@ -// Extra options for C# generator - -import "google/protobuf/descriptor.proto"; - -package google.protobuf; - -message CSharpFileOptions { - - // Namespace for generated classes; defaults to the package. - optional string namespace = 1; - - // Name of the "umbrella" class used for metadata about all - // the messages within this file. Default is based on the name - // of the file. - optional string umbrella_classname = 2; - - // Whether classes should be public (true) or internal (false) - optional bool public_classes = 3 [default = true]; - - // Whether to generate a single file for everything within the - // .proto file (false), or one file per message (true). - // This option is not currently honored; please log a feature - // request if you really want it. - optional bool multiple_files = 4; - - // Whether to nest messages within a single umbrella class (true) - // or create the umbrella class as a peer, with messages as - // top-level classes in the namespace (false) - optional bool nest_classes = 5; - - // Generate appropriate support for Code Contracts - // (Ongoing; support should improve over time) - optional bool code_contracts = 6; - - // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" - // would generate files within [output directory]/Foo/Bar - optional bool expand_namespace_directories = 7; - - // Generate attributes indicating non-CLS-compliance - optional bool cls_compliance = 8 [default = true]; - - // Generate messages/builders with the [Serializable] attribute - optional bool add_serializable = 9 [default = false]; - - // Generates a private ctor for Message types - optional bool generate_private_ctor = 10 [default = true]; - - // The extension that should be appended to the umbrella_classname when creating files. - optional string file_extension = 221 [default = ".cs"]; - - // A nested namespace for the umbrella class. Helpful for name collisions caused by - // umbrella_classname conflicting with an existing type. This will be automatically - // set to 'Proto' if a collision is detected with types being generated. This value - // is ignored when nest_classes == true - optional string umbrella_namespace = 222; - - // The output path for the source file(s) generated - optional string output_directory = 223 [default = "."]; - - // Will ignore the type generations and remove dependencies for the descriptor proto - // files that declare their package to be "google.protobuf" - optional bool ignore_google_protobuf = 224 [default = false]; - - // Controls how services are generated, GENERIC is the deprecated original implementation - // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and - // implementations using the included Windows RPC interop libarary. - optional CSharpServiceType service_generator_type = 225 [default = NONE]; - - // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and - // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. - optional bool generated_code_attributes = 226 [default = false]; -} - -enum CSharpServiceType { - // Services are ignored by the generator - NONE = 0; - // Generates the original Java generic service implementations - GENERIC = 1; - // Generates an interface for the service and nothing else - INTERFACE = 2; - // Generates an interface for the service and client/server wrappers for the interface - IRPCDISPATCH = 3; -} - -extend FileOptions { - optional CSharpFileOptions csharp_file_options = 1000; -} - -extend FieldOptions { - optional CSharpFieldOptions csharp_field_options = 1000; -} - -message CSharpFieldOptions { - // Provides the ability to override the name of the property - // generated for this field. This is applied to all properties - // and methods to do with this field, including HasFoo, FooCount, - // FooList etc. - optional string property_name = 1; -} - -message CSharpServiceOptions { - optional string interface_id = 1; -} - -extend ServiceOptions { - optional CSharpServiceOptions csharp_service_options = 1000; -} - -message CSharpMethodOptions { - optional int32 dispatch_id = 1; -} - -extend MethodOptions { - optional CSharpMethodOptions csharp_method_options = 1000; -} \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/protos/google/protobuf/descriptor.proto b/src/core/Akka.Persistence.Tests/protos/google/protobuf/descriptor.proto deleted file mode 100644 index 233f879410e..00000000000 --- a/src/core/Akka.Persistence.Tests/protos/google/protobuf/descriptor.proto +++ /dev/null @@ -1,533 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. -// -// The messages in this file describe the definitions found in .proto files. -// A valid .proto file can be translated directly to a FileDescriptorProto -// without any other information (e.g. without reading its imports). - - - -package google.protobuf; -option java_package = "com.google.protobuf"; -option java_outer_classname = "DescriptorProtos"; - -// descriptor.proto must be optimized for speed because reflection-based -// algorithms don't work during bootstrapping. -option optimize_for = SPEED; - -// The protocol compiler can output a FileDescriptorSet containing the .proto -// files it parses. -message FileDescriptorSet { - repeated FileDescriptorProto file = 1; -} - -// Describes a complete .proto file. -message FileDescriptorProto { - optional string name = 1; // file name, relative to root of source tree - optional string package = 2; // e.g. "foo", "foo.bar", etc. - - // Names of files imported by this file. - repeated string dependency = 3; - - // All top-level definitions in this file. - repeated DescriptorProto message_type = 4; - repeated EnumDescriptorProto enum_type = 5; - repeated ServiceDescriptorProto service = 6; - repeated FieldDescriptorProto extension = 7; - - optional FileOptions options = 8; - - // This field contains optional information about the original source code. - // You may safely remove this entire field whithout harming runtime - // functionality of the descriptors -- the information is needed only by - // development tools. - optional SourceCodeInfo source_code_info = 9; -} - -// Describes a message type. -message DescriptorProto { - optional string name = 1; - - repeated FieldDescriptorProto field = 2; - repeated FieldDescriptorProto extension = 6; - - repeated DescriptorProto nested_type = 3; - repeated EnumDescriptorProto enum_type = 4; - - message ExtensionRange { - optional int32 start = 1; - optional int32 end = 2; - } - repeated ExtensionRange extension_range = 5; - - optional MessageOptions options = 7; -} - -// Describes a field within a message. -message FieldDescriptorProto { - enum Type { - // 0 is reserved for errors. - // Order is weird for historical reasons. - TYPE_DOUBLE = 1; - TYPE_FLOAT = 2; - TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT64 if negative - // values are likely. - TYPE_UINT64 = 4; - TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT32 if negative - // values are likely. - TYPE_FIXED64 = 6; - TYPE_FIXED32 = 7; - TYPE_BOOL = 8; - TYPE_STRING = 9; - TYPE_GROUP = 10; // Tag-delimited aggregate. - TYPE_MESSAGE = 11; // Length-delimited aggregate. - - // New in version 2. - TYPE_BYTES = 12; - TYPE_UINT32 = 13; - TYPE_ENUM = 14; - TYPE_SFIXED32 = 15; - TYPE_SFIXED64 = 16; - TYPE_SINT32 = 17; // Uses ZigZag encoding. - TYPE_SINT64 = 18; // Uses ZigZag encoding. - }; - - enum Label { - // 0 is reserved for errors - LABEL_OPTIONAL = 1; - LABEL_REQUIRED = 2; - LABEL_REPEATED = 3; - // TODO(sanjay): Should we add LABEL_MAP? - }; - - optional string name = 1; - optional int32 number = 3; - optional Label label = 4; - - // If type_name is set, this need not be set. If both this and type_name - // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. - optional Type type = 5; - - // For message and enum types, this is the name of the type. If the name - // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping - // rules are used to find the type (i.e. first the nested types within this - // message are searched, then within the parent, on up to the root - // namespace). - optional string type_name = 6; - - // For extensions, this is the name of the type being extended. It is - // resolved in the same manner as type_name. - optional string extendee = 2; - - // For numeric types, contains the original text representation of the value. - // For booleans, "true" or "false". - // For strings, contains the default text contents (not escaped in any way). - // For bytes, contains the C escaped value. All bytes >= 128 are escaped. - // TODO(kenton): Base-64 encode? - optional string default_value = 7; - - optional FieldOptions options = 8; -} - -// Describes an enum type. -message EnumDescriptorProto { - optional string name = 1; - - repeated EnumValueDescriptorProto value = 2; - - optional EnumOptions options = 3; -} - -// Describes a value within an enum. -message EnumValueDescriptorProto { - optional string name = 1; - optional int32 number = 2; - - optional EnumValueOptions options = 3; -} - -// Describes a service. -message ServiceDescriptorProto { - optional string name = 1; - repeated MethodDescriptorProto method = 2; - - optional ServiceOptions options = 3; -} - -// Describes a method of a service. -message MethodDescriptorProto { - optional string name = 1; - - // Input and output type names. These are resolved in the same way as - // FieldDescriptorProto.type_name, but must refer to a message type. - optional string input_type = 2; - optional string output_type = 3; - - optional MethodOptions options = 4; -} - -// =================================================================== -// Options - -// Each of the definitions above may have "options" attached. These are -// just annotations which may cause code to be generated slightly differently -// or may contain hints for code that manipulates protocol messages. -// -// Clients may define custom options as extensions of the *Options messages. -// These extensions may not yet be known at parsing time, so the parser cannot -// store the values in them. Instead it stores them in a field in the *Options -// message called uninterpreted_option. This field must have the same name -// across all *Options messages. We then use this field to populate the -// extensions when we build a descriptor, at which point all protos have been -// parsed and so all extensions are known. -// -// Extension numbers for custom options may be chosen as follows: -// * For options which will only be used within a single application or -// organization, or for experimental options, use field numbers 50000 -// through 99999. It is up to you to ensure that you do not use the -// same number for multiple options. -// * For options which will be published and used publicly by multiple -// independent entities, e-mail kenton@google.com to reserve extension -// numbers. Simply tell me how many you need and I'll send you back a -// set of numbers to use -- there's no need to explain how you intend to -// use them. If this turns out to be popular, a web service will be set up -// to automatically assign option numbers. - - -message FileOptions { - - // Sets the Java package where classes generated from this .proto will be - // placed. By default, the proto package is used, but this is often - // inappropriate because proto packages do not normally start with backwards - // domain names. - optional string java_package = 1; - - - // If set, all the classes from the .proto file are wrapped in a single - // outer class with the given name. This applies to both Proto1 - // (equivalent to the old "--one_java_file" option) and Proto2 (where - // a .proto always translates to a single class, but you may want to - // explicitly choose the class name). - optional string java_outer_classname = 8; - - // If set true, then the Java code generator will generate a separate .java - // file for each top-level message, enum, and service defined in the .proto - // file. Thus, these types will *not* be nested inside the outer class - // named by java_outer_classname. However, the outer class will still be - // generated to contain the file's getDescriptor() method as well as any - // top-level extensions defined in the file. - optional bool java_multiple_files = 10 [default=false]; - - // If set true, then the Java code generator will generate equals() and - // hashCode() methods for all messages defined in the .proto file. This is - // purely a speed optimization, as the AbstractMessage base class includes - // reflection-based implementations of these methods. - optional bool java_generate_equals_and_hash = 20 [default=false]; - - // Generated classes can be optimized for speed or code size. - enum OptimizeMode { - SPEED = 1; // Generate complete code for parsing, serialization, - // etc. - CODE_SIZE = 2; // Use ReflectionOps to implement these methods. - LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. - } - optional OptimizeMode optimize_for = 9 [default=SPEED]; - - - - - // Should generic services be generated in each language? "Generic" services - // are not specific to any particular RPC system. They are generated by the - // main code generators in each language (without additional plugins). - // Generic services were the only kind of service generation supported by - // early versions of proto2. - // - // Generic services are now considered deprecated in favor of using plugins - // that generate code specific to your particular RPC system. Therefore, - // these default to false. Old code which depends on generic services should - // explicitly set them to true. - optional bool cc_generic_services = 16 [default=false]; - optional bool java_generic_services = 17 [default=false]; - optional bool py_generic_services = 18 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MessageOptions { - // Set true to use the old proto1 MessageSet wire format for extensions. - // This is provided for backwards-compatibility with the MessageSet wire - // format. You should not use this for any other reason: It's less - // efficient, has fewer features, and is more complicated. - // - // The message must be defined exactly as follows: - // message Foo { - // option message_set_wire_format = true; - // extensions 4 to max; - // } - // Note that the message cannot have any defined fields; MessageSets only - // have extensions. - // - // All extensions of your type must be singular messages; e.g. they cannot - // be int32s, enums, or repeated messages. - // - // Because this is an option, the above two restrictions are not enforced by - // the protocol compiler. - optional bool message_set_wire_format = 1 [default=false]; - - // Disables the generation of the standard "descriptor()" accessor, which can - // conflict with a field of the same name. This is meant to make migration - // from proto1 easier; new code should avoid fields named "descriptor". - optional bool no_standard_descriptor_accessor = 2 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message FieldOptions { - // The ctype option instructs the C++ code generator to use a different - // representation of the field than it normally would. See the specific - // options below. This option is not yet implemented in the open source - // release -- sorry, we'll try to include it in a future version! - optional CType ctype = 1 [default = STRING]; - enum CType { - // Default mode. - STRING = 0; - - CORD = 1; - - STRING_PIECE = 2; - } - // The packed option can be enabled for repeated primitive fields to enable - // a more efficient representation on the wire. Rather than repeatedly - // writing the tag and type for each element, the entire array is encoded as - // a single length-delimited blob. - optional bool packed = 2; - - - // Is this field deprecated? - // Depending on the target platform, this can emit Deprecated annotations - // for accessors, or it will be completely ignored; in the very least, this - // is a formalization for deprecating fields. - optional bool deprecated = 3 [default=false]; - - // EXPERIMENTAL. DO NOT USE. - // For "map" fields, the name of the field in the enclosed type that - // is the key for this map. For example, suppose we have: - // message Item { - // required string name = 1; - // required string value = 2; - // } - // message Config { - // repeated Item items = 1 [experimental_map_key="name"]; - // } - // In this situation, the map key for Item will be set to "name". - // TODO: Fully-implement this, then remove the "experimental_" prefix. - optional string experimental_map_key = 9; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumOptions { - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumValueOptions { - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message ServiceOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MethodOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -// A message representing a option the parser does not recognize. This only -// appears in options protos created by the compiler::Parser class. -// DescriptorPool resolves these when building Descriptor objects. Therefore, -// options protos in descriptor objects (e.g. returned by Descriptor::options(), -// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions -// in them. -message UninterpretedOption { - // The name of the uninterpreted option. Each string represents a segment in - // a dot-separated name. is_extension is true iff a segment represents an - // extension (denoted with parentheses in options specs in .proto files). - // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents - // "foo.(bar.baz).qux". - message NamePart { - required string name_part = 1; - required bool is_extension = 2; - } - repeated NamePart name = 2; - - // The value of the uninterpreted option, in whatever type the tokenizer - // identified it as during parsing. Exactly one of these should be set. - optional string identifier_value = 3; - optional uint64 positive_int_value = 4; - optional int64 negative_int_value = 5; - optional double double_value = 6; - optional bytes string_value = 7; - optional string aggregate_value = 8; -} - -// =================================================================== -// Optional source code info - -// Encapsulates information about the original source file from which a -// FileDescriptorProto was generated. -message SourceCodeInfo { - // A Location identifies a piece of source code in a .proto file which - // corresponds to a particular definition. This information is intended - // to be useful to IDEs, code indexers, documentation generators, and similar - // tools. - // - // For example, say we have a file like: - // message Foo { - // optional string foo = 1; - // } - // Let's look at just the field definition: - // optional string foo = 1; - // ^ ^^ ^^ ^ ^^^ - // a bc de f ghi - // We have the following locations: - // span path represents - // [a,i) [ 4, 0, 2, 0 ] The whole field definition. - // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). - // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). - // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). - // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). - // - // Notes: - // - A location may refer to a repeated field itself (i.e. not to any - // particular index within it). This is used whenever a set of elements are - // logically enclosed in a single code segment. For example, an entire - // extend block (possibly containing multiple extension definitions) will - // have an outer location whose path refers to the "extensions" repeated - // field without an index. - // - Multiple locations may have the same path. This happens when a single - // logical declaration is spread out across multiple places. The most - // obvious example is the "extend" block again -- there may be multiple - // extend blocks in the same scope, each of which will have the same path. - // - A location's span is not always a subset of its parent's span. For - // example, the "extendee" of an extension declaration appears at the - // beginning of the "extend" block and is shared by all extensions within - // the block. - // - Just because a location's span is a subset of some other location's span - // does not mean that it is a descendent. For example, a "group" defines - // both a type and a field in a single declaration. Thus, the locations - // corresponding to the type and field and their components will overlap. - // - Code which tries to interpret locations should probably be designed to - // ignore those that it doesn't understand, as more types of locations could - // be recorded in the future. - repeated Location location = 1; - message Location { - // Identifies which part of the FileDescriptorProto was defined at this - // location. - // - // Each element is a field number or an index. They form a path from - // the root FileDescriptorProto to the place where the definition. For - // example, this path: - // [ 4, 3, 2, 7, 1 ] - // refers to: - // file.message_type(3) // 4, 3 - // .field(7) // 2, 7 - // .name() // 1 - // This is because FileDescriptorProto.message_type has field number 4: - // repeated DescriptorProto message_type = 4; - // and DescriptorProto.field has field number 2: - // repeated FieldDescriptorProto field = 2; - // and FieldDescriptorProto.name has field number 1: - // optional string name = 1; - // - // Thus, the above path gives the location of a field name. If we removed - // the last element: - // [ 4, 3, 2, 7 ] - // this path refers to the whole field declaration (from the beginning - // of the label to the terminating semicolon). - repeated int32 path = 1 [packed=true]; - - // Always has exactly three or four elements: start line, start column, - // end line (optional, otherwise assumed same as start line), end column. - // These are packed into a single field for efficiency. Note that line - // and column numbers are zero-based -- typically you will want to add - // 1 to each before displaying to a user. - repeated int32 span = 2 [packed=true]; - - // TODO(kenton): Record comments appearing before and after the - // declaration. - } -} diff --git a/src/core/Akka.Persistence.Tests/protos/tutorial/addressbook.proto b/src/core/Akka.Persistence.Tests/protos/tutorial/addressbook.proto deleted file mode 100644 index 5abe35ce39b..00000000000 --- a/src/core/Akka.Persistence.Tests/protos/tutorial/addressbook.proto +++ /dev/null @@ -1,31 +0,0 @@ -package tutorial; - -import "google/protobuf/csharp_options.proto"; -option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; -option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; - -option optimize_for = SPEED; - -message Person { - required string name = 1; - required int32 id = 2; // Unique ID number for this person. - optional string email = 3; - - enum PhoneType { - MOBILE = 0; - HOME = 1; - WORK = 2; - } - - message PhoneNumber { - required string number = 1; - optional PhoneType type = 2 [default = HOME]; - } - - repeated PhoneNumber phone = 4; -} - -// Our address book file is just one of these. -message AddressBook { - repeated Person person = 1; -} diff --git a/src/core/Akka.Persistence/Akka.Persistence.csproj b/src/core/Akka.Persistence/Akka.Persistence.csproj index 3939835af65..ce5c00155b4 100644 --- a/src/core/Akka.Persistence/Akka.Persistence.csproj +++ b/src/core/Akka.Persistence/Akka.Persistence.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\ - true true @@ -33,16 +32,6 @@ bin\Release\Akka.Persistence.xml - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll - - - False - ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - @@ -85,7 +74,7 @@ - + @@ -96,13 +85,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll + True + True + + + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence/packages.config b/src/core/Akka.Persistence/packages.config deleted file mode 100644 index f138ea9a2ef..00000000000 --- a/src/core/Akka.Persistence/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/core/Akka.Persistence/paket.references b/src/core/Akka.Persistence/paket.references new file mode 100644 index 00000000000..0a488371f3d --- /dev/null +++ b/src/core/Akka.Persistence/paket.references @@ -0,0 +1,2 @@ +Google.ProtocolBuffers +Newtonsoft.Json \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj b/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj index eedd04f8c89..d6d6a0a6d14 100644 --- a/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj +++ b/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ v4.5 512 ..\..\ - true bbb6736c @@ -34,24 +32,9 @@ 4 - - ..\..\packages\Helios.1.4.1\lib\net45\Helios.dll - - - False - ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - + @@ -85,20 +68,12 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\packages\Helios\lib\net40\Helios.NET40.dll + True + True + + + + + + + ..\..\..\packages\Helios\lib\net45\Helios.dll + True + True + + + + + + + + + ..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit.Tests/packages.config b/src/core/Akka.Remote.TestKit.Tests/packages.config deleted file mode 100644 index a56f6ab0c95..00000000000 --- a/src/core/Akka.Remote.TestKit.Tests/packages.config +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit.Tests/paket.references b/src/core/Akka.Remote.TestKit.Tests/paket.references new file mode 100644 index 00000000000..8e8ccb3aa47 --- /dev/null +++ b/src/core/Akka.Remote.TestKit.Tests/paket.references @@ -0,0 +1,4 @@ +Helios +Microsoft.Bcl.Immutable +group Test +xunit \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj index 41d81e09cd8..4f4fb565fa3 100644 --- a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj +++ b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj @@ -35,26 +35,9 @@ bin\Release\Akka.Remote.TestKit.xml - - ..\..\packages\Helios.1.4.1\lib\net45\Helios.dll - - - False - ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - - - False - ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -71,12 +54,6 @@ - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll - @@ -84,7 +61,6 @@ - @@ -115,7 +91,7 @@ - + @@ -137,14 +113,7 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll + True + True + + + + + + + + + ..\..\..\packages\Helios\lib\net40\Helios.NET40.dll + True + True + + + + + + + ..\..\..\packages\Helios\lib\net45\Helios.dll + True + True + + + + + + + + + ..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/packages.config b/src/core/Akka.Remote.TestKit/packages.config deleted file mode 100644 index d425f928973..00000000000 --- a/src/core/Akka.Remote.TestKit/packages.config +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/paket.references b/src/core/Akka.Remote.TestKit/paket.references new file mode 100644 index 00000000000..01868d55773 --- /dev/null +++ b/src/core/Akka.Remote.TestKit/paket.references @@ -0,0 +1,6 @@ +Google.ProtocolBuffers +Helios +Microsoft.Bcl.Immutable +Newtonsoft.Json +group Test +xunit \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj b/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj index 496d77ef415..c7fe32c55f7 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj +++ b/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ v4.5 512 ..\..\ - true 39dbaf16 @@ -44,17 +42,6 @@ - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - True - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - True - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -92,20 +79,12 @@ - + - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests.MultiNode/packages.config b/src/core/Akka.Remote.Tests.MultiNode/packages.config deleted file mode 100644 index 15502b4d7f9..00000000000 --- a/src/core/Akka.Remote.Tests.MultiNode/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests.MultiNode/paket.references b/src/core/Akka.Remote.Tests.MultiNode/paket.references new file mode 100644 index 00000000000..29b5e86f541 --- /dev/null +++ b/src/core/Akka.Remote.Tests.MultiNode/paket.references @@ -0,0 +1,6 @@ +group Test +xunit +xunit.abstractions +xunit.assert +xunit.core +xunit.extensibility.core \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj index 6f71f7d3f51..8d1e4c58429 100644 --- a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj +++ b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj @@ -1,6 +1,5 @@  - Debug AnyCPU @@ -12,7 +11,6 @@ v4.5 512 ..\..\ - true 338f57d2 @@ -55,21 +53,6 @@ - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll - - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -77,7 +60,6 @@ - @@ -124,7 +106,7 @@ - + @@ -149,13 +131,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/app.config b/src/core/Akka.Remote.Tests/app.config index a01ef9c6f2d..dd193b79992 100644 --- a/src/core/Akka.Remote.Tests/app.config +++ b/src/core/Akka.Remote.Tests/app.config @@ -1,11 +1,155 @@  - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/packages.config b/src/core/Akka.Remote.Tests/packages.config deleted file mode 100644 index 33c0ad1013c..00000000000 --- a/src/core/Akka.Remote.Tests/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/paket.references b/src/core/Akka.Remote.Tests/paket.references new file mode 100644 index 00000000000..83a51faaffe --- /dev/null +++ b/src/core/Akka.Remote.Tests/paket.references @@ -0,0 +1,3 @@ +Google.ProtocolBuffers +group Test +xunit \ No newline at end of file diff --git a/src/core/Akka.Remote/Akka.Remote.csproj b/src/core/Akka.Remote/Akka.Remote.csproj index cfb97c32851..5aeac8f2bc9 100644 --- a/src/core/Akka.Remote/Akka.Remote.csproj +++ b/src/core/Akka.Remote/Akka.Remote.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\ - true true @@ -51,17 +50,6 @@ false - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - - - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll - - - False - ..\..\packages\Helios.1.4.1\lib\net45\Helios.dll - True - @@ -116,7 +104,7 @@ - + @@ -125,7 +113,6 @@ - + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll + True + True + + + + + + + + + ..\..\..\packages\Helios\lib\net40\Helios.NET40.dll + True + True + + + + + + + ..\..\..\packages\Helios\lib\net45\Helios.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote/app.config b/src/core/Akka.Remote/app.config index a01ef9c6f2d..dd193b79992 100644 --- a/src/core/Akka.Remote/app.config +++ b/src/core/Akka.Remote/app.config @@ -1,11 +1,155 @@  - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote/packages.config b/src/core/Akka.Remote/packages.config deleted file mode 100644 index 59ca935b9db..00000000000 --- a/src/core/Akka.Remote/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/core/Akka.Remote/paket.references b/src/core/Akka.Remote/paket.references new file mode 100644 index 00000000000..b0ac4e292a0 --- /dev/null +++ b/src/core/Akka.Remote/paket.references @@ -0,0 +1,2 @@ +Google.ProtocolBuffers +Helios \ No newline at end of file diff --git a/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj b/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj index 12b8528062a..ba488464bbd 100644 --- a/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj +++ b/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj @@ -1,6 +1,5 @@  - Debug AnyCPU @@ -12,7 +11,6 @@ v4.5 512 ..\..\ - true 71eec8b3 @@ -34,15 +32,6 @@ - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -50,7 +39,6 @@ - @@ -111,9 +99,8 @@ - + - @@ -134,14 +121,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.TestKit.Tests/packages.config b/src/core/Akka.TestKit.Tests/packages.config deleted file mode 100644 index 3109db107fb..00000000000 --- a/src/core/Akka.TestKit.Tests/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.TestKit.Tests/paket.references b/src/core/Akka.TestKit.Tests/paket.references new file mode 100644 index 00000000000..4bf78cf8fea --- /dev/null +++ b/src/core/Akka.TestKit.Tests/paket.references @@ -0,0 +1,2 @@ +group Test +xunit \ No newline at end of file diff --git a/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj b/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj index a4718baa02a..3077d6c8e61 100644 --- a/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj +++ b/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ v4.5 512 ..\..\ - true 39789108 @@ -39,15 +37,6 @@ - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -62,7 +51,7 @@ - + @@ -80,14 +69,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Tests.Shared.Internals/packages.config b/src/core/Akka.Tests.Shared.Internals/packages.config deleted file mode 100644 index 3109db107fb..00000000000 --- a/src/core/Akka.Tests.Shared.Internals/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Tests.Shared.Internals/paket.references b/src/core/Akka.Tests.Shared.Internals/paket.references new file mode 100644 index 00000000000..4bf78cf8fea --- /dev/null +++ b/src/core/Akka.Tests.Shared.Internals/paket.references @@ -0,0 +1,2 @@ +group Test +xunit \ No newline at end of file diff --git a/src/core/Akka.Tests/Akka.Tests.csproj b/src/core/Akka.Tests/Akka.Tests.csproj index 4b0175a5767..0a5b4b5eba0 100644 --- a/src/core/Akka.Tests/Akka.Tests.csproj +++ b/src/core/Akka.Tests/Akka.Tests.csproj @@ -1,7 +1,5 @@ - + - - Debug AnyCPU @@ -13,7 +11,6 @@ v4.5 512 ..\..\ - true 1318f3e8 @@ -55,37 +52,11 @@ false - - ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.dll - - - ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.Core.dll - - - ..\..\packages\FsCheck.2.0.5\lib\net45\FsCheck.dll - True - - - ..\..\packages\FSharp.Core.3.1.2.5\lib\net40\FSharp.Core.dll - True - - - ..\..\packages\fastJSON.2.0.27.1\lib\net40\fastjson.dll - - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -93,7 +64,6 @@ - @@ -207,7 +177,7 @@ Always - + @@ -232,14 +202,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + + + ..\..\..\packages\fastJSON\lib\net35\fastjson.dll + True + True + + + + + + + ..\..\..\packages\fastJSON\lib\net20\fastjson.dll + True + True + + + + + + + ..\..\..\packages\fastJSON\lib\net40\fastjson.dll + True + True + + + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\win8\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\win8\FluentAssertions.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\net40\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\net40\FluentAssertions.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\net45\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\net45\FluentAssertions.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\sl5\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\sl5\FluentAssertions.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\sl5\Microsoft.CSharp.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\sl5\Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\wp8\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\wp8\FluentAssertions.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\portable-monotouch+monoandroid+xamarin.ios\FluentAssertions.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\portable-win81+wpa81\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\portable-win81+wpa81\FluentAssertions.dll + True + True + + + + + + + ..\..\..\packages\test\FluentAssertions\lib\portable-net40+sl5+win8+wp8+wpa81\FluentAssertions.Core.dll + True + True + + + ..\..\..\packages\test\FluentAssertions\lib\portable-net40+sl5+win8+wp8+wpa81\FluentAssertions.dll + True + True + + + + + + + + + ..\..\..\packages\test\FsCheck\lib\net45\FsCheck.dll + True + True + + + + + + + ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45\FsCheck.dll + True + True + + + + + + + ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45+wp8\FsCheck.dll + True + True + + + + + + + ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45+wpa81+wp8\FsCheck.dll + True + True + + + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\net20\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\net40\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\portable-net45+monoandroid10+monotouch10+xamarinios10\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\portable-net45+sl5+netcore45\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45+wp8\FSharp.Core.dll + True + True + + + + + + + ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45+wpa81+wp8\FSharp.Core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + + + + + <__paket__xunit_runner_visualstudio_props>win8\xunit.runner.visualstudio + <__paket__xunit_runner_visualstudio_targets>win8\xunit.runner.visualstudio + + + + + <__paket__xunit_runner_visualstudio_props>net20\xunit.runner.visualstudio + + + + + <__paket__xunit_runner_visualstudio_props>wpa81\xunit.runner.visualstudio + <__paket__xunit_runner_visualstudio_targets>wpa81\xunit.runner.visualstudio + + + + + <__paket__xunit_runner_visualstudio_props>portable-net45+aspnetcore50+win+wpa81+wp80+monotouch+monoandroid\xunit.runner.visualstudio + + + + + \ No newline at end of file diff --git a/src/core/Akka.Tests/App.config b/src/core/Akka.Tests/App.config index 886d119fefe..1e47aeaedf5 100644 --- a/src/core/Akka.Tests/App.config +++ b/src/core/Akka.Tests/App.config @@ -1,4 +1,4 @@ - +
@@ -24,4 +24,153 @@ ]]> - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Tests/packages.config b/src/core/Akka.Tests/packages.config deleted file mode 100644 index 09bb0a85065..00000000000 --- a/src/core/Akka.Tests/packages.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Tests/paket.references b/src/core/Akka.Tests/paket.references new file mode 100644 index 00000000000..c61f5807c71 --- /dev/null +++ b/src/core/Akka.Tests/paket.references @@ -0,0 +1,7 @@ +fastJSON + +group Test +FluentAssertions +FsCheck +xunit.extensions +xunit.runner.visualstudio \ No newline at end of file diff --git a/src/core/Akka/Akka.csproj b/src/core/Akka/Akka.csproj index e95cb9cf8b9..64e6cee98cb 100644 --- a/src/core/Akka/Akka.csproj +++ b/src/core/Akka/Akka.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\ - true true @@ -54,10 +53,6 @@ false - - False - ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - @@ -376,7 +371,7 @@ - + @@ -384,9 +379,7 @@ Always - - + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka/paket.references b/src/core/Akka/paket.references new file mode 100644 index 00000000000..1063d003b92 --- /dev/null +++ b/src/core/Akka/paket.references @@ -0,0 +1 @@ +Newtonsoft.Json \ No newline at end of file diff --git a/src/examples/Chat/ChatClient/App.config b/src/examples/Chat/ChatClient/App.config index dd008ecefcc..3e4504645bc 100644 --- a/src/examples/Chat/ChatClient/App.config +++ b/src/examples/Chat/ChatClient/App.config @@ -5,16 +5,155 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/Chat/ChatMessages/ChatMessages.csproj b/src/examples/Chat/ChatMessages/ChatMessages.csproj index d4d41984048..f865678523b 100644 --- a/src/examples/Chat/ChatMessages/ChatMessages.csproj +++ b/src/examples/Chat/ChatMessages/ChatMessages.csproj @@ -1,6 +1,5 @@  - Debug @@ -13,7 +12,6 @@ v4.5 512 ..\..\..\ - true ac874559 @@ -62,22 +60,13 @@ ..\..\..\packages\fastJSON.2.0.27.1\lib\net40\fastjson.dll - - ..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - - - ..\..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - - - ..\..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - - + @@ -86,13 +75,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\fastJSON\lib\net35\fastjson.dll + True + True + + + + + + + ..\..\..\..\packages\fastJSON\lib\net20\fastjson.dll + True + True + + + + + + + ..\..\..\..\packages\fastJSON\lib\net40\fastjson.dll + True + True + + + + + + + + + ..\..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win8\xunit.core + <__paket__xunit_core_targets>win8\xunit.core + + + + + <__paket__xunit_core_props>monoandroid\xunit.core + + + + + <__paket__xunit_core_props>monotouch\xunit.core + + + + + <__paket__xunit_core_props>wp8\xunit.core + <__paket__xunit_core_targets>wp8\xunit.core + + + + + <__paket__xunit_core_props>Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + + + + + <__paket__xunit_core_props>portable-win81+wpa81\xunit.core + <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + + + + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/Chat/ChatMessages/packages.config b/src/examples/Chat/ChatMessages/packages.config deleted file mode 100644 index 9ef0ee3dcd8..00000000000 --- a/src/examples/Chat/ChatMessages/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/examples/Chat/ChatMessages/paket.references b/src/examples/Chat/ChatMessages/paket.references new file mode 100644 index 00000000000..713ba4ffa9a --- /dev/null +++ b/src/examples/Chat/ChatMessages/paket.references @@ -0,0 +1,3 @@ +fastJSON +group Test +xunit \ No newline at end of file diff --git a/src/examples/Chat/ChatServer/App.config b/src/examples/Chat/ChatServer/App.config index dd008ecefcc..3e4504645bc 100644 --- a/src/examples/Chat/ChatServer/App.config +++ b/src/examples/Chat/ChatServer/App.config @@ -5,16 +5,155 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config index ac5cd466feb..47e89e97117 100644 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config @@ -1,4 +1,4 @@ - +
@@ -33,4 +33,153 @@ ]]> - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj index 06f0af15eb1..02783942f1b 100644 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\..\ - true AnyCPU @@ -35,9 +34,6 @@ - - ..\..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - @@ -51,7 +47,7 @@ - + @@ -64,13 +60,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/packages.config b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/packages.config deleted file mode 100644 index 8a2bcdbc2dd..00000000000 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/paket.references b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/paket.references new file mode 100644 index 00000000000..da543da7bdd --- /dev/null +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/paket.references @@ -0,0 +1 @@ +Microsoft.Bcl.Immutable \ No newline at end of file diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config index 0fa1de829b9..01ea0c6f779 100644 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config @@ -1,4 +1,4 @@ - +
@@ -34,4 +34,153 @@ ]]> - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj index 52fc6b8538a..a2b7485db2b 100644 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\..\ - true AnyCPU @@ -35,10 +34,6 @@ - - ..\..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - @@ -52,7 +47,7 @@ - + @@ -69,13 +64,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/packages.config b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/packages.config deleted file mode 100644 index 8a2bcdbc2dd..00000000000 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/paket.references b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/paket.references new file mode 100644 index 00000000000..da543da7bdd --- /dev/null +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/paket.references @@ -0,0 +1 @@ +Microsoft.Bcl.Immutable \ No newline at end of file diff --git a/src/examples/Cluster/Samples.Cluster.Simple/App.config b/src/examples/Cluster/Samples.Cluster.Simple/App.config index 702c085578b..abbd33d8065 100644 --- a/src/examples/Cluster/Samples.Cluster.Simple/App.config +++ b/src/examples/Cluster/Samples.Cluster.Simple/App.config @@ -1,4 +1,4 @@ - +
@@ -33,4 +33,153 @@ ]]> - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj b/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj index a231e642bad..047d2236275 100644 --- a/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj +++ b/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true AnyCPU @@ -35,10 +34,6 @@ - - False - ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - @@ -51,7 +46,7 @@ - + @@ -68,13 +63,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Samples.Cluster.Simple/packages.config b/src/examples/Cluster/Samples.Cluster.Simple/packages.config deleted file mode 100644 index 8a2bcdbc2dd..00000000000 --- a/src/examples/Cluster/Samples.Cluster.Simple/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/examples/Cluster/Samples.Cluster.Simple/paket.references b/src/examples/Cluster/Samples.Cluster.Simple/paket.references new file mode 100644 index 00000000000..da543da7bdd --- /dev/null +++ b/src/examples/Cluster/Samples.Cluster.Simple/paket.references @@ -0,0 +1 @@ +Microsoft.Bcl.Immutable \ No newline at end of file diff --git a/src/examples/FSharp.Api/App.config b/src/examples/FSharp.Api/App.config index a338d00a376..4c2eaa0cdb4 100644 --- a/src/examples/FSharp.Api/App.config +++ b/src/examples/FSharp.Api/App.config @@ -4,11 +4,155 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/FSharp.Api/FSharp.Api.fsproj b/src/examples/FSharp.Api/FSharp.Api.fsproj index cef1eb9b943..4715804bedc 100644 --- a/src/examples/FSharp.Api/FSharp.Api.fsproj +++ b/src/examples/FSharp.Api/FSharp.Api.fsproj @@ -13,7 +13,6 @@ 4.3.1.0 FSharp.Api ..\..\ - true true @@ -77,27 +76,16 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + - - ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - @@ -120,4 +108,61 @@ --> + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/FSharp.Api/packages.config b/src/examples/FSharp.Api/packages.config deleted file mode 100644 index 505e58836ba..00000000000 --- a/src/examples/FSharp.Api/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/examples/FSharp.Api/paket.references b/src/examples/FSharp.Api/paket.references new file mode 100644 index 00000000000..1063d003b92 --- /dev/null +++ b/src/examples/FSharp.Api/paket.references @@ -0,0 +1 @@ +Newtonsoft.Json \ No newline at end of file diff --git a/src/examples/FSharp.Deploy.Local/App.config b/src/examples/FSharp.Deploy.Local/App.config index a338d00a376..4c2eaa0cdb4 100644 --- a/src/examples/FSharp.Deploy.Local/App.config +++ b/src/examples/FSharp.Deploy.Local/App.config @@ -4,11 +4,155 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/FSharp.Deploy.Remote/App.config b/src/examples/FSharp.Deploy.Remote/App.config index a338d00a376..4c2eaa0cdb4 100644 --- a/src/examples/FSharp.Deploy.Remote/App.config +++ b/src/examples/FSharp.Deploy.Remote/App.config @@ -4,11 +4,155 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/FaultTolerance/App.config b/src/examples/FaultTolerance/App.config index 8e15646352e..fde80ced889 100644 --- a/src/examples/FaultTolerance/App.config +++ b/src/examples/FaultTolerance/App.config @@ -1,6 +1,155 @@ - + - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/FaultTolerance/FaultTolerance.csproj b/src/examples/FaultTolerance/FaultTolerance.csproj index e7b7753e67b..6cf2d93482d 100644 --- a/src/examples/FaultTolerance/FaultTolerance.csproj +++ b/src/examples/FaultTolerance/FaultTolerance.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\ - true AnyCPU @@ -34,10 +33,6 @@ 4 - - False - ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - @@ -48,7 +43,7 @@ - + @@ -57,13 +52,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/FaultTolerance/packages.config b/src/examples/FaultTolerance/packages.config deleted file mode 100644 index 505e58836ba..00000000000 --- a/src/examples/FaultTolerance/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/examples/FaultTolerance/paket.references b/src/examples/FaultTolerance/paket.references new file mode 100644 index 00000000000..1063d003b92 --- /dev/null +++ b/src/examples/FaultTolerance/paket.references @@ -0,0 +1 @@ +Newtonsoft.Json \ No newline at end of file diff --git a/src/examples/HelloWorld/FSharp.HelloAkka/App.config b/src/examples/HelloWorld/FSharp.HelloAkka/App.config index a338d00a376..4c2eaa0cdb4 100644 --- a/src/examples/HelloWorld/FSharp.HelloAkka/App.config +++ b/src/examples/HelloWorld/FSharp.HelloAkka/App.config @@ -4,11 +4,155 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/HelloWorld/HelloAkka/App.config b/src/examples/HelloWorld/HelloAkka/App.config index 8e15646352e..fde80ced889 100644 --- a/src/examples/HelloWorld/HelloAkka/App.config +++ b/src/examples/HelloWorld/HelloAkka/App.config @@ -1,6 +1,155 @@ - + - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/PersistenceExample.FsApi/App.config b/src/examples/PersistenceExample.FsApi/App.config index a338d00a376..4c2eaa0cdb4 100644 --- a/src/examples/PersistenceExample.FsApi/App.config +++ b/src/examples/PersistenceExample.FsApi/App.config @@ -4,11 +4,155 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/PersistenceExample.FsApi/PersistenceExample.FsApi.fsproj b/src/examples/PersistenceExample.FsApi/PersistenceExample.FsApi.fsproj index 9f66e90a0b1..443bd1e5416 100644 --- a/src/examples/PersistenceExample.FsApi/PersistenceExample.FsApi.fsproj +++ b/src/examples/PersistenceExample.FsApi/PersistenceExample.FsApi.fsproj @@ -13,7 +13,6 @@ 4.3.1.0 PersistenceExample.FsApi ..\ - true true @@ -54,24 +53,13 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + - - ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - @@ -102,4 +90,61 @@ --> + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/PersistenceExample.FsApi/packages.config b/src/examples/PersistenceExample.FsApi/packages.config deleted file mode 100644 index 505e58836ba..00000000000 --- a/src/examples/PersistenceExample.FsApi/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/examples/PersistenceExample.FsApi/paket.references b/src/examples/PersistenceExample.FsApi/paket.references new file mode 100644 index 00000000000..1063d003b92 --- /dev/null +++ b/src/examples/PersistenceExample.FsApi/paket.references @@ -0,0 +1 @@ +Newtonsoft.Json \ No newline at end of file diff --git a/src/examples/PersistenceExample/App.config b/src/examples/PersistenceExample/App.config index 8e15646352e..fde80ced889 100644 --- a/src/examples/PersistenceExample/App.config +++ b/src/examples/PersistenceExample/App.config @@ -1,6 +1,155 @@ - + - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/RemoteDeploy/System1/App.config b/src/examples/RemoteDeploy/System1/App.config index a2dd99c6b4c..78a11d4cc5e 100644 --- a/src/examples/RemoteDeploy/System1/App.config +++ b/src/examples/RemoteDeploy/System1/App.config @@ -4,11 +4,155 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/RemoteDeploy/System1/System1.csproj b/src/examples/RemoteDeploy/System1/System1.csproj index 3dcf4fc5dc1..17496aea8be 100644 --- a/src/examples/RemoteDeploy/System1/System1.csproj +++ b/src/examples/RemoteDeploy/System1/System1.csproj @@ -1,4 +1,4 @@ - + @@ -83,13 +83,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\fastJSON\lib\net35\fastjson.dll + True + True + + + + + + + ..\..\..\..\packages\fastJSON\lib\net20\fastjson.dll + True + True + + + + + + + ..\..\..\..\packages\fastJSON\lib\net40\fastjson.dll + True + True + + + + + + + + + ..\..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + + + + + + ..\..\..\..\packages\qdfeed\lib\net35\QDFeedParser.dll + True + True + + + + + + + ..\..\..\..\packages\qdfeed\lib\net45\QDFeedParser.dll + True + True + + + + + + + ..\..\..\..\packages\qdfeed\lib\sl40\QDFeedParser.Silverlight.dll + True + True + + + + + + + ..\..\..\..\packages\qdfeed\lib\wp71\QDFeedParser.Mobile.dll + True + True + + + + + + + ..\..\..\..\packages\qdfeed\lib\windowsphone8\QDFeedParser.Mobile.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/Stocks/SymbolLookup/packages.config b/src/examples/Stocks/SymbolLookup/packages.config deleted file mode 100644 index 6aa2a478aed..00000000000 --- a/src/examples/Stocks/SymbolLookup/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/examples/Stocks/SymbolLookup/paket.references b/src/examples/Stocks/SymbolLookup/paket.references new file mode 100644 index 00000000000..e5ccd0a69bd --- /dev/null +++ b/src/examples/Stocks/SymbolLookup/paket.references @@ -0,0 +1,3 @@ +fastJSON +Microsoft.Bcl.Immutable +qdfeed \ No newline at end of file diff --git a/src/examples/TcpEchoService.Server/App.config b/src/examples/TcpEchoService.Server/App.config index 8e15646352e..fde80ced889 100644 --- a/src/examples/TcpEchoService.Server/App.config +++ b/src/examples/TcpEchoService.Server/App.config @@ -1,6 +1,155 @@ - + - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeClient/App.config b/src/examples/TimeServer/TimeClient/App.config index b8c84fb9a0c..a5279a7ef0f 100644 --- a/src/examples/TimeServer/TimeClient/App.config +++ b/src/examples/TimeServer/TimeClient/App.config @@ -1,4 +1,4 @@ - +
@@ -52,4 +52,153 @@ ]]> - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeClient/TimeClient.csproj b/src/examples/TimeServer/TimeClient/TimeClient.csproj index ac2cc61fe08..1e5e4a75b30 100644 --- a/src/examples/TimeServer/TimeClient/TimeClient.csproj +++ b/src/examples/TimeServer/TimeClient/TimeClient.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true AnyCPU @@ -34,10 +33,6 @@ 4 - - ..\..\..\packages\Helios.1.4.1\lib\net45\Helios.dll - True - @@ -48,7 +43,7 @@ - + @@ -61,13 +56,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\Helios\lib\net40\Helios.NET40.dll + True + True + + + + + + + ..\..\..\..\packages\Helios\lib\net45\Helios.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeClient/packages.config b/src/examples/TimeServer/TimeClient/packages.config deleted file mode 100644 index 04c0607cbc1..00000000000 --- a/src/examples/TimeServer/TimeClient/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/examples/TimeServer/TimeClient/paket.references b/src/examples/TimeServer/TimeClient/paket.references new file mode 100644 index 00000000000..c3d91cab15d --- /dev/null +++ b/src/examples/TimeServer/TimeClient/paket.references @@ -0,0 +1 @@ +Helios \ No newline at end of file diff --git a/src/examples/TimeServer/TimeServer/App.config b/src/examples/TimeServer/TimeServer/App.config index be06f62e62c..b832a59bd78 100644 --- a/src/examples/TimeServer/TimeServer/App.config +++ b/src/examples/TimeServer/TimeServer/App.config @@ -1,4 +1,4 @@ - +
@@ -52,4 +52,153 @@ ]]> - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeServer/TimeServer.csproj b/src/examples/TimeServer/TimeServer/TimeServer.csproj index 19662bafc96..67f61bd3137 100644 --- a/src/examples/TimeServer/TimeServer/TimeServer.csproj +++ b/src/examples/TimeServer/TimeServer/TimeServer.csproj @@ -12,7 +12,6 @@ v4.5 512 ..\..\..\ - true AnyCPU @@ -34,10 +33,6 @@ 4 - - False - ..\..\..\packages\Helios.1.4.1\lib\net45\Helios.dll - @@ -48,7 +43,7 @@ - + @@ -61,13 +56,6 @@ - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + + ..\..\..\..\packages\Helios\lib\net40\Helios.NET40.dll + True + True + + + + + + + ..\..\..\..\packages\Helios\lib\net45\Helios.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeServer/packages.config b/src/examples/TimeServer/TimeServer/packages.config deleted file mode 100644 index 04c0607cbc1..00000000000 --- a/src/examples/TimeServer/TimeServer/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/examples/TimeServer/TimeServer/paket.references b/src/examples/TimeServer/TimeServer/paket.references new file mode 100644 index 00000000000..c3d91cab15d --- /dev/null +++ b/src/examples/TimeServer/TimeServer/paket.references @@ -0,0 +1 @@ +Helios \ No newline at end of file From abc561624a8afea7bccaf59e861da1ce03040185 Mon Sep 17 00:00:00 2001 From: Sean Gilliam Date: Wed, 7 Oct 2015 14:10:42 -0500 Subject: [PATCH 049/105] [api-docs] Fixed various x-references This PR fixes various x-reference issues in the xmldocs. Most of these are in the form of replacing with when included in the . Sandcastle misinterprets the former when in a summary and puts a placeholder **[!parameter name]** instead of the correct reference *parameter name*. --- .../AutoFacDependencyResolver.cs | 2 +- .../WindsorDependencyResolver.cs | 2 +- .../Akka.DI.Core/IDependencyResolver.cs | 2 +- .../NinjectDependencyResolver.cs | 2 +- src/core/Akka.Cluster/Cluster.cs | 12 +++--- .../Akka.Cluster/ClusterMetricsCollector.cs | 38 +++++++++---------- src/core/Akka.Cluster/Gossip.cs | 2 - .../Akka.Persistence/AtLeastOnceDelivery.cs | 4 +- src/core/Akka.Remote/AckedDelivery.cs | 2 +- src/core/Akka.Remote/RemoteDeployer.cs | 2 +- src/core/Akka.Remote/RemoteSystemDaemon.cs | 3 +- src/core/Akka.Remote/RemoteTransport.cs | 2 +- .../Akka.Remote/Transport/TestTransport.cs | 4 +- src/core/Akka.Remote/Transport/Transport.cs | 2 +- src/core/Akka.TestKit/TestKitBase_Receive.cs | 2 +- src/core/Akka.TestKit/TestKitBase_Within.cs | 8 ++-- src/core/Akka/Actor/ActorProducerPipeline.cs | 2 +- src/core/Akka/Actor/FSM.cs | 4 +- src/core/Akka/Actor/PipeToSupport.cs | 6 +-- src/core/Akka/Actor/ReceiveActor.cs | 32 ++++++++-------- src/core/Akka/Actor/SupervisorStrategy.cs | 1 - src/core/Akka/Dispatch/Dispatchers.cs | 2 +- .../MessageQueues/DequeWrapperMessageQueue.cs | 2 +- src/core/Akka/Event/LoggingAdapterBase.cs | 14 +++++-- src/core/Akka/Pattern/CircuitBreaker.cs | 4 +- src/core/Akka/Util/AtomicBoolean.cs | 8 ++-- src/core/Akka/Util/AtomicReference.cs | 10 ++--- src/core/Akka/Util/ContinuousEnumerator.cs | 4 +- .../Akka/Util/Internal/ArrayExtensions.cs | 19 ++++++---- .../Akka/Util/MatchHandler/PartialAction.cs | 4 +- src/core/Akka/Util/MurmurHash.cs | 4 +- 31 files changed, 106 insertions(+), 99 deletions(-) diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac/AutoFacDependencyResolver.cs b/src/contrib/dependencyInjection/Akka.DI.AutoFac/AutoFacDependencyResolver.cs index 2c07d3cebda..665e12acae1 100644 --- a/src/contrib/dependencyInjection/Akka.DI.AutoFac/AutoFacDependencyResolver.cs +++ b/src/contrib/dependencyInjection/Akka.DI.AutoFac/AutoFacDependencyResolver.cs @@ -83,7 +83,7 @@ public Func CreateActorFactory(Type actorType) } /// - /// Used to register the configuration for an actor of the specified type + /// Used to register the configuration for an actor of the specified type /// /// The type of actor the configuration is based /// The configuration object for the given actor type diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/WindsorDependencyResolver.cs b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/WindsorDependencyResolver.cs index eba1f14b0c8..1586e879354 100644 --- a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/WindsorDependencyResolver.cs +++ b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/WindsorDependencyResolver.cs @@ -73,7 +73,7 @@ public Func CreateActorFactory(Type actorType) } /// - /// Used to register the configuration for an actor of the specified type + /// Used to register the configuration for an actor of the specified type /// /// The type of actor the configuration is based /// The configuration object for the given actor type diff --git a/src/contrib/dependencyInjection/Akka.DI.Core/IDependencyResolver.cs b/src/contrib/dependencyInjection/Akka.DI.Core/IDependencyResolver.cs index 6eb2ccb22a7..d393f372231 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Core/IDependencyResolver.cs +++ b/src/contrib/dependencyInjection/Akka.DI.Core/IDependencyResolver.cs @@ -28,7 +28,7 @@ public interface IDependencyResolver /// A delegate factory used to create actors Func CreateActorFactory(Type actorType); /// - /// Used to register the configuration for an actor of the specified type + /// Used to register the configuration for an actor of the specified type /// /// The type of actor the configuration is based /// The configuration object for the given actor type diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject/NinjectDependencyResolver.cs b/src/contrib/dependencyInjection/Akka.DI.Ninject/NinjectDependencyResolver.cs index ff308c35eee..37144e4f96b 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Ninject/NinjectDependencyResolver.cs +++ b/src/contrib/dependencyInjection/Akka.DI.Ninject/NinjectDependencyResolver.cs @@ -73,7 +73,7 @@ public Func CreateActorFactory(Type actorType) } /// - /// Used to register the configuration for an actor of the specified type + /// Used to register the configuration for an actor of the specified type /// /// The type of actor the configuration is based /// The configuration object for the given actor type diff --git a/src/core/Akka.Cluster/Cluster.cs b/src/core/Akka.Cluster/Cluster.cs index 235613a8adb..5b9ce69bb32 100644 --- a/src/core/Akka.Cluster/Cluster.cs +++ b/src/core/Akka.Cluster/Cluster.cs @@ -111,7 +111,7 @@ private async Task GetClusterCoreRef() /// /// The actor who'll receive the cluster domain events /// subclasses - /// A snapshot of will be sent to as the first message + /// A snapshot of will be sent to as the first message public void Subscribe(IActorRef subscriber, Type[] to) { Subscribe(subscriber, ClusterEvent.SubscriptionInitialStateMode.InitialStateAsSnapshot, to); @@ -123,10 +123,10 @@ public void Subscribe(IActorRef subscriber, Type[] to) /// The actor who'll receive the cluster domain events /// /// If set to the events corresponding to the current state - /// will be sent to to mimic what it would have seen if it were listening to the events when they occurred in the past. + /// will be sent to to mimic what it would have seen if it were listening to the events when they occurred in the past. /// /// If set to - /// a snapshot of will be sent to as the first message. + /// a snapshot of will be sent to as the first message. /// subclasses public void Subscribe(IActorRef subscriber, ClusterEvent.SubscriptionInitialStateMode initialStateMode, Type[] to) { @@ -161,7 +161,7 @@ public void SendCurrentClusterState(IActorRef receiver) } /// - /// Try to join this cluster node specified by . + /// Try to join this cluster node specified by . /// A command is sent to the node to join. /// /// An actor system can only join a cluster once. Additional attempts will be ignored. @@ -187,7 +187,7 @@ public void JoinSeedNodes(ImmutableList
seedNodes) } /// - /// Send command to issue state transition to LEAVING for the node specified by . + /// Send command to issue state transition to LEAVING for the node specified by . /// The member will go through the status changes (not published to /// subscribers) followed by and finally . /// @@ -205,7 +205,7 @@ public void Leave(Address address) } /// - /// Send command to DOWN the node specified by . + /// Send command to DOWN the node specified by . /// /// When a member is considered by the failure detector to be unreachable the leader is not /// allowed to perform its duties, such as changing status of new joining members to . diff --git a/src/core/Akka.Cluster/ClusterMetricsCollector.cs b/src/core/Akka.Cluster/ClusterMetricsCollector.cs index f66d418bb2d..412c53512bc 100644 --- a/src/core/Akka.Cluster/ClusterMetricsCollector.cs +++ b/src/core/Akka.Cluster/ClusterMetricsCollector.cs @@ -223,7 +223,7 @@ public MetricsGossip Remove(Address node) } /// - /// Only the nodes that are in the set. + /// Only the nodes that are in the set. /// public MetricsGossip Filter(ImmutableHashSet
includeNodes) { @@ -355,7 +355,7 @@ public NodeMetrics(Address address, long timestamp, ImmutableHashSet met public NodeMetrics(Address address, long timestamp) : this(address, timestamp, ImmutableHashSet.Create()) { } /// - /// Return the metric that matches . Returns null if not found. + /// Return the metric that matches . Returns null if not found. /// public Metric Metric(string key) { @@ -478,7 +478,7 @@ public override bool Equals(object obj) #region Static methods /// - /// Creates a new instance if is valid, otherwise + /// Creates a new instance if is valid, otherwise /// returns null. Invalid numeric values are negative and NaN/Infinite. /// public static Metric Create(string name, double value, double? decayFactor = null) @@ -747,17 +747,17 @@ public PerformanceCounterMetricsCollector(ActorSystem system) : this(Cluster.Get private PerformanceCounter _systemLoadAverageCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total", true); private PerformanceCounter _systemAvailableMemory = new PerformanceCounter("Memory", "Available MBytes", true); - private static readonly bool IsRunningOnMono = Type.GetType("Mono.Runtime") != null; + private static readonly bool IsRunningOnMono = Type.GetType("Mono.Runtime") != null; - // Mono doesn't support Microsoft.VisualBasic, so need an alternative way of sampling this value - // see http://stackoverflow.com/questions/105031/how-do-you-get-total-amount-of-ram-the-computer-has - private PerformanceCounter _monoSystemMaxMemory = IsRunningOnMono - ? new PerformanceCounter("Mono Memory", "Total Physical Memory") - : null; + // Mono doesn't support Microsoft.VisualBasic, so need an alternative way of sampling this value + // see http://stackoverflow.com/questions/105031/how-do-you-get-total-amount-of-ram-the-computer-has + private PerformanceCounter _monoSystemMaxMemory = IsRunningOnMono + ? new PerformanceCounter("Mono Memory", "Total Physical Memory") + : null; - #endregion + #endregion public Address Address { get; private set; } @@ -817,20 +817,20 @@ public Metric SystemMemoryAvailable() ///
public Metric SystemMaxMemory() { - return Metric.Create(StandardMetrics.SystemMemoryMax, - IsRunningOnMono - ? _monoSystemMaxMemory.RawValue - : GetVbTotalPhysicalMemory()); + return Metric.Create(StandardMetrics.SystemMemoryMax, + IsRunningOnMono + ? _monoSystemMaxMemory.RawValue + : GetVbTotalPhysicalMemory()); } - double GetVbTotalPhysicalMemory() - { + double GetVbTotalPhysicalMemory() + { #if __MonoCS__ - throw new NotImplementedException(); + throw new NotImplementedException(); #else - return new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory; + return new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory; #endif - } + } #endregion diff --git a/src/core/Akka.Cluster/Gossip.cs b/src/core/Akka.Cluster/Gossip.cs index 8ec7109ac85..61c60214017 100644 --- a/src/core/Akka.Cluster/Gossip.cs +++ b/src/core/Akka.Cluster/Gossip.cs @@ -205,7 +205,6 @@ public Gossip Merge(Gossip that) return new Gossip(mergedMembers, new GossipOverview(mergedSeen, mergedReachability), mergedVClock); } - /// // First check that: // 1. we don't have any members that are unreachable, or // 2. all unreachable members in the set have status DOWN or EXITING @@ -213,7 +212,6 @@ public Gossip Merge(Gossip that) // When that is done we check that all members with a convergence // status is in the seen table and has the latest vector clock // version - /// public bool Convergence(UniqueAddress selfUniqueAddress) { var unreachable = _overview.Reachability.AllUnreachableOrTerminated diff --git a/src/core/Akka.Persistence/AtLeastOnceDelivery.cs b/src/core/Akka.Persistence/AtLeastOnceDelivery.cs index 476d51c1381..f1cea90c7c0 100644 --- a/src/core/Akka.Persistence/AtLeastOnceDelivery.cs +++ b/src/core/Akka.Persistence/AtLeastOnceDelivery.cs @@ -190,9 +190,9 @@ public void Init() public int UnconfirmedCount { get { return _unconfirmed.Count; } } /// - /// Send the message created with function to the + /// Send the message created with function to the /// actor. It will retry sending the message until the delivery is confirmed with . - /// Correlation between these two methods is performed by delivery id - parameter of . + /// Correlation between these two methods is performed by delivery id - parameter of . /// Usually it's passed inside the message to the destination, which replies with the message having the same id. /// /// During recovery this method won't send out any message, but it will be sent later until corresponding diff --git a/src/core/Akka.Remote/AckedDelivery.cs b/src/core/Akka.Remote/AckedDelivery.cs index cbb03620dad..b6febe0d06d 100644 --- a/src/core/Akka.Remote/AckedDelivery.cs +++ b/src/core/Akka.Remote/AckedDelivery.cs @@ -196,7 +196,7 @@ sealed class Ack /// Class representing an acknowledgement with select negative acknowledgements. /// /// Represents the highest sequence number received - /// Set of sequence numbers between the last delivered one and that has not been received. + /// Set of sequence numbers between the last delivered one and that has not been received. public Ack(SeqNo cumulativeAck, IEnumerable nacks) { Nacks = new SortedSet(nacks, SeqNo.Comparer); diff --git a/src/core/Akka.Remote/RemoteDeployer.cs b/src/core/Akka.Remote/RemoteDeployer.cs index 3e7566e4531..b972a325fb3 100644 --- a/src/core/Akka.Remote/RemoteDeployer.cs +++ b/src/core/Akka.Remote/RemoteDeployer.cs @@ -47,7 +47,7 @@ public override Deploy ParseConfig(string key, Config config) } /// - /// Used to determine if a given is an instance of . + /// Used to determine if a given is an instance of . /// private static Deploy CheckRemoteRouterConfig(Deploy deploy) { diff --git a/src/core/Akka.Remote/RemoteSystemDaemon.cs b/src/core/Akka.Remote/RemoteSystemDaemon.cs index dfcd9bf36b7..12b9843a71f 100644 --- a/src/core/Akka.Remote/RemoteSystemDaemon.cs +++ b/src/core/Akka.Remote/RemoteSystemDaemon.cs @@ -102,7 +102,8 @@ public RemoteSystemDaemon(ActorSystemImpl system, ActorPath path, IInternalActor /// /// Called when [receive]. /// - /// The message. + /// The message that was received. + /// The actor that sent the message. protected void OnReceive(object message, IActorRef sender) { //note: RemoteDaemon does not handle ActorSelection messages - those are handled directly by the RemoteActorRefProvider. diff --git a/src/core/Akka.Remote/RemoteTransport.cs b/src/core/Akka.Remote/RemoteTransport.cs index d519d85f0d3..742f5036248 100644 --- a/src/core/Akka.Remote/RemoteTransport.cs +++ b/src/core/Akka.Remote/RemoteTransport.cs @@ -68,7 +68,7 @@ protected RemoteTransport(ExtendedActorSystem system, RemoteActorRefProvider pro public abstract Task Shutdown(); /// - /// Sends the given message to the recipient, supplying if any. + /// Sends the given message to the recipient, supplying if any. /// public abstract void Send(object message, IActorRef sender, RemoteActorRef recipient); diff --git a/src/core/Akka.Remote/Transport/TestTransport.cs b/src/core/Akka.Remote/Transport/TestTransport.cs index e0ba4e67577..20caaaa93a0 100644 --- a/src/core/Akka.Remote/Transport/TestTransport.cs +++ b/src/core/Akka.Remote/Transport/TestTransport.cs @@ -333,7 +333,7 @@ public Func> CurrentBehavior /// /// Changes the current behavior to the provided one /// - /// Function that takes a parameter type and returns a Task + /// Function that takes a parameter type and returns a Task. public void Push(Func> behavior) { _behaviorStack.Push(behavior); @@ -484,7 +484,7 @@ public bool TransportsReady(params Address[] addresses) ///
/// Ordered pair of addresses representing an association. First element must be the address of the initiator. /// A pair of listeners that will be responsible for handling the events of the two endpoints - /// of the association. Elements in the Tuple must be in the same order as the addresses in . + /// of the association. Elements in the Tuple must be in the same order as the addresses in . public void RegisterListenerPair(Tuple key, Tuple listeners) { diff --git a/src/core/Akka.Remote/Transport/Transport.cs b/src/core/Akka.Remote/Transport/Transport.cs index c267dd3c732..62871f8a0b0 100644 --- a/src/core/Akka.Remote/Transport/Transport.cs +++ b/src/core/Akka.Remote/Transport/Transport.cs @@ -245,7 +245,7 @@ protected AssociationHandle(Address localAddress, Address remoteAddress) public TaskCompletionSource ReadHandlerSource { get; protected set; } /// - /// Asynchronously sends the specified to the remote endpoint. This method's implementation MUST be thread-safe + /// Asynchronously sends the specified to the remote endpoint. This method's implementation MUST be thread-safe /// as it might be called from different threads. This method MUST NOT block. /// /// Writes guarantee ordering of messages, but not their reception. The call to write returns with a boolean indicating if the diff --git a/src/core/Akka.TestKit/TestKitBase_Receive.cs b/src/core/Akka.TestKit/TestKitBase_Receive.cs index b80c827b15d..bd71e859b9c 100644 --- a/src/core/Akka.TestKit/TestKitBase_Receive.cs +++ b/src/core/Akka.TestKit/TestKitBase_Receive.cs @@ -246,7 +246,7 @@ public IReadOnlyList ReceiveWhile(Func filter, TimeSpan? max = /// /// Receive a series of messages. - /// It will continue to receive messages until the predicate returns false or the idle + /// It will continue to receive messages until the predicate returns false or the idle /// timeout is met (disabled by default) or the overall /// maximum duration is elapsed or expected messages count is reached. /// If a message that isn't of type the parameter diff --git a/src/core/Akka.TestKit/TestKitBase_Within.cs b/src/core/Akka.TestKit/TestKitBase_Within.cs index d9f82ce0633..88051f8ac82 100644 --- a/src/core/Akka.TestKit/TestKitBase_Within.cs +++ b/src/core/Akka.TestKit/TestKitBase_Within.cs @@ -15,7 +15,7 @@ public abstract partial class TestKitBase { /// - /// Execute code block while bounding its execution time between 0 seconds and . + /// Execute code block while bounding its execution time between 0 seconds and . /// `within` blocks may be nested. All methods in this class which take maximum wait times /// are available in a version which implicitly uses the remaining time governed by /// the innermost enclosing `within` block. @@ -27,7 +27,7 @@ public void Within(TimeSpan max, Action action) } /// - /// Execute code block while bounding its execution time between and . + /// Execute code block while bounding its execution time between and . /// `within` blocks may be nested. All methods in this class which take maximum wait times /// are available in a version which implicitly uses the remaining time governed by /// the innermost enclosing `within` block. @@ -40,7 +40,7 @@ public void Within(TimeSpan min, TimeSpan max, Action action, string hint = null /// - /// Execute code block while bounding its execution time between 0 seconds and . + /// Execute code block while bounding its execution time between 0 seconds and . /// `within` blocks may be nested. All methods in this class which take maximum wait times /// are available in a version which implicitly uses the remaining time governed by /// the innermost enclosing `within` block. @@ -52,7 +52,7 @@ public T Within(TimeSpan max, Func function) } /// - /// Execute code block while bounding its execution time between and . + /// Execute code block while bounding its execution time between and . /// `within` blocks may be nested. All methods in this class which take maximum wait times /// are available in a version which implicitly uses the remaining time governed by /// the innermost enclosing `within` block. diff --git a/src/core/Akka/Actor/ActorProducerPipeline.cs b/src/core/Akka/Actor/ActorProducerPipeline.cs index 6849006b9e7..5ffcdff1049 100644 --- a/src/core/Akka/Actor/ActorProducerPipeline.cs +++ b/src/core/Akka/Actor/ActorProducerPipeline.cs @@ -65,7 +65,7 @@ public virtual void BeforeIncarnated(ActorBase actor, IActorContext context) { } public abstract class ActorProducerPluginBase : IActorProducerPlugin where TActor : ActorBase { /// - /// By default derivatives of this plugin will be applied to all actors inheriting from actor generic type. + /// By default derivatives of this plugin will be applied to all actors inheriting from actor generic type. /// public virtual bool CanBeAppliedTo(Type actorType) { diff --git a/src/core/Akka/Actor/FSM.cs b/src/core/Akka/Actor/FSM.cs index 3d5d233d95d..6bd7dbe37fe 100644 --- a/src/core/Akka/Actor/FSM.cs +++ b/src/core/Akka/Actor/FSM.cs @@ -729,8 +729,8 @@ private void HandleTransition(TState previous, TState next) /// See http://scalachina.com/api/scala/PartialFunction.html /// /// The original to be called - /// The to be called if returns null - /// A which combines both the results of and + /// The to be called if returns null + /// A which combines both the results of and private static StateFunction OrElse(StateFunction original, StateFunction fallback) { StateFunction chained = delegate(Event @event) diff --git a/src/core/Akka/Actor/PipeToSupport.cs b/src/core/Akka/Actor/PipeToSupport.cs index 95eea539e04..621c1d3f679 100644 --- a/src/core/Akka/Actor/PipeToSupport.cs +++ b/src/core/Akka/Actor/PipeToSupport.cs @@ -16,7 +16,7 @@ namespace Akka.Actor public static class PipeToSupport { /// - /// Pipes the output of a Task directly to the 's mailbox once + /// Pipes the output of a Task directly to the 's mailbox once /// the task completes /// public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActorRef sender = null) @@ -32,8 +32,8 @@ public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActor } /// - /// Pipes the output of a Task directly to the 's mailbox once - /// the task completes. As this task has no result, only exceptions will be piped to the + /// Pipes the output of a Task directly to the 's mailbox once + /// the task completes. As this task has no result, only exceptions will be piped to the /// public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActorRef sender = null) { diff --git a/src/core/Akka/Actor/ReceiveActor.cs b/src/core/Akka/Actor/ReceiveActor.cs index c2181a73d00..bdcc0a3ed85 100644 --- a/src/core/Akka/Actor/ReceiveActor.cs +++ b/src/core/Akka/Actor/ReceiveActor.cs @@ -122,7 +122,7 @@ protected void Receive(Func handler) /// /// Registers a handler for incoming messages of the specified type . - /// If !=null then it must return true before a message is passed to . + /// If !=null then it must return true before a message is passed to . /// This method may only be called when constructing the actor or from or . /// Note that handlers registered prior to this may have handled the message already. /// In that case, this handler will not be invoked. @@ -138,8 +138,8 @@ protected void Receive(Action handler, Predicate shouldHandle = null) /// /// Registers a handler for incoming messages of the specified type . - /// If !=null then it must return true before a message is passed to . - /// This method may only be called when constructing the actor or from or . + /// If !=null then it must return true before a message is passed to . + /// This method may only be called when constructing the actor or from or . /// Note that handlers registered prior to this may have handled the message already. /// In that case, this handler will not be invoked. /// @@ -153,14 +153,14 @@ protected void Receive(Predicate shouldHandle, Action handler) /// - /// Registers a handler for incoming messages of the specified . - /// If !=null then it must return true before a message is passed to . - /// This method may only be called when constructing the actor or from or . + /// Registers a handler for incoming messages of the specified . + /// If !=null then it must return true before a message is passed to . + /// This method may only be called when constructing the actor or from or . /// Note that handlers registered prior to this may have handled the message already. /// In that case, this handler will not be invoked. /// /// The type of the message - /// The message handler that is invoked for incoming messages of the specified + /// The message handler that is invoked for incoming messages of the specified /// When not null it is used to determine if the message matches. protected void Receive(Type messageType, Action handler, Predicate shouldHandle = null) { @@ -170,14 +170,14 @@ protected void Receive(Type messageType, Action handler, Predicate - /// Registers a handler for incoming messages of the specified . - /// If !=null then it must return true before a message is passed to . - /// This method may only be called when constructing the actor or from or . + /// Registers a handler for incoming messages of the specified . + /// If !=null then it must return true before a message is passed to . + /// This method may only be called when constructing the actor or from or . /// Note that handlers registered prior to this may have handled the message already. /// In that case, this handler will not be invoked. /// /// The type of the message - /// The message handler that is invoked for incoming messages of the specified + /// The message handler that is invoked for incoming messages of the specified /// When not null it is used to determine if the message matches. protected void Receive(Type messageType, Predicate shouldHandle, Action handler) { @@ -192,7 +192,7 @@ protected void Receive(Type messageType, Predicate shouldHandle, Action< /// Registers a handler for incoming messages of the specified type . /// The handler should return true if it has handled the message. /// If the handler returns true no more handlers will be tried; otherwise the next registered handler will be tried. - /// This method may only be called when constructing the actor or from or . + /// This method may only be called when constructing the actor or from or . /// Note that handlers registered prior to this may have handled the message already. /// In that case, this handler will not be invoked. /// @@ -207,16 +207,16 @@ protected void Receive(Func handler) } /// - /// Registers a handler for incoming messages of the specified . + /// Registers a handler for incoming messages of the specified . /// The handler should return true if it has handled the message. /// If the handler returns true no more handlers will be tried; otherwise the next registered handler will be tried. - /// This method may only be called when constructing the actor or from or . + /// This method may only be called when constructing the actor or from or . /// Note that handlers registered prior to this may have handled the message already. /// In that case, this handler will not be invoked. /// /// The type of the message /// The message handler that is invoked for incoming messages of the - /// specified type . It should return trueif it handled/matched + /// specified type . It should return trueif it handled/matched /// the message; false otherwise. protected void Receive(Type messageType, Func handler) { @@ -230,7 +230,7 @@ protected void Receive(Type messageType, Func handler) /// /// Registers a handler for incoming messages of any type. - /// This method may only be called when constructing the actor or from or . + /// This method may only be called when constructing the actor or from or . /// Note that handlers registered prior to this may have handled the message already. /// In that case, this handler will not be invoked. /// diff --git a/src/core/Akka/Actor/SupervisorStrategy.cs b/src/core/Akka/Actor/SupervisorStrategy.cs index 5cf0c803781..cd298fda024 100644 --- a/src/core/Akka/Actor/SupervisorStrategy.cs +++ b/src/core/Akka/Actor/SupervisorStrategy.cs @@ -78,7 +78,6 @@ public bool HandleFailure(ActorCell actorCell, Exception cause, ChildRestartStat /// thrown. It will be restarted for other `Exception` types. /// The error is escalated if it's a `Exception`, i.e. `Error`. /// - /// The exception. /// Directive. public static IDecider DefaultDecider = Decider.From(Directive.Restart, Directive.Stop.When(), diff --git a/src/core/Akka/Dispatch/Dispatchers.cs b/src/core/Akka/Dispatch/Dispatchers.cs index bde518643fc..39626c5044b 100644 --- a/src/core/Akka/Dispatch/Dispatchers.cs +++ b/src/core/Akka/Dispatch/Dispatchers.cs @@ -226,7 +226,7 @@ private MessageDispatcherConfigurator LookupConfigurator(string id) /// /// The provided configuration section. /// An instance of the , if valid. - /// if the `id` property is missing from + /// if the `id` property is missing from /// thrown if the dispatcher path or type cannot be resolved. internal MessageDispatcher From(Config cfg) { diff --git a/src/core/Akka/Dispatch/MessageQueues/DequeWrapperMessageQueue.cs b/src/core/Akka/Dispatch/MessageQueues/DequeWrapperMessageQueue.cs index 47fa432a328..2bc7caf3732 100644 --- a/src/core/Akka/Dispatch/MessageQueues/DequeWrapperMessageQueue.cs +++ b/src/core/Akka/Dispatch/MessageQueues/DequeWrapperMessageQueue.cs @@ -20,7 +20,7 @@ public class DequeWrapperMessageQueue : IMessageQueue, IDequeBasedMessageQueueSe private readonly Stack _prependBuffer = new Stack(); private readonly IMessageQueue _messageQueue; /// - /// Takes another as an argument - wraps + /// Takes another as an argument - wraps /// in order to provide it with prepend () semantics. /// /// diff --git a/src/core/Akka/Event/LoggingAdapterBase.cs b/src/core/Akka/Event/LoggingAdapterBase.cs index 9f29f0f6f94..025c9c282c7 100644 --- a/src/core/Akka/Event/LoggingAdapterBase.cs +++ b/src/core/Akka/Event/LoggingAdapterBase.cs @@ -31,15 +31,21 @@ public abstract class LoggingAdapterBase : ILoggingAdapter /// Creates an instance of the LoggingAdapterBase. /// /// The log message formatter used by this logging adapter. - /// + /// This exception is thrown when the supplied message formatter is null. protected LoggingAdapterBase(ILogMessageFormatter logMessageFormatter) { if(logMessageFormatter == null) - throw new ArgumentException("logMessageFormatter"); + throw new ArgumentNullException("logMessageFormatter", "The message formatter must not be null."); _logMessageFormatter = logMessageFormatter; } - + + /// + /// Checks the logging adapter to see if the supplied is enabled. + /// + /// The log level to check if it is enabled in this logging adapter. + /// true if the supplied log level is enabled; otherwise false + /// This exception is thrown when the supplied log level is unknown. public bool IsEnabled(LogLevel logLevel) { switch(logLevel) @@ -62,7 +68,7 @@ public bool IsEnabled(LogLevel logLevel) /// /// The log level of the log event. /// The log message of the log event. - /// + /// This exception is thrown when the supplied log level is unknown. protected void NotifyLog(LogLevel logLevel, object message) { switch(logLevel) diff --git a/src/core/Akka/Pattern/CircuitBreaker.cs b/src/core/Akka/Pattern/CircuitBreaker.cs index f6cd03b0bce..bf5b0b85113 100644 --- a/src/core/Akka/Pattern/CircuitBreaker.cs +++ b/src/core/Akka/Pattern/CircuitBreaker.cs @@ -162,7 +162,7 @@ public void WithSyncCircuitBreaker( Action body ) /// /// Wraps invocations of asynchronous calls that need to be protected - /// If this does not complete within the time allotted, it should return default() + /// If this does not complete within the time allotted, it should return default() /// /// /// Await.result( @@ -173,7 +173,7 @@ public void WithSyncCircuitBreaker( Action body ) /// /// /// - /// or default() + /// or default() public T WithSyncCircuitBreaker( Func body ) { var cbTask = WithCircuitBreaker( () => Task.Factory.StartNew( body ) ); diff --git a/src/core/Akka/Util/AtomicBoolean.cs b/src/core/Akka/Util/AtomicBoolean.cs index 082586b7029..90c356d0176 100644 --- a/src/core/Akka/Util/AtomicBoolean.cs +++ b/src/core/Akka/Util/AtomicBoolean.cs @@ -23,7 +23,7 @@ internal class AtomicBoolean private int _value; /// - /// Sets the initial value of this to . + /// Sets the initial value of this to . /// public AtomicBoolean(bool initialValue = false) { @@ -47,10 +47,10 @@ public bool Value } /// - /// If equals , then set the Value to - /// . + /// If equals , then set the Value to + /// . /// - /// true if was set + /// true if was set public bool CompareAndSet(bool expected, bool newValue) { var expectedInt = expected ? _trueValue : _falseValue; diff --git a/src/core/Akka/Util/AtomicReference.cs b/src/core/Akka/Util/AtomicReference.cs index 3c4cd76e346..f0ea196e30b 100644 --- a/src/core/Akka/Util/AtomicReference.cs +++ b/src/core/Akka/Util/AtomicReference.cs @@ -19,7 +19,7 @@ namespace Akka.Util public class AtomicReference { /// - /// Sets the initial value of this to . + /// Sets the initial value of this to . /// public AtomicReference(T originalValue) { @@ -56,10 +56,10 @@ public T Value } /// - /// If equals , then set the Value to - /// . + /// If equals , then set the Value to + /// . /// - /// true if was set + /// true if was set public bool CompareAndSet(T expected, T newValue) { //special handling for null values @@ -84,7 +84,7 @@ public bool CompareAndSet(T expected, T newValue) #region Conversion operators /// - /// Implicit conversion operator = automatically casts the to an instance of + /// Implicit conversion operator = automatically casts the to an instance of . /// public static implicit operator T(AtomicReference aRef) { diff --git a/src/core/Akka/Util/ContinuousEnumerator.cs b/src/core/Akka/Util/ContinuousEnumerator.cs index 108bf383c2a..1a2d89e2476 100644 --- a/src/core/Akka/Util/ContinuousEnumerator.cs +++ b/src/core/Akka/Util/ContinuousEnumerator.cs @@ -63,9 +63,9 @@ object IEnumerator.Current internal static class ContinuousEnumeratorExtensions { /// - /// Provides a instance for . + /// Provides a instance for . /// - /// Internally, it just wraps 's internal iterator with circular iteration behavior. + /// Internally, it just wraps 's internal iterator with circular iteration behavior. /// public static ContinuousEnumerator GetContinuousEnumerator(this IEnumerable collection) { diff --git a/src/core/Akka/Util/Internal/ArrayExtensions.cs b/src/core/Akka/Util/Internal/ArrayExtensions.cs index 008fa5b61bf..861ec72321f 100644 --- a/src/core/Akka/Util/Internal/ArrayExtensions.cs +++ b/src/core/Akka/Util/Internal/ArrayExtensions.cs @@ -80,17 +80,19 @@ public static Dictionary ZipWithIndex(this IEnumerable collection) /// The array of items to slice /// The starting position to begin the slice /// The number of items to take - /// A slice of size beginning from position in . + /// A slice of size beginning from position in . internal static IEnumerable Slice(this IEnumerable items, int startIndex, int count) { return items.Skip(startIndex).Take(count); } /// - /// Select all the items in this array beginning with and up until the end of the array. + /// Select all the items in this array beginning with and up until the end of the array. /// - /// If is not found in the array, From will return an empty set. - /// If is found at the end of the array, From will return the entire original array. + /// + /// If is not found in the array, From will return an empty set. + /// If is found at the end of the array, From will return the entire original array. + /// /// internal static IEnumerable From(this IEnumerable items, T startingItem) { @@ -103,10 +105,11 @@ internal static IEnumerable From(this IEnumerable items, T startingItem } /// - /// Select all the items in this array from the beginning until (but not including) - /// - /// If is not found in the array, Until will select all items. - /// If is the first item in the array, an empty array will be returned. + /// Select all the items in this array from the beginning until (but not including) + /// + /// If is not found in the array, Until will select all items. + /// If is the first item in the array, an empty array will be returned. + /// /// internal static IEnumerable Until(this IEnumerable items, T startingItem) { diff --git a/src/core/Akka/Util/MatchHandler/PartialAction.cs b/src/core/Akka/Util/MatchHandler/PartialAction.cs index f69d1f406d5..9d1a4554845 100644 --- a/src/core/Akka/Util/MatchHandler/PartialAction.cs +++ b/src/core/Akka/Util/MatchHandler/PartialAction.cs @@ -8,11 +8,11 @@ namespace Akka.Tools.MatchHandler { /// - /// An action that returns true if the was handled. + /// An action that returns true if the was handled. /// /// The type of the argument /// The argument. - /// Returns true if the was handled + /// Returns true if the was handled public delegate bool PartialAction(T item); } diff --git a/src/core/Akka/Util/MurmurHash.cs b/src/core/Akka/Util/MurmurHash.cs index c1deb34f86f..f6b815004b7 100644 --- a/src/core/Akka/Util/MurmurHash.cs +++ b/src/core/Akka/Util/MurmurHash.cs @@ -125,7 +125,7 @@ public static uint FinalizeHash(uint hash) #region Internal 32-bit hashing helpers /// - /// Rotate a 32-bit unsigned integer to the left by bits + /// Rotate a 32-bit unsigned integer to the left by bits /// /// Original value /// The shift value @@ -136,7 +136,7 @@ private static uint RotateLeft32(uint original, int shift) } /// - /// Rotate a 64-bit unsigned integer to the left by bits + /// Rotate a 64-bit unsigned integer to the left by bits /// /// Original value /// The shift value From a0909e93f1c4ad94e3ec4cee2ad133f3de2829e2 Mon Sep 17 00:00:00 2001 From: Bartosz Sypytkowski Date: Mon, 5 Oct 2015 19:33:20 +0200 Subject: [PATCH 050/105] upgraded and fixed Paket references fixed xunit dependency missmatch causing runner inconclusive results added missing Wire dependency added missing System.Collections.Immutable deps multi node test runner missing references changed Akka.MultiNodeTestRunner config multinode test runner deps --- paket.dependencies | 8 +- paket.lock | 249 +++++++++++++++--- src/benchmark/PersistenceBenchmark/App.config | 4 - src/benchmark/PingPong/App.config | 4 - .../Akka.DI.TestKit/Akka.DI.TestKit.csproj | 79 +----- .../Akka.DI.Unity.Tests.csproj | 4 +- .../Akka.DI.Unity/Akka.DI.Unity.csproj | 4 +- .../Akka.TestKit.Xunit2.csproj | 116 +++++--- .../Akka.TestKit.Xunit2/paket.references | 3 +- .../Akka.Cluster.Tests.MultiNode.csproj | 118 ++++++--- .../paket.references | 6 +- .../Akka.Cluster.Tests.csproj | 118 ++++++--- src/core/Akka.Cluster.Tests/paket.references | 5 +- src/core/Akka.Cluster/Akka.Cluster.csproj | 2 +- src/core/Akka.Cluster/paket.references | 2 +- .../Akka.FSharp.Tests.fsproj | 117 +++++--- src/core/Akka.FSharp.Tests/app.config | 32 --- src/core/Akka.FSharp.Tests/paket.references | 4 +- src/core/Akka.FSharp/FsApi.fs | 6 +- src/core/Akka.FSharp/app.config | 4 - ...ka.MultiNodeTestRunner.Shared.Tests.csproj | 116 +++++--- .../paket.references | 3 +- .../Akka.MultiNodeTestRunner.csproj | 79 ++++-- src/core/Akka.MultiNodeTestRunner/App.config | 36 --- src/core/Akka.MultiNodeTestRunner/Program.cs | 2 +- .../Akka.MultiNodeTestRunner/paket.references | 7 +- .../Akka.NodeTestRunner.csproj | 53 +--- src/core/Akka.NodeTestRunner/App.config | 4 - src/core/Akka.NodeTestRunner/Program.cs | 2 +- src/core/Akka.NodeTestRunner/paket.references | 1 + src/core/Akka.Persistence.FSharp/app.config | 4 - .../Akka.Persistence.TestKit.Tests.csproj | 116 +++++--- .../paket.references | 3 +- .../Akka.Persistence.TestKit.csproj | 116 +++++--- .../Akka.Persistence.TestKit/paket.references | 3 +- .../Akka.Persistence.Tests.csproj | 116 +++++--- .../Akka.Persistence.Tests/paket.references | 3 +- .../Akka.Remote.TestKit.Tests.csproj | 118 ++++++--- .../paket.references | 5 +- .../Akka.Remote.TestKit.csproj | 138 ++++++---- src/core/Akka.Remote.TestKit/paket.references | 5 +- .../Akka.Remote.Tests.MultiNode.csproj | 130 ++++++--- .../paket.references | 3 +- .../Akka.Remote.Tests.csproj | 116 +++++--- src/core/Akka.Remote.Tests/app.config | 24 -- src/core/Akka.Remote.Tests/paket.references | 3 +- src/core/Akka.Remote/app.config | 4 - .../Akka.TestKit.Tests.csproj | 116 +++++--- src/core/Akka.TestKit.Tests/paket.references | 3 +- src/core/Akka.TestKit/Akka.TestKit.csproj | 2 - .../Akka.Tests.Shared.Internals.csproj | 116 +++++--- .../paket.references | 3 +- src/core/Akka.Tests/Akka.Tests.csproj | 169 +++++++----- src/core/Akka.Tests/App.config | 32 --- src/core/Akka.Tests/TestUtils/Comparable.cs | 4 +- src/core/Akka.Tests/paket.references | 6 +- src/core/Akka/Akka.csproj | 11 +- src/core/Akka/paket.references | 3 +- src/examples/Chat/ChatClient/App.config | 4 - .../Chat/ChatMessages/ChatMessages.csproj | 108 +------- .../Chat/ChatMessages/paket.references | 1 - src/examples/Chat/ChatServer/App.config | 4 - .../Samples.Cluster.Transformation/App.config | 4 - .../Samples.Cluster.Transformation.csproj | 2 +- .../paket.references | 2 +- .../App.config | 4 - ...mples.Cluster.ConsistentHashRouting.csproj | 2 +- .../paket.references | 2 +- .../Cluster/Samples.Cluster.Simple/App.config | 4 - .../Samples.Cluster.Simple.csproj | 2 +- .../Samples.Cluster.Simple/paket.references | 2 +- src/examples/FSharp.Api/App.config | 4 - src/examples/FSharp.Api/FSharp.Api.fsproj | 7 + src/examples/FSharp.Api/paket.references | 3 +- src/examples/FSharp.Deploy.Local/App.config | 4 - src/examples/FSharp.Deploy.Remote/App.config | 4 - src/examples/FaultTolerance/App.config | 4 - .../HelloWorld/FSharp.HelloAkka/App.config | 4 - src/examples/HelloWorld/HelloAkka/App.config | 4 - .../PersistenceExample.FsApi/App.config | 4 - src/examples/PersistenceExample/App.config | 4 - src/examples/RemoteDeploy/System1/App.config | 4 - src/examples/RemoteDeploy/System2/App.config | 4 - src/examples/Routing/App.config | 4 - .../SymbolLookup/Actors/TickerActors.cs | 3 +- src/examples/Stocks/SymbolLookup/App.config | 4 - .../Stocks/SymbolLookup/SymbolLookup.csproj | 51 +++- .../Stocks/SymbolLookup/paket.references | 4 +- src/examples/TcpEchoService.Server/App.config | 4 - src/examples/TimeServer/TimeClient/App.config | 4 - src/examples/TimeServer/TimeServer/App.config | 4 - 91 files changed, 1712 insertions(+), 1117 deletions(-) diff --git a/paket.dependencies b/paket.dependencies index ff0268f8c9f..9cb63a581b3 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -3,13 +3,12 @@ source https://www.nuget.org/api/v2/ nuget Autofac nuget Castle.Windsor nuget faker-csharp -nuget fastJSON -nuget FsPickler +nuget FsPickler >= 1.2 nuget FSPowerPack.Linq.Community nuget Google.ProtocolBuffers nuget Google.ProtocolBuffersLite nuget Helios -nuget Microsoft.Bcl.Immutable +nuget System.Collections.Immutable nuget Newtonsoft.Json nuget Ninject nuget NLog @@ -18,6 +17,7 @@ nuget Serilog nuget slf4net nuget structuremap nuget Unity +nuget Wire group Test source https://www.nuget.org/api/v2/ @@ -25,6 +25,8 @@ nuget NUnit nuget NUnit.Runners nuget FluentAssertions ~> 3 nuget FsCheck.Xunit +nuget xunit.core >= 2.1 +nuget xunit.assert nuget xunit.extensions nuget xunit.runner.console nuget xunit.runner.utility diff --git a/paket.lock b/paket.lock index 61e774091b8..03211650f75 100644 --- a/paket.lock +++ b/paket.lock @@ -1,70 +1,255 @@ NUGET - remote: https://www.nuget.org/api/v2 + remote: https://nuget.org/api/v2 specs: Autofac (3.5.2) Castle.Core (3.3.3) Castle.Windsor (3.3.0) Castle.Core (>= 3.3.0) - CommonServiceLocator (1.3) - framework: monoandroid, winv4.5 + CommonServiceLocator (1.3.0) - framework: monoandroid, winv4.5 faker-csharp (1.2.0) - fastJSON (2.1.14.0) FsPickler (1.4.0) - FSPowerPack.Core.Community (3.0.0.0) - FSPowerPack.Linq.Community (3.0.0.0) + FSPowerPack.Core.Community (3.0.0) + FSPowerPack.Linq.Community (3.0.0) FSPowerPack.Core.Community Google.ProtocolBuffers (2.4.1.555) Google.ProtocolBuffersLite (2.4.1.555) Helios (1.4.1) - Microsoft.Bcl.Immutable (1.0.34) Newtonsoft.Json (7.0.1) - Ninject (3.2.2.0) - NLog (4.1.1) + Ninject (3.2.2) + NLog (4.1.2) qdfeed (1.1.0) Serilog (1.5.11) slf4net (0.1.32.1) structuremap (3.1.6.186) - Unity (3.5.1404.0) - CommonServiceLocator (>= 1.2.0) - framework: monoandroid, winv4.5 + System.Collections (4.0.10) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 + System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 + System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Collections.Immutable (1.1.37) + System.Collections (>= 4.0.0) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 + System.Globalization (>= 4.0.0) - framework: dnxcore50 + System.Linq (>= 4.0.0) - framework: dnxcore50 + System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 + System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Diagnostics.Debug (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Globalization (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.IO (4.0.10) - framework: dnxcore50 + System.Globalization (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Text.Encoding (>= 4.0.0) - framework: dnxcore50 + System.Text.Encoding (>= 4.0.10) - framework: dnxcore50 + System.Text.Encoding.Extensions (>= 4.0.0) - framework: dnxcore50 + System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + System.Linq (4.0.0) - framework: dnxcore50 + System.Collections (>= 4.0.10) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.10) - framework: dnxcore50 + System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Runtime.Extensions (>= 4.0.10) - framework: dnxcore50 + System.Private.Uri (4.0.0) - framework: dnxcore50 + System.Reflection (4.0.10) - framework: dnxcore50 + System.IO (>= 4.0.0) - framework: dnxcore50 + System.Reflection.Primitives (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Reflection.Primitives (4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Resources.ResourceManager (4.0.0) - framework: dnxcore50 + System.Globalization (>= 4.0.0) - framework: dnxcore50 + System.Reflection (>= 4.0.0) - framework: dnxcore50 + System.Reflection (>= 4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Runtime (4.0.20) - framework: dnxcore50 + System.Private.Uri (>= 4.0.0) - framework: dnxcore50 + System.Runtime.Extensions (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Text.Encoding (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Text.Encoding.Extensions (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Text.Encoding (>= 4.0.10) - framework: dnxcore50 + System.Threading (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + System.Threading.Tasks (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + Unity (4.0.0) + CommonServiceLocator (>= 1.3.0) - framework: monoandroid, winv4.5, wpv8.1 + Wire (0.0.4) GROUP Build NUGET - remote: https://www.nuget.org/api/v2 + remote: https://nuget.org/api/v2 specs: - FAKE (4.4.2) + FAKE (4.4.6) NuGet.CommandLine (2.8.6) SourceLink.Fake (1.1.0) GROUP Legacy NUGET - remote: https://www.nuget.org/api/v2 + remote: https://nuget.org/api/v2 specs: xunit (1.9.2) GROUP Test NUGET - remote: https://www.nuget.org/api/v2 + remote: https://nuget.org/api/v2 specs: FluentAssertions (3.5.0) - FsCheck (2.0.7) + FsCheck (2.1.0) FSharp.Core (>= 3.1.2.5) - FsCheck.Xunit (2.0.7) - FsCheck (>= 2.0.7) - xunit (>= 1.9.2) + FsCheck.Xunit (2.1.0) + FsCheck (>= 2.1.0) + xunit.extensibility.execution (>= 2.1.0) FSharp.Core (4.0.0.1) NUnit (2.6.4) NUnit.Runners (2.6.4) - xunit (2.0.0) - xunit.assert (2.0.0) - xunit.core (2.0.0) - xunit.abstractions (2.0.0) - xunit.assert (2.0.0) - xunit.core (2.0.0) - xunit.extensibility.core (2.0.0) - xunit.extensibility.core (2.0.0) - xunit.abstractions (2.0.0) - xunit.extensions (2.0.0) - xunit (2.0.0) - xunit.runner.console (2.0.0) - xunit.runner.utility (2.0.0) + System.Collections (4.0.10) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 + System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 + System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Diagnostics.Contracts (4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Diagnostics.Debug (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Globalization (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.IO (4.0.10) - framework: dnxcore50 + System.Globalization (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Text.Encoding (>= 4.0.0) - framework: dnxcore50 + System.Text.Encoding (>= 4.0.10) - framework: dnxcore50 + System.Text.Encoding.Extensions (>= 4.0.0) - framework: dnxcore50 + System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + System.Linq (4.0.0) - framework: dnxcore50 + System.Collections (>= 4.0.10) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.10) - framework: dnxcore50 + System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Runtime.Extensions (>= 4.0.10) - framework: dnxcore50 + System.ObjectModel (4.0.10) - framework: dnxcore50 + System.Collections (>= 4.0.10) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.10) - framework: dnxcore50 + System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Threading (>= 4.0.10) - framework: dnxcore50 + System.Private.Uri (4.0.0) - framework: dnxcore50 + System.Reflection (4.0.10) - framework: dnxcore50 + System.IO (>= 4.0.0) - framework: dnxcore50 + System.Reflection.Primitives (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Reflection.Extensions (4.0.0) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.10) - framework: dnxcore50 + System.Reflection (>= 4.0.0) - framework: dnxcore50 + System.Reflection (>= 4.0.10) - framework: dnxcore50 + System.Reflection.Primitives (>= 4.0.0) - framework: dnxcore50 + System.Reflection.TypeExtensions (>= 4.0.0) - framework: dnxcore50 + System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Runtime.Extensions (>= 4.0.10) - framework: dnxcore50 + System.Reflection.Primitives (4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Reflection.TypeExtensions (4.0.0) - framework: dnxcore50 + System.Diagnostics.Contracts (>= 4.0.0) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.10) - framework: dnxcore50 + System.Linq (>= 4.0.0) - framework: dnxcore50 + System.Reflection (>= 4.0.0) - framework: dnxcore50 + System.Reflection (>= 4.0.10) - framework: dnxcore50 + System.Reflection.Primitives (>= 4.0.0) - framework: dnxcore50 + System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Runtime.Extensions (>= 4.0.10) - framework: dnxcore50 + System.Resources.ResourceManager (4.0.0) - framework: dnxcore50 + System.Globalization (>= 4.0.0) - framework: dnxcore50 + System.Reflection (>= 4.0.0) - framework: dnxcore50 + System.Reflection (>= 4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Runtime (4.0.20) - framework: dnxcore50 + System.Private.Uri (>= 4.0.0) - framework: dnxcore50 + System.Runtime.Extensions (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Text.Encoding (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Text.Encoding.Extensions (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Text.Encoding (>= 4.0.10) - framework: dnxcore50 + System.Text.RegularExpressions (4.0.10) - framework: dnxcore50 + System.Collections (>= 4.0.10) - framework: dnxcore50 + System.Globalization (>= 4.0.10) - framework: dnxcore50 + System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Runtime.Extensions (>= 4.0.10) - framework: dnxcore50 + System.Threading (>= 4.0.10) - framework: dnxcore50 + System.Threading (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + System.Threading.Tasks (4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + xunit (1.9.2) + xunit.abstractions (2.0.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 + xunit.assert (2.1.0) + System.Collections (>= 4.0.0) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 + System.Globalization (>= 4.0.0) - framework: dnxcore50 + System.Linq (>= 4.0.0) - framework: dnxcore50 + System.ObjectModel (>= 4.0.0) - framework: dnxcore50 + System.Reflection (>= 4.0.0) - framework: dnxcore50 + System.Reflection.Extensions (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 + System.Text.RegularExpressions (>= 4.0.0) - framework: dnxcore50 + System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + xunit.core (2.1.0) + System.Collections (>= 4.0.0) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 + System.Globalization (>= 4.0.0) - framework: dnxcore50 + System.Linq (>= 4.0.0) - framework: dnxcore50 + System.Reflection (>= 4.0.0) - framework: dnxcore50 + System.Reflection.Extensions (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 + System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + xunit.abstractions (>= 2.0.0) - framework: dnxcore50 + xunit.extensibility.core (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.1, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 + xunit.extensibility.execution (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.1, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 + xunit.extensibility.core (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 xunit.abstractions (2.0.0) - xunit.runner.visualstudio (2.0.1) + xunit.extensibility.execution (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 + xunit.extensibility.core (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.1, wpv8.0, >= net45 + xunit.extensions (1.9.2) + xunit (1.9.2) + xunit.runner.console (2.1.0) + xunit.runner.utility (2.1.0) + System.Collections (>= 4.0.0) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 + System.Globalization (>= 4.0.0) - framework: dnxcore50 + System.IO (>= 4.0.0) - framework: dnxcore50 + System.Linq (>= 4.0.0) - framework: dnxcore50 + System.Reflection (>= 4.0.0) - framework: dnxcore50 + System.Reflection.Extensions (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 + System.Text.RegularExpressions (>= 4.0.0) - framework: dnxcore50 + System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + xunit.abstractions (>= 2.0.0) - framework: dnxcore50 + xunit.abstractions (2.0.0) - framework: dnx451, monoandroid, monotouch, xamarinios, winv4.5, wpv8.1, wpv8.0, >= net35 + xunit.runner.visualstudio (2.1.0) diff --git a/src/benchmark/PersistenceBenchmark/App.config b/src/benchmark/PersistenceBenchmark/App.config index fde80ced889..2de963ff0c0 100644 --- a/src/benchmark/PersistenceBenchmark/App.config +++ b/src/benchmark/PersistenceBenchmark/App.config @@ -112,10 +112,6 @@ - - - - diff --git a/src/benchmark/PingPong/App.config b/src/benchmark/PingPong/App.config index 39e73226ebf..4b9e5cc452b 100644 --- a/src/benchmark/PingPong/App.config +++ b/src/benchmark/PingPong/App.config @@ -114,10 +114,6 @@ - - - - diff --git a/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj b/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj index b622b41b12d..b7680fdbbf7 100644 --- a/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj @@ -79,83 +79,10 @@ --> - + - - ..\..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - - - <__paket__xunit_core_props>monotouch\xunit.core - - - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - - - <__paket__xunit_core_props>Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core - - - - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + + ..\..\..\..\packages\test\xunit\lib\net20\xunit.dll True True diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj index 049189d1204..950bf02b13a 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj @@ -140,10 +140,10 @@ - + - ..\..\..\..\packages\Unity\lib\portable-net45+wp80+win8+MonoAndroid10+MonoTouch10\Microsoft.Practices.Unity.dll + ..\..\..\..\packages\Unity\lib\portable-net45+wp80+win8+wpa81+MonoAndroid10+MonoTouch10\Microsoft.Practices.Unity.dll True True diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj b/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj index b4eabaf3d0e..6f4504e6919 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj @@ -125,10 +125,10 @@ - + - ..\..\..\..\packages\Unity\lib\portable-net45+wp80+win8+MonoAndroid10+MonoTouch10\Microsoft.Practices.Unity.dll + ..\..\..\..\packages\Unity\lib\portable-net45+wp80+win8+wpa81+MonoAndroid10+MonoTouch10\Microsoft.Practices.Unity.dll True True diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj b/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj index 2981609dc99..e0ecbfe8b60 100644 --- a/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj +++ b/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj @@ -70,7 +70,7 @@ --> - + ..\..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -93,7 +93,7 @@ - ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -101,52 +101,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>win81\xunit.core - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - + - <__paket__xunit_core_props>Xamarin.iOS\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/paket.references b/src/contrib/testkits/Akka.TestKit.Xunit2/paket.references index 4bf78cf8fea..f1e55442a7e 100644 --- a/src/contrib/testkits/Akka.TestKit.Xunit2/paket.references +++ b/src/contrib/testkits/Akka.TestKit.Xunit2/paket.references @@ -1,2 +1,3 @@ group Test -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj b/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj index 2c793274535..2787b4f2c13 100644 --- a/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj +++ b/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj @@ -106,7 +106,7 @@ - ..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll True True @@ -114,7 +114,7 @@ - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -137,7 +137,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -145,52 +145,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>win81\xunit.core - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - + - <__paket__xunit_core_props>Xamarin.iOS\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.Cluster.Tests.MultiNode/paket.references b/src/core/Akka.Cluster.Tests.MultiNode/paket.references index 26d1c8e78f3..b678a533d76 100644 --- a/src/core/Akka.Cluster.Tests.MultiNode/paket.references +++ b/src/core/Akka.Cluster.Tests.MultiNode/paket.references @@ -1,3 +1,5 @@ -Microsoft.Bcl.Immutable +System.Collections.Immutable + group Test -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj b/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj index 8324eee71bb..87634eb3e16 100644 --- a/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj +++ b/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj @@ -222,7 +222,7 @@ - ..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll True True @@ -349,7 +349,7 @@ - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -372,7 +372,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -380,52 +380,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - + - <__paket__xunit_core_props>monoandroid\xunit.core + <__paket__xunit_core_props>win81\xunit.core - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - - - <__paket__xunit_core_props>Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - + - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.Cluster.Tests/paket.references b/src/core/Akka.Cluster.Tests/paket.references index a2040d828c0..743b6c0b38f 100644 --- a/src/core/Akka.Cluster.Tests/paket.references +++ b/src/core/Akka.Cluster.Tests/paket.references @@ -1,5 +1,6 @@ Google.ProtocolBuffers -Microsoft.Bcl.Immutable +System.Collections.Immutable group Test FluentAssertions -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Cluster/Akka.Cluster.csproj b/src/core/Akka.Cluster/Akka.Cluster.csproj index 439d679c039..c2194ed3444 100644 --- a/src/core/Akka.Cluster/Akka.Cluster.csproj +++ b/src/core/Akka.Cluster/Akka.Cluster.csproj @@ -193,7 +193,7 @@ - ..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll True True diff --git a/src/core/Akka.Cluster/paket.references b/src/core/Akka.Cluster/paket.references index c56b0b9850c..b4721cd0526 100644 --- a/src/core/Akka.Cluster/paket.references +++ b/src/core/Akka.Cluster/paket.references @@ -1,2 +1,2 @@ Google.ProtocolBuffers -Microsoft.Bcl.Immutable \ No newline at end of file +System.Collections.Immutable \ No newline at end of file diff --git a/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj b/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj index d8b51df80f3..8cd3f694aff 100644 --- a/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj +++ b/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj @@ -59,7 +59,6 @@ - @@ -216,7 +215,7 @@ - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -239,7 +238,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -247,52 +246,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - + - <__paket__xunit_core_props>monoandroid\xunit.core + <__paket__xunit_core_props>win81\xunit.core - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - - - <__paket__xunit_core_props>Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.FSharp.Tests/app.config b/src/core/Akka.FSharp.Tests/app.config index f6c76d955c4..c03004cd2a4 100644 --- a/src/core/Akka.FSharp.Tests/app.config +++ b/src/core/Akka.FSharp.Tests/app.config @@ -125,45 +125,13 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.FSharp.Tests/paket.references b/src/core/Akka.FSharp.Tests/paket.references index 419d69c953c..fa04e6f8f0d 100644 --- a/src/core/Akka.FSharp.Tests/paket.references +++ b/src/core/Akka.FSharp.Tests/paket.references @@ -1,2 +1,4 @@ group Test -FsCheck.Xunit \ No newline at end of file +FsCheck.Xunit +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.FSharp/FsApi.fs b/src/core/Akka.FSharp/FsApi.fs index d0c15f0ace9..d5e35a7ac26 100644 --- a/src/core/Akka.FSharp/FsApi.fs +++ b/src/core/Akka.FSharp/FsApi.fs @@ -44,7 +44,7 @@ module Serialization = // used for top level serialization type ExprSerializer(system) = inherit Serializer(system) - let fsp = FsPickler.CreateBinary() + let fsp = FsPickler.CreateBinarySerializer() override __.Identifier = 9 override __.IncludeManifest = true override __.ToBinary(o) = serializeToBinary fsp o @@ -424,7 +424,7 @@ type ExprDeciderSurrogate(serializedExpr: byte array) = member __.SerializedExpr = serializedExpr interface ISurrogate with member this.FromSurrogate _ = - let fsp = Nessos.FsPickler.FsPickler.CreateBinary() + let fsp = Nessos.FsPickler.FsPickler.CreateBinarySerializer() let expr = (Serialization.deserializeFromBinaryDirective)>> fsp (this.SerializedExpr)) ExprDecider(expr) :> ISurrogated @@ -435,7 +435,7 @@ and ExprDecider (expr: Expr<(exn->Directive)>) = member this.Decide (e: exn): Directive = this.Compiled.Value (e) interface ISurrogated with member this.ToSurrogate _ = - let fsp = Nessos.FsPickler.FsPickler.CreateBinary() + let fsp = Nessos.FsPickler.FsPickler.CreateBinarySerializer() ExprDeciderSurrogate(Serialization.serializeToBinary fsp this.Expr) :> ISurrogate type Strategy = diff --git a/src/core/Akka.FSharp/app.config b/src/core/Akka.FSharp/app.config index 480973c5631..2f259236304 100644 --- a/src/core/Akka.FSharp/app.config +++ b/src/core/Akka.FSharp/app.config @@ -111,10 +111,6 @@ - - - - diff --git a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj index e16fa009554..4d5e46cfdc6 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj +++ b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj @@ -108,7 +108,7 @@ - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -131,7 +131,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -139,52 +139,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>win81\xunit.core - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - + - <__paket__xunit_core_props>Xamarin.iOS\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/paket.references b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/paket.references index deaf88e37f2..329cdebecfc 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/paket.references +++ b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/paket.references @@ -1,3 +1,4 @@ faker-csharp group Test -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj index 556d1354051..04c879b994b 100644 --- a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj +++ b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj @@ -1,4 +1,4 @@ - + @@ -38,9 +38,6 @@ - - ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - @@ -87,7 +84,7 @@ --> - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -106,20 +103,31 @@ + + + + + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll + True + True + + + + - - ..\..\..\packages\test\xunit.runner.utility\lib\win8\xunit.runner.utility.win8.dll + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll True True - + - - ..\..\..\packages\test\xunit.runner.utility\lib\net35\xunit.runner.utility.desktop.dll + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll True True @@ -127,8 +135,8 @@ - - ..\..\..\packages\test\xunit.runner.utility\lib\monoandroid\xunit.runner.utility.MonoAndroid.dll + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll True True @@ -136,8 +144,8 @@ - - ..\..\..\packages\test\xunit.runner.utility\lib\monotouch\xunit.runner.utility.MonoTouch.dll + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll True True @@ -145,8 +153,17 @@ - - ..\..\..\packages\test\xunit.runner.utility\lib\wp8\xunit.runner.utility.wp8.dll + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll True True @@ -154,17 +171,37 @@ - - ..\..\..\packages\test\xunit.runner.utility\lib\Xamarin.iOS\xunit.runner.utility.iOS-Universal.dll + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll True True - + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.runner.utility\lib\net35\xunit.runner.utility.desktop.dll + True + True + + + + - - ..\..\..\packages\test\xunit.runner.utility\lib\portable-wpa81+win81\xunit.runner.utility.universal.dll + + ..\..\..\packages\test\xunit.runner.utility\lib\portable-net45+win8+wp8+wpa81\xunit.runner.utility.dotnet.dll True True diff --git a/src/core/Akka.MultiNodeTestRunner/App.config b/src/core/Akka.MultiNodeTestRunner/App.config index fde80ced889..82a34b6b6ca 100644 --- a/src/core/Akka.MultiNodeTestRunner/App.config +++ b/src/core/Akka.MultiNodeTestRunner/App.config @@ -112,44 +112,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/Program.cs b/src/core/Akka.MultiNodeTestRunner/Program.cs index d624817c443..5ae1a09a5f1 100644 --- a/src/core/Akka.MultiNodeTestRunner/Program.cs +++ b/src/core/Akka.MultiNodeTestRunner/Program.cs @@ -75,7 +75,7 @@ static void Main(string[] args) EnableAllSinks(assemblyName); PublishRunnerMessage(String.Format("Running MultiNodeTests for {0}", assemblyName)); - using (var controller = new XunitFrontController(assemblyName)) + using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, assemblyName)) { using (var discovery = new Discovery()) { diff --git a/src/core/Akka.MultiNodeTestRunner/paket.references b/src/core/Akka.MultiNodeTestRunner/paket.references index e16c8c54501..89febfd4dc5 100644 --- a/src/core/Akka.MultiNodeTestRunner/paket.references +++ b/src/core/Akka.MultiNodeTestRunner/paket.references @@ -1,2 +1,7 @@ group Test -xunit.runner.utility \ No newline at end of file +xunit.core +xunit.assert +xunit.extensions +xunit.runner.console +xunit.runner.utility +xunit.runner.visualstudio \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj index ce9853fcdc8..cf995b9aaf1 100644 --- a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj +++ b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj @@ -98,7 +98,7 @@ --> - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -118,15 +118,6 @@ - - - - ..\..\..\packages\test\xunit.runner.utility\lib\win8\xunit.runner.utility.win8.dll - True - True - - - @@ -136,46 +127,10 @@ - - - - ..\..\..\packages\test\xunit.runner.utility\lib\monoandroid\xunit.runner.utility.MonoAndroid.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.runner.utility\lib\monotouch\xunit.runner.utility.MonoTouch.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.runner.utility\lib\wp8\xunit.runner.utility.wp8.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.runner.utility\lib\Xamarin.iOS\xunit.runner.utility.iOS-Universal.dll - True - True - - - - + - - ..\..\..\packages\test\xunit.runner.utility\lib\portable-wpa81+win81\xunit.runner.utility.universal.dll + + ..\..\..\packages\test\xunit.runner.utility\lib\portable-net45+win8+wp8+wpa81\xunit.runner.utility.dotnet.dll True True diff --git a/src/core/Akka.NodeTestRunner/App.config b/src/core/Akka.NodeTestRunner/App.config index 09fc8e52b2d..c8c4db09f25 100644 --- a/src/core/Akka.NodeTestRunner/App.config +++ b/src/core/Akka.NodeTestRunner/App.config @@ -121,10 +121,6 @@ - - - - diff --git a/src/core/Akka.NodeTestRunner/Program.cs b/src/core/Akka.NodeTestRunner/Program.cs index 88767b12295..77c13d8c773 100644 --- a/src/core/Akka.NodeTestRunner/Program.cs +++ b/src/core/Akka.NodeTestRunner/Program.cs @@ -25,7 +25,7 @@ static void Main(string[] args) Thread.Sleep(TimeSpan.FromSeconds(10)); - using (var controller = new XunitFrontController(assemblyFileName)) + using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, assemblyFileName)) { /* need to pass in just the assembly name to Discovery, not the full path * i.e. "Akka.Cluster.Tests.MultiNode.dll" diff --git a/src/core/Akka.NodeTestRunner/paket.references b/src/core/Akka.NodeTestRunner/paket.references index e16c8c54501..d15f7ae54a1 100644 --- a/src/core/Akka.NodeTestRunner/paket.references +++ b/src/core/Akka.NodeTestRunner/paket.references @@ -1,2 +1,3 @@ group Test +xunit.abstractions xunit.runner.utility \ No newline at end of file diff --git a/src/core/Akka.Persistence.FSharp/app.config b/src/core/Akka.Persistence.FSharp/app.config index 480973c5631..2f259236304 100644 --- a/src/core/Akka.Persistence.FSharp/app.config +++ b/src/core/Akka.Persistence.FSharp/app.config @@ -111,10 +111,6 @@ - - - - diff --git a/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj b/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj index aab37b55df7..0b951e2da45 100644 --- a/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj +++ b/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj @@ -79,7 +79,7 @@ --> - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -102,7 +102,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -110,52 +110,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>win81\xunit.core - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - + - <__paket__xunit_core_props>Xamarin.iOS\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.Persistence.TestKit.Tests/paket.references b/src/core/Akka.Persistence.TestKit.Tests/paket.references index 4bf78cf8fea..f1e55442a7e 100644 --- a/src/core/Akka.Persistence.TestKit.Tests/paket.references +++ b/src/core/Akka.Persistence.TestKit.Tests/paket.references @@ -1,2 +1,3 @@ group Test -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj b/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj index d785ee52887..dd9685f772d 100644 --- a/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj +++ b/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj @@ -81,7 +81,7 @@ --> - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -104,7 +104,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -112,52 +112,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>win81\xunit.core - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - + - <__paket__xunit_core_props>Xamarin.iOS\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.Persistence.TestKit/paket.references b/src/core/Akka.Persistence.TestKit/paket.references index 4bf78cf8fea..f1e55442a7e 100644 --- a/src/core/Akka.Persistence.TestKit/paket.references +++ b/src/core/Akka.Persistence.TestKit/paket.references @@ -1,2 +1,3 @@ group Test -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj index ee4cc7e5e76..43510797058 100644 --- a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj +++ b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj @@ -182,7 +182,7 @@ - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -205,7 +205,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -213,52 +213,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>win81\xunit.core - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - + - <__paket__xunit_core_props>Xamarin.iOS\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.Persistence.Tests/paket.references b/src/core/Akka.Persistence.Tests/paket.references index 83a51faaffe..a94200f76e5 100644 --- a/src/core/Akka.Persistence.Tests/paket.references +++ b/src/core/Akka.Persistence.Tests/paket.references @@ -1,3 +1,4 @@ Google.ProtocolBuffers group Test -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj b/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj index d6d6a0a6d14..47cbd7c306b 100644 --- a/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj +++ b/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj @@ -106,7 +106,7 @@ - ..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll True True @@ -114,7 +114,7 @@ - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -137,7 +137,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -145,52 +145,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - + - <__paket__xunit_core_props>monoandroid\xunit.core + <__paket__xunit_core_props>win81\xunit.core - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - - - <__paket__xunit_core_props>Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.Remote.TestKit.Tests/paket.references b/src/core/Akka.Remote.TestKit.Tests/paket.references index 8e8ccb3aa47..aef171068ca 100644 --- a/src/core/Akka.Remote.TestKit.Tests/paket.references +++ b/src/core/Akka.Remote.TestKit.Tests/paket.references @@ -1,4 +1,5 @@ Helios -Microsoft.Bcl.Immutable +System.Collections.Immutable group Test -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj index 4f4fb565fa3..1a012ae8bb1 100644 --- a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj +++ b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj @@ -228,17 +228,6 @@ - - - - - ..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - True - - - - @@ -296,7 +285,18 @@ - + + + + ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -319,7 +319,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -327,52 +327,102 @@ - + - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core + <__paket__xunit_core_props>win81\xunit.core - + - <__paket__xunit_core_props>monoandroid\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>monotouch\xunit.core - - - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - - - <__paket__xunit_core_props>Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.Remote.TestKit/paket.references b/src/core/Akka.Remote.TestKit/paket.references index 01868d55773..f29ac52b610 100644 --- a/src/core/Akka.Remote.TestKit/paket.references +++ b/src/core/Akka.Remote.TestKit/paket.references @@ -1,6 +1,7 @@ Google.ProtocolBuffers Helios -Microsoft.Bcl.Immutable +System.Collections.Immutable Newtonsoft.Json group Test -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj b/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj index c7fe32c55f7..683cd3e2ab1 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj +++ b/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj @@ -33,9 +33,6 @@ - - ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - @@ -94,7 +91,18 @@ --> - + + + + ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + + + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -117,7 +125,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -125,52 +133,102 @@ - + - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core + <__paket__xunit_core_props>win81\xunit.core - + - <__paket__xunit_core_props>monoandroid\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - - - <__paket__xunit_core_props>monotouch\xunit.core - - - + - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - - - <__paket__xunit_core_props>Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.Remote.Tests.MultiNode/paket.references b/src/core/Akka.Remote.Tests.MultiNode/paket.references index 29b5e86f541..311dd9d2427 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/paket.references +++ b/src/core/Akka.Remote.Tests.MultiNode/paket.references @@ -1,5 +1,6 @@ +System.Collections.Immutable + group Test -xunit xunit.abstractions xunit.assert xunit.core diff --git a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj index 8d1e4c58429..964d65821c8 100644 --- a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj +++ b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj @@ -226,7 +226,7 @@ - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -249,7 +249,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -257,52 +257,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>win81\xunit.core - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - + - <__paket__xunit_core_props>Xamarin.iOS\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.Remote.Tests/app.config b/src/core/Akka.Remote.Tests/app.config index dd193b79992..3d69e0c8bdc 100644 --- a/src/core/Akka.Remote.Tests/app.config +++ b/src/core/Akka.Remote.Tests/app.config @@ -111,10 +111,6 @@ - - - - @@ -123,26 +119,6 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/src/core/Akka.Remote.Tests/paket.references b/src/core/Akka.Remote.Tests/paket.references index 83a51faaffe..a94200f76e5 100644 --- a/src/core/Akka.Remote.Tests/paket.references +++ b/src/core/Akka.Remote.Tests/paket.references @@ -1,3 +1,4 @@ Google.ProtocolBuffers group Test -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Remote/app.config b/src/core/Akka.Remote/app.config index dd193b79992..2a9455b55bf 100644 --- a/src/core/Akka.Remote/app.config +++ b/src/core/Akka.Remote/app.config @@ -111,10 +111,6 @@ - - - - diff --git a/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj b/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj index ba488464bbd..d559989b9ab 100644 --- a/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj +++ b/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj @@ -130,7 +130,7 @@ --> - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -153,7 +153,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -161,52 +161,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>win81\xunit.core - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - + - <__paket__xunit_core_props>Xamarin.iOS\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.TestKit.Tests/paket.references b/src/core/Akka.TestKit.Tests/paket.references index 4bf78cf8fea..f1e55442a7e 100644 --- a/src/core/Akka.TestKit.Tests/paket.references +++ b/src/core/Akka.TestKit.Tests/paket.references @@ -1,2 +1,3 @@ group Test -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.TestKit/Akka.TestKit.csproj b/src/core/Akka.TestKit/Akka.TestKit.csproj index 21e25311a7b..dda406a5efa 100644 --- a/src/core/Akka.TestKit/Akka.TestKit.csproj +++ b/src/core/Akka.TestKit/Akka.TestKit.csproj @@ -62,7 +62,6 @@ - @@ -146,7 +145,6 @@ - TextTemplatingFileGenerator diff --git a/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj b/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj index 3077d6c8e61..2447a50e155 100644 --- a/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj +++ b/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj @@ -78,7 +78,7 @@ --> - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -101,7 +101,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -109,52 +109,102 @@ - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - + - <__paket__xunit_core_props>monotouch\xunit.core + <__paket__xunit_core_props>win81\xunit.core - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - + - <__paket__xunit_core_props>Xamarin.iOS\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll True True diff --git a/src/core/Akka.Tests.Shared.Internals/paket.references b/src/core/Akka.Tests.Shared.Internals/paket.references index 4bf78cf8fea..f1e55442a7e 100644 --- a/src/core/Akka.Tests.Shared.Internals/paket.references +++ b/src/core/Akka.Tests.Shared.Internals/paket.references @@ -1,2 +1,3 @@ group Test -xunit \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Tests/Akka.Tests.csproj b/src/core/Akka.Tests/Akka.Tests.csproj index 0a5b4b5eba0..82649fb97c2 100644 --- a/src/core/Akka.Tests/Akka.Tests.csproj +++ b/src/core/Akka.Tests/Akka.Tests.csproj @@ -1,4 +1,4 @@ - + Debug @@ -213,8 +213,8 @@ - - ..\..\..\packages\fastJSON\lib\net35\fastjson.dll + + ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll True True @@ -222,17 +222,44 @@ - - ..\..\..\packages\fastJSON\lib\net20\fastjson.dll + + ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll True True - + - - ..\..\..\packages\fastJSON\lib\net40\fastjson.dll + + ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll True True @@ -462,7 +489,7 @@ - + ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll @@ -485,7 +512,7 @@ - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll True True @@ -493,52 +520,28 @@ - + - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core + <__paket__xunit_core_props>win81\xunit.core - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - - - <__paket__xunit_core_props>monotouch\xunit.core - - - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - - - <__paket__xunit_core_props>Xamarin.iOS\xunit.core - - - + - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core + <__paket__xunit_core_props>wpa81\xunit.core - + - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll True True @@ -547,28 +550,76 @@ - - <__paket__xunit_runner_visualstudio_props>win8\xunit.runner.visualstudio - <__paket__xunit_runner_visualstudio_targets>win8\xunit.runner.visualstudio - + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + - - - <__paket__xunit_runner_visualstudio_props>net20\xunit.runner.visualstudio - + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + - - <__paket__xunit_runner_visualstudio_props>wpa81\xunit.runner.visualstudio - <__paket__xunit_runner_visualstudio_targets>wpa81\xunit.runner.visualstudio - + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + - - - <__paket__xunit_runner_visualstudio_props>portable-net45+aspnetcore50+win+wpa81+wp80+monotouch+monoandroid\xunit.runner.visualstudio - + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll + True + True + + - - \ No newline at end of file diff --git a/src/core/Akka.Tests/App.config b/src/core/Akka.Tests/App.config index 1e47aeaedf5..f7a16eaadc0 100644 --- a/src/core/Akka.Tests/App.config +++ b/src/core/Akka.Tests/App.config @@ -133,44 +133,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/core/Akka.Tests/TestUtils/Comparable.cs b/src/core/Akka.Tests/TestUtils/Comparable.cs index bd1c47f0362..2a824c27c90 100644 --- a/src/core/Akka.Tests/TestUtils/Comparable.cs +++ b/src/core/Akka.Tests/TestUtils/Comparable.cs @@ -5,6 +5,8 @@ // //----------------------------------------------------------------------- +using Newtonsoft.Json; + namespace Akka.Tests.TestUtils { public class Comparable @@ -23,7 +25,7 @@ public override int GetHashCode() public override string ToString() { - var res = fastJSON.JSON.Instance.ToJSON(this); + var res = JsonConvert.SerializeObject(this); return res; } } diff --git a/src/core/Akka.Tests/paket.references b/src/core/Akka.Tests/paket.references index c61f5807c71..b802fa0b5c0 100644 --- a/src/core/Akka.Tests/paket.references +++ b/src/core/Akka.Tests/paket.references @@ -1,7 +1,7 @@ -fastJSON +Newtonsoft.Json group Test FluentAssertions FsCheck -xunit.extensions -xunit.runner.visualstudio \ No newline at end of file +xunit.core +xunit.assert \ No newline at end of file diff --git a/src/core/Akka/Akka.csproj b/src/core/Akka/Akka.csproj index 64e6cee98cb..b9e406d908e 100644 --- a/src/core/Akka/Akka.csproj +++ b/src/core/Akka/Akka.csproj @@ -58,10 +58,6 @@ - - ..\..\packages\Wire.0.0.4\lib\Wire.dll - True - @@ -444,4 +440,11 @@ + + + ..\..\..\packages\Wire\lib\Wire.dll + True + True + + \ No newline at end of file diff --git a/src/core/Akka/paket.references b/src/core/Akka/paket.references index 1063d003b92..03830501c65 100644 --- a/src/core/Akka/paket.references +++ b/src/core/Akka/paket.references @@ -1 +1,2 @@ -Newtonsoft.Json \ No newline at end of file +Newtonsoft.Json +Wire \ No newline at end of file diff --git a/src/examples/Chat/ChatClient/App.config b/src/examples/Chat/ChatClient/App.config index 3e4504645bc..48ac5d9fffc 100644 --- a/src/examples/Chat/ChatClient/App.config +++ b/src/examples/Chat/ChatClient/App.config @@ -115,10 +115,6 @@ - - - - diff --git a/src/examples/Chat/ChatMessages/ChatMessages.csproj b/src/examples/Chat/ChatMessages/ChatMessages.csproj index f865678523b..359c93b1cd0 100644 --- a/src/examples/Chat/ChatMessages/ChatMessages.csproj +++ b/src/examples/Chat/ChatMessages/ChatMessages.csproj @@ -84,112 +84,10 @@ --> - + - - ..\..\..\..\packages\fastJSON\lib\net35\fastjson.dll - True - True - - - - - - - ..\..\..\..\packages\fastJSON\lib\net20\fastjson.dll - True - True - - - - - - - ..\..\..\..\packages\fastJSON\lib\net40\fastjson.dll - True - True - - - - - - - - - ..\..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win8\xunit.core - <__paket__xunit_core_targets>win8\xunit.core - - - - - <__paket__xunit_core_props>monoandroid\xunit.core - - - - - <__paket__xunit_core_props>monotouch\xunit.core - - - - - <__paket__xunit_core_props>wp8\xunit.core - <__paket__xunit_core_targets>wp8\xunit.core - - - - - <__paket__xunit_core_props>Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core - - - - - <__paket__xunit_core_props>portable-win81+wpa81\xunit.core - <__paket__xunit_core_targets>portable-win81+wpa81\xunit.core - - - - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + + ..\..\..\..\packages\test\xunit\lib\net20\xunit.dll True True diff --git a/src/examples/Chat/ChatMessages/paket.references b/src/examples/Chat/ChatMessages/paket.references index 713ba4ffa9a..4bf78cf8fea 100644 --- a/src/examples/Chat/ChatMessages/paket.references +++ b/src/examples/Chat/ChatMessages/paket.references @@ -1,3 +1,2 @@ -fastJSON group Test xunit \ No newline at end of file diff --git a/src/examples/Chat/ChatServer/App.config b/src/examples/Chat/ChatServer/App.config index 3e4504645bc..48ac5d9fffc 100644 --- a/src/examples/Chat/ChatServer/App.config +++ b/src/examples/Chat/ChatServer/App.config @@ -115,10 +115,6 @@ - - - - diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config index 47e89e97117..90b07230013 100644 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config @@ -142,10 +142,6 @@ - - - - diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj index 02783942f1b..fd2e90c81ee 100644 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj @@ -72,7 +72,7 @@ - ..\..\..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + ..\..\..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll True True diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/paket.references b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/paket.references index da543da7bdd..1bfbdbed4d6 100644 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/paket.references +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/paket.references @@ -1 +1 @@ -Microsoft.Bcl.Immutable \ No newline at end of file +System.Collections.Immutable \ No newline at end of file diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config index 01ea0c6f779..de502654b95 100644 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config @@ -143,10 +143,6 @@ - - - - diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj index a2b7485db2b..c26bc14b252 100644 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj @@ -76,7 +76,7 @@ - ..\..\..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + ..\..\..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll True True diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/paket.references b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/paket.references index da543da7bdd..1bfbdbed4d6 100644 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/paket.references +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/paket.references @@ -1 +1 @@ -Microsoft.Bcl.Immutable \ No newline at end of file +System.Collections.Immutable \ No newline at end of file diff --git a/src/examples/Cluster/Samples.Cluster.Simple/App.config b/src/examples/Cluster/Samples.Cluster.Simple/App.config index abbd33d8065..65b7892db67 100644 --- a/src/examples/Cluster/Samples.Cluster.Simple/App.config +++ b/src/examples/Cluster/Samples.Cluster.Simple/App.config @@ -142,10 +142,6 @@ - - - - diff --git a/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj b/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj index 047d2236275..96f7e7ef7c2 100644 --- a/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj +++ b/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj @@ -75,7 +75,7 @@ - ..\..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + ..\..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll True True diff --git a/src/examples/Cluster/Samples.Cluster.Simple/paket.references b/src/examples/Cluster/Samples.Cluster.Simple/paket.references index da543da7bdd..1bfbdbed4d6 100644 --- a/src/examples/Cluster/Samples.Cluster.Simple/paket.references +++ b/src/examples/Cluster/Samples.Cluster.Simple/paket.references @@ -1 +1 @@ -Microsoft.Bcl.Immutable \ No newline at end of file +System.Collections.Immutable \ No newline at end of file diff --git a/src/examples/FSharp.Api/App.config b/src/examples/FSharp.Api/App.config index 4c2eaa0cdb4..f024efe74fc 100644 --- a/src/examples/FSharp.Api/App.config +++ b/src/examples/FSharp.Api/App.config @@ -114,10 +114,6 @@ - - - - diff --git a/src/examples/FSharp.Api/FSharp.Api.fsproj b/src/examples/FSharp.Api/FSharp.Api.fsproj index 4715804bedc..28bbf3a3746 100644 --- a/src/examples/FSharp.Api/FSharp.Api.fsproj +++ b/src/examples/FSharp.Api/FSharp.Api.fsproj @@ -165,4 +165,11 @@ + + + ..\..\..\packages\Wire\lib\Wire.dll + True + True + + \ No newline at end of file diff --git a/src/examples/FSharp.Api/paket.references b/src/examples/FSharp.Api/paket.references index 1063d003b92..03830501c65 100644 --- a/src/examples/FSharp.Api/paket.references +++ b/src/examples/FSharp.Api/paket.references @@ -1 +1,2 @@ -Newtonsoft.Json \ No newline at end of file +Newtonsoft.Json +Wire \ No newline at end of file diff --git a/src/examples/FSharp.Deploy.Local/App.config b/src/examples/FSharp.Deploy.Local/App.config index 4c2eaa0cdb4..f024efe74fc 100644 --- a/src/examples/FSharp.Deploy.Local/App.config +++ b/src/examples/FSharp.Deploy.Local/App.config @@ -114,10 +114,6 @@ - - - - diff --git a/src/examples/FSharp.Deploy.Remote/App.config b/src/examples/FSharp.Deploy.Remote/App.config index 4c2eaa0cdb4..f024efe74fc 100644 --- a/src/examples/FSharp.Deploy.Remote/App.config +++ b/src/examples/FSharp.Deploy.Remote/App.config @@ -114,10 +114,6 @@ - - - - diff --git a/src/examples/FaultTolerance/App.config b/src/examples/FaultTolerance/App.config index fde80ced889..2de963ff0c0 100644 --- a/src/examples/FaultTolerance/App.config +++ b/src/examples/FaultTolerance/App.config @@ -112,10 +112,6 @@ - - - - diff --git a/src/examples/HelloWorld/FSharp.HelloAkka/App.config b/src/examples/HelloWorld/FSharp.HelloAkka/App.config index 4c2eaa0cdb4..f024efe74fc 100644 --- a/src/examples/HelloWorld/FSharp.HelloAkka/App.config +++ b/src/examples/HelloWorld/FSharp.HelloAkka/App.config @@ -114,10 +114,6 @@ - - - - diff --git a/src/examples/HelloWorld/HelloAkka/App.config b/src/examples/HelloWorld/HelloAkka/App.config index fde80ced889..2de963ff0c0 100644 --- a/src/examples/HelloWorld/HelloAkka/App.config +++ b/src/examples/HelloWorld/HelloAkka/App.config @@ -112,10 +112,6 @@ - - - - diff --git a/src/examples/PersistenceExample.FsApi/App.config b/src/examples/PersistenceExample.FsApi/App.config index 4c2eaa0cdb4..f024efe74fc 100644 --- a/src/examples/PersistenceExample.FsApi/App.config +++ b/src/examples/PersistenceExample.FsApi/App.config @@ -114,10 +114,6 @@ - - - - diff --git a/src/examples/PersistenceExample/App.config b/src/examples/PersistenceExample/App.config index fde80ced889..2de963ff0c0 100644 --- a/src/examples/PersistenceExample/App.config +++ b/src/examples/PersistenceExample/App.config @@ -112,10 +112,6 @@ - - - - diff --git a/src/examples/RemoteDeploy/System1/App.config b/src/examples/RemoteDeploy/System1/App.config index 78a11d4cc5e..375214d25ca 100644 --- a/src/examples/RemoteDeploy/System1/App.config +++ b/src/examples/RemoteDeploy/System1/App.config @@ -114,10 +114,6 @@ - - - - diff --git a/src/examples/RemoteDeploy/System2/App.config b/src/examples/RemoteDeploy/System2/App.config index 78a11d4cc5e..375214d25ca 100644 --- a/src/examples/RemoteDeploy/System2/App.config +++ b/src/examples/RemoteDeploy/System2/App.config @@ -114,10 +114,6 @@ - - - - diff --git a/src/examples/Routing/App.config b/src/examples/Routing/App.config index fde80ced889..2de963ff0c0 100644 --- a/src/examples/Routing/App.config +++ b/src/examples/Routing/App.config @@ -112,10 +112,6 @@ - - - - diff --git a/src/examples/Stocks/SymbolLookup/Actors/TickerActors.cs b/src/examples/Stocks/SymbolLookup/Actors/TickerActors.cs index f4a3da11363..9893277f9b3 100644 --- a/src/examples/Stocks/SymbolLookup/Actors/TickerActors.cs +++ b/src/examples/Stocks/SymbolLookup/Actors/TickerActors.cs @@ -8,6 +8,7 @@ using System; using System.Net.Http; using Akka.Actor; +using Newtonsoft.Json; using QDFeedParser; using SymbolLookup.Actors.Messages; using SymbolLookup.YahooFinance; @@ -107,7 +108,7 @@ protected override void OnReceive(object msg) var quoteStrTask = _client.GetStringAsync(StockUriHelper.CreateStockQuoteUri(symboldata.Symbol)); quoteStrTask.Wait(); var quoteStr = quoteStrTask.Result; - var quoteData = fastJSON.JSON.Instance.ToObject(quoteStr); + var quoteData = JsonConvert.DeserializeObject(quoteStr); if (quoteData == null || quoteData.query == null || quoteData.query.results == null) { //request failed for whatever reason, diff --git a/src/examples/Stocks/SymbolLookup/App.config b/src/examples/Stocks/SymbolLookup/App.config index fde80ced889..2de963ff0c0 100644 --- a/src/examples/Stocks/SymbolLookup/App.config +++ b/src/examples/Stocks/SymbolLookup/App.config @@ -112,10 +112,6 @@ - - - - diff --git a/src/examples/Stocks/SymbolLookup/SymbolLookup.csproj b/src/examples/Stocks/SymbolLookup/SymbolLookup.csproj index 320e7b3126d..cfe76ef4e1c 100644 --- a/src/examples/Stocks/SymbolLookup/SymbolLookup.csproj +++ b/src/examples/Stocks/SymbolLookup/SymbolLookup.csproj @@ -125,8 +125,8 @@ - - ..\..\..\..\packages\fastJSON\lib\net35\fastjson.dll + + ..\..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll True True @@ -134,28 +134,44 @@ - - ..\..\..\..\packages\fastJSON\lib\net20\fastjson.dll + + ..\..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll True True - + - - ..\..\..\..\packages\fastJSON\lib\net40\fastjson.dll + + ..\..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll True True - - - + - - ..\..\..\..\packages\Microsoft.Bcl.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + ..\..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll True True @@ -209,4 +225,15 @@ + + + + + ..\..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/Stocks/SymbolLookup/paket.references b/src/examples/Stocks/SymbolLookup/paket.references index e5ccd0a69bd..2f15ac5d44d 100644 --- a/src/examples/Stocks/SymbolLookup/paket.references +++ b/src/examples/Stocks/SymbolLookup/paket.references @@ -1,3 +1,3 @@ -fastJSON -Microsoft.Bcl.Immutable +Newtonsoft.Json +System.Collections.Immutable qdfeed \ No newline at end of file diff --git a/src/examples/TcpEchoService.Server/App.config b/src/examples/TcpEchoService.Server/App.config index fde80ced889..2de963ff0c0 100644 --- a/src/examples/TcpEchoService.Server/App.config +++ b/src/examples/TcpEchoService.Server/App.config @@ -112,10 +112,6 @@ - - - - diff --git a/src/examples/TimeServer/TimeClient/App.config b/src/examples/TimeServer/TimeClient/App.config index a5279a7ef0f..0c7096bc3a8 100644 --- a/src/examples/TimeServer/TimeClient/App.config +++ b/src/examples/TimeServer/TimeClient/App.config @@ -161,10 +161,6 @@ - - - - diff --git a/src/examples/TimeServer/TimeServer/App.config b/src/examples/TimeServer/TimeServer/App.config index b832a59bd78..ed4a4974b8b 100644 --- a/src/examples/TimeServer/TimeServer/App.config +++ b/src/examples/TimeServer/TimeServer/App.config @@ -161,10 +161,6 @@ - - - - From 4e079e00663dac0962695ee36a7aee51e62023a8 Mon Sep 17 00:00:00 2001 From: rogeralsing Date: Sat, 3 Oct 2015 20:10:03 +0200 Subject: [PATCH 051/105] hocon-empty Try two --- .../Akka.Tests/Configuration/ConfigurationSpec.cs | 13 +++++++++++++ src/core/Akka/Configuration/Hocon/HoconValue.cs | 14 +++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/core/Akka.Tests/Configuration/ConfigurationSpec.cs b/src/core/Akka.Tests/Configuration/ConfigurationSpec.cs index 2684924ff6d..8eff7d3c34b 100644 --- a/src/core/Akka.Tests/Configuration/ConfigurationSpec.cs +++ b/src/core/Akka.Tests/Configuration/ConfigurationSpec.cs @@ -94,6 +94,19 @@ public class MyObjectConfig public bool BoolProperty { get; set; } public int[] IntergerArray { get; set; } } + + [Fact] + public void ParsingEmptyStringShouldProduceEmptyHoconRoot() + { + var value = Parser.Parse(string.Empty, null).Value; + value.IsEmpty.ShouldBeTrue(); + } + + [Fact] + public void Config_Empty_is_Empty() + { + ConfigurationFactory.Empty.IsEmpty.ShouldBeTrue(); + } } } diff --git a/src/core/Akka/Configuration/Hocon/HoconValue.cs b/src/core/Akka/Configuration/Hocon/HoconValue.cs index cad11141b11..0edfbf8b113 100644 --- a/src/core/Akka/Configuration/Hocon/HoconValue.cs +++ b/src/core/Akka/Configuration/Hocon/HoconValue.cs @@ -32,7 +32,19 @@ public HoconValue() /// public bool IsEmpty { - get { return Values.Count == 0; } + get + { + if (Values.Count == 0) + return true; + + var first = Values[0] as HoconObject; + if (first != null) + { + if (first.Items.Count == 0) + return true; + } + return false; + } } /// From bd91bcd50d918e5e8ee4b085e53d603cfd46c89a Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Wed, 7 Oct 2015 12:45:32 +0400 Subject: [PATCH 052/105] #1296 Port EventBusUnsubscribers --- src/core/Akka.Tests/Event/EventStreamSpec.cs | 2 + .../Akka/Actor/Internal/ActorSystemImpl.cs | 4 +- src/core/Akka/Akka.csproj | 1 + src/core/Akka/Event/EventBusUnsubscriber.cs | 132 ++++++++++++++++++ src/core/Akka/Event/EventStream.cs | 89 +++++++++++- 5 files changed, 224 insertions(+), 4 deletions(-) create mode 100644 src/core/Akka/Event/EventBusUnsubscriber.cs diff --git a/src/core/Akka.Tests/Event/EventStreamSpec.cs b/src/core/Akka.Tests/Event/EventStreamSpec.cs index 271417fb891..f2425e59b0d 100644 --- a/src/core/Akka.Tests/Event/EventStreamSpec.cs +++ b/src/core/Akka.Tests/Event/EventStreamSpec.cs @@ -62,7 +62,9 @@ private class CCATBT : CC, ATT, BTT { } [Fact] public void ManageSubscriptions() { + var bus = new EventStream(true); + bus.StartUnsubscriber(Sys); bus.Subscribe(TestActor, typeof(M)); bus.Publish(new M { Value = 42 }); diff --git a/src/core/Akka/Actor/Internal/ActorSystemImpl.cs b/src/core/Akka/Actor/Internal/ActorSystemImpl.cs index 43015bee047..01b318e996d 100644 --- a/src/core/Akka/Actor/Internal/ActorSystemImpl.cs +++ b/src/core/Akka/Actor/Internal/ActorSystemImpl.cs @@ -102,8 +102,10 @@ public void Start() if(_settings.LogDeadLetters > 0) _logDeadLetterListener = SystemActorOf("deadLetterListener"); + _eventStream.StartUnsubscriber(this); - if(_settings.LogConfigOnStart) + + if (_settings.LogConfigOnStart) { _log.Warning(Settings.ToString()); } diff --git a/src/core/Akka/Akka.csproj b/src/core/Akka/Akka.csproj index e95cb9cf8b9..086c63447f7 100644 --- a/src/core/Akka/Akka.csproj +++ b/src/core/Akka/Akka.csproj @@ -221,6 +221,7 @@ + diff --git a/src/core/Akka/Event/EventBusUnsubscriber.cs b/src/core/Akka/Event/EventBusUnsubscriber.cs new file mode 100644 index 00000000000..be88f92c8a4 --- /dev/null +++ b/src/core/Akka/Event/EventBusUnsubscriber.cs @@ -0,0 +1,132 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using Akka.Actor; +using Akka.Actor.Internal; +using Akka.Util.Internal; + +namespace Akka.Event +{ + /// + /// INTERNAL API + /// + /// Watches all actors which subscribe on the given eventStream, and unsubscribes them from it when they are Terminated. + /// + /// Assumptions note: + /// We do not guarantee happens-before in the EventStream when 2 threads subscribe(a) / unsubscribe(a) on the same actor, + /// thus the messages sent to this actor may appear to be reordered - this is fine, because the worst-case is starting to + /// needlessly watch the actor which will not cause trouble for the stream. This is a trade-off between slowing down + /// subscribe calls * because of the need of linearizing the history message sequence and the possibility of sometimes + /// watching a few actors too much - we opt for the 2nd choice here. + /// + class EventStreamUnsubscriber : ActorBase + { + private readonly EventStream _eventStream; + private readonly bool _debug; + private readonly ActorSystem _system; + + public EventStreamUnsubscriber(EventStream eventStream, ActorSystem system, bool debug) + { + _eventStream = eventStream; + _system = system; + _debug = debug; + + } + + protected override bool Receive(object message) + { + return message.Match().With(register => + { + if (_debug) + _eventStream.Publish(new Debug(this.GetType().Name, GetType(), + string.Format("watching {0} in order to unsubscribe from EventStream when it terminates", register.Actor))); + Context.Watch(register.Actor); + }).With(unregister => + { + if (_debug) + _eventStream.Publish(new Debug(this.GetType().Name, GetType(), + string.Format("unwatching {0} since has no subscriptions", unregister.Actor))); + Context.Unwatch(unregister.Actor); + }).With(terminated => + { + if (_debug) + _eventStream.Publish(new Debug(this.GetType().Name, GetType(), + string.Format("unsubscribe {0} from {1}, because it was terminated", terminated.Actor , _eventStream ))); + _eventStream.Unsubscribe(terminated.Actor); + }) + .WasHandled; + } + + protected override void PreStart() + { + if (_debug) + _eventStream.Publish(new Debug(this.GetType().Name, GetType(), + string.Format("registering unsubscriber with {0}", _eventStream))); + _eventStream.InitUnsubscriber(Self, _system); + } + + internal class Register + { + public Register(IActorRef actor) + { + Actor = actor; + } + + public IActorRef Actor { get; private set; } + } + + + internal class Terminated + { + public Terminated(IActorRef actor) + { + Actor = actor; + } + + public IActorRef Actor { get; private set; } + } + + internal class UnregisterIfNoMoreSubscribedChannels + { + public UnregisterIfNoMoreSubscribedChannels(IActorRef actor) + { + Actor = actor; + } + + public IActorRef Actor { get; private set; } + } + } + + + + /// + /// Provides factory for Akka.Event.EventStreamUnsubscriber actors with unique names. + /// This is needed if someone spins up more EventStreams using the same ActorSystem, + /// each stream gets it's own unsubscriber. + /// + class EventStreamUnsubscribersProvider + { + private readonly AtomicCounter _unsubscribersCounter = new AtomicCounter(0); + private static readonly EventStreamUnsubscribersProvider _instance = new EventStreamUnsubscribersProvider(); + + + public static EventStreamUnsubscribersProvider Instance + { + get { return _instance; } + } + + public void Start(ActorSystem system, EventStream eventStream, bool debug) + { + system.ActorOf(Props.Create(eventStream, system, debug), + string.Format("EventStreamUnsubscriber-{0}", _unsubscribersCounter.IncrementAndGet())); + } + } +} diff --git a/src/core/Akka/Event/EventStream.cs b/src/core/Akka/Event/EventStream.cs index 91f6bf6cbb9..a1eb038cf3d 100644 --- a/src/core/Akka/Event/EventStream.cs +++ b/src/core/Akka/Event/EventStream.cs @@ -6,7 +6,13 @@ //----------------------------------------------------------------------- using System; +using System.Collections.Generic; +using System.Linq; using Akka.Actor; +using Akka.Actor.Internal; +using Akka.Util; +using Akka.Util.Internal; +using Akka.Util.Internal.Collections; namespace Akka.Event { @@ -25,6 +31,9 @@ public class EventStream : LoggingBus /// private readonly bool _debug; + + private readonly AtomicReference, IActorRef>> _initiallySubscribedOrUnsubscriber = + new AtomicReference, IActorRef>>(); /// /// Initializes a new instance of the class. /// @@ -50,7 +59,7 @@ public override bool Subscribe(IActorRef subscriber, Type channel) { Publish(new Debug(SimpleName(this), GetType(), "subscribing " + subscriber + " to channel " + channel)); } - + RegisterWithUnsubscriber(subscriber); return base.Subscribe(subscriber, channel); } @@ -70,7 +79,7 @@ public override bool Unsubscribe(IActorRef subscriber, Type channel) { Publish(new Debug(SimpleName(this), GetType(), "unsubscribing " + subscriber + " from channel " + channel)); } - + UnregisterIfNoMoreSubscribedChannels(subscriber); return base.Unsubscribe(subscriber, channel); } @@ -89,9 +98,83 @@ public override bool Unsubscribe(IActorRef subscriber) { Publish(new Debug(SimpleName(this), GetType(), "unsubscribing " + subscriber + " from all channels")); } - + UnregisterIfNoMoreSubscribedChannels(subscriber); return base.Unsubscribe(subscriber); } + + public void StartUnsubscriber(ActorSystem system) + { + EventStreamUnsubscribersProvider.Instance.Start(system, this, _debug); + } + + public bool InitUnsubscriber(IActorRef unsubscriber, ActorSystem system) + { + if (system == null) + { + return false; + } + return _initiallySubscribedOrUnsubscriber.Match().With>>(v => + { + if (_initiallySubscribedOrUnsubscriber.CompareAndSet(v, Either.Right(unsubscriber))) + { + if (_debug) + { + Publish(new Debug(SimpleName(this), GetType(), + string.Format("initialized unsubscriber to: {0} registering {1} initial subscribers with it", unsubscriber, v.Value.Count))); + + } + v.Value.ForEach(RegisterWithUnsubscriber); + + + } + else + { + InitUnsubscriber(unsubscriber, system); + } + + + }).With>(presentUnsubscriber => + { + if (_debug) + { + Publish(new Debug(SimpleName(this), GetType(), + string.Format("not using unsubscriber {0}, because already initialized with {1}", unsubscriber, presentUnsubscriber))); + + } + }).WasHandled; + } + + private void RegisterWithUnsubscriber(IActorRef subscriber) + { + _initiallySubscribedOrUnsubscriber.Match().With>>(v => + { + if (_initiallySubscribedOrUnsubscriber.CompareAndSet(v, + Either.Left>(v.Value.Add(subscriber)))) + { + RegisterWithUnsubscriber(subscriber); + } + + }).With>(unsubscriber => + { + unsubscriber.Value.Tell( new EventStreamUnsubscriber.Register(subscriber)); + }); + } + + private void UnregisterIfNoMoreSubscribedChannels(IActorRef subscriber) + { + _initiallySubscribedOrUnsubscriber.Match().With>>(v => + { + if (_initiallySubscribedOrUnsubscriber.CompareAndSet(v, + Either.Left>(v.Value.Remove(subscriber)))) + { + UnregisterIfNoMoreSubscribedChannels(subscriber); + } + + }).With>(unsubscriber => + { + unsubscriber.Value.Tell(new EventStreamUnsubscriber.UnregisterIfNoMoreSubscribedChannels(subscriber)); + }); + } } } From 70de5455aa3d33e6c33b032aba1fed77502c7ec6 Mon Sep 17 00:00:00 2001 From: Sean Gilliam Date: Thu, 8 Oct 2015 13:49:32 -0500 Subject: [PATCH 053/105] Renamed internal exceptions to follow .NET standard Closes #1192. This PR renames various internal exceptions to follow the .NET standard of suffixing exceptions with "Exception". Since these are internal and not public it shouldn't break the public API. --- .../Akka.Remote.TestKit.Tests/BarrierSpec.cs | 28 +++--- .../Akka.Remote.TestKit/BarrierCoordinator.cs | 86 +++++++++---------- src/core/Akka.Remote.TestKit/Controller.cs | 12 +-- src/core/Akka.Remote/Endpoint.cs | 22 ++--- src/core/Akka.Remote/EndpointManager.cs | 6 +- 5 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/core/Akka.Remote.TestKit.Tests/BarrierSpec.cs b/src/core/Akka.Remote.TestKit.Tests/BarrierSpec.cs index 0a8f7e51d80..e491c916db1 100644 --- a/src/core/Akka.Remote.TestKit.Tests/BarrierSpec.cs +++ b/src/core/Akka.Remote.TestKit.Tests/BarrierSpec.cs @@ -93,7 +93,7 @@ public void ABarrierCoordinatorMustRegisterClientsAndRemoveThem() //EventFilter(1, () => b.Tell(new BarrierCoordinator.RemoveClient(A), TestActor)); //appears to be a bug in the testfilter b.Tell(new BarrierCoordinator.RemoveClient(A)); ExpectMsg(new Failed(b, - new BarrierCoordinator.BarrierEmpty( + new BarrierCoordinator.BarrierEmptyException( new BarrierCoordinator.Data(ImmutableHashSet.Create(), "", null, null), "cannot remove RoleName(a): no client to remove"))); } @@ -208,12 +208,12 @@ public void ABarrierCoordinatorMustFailBarrierWithDisconnectingNode() //TODO: EventFilter? barrier.Tell(new Controller.ClientDisconnected(B)); var msg = ExpectMsg(); - Assert.Equal(new BarrierCoordinator.ClientLost( + Assert.Equal(new BarrierCoordinator.ClientLostException( new BarrierCoordinator.Data( ImmutableHashSet.Create(nodeA), "bar6", ImmutableHashSet.Create(a.Ref), - ((BarrierCoordinator.ClientLost) msg.Exception).BarrierData.Deadline) + ((BarrierCoordinator.ClientLostException) msg.Exception).BarrierData.Deadline) , B), msg.Exception); } @@ -234,12 +234,12 @@ public void ABarrierCoordinatorMustFailBarrierWhenDisconnectingNodeWhoAlreadyArr //TODO: Event filter? barrier.Tell(new Controller.ClientDisconnected(B)); var msg = ExpectMsg(); - Assert.Equal(new BarrierCoordinator.ClientLost( + Assert.Equal(new BarrierCoordinator.ClientLostException( new BarrierCoordinator.Data( ImmutableHashSet.Create(nodeA, nodeC), "bar7", ImmutableHashSet.Create(a.Ref), - ((BarrierCoordinator.ClientLost)msg.Exception).BarrierData.Deadline) + ((BarrierCoordinator.ClientLostException)msg.Exception).BarrierData.Deadline) , B), msg.Exception); } @@ -258,14 +258,14 @@ public void ABarrierCoordinatorMustFailWhenEnteringWrongBarrier() //TODO: Event filter b.Send(barrier, new EnterBarrier("foo", null)); var msg = ExpectMsg(); - Assert.Equal(new BarrierCoordinator.WrongBarrier( + Assert.Equal(new BarrierCoordinator.WrongBarrierException( "foo", b.Ref, new BarrierCoordinator.Data( ImmutableHashSet.Create(nodeA, nodeB), "bar8", ImmutableHashSet.Create(a.Ref), - ((BarrierCoordinator.WrongBarrier)msg.Exception).BarrierData.Deadline) + ((BarrierCoordinator.WrongBarrierException)msg.Exception).BarrierData.Deadline) ), msg.Exception); } @@ -277,12 +277,12 @@ public void ABarrierCoordinatorMustFailBarrierAfterFirstFailure() //TODO: EventFilter barrier.Tell(new BarrierCoordinator.RemoveClient(A)); var msg = ExpectMsg(); - Assert.Equal(new BarrierCoordinator.BarrierEmpty( + Assert.Equal(new BarrierCoordinator.BarrierEmptyException( new BarrierCoordinator.Data( ImmutableHashSet.Create(), "", ImmutableHashSet.Create(), - ((BarrierCoordinator.BarrierEmpty)msg.Exception).BarrierData.Deadline) + ((BarrierCoordinator.BarrierEmptyException)msg.Exception).BarrierData.Deadline) , "cannot remove RoleName(a): no client to remove"), msg.Exception); barrier.Tell(new Controller.NodeInfo(A, Address.Parse("akka://sys"), a.Ref)); a.Send(barrier, new EnterBarrier("bar9", null)); @@ -300,15 +300,15 @@ public void ABarrierCoordinatorMustFailAfterBarrierTimeout() barrier.Tell(nodeA); barrier.Tell(nodeB); a.Send(barrier, new EnterBarrier("bar10", null)); - EventFilter.Exception().ExpectOne(() => + EventFilter.Exception().ExpectOne(() => { var msg = ExpectMsg(TimeSpan.FromSeconds(7)); - Assert.Equal(new BarrierCoordinator.BarrierTimeout( + Assert.Equal(new BarrierCoordinator.BarrierTimeoutException( new BarrierCoordinator.Data( ImmutableHashSet.Create(nodeA, nodeB), "bar10", ImmutableHashSet.Create(a.Ref), - ((BarrierCoordinator.BarrierTimeout)msg.Exception).BarrierData.Deadline) + ((BarrierCoordinator.BarrierTimeoutException)msg.Exception).BarrierData.Deadline) ), msg.Exception); }); } @@ -325,12 +325,12 @@ public void ABarrierCoordinatorMustFailIfANodeRegistersTwice() //TODO: Event filter barrier.Tell(nodeB); var msg = ExpectMsg(); - Assert.Equal(new BarrierCoordinator.DuplicateNode( + Assert.Equal(new BarrierCoordinator.DuplicateNodeException( new BarrierCoordinator.Data( ImmutableHashSet.Create(nodeA), "", ImmutableHashSet.Create(), - ((BarrierCoordinator.DuplicateNode)msg.Exception).BarrierData.Deadline) + ((BarrierCoordinator.DuplicateNodeException)msg.Exception).BarrierData.Deadline) , nodeB), msg.Exception); } diff --git a/src/core/Akka.Remote.TestKit/BarrierCoordinator.cs b/src/core/Akka.Remote.TestKit/BarrierCoordinator.cs index e927b1cc6e9..86784944239 100644 --- a/src/core/Akka.Remote.TestKit/BarrierCoordinator.cs +++ b/src/core/Akka.Remote.TestKit/BarrierCoordinator.cs @@ -121,9 +121,9 @@ public override int GetHashCode() } } - public sealed class BarrierTimeout : Exception + public sealed class BarrierTimeoutException : Exception { - public BarrierTimeout(Data barrierData) + public BarrierTimeoutException(Data barrierData) : base(string.Format("timeout while waiting for barrier '{0}'", barrierData.Barrier)) { BarrierData = barrierData; @@ -131,7 +131,7 @@ public BarrierTimeout(Data barrierData) public Data BarrierData { get; private set; } - private bool Equals(BarrierTimeout other) + private bool Equals(BarrierTimeoutException other) { return Equals(BarrierData, other.BarrierData); } @@ -140,7 +140,7 @@ public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - return obj is BarrierTimeout && Equals((BarrierTimeout) obj); + return obj is BarrierTimeoutException && Equals((BarrierTimeoutException) obj); } public override int GetHashCode() @@ -148,20 +148,20 @@ public override int GetHashCode() return (BarrierData != null ? BarrierData.GetHashCode() : 0); } - public static bool operator ==(BarrierTimeout left, BarrierTimeout right) + public static bool operator ==(BarrierTimeoutException left, BarrierTimeoutException right) { return Equals(left, right); } - public static bool operator !=(BarrierTimeout left, BarrierTimeout right) + public static bool operator !=(BarrierTimeoutException left, BarrierTimeoutException right) { return !Equals(left, right); } } - public sealed class FailedBarrier : Exception + public sealed class FailedBarrierException : Exception { - public FailedBarrier(Data barrierData) + public FailedBarrierException(Data barrierData) : base(string.Format("failing barrier '{0}'", barrierData.Barrier)) { BarrierData = barrierData; @@ -169,7 +169,7 @@ public FailedBarrier(Data barrierData) public Data BarrierData { get; private set; } - private bool Equals(FailedBarrier other) + private bool Equals(FailedBarrierException other) { return Equals(BarrierData, other.BarrierData); } @@ -178,7 +178,7 @@ public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - return obj is FailedBarrier && Equals((FailedBarrier) obj); + return obj is FailedBarrierException && Equals((FailedBarrierException) obj); } public override int GetHashCode() @@ -186,20 +186,20 @@ public override int GetHashCode() return (BarrierData != null ? BarrierData.GetHashCode() : 0); } - public static bool operator ==(FailedBarrier left, FailedBarrier right) + public static bool operator ==(FailedBarrierException left, FailedBarrierException right) { return Equals(left, right); } - public static bool operator !=(FailedBarrier left, FailedBarrier right) + public static bool operator !=(FailedBarrierException left, FailedBarrierException right) { return !Equals(left, right); } } - public sealed class DuplicateNode : Exception + public sealed class DuplicateNodeException : Exception { - public DuplicateNode(Data barrierData, Controller.NodeInfo node) + public DuplicateNodeException(Data barrierData, Controller.NodeInfo node) : base(string.Format(node.ToString())) { Node = node; @@ -210,7 +210,7 @@ public DuplicateNode(Data barrierData, Controller.NodeInfo node) public Controller.NodeInfo Node { get; private set; } - private bool Equals(DuplicateNode other) + private bool Equals(DuplicateNodeException other) { return Equals(BarrierData, other.BarrierData) && Equals(Node, other.Node); } @@ -219,7 +219,7 @@ public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - return obj is DuplicateNode && Equals((DuplicateNode) obj); + return obj is DuplicateNodeException && Equals((DuplicateNodeException) obj); } public override int GetHashCode() @@ -230,20 +230,20 @@ public override int GetHashCode() } } - public static bool operator ==(DuplicateNode left, DuplicateNode right) + public static bool operator ==(DuplicateNodeException left, DuplicateNodeException right) { return Equals(left, right); } - public static bool operator !=(DuplicateNode left, DuplicateNode right) + public static bool operator !=(DuplicateNodeException left, DuplicateNodeException right) { return !Equals(left, right); } } - public sealed class WrongBarrier : Exception + public sealed class WrongBarrierException : Exception { - public WrongBarrier(string barrier, IActorRef client, Data barrierData) + public WrongBarrierException(string barrier, IActorRef client, Data barrierData) : base(string.Format("tried")) { BarrierData = barrierData; @@ -257,7 +257,7 @@ public WrongBarrier(string barrier, IActorRef client, Data barrierData) public Data BarrierData { get; private set; } - private bool Equals(WrongBarrier other) + private bool Equals(WrongBarrierException other) { return string.Equals(Barrier, other.Barrier) && Equals(Client, other.Client) && Equals(BarrierData, other.BarrierData); } @@ -266,7 +266,7 @@ public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - return obj is WrongBarrier && Equals((WrongBarrier) obj); + return obj is WrongBarrierException && Equals((WrongBarrierException) obj); } public override int GetHashCode() @@ -280,20 +280,20 @@ public override int GetHashCode() } } - public static bool operator ==(WrongBarrier left, WrongBarrier right) + public static bool operator ==(WrongBarrierException left, WrongBarrierException right) { return Equals(left, right); } - public static bool operator !=(WrongBarrier left, WrongBarrier right) + public static bool operator !=(WrongBarrierException left, WrongBarrierException right) { return !Equals(left, right); } } - public sealed class BarrierEmpty : Exception + public sealed class BarrierEmptyException : Exception { - public BarrierEmpty(Data barrierData, string message) + public BarrierEmptyException(Data barrierData, string message) : base(message) { BarrierData = barrierData; @@ -301,7 +301,7 @@ public BarrierEmpty(Data barrierData, string message) public Data BarrierData { get; private set; } - private bool Equals(BarrierEmpty other) + private bool Equals(BarrierEmptyException other) { return Equals(BarrierData, other.BarrierData); } @@ -310,7 +310,7 @@ public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - return obj is BarrierEmpty && Equals((BarrierEmpty) obj); + return obj is BarrierEmptyException && Equals((BarrierEmptyException) obj); } public override int GetHashCode() @@ -318,20 +318,20 @@ public override int GetHashCode() return (BarrierData != null ? BarrierData.GetHashCode() : 0); } - public static bool operator ==(BarrierEmpty left, BarrierEmpty right) + public static bool operator ==(BarrierEmptyException left, BarrierEmptyException right) { return Equals(left, right); } - public static bool operator !=(BarrierEmpty left, BarrierEmpty right) + public static bool operator !=(BarrierEmptyException left, BarrierEmptyException right) { return !Equals(left, right); } } - public sealed class ClientLost : Exception + public sealed class ClientLostException : Exception { - public ClientLost(Data barrierData, RoleName client) + public ClientLostException(Data barrierData, RoleName client) : base(string.Format("unannounced disconnect of {0}", client)) { Client = client; @@ -342,7 +342,7 @@ public ClientLost(Data barrierData, RoleName client) public RoleName Client { get; private set; } - private bool Equals(ClientLost other) + private bool Equals(ClientLostException other) { return Equals(BarrierData, other.BarrierData) && Equals(Client, other.Client); } @@ -351,7 +351,7 @@ public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - return obj is ClientLost && Equals((ClientLost) obj); + return obj is ClientLostException && Equals((ClientLostException) obj); } public override int GetHashCode() @@ -363,12 +363,12 @@ public override int GetHashCode() } } - public static bool operator ==(ClientLost left, ClientLost right) + public static bool operator ==(ClientLostException left, ClientLostException right) { return Equals(left, right); } - public static bool operator !=(ClientLost left, ClientLost right) + public static bool operator !=(ClientLostException left, ClientLostException right) { return !Equals(left, right); } @@ -403,7 +403,7 @@ protected void InitFSM() @event.FsmEvent.Match() .With(node => { - if (clients.Any(x => x.Name == node.Name)) throw new DuplicateNode(@event.StateData, node); + if (clients.Any(x => x.Name == node.Name)) throw new DuplicateNodeException(@event.StateData, node); nextState = Stay().Using(@event.StateData.Copy(clients.Add(node))); }) .With(disconnected => @@ -419,7 +419,7 @@ protected void InitFSM() if (client == null) nextState = Stay(); else { - throw new ClientLost(@event.StateData.Copy(clients.Remove(client), arrived:arrived.Where(x => x != client.FSM).ToImmutableHashSet()), disconnected.Name); + throw new ClientLostException(@event.StateData.Copy(clients.Remove(client), arrived:arrived.Where(x => x != client.FSM).ToImmutableHashSet()), disconnected.Name); } } }); @@ -455,7 +455,7 @@ protected void InitFSM() .With(client => { if (clients.Count == 0) - throw new BarrierEmpty(@event.StateData, + throw new BarrierEmptyException(@event.StateData, string.Format("cannot remove {0}: no client to remove", client.Name)); nextState = Stay().Using(@event.StateData.Copy(clients.Where(x => x.Name != client.Name).ToImmutableHashSet())); @@ -474,7 +474,7 @@ protected void InitFSM() .With(barrier => { if (barrier.Name != currentBarrier) - throw new WrongBarrier(barrier.Name, Sender, @event.StateData); + throw new WrongBarrierException(barrier.Name, Sender, @event.StateData); var together = clients.Any(x => x.FSM == Sender) ? @event.StateData.Arrived.Add(Sender) : @event.StateData.Arrived; @@ -503,12 +503,12 @@ protected void InitFSM() }) .With(barrier => { - if(barrier.Name != currentBarrier) throw new WrongBarrier(barrier.Name, Sender, @event.StateData); - throw new FailedBarrier(@event.StateData); + if(barrier.Name != currentBarrier) throw new WrongBarrierException(barrier.Name, Sender, @event.StateData); + throw new FailedBarrierException(@event.StateData); }) .With(() => { - throw new BarrierTimeout(@event.StateData); + throw new BarrierTimeoutException(@event.StateData); }); return nextState; diff --git a/src/core/Akka.Remote.TestKit/Controller.cs b/src/core/Akka.Remote.TestKit/Controller.cs index 40d0a901596..6c8f12cb321 100644 --- a/src/core/Akka.Remote.TestKit/Controller.cs +++ b/src/core/Akka.Remote.TestKit/Controller.cs @@ -219,21 +219,21 @@ protected override SupervisorStrategy SupervisorStrategy() { return new OneForOneStrategy(e => { - var barrierTimeout = e as BarrierCoordinator.BarrierTimeout; + var barrierTimeout = e as BarrierCoordinator.BarrierTimeoutException; if (barrierTimeout != null) return FailBarrier(barrierTimeout.BarrierData); - var failedBarrier = e as BarrierCoordinator.FailedBarrier; + var failedBarrier = e as BarrierCoordinator.FailedBarrierException; if (failedBarrier != null) return FailBarrier(failedBarrier.BarrierData); - var barrierEmpty = e as BarrierCoordinator.BarrierEmpty; + var barrierEmpty = e as BarrierCoordinator.BarrierEmptyException; if(barrierEmpty != null) return Directive.Resume; - var wrongBarrier = e as BarrierCoordinator.WrongBarrier; + var wrongBarrier = e as BarrierCoordinator.WrongBarrierException; if (wrongBarrier != null) { wrongBarrier.Client.Tell(new ToClient(new BarrierResult(wrongBarrier.Barrier, false))); return FailBarrier(wrongBarrier.BarrierData); } - var clientLost = e as BarrierCoordinator.ClientLost; + var clientLost = e as BarrierCoordinator.ClientLostException; if (clientLost != null) return FailBarrier(clientLost.BarrierData); - var duplicateNode = e as BarrierCoordinator.DuplicateNode; + var duplicateNode = e as BarrierCoordinator.DuplicateNodeException; if (duplicateNode != null) return FailBarrier(duplicateNode.BarrierData); throw new InvalidOperationException(String.Format("Cannot process exception of type {0}", e.GetType())); }); diff --git a/src/core/Akka.Remote/Endpoint.cs b/src/core/Akka.Remote/Endpoint.cs index a3d7c55d0f2..345de5743de 100644 --- a/src/core/Akka.Remote/Endpoint.cs +++ b/src/core/Akka.Remote/Endpoint.cs @@ -160,9 +160,9 @@ internal interface IAssociationProblem { } /// /// INTERNAL API /// - internal sealed class ShutDownAssociation : EndpointException, IAssociationProblem + internal sealed class ShutDownAssociationException : EndpointException, IAssociationProblem { - public ShutDownAssociation(Address localAddress, Address remoteAddress, Exception cause = null) + public ShutDownAssociationException(Address localAddress, Address remoteAddress, Exception cause = null) : base(string.Format("Shut down address: {0}", remoteAddress), cause) { RemoteAddress = remoteAddress; @@ -174,9 +174,9 @@ public ShutDownAssociation(Address localAddress, Address remoteAddress, Exceptio public Address RemoteAddress { get; private set; } } - internal sealed class InvalidAssociation : EndpointException, IAssociationProblem + internal sealed class InvalidAddressAssociationException : EndpointException, IAssociationProblem { - public InvalidAssociation(Address localAddress, Address remoteAddress, Exception cause = null) + public InvalidAddressAssociationException(Address localAddress, Address remoteAddress, Exception cause = null) : base(string.Format("Invalid address: {0}", remoteAddress), cause) { RemoteAddress = remoteAddress; @@ -191,9 +191,9 @@ public InvalidAssociation(Address localAddress, Address remoteAddress, Exception /// /// INTERNAL API /// - internal sealed class HopelessAssociation : EndpointException, IAssociationProblem + internal sealed class HopelessAssociationException : EndpointException, IAssociationProblem { - public HopelessAssociation(Address localAddress, Address remoteAddress, int? uid = null, Exception cause = null) + public HopelessAssociationException(Address localAddress, Address remoteAddress, int? uid = null, Exception cause = null) : base("Catastrophic association error.", cause) { RemoteAddress = remoteAddress; @@ -488,7 +488,7 @@ protected void Gated(object message) // In other words, this action is safe. if (!UidConfirmed && BailoutAt.IsOverdue) { - throw new InvalidAssociation(_localAddress, _remoteAddress, + throw new InvalidAddressAssociationException(_localAddress, _remoteAddress, new TimeoutException("Delivery of system messages timed out and they were dropped")); } @@ -628,7 +628,7 @@ private void TryBuffer(EndpointManager.Send s) } catch (Exception ex) { - throw new HopelessAssociation(_localAddress, _remoteAddress, Uid, ex); + throw new HopelessAssociationException(_localAddress, _remoteAddress, Uid, ex); } } @@ -913,7 +913,7 @@ private void Initializing(object message) var failure = message as Status.Failure; if (failure.Cause is InvalidAssociationException) { - PublishAndThrow(new InvalidAssociation(LocalAddress, RemoteAddress, failure.Cause), + PublishAndThrow(new InvalidAddressAssociationException(LocalAddress, RemoteAddress, failure.Cause), LogLevel.WarningLevel); } else @@ -1685,10 +1685,10 @@ private void HandleDisassociated(DisassociateInfo info) switch (info) { case DisassociateInfo.Quarantined: - throw new InvalidAssociation(LocalAddress, RemoteAddress, new InvalidAssociationException("The remote system has quarantined this system. No further associations " + + throw new InvalidAddressAssociationException(LocalAddress, RemoteAddress, new InvalidAssociationException("The remote system has quarantined this system. No further associations " + "to the remote system are possible until this system is restarted.")); case DisassociateInfo.Shutdown: - throw new ShutDownAssociation(LocalAddress, RemoteAddress, new InvalidAssociationException("The remote system terminated the association because it is shutting down.")); + throw new ShutDownAssociationException(LocalAddress, RemoteAddress, new InvalidAssociationException("The remote system terminated the association because it is shutting down.")); case DisassociateInfo.Unknown: default: Context.Stop(Self); diff --git a/src/core/Akka.Remote/EndpointManager.cs b/src/core/Akka.Remote/EndpointManager.cs index e397d37b788..9c3695f0a4d 100644 --- a/src/core/Akka.Remote/EndpointManager.cs +++ b/src/core/Akka.Remote/EndpointManager.cs @@ -340,7 +340,7 @@ protected override SupervisorStrategy SupervisorStrategy() var directive = Directive.Stop; ex.Match() - .With(ia => + .With(ia => { log.Warning("Tried to associate with unreachable remote address [{0}]. Address is now gated for {1} ms, all messages to this address will be delivered to dead letters. Reason: [{2}]", ia.RemoteAddress, settings.RetryGateClosedFor.TotalMilliseconds, ia.Message); @@ -348,7 +348,7 @@ protected override SupervisorStrategy SupervisorStrategy() AddressTerminatedTopic.Get(Context.System).Publish(new AddressTerminated(ia.RemoteAddress)); directive = Directive.Stop; }) - .With(shutdown => + .With(shutdown => { log.Debug("Remote system with address [{0}] has shut down. Address is now gated for {1}ms, all messages to this address will be delivered to dead letters.", shutdown.RemoteAddress, settings.RetryGateClosedFor.TotalMilliseconds); @@ -356,7 +356,7 @@ protected override SupervisorStrategy SupervisorStrategy() AddressTerminatedTopic.Get(Context.System).Publish(new AddressTerminated(shutdown.RemoteAddress)); directive = Directive.Stop; }) - .With(hopeless => + .With(hopeless => { if (settings.QuarantineDuration.HasValue && hopeless.Uid.HasValue) { From 44c29ccefaeca0abdc4fd1f81daf1dc27a285f66 Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Fri, 9 Oct 2015 12:37:45 +0400 Subject: [PATCH 054/105] #758 added RemoteDeploymentWatcher --- src/core/Akka.Remote/Akka.Remote.csproj | 1 + .../Akka.Remote/RemoteActorRefProvider.cs | 9 +++ .../Akka.Remote/RemoteDeploymentWatcher.cs | 55 +++++++++++++++++++ src/core/Akka.TestKit/TestActorRefBase.cs | 6 ++ src/core/Akka.TestKit/TestProbe.cs | 6 ++ src/core/Akka/Actor/ActorRef.cs | 26 ++++----- 6 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 src/core/Akka.Remote/RemoteDeploymentWatcher.cs diff --git a/src/core/Akka.Remote/Akka.Remote.csproj b/src/core/Akka.Remote/Akka.Remote.csproj index 5aeac8f2bc9..085849c5851 100644 --- a/src/core/Akka.Remote/Akka.Remote.csproj +++ b/src/core/Akka.Remote/Akka.Remote.csproj @@ -76,6 +76,7 @@ + diff --git a/src/core/Akka.Remote/RemoteActorRefProvider.cs b/src/core/Akka.Remote/RemoteActorRefProvider.cs index e5c52e4e040..b2f099efb2b 100644 --- a/src/core/Akka.Remote/RemoteActorRefProvider.cs +++ b/src/core/Akka.Remote/RemoteActorRefProvider.cs @@ -95,6 +95,7 @@ public void UnregisterTempActor(ActorPath path) private volatile IActorRef _remotingTerminator; private volatile IActorRef _remoteWatcher; + private volatile IActorRef _remoteDeploymentWatcher; public virtual void Init(ActorSystemImpl system) { @@ -111,6 +112,7 @@ public virtual void Init(ActorSystemImpl system) Transport.Start(); _remoteWatcher = CreateRemoteWatcher(system); + _remoteDeploymentWatcher = CreateRemoteDeploymentWatcher(system); } protected virtual IActorRef CreateRemoteWatcher(ActorSystemImpl system) @@ -124,6 +126,12 @@ protected virtual IActorRef CreateRemoteWatcher(ActorSystemImpl system) RemoteSettings.WatchHeartbeatExpectedResponseAfter)), "remote-watcher"); } + protected virtual IActorRef CreateRemoteDeploymentWatcher(ActorSystemImpl system) + { + return system.SystemActorOf(RemoteSettings.ConfigureDispatcher(Props.Create()), + "remote-deployment-watcher"); + } + protected DefaultFailureDetectorRegistry
CreateRemoteWatcherFailureDetector(ActorSystem system) { return new DefaultFailureDetectorRegistry
(() => @@ -358,6 +366,7 @@ public void UseActorOnNode(RemoteActorRef actor, Props props, Deploy deploy, IIn _log.Debug("[{0}] Instantiating Remote Actor [{1}]", RootPath, actor.Path); IActorRef remoteNode = ResolveActorRef(new RootActorPath(actor.Path.Address) / "remote"); remoteNode.Tell(new DaemonMsgCreate(props, deploy, actor.Path.ToSerializationFormat(), supervisor)); + _remoteDeploymentWatcher.Tell(new RemoteDeploymentWatcher.WatchRemote(actor, supervisor)); } /// diff --git a/src/core/Akka.Remote/RemoteDeploymentWatcher.cs b/src/core/Akka.Remote/RemoteDeploymentWatcher.cs new file mode 100644 index 00000000000..0ec8aa3c01b --- /dev/null +++ b/src/core/Akka.Remote/RemoteDeploymentWatcher.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Akka.Actor; +using Akka.Dispatch; +using Akka.Dispatch.SysMsg; +using Akka.Util.Internal.Collections; + +namespace Akka.Remote +{ + /// + /// Responsible for cleaning up child references of remote deployed actors when remote node + /// goes down (crash, network failure), i.e. triggered by Akka.Actor.Terminated.AddressTerminated + /// + internal class RemoteDeploymentWatcher : ActorBase, IRequiresMessageQueue + { + + private readonly IImmutableMap _supervisors = + ImmutableTreeMap.Empty; + protected override bool Receive(object message) + { + if (message == null) + { + return false; + } + return message.Match().With(w => + { + _supervisors.Add(w.Actor, w.Supervisor); + Context.Watch(w.Actor); + }).With(t => + { + IInternalActorRef supervisor; + if (_supervisors.TryGet(t.ActorRef, out supervisor)) + { + supervisor.SendSystemMessage(new DeathWatchNotification(t.ActorRef, t.ExistenceConfirmed, t.AddressTerminated), supervisor); + _supervisors.Remove(t.ActorRef); + } + }).WasHandled; + } + + internal class WatchRemote + { + public WatchRemote(IActorRef actor, IInternalActorRef supervisor) + { + Actor = actor; + Supervisor = supervisor; + } + + public IActorRef Actor { get; private set; } + public IInternalActorRef Supervisor { get; private set; } + } + } +} diff --git a/src/core/Akka.TestKit/TestActorRefBase.cs b/src/core/Akka.TestKit/TestActorRefBase.cs index 52e3ad9f401..d984dd146f7 100644 --- a/src/core/Akka.TestKit/TestActorRefBase.cs +++ b/src/core/Akka.TestKit/TestActorRefBase.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using Akka.Actor; using Akka.Dispatch; +using Akka.Dispatch.SysMsg; using Akka.TestKit.Internal; using Akka.Util; @@ -238,6 +239,11 @@ void IInternalActorRef.Suspend() { _internalRef.Suspend(); } + + public void SendSystemMessage(ISystemMessage message, IActorRef sender) + { + _internalRef .SendSystemMessage(message, sender); + } } } diff --git a/src/core/Akka.TestKit/TestProbe.cs b/src/core/Akka.TestKit/TestProbe.cs index 618495d9597..a84bc3b4c29 100644 --- a/src/core/Akka.TestKit/TestProbe.cs +++ b/src/core/Akka.TestKit/TestProbe.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using Akka.Actor; +using Akka.Dispatch.SysMsg; using Akka.Util; namespace Akka.TestKit @@ -139,6 +140,11 @@ void IInternalActorRef.Suspend() ((IInternalActorRef)TestActor).Suspend(); } + public void SendSystemMessage(ISystemMessage message, IActorRef sender) + { + ((IInternalActorRef)TestActor).SendSystemMessage(message, sender); + } + public int CompareTo(object obj) { return TestActor.CompareTo(obj); diff --git a/src/core/Akka/Actor/ActorRef.cs b/src/core/Akka/Actor/ActorRef.cs index 006b9000239..95c2ecd32e0 100644 --- a/src/core/Akka/Actor/ActorRef.cs +++ b/src/core/Akka/Actor/ActorRef.cs @@ -100,19 +100,6 @@ protected override void TellInternal(object message, IActorRef sender) } } } - - protected void SendSystemMessage(ISystemMessage message, IActorRef sender) - { - var d = message as DeathWatchNotification; - if (message is Terminate) - { - Stop(); - } - else if (d != null) - { - this.Tell(new Terminated(d.Actor, d.ExistenceConfirmed, d.AddressTerminated)); - } - } } @@ -263,6 +250,7 @@ public interface IInternalActorRef : IActorRef, IActorRefScope void Stop(); void Restart(Exception cause); void Suspend(); + void SendSystemMessage(ISystemMessage message, IActorRef sender); } public abstract class InternalActorRefBase : ActorRefBase, IInternalActorRef @@ -287,6 +275,18 @@ public abstract class InternalActorRefBase : ActorRefBase, IInternalActorRef public abstract bool IsTerminated { get; } public abstract bool IsLocal { get; } + public void SendSystemMessage(ISystemMessage message, IActorRef sender) + { + var d = message as DeathWatchNotification; + if (message is Terminate) + { + Stop(); + } + else if (d != null) + { + this.Tell(new Terminated(d.Actor, d.ExistenceConfirmed, d.AddressTerminated)); + } + } } public abstract class MinimalActorRef : InternalActorRefBase, ILocalRef From 60b5d2a318b485652e0888190aaa930fe43b1bbc Mon Sep 17 00:00:00 2001 From: Willie Ferguson Date: Mon, 12 Oct 2015 09:56:23 +0200 Subject: [PATCH 055/105] Akka IO Transport: framing support --- .../AddressConverters.cs | 6 ++- .../AkkaIOTransport.cs | 9 +++- .../ConnectionAssociation.cs | 51 +++++++++++++++---- .../TransportManager.cs | 19 ++++--- 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/AddressConverters.cs b/src/contrib/transports/Akka.Remote.AkkaIOTransport/AddressConverters.cs index 40af6fc016a..8c17c58e884 100644 --- a/src/contrib/transports/Akka.Remote.AkkaIOTransport/AddressConverters.cs +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/AddressConverters.cs @@ -21,13 +21,15 @@ public static Address ToAddress(this EndPoint endpoint, ActorSystem system) return new Address(AkkaIOTransport.Protocal, system.Name, dns.Host, dns.Port); var ip = endpoint as IPEndPoint; if (ip != null) - return new Address(AkkaIOTransport.Protocal, system.Name, "127.0.0.1", ip.Port); + return new Address(AkkaIOTransport.Protocal, system.Name, ip.Address.MapToIPv4().ToString(), ip.Port); throw new ArgumentException("endpoint"); } public static EndPoint ToEndpoint(this Address address) { - return new DnsEndPoint(address.Host, address.Port.GetValueOrDefault(9099), AddressFamily.InterNetwork); + if (address == null || address.Host == null || !address.Port.HasValue) + throw new ArgumentException("Invalid address", "address"); + return new DnsEndPoint(address.Host, address.Port.Value, AddressFamily.InterNetwork); } } } \ No newline at end of file diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/AkkaIOTransport.cs b/src/contrib/transports/Akka.Remote.AkkaIOTransport/AkkaIOTransport.cs index 236a129c82a..6f4031fe975 100644 --- a/src/contrib/transports/Akka.Remote.AkkaIOTransport/AkkaIOTransport.cs +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/AkkaIOTransport.cs @@ -22,9 +22,11 @@ class Settings public Settings(Config config) { Port = config.GetInt("port"); + Hostname = config.GetString("hostname"); } - public int Port { get; set; } + public int Port { get; private set; } + public string Hostname { get; private set; } } private readonly IActorRef _manager; @@ -37,6 +39,9 @@ public AkkaIOTransport(ActorSystem system, Config config) } public override string SchemeIdentifier { get { return Protocal; } } + + public override long MaximumPayloadBytes { get { return 128000; } } + public override bool IsResponsibleFor(Address remote) { return true; @@ -44,7 +49,7 @@ public override bool IsResponsibleFor(Address remote) public override Task>> Listen() { - return _manager.Ask>>(new Listen(_settings.Port)); + return _manager.Ask>>(new Listen(_settings.Hostname, _settings.Port)); } public override Task Associate(Address remoteAddress) { diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/ConnectionAssociation.cs b/src/contrib/transports/Akka.Remote.AkkaIOTransport/ConnectionAssociation.cs index 891d02fe7fe..a8ea5eddd72 100644 --- a/src/contrib/transports/Akka.Remote.AkkaIOTransport/ConnectionAssociation.cs +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/ConnectionAssociation.cs @@ -5,6 +5,7 @@ // //----------------------------------------------------------------------- +using System; using System.Threading.Tasks; using Akka.Actor; using Akka.IO; @@ -53,7 +54,7 @@ protected override void OnReceive(object message) if (message is IHandleEventListener) { var el = message as IHandleEventListener; - Context.Become(Receiving(el)); + Context.Become(WaitingForPrefix(el, IO.ByteString.Empty)); Stash.UnstashAll(); } else @@ -62,27 +63,57 @@ protected override void OnReceive(object message) } } - private UntypedReceive Receiving(IHandleEventListener el) + private UntypedReceive WaitingForPrefix(IHandleEventListener el, IO.ByteString buffer) { + if (buffer.Count >= 4) + { + var length = buffer.Iterator().GetInt(); + return WaitingForBody(el, buffer.Drop(4), length); + } return message => { if (message is Tcp.Received) { var received = message as Tcp.Received; - el.Notify(new InboundPayload(ByteString.CopyFrom(received.Data.ToArray()))); + Become(WaitingForPrefix(el, buffer.Concat(received.Data))); } - if (message is ByteString) - { - var bs = message as ByteString; - _connection.Tell(Tcp.Write.Create(IO.ByteString.Create(bs.ToByteArray()))); - } - else + else HandleWrite(message); + }; + } + + private UntypedReceive WaitingForBody(IHandleEventListener el, IO.ByteString buffer, int length) + { + if (buffer.Count >= length) + { + var parts = buffer.SplitAt(length); + el.Notify(new InboundPayload(ByteString.CopyFrom(parts.Item1.ToArray()))); + return WaitingForPrefix(el, parts.Item2); + } + return message => + { + if (message is Tcp.Received) { - Unhandled(message); + var received = message as Tcp.Received; + Become(WaitingForBody(el, buffer.Concat(received.Data), length)); } + else HandleWrite(message); }; } + private void HandleWrite(object message) + { + if (message is ByteString) + { + var bs = message as ByteString; + var buffer = ByteString.Unsafe.GetBuffer(bs); + var builder = new ByteStringBuilder(); + builder.PutInt(buffer.Length, ByteOrder.BigEndian); + builder.PutBytes(buffer); + _connection.Tell(Tcp.Write.Create(builder.Result())); + } + else Unhandled(message); + } + public IStash Stash { get; set; } } } \ No newline at end of file diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/TransportManager.cs b/src/contrib/transports/Akka.Remote.AkkaIOTransport/TransportManager.cs index c05c5d5f27c..768b507fe40 100644 --- a/src/contrib/transports/Akka.Remote.AkkaIOTransport/TransportManager.cs +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/TransportManager.cs @@ -26,10 +26,13 @@ public Associate(Address remoteAddress) } class Listen { - public Listen(int port) + public Listen(string hostname, int port) { + Hostname = hostname; Port = port; } + + public string Hostname { get; private set; } public int Port { get; private set; } } @@ -42,14 +45,14 @@ protected override void OnReceive(object message) { var associate = message as Associate; Context.System.Tcp().Tell(new Tcp.Connect(associate.RemoteAddress.ToEndpoint())); - BecomeStacked(WaitingForConnected(Sender)); + BecomeStacked(WaitingForConnected(Sender, associate)); } else if (message is Listen) { var listen = message as Listen; var handler = Context.ActorOf(Props.Create(() => new TransportListener())); - Context.System.Tcp().Tell(new Tcp.Bind(handler, new IPEndPoint(IPAddress.Loopback, listen.Port))); - BecomeStacked(WaitingForBound(Sender, handler)); + Context.System.Tcp().Tell(new Tcp.Bind(handler, new IPEndPoint(IPAddress.Any, listen.Port))); + BecomeStacked(WaitingForBound(Sender, handler, listen)); } else { @@ -57,7 +60,7 @@ protected override void OnReceive(object message) } } - private Receive WaitingForBound(IActorRef replyTo, IActorRef handler) + private Receive WaitingForBound(IActorRef replyTo, IActorRef handler, Listen listen) { return message => { @@ -66,7 +69,7 @@ private Receive WaitingForBound(IActorRef replyTo, IActorRef handler) var bound = message as Tcp.Bound; var promise = new TaskCompletionSource(); promise.Task.PipeTo(handler); - replyTo.Tell(Tuple.Create(bound.LocalAddress.ToAddress(Context.System), promise)); + replyTo.Tell(Tuple.Create(new Address(AkkaIOTransport.Protocal, Context.System.Name, listen.Hostname, ((IPEndPoint) bound.LocalAddress).Port), promise)); UnbecomeStacked(); Stash.Unstash(); return true; @@ -75,7 +78,7 @@ private Receive WaitingForBound(IActorRef replyTo, IActorRef handler) }; } - private Receive WaitingForConnected(IActorRef replyTo) + private Receive WaitingForConnected(IActorRef replyTo, Associate associate) { return message => { @@ -84,7 +87,7 @@ private Receive WaitingForConnected(IActorRef replyTo) var connected = message as Tcp.Connected; var handler = Context.ActorOf(Props.Create(() => new ConnectionAssociationActor(Sender))); Sender.Tell(new Tcp.Register(handler)); - replyTo.Tell(new ConnectionAssociationHandle(handler, connected.LocalAddress.ToAddress(Context.System), connected.RemoteAddress.ToAddress(Context.System))); + replyTo.Tell(new ConnectionAssociationHandle(handler, connected.LocalAddress.ToAddress(Context.System), associate.RemoteAddress)); UnbecomeStacked(); Stash.Unstash(); return true; From 6ac11f222974abde3da5bd119c707e29f5262f13 Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Tue, 13 Oct 2015 13:40:09 +0400 Subject: [PATCH 056/105] fix #1376 EventStreamUnsubscriber and RemoteDeploymentWatcher are created under `/user` --- src/core/Akka.Tests/Event/EventStreamSpec.cs | 3 ++- src/core/Akka/Event/EventBusUnsubscriber.cs | 4 ++-- src/core/Akka/Event/EventStream.cs | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/core/Akka.Tests/Event/EventStreamSpec.cs b/src/core/Akka.Tests/Event/EventStreamSpec.cs index f2425e59b0d..1a570bee5dd 100644 --- a/src/core/Akka.Tests/Event/EventStreamSpec.cs +++ b/src/core/Akka.Tests/Event/EventStreamSpec.cs @@ -12,6 +12,7 @@ using Akka.Tests.TestUtils; using System; using System.Linq; +using Akka.Util.Internal; using Xunit; namespace Akka.Tests.Event @@ -64,7 +65,7 @@ public void ManageSubscriptions() { var bus = new EventStream(true); - bus.StartUnsubscriber(Sys); + bus.StartUnsubscriber(Sys.AsInstanceOf()); bus.Subscribe(TestActor, typeof(M)); bus.Publish(new M { Value = 42 }); diff --git a/src/core/Akka/Event/EventBusUnsubscriber.cs b/src/core/Akka/Event/EventBusUnsubscriber.cs index be88f92c8a4..67ed2d212ed 100644 --- a/src/core/Akka/Event/EventBusUnsubscriber.cs +++ b/src/core/Akka/Event/EventBusUnsubscriber.cs @@ -123,9 +123,9 @@ public static EventStreamUnsubscribersProvider Instance get { return _instance; } } - public void Start(ActorSystem system, EventStream eventStream, bool debug) + public void Start(ActorSystemImpl system, EventStream eventStream, bool debug) { - system.ActorOf(Props.Create(eventStream, system, debug), + system.SystemActorOf(Props.Create(eventStream, system, debug), string.Format("EventStreamUnsubscriber-{0}", _unsubscribersCounter.IncrementAndGet())); } } diff --git a/src/core/Akka/Event/EventStream.cs b/src/core/Akka/Event/EventStream.cs index a1eb038cf3d..968867f8f85 100644 --- a/src/core/Akka/Event/EventStream.cs +++ b/src/core/Akka/Event/EventStream.cs @@ -102,7 +102,7 @@ public override bool Unsubscribe(IActorRef subscriber) return base.Unsubscribe(subscriber); } - public void StartUnsubscriber(ActorSystem system) + public void StartUnsubscriber(ActorSystemImpl system) { EventStreamUnsubscribersProvider.Instance.Start(system, this, _debug); } From d3238e5f644ac7df3dfa84bbd5326aa541dddd6a Mon Sep 17 00:00:00 2001 From: Graeme Bradbury Date: Tue, 13 Oct 2015 22:20:12 +0100 Subject: [PATCH 057/105] Tweaking the visualizer Replaced passed messages with tick images. Defaulted display to just the node facts rather than full test. (full test is still in timeline but needs to be scrolled to, or zoomed out to become visible) Simple instructions at head of page resolves #1337 --- .../Akka.MultiNodeTestRunner.Shared.csproj | 2 + ...tiNodeTestRunner.Shared.csproj.DotSettings | 2 + .../Persistence/TimelineItem.cs | 65 +++------- .../Persistence/TimelineItemFactory.cs | 49 ++++++++ .../VisualizerRuntimeTemplate.Tree.cs | 79 +++++++++--- .../Persistence/VisualizerRuntimeTemplate.cs | 113 ++++++++++++------ .../Persistence/VisualizerRuntimeTemplate.tt | 27 ++++- 7 files changed, 228 insertions(+), 109 deletions(-) create mode 100644 src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj.DotSettings create mode 100644 src/core/Akka.MultiNodeTestRunner.Shared/Persistence/TimelineItemFactory.cs diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj b/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj index 7d25c8ef0d1..11e5d887e7d 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj +++ b/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj @@ -21,6 +21,7 @@ DEBUG;TRACE prompt 4 + 5 pdbonly @@ -44,6 +45,7 @@ + diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj.DotSettings b/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj.DotSettings new file mode 100644 index 00000000000..662f95686eb --- /dev/null +++ b/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp50 \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/TimelineItem.cs b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/TimelineItem.cs index a2922e441e3..dfa3cfe44fe 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/TimelineItem.cs +++ b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/TimelineItem.cs @@ -1,69 +1,38 @@ -// ----------------------------------------------------------------------- -// -// Copyright (C) 2013-2015 Akka.NET project -// -// ----------------------------------------------------------------------- - +// ----------------------------------------------------------------------- +// +// Copyright (C) 2013-2015 Akka.NET project +// +// ----------------------------------------------------------------------- using System; namespace Akka.MultiNodeTestRunner.Shared.Persistence { public class TimelineItem { - private static readonly string eventFormat = "{{ className:'{0}', content:'{1}', start:'{2}', group:{3} }}"; + private const string EventFormat = "{{ className:'{0}', content:'{1}', start:'{2}', group:{3}, title:'{4}' }}"; - private static readonly string[] CssClasses = - { - "vis-item-one", - "vis-item-two", - "vis-item-three", - "vis-item-four", - "vis-item-five", - "vis-item-six", - "vis-item-seven", - "vis-item-eight", - "vis-item-nine", - "vis-item-ten", - "vis-item-eleven", - "vis-item-twelve", - "vis-item-thirteen", - "vis-item-fourteen", - "vis-item-fifteen" - }; + public TimelineItem(string cssClass, string content, string title, DateTime dateTime, int groupId) + { + Classname = cssClass; + Content = content; + Start = dateTime; + GroupId = groupId; + Title = title; + } public string Classname { get; private set; } public string Content { get; private set; } + public string Title { get; private set; } + public DateTime Start { get; private set; } public int GroupId { get; private set; } public string ToJavascriptString() { - return string.Format(eventFormat, Classname, Content, Start.ToString("o"), GroupId); - } - - public static TimelineItem CreateSpecMessage(string content, int groupId, long startTimeStamp) - { - return new TimelineItem - { - Classname = "timeline-message", - Content = content, - Start = new DateTime(startTimeStamp), - GroupId = groupId - }; - } - - public static TimelineItem CreateNodeFact(string content, int groupId, long startTimeStamp) - { - return new TimelineItem - { - Classname = CssClasses[startTimeStamp % 15], - Content = content, - Start = new DateTime(startTimeStamp), - GroupId = groupId - }; + return string.Format(EventFormat, Classname, Content, Start.ToString("o"), GroupId, Title); } } } \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/TimelineItemFactory.cs b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/TimelineItemFactory.cs new file mode 100644 index 00000000000..f695aa7e3c5 --- /dev/null +++ b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/TimelineItemFactory.cs @@ -0,0 +1,49 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2013-2015 Akka.NET project +// +// ----------------------------------------------------------------------- +using System; + +namespace Akka.MultiNodeTestRunner.Shared.Persistence +{ + public static class TimelineItemFactory + { + private static readonly string[] CssClasses = + { + "vis-item-one", + "vis-item-two", + "vis-item-three", + "vis-item-four", + "vis-item-five", + "vis-item-six", + "vis-item-seven", + "vis-item-eight", + "vis-item-nine", + "vis-item-ten", + "vis-item-eleven", + "vis-item-twelve", + "vis-item-thirteen", + "vis-item-fourteen", + "vis-item-fifteen" + }; + + private static readonly string passedTestContent = @"
"; + + public static TimelineItem CreateSpecMessage(string prefix, string title, int groupId, long startTimeStamp) + { + var content = title.Replace(prefix, string.Empty); + return new TimelineItem("timeline-message", content, title, new DateTime(startTimeStamp), groupId); + } + + public static TimelineItem CreateNodeFact(string prefix, string title, int groupId, long startTimeStamp) + { + var content = title.Replace(prefix, string.Empty); + if (title.EndsWith("PASS") || title.EndsWith("passed.")) + { + content = passedTestContent; + } + return new TimelineItem(CssClasses[startTimeStamp%15], content, title, new DateTime(startTimeStamp), groupId); + } + } +} \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.Tree.cs b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.Tree.cs index 59b1f809d89..7d33c529091 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.Tree.cs +++ b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.Tree.cs @@ -1,9 +1,9 @@ -// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------- // // Copyright (C) 2013-2015 Akka.NET project -// -// ----------------------------------------------------------------------- - +// +// ----------------------------------------------------------------------- +using System; using System.Collections.Generic; using System.Linq; using Akka.MultiNodeTestRunner.Shared.Reporting; @@ -21,9 +21,10 @@ public TestRunTree Tree set { _tree = value; - Prefix = LongestCommonPrefix(value.Specs - .Select(s => s.FactName) - .ToArray()); + Prefix = LongestCommonPrefix( + value.Specs + .Select(s => s.FactName) + .ToArray()); } } @@ -34,18 +35,19 @@ public string BuildSpecificationId(FactData spec) public string BuildTimelineItem(FactData spec) { - var messages = - spec.RunnerMessages - .Select(m => - TimelineItem.CreateSpecMessage(m.Message, m.NodeIndex, m.TimeStamp)); + var messages = spec.RunnerMessages + .Select(m => TimelineItemFactory.CreateSpecMessage(Prefix, m.Message, m.NodeIndex, m.TimeStamp)); var facts = - spec.NodeFacts - .SelectMany(m => - m.Value.EventStream - .Select(e => - TimelineItem.CreateNodeFact(e.Message, e.NodeIndex, e.TimeStamp))); - + spec.NodeFacts.SelectMany( + nodeFact => + nodeFact.Value.EventStream.Select( + nodeMessage => + TimelineItemFactory.CreateNodeFact( + Prefix, + nodeMessage.Message, + nodeMessage.NodeIndex, + nodeMessage.TimeStamp))); var itemStrings = messages.Concat(facts) .Select(i => i.ToJavascriptString()); @@ -56,13 +58,52 @@ public string BuildTimelineItem(FactData spec) public string BuildGroupItems(FactData spec) { var groups = spec.NodeFacts - .Select(nf => - string.Format("{{ id:{0}, content:'Node {0}' }}", nf.Value.NodeIndex)) + .Select( + nf => + string.Format("{{ id:{0}, content:'Node {0}' }}", nf.Value.NodeIndex)) .Concat(@"{ id:-1, content:'Misc' }"); return string.Join(",\r\n", groups); } + public string BuildOptions(FactData spec) + { + var events = + spec.NodeFacts.SelectMany( + nodeFact => + nodeFact.Value.EventStream + .Select( + nodeMessage => + nodeMessage.TimeStamp)) + .ToList(); + + var firstEventTimeStamp = events.Aggregate( + (aggregate, nextValue) => + aggregate > nextValue + ? nextValue + : aggregate); + + var lastEventTimeStamp = events.Aggregate( + (aggregate, nextValue) => + aggregate < nextValue + ? nextValue + : aggregate); + + + var startEventTime = new DateTime(firstEventTimeStamp); + var endDisplayTime = new DateTime(lastEventTimeStamp); + + // TODO: Find a better way of calculating additional time from message length + // The last message is the 3 second wait. Which is about half the delta from start to end in length. + var startEndDelta = (endDisplayTime - startEventTime).Ticks/2; + endDisplayTime = endDisplayTime.AddTicks(startEndDelta); + + return string.Format( + "{{ start:'{0}', end:'{1}', align:'left', clickToUse:true }}", + startEventTime.ToString("o"), + endDisplayTime.ToString("o")); + } + private static string LongestCommonPrefix(IReadOnlyList strings) { if (strings == null || strings.Count == 0) diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.cs b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.cs index 981f5000a03..01eab9aa223 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.cs +++ b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.cs @@ -1,7 +1,7 @@ // ------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version: 14.0.0.0 +// Runtime Version: 12.0.0.0 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -18,8 +18,8 @@ namespace Akka.MultiNodeTestRunner.Shared.Persistence /// Class to produce the template output ///
- #line 1 "D:\akka\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Persistence\VisualizerRuntimeTemplate.tt" - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "14.0.0.0")] + #line 1 "C:\akka\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Persistence\VisualizerRuntimeTemplate.tt" + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "12.0.0.0")] public partial class VisualizerRuntimeTemplate : VisualizerRuntimeTemplateBase { #line hidden @@ -28,52 +28,80 @@ public partial class VisualizerRuntimeTemplate : VisualizerRuntimeTemplateBase /// public virtual string TransformText() { - this.Write(@" - - - - - - "); + this.Write("\r\n<html>\r\n<head>\r\n\t<script src=\"https://cdnjs.cloudflare.com/ajax/libs/vis/4.8.1/" + + "vis.min.js\"></script>\r\n\t<link href=\"https://cdnjs.cloudflare.com/ajax/libs/vis/4" + + ".8.1/vis.min.css\" rel=\"stylesheet\" type=\"text/css\" />\r\n\t<style type=\"text/css\">\r" + + "\n\t\t.vis-item-one { border-color:#00AABF; background-color:#7FD4DF; }\r\n\t\t.vis-ite" + + "m-two { border-color:#0D9DBC; background-color:#86CEDD; }\r\n\t\t.vis-item-three { b" + + "order-color:#1B91B9; background-color:#8DC8DC; }\r\n\t\t.vis-item-four { border-colo" + + "r:#2885B6; background-color:#93C2DA; }\r\n\t\t.vis-item-five { border-color:#3679B3;" + + " background-color:#9ABCD9; }\r\n\t\t.vis-item-six { border-color:#446DB0; background" + + "-color:#A1B6D7; }\r\n\t\t.vis-item-seven { border-color:#5161AD; background-color:#A" + + "8B0D6; }\r\n\t\t.vis-item-eight { border-color:#5F55AB; background-color:#AFAAD5; }\r" + + "\n\t\t.vis-item-nine { border-color:#6D48A8; background-color:#B6A3D3; }\r\n\t\t.vis-it" + + "em-ten { border-color:#7A3CA5; background-color:#BC9DD2; }\r\n\t\t.vis-item-eleven {" + + " border-color:#8830A2; background-color:#C397D0; }\r\n\t\t.vis-item-twelve { border-" + + "color:#96249F; background-color:#CA91CF; }\r\n\t\t.vis-item-thirteen { border-color:" + + "#A3189C; background-color:#D18BCD; }\r\n\t\t.vis-item-fourteen { border-color:#B10C9" + + "9; background-color:#D885CC; }\r\n\t\t.vis-item-fifteen { border-color:#BF0097; back" + + "ground-color:#DF7FCB; }\r\n\t\tdiv.cross-image {\r\n\t\t\twidth: 16px;\r\n\t\t\thei" + + "ght: 16px;\r\n\t\t\tbackground-image: url(\'data:image/png;base64,iVBORw0KGg" + + "oAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQW" + + "RvYmUgSW1hZ2VSZWFkeXHJZTwAAAIhSURBVDjLlZPrThNRFIWJicmJz6BWiYbIkYDEG0JbBiitDQgm0P" + + "uFXqSAtKXtpE2hNuoPTXwSnwtExd6w0pl2OtPlrphKLSXhx07OZM769qy19wwAGLhM1ddC184+d18QMz" + + "oq3lfsD3LZ7Y3XbE5DL6Atzuyilc5Ciyd7IHVfgNcDYTQ2tvDr5crn6uLSvX+Av2Lk36FFpSVENDe3Ox" + + "DZu8apO5rROJDLo30+Nlvj5RnTlVNAKs1aCVFr7b4BPn6Cls21AWgEQlz2+Dl1h7IdA+i97A/geP65Wh" + + "bmrnZZ0GIJpr6OqZqYAd5/gJpKox4Mg7pD2YoC2b0/54rJQuJZdm6Izcgma4TW1WZ0h+y8BfbyJMwBmS" + + "xkjw+VObNanp5h/adwGhaTXF4NWbLj9gEONyCmUZmd10pGgf1/vwcgOT3tUQE0DdicwIod2EmSbwsKE1" + + "P8QoDkcHPJ5YESjgBJkYQpIEZ2KEB51Y6y3ojvY+P8XEDN7uKS0w0ltA7QGCWHCxSWWpwyaCeLy0BkA7" + + "UXyyg8fIzDoWHeBaDN4tQdSvAVdU1Aok+nsNTipIEVnkywo/FHatVkBoIhnFisOBoZxcGtQd4B0GYJNZ" + + "sDSiAEadUBCkstPtN3Avs2Msa+Dt9XfxoFSNYF/Bh9gP0bOqHLAm2WUF1YQskwrVFYPWkf3h1iXwbvqG" + + "fFPSGW9Eah8HSS9fuZDnS32f71m8KFY7xs/QZyu6TH2+2+FAAAAABJRU5ErkJggg==\');\r\n\t\t}\r\n\t\tdi" + + "v.tick-image {\r\n\t\t\twidth: 16px;\r\n\t\t\theight: 16px;\r\n\t\t\tbackg" + + "round-image: url(\'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf" + + "8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGr" + + "SURBVDjLvZPZLkNhFIV75zjvYm7VGFNCqoZUJ+roKUUpjRuqp61Wq0NKDMelGGqOxBSUIBKXWtWGZxAv" + + "obr8lWjChRgSF//dv9be+9trCwAI/vIE/26gXmviW5bqnb8yUK028qZjPfoPWEj4Ku5HBspgAz941IXZ" + + "eze8N1bottSo8BTZviVWrEh546EO03EXpuJOdG63otJbjBKHkEp/Ml6yNYYzpuezWL4s5VMtT8acCMQc" + + "b5XL3eJE8VgBlR7BeMGW9Z4yT9y1CeyucuhdTGDxfftaBO7G4L+zg91UocxVmCiy51NpiP3n2treUPuj" + + "L8xhOjYOzZYsQWANyRYlU4Y9Br6oHd5bDh0bCpSOixJiWx71YY09J5pM/WEbzFcDmHvwwBu2wnikg+lE" + + "j4mwBe5bC5h1OUqcwpdC60dxegRmR06TyjCF9G9z+qM2uCJmuMJmaNZaUrCSIi6X+jJIBBYtW5Cge7cd" + + "7sgoHDfDaAvKQGAlRZYc6ltJlMxX03UzlaRlBdQrzSCwksLRbOpHUSb7pcsnxCCwngvM2Rm/ugUCi84f" + + "ycr4l2t8Bb6iqTxSCgNIAAAAAElFTkSuQmCC\');\r\n\t\t}\r\n\t\tdiv.border {\r\n\t\t\tborder-style: d" + + "ashed;\r\n\t\t\tborder-width: thin;\r\n\t\t\tmargin-bottom: 5px;\r\n\t\t}\r\n\t</style>\r\n\t<title>" + + ""); - #line 28 "D:\akka\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Persistence\VisualizerRuntimeTemplate.tt" + #line 43 "C:\akka\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Persistence\VisualizerRuntimeTemplate.tt" Write(Prefix); #line default #line hidden - this.Write("\r\n\r\n\r\n\r\n"); + this.Write(@" + + +
+ Help / Instructions +

Click on a timeline to activate. Click off the timeline or press ESC to deactivate

+

Scroll up to zoom into an active timeline. Scroll down to zoom out of an active timeline

+

Click and hold to move an active timeline.

+
+"); - #line 32 "D:\akka\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Persistence\VisualizerRuntimeTemplate.tt" + #line 52 "C:\akka\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Persistence\VisualizerRuntimeTemplate.tt" foreach (var spec in Tree.Specs) { #line default #line hidden - this.Write("

"); + this.Write("
\r\n

"); - #line 33 "D:\akka\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Persistence\VisualizerRuntimeTemplate.tt" + #line 54 "C:\akka\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Persistence\VisualizerRuntimeTemplate.tt" Write(spec.FactName.Replace(Prefix, "")); #line default #line hidden this.Write("

\r\n
\r\n\r\n\r\n\r\n"); + this.Write("\t];\r\n\r\n\tvar options = "); - #line 52 "D:\akka\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Persistence\VisualizerRuntimeTemplate.tt" + #line 68 "C:\akka\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Persistence\VisualizerRuntimeTemplate.tt" + Write(BuildOptions(spec)); + + #line default + #line hidden + this.Write(";\r\n\r\n\tvar timeline = new vis.Timeline(container, items, groups, options);\r\n\r\n
\r\n"); + + #line 73 "C:\akka\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Persistence\VisualizerRuntimeTemplate.tt" } #line default @@ -119,7 +154,7 @@ public virtual string TransformText() /// /// Base class for this transformation /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "14.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "12.0.0.0")] public class VisualizerRuntimeTemplateBase { #region Fields diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.tt b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.tt index 3537d4159ab..72d9732865f 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.tt +++ b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.tt @@ -24,12 +24,33 @@ .vis-item-thirteen { border-color:#A3189C; background-color:#D18BCD; } .vis-item-fourteen { border-color:#B10C99; background-color:#D885CC; } .vis-item-fifteen { border-color:#BF0097; background-color:#DF7FCB; } + div.cross-image { + width: 16px; + height: 16px; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIhSURBVDjLlZPrThNRFIWJicmJz6BWiYbIkYDEG0JbBiitDQgm0PuFXqSAtKXtpE2hNuoPTXwSnwtExd6w0pl2OtPlrphKLSXhx07OZM769qy19wwAGLhM1ddC184+d18QMzoq3lfsD3LZ7Y3XbE5DL6Atzuyilc5Ciyd7IHVfgNcDYTQ2tvDr5crn6uLSvX+Av2Lk36FFpSVENDe3OxDZu8apO5rROJDLo30+Nlvj5RnTlVNAKs1aCVFr7b4BPn6Cls21AWgEQlz2+Dl1h7IdA+i97A/geP65WhbmrnZZ0GIJpr6OqZqYAd5/gJpKox4Mg7pD2YoC2b0/54rJQuJZdm6Izcgma4TW1WZ0h+y8BfbyJMwBmSxkjw+VObNanp5h/adwGhaTXF4NWbLj9gEONyCmUZmd10pGgf1/vwcgOT3tUQE0DdicwIod2EmSbwsKE1P8QoDkcHPJ5YESjgBJkYQpIEZ2KEB51Y6y3ojvY+P8XEDN7uKS0w0ltA7QGCWHCxSWWpwyaCeLy0BkA7UXyyg8fIzDoWHeBaDN4tQdSvAVdU1Aok+nsNTipIEVnkywo/FHatVkBoIhnFisOBoZxcGtQd4B0GYJNZsDSiAEadUBCkstPtN3Avs2Msa+Dt9XfxoFSNYF/Bh9gP0bOqHLAm2WUF1YQskwrVFYPWkf3h1iXwbvqGfFPSGW9Eah8HSS9fuZDnS32f71m8KFY7xs/QZyu6TH2+2+FAAAAABJRU5ErkJggg=='); + } + div.tick-image { + width: 16px; + height: 16px; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGrSURBVDjLvZPZLkNhFIV75zjvYm7VGFNCqoZUJ+roKUUpjRuqp61Wq0NKDMelGGqOxBSUIBKXWtWGZxAvobr8lWjChRgSF//dv9be+9trCwAI/vIE/26gXmviW5bqnb8yUK028qZjPfoPWEj4Ku5HBspgAz941IXZeze8N1bottSo8BTZviVWrEh546EO03EXpuJOdG63otJbjBKHkEp/Ml6yNYYzpuezWL4s5VMtT8acCMQcb5XL3eJE8VgBlR7BeMGW9Z4yT9y1CeyucuhdTGDxfftaBO7G4L+zg91UocxVmCiy51NpiP3n2treUPujL8xhOjYOzZYsQWANyRYlU4Y9Br6oHd5bDh0bCpSOixJiWx71YY09J5pM/WEbzFcDmHvwwBu2wnikg+lEj4mwBe5bC5h1OUqcwpdC60dxegRmR06TyjCF9G9z+qM2uCJmuMJmaNZaUrCSIi6X+jJIBBYtW5Cge7cd7sgoHDfDaAvKQGAlRZYc6ltJlMxX03UzlaRlBdQrzSCwksLRbOpHUSb7pcsnxCCwngvM2Rm/ugUCi84fycr4l2t8Bb6iqTxSCgNIAAAAAElFTkSuQmCC'); + } + div.border { + border-style: dashed; + border-width: thin; + margin-bottom: 5px; + } <# Write(Prefix); #> - +
+ Help / Instructions +

Click on a timeline to activate. Click off the timeline or press ESC to deactivate

+

Scroll up to zoom into an active timeline. Scroll down to zoom out of an active timeline

+

Click and hold to move an active timeline.

+
<# foreach (var spec in Tree.Specs) { #> +

<# Write(spec.FactName.Replace(Prefix, "")); #>

@@ -44,11 +65,11 @@ <# Write(BuildGroupItems(spec)); #> ]; - var options = {}; + var options = <# Write(BuildOptions(spec)); #>; var timeline = new vis.Timeline(container, items, groups, options); - +
<# } #> \ No newline at end of file From 36d087993774662a8325ddd6873a35612330593f Mon Sep 17 00:00:00 2001 From: Sean Gilliam Date: Tue, 13 Oct 2015 15:10:44 -0500 Subject: [PATCH 058/105] [api-docs] Documentation cleanup This PR cleans up a bit of documentation. - Fleshed out the api docs for the various Akka exceptions. - Fixed a couple of x-references. - Moved the link in the various dependency resolvers Release method to the DI Core readme. That link didn't really relate to that method. - Replaced some extraneous tags with self-closing tabs. --- .../AutoFacDependencyResolver.cs | 3 +- .../WindsorDependencyResolver.cs | 3 +- .../Akka.DI.Core/DIActorProducer.cs | 8 +- .../Akka.DI.Core/IDependencyResolver.cs | 3 +- .../Akka.DI.Core/Readme.md | 2 + .../NinjectDependencyResolver.cs | 3 +- .../StructureMapDependencyResolver.cs | 3 +- .../Akka.DI.Unity/UnityDependencyResolver.cs | 3 +- src/core/Akka.Remote.TestKit/Conductor.cs | 4 +- src/core/Akka.Remote.TestKit/Extension.cs | 2 +- .../EventFilter/IEventFilterApplier.cs | 2 +- src/core/Akka.TestKit/INoImplicitSender.cs | 4 +- src/core/Akka.TestKit/TestActorRef.cs | 2 +- src/core/Akka.TestKit/TestActors/EchoActor.cs | 12 +- src/core/Akka.TestKit/TestKitSettings.cs | 2 +- src/core/Akka/Actor/Exceptions.cs | 278 +++++++++++++++--- src/core/Akka/Dispatch/DequeBasedMailbox.cs | 7 +- .../MessageQueues/DequeWrapperMessageQueue.cs | 6 +- .../Akka/Dispatch/SysMsg/ISystemMessage.cs | 1 - .../MatchHandler/IPartialActionBuilder.cs | 2 +- .../Akka/Util/MatchHandler/MatchBuilder.cs | 4 +- 21 files changed, 267 insertions(+), 87 deletions(-) diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac/AutoFacDependencyResolver.cs b/src/contrib/dependencyInjection/Akka.DI.AutoFac/AutoFacDependencyResolver.cs index 665e12acae1..3ae95adcba3 100644 --- a/src/contrib/dependencyInjection/Akka.DI.AutoFac/AutoFacDependencyResolver.cs +++ b/src/contrib/dependencyInjection/Akka.DI.AutoFac/AutoFacDependencyResolver.cs @@ -103,8 +103,7 @@ public virtual Props Create(Type actorType) } /// - /// Signals the DI container to release it's reference to the actor. - /// HERE + /// Signals the container to release it's reference to the actor. /// /// The actor to remove from the container public void Release(ActorBase actor) diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/WindsorDependencyResolver.cs b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/WindsorDependencyResolver.cs index 1586e879354..17617ceb250 100644 --- a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/WindsorDependencyResolver.cs +++ b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/WindsorDependencyResolver.cs @@ -93,8 +93,7 @@ public virtual Props Create(Type actorType) } /// - /// Signals the DI container to release it's reference to the actor. - /// HERE + /// Signals the container to release it's reference to the actor. /// /// The actor to remove from the container public void Release(ActorBase actor) diff --git a/src/contrib/dependencyInjection/Akka.DI.Core/DIActorProducer.cs b/src/contrib/dependencyInjection/Akka.DI.Core/DIActorProducer.cs index 1a3154ac06c..acfc36da957 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Core/DIActorProducer.cs +++ b/src/contrib/dependencyInjection/Akka.DI.Core/DIActorProducer.cs @@ -47,17 +47,13 @@ public ActorBase Produce() } /// - /// This method is used to signal the DI Container that it can - /// release it's reference to the actor. HERE + /// This method is used to signal the container that it can release it's reference to the actor. /// - /// - + /// The actor to remove from the container public void Release(ActorBase actor) { dependencyResolver.Release(actor); } - - } } diff --git a/src/contrib/dependencyInjection/Akka.DI.Core/IDependencyResolver.cs b/src/contrib/dependencyInjection/Akka.DI.Core/IDependencyResolver.cs index d393f372231..2057fba07c4 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Core/IDependencyResolver.cs +++ b/src/contrib/dependencyInjection/Akka.DI.Core/IDependencyResolver.cs @@ -40,8 +40,7 @@ public interface IDependencyResolver /// The configuration object for the given actor type Props Create(Type actorType); /// - /// Signals the DI container to release it's reference to the actor. - /// HERE + /// Signals the container to release it's reference to the actor. /// /// The actor to remove from the container void Release(ActorBase actor); diff --git a/src/contrib/dependencyInjection/Akka.DI.Core/Readme.md b/src/contrib/dependencyInjection/Akka.DI.Core/Readme.md index a1d375584e1..232f49d5e20 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Core/Readme.md +++ b/src/contrib/dependencyInjection/Akka.DI.Core/Readme.md @@ -2,6 +2,8 @@ **Actor Producer Extension** library used to create Dependency Injection Container for the [Akka.NET](https://github.com/akkadotnet/akka.net) framework. +To learn more about using Dependency Injection in .NET, see [here]( http://www.amazon.com/Dependency-Injection-NET-Mark-Seemann/dp/1935182501/ref=sr_1_1?ie=UTF8&qid=1425861096&sr=8-1&keywords=mark+seemann). + #What is it? **Akka.DI.Core** is an **ActorSystem extension** library for the Akka.NET framework that provides a simple way to create an Actor Dependency Resolver that can be used as an alternative to the basic capabilities of [Props](http://getakka.net/docs/Props) when you have actors with multiple dependencies. diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject/NinjectDependencyResolver.cs b/src/contrib/dependencyInjection/Akka.DI.Ninject/NinjectDependencyResolver.cs index 37144e4f96b..28228cbc21c 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Ninject/NinjectDependencyResolver.cs +++ b/src/contrib/dependencyInjection/Akka.DI.Ninject/NinjectDependencyResolver.cs @@ -93,8 +93,7 @@ public virtual Props Create(Type actorType) } /// - /// Signals the DI container to release it's reference to the actor. - /// HERE + /// Signals the container to release it's reference to the actor. /// /// The actor to remove from the container public void Release(ActorBase actor) diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap/StructureMapDependencyResolver.cs b/src/contrib/dependencyInjection/Akka.DI.StructureMap/StructureMapDependencyResolver.cs index f7389790e34..1a29e7c39a7 100644 --- a/src/contrib/dependencyInjection/Akka.DI.StructureMap/StructureMapDependencyResolver.cs +++ b/src/contrib/dependencyInjection/Akka.DI.StructureMap/StructureMapDependencyResolver.cs @@ -95,8 +95,7 @@ public virtual Props Create(Type actorType) } /// - /// Signals the DI container to release it's reference to the actor. - /// HERE + /// Signals the container to release it's reference to the actor. /// /// The actor to remove from the container public void Release(ActorBase actor) diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity/UnityDependencyResolver.cs b/src/contrib/dependencyInjection/Akka.DI.Unity/UnityDependencyResolver.cs index 4b5dec7b066..e5d92057e13 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity/UnityDependencyResolver.cs +++ b/src/contrib/dependencyInjection/Akka.DI.Unity/UnityDependencyResolver.cs @@ -93,8 +93,7 @@ public virtual Props Create(Type actorType) } /// - /// Signals the DI container to release it's reference to the actor. - /// HERE + /// Signals the container to release it's reference to the actor. /// /// The actor to remove from the container public void Release(ActorBase actor) diff --git a/src/core/Akka.Remote.TestKit/Conductor.cs b/src/core/Akka.Remote.TestKit/Conductor.cs index 67e54829b5b..820a0196f4e 100644 --- a/src/core/Akka.Remote.TestKit/Conductor.cs +++ b/src/core/Akka.Remote.TestKit/Conductor.cs @@ -24,8 +24,8 @@ namespace Akka.Remote.TestKit /// The conductor is the one orchestrating the test: it governs the /// 's ports to which all /// Players connect, it issues commands to their - /// and provides support - /// for barriers using the . + /// and provides support + /// for barriers using the . /// All of this is bundled inside the /// partial class TestConductor //Conductor trait in JVM version diff --git a/src/core/Akka.Remote.TestKit/Extension.cs b/src/core/Akka.Remote.TestKit/Extension.cs index 107e3a58bf2..03dcc24fba0 100644 --- a/src/core/Akka.Remote.TestKit/Extension.cs +++ b/src/core/Akka.Remote.TestKit/Extension.cs @@ -15,7 +15,7 @@ namespace Akka.Remote.TestKit { /// - /// Access to the extension: + /// Access to the extension: /// /// {{{ /// var tc = TestConductor(system) diff --git a/src/core/Akka.TestKit/EventFilter/IEventFilterApplier.cs b/src/core/Akka.TestKit/EventFilter/IEventFilterApplier.cs index 574363bf0d0..41642b3aa94 100644 --- a/src/core/Akka.TestKit/EventFilter/IEventFilterApplier.cs +++ b/src/core/Akka.TestKit/EventFilter/IEventFilterApplier.cs @@ -123,7 +123,7 @@ public interface IEventFilterApplier /// /// Prevents events from being logged from now on. To allow events to be logged again, call - /// Unmute on the returned object. + /// on the returned object. /// /// /// var filter = EventFilter.Debug().Mute(); diff --git a/src/core/Akka.TestKit/INoImplicitSender.cs b/src/core/Akka.TestKit/INoImplicitSender.cs index 91e19e444a1..4f77057476a 100644 --- a/src/core/Akka.TestKit/INoImplicitSender.cs +++ b/src/core/Akka.TestKit/INoImplicitSender.cs @@ -10,8 +10,8 @@ namespace Akka.TestKit { /// - /// Normally test classes has TestActor as implicit sender. - /// So when no sender is specified when sending messages, TestActor + /// Normally test classes has as implicit sender. + /// So when no sender is specified when sending messages, /// is used. /// When a a test class implements this behavior is removed and the normal /// behavior is restored, i.e. is used as sender when no sender has been specified. diff --git a/src/core/Akka.TestKit/TestActorRef.cs b/src/core/Akka.TestKit/TestActorRef.cs index 69df849b013..2ea4d12fd1c 100644 --- a/src/core/Akka.TestKit/TestActorRef.cs +++ b/src/core/Akka.TestKit/TestActorRef.cs @@ -14,7 +14,7 @@ namespace Akka.TestKit /// overrides the dispatcher to and sets the receiveTimeout to None. Otherwise, /// it acts just like a normal ActorRef. You may retrieve a reference to the underlying actor to test internal logic. /// A can be implicitly casted to an or you can get the actual - /// from the Ref property. + /// from the property. /// /// The type of actor public class TestActorRef : TestActorRefBase where TActor : ActorBase diff --git a/src/core/Akka.TestKit/TestActors/EchoActor.cs b/src/core/Akka.TestKit/TestActors/EchoActor.cs index b0eabd81d61..679dc2c2477 100644 --- a/src/core/Akka.TestKit/TestActors/EchoActor.cs +++ b/src/core/Akka.TestKit/TestActors/EchoActor.cs @@ -11,9 +11,9 @@ namespace Akka.TestKit.TestActors { /// /// An is an actor that echoes whatever is sent to it, to the - /// TestKit's TestActor. - /// By default it also echoes back to the sender, unless the sender is the TestActor - /// (in this case the TestActor will only receive one message). + /// TestKit's . + /// By default it also echoes back to the sender, unless the sender is the + /// (in this case the will only receive one message). /// public class EchoActor : ReceiveActor { @@ -32,9 +32,9 @@ public EchoActor(TestKitBase testkit, bool echoBackToSenderAsWell=true) /// /// Returns a object that can be used to create an . /// The echoes whatever is sent to it, to the - /// TestKit's TestActor. - /// By default it also echoes back to the sender, unless the sender is the TestActor - /// (in this case the TestActor will only receive one message) or unless + /// TestKit's . + /// By default it also echoes back to the sender, unless the sender is the + /// (in this case the will only receive one message) or unless /// has been set to false. /// public static Props Props(TestKitBase testkit, bool echoBackToSenderAsWell = true) diff --git a/src/core/Akka.TestKit/TestKitSettings.cs b/src/core/Akka.TestKit/TestKitSettings.cs index 39d75e118b4..0d899cf49ba 100644 --- a/src/core/Akka.TestKit/TestKitSettings.cs +++ b/src/core/Akka.TestKit/TestKitSettings.cs @@ -64,7 +64,7 @@ public TestKitSettings(Config config) /// /// If set to true calls to testkit will be logged. - /// This is enabled by seting configuration "akka.test.testkit.debug" value to a true. + /// This is enabled by setting the configuration value "akka.test.testkit.debug" to a true. /// public bool LogTestKitCalls { get { return _logTestKitCalls; } } } diff --git a/src/core/Akka/Actor/Exceptions.cs b/src/core/Akka/Actor/Exceptions.cs index b58d9c503c1..07ed1323d8d 100644 --- a/src/core/Akka/Actor/Exceptions.cs +++ b/src/core/Akka/Actor/Exceptions.cs @@ -11,52 +11,72 @@ namespace Akka.Actor { /// - /// Class AkkaException. + /// This exception provides the base for all Akka.NET specific exceptions within the system. /// public abstract class AkkaException : Exception { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// protected AkkaException() { } /// - /// Initializes a new instance of the class with a specified error message. + /// Initializes a new instance of the class. /// /// The message that describes the error. - /// An inner exception responsible for this error. + /// The exception that is the cause of the current exception. protected AkkaException(string message, Exception cause = null) : base(message, cause) { } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected AkkaException(SerializationInfo info, StreamingContext context) : base(info, context) { } + /// + /// The exception that is the cause of the current exception. + /// protected Exception Cause { get { return InnerException; } } } /// - /// An InvalidActorNameException is thrown when the actor name is invalid + /// This exception is thrown when the actor name is invalid. /// public class InvalidActorNameException : AkkaException { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. public InvalidActorNameException(string message) : base(message) { - //Intentionally left blank } + /// + /// Initializes a new instance of the class. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception. public InvalidActorNameException(string message, Exception innerException) : base(message, innerException) { - //Intentionally left blank } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected InvalidActorNameException(SerializationInfo info, StreamingContext context) : base(info, context) { @@ -64,16 +84,24 @@ protected InvalidActorNameException(SerializationInfo info, StreamingContext con } /// - /// Thrown when an Ask operation times out + /// This exception is thrown when an Ask operation times out. /// public class AskTimeoutException : AkkaException { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. public AskTimeoutException(string message) : base(message) { - //Intentionally left blank } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected AskTimeoutException(SerializationInfo info, StreamingContext context) : base(info, context) { @@ -81,27 +109,72 @@ protected AskTimeoutException(SerializationInfo info, StreamingContext context) } /// + /// This exception is thrown when the initialization logic for an Actor fails. /// public class ActorInitializationException : AkkaException { private readonly IActorRef _actor; - protected ActorInitializationException() : base(){} - public ActorInitializationException(string message) : base(message) { } + /// + /// Initializes a new instance of the class. + /// + protected ActorInitializationException() + : base() + { + } - public ActorInitializationException(string message, Exception cause) : base(message, cause) { } - public ActorInitializationException(IActorRef actor, string message, Exception cause = null) : base(message, cause) + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public ActorInitializationException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception. + public ActorInitializationException(string message, Exception cause) + : base(message, cause) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The actor whose initialization logic failed. + /// The message that describes the error. + /// The exception that is the cause of the current exception. + public ActorInitializationException(IActorRef actor, string message, Exception cause = null) + : base(message, cause) { _actor = actor; } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected ActorInitializationException(SerializationInfo info, StreamingContext context) : base(info, context) { } + /// + /// Retrieves the actor whose initialization logic failed. + /// public IActorRef Actor { get { return _actor; } } + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// public override string ToString() { if (_actor == null) return base.ToString(); @@ -110,37 +183,68 @@ public override string ToString() } /// - /// Class LoggerInitializationException is thrown to indicate that there was a problem initializing a logger. + /// This exception is thrown when there was a problem initializing a logger. /// public class LoggerInitializationException : AkkaException { - public LoggerInitializationException() : base() { } + /// + /// Initializes a new instance of the class. + /// + public LoggerInitializationException() + : base() + { + } - public LoggerInitializationException(string message) : base(message) { } + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public LoggerInitializationException(string message) + : base(message) + { + } - public LoggerInitializationException(string message, Exception cause = null) : base(message, cause) { } + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception. + public LoggerInitializationException(string message, Exception cause = null) + : base(message, cause) + { + } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected LoggerInitializationException(SerializationInfo info, StreamingContext context) : base(info, context) { } } - - /// - /// Thrown when a message has been sent to an actor. will by default stop the actor. + /// This exception is thrown when a message has been sent to an Actor. + /// will by default stop the actor. /// public class ActorKilledException : AkkaException { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The message. - public ActorKilledException(string message) : base(message) + /// The message that describes the error. + public ActorKilledException(string message) + : base(message) { } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected ActorKilledException(SerializationInfo info, StreamingContext context) : base(info, context) { @@ -148,13 +252,25 @@ protected ActorKilledException(SerializationInfo info, StreamingContext context) } /// - /// IllegalActorStateException is thrown when a core invariant in the Actor implementation has been violated. - /// For instance, if you try to create an Actor that doesn't inherit from . + /// This exception is thrown when a core invariant in the Actor implementation has been violated. + /// For instance, if you try to create an Actor that doesn't inherit from . /// public class IllegalActorStateException : AkkaException { - public IllegalActorStateException(string msg) : base(msg) { } + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public IllegalActorStateException(string message) + : base(message) + { + } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected IllegalActorStateException(SerializationInfo info, StreamingContext context) : base(info, context) { @@ -162,12 +278,24 @@ protected IllegalActorStateException(SerializationInfo info, StreamingContext co } /// - /// IllegalActorNameException is thrown when an Actor with an invalid name is deployed our bound. + /// This exception is thrown when an Actor with an invalid name is deployed. /// public class IllegalActorNameException : AkkaException { - public IllegalActorNameException(string msg) : base(msg) { } + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public IllegalActorNameException(string message) + : base(message) + { + } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected IllegalActorNameException(SerializationInfo info, StreamingContext context) : base(info, context) { @@ -175,24 +303,36 @@ protected IllegalActorNameException(SerializationInfo info, StreamingContext con } /// - /// A DeathPactException is thrown by an Actor that receives a Terminated(someActor) message + /// This exception is thrown by an Actor that receives a Terminated(someActor) message /// that it doesn't handle itself, effectively crashing the Actor and escalating to the supervisor. /// public class DeathPactException : AkkaException { private readonly IActorRef _deadActor; + /// + /// Initializes a new instance of the class. + /// + /// The actor that has been terminated. public DeathPactException(IActorRef deadActor) : base("Monitored actor [" + deadActor + "] terminated") { _deadActor = deadActor; } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected DeathPactException(SerializationInfo info, StreamingContext context) : base(info, context) { } + /// + /// Retrieves the actor that has been terminated. + /// public IActorRef DeadActor { get { return _deadActor; } @@ -200,7 +340,12 @@ public IActorRef DeadActor } /// - /// Class PreRestartException. + /// This exception is thrown when the method fails during a restart attempt. + /// + /// + /// This exception is not propagated to the supervisor, as it originates from the already failed instance, + /// hence it is only visible as log entry on the event stream. + /// /// public class PreRestartException : AkkaException { @@ -209,8 +354,14 @@ public class PreRestartException : AkkaException private Exception exception; private object optionalMessage; - public PreRestartException(IActorRef actor, Exception restartException, Exception cause, - object optionalMessage) + /// + /// Initializes a new instance of the class. + /// + /// The actor whose hook failed. + /// The exception thrown by the within . + /// The exception which caused the restart in the first place. + /// The message which was optionally passed into . + public PreRestartException(IActorRef actor, Exception restartException, Exception cause, object optionalMessage) { Actor = actor; e = restartException; @@ -218,6 +369,11 @@ public PreRestartException(IActorRef actor, Exception restartException, Exceptio this.optionalMessage = optionalMessage; } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected PreRestartException(SerializationInfo info, StreamingContext context) : base(info, context) { @@ -225,11 +381,8 @@ protected PreRestartException(SerializationInfo info, StreamingContext context) } /// - /// A PostRestartException is thrown when constructor or postRestart() method + /// This exception is thrown when the Actor constructor or method /// fails during a restart attempt. - /// : actor is the actor whose constructor or postRestart() hook failed. - /// : cause is the exception thrown by that actor within preRestart() - /// : originalCause is the exception which caused the restart in the first place /// public class PostRestartException : ActorInitializationException { @@ -238,8 +391,8 @@ public class PostRestartException : ActorInitializationException /// /// Initializes a new instance of the class. /// - /// The actor whose constructor or postRestart() hook failed. - /// Cause is the exception thrown by that actor within preRestart(). + /// The actor whose constructor or hook failed. + /// The exception thrown by the within . /// The original cause is the exception which caused the restart in the first place. public PostRestartException(IActorRef actor, Exception cause, Exception originalCause) :base(actor,"Exception post restart (" + (originalCause == null ?"null" : originalCause.GetType().ToString()) + ")", cause) @@ -247,22 +400,40 @@ public PostRestartException(IActorRef actor, Exception cause, Exception original _originalCause = originalCause; } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected PostRestartException(SerializationInfo info, StreamingContext context) : base(info, context) { } + /// + /// Retrieves the exception which caused the restart in the first place. + /// public Exception OriginalCause { get { return _originalCause; } } } - /// - /// Class ActorNotFoundException. + /// This exception is thrown when an Actor can not be found. /// public class ActorNotFoundException : AkkaException { - public ActorNotFoundException() : base() { } - + /// + /// Initializes a new instance of the class. + /// + public ActorNotFoundException() + : base() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected ActorNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { @@ -270,19 +441,36 @@ protected ActorNotFoundException(SerializationInfo info, StreamingContext contex } /// - /// InvalidMessageException is thrown when an invalid message is sent to an Actor. + /// This exception is thrown when an invalid message is sent to an Actor. + /// + /// /// Currently only null is an invalid message. + /// /// public class InvalidMessageException : AkkaException { - public InvalidMessageException() : this("Message is null") + /// + /// Initializes a new instance of the class. + /// + public InvalidMessageException() + : this("Message is null") { } - public InvalidMessageException(string message):base(message) + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public InvalidMessageException(string message) + : base(message) { } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected InvalidMessageException(SerializationInfo info, StreamingContext context) : base(info, context) { diff --git a/src/core/Akka/Dispatch/DequeBasedMailbox.cs b/src/core/Akka/Dispatch/DequeBasedMailbox.cs index 8a564ab37ae..77f6f57b154 100644 --- a/src/core/Akka/Dispatch/DequeBasedMailbox.cs +++ b/src/core/Akka/Dispatch/DequeBasedMailbox.cs @@ -6,24 +6,25 @@ //----------------------------------------------------------------------- using Akka.Actor; +using Akka.Dispatch.MessageQueues; namespace Akka.Dispatch { /// - /// Used for instances that support double-ended queues. + /// Used for instances that support double-ended queues. /// public interface IDequeBasedMailbox { /// /// Enqueues an to the front of - /// the . Typically called during + /// the . Typically called during /// a or operation. /// /// The message that will be prepended to the queue. void EnqueueFirst(Envelope envelope); /// - /// Posts a message to the back of the + /// Posts a message to the back of the /// /// The intended recipient of the message. /// The message that will be appended to the queue. diff --git a/src/core/Akka/Dispatch/MessageQueues/DequeWrapperMessageQueue.cs b/src/core/Akka/Dispatch/MessageQueues/DequeWrapperMessageQueue.cs index 2bc7caf3732..02a3cfa149c 100644 --- a/src/core/Akka/Dispatch/MessageQueues/DequeWrapperMessageQueue.cs +++ b/src/core/Akka/Dispatch/MessageQueues/DequeWrapperMessageQueue.cs @@ -20,7 +20,7 @@ public class DequeWrapperMessageQueue : IMessageQueue, IDequeBasedMessageQueueSe private readonly Stack _prependBuffer = new Stack(); private readonly IMessageQueue _messageQueue; /// - /// Takes another as an argument - wraps + /// Takes another as an argument - wraps /// in order to provide it with prepend () semantics. /// /// @@ -47,7 +47,7 @@ public int Count } /// - /// Enqueue a message to the back of the + /// Enqueue a message to the back of the /// /// public void Enqueue(Envelope envelope) @@ -59,7 +59,7 @@ public void Enqueue(Envelope envelope) /// Attempt to dequeue a message from the front of the prepend buffer. /// /// If the prepend buffer is empty, dequeue a message from the normal - /// wrapped but this wrapper. + /// wrapped but this wrapper. /// /// The message to return, if any /// true if a message was available, false otherwise. diff --git a/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs b/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs index 54694b7a68a..b0b112b8395 100644 --- a/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs +++ b/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs @@ -19,7 +19,6 @@ namespace Akka.Dispatch.SysMsg /// /// Class ISystemMessage. /// - /// ** public interface ISystemMessage : INoSerializationVerificationNeeded { } diff --git a/src/core/Akka/Util/MatchHandler/IPartialActionBuilder.cs b/src/core/Akka/Util/MatchHandler/IPartialActionBuilder.cs index 7c6d0ddd5ef..f2086bb5bff 100644 --- a/src/core/Akka/Util/MatchHandler/IPartialActionBuilder.cs +++ b/src/core/Akka/Util/MatchHandler/IPartialActionBuilder.cs @@ -12,7 +12,7 @@ namespace Akka.Tools.MatchHandler public interface IPartialActionBuilder { /// - /// Builds the specified delegate and arguments to a PartialAction<> + /// Builds the specified delegate and arguments to a /// If the number of arguments are 0, the delegate should be a Func<,bool> /// If the number of arguments are 1, the delegate should be a Func<,T1,bool> /// ... diff --git a/src/core/Akka/Util/MatchHandler/MatchBuilder.cs b/src/core/Akka/Util/MatchHandler/MatchBuilder.cs index 34e114d75b6..de567683577 100644 --- a/src/core/Akka/Util/MatchHandler/MatchBuilder.cs +++ b/src/core/Akka/Util/MatchHandler/MatchBuilder.cs @@ -125,9 +125,9 @@ public void MatchAny(Action handler) /// - /// Builds all added handlers and returns a PartialAction<object>. + /// Builds all added handlers and returns a . /// - /// Returns a PartialAction<object> + /// Returns a public PartialAction Build() { var partialAction = _compiler.Compile(_typeHandlers, _arguments, new MatchBuilderSignature(_signature)); From 15f72c09819fd3e9ecdc6271211a3a1ced74d8f6 Mon Sep 17 00:00:00 2001 From: Bartosz Sypytkowski Date: Wed, 14 Oct 2015 19:17:22 +0200 Subject: [PATCH 059/105] removed F# hack over JSON.NET serializer --- src/core/Akka.FSharp.Tests/ApiTests.fs | 5 ++++- src/core/Akka.FSharp/FsApi.fs | 8 ++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/core/Akka.FSharp.Tests/ApiTests.fs b/src/core/Akka.FSharp.Tests/ApiTests.fs index 43cfdd425a2..f07d79b499a 100644 --- a/src/core/Akka.FSharp.Tests/ApiTests.fs +++ b/src/core/Akka.FSharp.Tests/ApiTests.fs @@ -40,13 +40,16 @@ type TestUnion2 = | D of int [] -let ``can serialize and deserialize discriminated unions over remote nodes`` () = +let ``can serialize and deserialize discriminated unions over remote nodes using wire serializer`` () = let remoteConfig port = sprintf """ akka { actor { ask-timeout = 5s provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote" + serialization-bindings { + "System.Object" = wire + } } remote { helios.tcp { diff --git a/src/core/Akka.FSharp/FsApi.fs b/src/core/Akka.FSharp/FsApi.fs index d5e35a7ac26..56eb68f26bd 100644 --- a/src/core/Akka.FSharp/FsApi.fs +++ b/src/core/Akka.FSharp/FsApi.fs @@ -307,11 +307,7 @@ module Actors = | Func f -> match msg with | :? 'Message as m -> state <- f m - | _ -> - let serializer = UntypedActor.Context.System.Serialization.FindSerializerForType typeof :?> Akka.Serialization.NewtonSoftJsonSerializer - match Serialization.tryDeserializeJObject serializer.Serializer msg with - | Some(m) -> state <- f m - | None -> x.Unhandled msg + | _ -> x.Unhandled msg | Return _ -> x.PostStop() override x.PostStop() = base.PostStop () @@ -319,7 +315,7 @@ module Actors = /// Builds an actor message handler using an actor expression syntax. - let actor = ActorBuilder() + let actor = ActorBuilder() [] module Logging = From dfb7f61026d5d0b2d23efe1dd73af820f70a1d1c Mon Sep 17 00:00:00 2001 From: Emil Ingerslev Date: Thu, 15 Oct 2015 09:18:20 +0200 Subject: [PATCH 060/105] Add optional PipeTo completion handlers Added an optional success and failure handler to PipeTo, to simplify use of Tasks. PipeTo falls back to original behavior when not supplied. --- src/core/Akka/Actor/PipeToSupport.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/core/Akka/Actor/PipeToSupport.cs b/src/core/Akka/Actor/PipeToSupport.cs index 621c1d3f679..ea1eb5cd79f 100644 --- a/src/core/Akka/Actor/PipeToSupport.cs +++ b/src/core/Akka/Actor/PipeToSupport.cs @@ -5,6 +5,7 @@ // //----------------------------------------------------------------------- +using System; using System.Threading.Tasks; namespace Akka.Actor @@ -19,15 +20,19 @@ public static class PipeToSupport /// Pipes the output of a Task directly to the 's mailbox once /// the task completes /// - public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActorRef sender = null) + public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActorRef sender = null, Func success = null, Func failure = null) { sender = sender ?? ActorRefs.NoSender; return taskToPipe.ContinueWith(tresult => { if (tresult.IsCanceled || tresult.IsFaulted) - recipient.Tell(new Status.Failure(tresult.Exception), sender); + recipient.Tell(failure != null + ? failure((Exception)tresult.Exception) + : new Status.Failure((Exception)tresult.Exception), sender); else if (tresult.IsCompleted) - recipient.Tell(tresult.Result, sender); + recipient.Tell(success != null + ? success(tresult.Result) + : tresult.Result, sender); }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); } From 326c7a2444bf8e26fc06bf04342f019262baead0 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Fri, 16 Oct 2015 10:37:16 +0100 Subject: [PATCH 061/105] Revert "Add optional PipeTo completion handlers" --- src/core/Akka/Actor/PipeToSupport.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/core/Akka/Actor/PipeToSupport.cs b/src/core/Akka/Actor/PipeToSupport.cs index ea1eb5cd79f..621c1d3f679 100644 --- a/src/core/Akka/Actor/PipeToSupport.cs +++ b/src/core/Akka/Actor/PipeToSupport.cs @@ -5,7 +5,6 @@ // //----------------------------------------------------------------------- -using System; using System.Threading.Tasks; namespace Akka.Actor @@ -20,19 +19,15 @@ public static class PipeToSupport /// Pipes the output of a Task directly to the 's mailbox once /// the task completes /// - public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActorRef sender = null, Func success = null, Func failure = null) + public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActorRef sender = null) { sender = sender ?? ActorRefs.NoSender; return taskToPipe.ContinueWith(tresult => { if (tresult.IsCanceled || tresult.IsFaulted) - recipient.Tell(failure != null - ? failure((Exception)tresult.Exception) - : new Status.Failure((Exception)tresult.Exception), sender); + recipient.Tell(new Status.Failure(tresult.Exception), sender); else if (tresult.IsCompleted) - recipient.Tell(success != null - ? success(tresult.Result) - : tresult.Result, sender); + recipient.Tell(tresult.Result, sender); }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); } From 962c0fa85963bbdafb4a1ff54e0cc54d1410e424 Mon Sep 17 00:00:00 2001 From: Emil Ingerslev Date: Thu, 15 Oct 2015 09:18:20 +0200 Subject: [PATCH 062/105] Add optional PipeTo completion handlers Added an optional success and failure handler to PipeTo, to simplify use of Tasks. PipeTo falls back to original behavior when not supplied. --- .../Akka.Tests/Actor/PipeToSupportSpec.cs | 54 +++++++++++++++++++ src/core/Akka.Tests/Akka.Tests.csproj | 1 + src/core/Akka/Actor/PipeToSupport.cs | 11 ++-- 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 src/core/Akka.Tests/Actor/PipeToSupportSpec.cs diff --git a/src/core/Akka.Tests/Actor/PipeToSupportSpec.cs b/src/core/Akka.Tests/Actor/PipeToSupportSpec.cs new file mode 100644 index 00000000000..57fc49173a3 --- /dev/null +++ b/src/core/Akka.Tests/Actor/PipeToSupportSpec.cs @@ -0,0 +1,54 @@ +using System; +using System.Threading.Tasks; +using Akka.Actor; +using Akka.Event; +using Akka.TestKit; +using Xunit; + +namespace Akka.Tests.Actor +{ + public class PipeToSupportSpec : AkkaSpec + { + private TaskCompletionSource _taskCompletionSource; + private Task _task; + + public PipeToSupportSpec() + { + _taskCompletionSource = new TaskCompletionSource(); + _task = _taskCompletionSource.Task; + Sys.EventStream.Subscribe(TestActor, typeof(DeadLetter)); + } + + [Fact] + public void Should_by_default_send_task_result_as_message() + { + _task.PipeTo(TestActor); + _taskCompletionSource.SetResult("Hello"); + ExpectMsg("Hello"); + } + + [Fact] + public void Should_by_default_send_task_exception_as_status_failure_message() + { + _task.PipeTo(TestActor); + _taskCompletionSource.SetException(new Exception("Boom")); + ExpectMsg(x => x.Cause.InnerException.Message == "Boom"); + } + + [Fact] + public void Should_use_success_handling_to_transform_task_result() + { + _task.PipeTo(TestActor, success: x => "Hello " + x); + _taskCompletionSource.SetResult("World"); + ExpectMsg("Hello World"); + } + + [Fact] + public void Should_use_failure_handling_to_transform_task_exception() + { + _task.PipeTo(TestActor, failure: e => "Such a " + e.InnerException.Message); + _taskCompletionSource.SetException(new Exception("failure...")); + ExpectMsg("Such a failure..."); + } + } +} \ No newline at end of file diff --git a/src/core/Akka.Tests/Akka.Tests.csproj b/src/core/Akka.Tests/Akka.Tests.csproj index 82649fb97c2..90ce68cabf6 100644 --- a/src/core/Akka.Tests/Akka.Tests.csproj +++ b/src/core/Akka.Tests/Akka.Tests.csproj @@ -79,6 +79,7 @@ + diff --git a/src/core/Akka/Actor/PipeToSupport.cs b/src/core/Akka/Actor/PipeToSupport.cs index 621c1d3f679..ea1eb5cd79f 100644 --- a/src/core/Akka/Actor/PipeToSupport.cs +++ b/src/core/Akka/Actor/PipeToSupport.cs @@ -5,6 +5,7 @@ // //----------------------------------------------------------------------- +using System; using System.Threading.Tasks; namespace Akka.Actor @@ -19,15 +20,19 @@ public static class PipeToSupport /// Pipes the output of a Task directly to the 's mailbox once /// the task completes /// - public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActorRef sender = null) + public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActorRef sender = null, Func success = null, Func failure = null) { sender = sender ?? ActorRefs.NoSender; return taskToPipe.ContinueWith(tresult => { if (tresult.IsCanceled || tresult.IsFaulted) - recipient.Tell(new Status.Failure(tresult.Exception), sender); + recipient.Tell(failure != null + ? failure((Exception)tresult.Exception) + : new Status.Failure((Exception)tresult.Exception), sender); else if (tresult.IsCompleted) - recipient.Tell(tresult.Result, sender); + recipient.Tell(success != null + ? success(tresult.Result) + : tresult.Result, sender); }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); } From 7cd4f799f6cd38332fe09da2162444dc4fde7447 Mon Sep 17 00:00:00 2001 From: Bartosz Sypytkowski Date: Fri, 11 Sep 2015 19:00:00 +0100 Subject: [PATCH 063/105] SQL-based persistence journals query support Motivation: One of the popular problems related to Akka.Persistence is support for aggregation of events across multiple persisted streams. Since partitioned journals are part of the Akka.Persistence plugin design, this is hard to achieve using generic tools. Instead each journal provider should be allowed to define set of querying operations, it supports. Purpose of this commit is to introduce common set of querying messages to be used by all SQL-backed journals. This has been provided in form of Query message, which can take a collection of IHint parameters, that are used to specify filters around queried events. Currently there are three of them possible: - Query by provided persistence id collection. - Query by provided message manifest - manifest is often correlated with message type, but in this case it's won't take a inheritance rules when filtering a message. - Query by message timestamp range - range can be one-side open or closed one. Range is always left-side inclusive (From) and right-side exclusive (To) in order to avoid resending the same events in sliding window scenarios. In result, journal will emit each IPersistentRepresentation containing an event wrapped in QueryResponse message. End of the transmission will be signaled by QuerySuccess message and any possible errors will cause QueryFailure to used as a reply. Additional changes: In addition this commit fixes issue with concurrent access to SQL transaction by creating a dedicated sql connection object for each request. BREAKING CHANGES: The biggest change is modification of existing SQL table schemas - 'payload_type' field has been renamed to 'manifest' and aditional 'timestamp' field has been added. Another change is a generic 'SqlJournal' class that can be used as base class for incomming journal implementations for any future specific SQL providers. Also dependent types (like 'JournalDbEngine' and 'IQueryBuilder') have been changed to make querying possible. --- .paket/paket.bootstrapper.exe | Bin 28208 -> 25600 bytes .paket/paket.targets | 6 +- paket.dependencies | 13 +- paket.lock | 329 +++--- src/.vs/config/applicationhost.config | 1030 +++++++++++++++++ src/Akka.sln | 37 +- src/benchmark/PersistenceBenchmark/App.config | 26 +- src/benchmark/PingPong/App.config | 26 +- .../Akka.DI.Unity.Tests.csproj | 2 +- .../Akka.DI.Unity/Akka.DI.Unity.csproj | 2 +- ...Akka.Persistence.Sql.Common.TestKit.csproj | 220 ++++ .../Properties/AssemblyInfo.cs | 36 + .../SqlJournalQuerySpec.cs | 147 +++ .../paket.references | 5 + .../Akka.Persistence.Sql.Common.csproj | 7 +- .../Journal/ITimestampProvider.cs | 26 + .../Journal/JournalDbEngine.cs | 280 ++--- .../Journal/QueryBuilder.cs | 7 + .../Journal/QueryMapper.cs | 26 +- .../Journal/SqlJournal.cs | 77 ++ .../Queries/Hints.cs | 176 +++ .../Queries/Query.cs | 185 +++ .../Akka.Persistence.Sql.Common/Settings.cs | 7 + ...DbSnapshotStore.cs => SqlSnapshotStore.cs} | 129 ++- .../Akka.Persistence.Sqlite.Tests.csproj | 302 +++++ .../Properties/AssemblyInfo.cs | 36 + .../SqliteJournalQuerySpec.cs | 36 + .../SqliteJournalSpec.cs | 38 + .../SqliteSnapshotStoreSpec.cs | 37 + .../paket.references | 6 + .../Akka.Persistence.Sqlite.csproj | 157 +++ .../Akka.Persistence.Sqlite.nuspec | 20 + .../ConnectionContext.cs | 36 + .../Akka.Persistence.Sqlite/DbHelper.cs | 55 + .../Akka.Persistence.Sqlite/Extension.cs | 99 ++ .../Journal/SqliteJournal.cs | 41 + .../Journal/SqliteQueryBuilder.cs | 172 +++ .../Properties/AssemblyInfo.cs | 36 + .../Akka.Persistence.Sqlite/README.md | 73 ++ .../Snapshot/QueryBuilder.cs | 103 ++ .../Snapshot/SqliteQueryMapper.cs | 39 + .../Snapshot/SqliteSnapshotStore.cs | 27 + .../Akka.Persistence.Sqlite/paket.references | 1 + .../Akka.Persistence.Sqlite/sqlite.conf | 63 + .../Akka.Remote.AkkaIOTransport.csproj | 50 +- .../Akka.Remote.AkkaIOTransport/CHANGES.txt | 99 ++ .../licenses/license.txt | 31 + .../licenses/protoc-license.txt | 36 + .../google/protobuf/csharp_options.proto | 115 ++ .../protos/google/protobuf/descriptor.proto | 533 +++++++++ .../protos/tutorial/addressbook.proto | 31 + .../Akka.Cluster.Tests.csproj | 50 +- src/core/Akka.Cluster.Tests/CHANGES.txt | 99 ++ .../Akka.Cluster.Tests/licenses/license.txt | 31 + .../licenses/protoc-license.txt | 36 + .../google/protobuf/csharp_options.proto | 115 ++ .../protos/google/protobuf/descriptor.proto | 533 +++++++++ .../protos/tutorial/addressbook.proto | 31 + src/core/Akka.Cluster/Akka.Cluster.csproj | 50 +- src/core/Akka.Cluster/CHANGES.txt | 99 ++ src/core/Akka.Cluster/licenses/license.txt | 31 + .../Akka.Cluster/licenses/protoc-license.txt | 36 + .../google/protobuf/csharp_options.proto | 115 ++ .../protos/google/protobuf/descriptor.proto | 533 +++++++++ .../protos/tutorial/addressbook.proto | 31 + src/core/Akka.FSharp.Tests/app.config | 40 +- src/core/Akka.FSharp/app.config | 26 +- .../Akka.MultiNodeTestRunner.csproj | 77 ++ src/core/Akka.MultiNodeTestRunner/App.config | 40 +- src/core/Akka.NodeTestRunner/App.config | 26 +- src/core/Akka.Persistence.FSharp/app.config | 26 +- .../Akka.Persistence.TestKit.Tests.csproj | 4 + .../LocalSnapshotStoreSpec.cs | 5 +- .../MemoryJournalSpec.cs | 5 +- .../Journal/JournalSpec.cs | 5 +- .../Akka.Persistence.TestKit/PluginSpec.cs | 12 +- .../Snapshot/SnapshotStoreSpec.cs | 5 +- .../Akka.Persistence.Tests.csproj | 50 +- src/core/Akka.Persistence.Tests/CHANGES.txt | 99 ++ .../licenses/license.txt | 31 + .../licenses/protoc-license.txt | 36 + .../google/protobuf/csharp_options.proto | 115 ++ .../protos/google/protobuf/descriptor.proto | 533 +++++++++ .../protos/tutorial/addressbook.proto | 31 + .../Akka.Persistence/Akka.Persistence.csproj | 50 +- .../Akka.Persistence/AtLeastOnceDelivery.cs | 153 ++- src/core/Akka.Persistence/CHANGES.txt | 99 ++ .../Journal/AsyncWriteJournal.cs | 8 +- .../Journal/AsyncWriteProxy.cs | 14 +- .../Akka.Persistence/Journal/WriteJournal.cs | 10 +- src/core/Akka.Persistence/JournalProtocol.cs | 582 +++++++++- src/core/Akka.Persistence/Persistence.cs | 2 +- src/core/Akka.Persistence/Persistent.cs | 46 +- src/core/Akka.Persistence/Snapshot.cs | 347 +++++- .../Snapshot/LocalSnapshotStore.cs | 6 +- .../Snapshot/SnapshotStore.cs | 33 +- .../Akka.Persistence/licenses/license.txt | 31 + .../licenses/protoc-license.txt | 36 + .../google/protobuf/csharp_options.proto | 115 ++ .../protos/google/protobuf/descriptor.proto | 533 +++++++++ .../protos/tutorial/addressbook.proto | 31 + .../Akka.Remote.TestKit.csproj | 50 +- src/core/Akka.Remote.TestKit/CHANGES.txt | 99 ++ .../Akka.Remote.TestKit/licenses/license.txt | 31 + .../licenses/protoc-license.txt | 36 + .../google/protobuf/csharp_options.proto | 115 ++ .../protos/google/protobuf/descriptor.proto | 533 +++++++++ .../protos/tutorial/addressbook.proto | 31 + .../Akka.Remote.Tests.csproj | 50 +- src/core/Akka.Remote.Tests/CHANGES.txt | 99 ++ src/core/Akka.Remote.Tests/app.config | 32 +- .../Akka.Remote.Tests/licenses/license.txt | 31 + .../licenses/protoc-license.txt | 36 + .../google/protobuf/csharp_options.proto | 115 ++ .../protos/google/protobuf/descriptor.proto | 533 +++++++++ .../protos/tutorial/addressbook.proto | 31 + src/core/Akka.Remote/Akka.Remote.csproj | 50 +- src/core/Akka.Remote/CHANGES.txt | 99 ++ src/core/Akka.Remote/app.config | 26 +- src/core/Akka.Remote/licenses/license.txt | 31 + .../Akka.Remote/licenses/protoc-license.txt | 36 + .../google/protobuf/csharp_options.proto | 115 ++ .../protos/google/protobuf/descriptor.proto | 533 +++++++++ .../protos/tutorial/addressbook.proto | 31 + src/core/Akka.Tests/App.config | 40 +- src/core/Akka/Akka.csproj | 18 +- src/core/Akka/packages.config | 5 - src/examples/Chat/ChatClient/App.config | 26 +- src/examples/Chat/ChatServer/App.config | 26 +- .../Samples.Cluster.Transformation/App.config | 26 +- .../App.config | 26 +- .../Cluster/Samples.Cluster.Simple/App.config | 26 +- src/examples/FSharp.Api/App.config | 26 +- src/examples/FSharp.Api/FSharp.Api.fsproj | 18 +- src/examples/FSharp.Deploy.Local/App.config | 26 +- src/examples/FSharp.Deploy.Remote/App.config | 26 +- src/examples/FaultTolerance/App.config | 26 +- .../HelloWorld/FSharp.HelloAkka/App.config | 26 +- src/examples/HelloWorld/HelloAkka/App.config | 26 +- .../PersistenceExample.FsApi/App.config | 26 +- src/examples/PersistenceExample/App.config | 26 +- src/examples/RemoteDeploy/System1/App.config | 26 +- src/examples/RemoteDeploy/System2/App.config | 26 +- src/examples/Routing/App.config | 26 +- src/examples/Stocks/SymbolLookup/App.config | 26 +- src/examples/TcpEchoService.Server/App.config | 26 +- src/examples/TimeServer/TimeClient/App.config | 26 +- src/examples/TimeServer/TimeServer/App.config | 26 +- 148 files changed, 12419 insertions(+), 1048 deletions(-) create mode 100644 src/.vs/config/applicationhost.config create mode 100644 src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Akka.Persistence.Sql.Common.TestKit.csproj create mode 100644 src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Properties/AssemblyInfo.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/SqlJournalQuerySpec.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/paket.references create mode 100644 src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/ITimestampProvider.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Hints.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Query.cs rename src/contrib/persistence/Akka.Persistence.Sql.Common/Snapshot/{DbSnapshotStore.cs => SqlSnapshotStore.cs} (53%) create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Properties/AssemblyInfo.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalQuerySpec.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalSpec.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteSnapshotStoreSpec.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite.Tests/paket.references create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.nuspec create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/ConnectionContext.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/DbHelper.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/Extension.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteJournal.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteQueryBuilder.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/Properties/AssemblyInfo.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/README.md create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/QueryBuilder.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteQueryMapper.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteSnapshotStore.cs create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/paket.references create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/sqlite.conf create mode 100644 src/contrib/transports/Akka.Remote.AkkaIOTransport/CHANGES.txt create mode 100644 src/contrib/transports/Akka.Remote.AkkaIOTransport/licenses/license.txt create mode 100644 src/contrib/transports/Akka.Remote.AkkaIOTransport/licenses/protoc-license.txt create mode 100644 src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/google/protobuf/csharp_options.proto create mode 100644 src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/google/protobuf/descriptor.proto create mode 100644 src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/tutorial/addressbook.proto create mode 100644 src/core/Akka.Cluster.Tests/CHANGES.txt create mode 100644 src/core/Akka.Cluster.Tests/licenses/license.txt create mode 100644 src/core/Akka.Cluster.Tests/licenses/protoc-license.txt create mode 100644 src/core/Akka.Cluster.Tests/protos/google/protobuf/csharp_options.proto create mode 100644 src/core/Akka.Cluster.Tests/protos/google/protobuf/descriptor.proto create mode 100644 src/core/Akka.Cluster.Tests/protos/tutorial/addressbook.proto create mode 100644 src/core/Akka.Cluster/CHANGES.txt create mode 100644 src/core/Akka.Cluster/licenses/license.txt create mode 100644 src/core/Akka.Cluster/licenses/protoc-license.txt create mode 100644 src/core/Akka.Cluster/protos/google/protobuf/csharp_options.proto create mode 100644 src/core/Akka.Cluster/protos/google/protobuf/descriptor.proto create mode 100644 src/core/Akka.Cluster/protos/tutorial/addressbook.proto create mode 100644 src/core/Akka.Persistence.Tests/CHANGES.txt create mode 100644 src/core/Akka.Persistence.Tests/licenses/license.txt create mode 100644 src/core/Akka.Persistence.Tests/licenses/protoc-license.txt create mode 100644 src/core/Akka.Persistence.Tests/protos/google/protobuf/csharp_options.proto create mode 100644 src/core/Akka.Persistence.Tests/protos/google/protobuf/descriptor.proto create mode 100644 src/core/Akka.Persistence.Tests/protos/tutorial/addressbook.proto create mode 100644 src/core/Akka.Persistence/CHANGES.txt create mode 100644 src/core/Akka.Persistence/licenses/license.txt create mode 100644 src/core/Akka.Persistence/licenses/protoc-license.txt create mode 100644 src/core/Akka.Persistence/protos/google/protobuf/csharp_options.proto create mode 100644 src/core/Akka.Persistence/protos/google/protobuf/descriptor.proto create mode 100644 src/core/Akka.Persistence/protos/tutorial/addressbook.proto create mode 100644 src/core/Akka.Remote.TestKit/CHANGES.txt create mode 100644 src/core/Akka.Remote.TestKit/licenses/license.txt create mode 100644 src/core/Akka.Remote.TestKit/licenses/protoc-license.txt create mode 100644 src/core/Akka.Remote.TestKit/protos/google/protobuf/csharp_options.proto create mode 100644 src/core/Akka.Remote.TestKit/protos/google/protobuf/descriptor.proto create mode 100644 src/core/Akka.Remote.TestKit/protos/tutorial/addressbook.proto create mode 100644 src/core/Akka.Remote.Tests/CHANGES.txt create mode 100644 src/core/Akka.Remote.Tests/licenses/license.txt create mode 100644 src/core/Akka.Remote.Tests/licenses/protoc-license.txt create mode 100644 src/core/Akka.Remote.Tests/protos/google/protobuf/csharp_options.proto create mode 100644 src/core/Akka.Remote.Tests/protos/google/protobuf/descriptor.proto create mode 100644 src/core/Akka.Remote.Tests/protos/tutorial/addressbook.proto create mode 100644 src/core/Akka.Remote/CHANGES.txt create mode 100644 src/core/Akka.Remote/licenses/license.txt create mode 100644 src/core/Akka.Remote/licenses/protoc-license.txt create mode 100644 src/core/Akka.Remote/protos/google/protobuf/csharp_options.proto create mode 100644 src/core/Akka.Remote/protos/google/protobuf/descriptor.proto create mode 100644 src/core/Akka.Remote/protos/tutorial/addressbook.proto delete mode 100644 src/core/Akka/packages.config diff --git a/.paket/paket.bootstrapper.exe b/.paket/paket.bootstrapper.exe index ff2fa7f4fd127f48440a9493019cd5686b842581..8d1cd1875aef2c564dd2cad24bdb855bc4e209cf 100644 GIT binary patch literal 25600 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�u{G82x<%Ri5Xwv5P;oLu>K%x zvsCD^t>p!lvVCIxWNu1$Ct$By9Jw!S^-l4~@zMw#0quZaIW<$>6q&3Mq11LgwBbyM z+UzHP?U}hP%J9mP!mF8+>+tr0r%M+8%mPz(allrtkp2{yY!}Bv20rHA!=62ALh?9r z%&092Pc}80CuK~O2mHi6EbXevueM z6weeb8(;^|H|#$4{Gn{}EttNs{C#`rYvikJYrT!IN~X+__sLV|H~sn8*MHUh*5N0A z_3I@cUrT|MriG0ZX+a?IIFqqpNKaf9!)q#f3~zYM5619rM`GfE`N1$>FT^K47*6T) z=KNIUuV&bFP0!mDLA`sCMS5)ceL+hk>5jG5f- z#1nY2A>N7Bw0I{P)?(q1k?2WuCwfp0qz5mS=zN7-qFWU71c6R`o9p9(mrz(e0T>}I zRs{oN^Nsk#cLO19ek`O&?r69w6o^67&547k6N}Bm%Pe{Wf+uz(h5!3dX!nM|xM3I220yS^a)3>gcs`&Yxmu~-rf zm&QOz;SYSV_rn+tJr)kbZS0^(C;+u^*CD6AHx=Rw9cyNQ{QX z&+rgj|LXu?*1*rtFm8!aIN3n3gu}Ro`3i5s6to+zh6;RGOCl?Nd;q2(x_Ioekx($P z84gUWW(JH>K8yv>edVRZYCRG%MF?tO0t#gCVjM*0s&K);2~UgZ_{&(a#Ac?^6#v_W^ zHgVsq_{6>VnI?jL;=UNdR5uleJ$sNx95Ajy+B90`Bs)KWJDkhy-Xdk8c`vsMtefNsA*BamsWz zrnbg&JcVhgB~pwo6?7@1X+hJBO2$O=BLO5*iKPiJp`Q~C<|I(e!W5Dl(hSnQBn8fo zF`XNPg^^SsG0q9#j8Zg?Ixsn$G7{s=#vt=HDJ`Z(~biyf8lc@^b^ky9j)<{!uGHSuCQuk^jO)-4& z*U{h>21^;F8O#Ge%*dK>+EW@Ge@foi9Bc+IQ5kPq`Z8bdj5{ z(d_BZP}=w5aTzvXjd+uCdMSPYuTfC=L_>Hru`^XruWY1-tpY#O$q$XE@NhLVVmT>1 z@=mq)cJE7_!sE`AJ60&*zN>J1$8eXI*Ht=|3A4fsj^)o?_tzEtGB;>Sv{{_Y<>^xPGjHh;|c+hbQ2x5T+l*SbSP zcs_DS+;Rwi!&hOG9!(v>P5DFKyJ&|B(;ti%h6m}JXvhD2kMWdGO}_en$5(L=Z?*9p z!ji|a^0u92wGZcVQuwZ{lvg(gh~7GZUyWm)`=3XR)j+SuA?xsz_~tFY*IW5f zzu8ppq^efRrCmVzOeg41IIC>yd>Ce$8em|IR4f2tN53`t6II!@cuJXvBjK+&0r{*IHAHaOsUK}O1qdxN{x5~$E z*3UiyeSg@+jYPabYjZ6d+ypUwM&#nLFyx z*DmjJ`+l8#tmXD9w--$J;tg$0Mv`wkIN~9^4}re0mq~i*-($J_{V(q>6y%X!p>HSZ zjzC9FMhw3tk{*rVCI;@}!6zK0-0p6V&(XlrzTKt6Cm}xMA_G@y-Gs$f`Fv+VQsb;^j(1 z(ZM5ae%av_+Ou-8)I-}Y9)RI>$Z?Mb$5HRBT6iLrJ&8wKFRj=%S%px!20F> j2&tdSmk0j8vHzMLD5$^n^DFsv^MB1Q{I}J=zX$#wXZ}9) literal 28208 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 diff --git a/.paket/paket.targets b/.paket/paket.targets index 2812c681323..cef47deebcd 100644 --- a/.paket/paket.targets +++ b/.paket/paket.targets @@ -7,15 +7,17 @@ true $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)..\ + /Library/Frameworks/Mono.framework/Commands/mono + mono $(PaketToolsPath)paket.exe $(PaketToolsPath)paket.bootstrapper.exe "$(PaketExePath)" - mono --runtime=v4.0.30319 "$(PaketExePath)" + $(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)" "$(PaketBootStrapperExePath)" - mono --runtime=v4.0.30319 $(PaketBootStrapperExePath) + $(MonoPath) --runtime=v4.0.30319 $(PaketBootStrapperExePath) $(MSBuildProjectDirectory)\paket.references $(MSBuildProjectFullPath).paket.references diff --git a/paket.dependencies b/paket.dependencies index 9cb63a581b3..1fd178c8cd2 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -5,19 +5,26 @@ nuget Castle.Windsor nuget faker-csharp nuget FsPickler >= 1.2 nuget FSPowerPack.Linq.Community -nuget Google.ProtocolBuffers +nuget Google.ProtocolBuffers 2.4.1.521 framework: >= net45 nuget Google.ProtocolBuffersLite nuget Helios +nuget Nuget.CommandLine nuget System.Collections.Immutable -nuget Newtonsoft.Json +nuget Newtonsoft.Json 7.0.1 nuget Ninject nuget NLog nuget qdfeed nuget Serilog nuget slf4net nuget structuremap +nuget System.Data.SQLite.Core nuget Unity -nuget Wire +nuget Wire 0.0.4 framework: >= net45 +nuget xunit 2.0.0 framework: >= net45 +nuget xunit.abstractions 2.0.0 framework: >= net45 +nuget xunit.assert 2.0.0 framework: >= net45 +nuget xunit.core 2.0.0 framework: >= net45 +nuget xunit.extensibility.core 2.0.0 framework: >= net45 group Test source https://www.nuget.org/api/v2/ diff --git a/paket.lock b/paket.lock index 03211650f75..82eed47eb2c 100644 --- a/paket.lock +++ b/paket.lock @@ -5,93 +5,104 @@ NUGET Castle.Core (3.3.3) Castle.Windsor (3.3.0) Castle.Core (>= 3.3.0) - CommonServiceLocator (1.3.0) - framework: monoandroid, winv4.5 + CommonServiceLocator (1.3.0) faker-csharp (1.2.0) FsPickler (1.4.0) FSPowerPack.Core.Community (3.0.0) FSPowerPack.Linq.Community (3.0.0) FSPowerPack.Core.Community - Google.ProtocolBuffers (2.4.1.555) + Google.ProtocolBuffers (2.4.1.521) - framework: >= net45 Google.ProtocolBuffersLite (2.4.1.555) Helios (1.4.1) Newtonsoft.Json (7.0.1) Ninject (3.2.2) NLog (4.1.2) + NuGet.CommandLine (2.8.6) qdfeed (1.1.0) Serilog (1.5.11) slf4net (0.1.32.1) structuremap (3.1.6.186) System.Collections (4.0.10) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 - System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 - System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 - System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.0) + System.Resources.ResourceManager (>= 4.0.0) + System.Runtime (>= 4.0.0) + System.Runtime (>= 4.0.20) + System.Runtime.Extensions (>= 4.0.0) + System.Threading (>= 4.0.0) System.Collections.Immutable (1.1.37) - System.Collections (>= 4.0.0) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - framework: dnxcore50 - System.Linq (>= 4.0.0) - framework: dnxcore50 - System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 - System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Collections (>= 4.0.0) + System.Diagnostics.Debug (>= 4.0.0) + System.Globalization (>= 4.0.0) + System.Linq (>= 4.0.0) + System.Resources.ResourceManager (>= 4.0.0) + System.Runtime (>= 4.0.0) + System.Runtime.Extensions (>= 4.0.0) + System.Threading (>= 4.0.0) + System.Data.SQLite.Core (1.0.98.1) System.Diagnostics.Debug (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) System.Globalization (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) System.IO (4.0.10) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 - System.Text.Encoding (>= 4.0.0) - framework: dnxcore50 - System.Text.Encoding (>= 4.0.10) - framework: dnxcore50 - System.Text.Encoding.Extensions (>= 4.0.0) - framework: dnxcore50 - System.Threading (>= 4.0.0) - framework: dnxcore50 - System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + System.Globalization (>= 4.0.0) + System.Runtime (>= 4.0.20) + System.Text.Encoding (>= 4.0.0) + System.Text.Encoding (>= 4.0.10) + System.Text.Encoding.Extensions (>= 4.0.0) + System.Threading (>= 4.0.0) + System.Threading.Tasks (>= 4.0.0) System.Linq (4.0.0) - framework: dnxcore50 - System.Collections (>= 4.0.10) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.10) - framework: dnxcore50 - System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 - System.Runtime.Extensions (>= 4.0.10) - framework: dnxcore50 + System.Collections (>= 4.0.10) + System.Diagnostics.Debug (>= 4.0.10) + System.Resources.ResourceManager (>= 4.0.0) + System.Runtime (>= 4.0.20) + System.Runtime.Extensions (>= 4.0.10) System.Private.Uri (4.0.0) - framework: dnxcore50 System.Reflection (4.0.10) - framework: dnxcore50 - System.IO (>= 4.0.0) - framework: dnxcore50 - System.Reflection.Primitives (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.IO (>= 4.0.0) + System.Reflection.Primitives (>= 4.0.0) + System.Runtime (>= 4.0.20) System.Reflection.Primitives (4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) + System.Threading (>= 4.0.0) System.Resources.ResourceManager (4.0.0) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - framework: dnxcore50 - System.Reflection (>= 4.0.0) - framework: dnxcore50 - System.Reflection (>= 4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Globalization (>= 4.0.0) + System.Reflection (>= 4.0.0) + System.Reflection (>= 4.0.10) + System.Runtime (>= 4.0.0) + System.Runtime (>= 4.0.20) System.Runtime (4.0.20) - framework: dnxcore50 - System.Private.Uri (>= 4.0.0) - framework: dnxcore50 + System.Private.Uri (>= 4.0.0) System.Runtime.Extensions (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Runtime (>= 4.0.20) System.Text.Encoding (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) System.Text.Encoding.Extensions (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Text.Encoding (>= 4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) + System.Text.Encoding (>= 4.0.10) System.Threading (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) + System.Threading.Tasks (>= 4.0.0) System.Threading.Tasks (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - Unity (4.0.0) - CommonServiceLocator (>= 1.3.0) - framework: monoandroid, winv4.5, wpv8.1 - Wire (0.0.4) + System.Runtime (>= 4.0.0) + Unity (4.0.1) + CommonServiceLocator (>= 1.3.0) + Wire (0.0.4) - framework: >= net45 + xunit (2.0.0) - framework: >= net45 + xunit.assert (2.0.0) + xunit.core (2.0.0) + xunit.abstractions (2.0.0) - framework: >= net45 + xunit.assert (2.0.0) - framework: >= net45 + xunit.core (2.0.0) - framework: >= net45 + xunit.extensibility.core (2.0.0) + xunit.extensibility.core (2.0.0) - framework: >= net45 + xunit.abstractions (2.0.0) GROUP Build NUGET remote: https://nuget.org/api/v2 specs: - FAKE (4.4.6) + FAKE (4.5.2) NuGet.CommandLine (2.8.6) SourceLink.Fake (1.1.0) @@ -115,141 +126,141 @@ NUGET NUnit (2.6.4) NUnit.Runners (2.6.4) System.Collections (4.0.10) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 - System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 - System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 - System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.0) + System.Resources.ResourceManager (>= 4.0.0) + System.Runtime (>= 4.0.0) + System.Runtime (>= 4.0.20) + System.Runtime.Extensions (>= 4.0.0) + System.Threading (>= 4.0.0) System.Diagnostics.Contracts (4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) System.Diagnostics.Debug (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) System.Globalization (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) System.IO (4.0.10) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 - System.Text.Encoding (>= 4.0.0) - framework: dnxcore50 - System.Text.Encoding (>= 4.0.10) - framework: dnxcore50 - System.Text.Encoding.Extensions (>= 4.0.0) - framework: dnxcore50 - System.Threading (>= 4.0.0) - framework: dnxcore50 - System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + System.Globalization (>= 4.0.0) + System.Runtime (>= 4.0.20) + System.Text.Encoding (>= 4.0.0) + System.Text.Encoding (>= 4.0.10) + System.Text.Encoding.Extensions (>= 4.0.0) + System.Threading (>= 4.0.0) + System.Threading.Tasks (>= 4.0.0) System.Linq (4.0.0) - framework: dnxcore50 - System.Collections (>= 4.0.10) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.10) - framework: dnxcore50 - System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 - System.Runtime.Extensions (>= 4.0.10) - framework: dnxcore50 + System.Collections (>= 4.0.10) + System.Diagnostics.Debug (>= 4.0.10) + System.Resources.ResourceManager (>= 4.0.0) + System.Runtime (>= 4.0.20) + System.Runtime.Extensions (>= 4.0.10) System.ObjectModel (4.0.10) - framework: dnxcore50 - System.Collections (>= 4.0.10) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.10) - framework: dnxcore50 - System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 - System.Threading (>= 4.0.10) - framework: dnxcore50 + System.Collections (>= 4.0.10) + System.Diagnostics.Debug (>= 4.0.10) + System.Resources.ResourceManager (>= 4.0.0) + System.Runtime (>= 4.0.20) + System.Threading (>= 4.0.10) System.Private.Uri (4.0.0) - framework: dnxcore50 System.Reflection (4.0.10) - framework: dnxcore50 - System.IO (>= 4.0.0) - framework: dnxcore50 - System.Reflection.Primitives (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.IO (>= 4.0.0) + System.Reflection.Primitives (>= 4.0.0) + System.Runtime (>= 4.0.20) System.Reflection.Extensions (4.0.0) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.10) - framework: dnxcore50 - System.Reflection (>= 4.0.0) - framework: dnxcore50 - System.Reflection (>= 4.0.10) - framework: dnxcore50 - System.Reflection.Primitives (>= 4.0.0) - framework: dnxcore50 - System.Reflection.TypeExtensions (>= 4.0.0) - framework: dnxcore50 - System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 - System.Runtime.Extensions (>= 4.0.10) - framework: dnxcore50 + System.Diagnostics.Debug (>= 4.0.10) + System.Reflection (>= 4.0.0) + System.Reflection (>= 4.0.10) + System.Reflection.Primitives (>= 4.0.0) + System.Reflection.TypeExtensions (>= 4.0.0) + System.Resources.ResourceManager (>= 4.0.0) + System.Runtime (>= 4.0.0) + System.Runtime (>= 4.0.20) + System.Runtime.Extensions (>= 4.0.10) System.Reflection.Primitives (4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Threading (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) + System.Threading (>= 4.0.0) System.Reflection.TypeExtensions (4.0.0) - framework: dnxcore50 - System.Diagnostics.Contracts (>= 4.0.0) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.10) - framework: dnxcore50 - System.Linq (>= 4.0.0) - framework: dnxcore50 - System.Reflection (>= 4.0.0) - framework: dnxcore50 - System.Reflection (>= 4.0.10) - framework: dnxcore50 - System.Reflection.Primitives (>= 4.0.0) - framework: dnxcore50 - System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 - System.Runtime.Extensions (>= 4.0.10) - framework: dnxcore50 + System.Diagnostics.Contracts (>= 4.0.0) + System.Diagnostics.Debug (>= 4.0.10) + System.Linq (>= 4.0.0) + System.Reflection (>= 4.0.0) + System.Reflection (>= 4.0.10) + System.Reflection.Primitives (>= 4.0.0) + System.Resources.ResourceManager (>= 4.0.0) + System.Runtime (>= 4.0.0) + System.Runtime (>= 4.0.20) + System.Runtime.Extensions (>= 4.0.10) System.Resources.ResourceManager (4.0.0) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - framework: dnxcore50 - System.Reflection (>= 4.0.0) - framework: dnxcore50 - System.Reflection (>= 4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Globalization (>= 4.0.0) + System.Reflection (>= 4.0.0) + System.Reflection (>= 4.0.10) + System.Runtime (>= 4.0.0) + System.Runtime (>= 4.0.20) System.Runtime (4.0.20) - framework: dnxcore50 - System.Private.Uri (>= 4.0.0) - framework: dnxcore50 + System.Private.Uri (>= 4.0.0) System.Runtime.Extensions (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 + System.Runtime (>= 4.0.20) System.Text.Encoding (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) System.Text.Encoding.Extensions (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Text.Encoding (>= 4.0.10) - framework: dnxcore50 + System.Runtime (>= 4.0.0) + System.Text.Encoding (>= 4.0.10) System.Text.RegularExpressions (4.0.10) - framework: dnxcore50 - System.Collections (>= 4.0.10) - framework: dnxcore50 - System.Globalization (>= 4.0.10) - framework: dnxcore50 - System.Resources.ResourceManager (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - framework: dnxcore50 - System.Runtime.Extensions (>= 4.0.10) - framework: dnxcore50 - System.Threading (>= 4.0.10) - framework: dnxcore50 + System.Collections (>= 4.0.10) + System.Globalization (>= 4.0.10) + System.Resources.ResourceManager (>= 4.0.0) + System.Runtime (>= 4.0.20) + System.Runtime.Extensions (>= 4.0.10) + System.Threading (>= 4.0.10) System.Threading (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) + System.Threading.Tasks (>= 4.0.0) System.Threading.Tasks (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 + System.Runtime (>= 4.0.0) xunit (1.9.2) xunit.abstractions (2.0.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 xunit.assert (2.1.0) - System.Collections (>= 4.0.0) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - framework: dnxcore50 - System.Linq (>= 4.0.0) - framework: dnxcore50 - System.ObjectModel (>= 4.0.0) - framework: dnxcore50 - System.Reflection (>= 4.0.0) - framework: dnxcore50 - System.Reflection.Extensions (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 - System.Text.RegularExpressions (>= 4.0.0) - framework: dnxcore50 - System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 + System.Collections (>= 4.0.0) + System.Diagnostics.Debug (>= 4.0.0) + System.Globalization (>= 4.0.0) + System.Linq (>= 4.0.0) + System.ObjectModel (>= 4.0.0) + System.Reflection (>= 4.0.0) + System.Reflection.Extensions (>= 4.0.0) + System.Runtime (>= 4.0.0) + System.Runtime.Extensions (>= 4.0.0) + System.Text.RegularExpressions (>= 4.0.0) + System.Threading.Tasks (>= 4.0.0) xunit.core (2.1.0) - System.Collections (>= 4.0.0) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - framework: dnxcore50 - System.Linq (>= 4.0.0) - framework: dnxcore50 - System.Reflection (>= 4.0.0) - framework: dnxcore50 - System.Reflection.Extensions (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 - System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 - xunit.abstractions (>= 2.0.0) - framework: dnxcore50 - xunit.extensibility.core (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.1, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 - xunit.extensibility.execution (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.1, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 + System.Collections (>= 4.0.0) + System.Diagnostics.Debug (>= 4.0.0) + System.Globalization (>= 4.0.0) + System.Linq (>= 4.0.0) + System.Reflection (>= 4.0.0) + System.Reflection.Extensions (>= 4.0.0) + System.Runtime (>= 4.0.0) + System.Runtime.Extensions (>= 4.0.0) + System.Threading.Tasks (>= 4.0.0) + xunit.abstractions (>= 2.0.0) + xunit.extensibility.core (2.1.0) + xunit.extensibility.execution (2.1.0) xunit.extensibility.core (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 xunit.abstractions (2.0.0) xunit.extensibility.execution (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 - xunit.extensibility.core (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.1, wpv8.0, >= net45 + xunit.extensibility.core (2.1.0) xunit.extensions (1.9.2) xunit (1.9.2) xunit.runner.console (2.1.0) xunit.runner.utility (2.1.0) - System.Collections (>= 4.0.0) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.0) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - framework: dnxcore50 - System.IO (>= 4.0.0) - framework: dnxcore50 - System.Linq (>= 4.0.0) - framework: dnxcore50 - System.Reflection (>= 4.0.0) - framework: dnxcore50 - System.Reflection.Extensions (>= 4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - framework: dnxcore50 - System.Runtime.Extensions (>= 4.0.0) - framework: dnxcore50 - System.Text.RegularExpressions (>= 4.0.0) - framework: dnxcore50 - System.Threading (>= 4.0.0) - framework: dnxcore50 - System.Threading.Tasks (>= 4.0.0) - framework: dnxcore50 - xunit.abstractions (>= 2.0.0) - framework: dnxcore50 - xunit.abstractions (2.0.0) - framework: dnx451, monoandroid, monotouch, xamarinios, winv4.5, wpv8.1, wpv8.0, >= net35 + System.Collections (>= 4.0.0) + System.Diagnostics.Debug (>= 4.0.0) + System.Globalization (>= 4.0.0) + System.IO (>= 4.0.0) + System.Linq (>= 4.0.0) + System.Reflection (>= 4.0.0) + System.Reflection.Extensions (>= 4.0.0) + System.Runtime (>= 4.0.0) + System.Runtime.Extensions (>= 4.0.0) + System.Text.RegularExpressions (>= 4.0.0) + System.Threading (>= 4.0.0) + System.Threading.Tasks (>= 4.0.0) + xunit.abstractions (>= 2.0.0) + xunit.abstractions (2.0.0) xunit.runner.visualstudio (2.1.0) diff --git a/src/.vs/config/applicationhost.config b/src/.vs/config/applicationhost.config new file mode 100644 index 00000000000..c2abfb4801d --- /dev/null +++ b/src/.vs/config/applicationhost.config @@ -0,0 +1,1030 @@ + + + + + + + + +
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Akka.sln b/src/Akka.sln index 5d7d0cbb657..eec542968e5 100644 --- a/src/Akka.sln +++ b/src/Akka.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{00569E53-0F1E-4ECC-BAEE-8DFF37AB007A}" ProjectSection(SolutionItems) = preProject @@ -217,6 +217,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Remote.Tests.MultiNode", "core\Akka.Remote.Tests.MultiNode\Akka.Remote.Tests.MultiNode.csproj", "{C9105C76-B084-4DA1-9348-1C74A8F22F6B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Sql.Common.TestKit", "contrib\persistence\Akka.Persistence.Sql.Common.TestKit\Akka.Persistence.Sql.Common.TestKit.csproj", "{E7BC4F35-B9FB-49CB-B12C-CD00F6A08EA2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Sqlite", "contrib\persistence\Akka.Persistence.Sqlite\Akka.Persistence.Sqlite.csproj", "{453EFD22-7C53-4887-9DBF-FCFC9172E909}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Sqlite.Tests", "contrib\persistence\Akka.Persistence.Sqlite.Tests\Akka.Persistence.Sqlite.Tests.csproj", "{7A832BBF-053E-4E9F-BD83-D988A0130CC8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug Mono|Any CPU = Debug Mono|Any CPU @@ -790,6 +796,30 @@ Global {C9105C76-B084-4DA1-9348-1C74A8F22F6B}.Release Mono|Any CPU.Build.0 = Release|Any CPU {C9105C76-B084-4DA1-9348-1C74A8F22F6B}.Release|Any CPU.ActiveCfg = Release|Any CPU {C9105C76-B084-4DA1-9348-1C74A8F22F6B}.Release|Any CPU.Build.0 = Release|Any CPU + {E7BC4F35-B9FB-49CB-B12C-CD00F6A08EA2}.Debug Mono|Any CPU.ActiveCfg = Debug|Any CPU + {E7BC4F35-B9FB-49CB-B12C-CD00F6A08EA2}.Debug Mono|Any CPU.Build.0 = Debug|Any CPU + {E7BC4F35-B9FB-49CB-B12C-CD00F6A08EA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E7BC4F35-B9FB-49CB-B12C-CD00F6A08EA2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7BC4F35-B9FB-49CB-B12C-CD00F6A08EA2}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {E7BC4F35-B9FB-49CB-B12C-CD00F6A08EA2}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {E7BC4F35-B9FB-49CB-B12C-CD00F6A08EA2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E7BC4F35-B9FB-49CB-B12C-CD00F6A08EA2}.Release|Any CPU.Build.0 = Release|Any CPU + {453EFD22-7C53-4887-9DBF-FCFC9172E909}.Debug Mono|Any CPU.ActiveCfg = Debug|Any CPU + {453EFD22-7C53-4887-9DBF-FCFC9172E909}.Debug Mono|Any CPU.Build.0 = Debug|Any CPU + {453EFD22-7C53-4887-9DBF-FCFC9172E909}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {453EFD22-7C53-4887-9DBF-FCFC9172E909}.Debug|Any CPU.Build.0 = Debug|Any CPU + {453EFD22-7C53-4887-9DBF-FCFC9172E909}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {453EFD22-7C53-4887-9DBF-FCFC9172E909}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {453EFD22-7C53-4887-9DBF-FCFC9172E909}.Release|Any CPU.ActiveCfg = Release|Any CPU + {453EFD22-7C53-4887-9DBF-FCFC9172E909}.Release|Any CPU.Build.0 = Release|Any CPU + {7A832BBF-053E-4E9F-BD83-D988A0130CC8}.Debug Mono|Any CPU.ActiveCfg = Debug|Any CPU + {7A832BBF-053E-4E9F-BD83-D988A0130CC8}.Debug Mono|Any CPU.Build.0 = Debug|Any CPU + {7A832BBF-053E-4E9F-BD83-D988A0130CC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A832BBF-053E-4E9F-BD83-D988A0130CC8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A832BBF-053E-4E9F-BD83-D988A0130CC8}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {7A832BBF-053E-4E9F-BD83-D988A0130CC8}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {7A832BBF-053E-4E9F-BD83-D988A0130CC8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A832BBF-053E-4E9F-BD83-D988A0130CC8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -886,5 +916,8 @@ Global {F0781BEA-5BA0-4AF0-BB15-E3F209B681F5} = {01167D3C-49C4-4CDE-9787-C176D139ACDD} {39E6F51F-FA1E-4C62-B8F8-19065DE6D55D} = {73108242-625A-4D7B-AA09-63375DBAE464} {C9105C76-B084-4DA1-9348-1C74A8F22F6B} = {01167D3C-49C4-4CDE-9787-C176D139ACDD} + {E7BC4F35-B9FB-49CB-B12C-CD00F6A08EA2} = {264C22A4-CAFC-41F6-B82C-4DDC5C196767} + {453EFD22-7C53-4887-9DBF-FCFC9172E909} = {264C22A4-CAFC-41F6-B82C-4DDC5C196767} + {7A832BBF-053E-4E9F-BD83-D988A0130CC8} = {264C22A4-CAFC-41F6-B82C-4DDC5C196767} EndGlobalSection EndGlobal diff --git a/src/benchmark/PersistenceBenchmark/App.config b/src/benchmark/PersistenceBenchmark/App.config index 2de963ff0c0..e28ac54bd91 100644 --- a/src/benchmark/PersistenceBenchmark/App.config +++ b/src/benchmark/PersistenceBenchmark/App.config @@ -62,15 +62,15 @@ - + - + - + @@ -102,15 +102,15 @@ - + - + - + @@ -122,15 +122,15 @@ - + - + - + @@ -148,4 +148,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/benchmark/PingPong/App.config b/src/benchmark/PingPong/App.config index 4b9e5cc452b..955b940cb6d 100644 --- a/src/benchmark/PingPong/App.config +++ b/src/benchmark/PingPong/App.config @@ -64,15 +64,15 @@ - + - + - + @@ -104,15 +104,15 @@ - + - + - + @@ -124,15 +124,15 @@ - + - + - + @@ -150,5 +150,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj index 950bf02b13a..f7e7f77448c 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj @@ -82,7 +82,7 @@ --> - + ..\..\..\..\packages\CommonServiceLocator\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj b/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj index 6f4504e6919..ee4e5d4d066 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj @@ -67,7 +67,7 @@ --> - + ..\..\..\..\packages\CommonServiceLocator\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Akka.Persistence.Sql.Common.TestKit.csproj b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Akka.Persistence.Sql.Common.TestKit.csproj new file mode 100644 index 00000000000..968958e2a94 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Akka.Persistence.Sql.Common.TestKit.csproj @@ -0,0 +1,220 @@ + + + + + Debug + AnyCPU + {E7BC4F35-B9FB-49CB-B12C-CD00F6A08EA2} + Library + Properties + Akka.Persistence.Sql.Common.TestKit + Akka.Persistence.Sql.Common.TestKit + v4.5 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + {ad9418b6-c452-4169-94fb-d43de0bfa966} + Akka.Persistence.TestKit + + + {fca84dea-c118-424b-9eb8-34375dfef18a} + Akka.Persistence + + + {0D3CBAD0-BBDB-43E5-AFC4-ED1D3ECDC224} + Akka.TestKit + + + {5deddf90-37f0-48d3-a0b0-a5cbd8a7e377} + Akka + + + {7dbd5c17-5e9d-40c4-9201-d092751532a7} + Akka.TestKit.Xunit2 + + + {3b9e6211-9488-4db5-b714-24248693b38f} + Akka.Persistence.Sql.Common + + + + + + + + + + + + + ..\..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win81\xunit.core + + + + + <__paket__xunit_core_props>wpa81\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core + + + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll + True + True + + + + + \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Properties/AssemblyInfo.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..6456fcd8179 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Akka.Persistence.Sql.Common.TestKit")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Akka.Persistence.Sql.Common.TestKit")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("e7bc4f35-b9fb-49cb-b12c-cd00f6a08ea2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/SqlJournalQuerySpec.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/SqlJournalQuerySpec.cs new file mode 100644 index 00000000000..aecbd04bda0 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/SqlJournalQuerySpec.cs @@ -0,0 +1,147 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using Akka.Actor; +using Akka.Configuration; +using Akka.Persistence.Sql.Common.Journal; +using Akka.Persistence.Sql.Common.Queries; +using Akka.Persistence.TestKit; +using Xunit; +using Xunit.Abstractions; + +namespace Akka.Persistence.Sql.Common.TestKit +{ + public abstract class SqlJournalQuerySpec : PluginSpec + { + class TestTimestampProvider : ITimestampProvider + { + private static IDictionary, DateTime> KnownEventTimestampMappings = new Dictionary, DateTime> + { + {Tuple.Create("p-1", 1L), new DateTime(2001, 1, 1) }, + {Tuple.Create("p-1", 2L), new DateTime(2001, 1, 2) }, + {Tuple.Create("p-1", 3L), new DateTime(2001, 1, 3) }, + {Tuple.Create("p-2", 1L), new DateTime(2001, 1, 1) }, + {Tuple.Create("p-2", 2L), new DateTime(2001, 2, 1) }, + {Tuple.Create("p-3", 1L), new DateTime(2001, 1, 1) }, + {Tuple.Create("p-3", 2L), new DateTime(2003, 1, 1) }, + }; + + public DateTime GenerateTimestamp(IPersistentRepresentation message) + { + return KnownEventTimestampMappings[Tuple.Create(message.PersistenceId, message.SequenceNr)]; + } + } + + public static string TimestampConfig(string plugin) + { + return plugin + ".timestamp-provider =\"" + typeof(TestTimestampProvider).FullName + ", Akka.Persistence.Sql.Common.TestKit\""; + } + + private static readonly IPersistentRepresentation[] Events = + { + new Persistent("a-1", 1, "System.String", "p-1"), + new Persistent("a-2", 2, "System.String", "p-1"), + new Persistent("a-3", 3, "System.String", "p-1"), + new Persistent("a-4", 1, "System.String", "p-2"), + new Persistent(5, 2, "System.Int32", "p-2"), + new Persistent(6, 1, "System.Int32", "p-3"), + new Persistent("a-7", 2, "System.String", "p-3"), + }; + + public IActorRef JournalRef { get; protected set; } + + protected SqlJournalQuerySpec(Config config = null, string actorSystemName = null, ITestOutputHelper output = null) + : base(config, actorSystemName, output) + { + JournalRef = Extension.JournalFor(null); + } + + [Fact] + public void Journal_queried_on_PersistenceIdRange_returns_events_for_particular_persistent_ids() + { + var query = new Query(1, Hints.PersistenceIds(new[] { "p-1", "p-2" })); + QueryAndExpectSuccess(query, Events[0], Events[1], Events[2], Events[3], Events[4]); + } + + [Fact] + public void Journal_queried_on_Manifest_returns_events_with_particular_manifest() + { + var query = new Query(2, Hints.Manifest("System.Int32")); + QueryAndExpectSuccess(query, Events[4], Events[5]); + } + + [Fact] + public void Journal_queried_on_Timestamp_returns_events_occurred_after_or_equal_From_value() + { + var query = new Query(3, Hints.TimestampAfter(new DateTime(2001, 1, 3))); + QueryAndExpectSuccess(query, Events[2], Events[4], Events[6]); + } + + [Fact] + public void Journal_queried_on_Timestamp_returns_events_occurred_before_To_value() + { + var query = new Query(4, Hints.TimestampBefore(new DateTime(2001, 2, 1))); + QueryAndExpectSuccess(query, Events[0], Events[1], Events[2], Events[3], Events[5]); + } + + [Fact] + public void Journal_queried_on_Timestamp_returns_events_occurred_between_both_range_values() + { + var query = new Query(5, Hints.TimestampBetween(new DateTime(2001, 1, 3), new DateTime(2003, 1, 1))); + QueryAndExpectSuccess(query, Events[2], Events[4]); + } + + [Fact] + public void Journal_queried_using_multiple_hints_should_apply_all_of_them() + { + var query = new Query(6, + Hints.TimestampBefore(new DateTime(2001, 1, 3)), + Hints.PersistenceIds(new[] { "p-1", "p-2" }), + Hints.Manifest("System.String")); + + QueryAndExpectSuccess(query, Events[0], Events[1], Events[3]); + } + + protected void Initialize() + { + WriteEvents(); + } + + private void WriteEvents() + { + var probe = CreateTestProbe(); + var message = new WriteMessages(Events, probe.Ref, ActorInstanceId); + + JournalRef.Tell(message); + probe.ExpectMsg(); + foreach (var persistent in Events) + { + probe.ExpectMsg(new WriteMessageSuccess(persistent, ActorInstanceId)); + } + } + + private void QueryAndExpectSuccess(Query query, params IPersistentRepresentation[] events) + { + JournalRef.Tell(query, TestActor); + + foreach (var e in events) + { + ExpectMsg(q => + q.QueryId == query.QueryId && + q.Message.PersistenceId == e.PersistenceId && + q.Message.SequenceNr == e.SequenceNr && + q.Message.Manifest == e.Manifest && + q.Message.IsDeleted == e.IsDeleted && + Equals(q.Message.Payload, e.Payload)); + } + + ExpectMsg(new QuerySuccess(query.QueryId)); + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/paket.references b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/paket.references new file mode 100644 index 00000000000..aa6e6065aa7 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/paket.references @@ -0,0 +1,5 @@ +group Test +xunit.abstractions +xunit.assert +xunit.core +xunit.extensibility.core \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Akka.Persistence.Sql.Common.csproj b/src/contrib/persistence/Akka.Persistence.Sql.Common/Akka.Persistence.Sql.Common.csproj index fb06306d447..1e26d5753ad 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Akka.Persistence.Sql.Common.csproj +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Akka.Persistence.Sql.Common.csproj @@ -31,6 +31,7 @@ + @@ -40,12 +41,16 @@ + + + + - + diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/ITimestampProvider.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/ITimestampProvider.cs new file mode 100644 index 00000000000..5f4863ae8ce --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/ITimestampProvider.cs @@ -0,0 +1,26 @@ +using System; + +namespace Akka.Persistence.Sql.Common.Journal +{ + /// + /// Interface responsible for generation of timestamps for persisted messages in SQL-based journals. + /// + public interface ITimestampProvider + { + /// + /// Generates timestamp for provided message. + /// + DateTime GenerateTimestamp(IPersistentRepresentation message); + } + + /// + /// Default implementation of timestamp provider. Returns for any message. + /// + public sealed class DefaultTimestampProvider : ITimestampProvider + { + public DateTime GenerateTimestamp(IPersistentRepresentation message) + { + return DateTime.UtcNow; + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/JournalDbEngine.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/JournalDbEngine.cs index df199d4042b..09ac0e8a386 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/JournalDbEngine.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/JournalDbEngine.cs @@ -7,12 +7,14 @@ using System; using System.Collections.Generic; -using System.Data; +using System.Configuration; using System.Data.Common; using System.Linq; using System.Threading; using System.Threading.Tasks; using Akka.Actor; +using Akka.Event; +using Akka.Persistence.Sql.Common.Queries; namespace Akka.Persistence.Sql.Common.Journal { @@ -20,21 +22,23 @@ namespace Akka.Persistence.Sql.Common.Journal /// Class used for storing intermediate result of the /// in form which is ready to be stored directly in the SQL table. /// - public class JournalEntry + public sealed class JournalEntry { public readonly string PersistenceId; public readonly long SequenceNr; public readonly bool IsDeleted; - public readonly string PayloadType; + public readonly string Manifest; + public readonly DateTime Timestamp; public readonly byte[] Payload; - public JournalEntry(string persistenceId, long sequenceNr, bool isDeleted, string payloadType, byte[] payload) + public JournalEntry(string persistenceId, long sequenceNr, bool isDeleted, string manifest, DateTime timestamp, byte[] payload) { PersistenceId = persistenceId; SequenceNr = sequenceNr; IsDeleted = isDeleted; - PayloadType = payloadType; + Manifest = manifest; Payload = payload; + Timestamp = timestamp; } } @@ -53,23 +57,38 @@ public abstract class JournalDbEngine : IDisposable /// protected readonly LinkedList PendingOperations; - private readonly Akka.Serialization.Serialization _serialization; - private DbConnection _dbConnection; + /// + /// Timestamp provider used for generation of timestamps for incoming persistent messages. + /// + protected readonly ITimestampProvider TimestampProvider; - protected JournalDbEngine(JournalSettings settings, Akka.Serialization.Serialization serialization) + private readonly ActorSystem _system; + + protected JournalDbEngine(ActorSystem system) { - Settings = settings; - _serialization = serialization; + _system = system; - QueryMapper = new DefaultJournalQueryMapper(serialization); + Settings = new JournalSettings(system.Settings.Config.GetConfig(JournalConfigPath)); + QueryMapper = new DefaultJournalQueryMapper(_system.Serialization); + TimestampProvider = CreateTimestampProvider(); PendingOperations = new LinkedList(); } + /// + /// Returns a HOCON config path to associated journal. + /// + protected abstract string JournalConfigPath { get; } + + /// + /// System logger. + /// + protected ILoggingAdapter Log { get { return _system.Log; } } + /// /// Initializes a database connection. /// - protected abstract DbConnection CreateDbConnection(); + protected abstract DbConnection CreateDbConnection(string connectionString); /// /// Copies values from entities to database command. @@ -78,31 +97,20 @@ protected JournalDbEngine(JournalSettings settings, Akka.Serialization.Serializa /// protected abstract void CopyParamsToCommand(DbCommand sqlCommand, JournalEntry entry); - /// - /// Gets database connection. - /// - public IDbConnection DbConnection { get { return _dbConnection; } } - /// /// Used for generating SQL commands for journal-related database operations. /// - public IJournalQueryBuilder QueryBuilder { get; protected set; } + public IJournalQueryBuilder QueryBuilder { get; set; } /// /// Used for mapping results returned from database into objects. /// - public IJournalQueryMapper QueryMapper { get; protected set; } + public IJournalQueryMapper QueryMapper { get; set; } - /// - /// Initializes and opens a database connection. - /// - public void Open() + public DbConnection CreateDbConnection() { - // close connection if it was open - Close(); - - _dbConnection = CreateDbConnection(); - _dbConnection.Open(); + var connectionString = GetConnectionString(); + return CreateDbConnection(connectionString); } /// @@ -110,13 +118,7 @@ public void Open() /// public void Close() { - if (_dbConnection != null) - { - StopPendingOperations(); - - _dbConnection.Dispose(); - _dbConnection = null; - } + StopPendingOperations(); } /// @@ -141,6 +143,37 @@ void IDisposable.Dispose() Close(); } + /// + /// Performs + /// + public async Task ReadEvents(object queryId, IEnumerable hints, IActorRef sender, Action replayCallback) + { + using (var connection = CreateDbConnection()) + { + await connection.OpenAsync(); + + var sqlCommand = QueryBuilder.SelectEvents(hints); + CompleteCommand(sqlCommand, connection); + + var tokenSource = GetCancellationTokenSource(); + var reader = await sqlCommand.ExecuteReaderAsync(tokenSource.Token); + try + { + while (reader.Read()) + { + var persistent = QueryMapper.Map(reader, sender); + if (persistent != null) + replayCallback(persistent); + } + } + finally + { + PendingOperations.Remove(tokenSource); + reader.Close(); + } + } + } + /// /// Asynchronously replays all requested messages related to provided , /// using provided sequence ranges (inclusive) with number of messages replayed @@ -151,120 +184,109 @@ void IDisposable.Dispose() /// Upper inclusive sequence number bound. Unbound by default. /// Maximum number of messages to be replayed. Unbound by default. /// Action invoked for each replayed message. - public Task ReplayMessagesAsync(string persistenceId, long fromSequenceNr, long toSequenceNr, long max, IActorRef sender, Action replayCallback) + public async Task ReplayMessagesAsync(string persistenceId, long fromSequenceNr, long toSequenceNr, long max, IActorRef sender, Action replayCallback) { - var sqlCommand = QueryBuilder.SelectMessages(persistenceId, fromSequenceNr, toSequenceNr, max); - CompleteCommand(sqlCommand); + using (var connection = CreateDbConnection()) + { + await connection.OpenAsync(); - var tokenSource = GetCancellationTokenSource(); + var sqlCommand = QueryBuilder.SelectMessages(persistenceId, fromSequenceNr, toSequenceNr, max); + CompleteCommand(sqlCommand, connection); - return sqlCommand - .ExecuteReaderAsync(tokenSource.Token) - .ContinueWith(task => + var tokenSource = GetCancellationTokenSource(); + var reader = await sqlCommand.ExecuteReaderAsync(tokenSource.Token); + + try { - var reader = task.Result; - try - { - while (reader.Read()) - { - var persistent = QueryMapper.Map(reader, sender); - if (persistent != null) - { - replayCallback(persistent); - } - } - } - finally + while (reader.Read()) { - PendingOperations.Remove(tokenSource); - reader.Close(); + var persistent = QueryMapper.Map(reader, sender); + if (persistent != null) + replayCallback(persistent); } - }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); + } + finally + { + PendingOperations.Remove(tokenSource); + reader.Close(); + } + } } /// /// Asynchronously reads a highest sequence number of the event stream related with provided . /// - public Task ReadHighestSequenceNrAsync(string persistenceId, long fromSequenceNr) + public async Task ReadHighestSequenceNrAsync(string persistenceId, long fromSequenceNr) { - var sqlCommand = QueryBuilder.SelectHighestSequenceNr(persistenceId); - CompleteCommand(sqlCommand); + using (var connection = CreateDbConnection()) + { + await connection.OpenAsync(); - var tokenSource = GetCancellationTokenSource(); + var sqlCommand = QueryBuilder.SelectHighestSequenceNr(persistenceId); + CompleteCommand(sqlCommand, connection); + var tokenSource = GetCancellationTokenSource(); - return sqlCommand - .ExecuteScalarAsync(tokenSource.Token) - .ContinueWith(task => - { - PendingOperations.Remove(tokenSource); - var result = task.Result; - return result is long ? Convert.ToInt64(task.Result) : 0L; - }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); + var seqNr = await sqlCommand.ExecuteScalarAsync(tokenSource.Token); + return seqNr is long ? Convert.ToInt64(seqNr) : 0L; + } } /// - /// Synchronously writes all persistent inside SQL Server database. + /// Asynchronously writes all persistent inside SQL Server database. /// /// Specific table used for message persistence may be defined through configuration within /// 'akka.persistence.journal.sql-server' scope with 'schema-name' and 'table-name' keys. /// - public void WriteMessages(IEnumerable messages) + public async Task WriteMessagesAsync(IEnumerable messages) { - var persistentMessages = messages.ToArray(); - var sqlCommand = QueryBuilder.InsertBatchMessages(persistentMessages); - CompleteCommand(sqlCommand); + using (var connection = CreateDbConnection()) + { + await connection.OpenAsync(); - var journalEntries = persistentMessages.Select(ToJournalEntry).ToList(); + var persistentMessages = messages.ToArray(); + var sqlCommand = QueryBuilder.InsertBatchMessages(persistentMessages); + CompleteCommand(sqlCommand, connection); - InsertInTransaction(sqlCommand, journalEntries); + var journalEntries = persistentMessages.Select(ToJournalEntry).ToList(); + await InsertInTransactionAsync(sqlCommand, journalEntries); + } } /// - /// Synchronously deletes all persisted messages identified by provided + /// Asynchronously deletes all persisted messages identified by provided /// up to provided message sequence number (inclusive). If flag is cleared, /// messages will still reside inside database, but will be logically counted as deleted. /// - public void DeleteMessagesTo(string persistenceId, long toSequenceNr, bool isPermanent) - { - var sqlCommand = QueryBuilder.DeleteBatchMessages(persistenceId, toSequenceNr, isPermanent); - CompleteCommand(sqlCommand); - - sqlCommand.ExecuteNonQuery(); - } - - /// - /// Asynchronously writes all persistent inside SQL Server database. - /// - /// Specific table used for message persistence may be defined through configuration within - /// 'akka.persistence.journal.sql-server' scope with 'schema-name' and 'table-name' keys. - /// - public async Task WriteMessagesAsync(IEnumerable messages) + public async Task DeleteMessagesToAsync(string persistenceId, long toSequenceNr, bool isPermanent) { - var persistentMessages = messages.ToArray(); - var sqlCommand = QueryBuilder.InsertBatchMessages(persistentMessages); - CompleteCommand(sqlCommand); + using (var connection = CreateDbConnection()) + { + await connection.OpenAsync(); - var journalEntries = persistentMessages.Select(ToJournalEntry).ToList(); + var sqlCommand = QueryBuilder.DeleteBatchMessages(persistenceId, toSequenceNr, isPermanent); + CompleteCommand(sqlCommand, connection); - await InsertInTransactionAsync(sqlCommand, journalEntries); + await sqlCommand.ExecuteNonQueryAsync(); + } } /// - /// Asynchronously deletes all persisted messages identified by provided - /// up to provided message sequence number (inclusive). If flag is cleared, - /// messages will still reside inside database, but will be logically counted as deleted. + /// Returns connection string from either HOCON configuration or <connectionStrings> section of app.config. /// - public async Task DeleteMessagesToAsync(string persistenceId, long toSequenceNr, bool isPermanent) + protected virtual string GetConnectionString() { - var sqlCommand = QueryBuilder.DeleteBatchMessages(persistenceId, toSequenceNr, isPermanent); - CompleteCommand(sqlCommand); + var connectionString = Settings.ConnectionString; + if (string.IsNullOrEmpty(connectionString)) + { + connectionString = ConfigurationManager.ConnectionStrings[Settings.ConnectionStringName].ConnectionString; + } - await sqlCommand.ExecuteNonQueryAsync(); + return connectionString; } - private void CompleteCommand(DbCommand sqlCommand) + private void CompleteCommand(DbCommand sqlCommand, DbConnection connection) { - sqlCommand.Connection = _dbConnection; + sqlCommand.Connection = connection; sqlCommand.CommandTimeout = (int)Settings.ConnectionTimeout.TotalMilliseconds; } @@ -278,42 +300,24 @@ private CancellationTokenSource GetCancellationTokenSource() private JournalEntry ToJournalEntry(IPersistentRepresentation message) { var payloadType = message.Payload.GetType(); - var serializer = _serialization.FindSerializerForType(payloadType); + var serializer = _system.Serialization.FindSerializerForType(payloadType); + var manifest = string.IsNullOrEmpty(message.Manifest) ? payloadType.QualifiedTypeName() : message.Manifest; + var timestamp = TimestampProvider.GenerateTimestamp(message); + var payload = serializer.ToBinary(message.Payload); - return new JournalEntry(message.PersistenceId, message.SequenceNr, message.IsDeleted, - payloadType.QualifiedTypeName(), serializer.ToBinary(message.Payload)); + return new JournalEntry(message.PersistenceId, message.SequenceNr, message.IsDeleted, manifest, timestamp, payload); } - private void InsertInTransaction(DbCommand sqlCommand, IEnumerable journalEntries) + private ITimestampProvider CreateTimestampProvider() { - using (var tx = _dbConnection.BeginTransaction()) - { - sqlCommand.Transaction = tx; - try - { - foreach (var entry in journalEntries) - { - CopyParamsToCommand(sqlCommand, entry); - - if (sqlCommand.ExecuteNonQuery() != 1) - { - //TODO: something went wrong, ExecuteNonQuery() should return 1 (number of rows added) - } - } - - tx.Commit(); - } - catch (Exception) - { - tx.Rollback(); - throw; - } - } + var type = Type.GetType(Settings.TimestampProvider, true); + var instance = Activator.CreateInstance(type); + return (ITimestampProvider) instance; } private async Task InsertInTransactionAsync(DbCommand sqlCommand, IEnumerable journalEntries) { - using (var tx = _dbConnection.BeginTransaction()) + using (var tx = sqlCommand.Connection.BeginTransaction()) { sqlCommand.Transaction = tx; try @@ -322,10 +326,10 @@ private async Task InsertInTransactionAsync(DbCommand sqlCommand, IEnumerable //----------------------------------------------------------------------- +using System.Collections.Generic; using System.Data.Common; +using Akka.Persistence.Sql.Common.Queries; namespace Akka.Persistence.Sql.Common.Journal { @@ -14,6 +16,11 @@ namespace Akka.Persistence.Sql.Common.Journal /// public interface IJournalQueryBuilder { + /// + /// Returns query which should return events filtered accordingly to provided set of . + /// + DbCommand SelectEvents(IEnumerable hints); + /// /// Returns query which should return a frame of messages filtered accordingly to provided parameters. /// diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/QueryMapper.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/QueryMapper.cs index 2bc8f3a9861..9f0b8b59599 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/QueryMapper.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/QueryMapper.cs @@ -29,6 +29,12 @@ public interface IJournalQueryMapper /// internal class DefaultJournalQueryMapper : IJournalQueryMapper { + public const int PersistenceIdIndex = 0; + public const int SequenceNrIndex = 1; + public const int IsDeletedIndex = 2; + public const int ManifestIndex = 3; + public const int PayloadIndex = 4; + private readonly Akka.Serialization.Serialization _serialization; public DefaultJournalQueryMapper(Akka.Serialization.Serialization serialization) @@ -38,19 +44,21 @@ public DefaultJournalQueryMapper(Akka.Serialization.Serialization serialization) public IPersistentRepresentation Map(DbDataReader reader, IActorRef sender = null) { - var persistenceId = reader.GetString(0); - var sequenceNr = reader.GetInt64(1); - var isDeleted = reader.GetBoolean(2); - var payloadType = reader.GetString(3); - var payload = GetPayload(reader, payloadType); + var persistenceId = reader.GetString(PersistenceIdIndex); + var sequenceNr = reader.GetInt64(SequenceNrIndex); + var isDeleted = reader.GetBoolean(IsDeletedIndex); + var manifest = reader.GetString(ManifestIndex); + + // timestamp is SQL-journal specific field, it's not a part of casual Persistent instance + var payload = GetPayload(reader, manifest); - return new Persistent(payload, sequenceNr, payloadType, persistenceId, isDeleted, sender); + return new Persistent(payload, sequenceNr, manifest, persistenceId, isDeleted, sender); } - private object GetPayload(DbDataReader reader, string payloadType) + private object GetPayload(DbDataReader reader, string manifest) { - var type = Type.GetType(payloadType, true); - var binary = (byte[]) reader[4]; + var type = Type.GetType(manifest, true); + var binary = (byte[]) reader[PayloadIndex]; var serializer = _serialization.FindSerializerForType(type); return serializer.FromBinary(binary, type); diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs new file mode 100644 index 00000000000..aa2ca187f06 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Akka.Actor; +using Akka.Persistence.Journal; +using Akka.Persistence.Sql.Common.Queries; + +namespace Akka.Persistence.Sql.Common.Journal +{ + public abstract class SqlJournal : AsyncWriteJournal + { + protected readonly JournalDbEngine DbEngine; + + protected SqlJournal(JournalDbEngine dbEngine) + { + if (dbEngine == null) + throw new ArgumentNullException("dbEngine", "Database engine provided to sql journal cannot be null"); + + DbEngine = dbEngine; + } + + protected override void PostStop() + { + base.PostStop(); + DbEngine.Close(); + } + + protected override bool Receive(object message) + { + var wasHandled = base.Receive(message); + if (!wasHandled && message is Query) + { + HandleEventQuery(message as Query); + return true; + } + + return false; + } + + private void HandleEventQuery(Query query) + { + var queryId = query.QueryId; + var sender = Context.Sender; + DbEngine.ReadEvents(queryId, query.Hints, Context.Sender, reply => + { + foreach (var adapted in AdaptFromJournal(reply)) + { + sender.Tell(new QueryResponse(queryId, adapted)); + } + }) + .ContinueWith(task => + task.IsFaulted || task.IsCanceled ? (IQueryReply)new QueryFailure(queryId, task.Exception) : new QuerySuccess(queryId), + TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent) + .PipeTo(Context.Sender); + } + + public override Task ReplayMessagesAsync(string persistenceId, long fromSequenceNr, long toSequenceNr, long max, Action replayCallback) + { + return DbEngine.ReplayMessagesAsync(persistenceId, fromSequenceNr, toSequenceNr, max, Context.Sender, replayCallback); + } + + public override Task ReadHighestSequenceNrAsync(string persistenceId, long fromSequenceNr) + { + return DbEngine.ReadHighestSequenceNrAsync(persistenceId, fromSequenceNr); + } + + protected override Task WriteMessagesAsync(IEnumerable messages) + { + return DbEngine.WriteMessagesAsync(messages); + } + + protected override Task DeleteMessagesToAsync(string persistenceId, long toSequenceNr, bool isPermanent) + { + return DbEngine.DeleteMessagesToAsync(persistenceId, toSequenceNr, isPermanent); + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Hints.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Hints.cs new file mode 100644 index 00000000000..325de835ef5 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Hints.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using Akka.Persistence.Sql.Common.Journal; + +namespace Akka.Persistence.Sql.Common.Queries +{ + public interface IHint { } + + public static class Hints + { + /// + /// Returns a hint that expects a reply with events with matching manifest. + /// + public static IHint Manifest(string manifest) + { + return new WithManifest(manifest); + } + + /// + /// Returns a hint that expects a reply with events from provided set of persistence ids. + /// + public static IHint PersistenceIds(IEnumerable persistenceIds) + { + return new PersistenceIdRange(persistenceIds); + } + + /// + /// Returns a hint that expects a reply with events, that have timestamp value before provided date. + /// + public static IHint TimestampBefore(DateTime to) + { + return new TimestampRange(null, to); + } + + /// + /// Returns a hint that expects a reply with events, that have timestamp value after or equal provided date. + /// + public static IHint TimestampAfter(DateTime from) + { + return new TimestampRange(from, null); + } + + /// + /// Returns a hint that expects a reply with events, that have timestamp from between provided range of values (left side inclusive). + /// + public static IHint TimestampBetween(DateTime from, DateTime to) + { + return new TimestampRange(from, to); + } + } + + /// + /// Hint for the SQL journal used to filter journal entries returned in the response based on the manifest. + /// + [Serializable] + public sealed class WithManifest : IHint, IEquatable + { + + public readonly string Manifest; + + public WithManifest(string manifest) + { + if (string.IsNullOrEmpty(manifest)) throw new ArgumentException("Hint expected manifest, but none has been provided", "manifest"); + Manifest = manifest; + } + + public bool Equals(WithManifest other) + { + return other != null && other.Manifest.Equals(Manifest); + } + + public override bool Equals(object obj) + { + return Equals(obj as WithManifest); + } + + public override int GetHashCode() + { + return (Manifest != null ? Manifest.GetHashCode() : 0); + } + + public override string ToString() + { + return string.Format("WithManifest", Manifest); + } + } + + /// + /// Hint for the SQL journal used to filter journal entries returned in the response based on set of perisistence ids provided. + /// + [Serializable] + public sealed class PersistenceIdRange : IHint, IEquatable + { + public readonly ISet PersistenceIds; + + public PersistenceIdRange(IEnumerable persistenceIds) + { + if (persistenceIds == null) throw new ArgumentException("Hint expected persistence ids, but none has been provided", "persistenceIds"); + PersistenceIds = new HashSet(persistenceIds); + } + + public bool Equals(PersistenceIdRange other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return other.PersistenceIds.SetEquals(PersistenceIds); + } + + public override bool Equals(object obj) + { + return Equals(obj as PersistenceIdRange); + } + + public override int GetHashCode() + { + return (PersistenceIds != null ? PersistenceIds.GetHashCode() : 0); + } + + public override string ToString() + { + return string.Format("PersistenceIdRange", string.Join(", ", PersistenceIds)); + } + } + + /// + /// Hint for the SQL journal used to filter journal entries returned in the response based on their timestamp range. + /// Desired behavior of timestamp range is <from, to) - left side inclusive, right side exclusive. + /// Timestamp is generated by method, which may be overloaded. + /// + [Serializable] + public sealed class TimestampRange : IHint, IEquatable + { + public readonly DateTime? From; + public readonly DateTime? To; + + public TimestampRange(DateTime? @from, DateTime? to) + { + if (!from.HasValue && !to.HasValue) + throw new ArgumentException("TimestampRange hint requires either 'From' or 'To' or both range limiters provided"); + + if (from.HasValue && to.HasValue && from > to) + throw new ArgumentException("TimestampRange hint requires 'From' date to occur before 'To' date"); + + From = @from; + To = to; + } + + public bool Equals(TimestampRange other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(From, other.From) && Equals(To, other.To); + } + + public override bool Equals(object obj) + { + return Equals(obj as TimestampRange); + } + + public override int GetHashCode() + { + unchecked + { + return (From.GetHashCode() * 397) ^ To.GetHashCode(); + } + } + + public override string ToString() + { + return string.Format("TimestampRange", + From.HasValue ? From.Value.ToString() : "undefined", + To.HasValue ? To.Value.ToString() : "undefined"); + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Query.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Query.cs new file mode 100644 index 00000000000..426d2a015d0 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Query.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using Akka.Actor; + +namespace Akka.Persistence.Sql.Common.Queries +{ + public interface IQueryReply { } + + /// + /// Message send to particular SQL-based journal . It may be parametrized + /// using set of hints. SQL-based journal will respond with collection of + /// messages followed by when request succeed or the + /// message when request has failed for some reason. + /// + /// Since SQL journals can store events in linearized fashion, they are able to provide deterministic + /// set of events not based on any partition key. Therefore query request don't need to contain + /// partition id of the persistent actor. + /// + [Serializable] + public sealed class Query: IEquatable + { + public readonly object QueryId; + public readonly ISet Hints; + + public Query(object queryId, ISet hints) + { + if(hints == null) + throw new ArgumentNullException("hints", "Query expects set of hints passed not to be null"); + + QueryId = queryId; + Hints = hints; + } + + public Query(object queryId, params IHint[] hints) : this(queryId, new HashSet(hints)) { } + + public bool Equals(Query other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(QueryId, other.QueryId) && Hints.SetEquals(other.Hints); + } + + public override bool Equals(object obj) + { + return Equals(obj as Query); + } + + public override int GetHashCode() + { + unchecked + { + return ((QueryId != null ? QueryId.GetHashCode() : 0) * 397) ^ Hints.GetHashCode(); + } + } + + public override string ToString() + { + return string.Format("Query", QueryId, string.Join(",", Hints)); + } + } + + /// + /// Message send back from SQL-based journal to sender, + /// when the query execution has been completed and result is returned. + /// + [Serializable] + public sealed class QueryResponse : IQueryReply, IEquatable + { + public readonly object QueryId; + public readonly IPersistentRepresentation Message; + + public QueryResponse(object queryId, IPersistentRepresentation message) + { + QueryId = queryId; + Message = message; + } + + public bool Equals(QueryResponse other) + { + if (Equals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(QueryId, other.QueryId) && Equals(Message, other.Message); + } + + public override bool Equals(object obj) + { + return Equals(obj as QueryResponse); + } + + public override int GetHashCode() + { + unchecked + { + return ((QueryId != null ? QueryId.GetHashCode() : 0) * 397) ^ (Message != null ? Message.GetHashCode() : 0); + } + } + + public override string ToString() + { + return string.Format("QueryResponse", QueryId, Message); + } + } + + /// + /// Message send back from SQL-based journal, when has been successfully responded. + /// + [Serializable] + public sealed class QuerySuccess : IQueryReply, IEquatable + { + public readonly object QueryId; + + public QuerySuccess(object queryId) + { + QueryId = queryId; + } + + public bool Equals(QuerySuccess other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + return Equals(QueryId, other.QueryId); + } + + public override bool Equals(object obj) + { + return Equals(obj as QuerySuccess); + } + + public override int GetHashCode() + { + return (QueryId != null ? QueryId.GetHashCode() : 0); + } + + public override string ToString() + { + return string.Format("QuerySuccess", QueryId); + } + } + + /// + /// Message send back from SQL-based journal to sender, when the query execution has failed. + /// + [Serializable] + public sealed class QueryFailure : IQueryReply, IEquatable + { + /// + /// Identifier of the correlated . + /// + public readonly object QueryId; + public readonly Exception Reason; + + public QueryFailure(object queryId, Exception reason) + { + QueryId = queryId; + Reason = reason; + } + + public bool Equals(QueryFailure other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + return Equals(QueryId, other.QueryId) && Equals(Reason, other.Reason); + } + + public override bool Equals(object obj) + { + return Equals(obj as QueryFailure); + } + + public override int GetHashCode() + { + unchecked + { + return ((QueryId != null ? QueryId.GetHashCode() : 0) * 397) ^ (Reason != null ? Reason.GetHashCode() : 0); + } + } + + public override string ToString() + { + return string.Format("QueryFailure", QueryId, Reason); + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Settings.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Settings.cs index 4ac9be9ba2d..993697dd2ac 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Settings.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Settings.cs @@ -7,6 +7,7 @@ using System; using Akka.Configuration; +using Akka.Persistence.Sql.Common.Journal; namespace Akka.Persistence.Sql.Common { @@ -40,6 +41,11 @@ public class JournalSettings /// public string TableName { get; private set; } + /// + /// Fully qualified type name for used to generate journal timestamps. + /// + public string TimestampProvider { get; set; } + public JournalSettings(Config config) { if (config == null) throw new ArgumentNullException("config", "SqlServer journal settings cannot be initialized, because required HOCON section couldn't been found"); @@ -49,6 +55,7 @@ public JournalSettings(Config config) ConnectionTimeout = config.GetTimeSpan("connection-timeout"); SchemaName = config.GetString("schema-name"); TableName = config.GetString("table-name"); + TimestampProvider = config.GetString("timestamp-provider"); } } diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Snapshot/DbSnapshotStore.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Snapshot/SqlSnapshotStore.cs similarity index 53% rename from src/contrib/persistence/Akka.Persistence.Sql.Common/Snapshot/DbSnapshotStore.cs rename to src/contrib/persistence/Akka.Persistence.Sql.Common/Snapshot/SqlSnapshotStore.cs index 9a52bc6c806..4652afb58fe 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Snapshot/DbSnapshotStore.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Snapshot/SqlSnapshotStore.cs @@ -1,11 +1,12 @@ //----------------------------------------------------------------------- -// +// // Copyright (C) 2009-2015 Typesafe Inc. // Copyright (C) 2013-2015 Akka.NET project // //----------------------------------------------------------------------- using System.Collections.Generic; +using System.Configuration; using System.Data.Common; using System.Threading; using System.Threading.Tasks; @@ -16,16 +17,14 @@ namespace Akka.Persistence.Sql.Common.Snapshot /// /// Abstract snapshot store implementation, customized to work with SQL-based persistence providers. /// - public abstract class DbSnapshotStore : SnapshotStore + public abstract class SqlSnapshotStore : SnapshotStore { /// /// List of cancellation tokens for all pending asynchronous database operations. /// protected readonly LinkedList PendingOperations; - - private DbConnection _connection; - - protected DbSnapshotStore() + + protected SqlSnapshotStore() { QueryMapper = new DefaultSnapshotQueryMapper(Context.System.Serialization); PendingOperations = new LinkedList(); @@ -34,17 +33,20 @@ protected DbSnapshotStore() /// /// Returns a new instance of database connection. /// - protected abstract DbConnection CreateDbConnection(); + protected abstract DbConnection CreateDbConnection(string connectionString); /// - /// Gets settings for the current snapshot store. + /// Returns a new instance of database connection. /// - protected abstract SnapshotStoreSettings Settings { get; } + public DbConnection CreateDbConnection() + { + return CreateDbConnection(GetConnectionString()); + } /// - /// Gets current database connection. + /// Gets settings for the current snapshot store. /// - public DbConnection DbConnection { get { return _connection; } } + protected abstract SnapshotStoreSettings Settings { get; } /// /// Query builder used to convert snapshot store related operations into corresponding SQL queries. @@ -55,15 +57,7 @@ protected DbSnapshotStore() /// Query mapper used to map SQL query results into snapshots. /// public ISnapshotQueryMapper QueryMapper { get; set; } - - protected override void PreStart() - { - base.PreStart(); - - _connection = CreateDbConnection(); - _connection.Open(); - } - + protected override void PostStop() { base.PostStop(); @@ -78,75 +72,96 @@ protected override void PostStop() curr.Value.Cancel(); PendingOperations.Remove(curr); } + } - _connection.Close(); + protected virtual string GetConnectionString() + { + var connectionString = Settings.ConnectionString; + return string.IsNullOrEmpty(connectionString) + ? ConfigurationManager.ConnectionStrings[Settings.ConnectionStringName].ConnectionString + : connectionString; } /// /// Asynchronously loads snapshot with the highest sequence number for a persistent actor/view matching specified criteria. /// - protected override Task LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) + protected override async Task LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { - var sqlCommand = QueryBuilder.SelectSnapshot(persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp); - CompleteCommand(sqlCommand); + using (var connection = CreateDbConnection()) + { + await connection.OpenAsync(); + + var sqlCommand = QueryBuilder.SelectSnapshot(persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp); + CompleteCommand(sqlCommand, connection); - var tokenSource = GetCancellationTokenSource(); - return sqlCommand - .ExecuteReaderAsync(tokenSource.Token) - .ContinueWith(task => + var tokenSource = GetCancellationTokenSource(); + var reader = await sqlCommand.ExecuteReaderAsync(tokenSource.Token); + try { - var reader = task.Result; - try - { - return reader.Read() ? QueryMapper.Map(reader) : null; - } - finally - { - PendingOperations.Remove(tokenSource); - reader.Close(); - } - }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); + return reader.Read() ? QueryMapper.Map(reader) : null; + } + finally + { + PendingOperations.Remove(tokenSource); + reader.Close(); + } + } } /// /// Asynchronously stores a snapshot with metadata as record in SQL table. /// - protected override Task SaveAsync(SnapshotMetadata metadata, object snapshot) + protected override async Task SaveAsync(SnapshotMetadata metadata, object snapshot) { - var entry = ToSnapshotEntry(metadata, snapshot); - var sqlCommand = QueryBuilder.InsertSnapshot(entry); - CompleteCommand(sqlCommand); + using (var connection = CreateDbConnection()) + { + await connection.OpenAsync(); - var tokenSource = GetCancellationTokenSource(); + var entry = ToSnapshotEntry(metadata, snapshot); + var sqlCommand = QueryBuilder.InsertSnapshot(entry); + CompleteCommand(sqlCommand, connection); - return sqlCommand.ExecuteNonQueryAsync(tokenSource.Token) - .ContinueWith(task => + var tokenSource = GetCancellationTokenSource(); + try + { + await sqlCommand.ExecuteNonQueryAsync(tokenSource.Token); + } + finally { PendingOperations.Remove(tokenSource); - }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); + } + } } protected override void Saved(SnapshotMetadata metadata) { } - protected override void Delete(SnapshotMetadata metadata) + protected override async Task DeleteAsync(SnapshotMetadata metadata) { - var sqlCommand = QueryBuilder.DeleteOne(metadata.PersistenceId, metadata.SequenceNr, metadata.Timestamp); - CompleteCommand(sqlCommand); + using (var connection = CreateDbConnection()) + { + await connection.OpenAsync(); + var sqlCommand = QueryBuilder.DeleteOne(metadata.PersistenceId, metadata.SequenceNr, metadata.Timestamp); + CompleteCommand(sqlCommand, connection); - sqlCommand.ExecuteNonQuery(); + await sqlCommand.ExecuteNonQueryAsync(); + } } - protected override void Delete(string persistenceId, SnapshotSelectionCriteria criteria) + protected override async Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { - var sqlCommand = QueryBuilder.DeleteMany(persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp); - CompleteCommand(sqlCommand); + using (var connection = CreateDbConnection()) + { + await connection.OpenAsync(); + var sqlCommand = QueryBuilder.DeleteMany(persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp); + CompleteCommand(sqlCommand, connection); - sqlCommand.ExecuteNonQuery(); + await sqlCommand.ExecuteNonQueryAsync(); + } } - private void CompleteCommand(DbCommand command) + private void CompleteCommand(DbCommand command, DbConnection connection) { - command.Connection = _connection; + command.Connection = connection; command.CommandTimeout = (int)Settings.ConnectionTimeout.TotalMilliseconds; } diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj new file mode 100644 index 00000000000..4189fe6273a --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj @@ -0,0 +1,302 @@ + + + + + Debug + AnyCPU + {7A832BBF-053E-4E9F-BD83-D988A0130CC8} + Library + Properties + Akka.Persistence.Sqlite.Tests + Akka.Persistence.Sqlite.Tests + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + {ad9418b6-c452-4169-94fb-d43de0bfa966} + Akka.Persistence.TestKit + + + {fca84dea-c118-424b-9eb8-34375dfef18a} + Akka.Persistence + + + {0d3cbad0-bbdb-43e5-afc4-ed1d3ecdc224} + Akka.TestKit + + + {5deddf90-37f0-48d3-a0b0-a5cbd8a7e377} + Akka + + + {7dbd5c17-5e9d-40c4-9201-d092751532a7} + Akka.TestKit.Xunit2 + + + {e7bc4f35-b9fb-49cb-b12c-cd00f6a08ea2} + Akka.Persistence.Sql.Common.TestKit + + + {3b9e6211-9488-4db5-b714-24248693b38f} + Akka.Persistence.Sql.Common + + + {453efd22-7c53-4887-9dbf-fcfc9172e909} + Akka.Persistence.Sqlite + + + + + + + + + ..\..\..\..\packages\System.Data.SQLite.Core\lib\net45\System.Data.SQLite.dll + True + True + + + + + + + ..\..\..\..\packages\System.Data.SQLite.Core\lib\net46\System.Data.SQLite.dll + True + True + + + + + + + ..\..\..\..\packages\System.Data.SQLite.Core\lib\net20\System.Data.SQLite.dll + True + True + + + + + + + ..\..\..\..\packages\System.Data.SQLite.Core\lib\net40\System.Data.SQLite.dll + True + True + + + + + + + ..\..\..\..\packages\System.Data.SQLite.Core\lib\net451\System.Data.SQLite.dll + True + True + + + + + + + + <__paket__System_Data_SQLite_Core_targets>net45\System.Data.SQLite.Core + + + + + <__paket__System_Data_SQLite_Core_targets>net46\System.Data.SQLite.Core + + + + + <__paket__System_Data_SQLite_Core_targets>net20\System.Data.SQLite.Core + + + + + <__paket__System_Data_SQLite_Core_targets>net40\System.Data.SQLite.Core + + + + + <__paket__System_Data_SQLite_Core_targets>net451\System.Data.SQLite.Core + + + + + + + + + ..\..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll + True + True + + + + + + + + + ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll + True + True + + + + + + + + <__paket__xunit_core_props>win81\xunit.core + + + + + <__paket__xunit_core_props>wpa81\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core + + + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll + True + True + + + + + + + ..\..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll + True + True + + + + + \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Properties/AssemblyInfo.cs b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..a1ea9b52d10 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Akka.Persistence.Sqlite.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Akka.Persistence.Sqlite.Tests")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7a832bbf-053e-4e9f-bd83-d988a0130cc8")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalQuerySpec.cs b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalQuerySpec.cs new file mode 100644 index 00000000000..8b52dc8aebd --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalQuerySpec.cs @@ -0,0 +1,36 @@ +using Akka.Configuration; +using Akka.Persistence.Sql.Common.TestKit; +using Akka.Util.Internal; +using Xunit.Abstractions; + +namespace Akka.Persistence.Sqlite.Tests +{ + public class SqliteJournalQuerySpec : SqlJournalQuerySpec + { + private static AtomicCounter counter = new AtomicCounter(0); + + public SqliteJournalQuerySpec(ITestOutputHelper output) + : base(CreateSpecConfig("FullUri=file:memdb-journal-query-" + counter.IncrementAndGet() + ".db?mode=memory&cache=shared;"), "SqliteJournalQuerySpec", output: output) + { + Initialize(); + } + + private static Config CreateSpecConfig(string connectionString) + { + return ConfigurationFactory.ParseString(@" + akka.persistence { + publish-plugin-commands = on + journal { + plugin = ""akka.persistence.journal.sqlite"" + sqlite { + class = ""Akka.Persistence.Sqlite.Journal.SqliteJournal, Akka.Persistence.Sqlite"" + plugin-dispatcher = ""akka.actor.default-dispatcher"" + table-name = event_journal + auto-initialize = on + connection-string = """ + connectionString + @""" + } + } + }" + TimestampConfig("akka.persistence.journal.sqlite")); + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalSpec.cs b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalSpec.cs new file mode 100644 index 00000000000..0e537f55ed4 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalSpec.cs @@ -0,0 +1,38 @@ +using Akka.Configuration; +using Akka.Persistence.TestKit.Journal; +using Akka.Util.Internal; +using Xunit.Abstractions; + +namespace Akka.Persistence.Sqlite.Tests +{ + public class SqliteJournalSpec : JournalSpec + { + private static AtomicCounter counter = new AtomicCounter(0); + + public SqliteJournalSpec(ITestOutputHelper output) + : base(CreateSpecConfig("FullUri=file:memdb-journal-" + counter.IncrementAndGet() + ".db?mode=memory&cache=shared;"), "SqliteJournalSpec", output) + { + SqlitePersistence.Get(Sys); + + Initialize(); + } + + private static Config CreateSpecConfig(string connectionString) + { + return ConfigurationFactory.ParseString(@" + akka.persistence { + publish-plugin-commands = on + journal { + plugin = ""akka.persistence.journal.sqlite"" + sqlite { + class = ""Akka.Persistence.Sqlite.Journal.SqliteJournal, Akka.Persistence.Sqlite"" + plugin-dispatcher = ""akka.actor.default-dispatcher"" + table-name = event_journal + auto-initialize = on + connection-string = """ + connectionString + @""" + } + } + }"); + } + } +} diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteSnapshotStoreSpec.cs b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteSnapshotStoreSpec.cs new file mode 100644 index 00000000000..2274c9cee13 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteSnapshotStoreSpec.cs @@ -0,0 +1,37 @@ +using Akka.Configuration; +using Akka.Persistence.TestKit.Snapshot; +using Akka.Util.Internal; +using Xunit.Abstractions; + +namespace Akka.Persistence.Sqlite.Tests +{ + public class SqliteSnapshotStoreSpec : SnapshotStoreSpec + { + private static AtomicCounter counter = new AtomicCounter(0); + public SqliteSnapshotStoreSpec(ITestOutputHelper output) + : base(CreateSpecConfig("FullUri=file:memdb-snapshot-" + counter.IncrementAndGet() + ".db?mode=memory&cache=shared;"), "SqliteSnapshotStoreSpec", output) + { + SqlitePersistence.Get(Sys); + + Initialize(); + } + + private static Config CreateSpecConfig(string connectionString) + { + return ConfigurationFactory.ParseString(@" + akka.persistence { + publish-plugin-commands = on + snapshot-store { + plugin = ""akka.persistence.snapshot-store.sqlite"" + sqlite { + class = ""Akka.Persistence.Sqlite.Snapshot.SqliteSnapshotStore, Akka.Persistence.Sqlite"" + plugin-dispatcher = ""akka.actor.default-dispatcher"" + table-name = snapshot_store + auto-initialize = on + connection-string = """ + connectionString + @""" + } + } + }"); + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/paket.references b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/paket.references new file mode 100644 index 00000000000..16f189cb292 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/paket.references @@ -0,0 +1,6 @@ +System.Data.SQLite.Core + +group Test +xunit.core +xunit.assert +xunit.abstractions \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj new file mode 100644 index 00000000000..63fb2bc1f16 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj @@ -0,0 +1,157 @@ + + + + + Debug + AnyCPU + {453EFD22-7C53-4887-9DBF-FCFC9172E909} + Library + Properties + Akka.Persistence.Sqlite + Akka.Persistence.Sqlite + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + + + {fca84dea-c118-424b-9eb8-34375dfef18a} + Akka.Persistence + + + {5deddf90-37f0-48d3-a0b0-a5cbd8a7e377} + Akka + + + {3b9e6211-9488-4db5-b714-24248693b38f} + Akka.Persistence.Sql.Common + + + + + + + + + ..\..\..\..\packages\System.Data.SQLite.Core\lib\net45\System.Data.SQLite.dll + True + True + + + + + + + ..\..\..\..\packages\System.Data.SQLite.Core\lib\net46\System.Data.SQLite.dll + True + True + + + + + + + ..\..\..\..\packages\System.Data.SQLite.Core\lib\net20\System.Data.SQLite.dll + True + True + + + + + + + ..\..\..\..\packages\System.Data.SQLite.Core\lib\net40\System.Data.SQLite.dll + True + True + + + + + + + ..\..\..\..\packages\System.Data.SQLite.Core\lib\net451\System.Data.SQLite.dll + True + True + + + + + + + + <__paket__System_Data_SQLite_Core_targets>net45\System.Data.SQLite.Core + + + + + <__paket__System_Data_SQLite_Core_targets>net46\System.Data.SQLite.Core + + + + + <__paket__System_Data_SQLite_Core_targets>net20\System.Data.SQLite.Core + + + + + <__paket__System_Data_SQLite_Core_targets>net40\System.Data.SQLite.Core + + + + + <__paket__System_Data_SQLite_Core_targets>net451\System.Data.SQLite.Core + + + + + \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.nuspec b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.nuspec new file mode 100644 index 00000000000..0dbcafe25ce --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.nuspec @@ -0,0 +1,20 @@ + + + + @project@ + @project@@title@ + @build.number@ + @authors@ + @authors@ + Akka.NET Persistence journal and snapshot store backed by SQLite. + https://github.com/akkadotnet/akka.net/blob/master/LICENSE + https://github.com/akkadotnet/akka.net + http://getakka.net/images/AkkaNetLogo.Normal.png + false + @releaseNotes@ + @copyright@ + @tags@ persistence eventsource sqlserver + @dependencies@ + @references@ + + diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/ConnectionContext.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/ConnectionContext.cs new file mode 100644 index 00000000000..99415957e1d --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/ConnectionContext.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Concurrent; +using System.Data; +using System.Data.SQLite; + +namespace Akka.Persistence.Sqlite +{ + /// + /// This class has been made to make memory connections safe. In SQLite shared memory database exists as long, as there exists at least one opened connection to it. + /// + internal static class ConnectionContext + { + private static readonly ConcurrentDictionary Remembered = new ConcurrentDictionary(); + + public static SQLiteConnection Remember(string connectionString) + { + if (string.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString", "No connection string with connection to remember"); + + var conn = Remembered.GetOrAdd(connectionString, s => new SQLiteConnection(connectionString)); + + if (conn.State != ConnectionState.Open) + conn.Open(); + + return conn; + } + + public static void Forget(string connectionString) + { + SQLiteConnection conn; + if (Remembered.TryRemove(connectionString, out conn)) + { + conn.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/DbHelper.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/DbHelper.cs new file mode 100644 index 00000000000..b18328b56b2 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/DbHelper.cs @@ -0,0 +1,55 @@ +using System; +using System.Data.SQLite; + +namespace Akka.Persistence.Sqlite +{ + internal static class DbHelper + { + private const string JournalFormat = @" + CREATE TABLE IF NOT EXISTS {0} ( + persistence_id VARCHAR(255) NOT NULL, + sequence_nr INTEGER(8) NOT NULL, + is_deleted INTEGER(1) NOT NULL, + manifest VARCHAR(255) NOT NULL, + timestamp INTEGER NOT NULL, + payload BLOB NOT NULL, + PRIMARY KEY (persistence_id, sequence_nr) + );"; + + private const string SnapshotStoreFormat = @" + CREATE TABLE IF NOT EXISTS {0} ( + persistence_id VARCHAR(255) NOT NULL, + sequence_nr INTEGER(8) NOT NULL, + created_at INTEGER(8) NOT NULL, + manifest VARCHAR(255) NOT NULL, + snapshot BLOB NOT NULL, + PRIMARY KEY (persistence_id, sequence_nr) + );"; + + public static void CreateJournalTable(string connectionString, string tableName) + { + if (string.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString", "SqlitePersistence requires connection string to be provided"); + if (string.IsNullOrEmpty(tableName)) throw new ArgumentNullException("tableName", "SqlitePersistence requires journal table name to be provided"); + + using (var connection = new SQLiteConnection(connectionString)) + using (var command = new SQLiteCommand(string.Format(JournalFormat, tableName), connection)) + { + connection.Open(); + command.ExecuteNonQuery(); + } + } + + public static void CreateSnapshotStoreTable(string connectionString, string tableName) + { + if (string.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString", "SqlitePersistence requires connection string to be provided"); + if (string.IsNullOrEmpty(tableName)) throw new ArgumentNullException("tableName", "SqlitePersistence requires snapshot store table name to be provided"); + + using (var connection = new SQLiteConnection(connectionString)) + using (var command = new SQLiteCommand(string.Format(SnapshotStoreFormat, tableName), connection)) + { + connection.Open(); + command.ExecuteNonQuery(); + } + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Extension.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Extension.cs new file mode 100644 index 00000000000..0a196992384 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Extension.cs @@ -0,0 +1,99 @@ +using Akka.Actor; +using Akka.Configuration; +using Akka.Persistence.Sql.Common; + +namespace Akka.Persistence.Sqlite +{ + public class SqliteJournalSettings : JournalSettings + { + public const string ConfigPath = "akka.persistence.journal.sqlite"; + + /// + /// Flag determining in in case of event journal table missing, it should be automatically initialized. + /// + public bool AutoInitialize { get; private set; } + + public SqliteJournalSettings(Config config) : base(config) + { + AutoInitialize = config.GetBoolean("auto-initialize"); + } + } + + public class SqliteSnapshotSettings : SnapshotStoreSettings + { + public const string ConfigPath = "akka.persistence.snapshot-store.sqlite"; + + /// + /// Flag determining in in case of snapshot store table missing, it should be automatically initialized. + /// + public bool AutoInitialize { get; private set; } + + public SqliteSnapshotSettings(Config config) : base(config) + { + AutoInitialize = config.GetBoolean("auto-initialize"); + } + } + + public class SqlitePersistence : IExtension + { + /// + /// Returns a default configuration for akka persistence SQLite-based journals and snapshot stores. + /// + /// + public static Config DefaultConfiguration() + { + return ConfigurationFactory.FromResource("Akka.Persistence.Sqlite.sqlite.conf"); + } + + public static SqlitePersistence Get(ActorSystem system) + { + return system.WithExtension(); + } + + /// + /// Journal-related settings loaded from HOCON configuration. + /// + public readonly SqliteJournalSettings JournalSettings; + + /// + /// Snapshot store related settings loaded from HOCON configuration. + /// + public readonly SqliteSnapshotSettings SnapshotSettings; + + public SqlitePersistence(ExtendedActorSystem system) + { + system.Settings.InjectTopLevelFallback(DefaultConfiguration()); + + JournalSettings = new SqliteJournalSettings(system.Settings.Config.GetConfig(SqliteJournalSettings.ConfigPath)); + SnapshotSettings = new SqliteSnapshotSettings(system.Settings.Config.GetConfig(SqliteSnapshotSettings.ConfigPath)); + + if (!string.IsNullOrEmpty(JournalSettings.ConnectionString)) + { + ConnectionContext.Remember(JournalSettings.ConnectionString); + system.TerminationTask.ContinueWith(t => ConnectionContext.Forget(JournalSettings.ConnectionString)); + + if (JournalSettings.AutoInitialize) + DbHelper.CreateJournalTable(JournalSettings.ConnectionString, JournalSettings.TableName); + } + + if (!string.IsNullOrEmpty(SnapshotSettings.ConnectionString)) + { + ConnectionContext.Remember(SnapshotSettings.ConnectionString); + system.TerminationTask.ContinueWith(t => ConnectionContext.Forget(SnapshotSettings.ConnectionString)); + + if (SnapshotSettings.AutoInitialize) + { + DbHelper.CreateSnapshotStoreTable(SnapshotSettings.ConnectionString, SnapshotSettings.TableName); + } + } + } + } + + public class SqlitePersistenceProvder : ExtensionIdProvider + { + public override SqlitePersistence CreateExtension(ExtendedActorSystem system) + { + return new SqlitePersistence(system); + } + } +} diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteJournal.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteJournal.cs new file mode 100644 index 00000000000..a09049f50b6 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteJournal.cs @@ -0,0 +1,41 @@ +using System.Data.Common; +using System.Data.SQLite; +using Akka.Actor; +using Akka.Persistence.Sql.Common.Journal; + +namespace Akka.Persistence.Sqlite.Journal +{ + public class SqliteJournalEngine : JournalDbEngine + { + public SqliteJournalEngine(ActorSystem system) + : base(system) + { + QueryBuilder = new SqliteQueryBuilder(Settings.TableName); + } + + protected override string JournalConfigPath { get { return SqliteJournalSettings.ConfigPath; } } + + protected override DbConnection CreateDbConnection(string connectionString) + { + return new SQLiteConnection(connectionString); + } + + protected override void CopyParamsToCommand(DbCommand sqlCommand, JournalEntry entry) + { + sqlCommand.Parameters["@PersistenceId"].Value = entry.PersistenceId; + sqlCommand.Parameters["@SequenceNr"].Value = entry.SequenceNr; + sqlCommand.Parameters["@IsDeleted"].Value = entry.IsDeleted; + sqlCommand.Parameters["@Manifest"].Value = entry.Manifest; + sqlCommand.Parameters["@Timestamp"].Value = entry.Timestamp; + sqlCommand.Parameters["@Payload"].Value = entry.Payload; + } + } + + public class SqliteJournal : SqlJournal + { + public readonly SqlitePersistence Extension = SqlitePersistence.Get(Context.System); + public SqliteJournal() : base(new SqliteJournalEngine(Context.System)) + { + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteQueryBuilder.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteQueryBuilder.cs new file mode 100644 index 00000000000..131f556445b --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteQueryBuilder.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SQLite; +using System.Linq; +using System.Text; +using Akka.Persistence.Sql.Common.Journal; +using Akka.Persistence.Sql.Common.Queries; + +namespace Akka.Persistence.Sqlite.Journal +{ + internal class SqliteQueryBuilder : IJournalQueryBuilder + { + private readonly string _tableName; + + private readonly string _selectHighestSequenceNrSql; + private readonly string _insertMessagesSql; + + public SqliteQueryBuilder(string tableName) + { + _tableName = tableName; + _insertMessagesSql = string.Format( + "INSERT INTO {0} (persistence_id, sequence_nr, is_deleted, manifest, timestamp, payload) VALUES (@PersistenceId, @SequenceNr, @IsDeleted, @Manifest, @Timestamp, @Payload)", _tableName); + _selectHighestSequenceNrSql = string.Format(@"SELECT MAX(sequence_nr) FROM {0} WHERE persistence_id = ? ", _tableName); + } + + public DbCommand SelectEvents(IEnumerable hints) + { + var sqlCommand = new SQLiteCommand(); + + var sqlized = hints + .Select(h => HintToSql(h, sqlCommand)) + .Where(x => !string.IsNullOrEmpty(x)); + + var where = string.Join(" AND ", sqlized); + var sql = new StringBuilder("SELECT persistence_id, sequence_nr, is_deleted, manifest, payload FROM " + _tableName); + if (!string.IsNullOrEmpty(where)) + { + sql.Append(" WHERE ").Append(where); + } + + sqlCommand.CommandText = sql.ToString(); + return sqlCommand; + } + + private string HintToSql(IHint hint, SQLiteCommand command) + { + if (hint is TimestampRange) + { + var range = (TimestampRange)hint; + var sb = new StringBuilder(); + + if (range.From.HasValue) + { + sb.Append(" timestamp >= @TimestampFrom "); + command.Parameters.AddWithValue("@TimestampFrom", range.From.Value); + } + if (range.From.HasValue && range.To.HasValue) sb.Append("AND"); + if (range.To.HasValue) + { + sb.Append(" timestamp < @TimestampTo "); + command.Parameters.AddWithValue("@TimestampTo", range.To.Value); + } + + return sb.ToString(); + } + if (hint is PersistenceIdRange) + { + var range = (PersistenceIdRange)hint; + var sb = new StringBuilder(" persistence_id IN ("); + var i = 0; + foreach (var persistenceId in range.PersistenceIds) + { + var paramName = "@Pid" + (i++); + sb.Append(paramName).Append(','); + command.Parameters.AddWithValue(paramName, persistenceId); + } + return range.PersistenceIds.Count == 0 + ? string.Empty + : sb.Remove(sb.Length - 1, 1).Append(')').ToString(); + } + else if (hint is WithManifest) + { + var manifest = (WithManifest)hint; + command.Parameters.AddWithValue("@Manifest", manifest.Manifest); + return " manifest = @Manifest"; + } + else throw new NotSupportedException(string.Format("Sqlite journal doesn't support query with hint [{0}]", hint.GetType())); + } + + public DbCommand SelectMessages(string persistenceId, long fromSequenceNr, long toSequenceNr, long max) + { + var sb = new StringBuilder(@" + SELECT persistence_id, sequence_nr, is_deleted, manifest, payload FROM ").Append(_tableName) + .Append(" WHERE persistence_id = ? "); + + if (fromSequenceNr > 0) + { + if (toSequenceNr != long.MaxValue) + sb.Append(" AND sequence_nr BETWEEN ") + .Append(fromSequenceNr) + .Append(" AND ") + .Append(toSequenceNr); + else + sb.Append(" AND sequence_nr >= ").Append(fromSequenceNr); + } + + if (toSequenceNr != long.MaxValue) + sb.Append(" AND sequence_nr <= ").Append(toSequenceNr); + + if (max != long.MaxValue) + { + sb.Append(" LIMIT ").Append(max); + } + + var command = new SQLiteCommand(sb.ToString()) + { + Parameters = { new SQLiteParameter { Value = persistenceId } } + }; + + return command; + } + + public DbCommand SelectHighestSequenceNr(string persistenceId) + { + return new SQLiteCommand(_selectHighestSequenceNrSql) + { + Parameters = { new SQLiteParameter { Value = persistenceId } } + }; + } + + public DbCommand InsertBatchMessages(IPersistentRepresentation[] messages) + { + var command = new SQLiteCommand(_insertMessagesSql); + command.Parameters.Add("@PersistenceId", DbType.String); + command.Parameters.Add("@SequenceNr", DbType.Int64); + command.Parameters.Add("@IsDeleted", DbType.Boolean); + command.Parameters.Add("@Manifest", DbType.String); + command.Parameters.Add("@Timestamp", DbType.DateTime); + command.Parameters.Add("@Payload", DbType.Binary); + + return command; + } + + public DbCommand DeleteBatchMessages(string persistenceId, long toSequenceNr, bool permanent) + { + var sb = new StringBuilder(); + + if (permanent) + { + sb.Append("DELETE FROM ").Append(_tableName); + } + else + { + sb.AppendFormat("UPDATE {0} SET is_deleted = 1", _tableName); + } + + sb.Append(" WHERE persistence_id = ?"); + + if (toSequenceNr != long.MaxValue) + { + sb.Append(" AND sequence_nr <= ").Append(toSequenceNr); + } + + return new SQLiteCommand(sb.ToString()) + { + Parameters = { new SQLiteParameter { Value = persistenceId } } + }; + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Properties/AssemblyInfo.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..54e9a7dba57 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Akka.Persistence.Sqlite")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Akka.Persistence.Sqlite")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("453efd22-7c53-4887-9dbf-fcfc9172e909")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/README.md b/src/contrib/persistence/Akka.Persistence.Sqlite/README.md new file mode 100644 index 00000000000..5eaad2d2cb7 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/README.md @@ -0,0 +1,73 @@ +## Akka.Persistence.Sqlite + +Akka Persistence journal and snapshot store backed by SQL Server database. + +**WARNING: Akka.Persistence.Sqlite plugin is still in beta and it's mechanics described bellow may be still subject to change**. + +### Setup + +To activate the journal plugin, add the following lines to actor system configuration file: + +``` +akka.persistence.journal.plugin = "akka.persistence.journal.sqlite" +akka.persistence.journal.sqlite.connection-string = "" +``` + +Similar configuration may be used to setup a SQL Server snapshot store: + +``` +akka.persistence.snapshot-store.plugin = "akka.persistence.snapshot-store.sqlite" +akka.persistence.snapshot-store.sqlite.connection-string = "" +``` + +Remember that connection string must be provided separately to Journal and Snapshot Store. To finish setup simply initialize plugin using: `SqlitePersistence.Get(actorSystem);` + +### Configuration + +Both journal and snapshot store share the same configuration keys (however they resides in separate scopes, so they are definied distinctly for either journal or snapshot store): + +- `class` (string with fully qualified type name) - determines class to be used as a persistent journal. Default: *Akka.Persistence.Sqlite.Journal.SqliteJournal, Akka.Persistence.Sqlite* (for journal) and *Akka.Persistence.Sqlite.Snapshot.SqliteSnapshotStore, Akka.Persistence.Sqlite* (for snapshot store). +- `plugin-dispatcher` (string with configuration path) - describes a message dispatcher for persistent journal. Default: *akka.actor.default-dispatcher* +- `connection-string` - connection string used to access SQL Server database. Default: *none*. +- `connection-timeout` - timespan determining default connection timeouts on database-related operations. Default: *30s* +- `table-name` - name of the table used by either journal or snapshot store. Default: *event_journal* (for journal) or *snapshot_store* (for snapshot store) +- `auto-initialize` - flag determining if journal or snapshot store related tables should by automatically created when they have not been found in connected database. Default: *false* + +In addition, journal configuration specifies additional field: + +- `timestamp-provider` - fully qualified type name (with assembly) of the class responsible for generating timestamp values based on persisted message type. By default this points to *Akka.Persistence.Sql.Common.Journal.DefaultTimestampProvider, Akka.Persistence.Sql.Common*, which returns current UTC DateTime value. + +### In-memory databases + +Akka.Persistence.Sqlite plugin allows to use in-memory databases, however requires to use them in shared mode in order to work correctly. Example connection strings for such configurations are described below: + +- `FullUri=file::memory:?cache=shared;` for anonymous in-memory database instances. +- `FullUri=file:.db?mode=memory&cache=shared;` for named in-memory database instances. This way you can provide many separate databases residing in memory. + +### Custom SQL data queries + +SQLite persistence plugin defines a default table schema used for both journal and snapshot store. + +**EventJournal table**: + + +----------------+-------------+------------+----------------+------------+---------+ + | persistence_id | sequence_nr | is_deleted | manifest | timestamp | payload | + +----------------+-------------+------------+----------------+------------+---------+ + | varchar(255) | integer(8) | integer(1) | varchar(255) | integer(8) | blob | + +----------------+-------------+------------+----------------+------------+---------+ + +**SnapshotStore table**: + + +----------------+-------------+------------+----------------+----------+ + | persistence_id | sequence_nr | created_at | manifest | snapshot | + +----------------+-------------+------------+----------------+----------+ + | varchar(255) | integer(8) | integer(8) | varchar(255) | blob | + +----------------+-------------+------------+----------------+----------+ + +`created_at` column maps to `System.DateTime` value represented by it's ticks, to achieve 1 to 1 precision of dates between SQLite and .NET environment. + +Underneath Akka.Persistence.Sqlite uses a raw ADO.NET commands. You may choose not to use a dedicated built in ones, but to create your own being better fit for your use case. To do so, you have to create your own versions of `IJournalQueryBuilder` and `IJournalQueryMapper` (for custom journals) or `ISnapshotQueryBuilder` and `ISnapshotQueryMapper` (for custom snapshot store). + +### Tests + +The SQLite tests are packaged and run as part of the default "All" build task. They use dedicated shared in memory instances of SQLite database and can be executed in parallel. diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/QueryBuilder.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/QueryBuilder.cs new file mode 100644 index 00000000000..4f0a38f29ca --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/QueryBuilder.cs @@ -0,0 +1,103 @@ +using System; +using System.Data; +using System.Data.Common; +using System.Data.SQLite; +using System.Text; +using Akka.Persistence.Sql.Common.Snapshot; + +namespace Akka.Persistence.Sqlite.Snapshot +{ + internal class QueryBuilder : ISnapshotQueryBuilder + { + private readonly string _deleteSql; + private readonly string _insertSql; + private readonly string _selectSql; + + public QueryBuilder(SqliteSnapshotSettings settings) + { + _deleteSql = string.Format(@"DELETE FROM {0} WHERE persistence_id = ? ", settings.TableName); + _insertSql = string.Format(@"INSERT INTO {0} (persistence_id, sequence_nr, created_at, manifest, snapshot) VALUES (@PersistenceId, @SequenceNr, @Timestamp, @Manifest, @Snapshot)", settings.TableName); + _selectSql = string.Format(@"SELECT persistence_id, sequence_nr, created_at, manifest, snapshot FROM {0} WHERE persistence_id = ? ", settings.TableName); + } + + public DbCommand DeleteOne(string persistenceId, long sequenceNr, DateTime timestamp) + { + var sqlCommand = new SQLiteCommand(); + sqlCommand.Parameters.Add(new SQLiteParameter { Value = persistenceId }); + var sb = new StringBuilder(_deleteSql); + + if (sequenceNr < long.MaxValue && sequenceNr > 0) + { + sb.Append(@" AND sequence_nr = ").Append(sequenceNr); + } + + if (timestamp > DateTime.MinValue && timestamp < DateTime.MaxValue) + { + sb.AppendFormat(@" AND created_at = {0}", timestamp.Ticks); + } + + sqlCommand.CommandText = sb.ToString(); + + return sqlCommand; + } + + public DbCommand DeleteMany(string persistenceId, long maxSequenceNr, DateTime maxTimestamp) + { + var sqlCommand = new SQLiteCommand(); + sqlCommand.Parameters.Add(new SQLiteParameter { Value = persistenceId }); + var sb = new StringBuilder(_deleteSql); + + if (maxSequenceNr < long.MaxValue && maxSequenceNr > 0) + { + sb.Append(@" AND sequence_nr <= ").Append(maxSequenceNr); + } + + if (maxTimestamp > DateTime.MinValue && maxTimestamp < DateTime.MaxValue) + { + sb.AppendFormat(@" AND created_at <= {0}", maxTimestamp.Ticks); + } + + sqlCommand.CommandText = sb.ToString(); + + return sqlCommand; + } + + public DbCommand InsertSnapshot(SnapshotEntry entry) + { + var sqlCommand = new SQLiteCommand(_insertSql) + { + Parameters = + { + new SQLiteParameter("@PersistenceId", DbType.String, entry.PersistenceId.Length) { Value = entry.PersistenceId }, + new SQLiteParameter("@SequenceNr", DbType.Int64) { Value = entry.SequenceNr }, + new SQLiteParameter("@Timestamp", DbType.Int64) { Value = entry.Timestamp.Ticks }, + new SQLiteParameter("@Manifest", DbType.String, entry.SnapshotType.Length) { Value = entry.SnapshotType }, + new SQLiteParameter("@Snapshot", DbType.Binary, entry.Snapshot.Length) { Value = entry.Snapshot } + } + }; + + return sqlCommand; + } + + public DbCommand SelectSnapshot(string persistenceId, long maxSequenceNr, DateTime maxTimestamp) + { + var sqlCommand = new SQLiteCommand(); + sqlCommand.Parameters.Add(new SQLiteParameter { Value = persistenceId }); + + var sb = new StringBuilder(_selectSql); + if (maxSequenceNr > 0 && maxSequenceNr < long.MaxValue) + { + sb.Append(" AND sequence_nr <= ").Append(maxSequenceNr); + } + + if (maxTimestamp > DateTime.MinValue && maxTimestamp < DateTime.MaxValue) + { + sb.AppendFormat(" AND created_at <= {0} ", maxTimestamp.Ticks); + } + + sb.Append(" ORDER BY sequence_nr DESC"); + sqlCommand.CommandText = sb.ToString(); + return sqlCommand; + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteQueryMapper.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteQueryMapper.cs new file mode 100644 index 00000000000..4688bb53113 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteQueryMapper.cs @@ -0,0 +1,39 @@ +using System; +using System.Data.Common; +using Akka.Persistence.Sql.Common.Snapshot; + +namespace Akka.Persistence.Sqlite.Snapshot +{ + internal class SqliteQueryMapper : ISnapshotQueryMapper + { + private readonly Akka.Serialization.Serialization _serialization; + + public SqliteQueryMapper(Akka.Serialization.Serialization serialization) + { + _serialization = serialization; + } + + public SelectedSnapshot Map(DbDataReader reader) + { + var persistenceId = reader.GetString(0); + var sequenceNr = reader.GetInt64(1); + var timestamp = new DateTime(reader.GetInt64(2)); + + var metadata = new SnapshotMetadata(persistenceId, sequenceNr, timestamp); + var snapshot = GetSnapshot(reader); + + return new SelectedSnapshot(metadata, snapshot); + } + + private object GetSnapshot(DbDataReader reader) + { + var type = Type.GetType(reader.GetString(3), true); + var serializer = _serialization.FindSerializerForType(type); + var binary = (byte[])reader[4]; + + var obj = serializer.FromBinary(binary, type); + + return obj; + } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteSnapshotStore.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteSnapshotStore.cs new file mode 100644 index 00000000000..443cb44e37d --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteSnapshotStore.cs @@ -0,0 +1,27 @@ +using System.Data.Common; +using System.Data.SQLite; +using Akka.Persistence.Sql.Common; +using Akka.Persistence.Sql.Common.Snapshot; + +namespace Akka.Persistence.Sqlite.Snapshot +{ + public class SqliteSnapshotStore : SqlSnapshotStore + { + private readonly SqlitePersistence _extension; + + public SqliteSnapshotStore() + { + _extension = SqlitePersistence.Get(Context.System); + QueryBuilder = new QueryBuilder(_extension.SnapshotSettings); + QueryMapper = new SqliteQueryMapper(Context.System.Serialization); + } + + + protected override DbConnection CreateDbConnection(string connectionString) + { + return new SQLiteConnection(connectionString); + } + + protected override SnapshotStoreSettings Settings { get { return _extension.SnapshotSettings; } } + } +} \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/paket.references b/src/contrib/persistence/Akka.Persistence.Sqlite/paket.references new file mode 100644 index 00000000000..e72d54b641b --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/paket.references @@ -0,0 +1 @@ +System.Data.SQLite.Core \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/sqlite.conf b/src/contrib/persistence/Akka.Persistence.Sqlite/sqlite.conf new file mode 100644 index 00000000000..23e99edc74a --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/sqlite.conf @@ -0,0 +1,63 @@ +akka.persistence{ + + journal { + sqlite { + + # qualified type name of the SQL Server persistence journal actor + class = "Akka.Persistence.SqlServer.Journal.SqlServerJournal, Akka.Persistence.SqlServer" + + # dispatcher used to drive journal actor + plugin-dispatcher = "akka.actor.default-dispatcher" + + # connection string used for database access + connection-string = "" + + # connection string name for .config file used when no connection string has been provided + connection-string-name = "" + + # default SQL commands timeout + connection-timeout = 30s + + # SQL server schema name to table corresponding with persistent journal + schema-name = dbo + + # SQL server table corresponding with persistent journal + table-name = event_journal + + # should corresponding journal table be initialized automatically + auto-initialize = off + + # timestamp provider used for generation of journal entries timestamps + timestamp-provider = "Akka.Persistence.Sql.Common.Journal.DefaultTimestampProvider, Akka.Persistence.Sql.Common" + } + } + + snapshot-store { + sqlite { + + # qualified type name of the SQL Server persistence journal actor + class = "Akka.Persistence.SqlServer.Snapshot.SqlServerSnapshotStore, Akka.Persistence.SqlServer" + + # dispatcher used to drive journal actor + plugin-dispatcher = ""akka.actor.default-dispatcher"" + + # connection string used for database access + connection-string = "" + + # connection string name for .config file used when no connection string has been provided + connection-string-name = "" + + # default SQL commands timeout + connection-timeout = 30s + + # SQL server schema name to table corresponding with persistent journal + schema-name = dbo + + # SQL server table corresponding with persistent journal + table-name = snapshot_store + + # should corresponding journal table be initialized automatically + auto-initialize = off + } + } +} \ No newline at end of file diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj b/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj index 24b9941da27..fcc08ba79e7 100644 --- a/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj @@ -31,6 +31,24 @@ 4 + + True + + + True + + + True + + + True + + + True + + + True + @@ -66,35 +84,7 @@ --> - - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll - True - True - - - - + ..\..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll @@ -136,7 +126,7 @@ - + ..\..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/CHANGES.txt b/src/contrib/transports/Akka.Remote.AkkaIOTransport/CHANGES.txt new file mode 100644 index 00000000000..d80368c78f2 --- /dev/null +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/CHANGES.txt @@ -0,0 +1,99 @@ +=============================================================================== +Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet +(skeet@pobox.com) based on the work of many talented people. + +For more information about this port, visit its homepage: +http://protobuf-csharp-port.googlecode.com + +For more information about Protocol Buffers in general, visit the project page +for the C++, Java and Python project: +http://protobuf.googlecode.com +=============================================================================== +RELEASE NOTES - Version 2.4.1.473 +=============================================================================== + +Features: +- Added option service_generator_type to control service generation with + NONE, GENERIC, INTERFACE, or IRPCDISPATCH +- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking + services and implementations. +- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the + location of protoc.exe. +- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow + custom implementation of writers with both speed and size optimizations. +- Addition of the "Google.ProtoBuffers.Serialization" assembly to support + reading and writing messages to/from XML, JSON, IDictionary<,> and others. +- Several performance related fixes and tweeks +- Issue 3: Add option to mark generated code with attribute +- Issue 20: Support for decorating classes [Serializable] +- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] +- Issue 22: Reusable Builder classes +- Issue 24: Support for using Json/Xml formats with ICodedInputStream +- Issue 25: Added support for NuGet packages +- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 + +Fixes: +- Issue 13: Message with Field same name as message causes uncompilable .cs +- Issue 16: Does not integrate well with other tooling +- Issue 19: Support for negative enum values +- Issue 26: AddRange in GeneratedBuilder iterates twice. +- Issue 27: Remove XML documentation output from test projects to clear + warnings/errors. +- Issue 28: Circular message dependencies result in null default values for + Message fields. +- Issue 29: Message classes generated have a public default constructor. You + can disable private ctor generation with the option generate_private_ctor. +- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ +- Big-endian support for float, and double on Silverlight +- Packed and Unpacked parsing allow for all repeated, as per version 2.3 +- Fix for leaving Builder a public ctor on internal classes for use with + generic "where T: new()" constraints. + +Other: +- Changed the code signing key to a privately held key +- Reformatted all code and line-endings to C# defaults +- Reworking of performance benchmarks to produce reliable results, option /v2 +- Issue 34: Silverlight assemblies are now unit tested + +=============================================================================== +RELEASE NOTES - Version 2.3.0.277 +=============================================================================== + +Features: +- Added cls_compliance option to generate attributes indicating + non-CLS-compliance. +- Added file_extension option to control the generated output file's extension. +- Added umbrella_namespace option to place the umbrella class into a nested + namespace to address issues with proto files having the same name as a + message it contains. +- Added output_directory option to set the output path for the source file(s). +- Added ignore_google_protobuf option to avoid generating code for includes + from the google.protobuf package. +- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to + generate code with "option optimize_for = LITE_RUNTIME;". +- Added ability to invoke protoc.exe from within ProtoGen.exe. +- Upgraded to protoc.exe (2.3) compiler. + +Fixes: +- Issue 9: Class cannot be static and sealed error +- Issue 12: default value for enumerate fields must be filled out + +Other: +- Rewrite of build using MSBbuild instead of NAnt +- Moved to NUnit Version 2.2.8.0 +- Changed to using secure .snk for releases + +=============================================================================== +RELEASE NOTES - Version 0.9.1 +=============================================================================== + +Fixes: +- issue 10: Incorrect encoding of packed fields when serialized + +=============================================================================== +RELEASE NOTES - Version 0.9.0 +=============================================================================== + +- Initial release + +=============================================================================== \ No newline at end of file diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/licenses/license.txt b/src/contrib/transports/Akka.Remote.AkkaIOTransport/licenses/license.txt new file mode 100644 index 00000000000..b8e773b2e05 --- /dev/null +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/licenses/license.txt @@ -0,0 +1,31 @@ +Protocol Buffers - Google's data interchange format +Copyright 2008-2010 Google Inc. All rights reserved. +http://github.com/jskeet/dotnet-protobufs/ +Original C++/Java/Python code: +http://code.google.com/p/protobuf/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/licenses/protoc-license.txt b/src/contrib/transports/Akka.Remote.AkkaIOTransport/licenses/protoc-license.txt new file mode 100644 index 00000000000..c779cb0e1ed --- /dev/null +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/licenses/protoc-license.txt @@ -0,0 +1,36 @@ +protoc.exe was built from the original source at http://code.google.com/p/protobuf/ +The licence for this code is as follows: + +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. \ No newline at end of file diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/google/protobuf/csharp_options.proto b/src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/google/protobuf/csharp_options.proto new file mode 100644 index 00000000000..152df766f03 --- /dev/null +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/google/protobuf/csharp_options.proto @@ -0,0 +1,115 @@ +// Extra options for C# generator + +import "google/protobuf/descriptor.proto"; + +package google.protobuf; + +message CSharpFileOptions { + + // Namespace for generated classes; defaults to the package. + optional string namespace = 1; + + // Name of the "umbrella" class used for metadata about all + // the messages within this file. Default is based on the name + // of the file. + optional string umbrella_classname = 2; + + // Whether classes should be public (true) or internal (false) + optional bool public_classes = 3 [default = true]; + + // Whether to generate a single file for everything within the + // .proto file (false), or one file per message (true). + // This option is not currently honored; please log a feature + // request if you really want it. + optional bool multiple_files = 4; + + // Whether to nest messages within a single umbrella class (true) + // or create the umbrella class as a peer, with messages as + // top-level classes in the namespace (false) + optional bool nest_classes = 5; + + // Generate appropriate support for Code Contracts + // (Ongoing; support should improve over time) + optional bool code_contracts = 6; + + // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" + // would generate files within [output directory]/Foo/Bar + optional bool expand_namespace_directories = 7; + + // Generate attributes indicating non-CLS-compliance + optional bool cls_compliance = 8 [default = true]; + + // Generate messages/builders with the [Serializable] attribute + optional bool add_serializable = 9 [default = false]; + + // Generates a private ctor for Message types + optional bool generate_private_ctor = 10 [default = true]; + + // The extension that should be appended to the umbrella_classname when creating files. + optional string file_extension = 221 [default = ".cs"]; + + // A nested namespace for the umbrella class. Helpful for name collisions caused by + // umbrella_classname conflicting with an existing type. This will be automatically + // set to 'Proto' if a collision is detected with types being generated. This value + // is ignored when nest_classes == true + optional string umbrella_namespace = 222; + + // The output path for the source file(s) generated + optional string output_directory = 223 [default = "."]; + + // Will ignore the type generations and remove dependencies for the descriptor proto + // files that declare their package to be "google.protobuf" + optional bool ignore_google_protobuf = 224 [default = false]; + + // Controls how services are generated, GENERIC is the deprecated original implementation + // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and + // implementations using the included Windows RPC interop libarary. + optional CSharpServiceType service_generator_type = 225 [default = NONE]; + + // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and + // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. + optional bool generated_code_attributes = 226 [default = false]; +} + +enum CSharpServiceType { + // Services are ignored by the generator + NONE = 0; + // Generates the original Java generic service implementations + GENERIC = 1; + // Generates an interface for the service and nothing else + INTERFACE = 2; + // Generates an interface for the service and client/server wrappers for the interface + IRPCDISPATCH = 3; +} + +extend FileOptions { + optional CSharpFileOptions csharp_file_options = 1000; +} + +extend FieldOptions { + optional CSharpFieldOptions csharp_field_options = 1000; +} + +message CSharpFieldOptions { + // Provides the ability to override the name of the property + // generated for this field. This is applied to all properties + // and methods to do with this field, including HasFoo, FooCount, + // FooList etc. + optional string property_name = 1; +} + +message CSharpServiceOptions { + optional string interface_id = 1; +} + +extend ServiceOptions { + optional CSharpServiceOptions csharp_service_options = 1000; +} + +message CSharpMethodOptions { + optional int32 dispatch_id = 1; +} + +extend MethodOptions { + optional CSharpMethodOptions csharp_method_options = 1000; +} \ No newline at end of file diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/google/protobuf/descriptor.proto b/src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/google/protobuf/descriptor.proto new file mode 100644 index 00000000000..233f879410e --- /dev/null +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/google/protobuf/descriptor.proto @@ -0,0 +1,533 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + + +package google.protobuf; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + optional MessageOptions options = 7; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4; + TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + optional FieldOptions options = 8; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; +} + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail kenton@google.com to reserve extension +// numbers. Simply tell me how many you need and I'll send you back a +// set of numbers to use -- there's no need to explain how you intend to +// use them. If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. This is + // purely a speed optimization, as the AbstractMessage base class includes + // reflection-based implementations of these methods. + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of proto2. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. + optional bool packed = 2; + + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // EXPERIMENTAL. DO NOT USE. + // For "map" fields, the name of the field in the enclosed type that + // is the key for this map. For example, suppose we have: + // message Item { + // required string name = 1; + // required string value = 2; + // } + // message Config { + // repeated Item items = 1 [experimental_map_key="name"]; + // } + // In this situation, the map key for Item will be set to "name". + // TODO: Fully-implement this, then remove the "experimental_" prefix. + optional string experimental_map_key = 9; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // TODO(kenton): Record comments appearing before and after the + // declaration. + } +} diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/tutorial/addressbook.proto b/src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/tutorial/addressbook.proto new file mode 100644 index 00000000000..5abe35ce39b --- /dev/null +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/protos/tutorial/addressbook.proto @@ -0,0 +1,31 @@ +package tutorial; + +import "google/protobuf/csharp_options.proto"; +option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; +option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; + +option optimize_for = SPEED; + +message Person { + required string name = 1; + required int32 id = 2; // Unique ID number for this person. + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person person = 1; +} diff --git a/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj b/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj index 87634eb3e16..eb8385511dd 100644 --- a/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj +++ b/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj @@ -31,6 +31,24 @@ 4 + + True + + + True + + + True + + + True + + + True + + + True + @@ -133,35 +151,7 @@ --> - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll - True - True - - - - + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll @@ -203,7 +193,7 @@ - + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll diff --git a/src/core/Akka.Cluster.Tests/CHANGES.txt b/src/core/Akka.Cluster.Tests/CHANGES.txt new file mode 100644 index 00000000000..d80368c78f2 --- /dev/null +++ b/src/core/Akka.Cluster.Tests/CHANGES.txt @@ -0,0 +1,99 @@ +=============================================================================== +Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet +(skeet@pobox.com) based on the work of many talented people. + +For more information about this port, visit its homepage: +http://protobuf-csharp-port.googlecode.com + +For more information about Protocol Buffers in general, visit the project page +for the C++, Java and Python project: +http://protobuf.googlecode.com +=============================================================================== +RELEASE NOTES - Version 2.4.1.473 +=============================================================================== + +Features: +- Added option service_generator_type to control service generation with + NONE, GENERIC, INTERFACE, or IRPCDISPATCH +- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking + services and implementations. +- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the + location of protoc.exe. +- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow + custom implementation of writers with both speed and size optimizations. +- Addition of the "Google.ProtoBuffers.Serialization" assembly to support + reading and writing messages to/from XML, JSON, IDictionary<,> and others. +- Several performance related fixes and tweeks +- Issue 3: Add option to mark generated code with attribute +- Issue 20: Support for decorating classes [Serializable] +- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] +- Issue 22: Reusable Builder classes +- Issue 24: Support for using Json/Xml formats with ICodedInputStream +- Issue 25: Added support for NuGet packages +- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 + +Fixes: +- Issue 13: Message with Field same name as message causes uncompilable .cs +- Issue 16: Does not integrate well with other tooling +- Issue 19: Support for negative enum values +- Issue 26: AddRange in GeneratedBuilder iterates twice. +- Issue 27: Remove XML documentation output from test projects to clear + warnings/errors. +- Issue 28: Circular message dependencies result in null default values for + Message fields. +- Issue 29: Message classes generated have a public default constructor. You + can disable private ctor generation with the option generate_private_ctor. +- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ +- Big-endian support for float, and double on Silverlight +- Packed and Unpacked parsing allow for all repeated, as per version 2.3 +- Fix for leaving Builder a public ctor on internal classes for use with + generic "where T: new()" constraints. + +Other: +- Changed the code signing key to a privately held key +- Reformatted all code and line-endings to C# defaults +- Reworking of performance benchmarks to produce reliable results, option /v2 +- Issue 34: Silverlight assemblies are now unit tested + +=============================================================================== +RELEASE NOTES - Version 2.3.0.277 +=============================================================================== + +Features: +- Added cls_compliance option to generate attributes indicating + non-CLS-compliance. +- Added file_extension option to control the generated output file's extension. +- Added umbrella_namespace option to place the umbrella class into a nested + namespace to address issues with proto files having the same name as a + message it contains. +- Added output_directory option to set the output path for the source file(s). +- Added ignore_google_protobuf option to avoid generating code for includes + from the google.protobuf package. +- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to + generate code with "option optimize_for = LITE_RUNTIME;". +- Added ability to invoke protoc.exe from within ProtoGen.exe. +- Upgraded to protoc.exe (2.3) compiler. + +Fixes: +- Issue 9: Class cannot be static and sealed error +- Issue 12: default value for enumerate fields must be filled out + +Other: +- Rewrite of build using MSBbuild instead of NAnt +- Moved to NUnit Version 2.2.8.0 +- Changed to using secure .snk for releases + +=============================================================================== +RELEASE NOTES - Version 0.9.1 +=============================================================================== + +Fixes: +- issue 10: Incorrect encoding of packed fields when serialized + +=============================================================================== +RELEASE NOTES - Version 0.9.0 +=============================================================================== + +- Initial release + +=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/licenses/license.txt b/src/core/Akka.Cluster.Tests/licenses/license.txt new file mode 100644 index 00000000000..b8e773b2e05 --- /dev/null +++ b/src/core/Akka.Cluster.Tests/licenses/license.txt @@ -0,0 +1,31 @@ +Protocol Buffers - Google's data interchange format +Copyright 2008-2010 Google Inc. All rights reserved. +http://github.com/jskeet/dotnet-protobufs/ +Original C++/Java/Python code: +http://code.google.com/p/protobuf/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Cluster.Tests/licenses/protoc-license.txt b/src/core/Akka.Cluster.Tests/licenses/protoc-license.txt new file mode 100644 index 00000000000..c779cb0e1ed --- /dev/null +++ b/src/core/Akka.Cluster.Tests/licenses/protoc-license.txt @@ -0,0 +1,36 @@ +protoc.exe was built from the original source at http://code.google.com/p/protobuf/ +The licence for this code is as follows: + +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Cluster.Tests/protos/google/protobuf/csharp_options.proto new file mode 100644 index 00000000000..152df766f03 --- /dev/null +++ b/src/core/Akka.Cluster.Tests/protos/google/protobuf/csharp_options.proto @@ -0,0 +1,115 @@ +// Extra options for C# generator + +import "google/protobuf/descriptor.proto"; + +package google.protobuf; + +message CSharpFileOptions { + + // Namespace for generated classes; defaults to the package. + optional string namespace = 1; + + // Name of the "umbrella" class used for metadata about all + // the messages within this file. Default is based on the name + // of the file. + optional string umbrella_classname = 2; + + // Whether classes should be public (true) or internal (false) + optional bool public_classes = 3 [default = true]; + + // Whether to generate a single file for everything within the + // .proto file (false), or one file per message (true). + // This option is not currently honored; please log a feature + // request if you really want it. + optional bool multiple_files = 4; + + // Whether to nest messages within a single umbrella class (true) + // or create the umbrella class as a peer, with messages as + // top-level classes in the namespace (false) + optional bool nest_classes = 5; + + // Generate appropriate support for Code Contracts + // (Ongoing; support should improve over time) + optional bool code_contracts = 6; + + // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" + // would generate files within [output directory]/Foo/Bar + optional bool expand_namespace_directories = 7; + + // Generate attributes indicating non-CLS-compliance + optional bool cls_compliance = 8 [default = true]; + + // Generate messages/builders with the [Serializable] attribute + optional bool add_serializable = 9 [default = false]; + + // Generates a private ctor for Message types + optional bool generate_private_ctor = 10 [default = true]; + + // The extension that should be appended to the umbrella_classname when creating files. + optional string file_extension = 221 [default = ".cs"]; + + // A nested namespace for the umbrella class. Helpful for name collisions caused by + // umbrella_classname conflicting with an existing type. This will be automatically + // set to 'Proto' if a collision is detected with types being generated. This value + // is ignored when nest_classes == true + optional string umbrella_namespace = 222; + + // The output path for the source file(s) generated + optional string output_directory = 223 [default = "."]; + + // Will ignore the type generations and remove dependencies for the descriptor proto + // files that declare their package to be "google.protobuf" + optional bool ignore_google_protobuf = 224 [default = false]; + + // Controls how services are generated, GENERIC is the deprecated original implementation + // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and + // implementations using the included Windows RPC interop libarary. + optional CSharpServiceType service_generator_type = 225 [default = NONE]; + + // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and + // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. + optional bool generated_code_attributes = 226 [default = false]; +} + +enum CSharpServiceType { + // Services are ignored by the generator + NONE = 0; + // Generates the original Java generic service implementations + GENERIC = 1; + // Generates an interface for the service and nothing else + INTERFACE = 2; + // Generates an interface for the service and client/server wrappers for the interface + IRPCDISPATCH = 3; +} + +extend FileOptions { + optional CSharpFileOptions csharp_file_options = 1000; +} + +extend FieldOptions { + optional CSharpFieldOptions csharp_field_options = 1000; +} + +message CSharpFieldOptions { + // Provides the ability to override the name of the property + // generated for this field. This is applied to all properties + // and methods to do with this field, including HasFoo, FooCount, + // FooList etc. + optional string property_name = 1; +} + +message CSharpServiceOptions { + optional string interface_id = 1; +} + +extend ServiceOptions { + optional CSharpServiceOptions csharp_service_options = 1000; +} + +message CSharpMethodOptions { + optional int32 dispatch_id = 1; +} + +extend MethodOptions { + optional CSharpMethodOptions csharp_method_options = 1000; +} \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/protos/google/protobuf/descriptor.proto b/src/core/Akka.Cluster.Tests/protos/google/protobuf/descriptor.proto new file mode 100644 index 00000000000..233f879410e --- /dev/null +++ b/src/core/Akka.Cluster.Tests/protos/google/protobuf/descriptor.proto @@ -0,0 +1,533 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + + +package google.protobuf; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + optional MessageOptions options = 7; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4; + TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + optional FieldOptions options = 8; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; +} + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail kenton@google.com to reserve extension +// numbers. Simply tell me how many you need and I'll send you back a +// set of numbers to use -- there's no need to explain how you intend to +// use them. If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. This is + // purely a speed optimization, as the AbstractMessage base class includes + // reflection-based implementations of these methods. + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of proto2. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. + optional bool packed = 2; + + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // EXPERIMENTAL. DO NOT USE. + // For "map" fields, the name of the field in the enclosed type that + // is the key for this map. For example, suppose we have: + // message Item { + // required string name = 1; + // required string value = 2; + // } + // message Config { + // repeated Item items = 1 [experimental_map_key="name"]; + // } + // In this situation, the map key for Item will be set to "name". + // TODO: Fully-implement this, then remove the "experimental_" prefix. + optional string experimental_map_key = 9; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // TODO(kenton): Record comments appearing before and after the + // declaration. + } +} diff --git a/src/core/Akka.Cluster.Tests/protos/tutorial/addressbook.proto b/src/core/Akka.Cluster.Tests/protos/tutorial/addressbook.proto new file mode 100644 index 00000000000..5abe35ce39b --- /dev/null +++ b/src/core/Akka.Cluster.Tests/protos/tutorial/addressbook.proto @@ -0,0 +1,31 @@ +package tutorial; + +import "google/protobuf/csharp_options.proto"; +option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; +option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; + +option optimize_for = SPEED; + +message Person { + required string name = 1; + required int32 id = 2; // Unique ID number for this person. + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person person = 1; +} diff --git a/src/core/Akka.Cluster/Akka.Cluster.csproj b/src/core/Akka.Cluster/Akka.Cluster.csproj index c2194ed3444..8d7342e988a 100644 --- a/src/core/Akka.Cluster/Akka.Cluster.csproj +++ b/src/core/Akka.Cluster/Akka.Cluster.csproj @@ -49,6 +49,24 @@ bin\Release\Akka.Cluster.xml + + True + + + True + + + True + + + True + + + True + + + True + @@ -104,35 +122,7 @@ --> - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll - True - True - - - - + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll @@ -174,7 +164,7 @@ - + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll diff --git a/src/core/Akka.Cluster/CHANGES.txt b/src/core/Akka.Cluster/CHANGES.txt new file mode 100644 index 00000000000..d80368c78f2 --- /dev/null +++ b/src/core/Akka.Cluster/CHANGES.txt @@ -0,0 +1,99 @@ +=============================================================================== +Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet +(skeet@pobox.com) based on the work of many talented people. + +For more information about this port, visit its homepage: +http://protobuf-csharp-port.googlecode.com + +For more information about Protocol Buffers in general, visit the project page +for the C++, Java and Python project: +http://protobuf.googlecode.com +=============================================================================== +RELEASE NOTES - Version 2.4.1.473 +=============================================================================== + +Features: +- Added option service_generator_type to control service generation with + NONE, GENERIC, INTERFACE, or IRPCDISPATCH +- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking + services and implementations. +- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the + location of protoc.exe. +- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow + custom implementation of writers with both speed and size optimizations. +- Addition of the "Google.ProtoBuffers.Serialization" assembly to support + reading and writing messages to/from XML, JSON, IDictionary<,> and others. +- Several performance related fixes and tweeks +- Issue 3: Add option to mark generated code with attribute +- Issue 20: Support for decorating classes [Serializable] +- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] +- Issue 22: Reusable Builder classes +- Issue 24: Support for using Json/Xml formats with ICodedInputStream +- Issue 25: Added support for NuGet packages +- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 + +Fixes: +- Issue 13: Message with Field same name as message causes uncompilable .cs +- Issue 16: Does not integrate well with other tooling +- Issue 19: Support for negative enum values +- Issue 26: AddRange in GeneratedBuilder iterates twice. +- Issue 27: Remove XML documentation output from test projects to clear + warnings/errors. +- Issue 28: Circular message dependencies result in null default values for + Message fields. +- Issue 29: Message classes generated have a public default constructor. You + can disable private ctor generation with the option generate_private_ctor. +- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ +- Big-endian support for float, and double on Silverlight +- Packed and Unpacked parsing allow for all repeated, as per version 2.3 +- Fix for leaving Builder a public ctor on internal classes for use with + generic "where T: new()" constraints. + +Other: +- Changed the code signing key to a privately held key +- Reformatted all code and line-endings to C# defaults +- Reworking of performance benchmarks to produce reliable results, option /v2 +- Issue 34: Silverlight assemblies are now unit tested + +=============================================================================== +RELEASE NOTES - Version 2.3.0.277 +=============================================================================== + +Features: +- Added cls_compliance option to generate attributes indicating + non-CLS-compliance. +- Added file_extension option to control the generated output file's extension. +- Added umbrella_namespace option to place the umbrella class into a nested + namespace to address issues with proto files having the same name as a + message it contains. +- Added output_directory option to set the output path for the source file(s). +- Added ignore_google_protobuf option to avoid generating code for includes + from the google.protobuf package. +- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to + generate code with "option optimize_for = LITE_RUNTIME;". +- Added ability to invoke protoc.exe from within ProtoGen.exe. +- Upgraded to protoc.exe (2.3) compiler. + +Fixes: +- Issue 9: Class cannot be static and sealed error +- Issue 12: default value for enumerate fields must be filled out + +Other: +- Rewrite of build using MSBbuild instead of NAnt +- Moved to NUnit Version 2.2.8.0 +- Changed to using secure .snk for releases + +=============================================================================== +RELEASE NOTES - Version 0.9.1 +=============================================================================== + +Fixes: +- issue 10: Incorrect encoding of packed fields when serialized + +=============================================================================== +RELEASE NOTES - Version 0.9.0 +=============================================================================== + +- Initial release + +=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Cluster/licenses/license.txt b/src/core/Akka.Cluster/licenses/license.txt new file mode 100644 index 00000000000..b8e773b2e05 --- /dev/null +++ b/src/core/Akka.Cluster/licenses/license.txt @@ -0,0 +1,31 @@ +Protocol Buffers - Google's data interchange format +Copyright 2008-2010 Google Inc. All rights reserved. +http://github.com/jskeet/dotnet-protobufs/ +Original C++/Java/Python code: +http://code.google.com/p/protobuf/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Cluster/licenses/protoc-license.txt b/src/core/Akka.Cluster/licenses/protoc-license.txt new file mode 100644 index 00000000000..c779cb0e1ed --- /dev/null +++ b/src/core/Akka.Cluster/licenses/protoc-license.txt @@ -0,0 +1,36 @@ +protoc.exe was built from the original source at http://code.google.com/p/protobuf/ +The licence for this code is as follows: + +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Cluster/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Cluster/protos/google/protobuf/csharp_options.proto new file mode 100644 index 00000000000..152df766f03 --- /dev/null +++ b/src/core/Akka.Cluster/protos/google/protobuf/csharp_options.proto @@ -0,0 +1,115 @@ +// Extra options for C# generator + +import "google/protobuf/descriptor.proto"; + +package google.protobuf; + +message CSharpFileOptions { + + // Namespace for generated classes; defaults to the package. + optional string namespace = 1; + + // Name of the "umbrella" class used for metadata about all + // the messages within this file. Default is based on the name + // of the file. + optional string umbrella_classname = 2; + + // Whether classes should be public (true) or internal (false) + optional bool public_classes = 3 [default = true]; + + // Whether to generate a single file for everything within the + // .proto file (false), or one file per message (true). + // This option is not currently honored; please log a feature + // request if you really want it. + optional bool multiple_files = 4; + + // Whether to nest messages within a single umbrella class (true) + // or create the umbrella class as a peer, with messages as + // top-level classes in the namespace (false) + optional bool nest_classes = 5; + + // Generate appropriate support for Code Contracts + // (Ongoing; support should improve over time) + optional bool code_contracts = 6; + + // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" + // would generate files within [output directory]/Foo/Bar + optional bool expand_namespace_directories = 7; + + // Generate attributes indicating non-CLS-compliance + optional bool cls_compliance = 8 [default = true]; + + // Generate messages/builders with the [Serializable] attribute + optional bool add_serializable = 9 [default = false]; + + // Generates a private ctor for Message types + optional bool generate_private_ctor = 10 [default = true]; + + // The extension that should be appended to the umbrella_classname when creating files. + optional string file_extension = 221 [default = ".cs"]; + + // A nested namespace for the umbrella class. Helpful for name collisions caused by + // umbrella_classname conflicting with an existing type. This will be automatically + // set to 'Proto' if a collision is detected with types being generated. This value + // is ignored when nest_classes == true + optional string umbrella_namespace = 222; + + // The output path for the source file(s) generated + optional string output_directory = 223 [default = "."]; + + // Will ignore the type generations and remove dependencies for the descriptor proto + // files that declare their package to be "google.protobuf" + optional bool ignore_google_protobuf = 224 [default = false]; + + // Controls how services are generated, GENERIC is the deprecated original implementation + // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and + // implementations using the included Windows RPC interop libarary. + optional CSharpServiceType service_generator_type = 225 [default = NONE]; + + // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and + // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. + optional bool generated_code_attributes = 226 [default = false]; +} + +enum CSharpServiceType { + // Services are ignored by the generator + NONE = 0; + // Generates the original Java generic service implementations + GENERIC = 1; + // Generates an interface for the service and nothing else + INTERFACE = 2; + // Generates an interface for the service and client/server wrappers for the interface + IRPCDISPATCH = 3; +} + +extend FileOptions { + optional CSharpFileOptions csharp_file_options = 1000; +} + +extend FieldOptions { + optional CSharpFieldOptions csharp_field_options = 1000; +} + +message CSharpFieldOptions { + // Provides the ability to override the name of the property + // generated for this field. This is applied to all properties + // and methods to do with this field, including HasFoo, FooCount, + // FooList etc. + optional string property_name = 1; +} + +message CSharpServiceOptions { + optional string interface_id = 1; +} + +extend ServiceOptions { + optional CSharpServiceOptions csharp_service_options = 1000; +} + +message CSharpMethodOptions { + optional int32 dispatch_id = 1; +} + +extend MethodOptions { + optional CSharpMethodOptions csharp_method_options = 1000; +} \ No newline at end of file diff --git a/src/core/Akka.Cluster/protos/google/protobuf/descriptor.proto b/src/core/Akka.Cluster/protos/google/protobuf/descriptor.proto new file mode 100644 index 00000000000..233f879410e --- /dev/null +++ b/src/core/Akka.Cluster/protos/google/protobuf/descriptor.proto @@ -0,0 +1,533 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + + +package google.protobuf; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + optional MessageOptions options = 7; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4; + TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + optional FieldOptions options = 8; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; +} + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail kenton@google.com to reserve extension +// numbers. Simply tell me how many you need and I'll send you back a +// set of numbers to use -- there's no need to explain how you intend to +// use them. If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. This is + // purely a speed optimization, as the AbstractMessage base class includes + // reflection-based implementations of these methods. + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of proto2. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. + optional bool packed = 2; + + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // EXPERIMENTAL. DO NOT USE. + // For "map" fields, the name of the field in the enclosed type that + // is the key for this map. For example, suppose we have: + // message Item { + // required string name = 1; + // required string value = 2; + // } + // message Config { + // repeated Item items = 1 [experimental_map_key="name"]; + // } + // In this situation, the map key for Item will be set to "name". + // TODO: Fully-implement this, then remove the "experimental_" prefix. + optional string experimental_map_key = 9; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // TODO(kenton): Record comments appearing before and after the + // declaration. + } +} diff --git a/src/core/Akka.Cluster/protos/tutorial/addressbook.proto b/src/core/Akka.Cluster/protos/tutorial/addressbook.proto new file mode 100644 index 00000000000..5abe35ce39b --- /dev/null +++ b/src/core/Akka.Cluster/protos/tutorial/addressbook.proto @@ -0,0 +1,31 @@ +package tutorial; + +import "google/protobuf/csharp_options.proto"; +option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; +option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; + +option optimize_for = SPEED; + +message Person { + required string name = 1; + required int32 id = 2; // Unique ID number for this person. + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person person = 1; +} diff --git a/src/core/Akka.FSharp.Tests/app.config b/src/core/Akka.FSharp.Tests/app.config index c03004cd2a4..9efc87884ed 100644 --- a/src/core/Akka.FSharp.Tests/app.config +++ b/src/core/Akka.FSharp.Tests/app.config @@ -75,15 +75,15 @@ - + - + - + @@ -115,15 +115,15 @@ - + - + - + @@ -133,5 +133,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.FSharp/app.config b/src/core/Akka.FSharp/app.config index 2f259236304..27ad5b4a789 100644 --- a/src/core/Akka.FSharp/app.config +++ b/src/core/Akka.FSharp/app.config @@ -61,15 +61,15 @@ - + - + - + @@ -101,15 +101,15 @@ - + - + - + @@ -121,15 +121,15 @@ - + - + - + @@ -147,5 +147,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj index 04c879b994b..794443b1322 100644 --- a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj +++ b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj @@ -83,6 +83,17 @@ --> + + + + + ..\..\..\packages\test\xunit\lib\net20\xunit.dll + True + True + + + + @@ -114,6 +125,35 @@ + + + + <__paket__xunit_core_props>win81\xunit.core + + + + + <__paket__xunit_core_props>wpa81\xunit.core + + + + + <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core + + + + + + + + + ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll + True + True + + + + @@ -188,6 +228,17 @@ + + + + + ..\..\..\packages\test\xunit.extensions\lib\net20\xunit.extensions.dll + True + True + + + + @@ -208,4 +259,30 @@ + + + + <__paket__xunit_runner_visualstudio_props>win81\xunit.runner.visualstudio + <__paket__xunit_runner_visualstudio_targets>win81\xunit.runner.visualstudio + + + + + <__paket__xunit_runner_visualstudio_props>net20\xunit.runner.visualstudio + + + + + <__paket__xunit_runner_visualstudio_props>wpa81\xunit.runner.visualstudio + <__paket__xunit_runner_visualstudio_targets>wpa81\xunit.runner.visualstudio + + + + + <__paket__xunit_runner_visualstudio_props>portable-net45+win8+wp8+wpa81\xunit.runner.visualstudio + + + + + \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/App.config b/src/core/Akka.MultiNodeTestRunner/App.config index 82a34b6b6ca..5126174a197 100644 --- a/src/core/Akka.MultiNodeTestRunner/App.config +++ b/src/core/Akka.MultiNodeTestRunner/App.config @@ -62,15 +62,15 @@ - + - + - + @@ -102,18 +102,46 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/App.config b/src/core/Akka.NodeTestRunner/App.config index c8c4db09f25..060f4e63806 100644 --- a/src/core/Akka.NodeTestRunner/App.config +++ b/src/core/Akka.NodeTestRunner/App.config @@ -71,15 +71,15 @@ - + - + - + @@ -111,15 +111,15 @@ - + - + - + @@ -131,15 +131,15 @@ - + - + - + @@ -157,4 +157,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence.FSharp/app.config b/src/core/Akka.Persistence.FSharp/app.config index 2f259236304..27ad5b4a789 100644 --- a/src/core/Akka.Persistence.FSharp/app.config +++ b/src/core/Akka.Persistence.FSharp/app.config @@ -61,15 +61,15 @@ - + - + - + @@ -101,15 +101,15 @@ - + - + - + @@ -121,15 +121,15 @@ - + - + - + @@ -147,5 +147,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj b/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj index 0b951e2da45..13b75f4f925 100644 --- a/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj +++ b/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj @@ -46,6 +46,10 @@ + + {7DBD5C17-5E9D-40C4-9201-D092751532A7} + Akka.TestKit.Xunit2 + {AD9418B6-C452-4169-94FB-D43DE0BFA966} Akka.Persistence.TestKit diff --git a/src/core/Akka.Persistence.TestKit.Tests/LocalSnapshotStoreSpec.cs b/src/core/Akka.Persistence.TestKit.Tests/LocalSnapshotStoreSpec.cs index 8adc5d174f6..9fac6cc6398 100644 --- a/src/core/Akka.Persistence.TestKit.Tests/LocalSnapshotStoreSpec.cs +++ b/src/core/Akka.Persistence.TestKit.Tests/LocalSnapshotStoreSpec.cs @@ -10,18 +10,19 @@ using Akka.Configuration; using Akka.Persistence.TestKit.Snapshot; using Xunit; +using Xunit.Abstractions; namespace Akka.Persistence.TestKit.Tests { public class LocalSnapshotStoreSpec : SnapshotStoreSpec { private readonly string _path; - public LocalSnapshotStoreSpec() + public LocalSnapshotStoreSpec(ITestOutputHelper output) : base(ConfigurationFactory.ParseString( @"akka.test.timefactor = 3 akka.persistence.snapshot-store.plugin = ""akka.persistence.snapshot-store.local"" akka.persistence.snapshot-store.local.dir = ""target/snapshots-" + Guid.NewGuid() + @""""), - "LocalSnapshotStoreSpec") + "LocalSnapshotStoreSpec", output) { _path = Sys.Settings.Config.GetString("akka.persistence.snapshot-store.local.dir"); Sys.CreateStorageLocations(_path); diff --git a/src/core/Akka.Persistence.TestKit.Tests/MemoryJournalSpec.cs b/src/core/Akka.Persistence.TestKit.Tests/MemoryJournalSpec.cs index 8fbfb6e2bb6..4d9d88e57ca 100644 --- a/src/core/Akka.Persistence.TestKit.Tests/MemoryJournalSpec.cs +++ b/src/core/Akka.Persistence.TestKit.Tests/MemoryJournalSpec.cs @@ -6,13 +6,14 @@ //----------------------------------------------------------------------- using Akka.Persistence.TestKit.Journal; +using Xunit.Abstractions; namespace Akka.Persistence.TestKit.Tests { public class MemoryJournalSpec : JournalSpec { - public MemoryJournalSpec() - : base(actorSystemName: "MemoryJournalSpec") + public MemoryJournalSpec(ITestOutputHelper output) + : base(actorSystemName: "MemoryJournalSpec", output: output) { Initialize(); } diff --git a/src/core/Akka.Persistence.TestKit/Journal/JournalSpec.cs b/src/core/Akka.Persistence.TestKit/Journal/JournalSpec.cs index 17fe4f0ba2a..42995249917 100644 --- a/src/core/Akka.Persistence.TestKit/Journal/JournalSpec.cs +++ b/src/core/Akka.Persistence.TestKit/Journal/JournalSpec.cs @@ -12,6 +12,7 @@ using Akka.Configuration; using Akka.TestKit; using Xunit; +using Xunit.Abstractions; namespace Akka.Persistence.TestKit.Journal { @@ -36,8 +37,8 @@ class = ""{0}"" private TestProbe _senderProbe; private TestProbe _receiverProbe; - protected JournalSpec(Config config = null, string actorSystemName = null, string testActorName = null) - : base(FromConfig(config).WithFallback(Config), actorSystemName ?? "JournalSpec", testActorName) + protected JournalSpec(Config config = null, string actorSystemName = null, ITestOutputHelper output = null) + : base(FromConfig(config).WithFallback(Config), actorSystemName ?? "JournalSpec", output) { } diff --git a/src/core/Akka.Persistence.TestKit/PluginSpec.cs b/src/core/Akka.Persistence.TestKit/PluginSpec.cs index 740b927d37d..2c48cbe5509 100644 --- a/src/core/Akka.Persistence.TestKit/PluginSpec.cs +++ b/src/core/Akka.Persistence.TestKit/PluginSpec.cs @@ -8,13 +8,12 @@ using System; using Akka.Actor; using Akka.Configuration; -using Akka.TestKit; -using Akka.TestKit.Xunit2; using Akka.Util.Internal; +using Xunit.Abstractions; namespace Akka.Persistence.TestKit { - public abstract class PluginSpec : TestKitBase, IDisposable + public abstract class PluginSpec : Akka.TestKit.Xunit2.TestKit, IDisposable { private static readonly AtomicCounter Counter = new AtomicCounter(0); private readonly PersistenceExtension _extension; @@ -22,8 +21,8 @@ public abstract class PluginSpec : TestKitBase, IDisposable protected int ActorInstanceId = 1; - protected PluginSpec(Config config = null, string actorSystemName = null, string testActorName = null) - : base(new XunitAssertions(), FromConfig(config), actorSystemName, testActorName) + protected PluginSpec(Config config = null, string actorSystemName = null, ITestOutputHelper output = null) + : base(FromConfig(config), actorSystemName, output) { _extension = Persistence.Instance.Apply(Sys as ExtendedActorSystem); _pid = "p-" + Counter.IncrementAndGet(); @@ -52,8 +51,7 @@ public void Dispose() protected virtual void Dispose(bool disposing) { - if (disposing) - Shutdown(); + //if (disposing) FSMBase.Shutdown(); } } } diff --git a/src/core/Akka.Persistence.TestKit/Snapshot/SnapshotStoreSpec.cs b/src/core/Akka.Persistence.TestKit/Snapshot/SnapshotStoreSpec.cs index 6445f59c870..1d47f811d51 100644 --- a/src/core/Akka.Persistence.TestKit/Snapshot/SnapshotStoreSpec.cs +++ b/src/core/Akka.Persistence.TestKit/Snapshot/SnapshotStoreSpec.cs @@ -12,6 +12,7 @@ using Akka.Configuration; using Akka.TestKit; using Xunit; +using Xunit.Abstractions; namespace Akka.Persistence.TestKit.Snapshot { @@ -37,8 +38,8 @@ class = ""TestPersistencePlugin.MySnapshotStore, TestPersistencePlugin"" private readonly TestProbe _senderProbe; protected List Metadata; - protected SnapshotStoreSpec(Config config = null, string actorSystemName = null, string testActorName = null) - : base(FromConfig(config).WithFallback(Config), actorSystemName ?? "SnapshotStoreSpec", testActorName) + protected SnapshotStoreSpec(Config config = null, string actorSystemName = null, ITestOutputHelper output = null) + : base(FromConfig(config).WithFallback(Config), actorSystemName ?? "SnapshotStoreSpec", output) { _senderProbe = CreateTestProbe(); } diff --git a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj index 43510797058..ac086707e6f 100644 --- a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj +++ b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj @@ -32,6 +32,24 @@ 4 + + True + + + True + + + True + + + True + + + True + + + True + @@ -96,35 +114,7 @@ --> - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll - True - True - - - - + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll @@ -166,7 +156,7 @@ - + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll diff --git a/src/core/Akka.Persistence.Tests/CHANGES.txt b/src/core/Akka.Persistence.Tests/CHANGES.txt new file mode 100644 index 00000000000..d80368c78f2 --- /dev/null +++ b/src/core/Akka.Persistence.Tests/CHANGES.txt @@ -0,0 +1,99 @@ +=============================================================================== +Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet +(skeet@pobox.com) based on the work of many talented people. + +For more information about this port, visit its homepage: +http://protobuf-csharp-port.googlecode.com + +For more information about Protocol Buffers in general, visit the project page +for the C++, Java and Python project: +http://protobuf.googlecode.com +=============================================================================== +RELEASE NOTES - Version 2.4.1.473 +=============================================================================== + +Features: +- Added option service_generator_type to control service generation with + NONE, GENERIC, INTERFACE, or IRPCDISPATCH +- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking + services and implementations. +- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the + location of protoc.exe. +- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow + custom implementation of writers with both speed and size optimizations. +- Addition of the "Google.ProtoBuffers.Serialization" assembly to support + reading and writing messages to/from XML, JSON, IDictionary<,> and others. +- Several performance related fixes and tweeks +- Issue 3: Add option to mark generated code with attribute +- Issue 20: Support for decorating classes [Serializable] +- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] +- Issue 22: Reusable Builder classes +- Issue 24: Support for using Json/Xml formats with ICodedInputStream +- Issue 25: Added support for NuGet packages +- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 + +Fixes: +- Issue 13: Message with Field same name as message causes uncompilable .cs +- Issue 16: Does not integrate well with other tooling +- Issue 19: Support for negative enum values +- Issue 26: AddRange in GeneratedBuilder iterates twice. +- Issue 27: Remove XML documentation output from test projects to clear + warnings/errors. +- Issue 28: Circular message dependencies result in null default values for + Message fields. +- Issue 29: Message classes generated have a public default constructor. You + can disable private ctor generation with the option generate_private_ctor. +- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ +- Big-endian support for float, and double on Silverlight +- Packed and Unpacked parsing allow for all repeated, as per version 2.3 +- Fix for leaving Builder a public ctor on internal classes for use with + generic "where T: new()" constraints. + +Other: +- Changed the code signing key to a privately held key +- Reformatted all code and line-endings to C# defaults +- Reworking of performance benchmarks to produce reliable results, option /v2 +- Issue 34: Silverlight assemblies are now unit tested + +=============================================================================== +RELEASE NOTES - Version 2.3.0.277 +=============================================================================== + +Features: +- Added cls_compliance option to generate attributes indicating + non-CLS-compliance. +- Added file_extension option to control the generated output file's extension. +- Added umbrella_namespace option to place the umbrella class into a nested + namespace to address issues with proto files having the same name as a + message it contains. +- Added output_directory option to set the output path for the source file(s). +- Added ignore_google_protobuf option to avoid generating code for includes + from the google.protobuf package. +- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to + generate code with "option optimize_for = LITE_RUNTIME;". +- Added ability to invoke protoc.exe from within ProtoGen.exe. +- Upgraded to protoc.exe (2.3) compiler. + +Fixes: +- Issue 9: Class cannot be static and sealed error +- Issue 12: default value for enumerate fields must be filled out + +Other: +- Rewrite of build using MSBbuild instead of NAnt +- Moved to NUnit Version 2.2.8.0 +- Changed to using secure .snk for releases + +=============================================================================== +RELEASE NOTES - Version 0.9.1 +=============================================================================== + +Fixes: +- issue 10: Incorrect encoding of packed fields when serialized + +=============================================================================== +RELEASE NOTES - Version 0.9.0 +=============================================================================== + +- Initial release + +=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/licenses/license.txt b/src/core/Akka.Persistence.Tests/licenses/license.txt new file mode 100644 index 00000000000..b8e773b2e05 --- /dev/null +++ b/src/core/Akka.Persistence.Tests/licenses/license.txt @@ -0,0 +1,31 @@ +Protocol Buffers - Google's data interchange format +Copyright 2008-2010 Google Inc. All rights reserved. +http://github.com/jskeet/dotnet-protobufs/ +Original C++/Java/Python code: +http://code.google.com/p/protobuf/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Persistence.Tests/licenses/protoc-license.txt b/src/core/Akka.Persistence.Tests/licenses/protoc-license.txt new file mode 100644 index 00000000000..c779cb0e1ed --- /dev/null +++ b/src/core/Akka.Persistence.Tests/licenses/protoc-license.txt @@ -0,0 +1,36 @@ +protoc.exe was built from the original source at http://code.google.com/p/protobuf/ +The licence for this code is as follows: + +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Persistence.Tests/protos/google/protobuf/csharp_options.proto new file mode 100644 index 00000000000..152df766f03 --- /dev/null +++ b/src/core/Akka.Persistence.Tests/protos/google/protobuf/csharp_options.proto @@ -0,0 +1,115 @@ +// Extra options for C# generator + +import "google/protobuf/descriptor.proto"; + +package google.protobuf; + +message CSharpFileOptions { + + // Namespace for generated classes; defaults to the package. + optional string namespace = 1; + + // Name of the "umbrella" class used for metadata about all + // the messages within this file. Default is based on the name + // of the file. + optional string umbrella_classname = 2; + + // Whether classes should be public (true) or internal (false) + optional bool public_classes = 3 [default = true]; + + // Whether to generate a single file for everything within the + // .proto file (false), or one file per message (true). + // This option is not currently honored; please log a feature + // request if you really want it. + optional bool multiple_files = 4; + + // Whether to nest messages within a single umbrella class (true) + // or create the umbrella class as a peer, with messages as + // top-level classes in the namespace (false) + optional bool nest_classes = 5; + + // Generate appropriate support for Code Contracts + // (Ongoing; support should improve over time) + optional bool code_contracts = 6; + + // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" + // would generate files within [output directory]/Foo/Bar + optional bool expand_namespace_directories = 7; + + // Generate attributes indicating non-CLS-compliance + optional bool cls_compliance = 8 [default = true]; + + // Generate messages/builders with the [Serializable] attribute + optional bool add_serializable = 9 [default = false]; + + // Generates a private ctor for Message types + optional bool generate_private_ctor = 10 [default = true]; + + // The extension that should be appended to the umbrella_classname when creating files. + optional string file_extension = 221 [default = ".cs"]; + + // A nested namespace for the umbrella class. Helpful for name collisions caused by + // umbrella_classname conflicting with an existing type. This will be automatically + // set to 'Proto' if a collision is detected with types being generated. This value + // is ignored when nest_classes == true + optional string umbrella_namespace = 222; + + // The output path for the source file(s) generated + optional string output_directory = 223 [default = "."]; + + // Will ignore the type generations and remove dependencies for the descriptor proto + // files that declare their package to be "google.protobuf" + optional bool ignore_google_protobuf = 224 [default = false]; + + // Controls how services are generated, GENERIC is the deprecated original implementation + // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and + // implementations using the included Windows RPC interop libarary. + optional CSharpServiceType service_generator_type = 225 [default = NONE]; + + // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and + // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. + optional bool generated_code_attributes = 226 [default = false]; +} + +enum CSharpServiceType { + // Services are ignored by the generator + NONE = 0; + // Generates the original Java generic service implementations + GENERIC = 1; + // Generates an interface for the service and nothing else + INTERFACE = 2; + // Generates an interface for the service and client/server wrappers for the interface + IRPCDISPATCH = 3; +} + +extend FileOptions { + optional CSharpFileOptions csharp_file_options = 1000; +} + +extend FieldOptions { + optional CSharpFieldOptions csharp_field_options = 1000; +} + +message CSharpFieldOptions { + // Provides the ability to override the name of the property + // generated for this field. This is applied to all properties + // and methods to do with this field, including HasFoo, FooCount, + // FooList etc. + optional string property_name = 1; +} + +message CSharpServiceOptions { + optional string interface_id = 1; +} + +extend ServiceOptions { + optional CSharpServiceOptions csharp_service_options = 1000; +} + +message CSharpMethodOptions { + optional int32 dispatch_id = 1; +} + +extend MethodOptions { + optional CSharpMethodOptions csharp_method_options = 1000; +} \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/protos/google/protobuf/descriptor.proto b/src/core/Akka.Persistence.Tests/protos/google/protobuf/descriptor.proto new file mode 100644 index 00000000000..233f879410e --- /dev/null +++ b/src/core/Akka.Persistence.Tests/protos/google/protobuf/descriptor.proto @@ -0,0 +1,533 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + + +package google.protobuf; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + optional MessageOptions options = 7; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4; + TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + optional FieldOptions options = 8; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; +} + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail kenton@google.com to reserve extension +// numbers. Simply tell me how many you need and I'll send you back a +// set of numbers to use -- there's no need to explain how you intend to +// use them. If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. This is + // purely a speed optimization, as the AbstractMessage base class includes + // reflection-based implementations of these methods. + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of proto2. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. + optional bool packed = 2; + + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // EXPERIMENTAL. DO NOT USE. + // For "map" fields, the name of the field in the enclosed type that + // is the key for this map. For example, suppose we have: + // message Item { + // required string name = 1; + // required string value = 2; + // } + // message Config { + // repeated Item items = 1 [experimental_map_key="name"]; + // } + // In this situation, the map key for Item will be set to "name". + // TODO: Fully-implement this, then remove the "experimental_" prefix. + optional string experimental_map_key = 9; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // TODO(kenton): Record comments appearing before and after the + // declaration. + } +} diff --git a/src/core/Akka.Persistence.Tests/protos/tutorial/addressbook.proto b/src/core/Akka.Persistence.Tests/protos/tutorial/addressbook.proto new file mode 100644 index 00000000000..5abe35ce39b --- /dev/null +++ b/src/core/Akka.Persistence.Tests/protos/tutorial/addressbook.proto @@ -0,0 +1,31 @@ +package tutorial; + +import "google/protobuf/csharp_options.proto"; +option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; +option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; + +option optimize_for = SPEED; + +message Person { + required string name = 1; + required int32 id = 2; // Unique ID number for this person. + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person person = 1; +} diff --git a/src/core/Akka.Persistence/Akka.Persistence.csproj b/src/core/Akka.Persistence/Akka.Persistence.csproj index ce5c00155b4..383440396d1 100644 --- a/src/core/Akka.Persistence/Akka.Persistence.csproj +++ b/src/core/Akka.Persistence/Akka.Persistence.csproj @@ -32,6 +32,24 @@ bin\Release\Akka.Persistence.xml + + True + + + True + + + True + + + True + + + True + + + True + @@ -94,35 +112,7 @@ --> - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll - True - True - - - - + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll @@ -164,7 +154,7 @@ - + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll diff --git a/src/core/Akka.Persistence/AtLeastOnceDelivery.cs b/src/core/Akka.Persistence/AtLeastOnceDelivery.cs index f1cea90c7c0..75873b45033 100644 --- a/src/core/Akka.Persistence/AtLeastOnceDelivery.cs +++ b/src/core/Akka.Persistence/AtLeastOnceDelivery.cs @@ -25,37 +25,95 @@ namespace Akka.Persistence /// . /// [Serializable] - public sealed class AtLeastOnceDeliverySnapshot : IMessage + public sealed class AtLeastOnceDeliverySnapshot : IMessage, IEquatable { public AtLeastOnceDeliverySnapshot(long deliveryId, UnconfirmedDelivery[] unconfirmedDeliveries) { + if(unconfirmedDeliveries == null) + throw new ArgumentNullException("unconfirmedDeliveries", "AtLeastOnceDeliverySnapshot expects not null array of unconfirmed deliveries"); + DeliveryId = deliveryId; UnconfirmedDeliveries = unconfirmedDeliveries; } - public long DeliveryId { get; private set; } - public UnconfirmedDelivery[] UnconfirmedDeliveries { get; private set; } + public readonly long DeliveryId; + public readonly UnconfirmedDelivery[] UnconfirmedDeliveries; + + public bool Equals(AtLeastOnceDeliverySnapshot other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(DeliveryId, other.DeliveryId) + && Equals(UnconfirmedDeliveries, UnconfirmedDeliveries); + } + + public override bool Equals(object obj) + { + return Equals(obj as AtLeastOnceDeliverySnapshot); + } + + public override int GetHashCode() + { + unchecked + { + return (DeliveryId.GetHashCode() * 397) ^ (UnconfirmedDeliveries != null ? UnconfirmedDeliveries.GetHashCode() : 0); + } + } + + public override string ToString() + { + return string.Format("AtLeastOnceDeliverySnapshot", DeliveryId, UnconfirmedDeliveries.Length); + } } /// /// message should be sent after /// limit will be reached. /// - public sealed class UnconfirmedWarning + [Serializable] + public sealed class UnconfirmedWarning : IEquatable { public UnconfirmedWarning(UnconfirmedDelivery[] unconfirmedDeliveries) { + if(unconfirmedDeliveries == null) + throw new ArgumentNullException("unconfirmedDeliveries", "UnconfirmedWarning expects not null array of unconfirmed deliveries"); + UnconfirmedDeliveries = unconfirmedDeliveries; } - public UnconfirmedDelivery[] UnconfirmedDeliveries { get; set; } + public readonly UnconfirmedDelivery[] UnconfirmedDeliveries; + + public bool Equals(UnconfirmedWarning other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(UnconfirmedDeliveries, other.UnconfirmedDeliveries); + } + + public override bool Equals(object obj) + { + return Equals(obj as UnconfirmedWarning); + } + + public override int GetHashCode() + { + return (UnconfirmedDeliveries != null ? UnconfirmedDeliveries.GetHashCode() : 0); + } + + public override string ToString() + { + return string.Format("UnconfirmedWarning", UnconfirmedDeliveries.Length); + } } /// /// contains details about unconfirmed messages. /// It's included inside and . /// - public sealed class UnconfirmedDelivery + [Serializable] + public sealed class UnconfirmedDelivery : IEquatable { public UnconfirmedDelivery(long deliveryId, ActorPath destination, object message) { @@ -64,12 +122,44 @@ public UnconfirmedDelivery(long deliveryId, ActorPath destination, object messag Message = message; } - public long DeliveryId { get; set; } - public ActorPath Destination { get; set; } - public object Message { get; set; } + public readonly long DeliveryId; + public readonly ActorPath Destination; + public readonly object Message; + + public bool Equals(UnconfirmedDelivery other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(DeliveryId, other.DeliveryId) + && Equals(Destination, other.Destination) + && Equals(Message, other.Message); + } + + public override bool Equals(object obj) + { + return Equals(obj as UnconfirmedDelivery); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = DeliveryId.GetHashCode(); + hashCode = (hashCode * 397) ^ (Destination != null ? Destination.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Message != null ? Message.GetHashCode() : 0); + return hashCode; + } + } + + public override string ToString() + { + return string.Format("UnconfirmedDelivery", DeliveryId, Destination, Message); + } } - internal sealed class Delivery + [Serializable] + internal sealed class Delivery : IEquatable { public Delivery(ActorPath destination, object message, DateTime timestamp, int attempt) { @@ -79,17 +169,50 @@ public Delivery(ActorPath destination, object message, DateTime timestamp, int a Attempt = attempt; } - public ActorPath Destination { get; private set; } - public object Message { get; private set; } - public DateTime Timestamp { get; private set; } - public int Attempt { get; private set; } + public readonly ActorPath Destination; + public readonly object Message; + public readonly DateTime Timestamp; + public readonly int Attempt; public Delivery IncrementedCopy() { return new Delivery(Destination, Message, Timestamp, Attempt + 1); } - } + public bool Equals(Delivery other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Attempt, other.Attempt) + && Equals(Timestamp, other.Timestamp) + && Equals(Destination, other.Destination) + && Equals(Message, other.Message); + } + + public override bool Equals(object obj) + { + return Equals(obj as Delivery); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (Destination != null ? Destination.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Message != null ? Message.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ Timestamp.GetHashCode(); + hashCode = (hashCode * 397) ^ Attempt; + return hashCode; + } + } + + public override string ToString() + { + return string.Format("Delivery and others. +- Several performance related fixes and tweeks +- Issue 3: Add option to mark generated code with attribute +- Issue 20: Support for decorating classes [Serializable] +- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] +- Issue 22: Reusable Builder classes +- Issue 24: Support for using Json/Xml formats with ICodedInputStream +- Issue 25: Added support for NuGet packages +- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 + +Fixes: +- Issue 13: Message with Field same name as message causes uncompilable .cs +- Issue 16: Does not integrate well with other tooling +- Issue 19: Support for negative enum values +- Issue 26: AddRange in GeneratedBuilder iterates twice. +- Issue 27: Remove XML documentation output from test projects to clear + warnings/errors. +- Issue 28: Circular message dependencies result in null default values for + Message fields. +- Issue 29: Message classes generated have a public default constructor. You + can disable private ctor generation with the option generate_private_ctor. +- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ +- Big-endian support for float, and double on Silverlight +- Packed and Unpacked parsing allow for all repeated, as per version 2.3 +- Fix for leaving Builder a public ctor on internal classes for use with + generic "where T: new()" constraints. + +Other: +- Changed the code signing key to a privately held key +- Reformatted all code and line-endings to C# defaults +- Reworking of performance benchmarks to produce reliable results, option /v2 +- Issue 34: Silverlight assemblies are now unit tested + +=============================================================================== +RELEASE NOTES - Version 2.3.0.277 +=============================================================================== + +Features: +- Added cls_compliance option to generate attributes indicating + non-CLS-compliance. +- Added file_extension option to control the generated output file's extension. +- Added umbrella_namespace option to place the umbrella class into a nested + namespace to address issues with proto files having the same name as a + message it contains. +- Added output_directory option to set the output path for the source file(s). +- Added ignore_google_protobuf option to avoid generating code for includes + from the google.protobuf package. +- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to + generate code with "option optimize_for = LITE_RUNTIME;". +- Added ability to invoke protoc.exe from within ProtoGen.exe. +- Upgraded to protoc.exe (2.3) compiler. + +Fixes: +- Issue 9: Class cannot be static and sealed error +- Issue 12: default value for enumerate fields must be filled out + +Other: +- Rewrite of build using MSBbuild instead of NAnt +- Moved to NUnit Version 2.2.8.0 +- Changed to using secure .snk for releases + +=============================================================================== +RELEASE NOTES - Version 0.9.1 +=============================================================================== + +Fixes: +- issue 10: Incorrect encoding of packed fields when serialized + +=============================================================================== +RELEASE NOTES - Version 0.9.0 +=============================================================================== + +- Initial release + +=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Persistence/Journal/AsyncWriteJournal.cs b/src/core/Akka.Persistence/Journal/AsyncWriteJournal.cs index 02e2559600f..20bc9cd3a9a 100644 --- a/src/core/Akka.Persistence/Journal/AsyncWriteJournal.cs +++ b/src/core/Akka.Persistence/Journal/AsyncWriteJournal.cs @@ -161,10 +161,10 @@ public Desequenced(object message, long sequenceNr, IActorRef target, IActorRef Sender = sender; } - public object Message { get; private set; } - public long SequenceNr { get; private set; } - public IActorRef Target { get; private set; } - public IActorRef Sender { get; private set; } + public readonly object Message; + public readonly long SequenceNr; + public readonly IActorRef Target; + public readonly IActorRef Sender; } internal class Resequencer : ActorBase diff --git a/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs b/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs index b38199d3f23..82f3f58ee66 100644 --- a/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs +++ b/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs @@ -43,7 +43,7 @@ public SetStore(IActorRef store) Store = store; } - public IActorRef Store { get; private set; } + public readonly IActorRef Store; } public static class AsyncWriteTarget @@ -106,7 +106,9 @@ public ReplayMessages(string persistenceId, long fromSequenceNr, long toSequence public long Max { get; private set; } public bool Equals(ReplayMessages other) { - if (other == null) return false; + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + return PersistenceId == other.PersistenceId && FromSequenceNr == other.FromSequenceNr && ToSequenceNr == other.ToSequenceNr @@ -127,7 +129,9 @@ public ReadHighestSequenceNr(string persistenceId, long fromSequenceNr) public long FromSequenceNr { get; private set; } public bool Equals(ReadHighestSequenceNr other) { - if (other == null) return false; + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + return PersistenceId == other.PersistenceId && FromSequenceNr == other.FromSequenceNr; } @@ -148,7 +152,9 @@ public DeleteMessagesTo(string persistenceId, long toSequenceNr, bool isPermanen public bool IsPermanent { get; private set; } public bool Equals(DeleteMessagesTo other) { - if (other == null) return false; + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + return PersistenceId == other.PersistenceId && ToSequenceNr == other.ToSequenceNr && IsPermanent == other.IsPermanent; diff --git a/src/core/Akka.Persistence/Journal/WriteJournal.cs b/src/core/Akka.Persistence/Journal/WriteJournal.cs index 76dc3f1ec05..833b5c8596c 100644 --- a/src/core/Akka.Persistence/Journal/WriteJournal.cs +++ b/src/core/Akka.Persistence/Journal/WriteJournal.cs @@ -58,9 +58,15 @@ protected IPersistentRepresentation AdaptToJournal(IPersistentRepresentation rep { var payload = representation.Payload; var adapter = _eventAdapters.Get(payload.GetType()); - var manifest = adapter.Manifest(payload); + representation = representation.WithPayload(adapter.ToJournal(payload)); - return representation.WithPayload(adapter.ToJournal(payload)).WithManifest(manifest); + // IdentityEventAdapter returns "" as manifest and normally the incoming PersistentRepr + // doesn't have an assigned manifest, but when WriteMessages is sent directly to the + // journal for testing purposes we want to preserve the original manifest instead of + // letting IdentityEventAdapter clearing it out. + return Equals(adapter, IdentityEventAdapter.Instance) + ? representation + : representation.WithManifest(adapter.Manifest(payload)); } } } diff --git a/src/core/Akka.Persistence/JournalProtocol.cs b/src/core/Akka.Persistence/JournalProtocol.cs index 2dcc9ee8ee7..5ad47a9bb4d 100644 --- a/src/core/Akka.Persistence/JournalProtocol.cs +++ b/src/core/Akka.Persistence/JournalProtocol.cs @@ -11,7 +11,8 @@ namespace Akka.Persistence { - public sealed class DeleteMessages + [Serializable] + public sealed class DeleteMessages : IEquatable { public DeleteMessages(IEnumerable messageIds, bool isPermanent, IActorRef requestor) { @@ -20,25 +21,81 @@ public DeleteMessages(IEnumerable messageIds, bool isPerman Requestor = requestor; } - public IEnumerable MessageIds { get; private set; } - public bool IsPermanent { get; private set; } - public IActorRef Requestor { get; private set; } + public readonly IEnumerable MessageIds; + public readonly bool IsPermanent; + public readonly IActorRef Requestor; + + public bool Equals(DeleteMessages other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Requestor, other.Requestor) + && Equals(IsPermanent, other.IsPermanent) + && Equals(MessageIds, other.MessageIds); + } + + public override bool Equals(object obj) + { + return Equals(obj as DeleteMessages); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (MessageIds != null ? MessageIds.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ IsPermanent.GetHashCode(); + hashCode = (hashCode * 397) ^ (Requestor != null ? Requestor.GetHashCode() : 0); + return hashCode; + } + } + + public override string ToString() + { + return string.Format("DeleteMessages", Requestor, IsPermanent); + } } - public sealed class DeleteMessagesSuccess + [Serializable] + public sealed class DeleteMessagesSuccess : IEquatable { public DeleteMessagesSuccess(IEnumerable messageIds) { MessageIds = messageIds; } - public IEnumerable MessageIds { get; private set; } + public readonly IEnumerable MessageIds; + + public bool Equals(DeleteMessagesSuccess other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(MessageIds, other.MessageIds); + } + + public override bool Equals(object obj) + { + return Equals(obj as DeleteMessagesSuccess); + } + + public override int GetHashCode() + { + return (MessageIds != null ? MessageIds.GetHashCode() : 0); + } + + public override string ToString() + { + return "DeleteMessagesSuccess<>"; + } } /// /// Reply message to failed request. /// - public sealed class DeleteMessagesFailure + [Serializable] + public sealed class DeleteMessagesFailure : IEquatable { public DeleteMessagesFailure(Exception cause) { @@ -48,40 +105,90 @@ public DeleteMessagesFailure(Exception cause) Cause = cause; } - public Exception Cause { get; private set; } + public readonly Exception Cause; + + public bool Equals(DeleteMessagesFailure other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Cause, other.Cause); + } + + public override bool Equals(object obj) + { + return Equals(obj as DeleteMessagesFailure); + } + + public override int GetHashCode() + { + return (Cause != null ? Cause.GetHashCode() : 0); + } + + public override string ToString() + { + return string.Format("DeleteMessagesFailure", Cause); + } } /// /// Request to delete all persistent messages with sequence numbers up to `toSequenceNr` (inclusive). /// + [Serializable] public sealed class DeleteMessagesTo : IEquatable { public DeleteMessagesTo(string persistenceId, long toSequenceNr, bool isPermanent) { + if (string.IsNullOrEmpty(persistenceId)) throw new ArgumentNullException("persistenceId", "DeleteMessagesTo requires persistence id to be provided"); + PersistenceId = persistenceId; ToSequenceNr = toSequenceNr; IsPermanent = isPermanent; } - public string PersistenceId { get; private set; } - public long ToSequenceNr { get; private set; } + public readonly string PersistenceId; + public readonly long ToSequenceNr; /// /// If false, the persistent messages are marked as deleted in the journal, /// otherwise they are permanently deleted from the journal. /// - public bool IsPermanent { get; private set; } + public readonly bool IsPermanent; public bool Equals(DeleteMessagesTo other) { - if (other == null) return false; + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + return PersistenceId == other.PersistenceId && ToSequenceNr == other.ToSequenceNr && IsPermanent == other.IsPermanent; } + + public override bool Equals(object obj) + { + return Equals(obj as DeleteMessagesTo); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (PersistenceId != null ? PersistenceId.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ ToSequenceNr.GetHashCode(); + hashCode = (hashCode * 397) ^ IsPermanent.GetHashCode(); + return hashCode; + } + } + + public override string ToString() + { + return string.Format("DeleteMessagesTo", PersistenceId, ToSequenceNr, IsPermanent); + } } - internal sealed class WriteConfirmationsFailure + [Serializable] + internal sealed class WriteConfirmationsFailure : IEquatable { public WriteConfirmationsFailure(Exception cause) { @@ -91,10 +198,34 @@ public WriteConfirmationsFailure(Exception cause) Cause = cause; } - public Exception Cause { get; private set; } + public readonly Exception Cause; + + public bool Equals(WriteConfirmationsFailure other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Cause, other.Cause); + } + + public override bool Equals(object obj) + { + return Equals(obj as WriteConfirmationsFailure); + } + + public override int GetHashCode() + { + return (Cause != null ? Cause.GetHashCode() : 0); + } + + public override string ToString() + { + return string.Format("WriteConfirmationsFailure", Cause); + } } - public sealed class WriteMessages + [Serializable] + public sealed class WriteMessages : IEquatable { public WriteMessages(IEnumerable messages, IActorRef persistentActor, int actorInstanceId) @@ -104,9 +235,40 @@ public WriteMessages(IEnumerable messages, IActorRef persis ActorInstanceId = actorInstanceId; } - public IEnumerable Messages { get; private set; } - public IActorRef PersistentActor { get; private set; } - public int ActorInstanceId { get; private set; } + public readonly IEnumerable Messages; + public readonly IActorRef PersistentActor; + public readonly int ActorInstanceId; + + public bool Equals(WriteMessages other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(ActorInstanceId, other.ActorInstanceId) + && Equals(PersistentActor, other.PersistentActor) + && Equals(Messages, other.Messages); + } + + public override bool Equals(object obj) + { + return Equals(obj as WriteMessages); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (Messages != null ? Messages.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (PersistentActor != null ? PersistentActor.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ ActorInstanceId; + return hashCode; + } + } + + public override string ToString() + { + return string.Format("WriteMessages", ActorInstanceId, PersistentActor); + } } /// @@ -122,15 +284,28 @@ private WriteMessagesSuccessful() { } public bool Equals(WriteMessagesSuccessful other) { + if (ReferenceEquals(other, null)) return false; + return true; } + + public override bool Equals(object obj) + { + return Equals(obj as WriteMessagesSuccessful); + } + + public override string ToString() + { + return "WriteMessagesSuccessful<>"; + } } /// /// Reply message to a failed request. This reply is sent /// to the requestor before all subsequent replies. /// - public sealed class WriteMessagesFailed + [Serializable] + public sealed class WriteMessagesFailed : IEquatable { public WriteMessagesFailed(Exception cause) { @@ -140,14 +315,38 @@ public WriteMessagesFailed(Exception cause) Cause = cause; } - public Exception Cause { get; private set; } + public readonly Exception Cause; + + public bool Equals(WriteMessagesFailed other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Cause, other.Cause); + } + + public override bool Equals(object obj) + { + return Equals(obj as WriteMessagesFailed); + } + + public override int GetHashCode() + { + return (Cause != null ? Cause.GetHashCode() : 0); + } + + public override string ToString() + { + return string.Format("WriteMessagesFailed", Cause); + } } /// /// Reply message to a successful request. For each contained /// message in the request, a separate reply is sent to the requestor. /// - public sealed class WriteMessageSuccess + [Serializable] + public sealed class WriteMessageSuccess : IEquatable { public WriteMessageSuccess(IPersistentRepresentation persistent, int actorInstanceId) { @@ -158,16 +357,43 @@ public WriteMessageSuccess(IPersistentRepresentation persistent, int actorInstan /// /// Successfully written message. /// - public IPersistentRepresentation Persistent { get; private set; } + public readonly IPersistentRepresentation Persistent; + public readonly int ActorInstanceId; + + public bool Equals(WriteMessageSuccess other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(ActorInstanceId, other.ActorInstanceId) + && Equals(Persistent, other.Persistent); + } + + public override bool Equals(object obj) + { + return Equals(obj as WriteMessageSuccess); + } + + public override int GetHashCode() + { + unchecked + { + return ((Persistent != null ? Persistent.GetHashCode() : 0) * 397) ^ ActorInstanceId; + } + } - public int ActorInstanceId { get; private set; } + public override string ToString() + { + return string.Format("WriteMessageSuccess", ActorInstanceId, Persistent); + } } /// /// Reply message to a failed request. For each contained /// message in the request, a separate reply is sent to the requestor. /// - public sealed class WriteMessageFailure + [Serializable] + public sealed class WriteMessageFailure : IEquatable { public WriteMessageFailure(IPersistentRepresentation persistent, Exception cause, int actorInstanceId) { @@ -182,17 +408,49 @@ public WriteMessageFailure(IPersistentRepresentation persistent, Exception cause /// /// Message failed to be written. /// - public IPersistentRepresentation Persistent { get; private set; } + public readonly IPersistentRepresentation Persistent; /// /// Failure cause. /// - public Exception Cause { get; private set; } + public readonly Exception Cause; + + public readonly int ActorInstanceId; + + public bool Equals(WriteMessageFailure other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; - public int ActorInstanceId { get; private set; } + return Equals(ActorInstanceId, other.ActorInstanceId) + && Equals(Persistent, other.Persistent) + && Equals(Cause, other.Cause); + } + + public override bool Equals(object obj) + { + return Equals(obj as WriteMessageFailure); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (Cause != null ? Cause.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ ActorInstanceId; + hashCode = (hashCode * 397) ^ (Persistent != null ? Persistent.GetHashCode() : 0); + return hashCode; + } + } + + public override string ToString() + { + return string.Format("WriteMessageFailure", ActorInstanceId, Persistent, Cause); + } } - public sealed class LoopMessage + [Serializable] + public sealed class LoopMessage : IEquatable { public LoopMessage(object message, IActorRef persistentActor, int actorInstanceId) { @@ -201,15 +459,47 @@ public LoopMessage(object message, IActorRef persistentActor, int actorInstanceI ActorInstanceId = actorInstanceId; } - public object Message { get; private set; } - public IActorRef PersistentActor { get; private set; } - public int ActorInstanceId { get; private set; } + public readonly object Message; + public readonly IActorRef PersistentActor; + public readonly int ActorInstanceId; + + public bool Equals(LoopMessage other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(ActorInstanceId, other.ActorInstanceId) + && Equals(PersistentActor, other.PersistentActor) + && Equals(Message, other.Message); + } + + public override bool Equals(object obj) + { + return Equals(obj as LoopMessage); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (Message != null ? Message.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (PersistentActor != null ? PersistentActor.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ ActorInstanceId; + return hashCode; + } + } + + public override string ToString() + { + return string.Format("LoopMessage", ActorInstanceId, PersistentActor, Message); + } } /// /// Reply message to a with a non-persistent message. /// - public sealed class LoopMessageSuccess + [Serializable] + public sealed class LoopMessageSuccess : IEquatable { public LoopMessageSuccess(object message, int actorInstanceId) { @@ -220,14 +510,41 @@ public LoopMessageSuccess(object message, int actorInstanceId) /// /// A looped message. /// - public object Message { get; private set; } + public readonly object Message; + public readonly int ActorInstanceId; + + public bool Equals(LoopMessageSuccess other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(ActorInstanceId, other.ActorInstanceId) + && Equals(Message, other.Message); + } + + public override bool Equals(object obj) + { + return Equals(obj as LoopMessageSuccess); + } - public int ActorInstanceId { get; private set; } + public override int GetHashCode() + { + unchecked + { + return ((Message != null ? Message.GetHashCode() : 0) * 397) ^ ActorInstanceId; + } + } + + public override string ToString() + { + return string.Format("LoopMessageSuccess", ActorInstanceId, Message); + } } /// /// Request to replay messages to the . /// + [Serializable] public sealed class ReplayMessages : IEquatable { public ReplayMessages(long fromSequenceNr, long toSequenceNr, long max, string persistenceId, @@ -244,62 +561,108 @@ public ReplayMessages(long fromSequenceNr, long toSequenceNr, long max, string p /// /// Inclusive lower sequence number bound where a replay should start. /// - public long FromSequenceNr { get; private set; } + public readonly long FromSequenceNr; /// /// Inclusive upper sequence number bound where a replay should end. /// - public long ToSequenceNr { get; private set; } + public readonly long ToSequenceNr; /// /// Maximum number of messages to be replayed. /// - public long Max { get; private set; } + public readonly long Max; /// /// Requesting persistent actor identifier. /// - public string PersistenceId { get; private set; } + public readonly string PersistenceId; /// /// Requesting persistent actor. /// - public IActorRef PersistentActor { get; private set; } + public readonly IActorRef PersistentActor; /// /// If true, message marked as deleted shall be replayed. /// - public bool ReplayDeleted { get; private set; } + public readonly bool ReplayDeleted; public bool Equals(ReplayMessages other) { - if (other == null) return false; - return PersistenceId == other.PersistenceId - && PersistentActor == other.PersistentActor - && FromSequenceNr == other.FromSequenceNr - && ToSequenceNr == other.ToSequenceNr - && Max == other.Max - && ReplayDeleted == other.ReplayDeleted; + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(PersistenceId, other.PersistenceId) + && Equals(PersistentActor, other.PersistentActor) + && Equals(FromSequenceNr, other.FromSequenceNr) + && Equals(ToSequenceNr, other.ToSequenceNr) + && Equals(Max, other.Max) + && Equals(ReplayDeleted, other.ReplayDeleted); + } + + public override bool Equals(object obj) + { + return Equals(obj as ReplayMessages); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = FromSequenceNr.GetHashCode(); + hashCode = (hashCode * 397) ^ ToSequenceNr.GetHashCode(); + hashCode = (hashCode * 397) ^ Max.GetHashCode(); + hashCode = (hashCode * 397) ^ (PersistenceId != null ? PersistenceId.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (PersistentActor != null ? PersistentActor.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ ReplayDeleted.GetHashCode(); + return hashCode; + } } } /// /// Reply message to a request. A separate reply is sent to the requestor for each replayed message. /// - public sealed class ReplayedMessage + [Serializable] + public sealed class ReplayedMessage : IEquatable { public ReplayedMessage(IPersistentRepresentation persistent) { Persistent = persistent; } - public IPersistentRepresentation Persistent { get; private set; } + public readonly IPersistentRepresentation Persistent; + + public bool Equals(ReplayedMessage other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Persistent, other.Persistent); + } + + public override bool Equals(object obj) + { + return Equals(obj as ReplayedMessage); + } + + public override int GetHashCode() + { + return (Persistent != null ? Persistent.GetHashCode() : 0); + } + + public override string ToString() + { + return string.Format("ReplayedMessage", Persistent); + } } /// /// Reply message to a successful request. This reply is sent /// to the requestor after all have been sent (if any). /// + [Serializable] public class ReplayMessagesSuccess : IEquatable { public static readonly ReplayMessagesSuccess Instance = new ReplayMessagesSuccess(); @@ -308,11 +671,23 @@ private ReplayMessagesSuccess() { } public bool Equals(ReplayMessagesSuccess other) { + if (ReferenceEquals(other, null)) return false; return true; } + + public override bool Equals(object obj) + { + return Equals(obj as ReplayMessagesSuccess); + } + + public override string ToString() + { + return "ReplayMessagesSuccess<>"; + } } - public sealed class ReplayMessagesFailure + [Serializable] + public sealed class ReplayMessagesFailure : IEquatable { public ReplayMessagesFailure(Exception cause) { @@ -322,9 +697,33 @@ public ReplayMessagesFailure(Exception cause) Cause = cause; } - public Exception Cause { get; private set; } + public readonly Exception Cause; + + public bool Equals(ReplayMessagesFailure other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Cause, other.Cause); + } + + public override bool Equals(object obj) + { + return Equals(obj as ReplayMessagesFailure); + } + + public override int GetHashCode() + { + return Cause.GetHashCode(); + } + + public override string ToString() + { + return string.Format("ReplayMessagesFailure", Cause); + } } + [Serializable] public sealed class ReadHighestSequenceNr : IEquatable { public ReadHighestSequenceNr(long fromSequenceNr, string persistenceId, IActorRef persistentActor) @@ -334,21 +733,45 @@ public ReadHighestSequenceNr(long fromSequenceNr, string persistenceId, IActorRe PersistentActor = persistentActor; } - public long FromSequenceNr { get; private set; } + public readonly long FromSequenceNr; - public string PersistenceId { get; private set; } + public readonly string PersistenceId; - public IActorRef PersistentActor { get; private set; } + public readonly IActorRef PersistentActor; public bool Equals(ReadHighestSequenceNr other) { - if (other == null) return false; - return PersistenceId == other.PersistenceId - && FromSequenceNr == other.FromSequenceNr - && PersistentActor == other.PersistentActor; + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(PersistenceId, other.PersistenceId) + && Equals(FromSequenceNr, other.FromSequenceNr) + && Equals(PersistentActor, other.PersistentActor); + } + + public override bool Equals(object obj) + { + return Equals(obj as ReadHighestSequenceNr); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = FromSequenceNr.GetHashCode(); + hashCode = (hashCode * 397) ^ (PersistenceId != null ? PersistenceId.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (PersistentActor != null ? PersistentActor.GetHashCode() : 0); + return hashCode; + } + } + + public override string ToString() + { + return string.Format("ReadHighestSequenceNr", PersistenceId, FromSequenceNr, PersistentActor); } } + [Serializable] public sealed class ReadHighestSequenceNrSuccess : IEquatable, IComparable { @@ -357,10 +780,13 @@ public ReadHighestSequenceNrSuccess(long highestSequenceNr) HighestSequenceNr = highestSequenceNr; } - public long HighestSequenceNr { get; private set; } + public readonly long HighestSequenceNr; public bool Equals(ReadHighestSequenceNrSuccess other) { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + return HighestSequenceNr == other.HighestSequenceNr; } @@ -372,27 +798,55 @@ public int CompareTo(ReadHighestSequenceNrSuccess other) public override bool Equals(object obj) { - var other = obj as ReadHighestSequenceNrSuccess; - return other != null && Equals(other); + return Equals(obj as ReadHighestSequenceNrSuccess); } public override int GetHashCode() { return HighestSequenceNr.GetHashCode(); } + + public override string ToString() + { + return string.Format("ReadHighestSequenceNrSuccess", HighestSequenceNr); + } } - public sealed class ReadHighestSequenceNrFailure + [Serializable] + public sealed class ReadHighestSequenceNrFailure : IEquatable { public ReadHighestSequenceNrFailure(Exception cause) { - if (cause == null) + if (cause == null) throw new ArgumentNullException("cause", "ReadHighestSequenceNrFailure cause exception cannot be null"); Cause = cause; } - public Exception Cause { get; private set; } + public readonly Exception Cause; + + public bool Equals(ReadHighestSequenceNrFailure other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Cause, other.Cause); + } + + public override bool Equals(object obj) + { + return Equals(obj as ReadHighestSequenceNrFailure); + } + + public override int GetHashCode() + { + return Cause.GetHashCode(); + } + + public override string ToString() + { + return string.Format("ReadHighestSequenceNrFailure", Cause); + } } } diff --git a/src/core/Akka.Persistence/Persistence.cs b/src/core/Akka.Persistence/Persistence.cs index 8da992c2035..f2626f02055 100644 --- a/src/core/Akka.Persistence/Persistence.cs +++ b/src/core/Akka.Persistence/Persistence.cs @@ -153,7 +153,7 @@ private PluginHolder CreatePlugin(string configPath, Func dispatch var pluginConfig = _system.Settings.Config.GetConfig(configPath); var pluginTypeName = pluginConfig.GetString("class"); - var pluginType = Type.GetType(pluginTypeName); + var pluginType = Type.GetType(pluginTypeName, true); var shouldInjectConfig = pluginConfig.HasPath("inject-config") && pluginConfig.GetBoolean("inject-config"); var pluginDispatcherId = pluginConfig.HasPath("plugin-dispatcher") diff --git a/src/core/Akka.Persistence/Persistent.cs b/src/core/Akka.Persistence/Persistent.cs index 2cbab424e46..b130f1e3bc0 100644 --- a/src/core/Akka.Persistence/Persistent.cs +++ b/src/core/Akka.Persistence/Persistent.cs @@ -113,9 +113,9 @@ public interface IPersistentRepresentation : IPersistentEnvelope, IWithPersisten } [Serializable] - public class Persistent : IPersistentRepresentation + public class Persistent : IPersistentRepresentation, IEquatable { - public readonly string Undefined = string.Empty; + public static readonly string Undefined = string.Empty; public Persistent(object payload, long sequenceNr = 0L, string manifest = null, string persistenceId = null, bool isDeleted = false, IActorRef sender = null) { @@ -160,6 +160,48 @@ public IPersistentRepresentation PrepareWrite(IActorContext context) { return PrepareWrite(Sender is FutureActorRef ? context.System.DeadLetters : Sender); } + + public bool Equals(IPersistentRepresentation other) + { + if (other == null) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(PersistenceId, other.PersistenceId) + && Equals(SequenceNr, other.SequenceNr) + && Equals(IsDeleted, other.IsDeleted) + && Equals(Manifest, other.Manifest) + && Equals(Sender, other.Sender) + && Equals(Payload, other.Payload); + } + + public override bool Equals(object obj) + { + return Equals(obj as IPersistentRepresentation); + } + + protected bool Equals(Persistent other) + { + return Equals(Payload, other.Payload) && Equals(Sender, other.Sender) && string.Equals(PersistenceId, other.PersistenceId) && IsDeleted == other.IsDeleted && SequenceNr == other.SequenceNr && string.Equals(Manifest, other.Manifest); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (Payload != null ? Payload.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Sender != null ? Sender.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (PersistenceId != null ? PersistenceId.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ IsDeleted.GetHashCode(); + hashCode = (hashCode * 397) ^ SequenceNr.GetHashCode(); + hashCode = (hashCode * 397) ^ (Manifest != null ? Manifest.GetHashCode() : 0); + return hashCode; + } + } + + public override string ToString() + { + return string.Format("Persistent", PersistenceId, SequenceNr, IsDeleted, Manifest, Sender, Payload); + } } } diff --git a/src/core/Akka.Persistence/Snapshot.cs b/src/core/Akka.Persistence/Snapshot.cs index 3fd678a6dad..dda82f06fd1 100644 --- a/src/core/Akka.Persistence/Snapshot.cs +++ b/src/core/Akka.Persistence/Snapshot.cs @@ -11,6 +11,7 @@ namespace Akka.Persistence { + [Serializable] public sealed class SnapshotMetadata : IEquatable { internal class SnapshotMetadataTimestampComparer : IComparer @@ -39,17 +40,17 @@ public SnapshotMetadata(string persistenceId, long sequenceNr, DateTime timestam /// /// Id of the persistent actor, from which the snapshot was taken. /// - public string PersistenceId { get; private set; } + public readonly string PersistenceId; /// /// Sequence number at which a snapshot was taken. /// - public long SequenceNr { get; private set; } + public readonly long SequenceNr; /// /// Time at which the snapshot was saved. /// - public DateTime Timestamp { get; private set; } + public readonly DateTime Timestamp; public override bool Equals(object obj) { @@ -58,7 +59,10 @@ public override bool Equals(object obj) public bool Equals(SnapshotMetadata other) { - return other != null && string.Equals(PersistenceId, other.PersistenceId) && SequenceNr == other.SequenceNr && Timestamp.Equals(other.Timestamp); + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return string.Equals(PersistenceId, other.PersistenceId) && SequenceNr == other.SequenceNr && Timestamp.Equals(other.Timestamp); } public override int GetHashCode() @@ -71,11 +75,17 @@ public override int GetHashCode() return hashCode; } } + + public override string ToString() + { + return string.Format("SnapshotMetadata", PersistenceId, SequenceNr, Timestamp); + } } /// /// Sent to after successful saving of a snapshot. /// + [Serializable] public sealed class SaveSnapshotSuccess : IEquatable { public SaveSnapshotSuccess(SnapshotMetadata metadata) @@ -83,18 +93,37 @@ public SaveSnapshotSuccess(SnapshotMetadata metadata) Metadata = metadata; } - public SnapshotMetadata Metadata { get; private set; } + public readonly SnapshotMetadata Metadata; public bool Equals(SaveSnapshotSuccess other) { - return other != null && other.Metadata.Equals(Metadata); + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Metadata, other.Metadata); + } + + public override bool Equals(object obj) + { + return Equals(obj as SaveSnapshotSuccess); + } + + public override int GetHashCode() + { + return (Metadata != null ? Metadata.GetHashCode() : 0); + } + + public override string ToString() + { + return string.Format("SaveSnapshotSuccess<{0}>", Metadata); } } /// /// Sent to after failed saving a snapshot. /// - public sealed class SaveSnapshotFailure + [Serializable] + public sealed class SaveSnapshotFailure : IEquatable { public SaveSnapshotFailure(SnapshotMetadata metadata, Exception cause) { @@ -105,19 +134,46 @@ public SaveSnapshotFailure(SnapshotMetadata metadata, Exception cause) /// /// Snapshot metadata. /// - public SnapshotMetadata Metadata { get; private set; } + public readonly SnapshotMetadata Metadata; /// /// A failure cause. /// - public Exception Cause { get; private set; } + public readonly Exception Cause; + + public bool Equals(SaveSnapshotFailure other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Cause, other.Cause) && Equals(Metadata, other.Metadata); + } + + public override bool Equals(object obj) + { + return Equals(obj as SaveSnapshotFailure); + } + + public override int GetHashCode() + { + unchecked + { + return ((Metadata != null ? Metadata.GetHashCode() : 0) * 397) ^ (Cause != null ? Cause.GetHashCode() : 0); + } + } + + public override string ToString() + { + return string.Format("SaveSnapshotFailure", Metadata, Cause); + } } /// /// Offers a a previously saved snapshot during recovery. /// This offer is received before any further replayed messages. /// - public sealed class SnapshotOffer + [Serializable] + public sealed class SnapshotOffer : IEquatable { public SnapshotOffer(SnapshotMetadata metadata, object snapshot) { @@ -125,14 +181,41 @@ public SnapshotOffer(SnapshotMetadata metadata, object snapshot) Snapshot = snapshot; } - public SnapshotMetadata Metadata { get; private set; } - public object Snapshot { get; private set; } + public readonly SnapshotMetadata Metadata; + public readonly object Snapshot; + + public bool Equals(SnapshotOffer other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Metadata, other.Metadata) && Equals(Snapshot, other.Snapshot); + } + + public override bool Equals(object obj) + { + return Equals(obj as SnapshotOffer); + } + + public override int GetHashCode() + { + unchecked + { + return ((Metadata != null ? Metadata.GetHashCode() : 0) * 397) ^ (Snapshot != null ? Snapshot.GetHashCode() : 0); + } + } + + public override string ToString() + { + return string.Format("SnapshotOffer", Metadata, Snapshot); + } } /// /// Selection criteria for loading and deleting a snapshots. /// - public sealed class SnapshotSelectionCriteria + [Serializable] + public sealed class SnapshotSelectionCriteria : IEquatable { public static readonly SnapshotSelectionCriteria Latest = new SnapshotSelectionCriteria(long.MaxValue, DateTime.MaxValue); public static readonly SnapshotSelectionCriteria None = new SnapshotSelectionCriteria(0L, DateTime.MinValue); @@ -151,12 +234,12 @@ public SnapshotSelectionCriteria(long maxSequenceNr) : this(maxSequenceNr, DateT /// /// Upper bound for a selected snapshot's sequence number. /// - public long MaxSequenceNr { get; private set; } + public readonly long MaxSequenceNr; /// /// Upper bound for a selected snapshot's timestamp. /// - public DateTime MaxTimeStamp { get; private set; } + public readonly DateTime MaxTimeStamp; internal SnapshotSelectionCriteria Limit(long toSequenceNr) { @@ -169,12 +252,39 @@ internal bool IsMatch(SnapshotMetadata metadata) { return metadata.SequenceNr <= MaxSequenceNr && metadata.Timestamp <= MaxTimeStamp; } + + public bool Equals(SnapshotSelectionCriteria other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return MaxSequenceNr == other.MaxSequenceNr && MaxTimeStamp == other.MaxTimeStamp; + } + + public override bool Equals(object obj) + { + return Equals(obj as SnapshotSelectionCriteria); + } + + public override int GetHashCode() + { + unchecked + { + return (MaxSequenceNr.GetHashCode() * 397) ^ MaxTimeStamp.GetHashCode(); + } + } + + public override string ToString() + { + return string.Format("SnapshotSelectionCriteria /// A selected snapshot matching . /// - public sealed class SelectedSnapshot + [Serializable] + public sealed class SelectedSnapshot : IEquatable { public SelectedSnapshot(SnapshotMetadata metadata, object snapshot) { @@ -182,8 +292,34 @@ public SelectedSnapshot(SnapshotMetadata metadata, object snapshot) Snapshot = snapshot; } - public SnapshotMetadata Metadata { get; private set; } - public object Snapshot { get; private set; } + public readonly SnapshotMetadata Metadata; + public readonly object Snapshot; + + public bool Equals(SelectedSnapshot other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Metadata, other.Metadata) && Equals(Snapshot, other.Snapshot); + } + + public override bool Equals(object obj) + { + return Equals(obj as SelectedSnapshot); + } + + public override int GetHashCode() + { + unchecked + { + return ((Metadata != null ? Metadata.GetHashCode() : 0) * 397) ^ (Snapshot != null ? Snapshot.GetHashCode() : 0); + } + } + + public override string ToString() + { + return string.Format("SelectedSnapshot", Metadata, Snapshot); + } } @@ -192,7 +328,8 @@ public SelectedSnapshot(SnapshotMetadata metadata, object snapshot) /// /// Instructs a snapshot store to load the snapshot. /// - public sealed class LoadSnapshot + [Serializable] + public sealed class LoadSnapshot: IEquatable { public LoadSnapshot(string persistenceId, SnapshotSelectionCriteria criteria, long toSequenceNr) { @@ -204,23 +341,55 @@ public LoadSnapshot(string persistenceId, SnapshotSelectionCriteria criteria, lo /// /// Persistent actor identifier. /// - public string PersistenceId { get; private set; } + public readonly string PersistenceId; /// /// Criteria for selecting snapshot, from which the recovery should start. /// - public SnapshotSelectionCriteria Criteria { get; private set; } + public readonly SnapshotSelectionCriteria Criteria; /// /// Upper, inclusive sequence number bound for recovery. /// - public long ToSequenceNr { get; private set; } + public readonly long ToSequenceNr; + + public bool Equals(LoadSnapshot other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(ToSequenceNr, other.ToSequenceNr) + && Equals(PersistenceId, other.PersistenceId) + && Equals(Criteria, other.Criteria); + } + + public override bool Equals(object obj) + { + return Equals(obj as LoadSnapshot); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (PersistenceId != null ? PersistenceId.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Criteria != null ? Criteria.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ ToSequenceNr.GetHashCode(); + return hashCode; + } + } + + public override string ToString() + { + return string.Format("LoadSnapshot", PersistenceId, ToSequenceNr, Criteria); + } } /// /// Response to a message. /// - public sealed class LoadSnapshotResult + [Serializable] + public sealed class LoadSnapshotResult : IEquatable { public LoadSnapshotResult(SelectedSnapshot snapshot, long toSequenceNr) { @@ -231,42 +400,127 @@ public LoadSnapshotResult(SelectedSnapshot snapshot, long toSequenceNr) /// /// Loaded snapshot or null if none provided. /// - public SelectedSnapshot Snapshot { get; private set; } - public long ToSequenceNr { get; private set; } + public readonly SelectedSnapshot Snapshot; + public readonly long ToSequenceNr; + + public bool Equals(LoadSnapshotResult other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(ToSequenceNr, other.ToSequenceNr) + && Equals(Snapshot, other.Snapshot); + } + + public override bool Equals(object obj) + { + return Equals(obj as LoadSnapshotResult); + } + + public override int GetHashCode() + { + unchecked + { + return ((Snapshot != null ? Snapshot.GetHashCode() : 0) * 397) ^ ToSequenceNr.GetHashCode(); + } + } + + public override string ToString() + { + return string.Format("LoadSnapshotResult", ToSequenceNr, Snapshot); + } } /// /// Instructs a snapshot store to save a snapshot. /// - public sealed class SaveSnapshot + [Serializable] + public sealed class SaveSnapshot : IEquatable { public SaveSnapshot(SnapshotMetadata metadata, object snapshot) { + if (metadata == null) + throw new ArgumentNullException("metadata", "SaveSnapshot requires SnapshotMetadata to be provided"); + Metadata = metadata; Snapshot = snapshot; } - public SnapshotMetadata Metadata { get; private set; } - public object Snapshot { get; private set; } + public readonly SnapshotMetadata Metadata; + public readonly object Snapshot; + + public bool Equals(SaveSnapshot other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Metadata, other.Metadata) && Equals(Snapshot, other.Snapshot); + } + + public override bool Equals(object obj) + { + return Equals(obj as SaveSnapshot); + } + + public override int GetHashCode() + { + unchecked + { + return ((Metadata != null ? Metadata.GetHashCode() : 0) * 397) ^ (Snapshot != null ? Snapshot.GetHashCode() : 0); + } + } + + public override string ToString() + { + return string.Format("SaveSnapshot", Metadata, Snapshot); + } } /// /// Instructs a snapshot store to delete a snapshot. /// - public sealed class DeleteSnapshot + [Serializable] + public sealed class DeleteSnapshot : IEquatable { public DeleteSnapshot(SnapshotMetadata metadata) { + if(metadata == null) + throw new ArgumentNullException("metadata", "DeleteSnapshot requires SnapshotMetadata to be provided"); + Metadata = metadata; } - public SnapshotMetadata Metadata { get; private set; } + public readonly SnapshotMetadata Metadata; + + public bool Equals(DeleteSnapshot other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Metadata, other.Metadata); + } + + public override bool Equals(object obj) + { + return Equals(obj as DeleteSnapshot); + } + + public override int GetHashCode() + { + return Metadata.GetHashCode(); + } + + public override string ToString() + { + return string.Format("DeleteSnapshot", Metadata); + } } /// /// Instructs a snapshot store to delete all snapshots that match provided criteria. /// - public sealed class DeleteSnapshots + [Serializable] + public sealed class DeleteSnapshots : IEquatable { public DeleteSnapshots(string persistenceId, SnapshotSelectionCriteria criteria) { @@ -274,8 +528,35 @@ public DeleteSnapshots(string persistenceId, SnapshotSelectionCriteria criteria) Criteria = criteria; } - public string PersistenceId { get; private set; } - public SnapshotSelectionCriteria Criteria { get; private set; } + public readonly string PersistenceId; + public readonly SnapshotSelectionCriteria Criteria; + + public bool Equals(DeleteSnapshots other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(PersistenceId, other.PersistenceId) + && Equals(Criteria, other.Criteria); + } + + public override bool Equals(object obj) + { + return Equals(obj as DeleteSnapshots); + } + + public override int GetHashCode() + { + unchecked + { + return ((PersistenceId != null ? PersistenceId.GetHashCode() : 0) * 397) ^ (Criteria != null ? Criteria.GetHashCode() : 0); + } + } + + public override string ToString() + { + return string.Format("DeleteSnapshots", PersistenceId, Criteria); + } } #endregion diff --git a/src/core/Akka.Persistence/Snapshot/LocalSnapshotStore.cs b/src/core/Akka.Persistence/Snapshot/LocalSnapshotStore.cs index ae97882061d..5b2cb8a5d8f 100644 --- a/src/core/Akka.Persistence/Snapshot/LocalSnapshotStore.cs +++ b/src/core/Akka.Persistence/Snapshot/LocalSnapshotStore.cs @@ -103,17 +103,17 @@ protected override void Saved(SnapshotMetadata metadata) _saving.Remove(metadata); } - protected override void Delete(SnapshotMetadata metadata) + protected override async Task DeleteAsync(SnapshotMetadata metadata) { _saving.Remove(metadata); GetSnapshotFile(metadata).Delete(); } - protected override void Delete(string persistenceId, SnapshotSelectionCriteria criteria) + protected override async Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { foreach (var metadata in GetSnapshotMetadata(persistenceId, criteria)) { - Delete(metadata); + await DeleteAsync(metadata); } } diff --git a/src/core/Akka.Persistence/Snapshot/SnapshotStore.cs b/src/core/Akka.Persistence/Snapshot/SnapshotStore.cs index 5b423d25af2..cce045982fd 100644 --- a/src/core/Akka.Persistence/Snapshot/SnapshotStore.cs +++ b/src/core/Akka.Persistence/Snapshot/SnapshotStore.cs @@ -59,28 +59,31 @@ protected override bool Receive(object message) else if (message is SaveSnapshotFailure) { var msg = (SaveSnapshotFailure)message; - Delete(msg.Metadata); - Sender.Tell(message); // Sender is PersistentActor + DeleteAsync(msg.Metadata) + .ContinueWith(t => msg) + .PipeTo(Sender); // Sender is PersistentActor } else if (message is DeleteSnapshot) { var msg = (DeleteSnapshot)message; - Delete(msg.Metadata); - - if (_publish) + var eventStream = Context.System.EventStream; + DeleteAsync(msg.Metadata).ContinueWith(t => { - Context.System.EventStream.Publish(message); - } + if (_publish) eventStream.Publish(message); + }, + TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); + } else if (message is DeleteSnapshots) { - var msg = (DeleteSnapshots) message; - Delete(msg.PersistenceId, msg.Criteria); - - if (_publish) + var msg = (DeleteSnapshots)message; + var eventStream = Context.System.EventStream; + DeleteAsync(msg.PersistenceId, msg.Criteria).ContinueWith(t => { - Context.System.EventStream.Publish(message); - } + if (_publish) eventStream.Publish(message); + }, + TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); + } else return false; return true; @@ -104,12 +107,12 @@ protected override bool Receive(object message) /// /// Deletes the snapshot identified by . /// - protected abstract void Delete(SnapshotMetadata metadata); + protected abstract Task DeleteAsync(SnapshotMetadata metadata); /// /// Deletes all snapshots matching provided . /// - protected abstract void Delete(string persistenceId, SnapshotSelectionCriteria criteria); + protected abstract Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria); } } diff --git a/src/core/Akka.Persistence/licenses/license.txt b/src/core/Akka.Persistence/licenses/license.txt new file mode 100644 index 00000000000..b8e773b2e05 --- /dev/null +++ b/src/core/Akka.Persistence/licenses/license.txt @@ -0,0 +1,31 @@ +Protocol Buffers - Google's data interchange format +Copyright 2008-2010 Google Inc. All rights reserved. +http://github.com/jskeet/dotnet-protobufs/ +Original C++/Java/Python code: +http://code.google.com/p/protobuf/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Persistence/licenses/protoc-license.txt b/src/core/Akka.Persistence/licenses/protoc-license.txt new file mode 100644 index 00000000000..c779cb0e1ed --- /dev/null +++ b/src/core/Akka.Persistence/licenses/protoc-license.txt @@ -0,0 +1,36 @@ +protoc.exe was built from the original source at http://code.google.com/p/protobuf/ +The licence for this code is as follows: + +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Persistence/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Persistence/protos/google/protobuf/csharp_options.proto new file mode 100644 index 00000000000..152df766f03 --- /dev/null +++ b/src/core/Akka.Persistence/protos/google/protobuf/csharp_options.proto @@ -0,0 +1,115 @@ +// Extra options for C# generator + +import "google/protobuf/descriptor.proto"; + +package google.protobuf; + +message CSharpFileOptions { + + // Namespace for generated classes; defaults to the package. + optional string namespace = 1; + + // Name of the "umbrella" class used for metadata about all + // the messages within this file. Default is based on the name + // of the file. + optional string umbrella_classname = 2; + + // Whether classes should be public (true) or internal (false) + optional bool public_classes = 3 [default = true]; + + // Whether to generate a single file for everything within the + // .proto file (false), or one file per message (true). + // This option is not currently honored; please log a feature + // request if you really want it. + optional bool multiple_files = 4; + + // Whether to nest messages within a single umbrella class (true) + // or create the umbrella class as a peer, with messages as + // top-level classes in the namespace (false) + optional bool nest_classes = 5; + + // Generate appropriate support for Code Contracts + // (Ongoing; support should improve over time) + optional bool code_contracts = 6; + + // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" + // would generate files within [output directory]/Foo/Bar + optional bool expand_namespace_directories = 7; + + // Generate attributes indicating non-CLS-compliance + optional bool cls_compliance = 8 [default = true]; + + // Generate messages/builders with the [Serializable] attribute + optional bool add_serializable = 9 [default = false]; + + // Generates a private ctor for Message types + optional bool generate_private_ctor = 10 [default = true]; + + // The extension that should be appended to the umbrella_classname when creating files. + optional string file_extension = 221 [default = ".cs"]; + + // A nested namespace for the umbrella class. Helpful for name collisions caused by + // umbrella_classname conflicting with an existing type. This will be automatically + // set to 'Proto' if a collision is detected with types being generated. This value + // is ignored when nest_classes == true + optional string umbrella_namespace = 222; + + // The output path for the source file(s) generated + optional string output_directory = 223 [default = "."]; + + // Will ignore the type generations and remove dependencies for the descriptor proto + // files that declare their package to be "google.protobuf" + optional bool ignore_google_protobuf = 224 [default = false]; + + // Controls how services are generated, GENERIC is the deprecated original implementation + // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and + // implementations using the included Windows RPC interop libarary. + optional CSharpServiceType service_generator_type = 225 [default = NONE]; + + // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and + // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. + optional bool generated_code_attributes = 226 [default = false]; +} + +enum CSharpServiceType { + // Services are ignored by the generator + NONE = 0; + // Generates the original Java generic service implementations + GENERIC = 1; + // Generates an interface for the service and nothing else + INTERFACE = 2; + // Generates an interface for the service and client/server wrappers for the interface + IRPCDISPATCH = 3; +} + +extend FileOptions { + optional CSharpFileOptions csharp_file_options = 1000; +} + +extend FieldOptions { + optional CSharpFieldOptions csharp_field_options = 1000; +} + +message CSharpFieldOptions { + // Provides the ability to override the name of the property + // generated for this field. This is applied to all properties + // and methods to do with this field, including HasFoo, FooCount, + // FooList etc. + optional string property_name = 1; +} + +message CSharpServiceOptions { + optional string interface_id = 1; +} + +extend ServiceOptions { + optional CSharpServiceOptions csharp_service_options = 1000; +} + +message CSharpMethodOptions { + optional int32 dispatch_id = 1; +} + +extend MethodOptions { + optional CSharpMethodOptions csharp_method_options = 1000; +} \ No newline at end of file diff --git a/src/core/Akka.Persistence/protos/google/protobuf/descriptor.proto b/src/core/Akka.Persistence/protos/google/protobuf/descriptor.proto new file mode 100644 index 00000000000..233f879410e --- /dev/null +++ b/src/core/Akka.Persistence/protos/google/protobuf/descriptor.proto @@ -0,0 +1,533 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + + +package google.protobuf; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + optional MessageOptions options = 7; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4; + TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + optional FieldOptions options = 8; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; +} + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail kenton@google.com to reserve extension +// numbers. Simply tell me how many you need and I'll send you back a +// set of numbers to use -- there's no need to explain how you intend to +// use them. If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. This is + // purely a speed optimization, as the AbstractMessage base class includes + // reflection-based implementations of these methods. + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of proto2. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. + optional bool packed = 2; + + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // EXPERIMENTAL. DO NOT USE. + // For "map" fields, the name of the field in the enclosed type that + // is the key for this map. For example, suppose we have: + // message Item { + // required string name = 1; + // required string value = 2; + // } + // message Config { + // repeated Item items = 1 [experimental_map_key="name"]; + // } + // In this situation, the map key for Item will be set to "name". + // TODO: Fully-implement this, then remove the "experimental_" prefix. + optional string experimental_map_key = 9; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // TODO(kenton): Record comments appearing before and after the + // declaration. + } +} diff --git a/src/core/Akka.Persistence/protos/tutorial/addressbook.proto b/src/core/Akka.Persistence/protos/tutorial/addressbook.proto new file mode 100644 index 00000000000..5abe35ce39b --- /dev/null +++ b/src/core/Akka.Persistence/protos/tutorial/addressbook.proto @@ -0,0 +1,31 @@ +package tutorial; + +import "google/protobuf/csharp_options.proto"; +option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; +option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; + +option optimize_for = SPEED; + +message Person { + required string name = 1; + required int32 id = 2; // Unique ID number for this person. + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person person = 1; +} diff --git a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj index 1a012ae8bb1..32220732774 100644 --- a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj +++ b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj @@ -35,6 +35,24 @@ bin\Release\Akka.Remote.TestKit.xml + + True + + + True + + + True + + + True + + + True + + + True + @@ -123,35 +141,7 @@ --> - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll - True - True - - - - + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll @@ -193,7 +183,7 @@ - + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll diff --git a/src/core/Akka.Remote.TestKit/CHANGES.txt b/src/core/Akka.Remote.TestKit/CHANGES.txt new file mode 100644 index 00000000000..d80368c78f2 --- /dev/null +++ b/src/core/Akka.Remote.TestKit/CHANGES.txt @@ -0,0 +1,99 @@ +=============================================================================== +Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet +(skeet@pobox.com) based on the work of many talented people. + +For more information about this port, visit its homepage: +http://protobuf-csharp-port.googlecode.com + +For more information about Protocol Buffers in general, visit the project page +for the C++, Java and Python project: +http://protobuf.googlecode.com +=============================================================================== +RELEASE NOTES - Version 2.4.1.473 +=============================================================================== + +Features: +- Added option service_generator_type to control service generation with + NONE, GENERIC, INTERFACE, or IRPCDISPATCH +- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking + services and implementations. +- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the + location of protoc.exe. +- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow + custom implementation of writers with both speed and size optimizations. +- Addition of the "Google.ProtoBuffers.Serialization" assembly to support + reading and writing messages to/from XML, JSON, IDictionary<,> and others. +- Several performance related fixes and tweeks +- Issue 3: Add option to mark generated code with attribute +- Issue 20: Support for decorating classes [Serializable] +- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] +- Issue 22: Reusable Builder classes +- Issue 24: Support for using Json/Xml formats with ICodedInputStream +- Issue 25: Added support for NuGet packages +- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 + +Fixes: +- Issue 13: Message with Field same name as message causes uncompilable .cs +- Issue 16: Does not integrate well with other tooling +- Issue 19: Support for negative enum values +- Issue 26: AddRange in GeneratedBuilder iterates twice. +- Issue 27: Remove XML documentation output from test projects to clear + warnings/errors. +- Issue 28: Circular message dependencies result in null default values for + Message fields. +- Issue 29: Message classes generated have a public default constructor. You + can disable private ctor generation with the option generate_private_ctor. +- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ +- Big-endian support for float, and double on Silverlight +- Packed and Unpacked parsing allow for all repeated, as per version 2.3 +- Fix for leaving Builder a public ctor on internal classes for use with + generic "where T: new()" constraints. + +Other: +- Changed the code signing key to a privately held key +- Reformatted all code and line-endings to C# defaults +- Reworking of performance benchmarks to produce reliable results, option /v2 +- Issue 34: Silverlight assemblies are now unit tested + +=============================================================================== +RELEASE NOTES - Version 2.3.0.277 +=============================================================================== + +Features: +- Added cls_compliance option to generate attributes indicating + non-CLS-compliance. +- Added file_extension option to control the generated output file's extension. +- Added umbrella_namespace option to place the umbrella class into a nested + namespace to address issues with proto files having the same name as a + message it contains. +- Added output_directory option to set the output path for the source file(s). +- Added ignore_google_protobuf option to avoid generating code for includes + from the google.protobuf package. +- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to + generate code with "option optimize_for = LITE_RUNTIME;". +- Added ability to invoke protoc.exe from within ProtoGen.exe. +- Upgraded to protoc.exe (2.3) compiler. + +Fixes: +- Issue 9: Class cannot be static and sealed error +- Issue 12: default value for enumerate fields must be filled out + +Other: +- Rewrite of build using MSBbuild instead of NAnt +- Moved to NUnit Version 2.2.8.0 +- Changed to using secure .snk for releases + +=============================================================================== +RELEASE NOTES - Version 0.9.1 +=============================================================================== + +Fixes: +- issue 10: Incorrect encoding of packed fields when serialized + +=============================================================================== +RELEASE NOTES - Version 0.9.0 +=============================================================================== + +- Initial release + +=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/licenses/license.txt b/src/core/Akka.Remote.TestKit/licenses/license.txt new file mode 100644 index 00000000000..b8e773b2e05 --- /dev/null +++ b/src/core/Akka.Remote.TestKit/licenses/license.txt @@ -0,0 +1,31 @@ +Protocol Buffers - Google's data interchange format +Copyright 2008-2010 Google Inc. All rights reserved. +http://github.com/jskeet/dotnet-protobufs/ +Original C++/Java/Python code: +http://code.google.com/p/protobuf/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Remote.TestKit/licenses/protoc-license.txt b/src/core/Akka.Remote.TestKit/licenses/protoc-license.txt new file mode 100644 index 00000000000..c779cb0e1ed --- /dev/null +++ b/src/core/Akka.Remote.TestKit/licenses/protoc-license.txt @@ -0,0 +1,36 @@ +protoc.exe was built from the original source at http://code.google.com/p/protobuf/ +The licence for this code is as follows: + +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Remote.TestKit/protos/google/protobuf/csharp_options.proto new file mode 100644 index 00000000000..152df766f03 --- /dev/null +++ b/src/core/Akka.Remote.TestKit/protos/google/protobuf/csharp_options.proto @@ -0,0 +1,115 @@ +// Extra options for C# generator + +import "google/protobuf/descriptor.proto"; + +package google.protobuf; + +message CSharpFileOptions { + + // Namespace for generated classes; defaults to the package. + optional string namespace = 1; + + // Name of the "umbrella" class used for metadata about all + // the messages within this file. Default is based on the name + // of the file. + optional string umbrella_classname = 2; + + // Whether classes should be public (true) or internal (false) + optional bool public_classes = 3 [default = true]; + + // Whether to generate a single file for everything within the + // .proto file (false), or one file per message (true). + // This option is not currently honored; please log a feature + // request if you really want it. + optional bool multiple_files = 4; + + // Whether to nest messages within a single umbrella class (true) + // or create the umbrella class as a peer, with messages as + // top-level classes in the namespace (false) + optional bool nest_classes = 5; + + // Generate appropriate support for Code Contracts + // (Ongoing; support should improve over time) + optional bool code_contracts = 6; + + // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" + // would generate files within [output directory]/Foo/Bar + optional bool expand_namespace_directories = 7; + + // Generate attributes indicating non-CLS-compliance + optional bool cls_compliance = 8 [default = true]; + + // Generate messages/builders with the [Serializable] attribute + optional bool add_serializable = 9 [default = false]; + + // Generates a private ctor for Message types + optional bool generate_private_ctor = 10 [default = true]; + + // The extension that should be appended to the umbrella_classname when creating files. + optional string file_extension = 221 [default = ".cs"]; + + // A nested namespace for the umbrella class. Helpful for name collisions caused by + // umbrella_classname conflicting with an existing type. This will be automatically + // set to 'Proto' if a collision is detected with types being generated. This value + // is ignored when nest_classes == true + optional string umbrella_namespace = 222; + + // The output path for the source file(s) generated + optional string output_directory = 223 [default = "."]; + + // Will ignore the type generations and remove dependencies for the descriptor proto + // files that declare their package to be "google.protobuf" + optional bool ignore_google_protobuf = 224 [default = false]; + + // Controls how services are generated, GENERIC is the deprecated original implementation + // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and + // implementations using the included Windows RPC interop libarary. + optional CSharpServiceType service_generator_type = 225 [default = NONE]; + + // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and + // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. + optional bool generated_code_attributes = 226 [default = false]; +} + +enum CSharpServiceType { + // Services are ignored by the generator + NONE = 0; + // Generates the original Java generic service implementations + GENERIC = 1; + // Generates an interface for the service and nothing else + INTERFACE = 2; + // Generates an interface for the service and client/server wrappers for the interface + IRPCDISPATCH = 3; +} + +extend FileOptions { + optional CSharpFileOptions csharp_file_options = 1000; +} + +extend FieldOptions { + optional CSharpFieldOptions csharp_field_options = 1000; +} + +message CSharpFieldOptions { + // Provides the ability to override the name of the property + // generated for this field. This is applied to all properties + // and methods to do with this field, including HasFoo, FooCount, + // FooList etc. + optional string property_name = 1; +} + +message CSharpServiceOptions { + optional string interface_id = 1; +} + +extend ServiceOptions { + optional CSharpServiceOptions csharp_service_options = 1000; +} + +message CSharpMethodOptions { + optional int32 dispatch_id = 1; +} + +extend MethodOptions { + optional CSharpMethodOptions csharp_method_options = 1000; +} \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/protos/google/protobuf/descriptor.proto b/src/core/Akka.Remote.TestKit/protos/google/protobuf/descriptor.proto new file mode 100644 index 00000000000..233f879410e --- /dev/null +++ b/src/core/Akka.Remote.TestKit/protos/google/protobuf/descriptor.proto @@ -0,0 +1,533 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + + +package google.protobuf; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + optional MessageOptions options = 7; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4; + TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + optional FieldOptions options = 8; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; +} + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail kenton@google.com to reserve extension +// numbers. Simply tell me how many you need and I'll send you back a +// set of numbers to use -- there's no need to explain how you intend to +// use them. If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. This is + // purely a speed optimization, as the AbstractMessage base class includes + // reflection-based implementations of these methods. + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of proto2. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. + optional bool packed = 2; + + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // EXPERIMENTAL. DO NOT USE. + // For "map" fields, the name of the field in the enclosed type that + // is the key for this map. For example, suppose we have: + // message Item { + // required string name = 1; + // required string value = 2; + // } + // message Config { + // repeated Item items = 1 [experimental_map_key="name"]; + // } + // In this situation, the map key for Item will be set to "name". + // TODO: Fully-implement this, then remove the "experimental_" prefix. + optional string experimental_map_key = 9; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // TODO(kenton): Record comments appearing before and after the + // declaration. + } +} diff --git a/src/core/Akka.Remote.TestKit/protos/tutorial/addressbook.proto b/src/core/Akka.Remote.TestKit/protos/tutorial/addressbook.proto new file mode 100644 index 00000000000..5abe35ce39b --- /dev/null +++ b/src/core/Akka.Remote.TestKit/protos/tutorial/addressbook.proto @@ -0,0 +1,31 @@ +package tutorial; + +import "google/protobuf/csharp_options.proto"; +option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; +option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; + +option optimize_for = SPEED; + +message Person { + required string name = 1; + required int32 id = 2; // Unique ID number for this person. + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person person = 1; +} diff --git a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj index 964d65821c8..562732f4c6c 100644 --- a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj +++ b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj @@ -52,6 +52,24 @@ false + + True + + + True + + + True + + + True + + + True + + + True + @@ -140,35 +158,7 @@ --> - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll - True - True - - - - + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll @@ -210,7 +200,7 @@ - + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll diff --git a/src/core/Akka.Remote.Tests/CHANGES.txt b/src/core/Akka.Remote.Tests/CHANGES.txt new file mode 100644 index 00000000000..d80368c78f2 --- /dev/null +++ b/src/core/Akka.Remote.Tests/CHANGES.txt @@ -0,0 +1,99 @@ +=============================================================================== +Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet +(skeet@pobox.com) based on the work of many talented people. + +For more information about this port, visit its homepage: +http://protobuf-csharp-port.googlecode.com + +For more information about Protocol Buffers in general, visit the project page +for the C++, Java and Python project: +http://protobuf.googlecode.com +=============================================================================== +RELEASE NOTES - Version 2.4.1.473 +=============================================================================== + +Features: +- Added option service_generator_type to control service generation with + NONE, GENERIC, INTERFACE, or IRPCDISPATCH +- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking + services and implementations. +- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the + location of protoc.exe. +- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow + custom implementation of writers with both speed and size optimizations. +- Addition of the "Google.ProtoBuffers.Serialization" assembly to support + reading and writing messages to/from XML, JSON, IDictionary<,> and others. +- Several performance related fixes and tweeks +- Issue 3: Add option to mark generated code with attribute +- Issue 20: Support for decorating classes [Serializable] +- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] +- Issue 22: Reusable Builder classes +- Issue 24: Support for using Json/Xml formats with ICodedInputStream +- Issue 25: Added support for NuGet packages +- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 + +Fixes: +- Issue 13: Message with Field same name as message causes uncompilable .cs +- Issue 16: Does not integrate well with other tooling +- Issue 19: Support for negative enum values +- Issue 26: AddRange in GeneratedBuilder iterates twice. +- Issue 27: Remove XML documentation output from test projects to clear + warnings/errors. +- Issue 28: Circular message dependencies result in null default values for + Message fields. +- Issue 29: Message classes generated have a public default constructor. You + can disable private ctor generation with the option generate_private_ctor. +- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ +- Big-endian support for float, and double on Silverlight +- Packed and Unpacked parsing allow for all repeated, as per version 2.3 +- Fix for leaving Builder a public ctor on internal classes for use with + generic "where T: new()" constraints. + +Other: +- Changed the code signing key to a privately held key +- Reformatted all code and line-endings to C# defaults +- Reworking of performance benchmarks to produce reliable results, option /v2 +- Issue 34: Silverlight assemblies are now unit tested + +=============================================================================== +RELEASE NOTES - Version 2.3.0.277 +=============================================================================== + +Features: +- Added cls_compliance option to generate attributes indicating + non-CLS-compliance. +- Added file_extension option to control the generated output file's extension. +- Added umbrella_namespace option to place the umbrella class into a nested + namespace to address issues with proto files having the same name as a + message it contains. +- Added output_directory option to set the output path for the source file(s). +- Added ignore_google_protobuf option to avoid generating code for includes + from the google.protobuf package. +- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to + generate code with "option optimize_for = LITE_RUNTIME;". +- Added ability to invoke protoc.exe from within ProtoGen.exe. +- Upgraded to protoc.exe (2.3) compiler. + +Fixes: +- Issue 9: Class cannot be static and sealed error +- Issue 12: default value for enumerate fields must be filled out + +Other: +- Rewrite of build using MSBbuild instead of NAnt +- Moved to NUnit Version 2.2.8.0 +- Changed to using secure .snk for releases + +=============================================================================== +RELEASE NOTES - Version 0.9.1 +=============================================================================== + +Fixes: +- issue 10: Incorrect encoding of packed fields when serialized + +=============================================================================== +RELEASE NOTES - Version 0.9.0 +=============================================================================== + +- Initial release + +=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/app.config b/src/core/Akka.Remote.Tests/app.config index 3d69e0c8bdc..012b4e29c9d 100644 --- a/src/core/Akka.Remote.Tests/app.config +++ b/src/core/Akka.Remote.Tests/app.config @@ -65,15 +65,15 @@ - + - + - + @@ -101,15 +101,15 @@ - + - + - + @@ -127,5 +127,25 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/licenses/license.txt b/src/core/Akka.Remote.Tests/licenses/license.txt new file mode 100644 index 00000000000..b8e773b2e05 --- /dev/null +++ b/src/core/Akka.Remote.Tests/licenses/license.txt @@ -0,0 +1,31 @@ +Protocol Buffers - Google's data interchange format +Copyright 2008-2010 Google Inc. All rights reserved. +http://github.com/jskeet/dotnet-protobufs/ +Original C++/Java/Python code: +http://code.google.com/p/protobuf/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Remote.Tests/licenses/protoc-license.txt b/src/core/Akka.Remote.Tests/licenses/protoc-license.txt new file mode 100644 index 00000000000..c779cb0e1ed --- /dev/null +++ b/src/core/Akka.Remote.Tests/licenses/protoc-license.txt @@ -0,0 +1,36 @@ +protoc.exe was built from the original source at http://code.google.com/p/protobuf/ +The licence for this code is as follows: + +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Remote.Tests/protos/google/protobuf/csharp_options.proto new file mode 100644 index 00000000000..152df766f03 --- /dev/null +++ b/src/core/Akka.Remote.Tests/protos/google/protobuf/csharp_options.proto @@ -0,0 +1,115 @@ +// Extra options for C# generator + +import "google/protobuf/descriptor.proto"; + +package google.protobuf; + +message CSharpFileOptions { + + // Namespace for generated classes; defaults to the package. + optional string namespace = 1; + + // Name of the "umbrella" class used for metadata about all + // the messages within this file. Default is based on the name + // of the file. + optional string umbrella_classname = 2; + + // Whether classes should be public (true) or internal (false) + optional bool public_classes = 3 [default = true]; + + // Whether to generate a single file for everything within the + // .proto file (false), or one file per message (true). + // This option is not currently honored; please log a feature + // request if you really want it. + optional bool multiple_files = 4; + + // Whether to nest messages within a single umbrella class (true) + // or create the umbrella class as a peer, with messages as + // top-level classes in the namespace (false) + optional bool nest_classes = 5; + + // Generate appropriate support for Code Contracts + // (Ongoing; support should improve over time) + optional bool code_contracts = 6; + + // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" + // would generate files within [output directory]/Foo/Bar + optional bool expand_namespace_directories = 7; + + // Generate attributes indicating non-CLS-compliance + optional bool cls_compliance = 8 [default = true]; + + // Generate messages/builders with the [Serializable] attribute + optional bool add_serializable = 9 [default = false]; + + // Generates a private ctor for Message types + optional bool generate_private_ctor = 10 [default = true]; + + // The extension that should be appended to the umbrella_classname when creating files. + optional string file_extension = 221 [default = ".cs"]; + + // A nested namespace for the umbrella class. Helpful for name collisions caused by + // umbrella_classname conflicting with an existing type. This will be automatically + // set to 'Proto' if a collision is detected with types being generated. This value + // is ignored when nest_classes == true + optional string umbrella_namespace = 222; + + // The output path for the source file(s) generated + optional string output_directory = 223 [default = "."]; + + // Will ignore the type generations and remove dependencies for the descriptor proto + // files that declare their package to be "google.protobuf" + optional bool ignore_google_protobuf = 224 [default = false]; + + // Controls how services are generated, GENERIC is the deprecated original implementation + // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and + // implementations using the included Windows RPC interop libarary. + optional CSharpServiceType service_generator_type = 225 [default = NONE]; + + // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and + // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. + optional bool generated_code_attributes = 226 [default = false]; +} + +enum CSharpServiceType { + // Services are ignored by the generator + NONE = 0; + // Generates the original Java generic service implementations + GENERIC = 1; + // Generates an interface for the service and nothing else + INTERFACE = 2; + // Generates an interface for the service and client/server wrappers for the interface + IRPCDISPATCH = 3; +} + +extend FileOptions { + optional CSharpFileOptions csharp_file_options = 1000; +} + +extend FieldOptions { + optional CSharpFieldOptions csharp_field_options = 1000; +} + +message CSharpFieldOptions { + // Provides the ability to override the name of the property + // generated for this field. This is applied to all properties + // and methods to do with this field, including HasFoo, FooCount, + // FooList etc. + optional string property_name = 1; +} + +message CSharpServiceOptions { + optional string interface_id = 1; +} + +extend ServiceOptions { + optional CSharpServiceOptions csharp_service_options = 1000; +} + +message CSharpMethodOptions { + optional int32 dispatch_id = 1; +} + +extend MethodOptions { + optional CSharpMethodOptions csharp_method_options = 1000; +} \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/protos/google/protobuf/descriptor.proto b/src/core/Akka.Remote.Tests/protos/google/protobuf/descriptor.proto new file mode 100644 index 00000000000..233f879410e --- /dev/null +++ b/src/core/Akka.Remote.Tests/protos/google/protobuf/descriptor.proto @@ -0,0 +1,533 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + + +package google.protobuf; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + optional MessageOptions options = 7; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4; + TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + optional FieldOptions options = 8; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; +} + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail kenton@google.com to reserve extension +// numbers. Simply tell me how many you need and I'll send you back a +// set of numbers to use -- there's no need to explain how you intend to +// use them. If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. This is + // purely a speed optimization, as the AbstractMessage base class includes + // reflection-based implementations of these methods. + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of proto2. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. + optional bool packed = 2; + + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // EXPERIMENTAL. DO NOT USE. + // For "map" fields, the name of the field in the enclosed type that + // is the key for this map. For example, suppose we have: + // message Item { + // required string name = 1; + // required string value = 2; + // } + // message Config { + // repeated Item items = 1 [experimental_map_key="name"]; + // } + // In this situation, the map key for Item will be set to "name". + // TODO: Fully-implement this, then remove the "experimental_" prefix. + optional string experimental_map_key = 9; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // TODO(kenton): Record comments appearing before and after the + // declaration. + } +} diff --git a/src/core/Akka.Remote.Tests/protos/tutorial/addressbook.proto b/src/core/Akka.Remote.Tests/protos/tutorial/addressbook.proto new file mode 100644 index 00000000000..5abe35ce39b --- /dev/null +++ b/src/core/Akka.Remote.Tests/protos/tutorial/addressbook.proto @@ -0,0 +1,31 @@ +package tutorial; + +import "google/protobuf/csharp_options.proto"; +option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; +option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; + +option optimize_for = SPEED; + +message Person { + required string name = 1; + required int32 id = 2; // Unique ID number for this person. + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person person = 1; +} diff --git a/src/core/Akka.Remote/Akka.Remote.csproj b/src/core/Akka.Remote/Akka.Remote.csproj index 085849c5851..e0e44254cee 100644 --- a/src/core/Akka.Remote/Akka.Remote.csproj +++ b/src/core/Akka.Remote/Akka.Remote.csproj @@ -50,6 +50,24 @@ false + + True + + + True + + + True + + + True + + + True + + + True + @@ -123,35 +141,7 @@ --> - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net35\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net20\Google.ProtocolBuffers.dll - True - True - - - - + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll @@ -193,7 +183,7 @@ - + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll diff --git a/src/core/Akka.Remote/CHANGES.txt b/src/core/Akka.Remote/CHANGES.txt new file mode 100644 index 00000000000..d80368c78f2 --- /dev/null +++ b/src/core/Akka.Remote/CHANGES.txt @@ -0,0 +1,99 @@ +=============================================================================== +Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet +(skeet@pobox.com) based on the work of many talented people. + +For more information about this port, visit its homepage: +http://protobuf-csharp-port.googlecode.com + +For more information about Protocol Buffers in general, visit the project page +for the C++, Java and Python project: +http://protobuf.googlecode.com +=============================================================================== +RELEASE NOTES - Version 2.4.1.473 +=============================================================================== + +Features: +- Added option service_generator_type to control service generation with + NONE, GENERIC, INTERFACE, or IRPCDISPATCH +- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking + services and implementations. +- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the + location of protoc.exe. +- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow + custom implementation of writers with both speed and size optimizations. +- Addition of the "Google.ProtoBuffers.Serialization" assembly to support + reading and writing messages to/from XML, JSON, IDictionary<,> and others. +- Several performance related fixes and tweeks +- Issue 3: Add option to mark generated code with attribute +- Issue 20: Support for decorating classes [Serializable] +- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] +- Issue 22: Reusable Builder classes +- Issue 24: Support for using Json/Xml formats with ICodedInputStream +- Issue 25: Added support for NuGet packages +- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 + +Fixes: +- Issue 13: Message with Field same name as message causes uncompilable .cs +- Issue 16: Does not integrate well with other tooling +- Issue 19: Support for negative enum values +- Issue 26: AddRange in GeneratedBuilder iterates twice. +- Issue 27: Remove XML documentation output from test projects to clear + warnings/errors. +- Issue 28: Circular message dependencies result in null default values for + Message fields. +- Issue 29: Message classes generated have a public default constructor. You + can disable private ctor generation with the option generate_private_ctor. +- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ +- Big-endian support for float, and double on Silverlight +- Packed and Unpacked parsing allow for all repeated, as per version 2.3 +- Fix for leaving Builder a public ctor on internal classes for use with + generic "where T: new()" constraints. + +Other: +- Changed the code signing key to a privately held key +- Reformatted all code and line-endings to C# defaults +- Reworking of performance benchmarks to produce reliable results, option /v2 +- Issue 34: Silverlight assemblies are now unit tested + +=============================================================================== +RELEASE NOTES - Version 2.3.0.277 +=============================================================================== + +Features: +- Added cls_compliance option to generate attributes indicating + non-CLS-compliance. +- Added file_extension option to control the generated output file's extension. +- Added umbrella_namespace option to place the umbrella class into a nested + namespace to address issues with proto files having the same name as a + message it contains. +- Added output_directory option to set the output path for the source file(s). +- Added ignore_google_protobuf option to avoid generating code for includes + from the google.protobuf package. +- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to + generate code with "option optimize_for = LITE_RUNTIME;". +- Added ability to invoke protoc.exe from within ProtoGen.exe. +- Upgraded to protoc.exe (2.3) compiler. + +Fixes: +- Issue 9: Class cannot be static and sealed error +- Issue 12: default value for enumerate fields must be filled out + +Other: +- Rewrite of build using MSBbuild instead of NAnt +- Moved to NUnit Version 2.2.8.0 +- Changed to using secure .snk for releases + +=============================================================================== +RELEASE NOTES - Version 0.9.1 +=============================================================================== + +Fixes: +- issue 10: Incorrect encoding of packed fields when serialized + +=============================================================================== +RELEASE NOTES - Version 0.9.0 +=============================================================================== + +- Initial release + +=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Remote/app.config b/src/core/Akka.Remote/app.config index 2a9455b55bf..3db760888d4 100644 --- a/src/core/Akka.Remote/app.config +++ b/src/core/Akka.Remote/app.config @@ -65,15 +65,15 @@ - + - + - + @@ -101,15 +101,15 @@ - + - + - + @@ -121,15 +121,15 @@ - + - + - + @@ -147,5 +147,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote/licenses/license.txt b/src/core/Akka.Remote/licenses/license.txt new file mode 100644 index 00000000000..b8e773b2e05 --- /dev/null +++ b/src/core/Akka.Remote/licenses/license.txt @@ -0,0 +1,31 @@ +Protocol Buffers - Google's data interchange format +Copyright 2008-2010 Google Inc. All rights reserved. +http://github.com/jskeet/dotnet-protobufs/ +Original C++/Java/Python code: +http://code.google.com/p/protobuf/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Remote/licenses/protoc-license.txt b/src/core/Akka.Remote/licenses/protoc-license.txt new file mode 100644 index 00000000000..c779cb0e1ed --- /dev/null +++ b/src/core/Akka.Remote/licenses/protoc-license.txt @@ -0,0 +1,36 @@ +protoc.exe was built from the original source at http://code.google.com/p/protobuf/ +The licence for this code is as follows: + +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Remote/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Remote/protos/google/protobuf/csharp_options.proto new file mode 100644 index 00000000000..152df766f03 --- /dev/null +++ b/src/core/Akka.Remote/protos/google/protobuf/csharp_options.proto @@ -0,0 +1,115 @@ +// Extra options for C# generator + +import "google/protobuf/descriptor.proto"; + +package google.protobuf; + +message CSharpFileOptions { + + // Namespace for generated classes; defaults to the package. + optional string namespace = 1; + + // Name of the "umbrella" class used for metadata about all + // the messages within this file. Default is based on the name + // of the file. + optional string umbrella_classname = 2; + + // Whether classes should be public (true) or internal (false) + optional bool public_classes = 3 [default = true]; + + // Whether to generate a single file for everything within the + // .proto file (false), or one file per message (true). + // This option is not currently honored; please log a feature + // request if you really want it. + optional bool multiple_files = 4; + + // Whether to nest messages within a single umbrella class (true) + // or create the umbrella class as a peer, with messages as + // top-level classes in the namespace (false) + optional bool nest_classes = 5; + + // Generate appropriate support for Code Contracts + // (Ongoing; support should improve over time) + optional bool code_contracts = 6; + + // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" + // would generate files within [output directory]/Foo/Bar + optional bool expand_namespace_directories = 7; + + // Generate attributes indicating non-CLS-compliance + optional bool cls_compliance = 8 [default = true]; + + // Generate messages/builders with the [Serializable] attribute + optional bool add_serializable = 9 [default = false]; + + // Generates a private ctor for Message types + optional bool generate_private_ctor = 10 [default = true]; + + // The extension that should be appended to the umbrella_classname when creating files. + optional string file_extension = 221 [default = ".cs"]; + + // A nested namespace for the umbrella class. Helpful for name collisions caused by + // umbrella_classname conflicting with an existing type. This will be automatically + // set to 'Proto' if a collision is detected with types being generated. This value + // is ignored when nest_classes == true + optional string umbrella_namespace = 222; + + // The output path for the source file(s) generated + optional string output_directory = 223 [default = "."]; + + // Will ignore the type generations and remove dependencies for the descriptor proto + // files that declare their package to be "google.protobuf" + optional bool ignore_google_protobuf = 224 [default = false]; + + // Controls how services are generated, GENERIC is the deprecated original implementation + // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and + // implementations using the included Windows RPC interop libarary. + optional CSharpServiceType service_generator_type = 225 [default = NONE]; + + // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and + // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. + optional bool generated_code_attributes = 226 [default = false]; +} + +enum CSharpServiceType { + // Services are ignored by the generator + NONE = 0; + // Generates the original Java generic service implementations + GENERIC = 1; + // Generates an interface for the service and nothing else + INTERFACE = 2; + // Generates an interface for the service and client/server wrappers for the interface + IRPCDISPATCH = 3; +} + +extend FileOptions { + optional CSharpFileOptions csharp_file_options = 1000; +} + +extend FieldOptions { + optional CSharpFieldOptions csharp_field_options = 1000; +} + +message CSharpFieldOptions { + // Provides the ability to override the name of the property + // generated for this field. This is applied to all properties + // and methods to do with this field, including HasFoo, FooCount, + // FooList etc. + optional string property_name = 1; +} + +message CSharpServiceOptions { + optional string interface_id = 1; +} + +extend ServiceOptions { + optional CSharpServiceOptions csharp_service_options = 1000; +} + +message CSharpMethodOptions { + optional int32 dispatch_id = 1; +} + +extend MethodOptions { + optional CSharpMethodOptions csharp_method_options = 1000; +} \ No newline at end of file diff --git a/src/core/Akka.Remote/protos/google/protobuf/descriptor.proto b/src/core/Akka.Remote/protos/google/protobuf/descriptor.proto new file mode 100644 index 00000000000..233f879410e --- /dev/null +++ b/src/core/Akka.Remote/protos/google/protobuf/descriptor.proto @@ -0,0 +1,533 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + + +package google.protobuf; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + optional MessageOptions options = 7; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4; + TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + optional FieldOptions options = 8; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; +} + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail kenton@google.com to reserve extension +// numbers. Simply tell me how many you need and I'll send you back a +// set of numbers to use -- there's no need to explain how you intend to +// use them. If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. This is + // purely a speed optimization, as the AbstractMessage base class includes + // reflection-based implementations of these methods. + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of proto2. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. + optional bool packed = 2; + + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // EXPERIMENTAL. DO NOT USE. + // For "map" fields, the name of the field in the enclosed type that + // is the key for this map. For example, suppose we have: + // message Item { + // required string name = 1; + // required string value = 2; + // } + // message Config { + // repeated Item items = 1 [experimental_map_key="name"]; + // } + // In this situation, the map key for Item will be set to "name". + // TODO: Fully-implement this, then remove the "experimental_" prefix. + optional string experimental_map_key = 9; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // TODO(kenton): Record comments appearing before and after the + // declaration. + } +} diff --git a/src/core/Akka.Remote/protos/tutorial/addressbook.proto b/src/core/Akka.Remote/protos/tutorial/addressbook.proto new file mode 100644 index 00000000000..5abe35ce39b --- /dev/null +++ b/src/core/Akka.Remote/protos/tutorial/addressbook.proto @@ -0,0 +1,31 @@ +package tutorial; + +import "google/protobuf/csharp_options.proto"; +option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; +option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; + +option optimize_for = SPEED; + +message Person { + required string name = 1; + required int32 id = 2; // Unique ID number for this person. + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} + +// Our address book file is just one of these. +message AddressBook { + repeated Person person = 1; +} diff --git a/src/core/Akka.Tests/App.config b/src/core/Akka.Tests/App.config index f7a16eaadc0..84d31f6d694 100644 --- a/src/core/Akka.Tests/App.config +++ b/src/core/Akka.Tests/App.config @@ -83,15 +83,15 @@ - + - + - + @@ -123,15 +123,15 @@ - + - + - + @@ -141,4 +141,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka/Akka.csproj b/src/core/Akka/Akka.csproj index 3ea0fc35fe9..052e93c0ae5 100644 --- a/src/core/Akka/Akka.csproj +++ b/src/core/Akka/Akka.csproj @@ -441,11 +441,15 @@ - - - ..\..\..\packages\Wire\lib\Wire.dll - True - True - - + + + + + ..\..\..\packages\Wire\lib\Wire.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka/packages.config b/src/core/Akka/packages.config deleted file mode 100644 index 61d501c37a0..00000000000 --- a/src/core/Akka/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/examples/Chat/ChatClient/App.config b/src/examples/Chat/ChatClient/App.config index 48ac5d9fffc..2c2edeeba16 100644 --- a/src/examples/Chat/ChatClient/App.config +++ b/src/examples/Chat/ChatClient/App.config @@ -69,15 +69,15 @@ - + - + - + @@ -105,15 +105,15 @@ - + - + - + @@ -125,15 +125,15 @@ - + - + - + @@ -151,5 +151,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/Chat/ChatServer/App.config b/src/examples/Chat/ChatServer/App.config index 48ac5d9fffc..2c2edeeba16 100644 --- a/src/examples/Chat/ChatServer/App.config +++ b/src/examples/Chat/ChatServer/App.config @@ -69,15 +69,15 @@ - + - + - + @@ -105,15 +105,15 @@ - + - + - + @@ -125,15 +125,15 @@ - + - + - + @@ -151,5 +151,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config index 90b07230013..61fb7b251d8 100644 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config @@ -92,15 +92,15 @@ - + - + - + @@ -132,15 +132,15 @@ - + - + - + @@ -152,15 +152,15 @@ - + - + - + @@ -178,4 +178,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config index de502654b95..193c2a22e74 100644 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config @@ -93,15 +93,15 @@ - + - + - + @@ -133,15 +133,15 @@ - + - + - + @@ -153,15 +153,15 @@ - + - + - + @@ -179,4 +179,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Samples.Cluster.Simple/App.config b/src/examples/Cluster/Samples.Cluster.Simple/App.config index 65b7892db67..72f33902f02 100644 --- a/src/examples/Cluster/Samples.Cluster.Simple/App.config +++ b/src/examples/Cluster/Samples.Cluster.Simple/App.config @@ -92,15 +92,15 @@ - + - + - + @@ -132,15 +132,15 @@ - + - + - + @@ -152,15 +152,15 @@ - + - + - + @@ -178,4 +178,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/FSharp.Api/App.config b/src/examples/FSharp.Api/App.config index f024efe74fc..2e989121800 100644 --- a/src/examples/FSharp.Api/App.config +++ b/src/examples/FSharp.Api/App.config @@ -64,15 +64,15 @@ - + - + - + @@ -104,15 +104,15 @@ - + - + - + @@ -124,15 +124,15 @@ - + - + - + @@ -150,5 +150,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/FSharp.Api/FSharp.Api.fsproj b/src/examples/FSharp.Api/FSharp.Api.fsproj index 28bbf3a3746..2a92d343bf9 100644 --- a/src/examples/FSharp.Api/FSharp.Api.fsproj +++ b/src/examples/FSharp.Api/FSharp.Api.fsproj @@ -165,11 +165,15 @@ - - - ..\..\..\packages\Wire\lib\Wire.dll - True - True - - + + + + + ..\..\..\packages\Wire\lib\Wire.dll + True + True + + + + \ No newline at end of file diff --git a/src/examples/FSharp.Deploy.Local/App.config b/src/examples/FSharp.Deploy.Local/App.config index f024efe74fc..2e989121800 100644 --- a/src/examples/FSharp.Deploy.Local/App.config +++ b/src/examples/FSharp.Deploy.Local/App.config @@ -64,15 +64,15 @@ - + - + - + @@ -104,15 +104,15 @@ - + - + - + @@ -124,15 +124,15 @@ - + - + - + @@ -150,5 +150,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/FSharp.Deploy.Remote/App.config b/src/examples/FSharp.Deploy.Remote/App.config index f024efe74fc..2e989121800 100644 --- a/src/examples/FSharp.Deploy.Remote/App.config +++ b/src/examples/FSharp.Deploy.Remote/App.config @@ -64,15 +64,15 @@ - + - + - + @@ -104,15 +104,15 @@ - + - + - + @@ -124,15 +124,15 @@ - + - + - + @@ -150,5 +150,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/FaultTolerance/App.config b/src/examples/FaultTolerance/App.config index 2de963ff0c0..e28ac54bd91 100644 --- a/src/examples/FaultTolerance/App.config +++ b/src/examples/FaultTolerance/App.config @@ -62,15 +62,15 @@ - + - + - + @@ -102,15 +102,15 @@ - + - + - + @@ -122,15 +122,15 @@ - + - + - + @@ -148,4 +148,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/HelloWorld/FSharp.HelloAkka/App.config b/src/examples/HelloWorld/FSharp.HelloAkka/App.config index f024efe74fc..2e989121800 100644 --- a/src/examples/HelloWorld/FSharp.HelloAkka/App.config +++ b/src/examples/HelloWorld/FSharp.HelloAkka/App.config @@ -64,15 +64,15 @@ - + - + - + @@ -104,15 +104,15 @@ - + - + - + @@ -124,15 +124,15 @@ - + - + - + @@ -150,5 +150,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/HelloWorld/HelloAkka/App.config b/src/examples/HelloWorld/HelloAkka/App.config index 2de963ff0c0..e28ac54bd91 100644 --- a/src/examples/HelloWorld/HelloAkka/App.config +++ b/src/examples/HelloWorld/HelloAkka/App.config @@ -62,15 +62,15 @@ - + - + - + @@ -102,15 +102,15 @@ - + - + - + @@ -122,15 +122,15 @@ - + - + - + @@ -148,4 +148,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/PersistenceExample.FsApi/App.config b/src/examples/PersistenceExample.FsApi/App.config index f024efe74fc..2e989121800 100644 --- a/src/examples/PersistenceExample.FsApi/App.config +++ b/src/examples/PersistenceExample.FsApi/App.config @@ -64,15 +64,15 @@ - + - + - + @@ -104,15 +104,15 @@ - + - + - + @@ -124,15 +124,15 @@ - + - + - + @@ -150,5 +150,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/PersistenceExample/App.config b/src/examples/PersistenceExample/App.config index 2de963ff0c0..e28ac54bd91 100644 --- a/src/examples/PersistenceExample/App.config +++ b/src/examples/PersistenceExample/App.config @@ -62,15 +62,15 @@ - + - + - + @@ -102,15 +102,15 @@ - + - + - + @@ -122,15 +122,15 @@ - + - + - + @@ -148,4 +148,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/RemoteDeploy/System1/App.config b/src/examples/RemoteDeploy/System1/App.config index 375214d25ca..8961a671524 100644 --- a/src/examples/RemoteDeploy/System1/App.config +++ b/src/examples/RemoteDeploy/System1/App.config @@ -68,15 +68,15 @@ - + - + - + @@ -104,15 +104,15 @@ - + - + - + @@ -124,15 +124,15 @@ - + - + - + @@ -150,5 +150,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/RemoteDeploy/System2/App.config b/src/examples/RemoteDeploy/System2/App.config index 375214d25ca..8961a671524 100644 --- a/src/examples/RemoteDeploy/System2/App.config +++ b/src/examples/RemoteDeploy/System2/App.config @@ -68,15 +68,15 @@ - + - + - + @@ -104,15 +104,15 @@ - + - + - + @@ -124,15 +124,15 @@ - + - + - + @@ -150,5 +150,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/Routing/App.config b/src/examples/Routing/App.config index 2de963ff0c0..e28ac54bd91 100644 --- a/src/examples/Routing/App.config +++ b/src/examples/Routing/App.config @@ -62,15 +62,15 @@ - + - + - + @@ -102,15 +102,15 @@ - + - + - + @@ -122,15 +122,15 @@ - + - + - + @@ -148,4 +148,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/Stocks/SymbolLookup/App.config b/src/examples/Stocks/SymbolLookup/App.config index 2de963ff0c0..e28ac54bd91 100644 --- a/src/examples/Stocks/SymbolLookup/App.config +++ b/src/examples/Stocks/SymbolLookup/App.config @@ -62,15 +62,15 @@ - + - + - + @@ -102,15 +102,15 @@ - + - + - + @@ -122,15 +122,15 @@ - + - + - + @@ -148,4 +148,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/TcpEchoService.Server/App.config b/src/examples/TcpEchoService.Server/App.config index 2de963ff0c0..e28ac54bd91 100644 --- a/src/examples/TcpEchoService.Server/App.config +++ b/src/examples/TcpEchoService.Server/App.config @@ -62,15 +62,15 @@ - + - + - + @@ -102,15 +102,15 @@ - + - + - + @@ -122,15 +122,15 @@ - + - + - + @@ -148,4 +148,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeClient/App.config b/src/examples/TimeServer/TimeClient/App.config index 0c7096bc3a8..ebd328d8d80 100644 --- a/src/examples/TimeServer/TimeClient/App.config +++ b/src/examples/TimeServer/TimeClient/App.config @@ -111,15 +111,15 @@ - + - + - + @@ -151,15 +151,15 @@ - + - + - + @@ -171,15 +171,15 @@ - + - + - + @@ -197,4 +197,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeServer/App.config b/src/examples/TimeServer/TimeServer/App.config index ed4a4974b8b..36b9693ef4f 100644 --- a/src/examples/TimeServer/TimeServer/App.config +++ b/src/examples/TimeServer/TimeServer/App.config @@ -111,15 +111,15 @@ - + - + - + @@ -151,15 +151,15 @@ - + - + - + @@ -171,15 +171,15 @@ - + - + - + @@ -197,4 +197,12 @@ + + + + + + + + \ No newline at end of file From da8e20fd2c97890aecc4dbcf470cbcb3f688934d Mon Sep 17 00:00:00 2001 From: Uladzimir Makarau Date: Sun, 25 Oct 2015 09:28:02 +0100 Subject: [PATCH 064/105] Publish not sent remote messages to DeadLetters (fix for #1390) - EndpointWriter now publishes actual messages instead of LinkedListNodes to DeadLetters - RemoteDeadLetterActorRef now handles submitted dead letters --- src/core/Akka.Remote/Endpoint.cs | 15 ++++--- .../Akka.Remote/RemoteActorRefProvider.cs | 41 +++++++++++-------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/core/Akka.Remote/Endpoint.cs b/src/core/Akka.Remote/Endpoint.cs index 345de5743de..ebc167ad28f 100644 --- a/src/core/Akka.Remote/Endpoint.cs +++ b/src/core/Akka.Remote/Endpoint.cs @@ -878,16 +878,19 @@ protected override void PreStart() protected override void PostStop() { _ackIdleTimerCancelable.CancelIfNotNull(); - while (_prioBuffer.Any()) + + foreach (var msg in _prioBuffer) { - _system.DeadLetters.Tell(_prioBuffer.First); - _prioBuffer.RemoveFirst(); + _system.DeadLetters.Tell(msg); } - while (_buffer.Any()) + _prioBuffer.Clear(); + + foreach (var msg in _buffer) { - _system.DeadLetters.Tell(_buffer.First); - _buffer.RemoveFirst(); + _system.DeadLetters.Tell(msg); } + _buffer.Clear(); + if (_handle != null) _handle.Disassociate(_stopReason); EventPublisher.NotifyListeners(new DisassociatedEvent(LocalAddress, RemoteAddress, Inbound)); } diff --git a/src/core/Akka.Remote/RemoteActorRefProvider.cs b/src/core/Akka.Remote/RemoteActorRefProvider.cs index b2f099efb2b..dd38470541a 100644 --- a/src/core/Akka.Remote/RemoteActorRefProvider.cs +++ b/src/core/Akka.Remote/RemoteActorRefProvider.cs @@ -529,23 +529,30 @@ public RemoteDeadLetterActorRef(IActorRefProvider provider, ActorPath actorPath, protected override void TellInternal(object message, IActorRef sender) { - var send = message as EndpointManager.Send; - if (send != null) - { - // else ignore: it is a reliably delivered message that might be retried later, and it has not yet deserved - // the dead letter status - //TODO: Seems to have started causing endless cycle of messages (and stack overflow) - //if (send.Seq == null) Tell(message, sender); - return; - } - var deadLetter = message as DeadLetter; - if (deadLetter != null) - { - // else ignore: it is a reliably delivered message that might be retried later, and it has not yet deserved - // the dead letter status - //TODO: if(deadLetter.Message) - } - + message + .Match() + .With( + send => + { + // else ignore: it is a reliably delivered message that might be retried later, and it has not yet deserved + // the dead letter status + if (send.Seq == null) + { + base.TellInternal(send.Message, send.SenderOption ?? ActorRefs.NoSender); + } + }) + .With( + deadLetter => + { + // else ignore: it is a reliably delivered message that might be retried later, and it has not yet deserved + // the dead letter status + var deadSend = deadLetter.Message as EndpointManager.Send; + if (deadSend != null && deadSend.Seq == null) + { + base.TellInternal(deadSend.Message, deadSend.SenderOption ?? ActorRefs.NoSender); + } + }) + .Default(_ => base.TellInternal(message, sender)); } } } From cdde2e89f3c0d3daa3531b5ca84271cc845c08ad Mon Sep 17 00:00:00 2001 From: Artem Borzilov Date: Thu, 29 Oct 2015 01:53:31 +0300 Subject: [PATCH 065/105] Fix incorrect Exception cast in SelectionHandlerSupervisorStrategy --- src/core/Akka/IO/SelectionHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Akka/IO/SelectionHandler.cs b/src/core/Akka/IO/SelectionHandler.cs index b3753d3f39e..eb4aa8d58cd 100644 --- a/src/core/Akka/IO/SelectionHandler.cs +++ b/src/core/Akka/IO/SelectionHandler.cs @@ -353,7 +353,7 @@ protected override void LogFailure(IActorContext context, IActorRef child, Excep { try { - var e = (ActorInitializationException) cause; + var e = cause as ActorInitializationException; var logMessage = e != null ? e.GetBaseException() .Message : cause.Message; From d259edeb572352cb755f3ce6ebe7857a7acbda3f Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Fri, 30 Oct 2015 09:39:03 +0400 Subject: [PATCH 066/105] added raw implementation with failed tests --- .../Akka.Persistence.Tests.csproj | 1 + .../Fsm/PersistentFSMSpec.cs | 430 +++++++++++ .../Akka.Persistence/Akka.Persistence.csproj | 2 + .../Akka.Persistence/Fsm/PersistentFSM.cs | 682 ++++++++++++++++++ .../Akka.Persistence/Fsm/PersistentFSMBase.cs | 215 ++++++ src/core/Akka/Actor/FSM.cs | 2 +- 6 files changed, 1331 insertions(+), 1 deletion(-) create mode 100644 src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs create mode 100644 src/core/Akka.Persistence/Fsm/PersistentFSM.cs create mode 100644 src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs diff --git a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj index 43510797058..4cc81ded709 100644 --- a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj +++ b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj @@ -44,6 +44,7 @@ + diff --git a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs new file mode 100644 index 00000000000..34d92827634 --- /dev/null +++ b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs @@ -0,0 +1,430 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Akka.Actor; +using Akka.Dispatch.SysMsg; +using Akka.Persistence.Fsm; +using Akka.TestKit; +using Akka.Util; +using Xunit; + +namespace Akka.Persistence.Tests.Fsm +{ + public partial class PersistentFSMSpec : PersistenceSpec + { + private readonly Random _random = new Random(); + public PersistentFSMSpec() + : base(PersistenceSpec.Configuration("inmem", "PersistentFSMSpec")) + { + } + + [Fact] + public void PersistentFSM_should_has_function_as_regular_fsm() + { + var dummyReportActorRef = CreateTestProbe().Ref; + + var fsmRef = Sys.ActorOf(Props.Create(Name, dummyReportActorRef), Name); + + Watch(fsmRef); + fsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); + + var shirt = new Item("1", "Shirt", 59.99F); + var shoes = new Item("2", "Shoes", 89.99F); + var coat = new Item("3", "Coat", 119.99F); + + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new AddItem(shirt)); + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new AddItem(shoes)); + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new AddItem(coat)); + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new Buy()); + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new Leave()); + ExpectMsg>(state => state.State == UserState.LookingAround); + ExpectMsg(); + ExpectMsg>(state => state.From == UserState.LookingAround); + ExpectMsg(); + ExpectMsg(); + ExpectMsg(); + ExpectMsg>(); + ExpectMsg(); + ExpectTerminated(fsmRef); + } + + [Fact] + public void PersistentFSM_should_has_function_as_regular_fsm_on_state_timeout() + { + var dummyReportActorRef = CreateTestProbe().Ref; + + var fsmRef = Sys.ActorOf(Props.Create(Name, dummyReportActorRef), Name); + + Watch(fsmRef); + + fsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); + + var shirt = new Item("1", "Shirt", 59.99F); + + fsmRef.Tell(new AddItem(shirt)); + ExpectMsg>(state => + { + return state.State == UserState.LookingAround; + + }); + + ExpectMsg>(); + + Within(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1.9), () => + { + ExpectMsg>(); + return true; + }); + + ExpectTerminated(fsmRef); + } + + [Fact] + public void PersistentFSM_should_recover_successfully_with_correct_state_data() + { + var dummyReportActorRef = CreateTestProbe().Ref; + + var fsmRef = Sys.ActorOf(Props.Create(()=> new WebStoreCustomerFSM(Name, dummyReportActorRef))); + + Watch(fsmRef); + fsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); + + var shirt = new Item("1", "Shirt", 59.99F); + var shoes = new Item("2", "Shoes", 89.99F); + var coat = new Item("3", "Coat", 119.99F); + + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new AddItem(shirt)); + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new AddItem(shoes)); + fsmRef.Tell(new GetCurrentCart()); + + + //fsmRef.Tell(new AddItem(coat)); + //fsmRef.Tell(new GetCurrentCart()); + //fsmRef.Tell(new Buy()); + //fsmRef.Tell(new GetCurrentCart()); + //fsmRef.Tell(new Leave()); + + + ExpectMsg>(); + ExpectMsg(); + ExpectMsg>(state => + { + return state.From == UserState.LookingAround; + + }); + ExpectMsg(); + ExpectMsg(); + + fsmRef.Tell(PoisonPill.Instance); + ExpectTerminated(fsmRef); + + var recoveredFsmRef = Sys.ActorOf(Props.Create(() => new WebStoreCustomerFSM(Name, dummyReportActorRef))); + Watch(recoveredFsmRef); + recoveredFsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); + + recoveredFsmRef.Tell(new GetCurrentCart()); + recoveredFsmRef.Tell(new AddItem(coat)); + recoveredFsmRef.Tell(new GetCurrentCart()); + recoveredFsmRef.Tell(new Buy()); + recoveredFsmRef.Tell(new GetCurrentCart()); + recoveredFsmRef.Tell(new Leave()); + + ExpectMsg>(state => + { + return state.State == UserState.Shopping; + + }); + ExpectMsg(); + ExpectMsg(); + ExpectMsg>(); + ExpectMsg(); + ExpectTerminated(recoveredFsmRef); + } + + internal class WebStoreCustomerFSM : PersistentFSM + { + private readonly string _persistenceId; + private readonly IActorRef _reportActor; + + public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) + { + _persistenceId = persistenceId; + _reportActor = reportActor; + StartWith(UserState.LookingAround, new EmptyShoppingCart()); + + When(UserState.LookingAround, (@event,state) => + { + if (@event.FsmEvent is AddItem) + { + var addItem = (AddItem) @event.FsmEvent; + return + GoTo(UserState.Shopping) + .Applying(new ItemAdded(addItem.Item)).ForMax(TimeSpan.FromSeconds(1)); + } + if (@event.FsmEvent is GetCurrentCart) + { + return Stay().Replying(@event.StateData); + } + return state; + }); + + + When(UserState.Shopping, (@event, state) => + { + if (@event.FsmEvent is AddItem) + { + var addItem = ((AddItem) @event.FsmEvent); + return Stay().Applying(new ItemAdded(addItem.Item)).ForMax(TimeSpan.FromSeconds(1)); + } + if (@event.FsmEvent is Buy) + { + return + GoTo(UserState.Paid) + .Applying(new OrderExecuted()) + .AndThen(cart => + { + if (cart is NonEmptyShoppingCart) + { + _reportActor.Tell(new PurchaseWasMade()); + } + }); + } + if (@event.FsmEvent is Leave) + { + return Stop().Applying(new OrderDiscarded()).AndThen(cart => + { + _reportActor.Tell(new ShoppingCardDiscarded()); + }); + } + if (@event.FsmEvent is GetCurrentCart) + { + return Stay().Replying(@event.StateData); + } + if (@event.FsmEvent is StateTimeout) + { + return GoTo(UserState.Inactive).ForMax(TimeSpan.FromSeconds(2)); + } + return state; + }); + + + When(UserState.Inactive, (@event, state) => + { + if (@event.FsmEvent is AddItem) + { + var addItem = (AddItem) @event.FsmEvent; + return + GoTo(UserState.Shopping) + .Applying(new ItemAdded(addItem.Item)) + .ForMax(TimeSpan.FromSeconds(1)); + } + if (@event.FsmEvent is StateTimeout) + { + //var addItem = ((AddItem)@event) + return Stop().Applying(new OrderDiscarded()).AndThen(cart => + { + _reportActor.Tell(new ShoppingCardDiscarded()); + }); + } + return state; + }); + + When(UserState.Paid, (@event, state) => + { + if (@event.FsmEvent is Leave) + { + return Stop(); + } + if (@event.FsmEvent is GetCurrentCart) + { + return Stay().Replying(@event.StateData); + } + return state; + }); + } + + public override string PersistenceId { get { return _persistenceId; }} + + + + //protected override IShoppingCart ApplyEvent(IDomainEvent state, IShoppingCart data) + //{ + // if (state is ItemAdded) + // { + // return data.AddItem(((ItemAdded)state).Item); + // } + // if (state is OrderExecuted) + // { + // return data; + // } + // if (state is OrderDiscarded) + // { + // return data.Empty(); + // } + // return data; + //} + + + //protected override void OnRecoveryCompleted() + //{ + // // + //} + + protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) + { + if (e is ItemAdded) + { + var itemAdded = (ItemAdded) e; + return data.AddItem(itemAdded.Item); + } + if (e is OrderExecuted) + { + return data; + } + if (e is OrderDiscarded) + { + return data.Empty(); + } + + return data; + } + } + + } + + #region Custome States + internal enum UserState + { + Shopping, + Inactive, + Paid, + LookingAround + } + + #endregion + + #region Customer states data + + internal class Item + { + public string Id { get; } + public string Name { get; } + public float Price { get; } + + public Item(string id, string name, float price) + { + Id = id; + Name = name; + Price = price; + } + } + + internal interface IShoppingCart + { + IShoppingCart AddItem(Item item); + IShoppingCart Empty(); + } + + internal class EmptyShoppingCart : IShoppingCart + { + public IShoppingCart AddItem(Item item) + { + return new NonEmptyShoppingCart(); + } + + public IShoppingCart Empty() + { + return this; + } + } + + internal class NonEmptyShoppingCart : IShoppingCart + { + public IShoppingCart AddItem(Item item) + { + return this; + } + + public IShoppingCart Empty() + { + return new EmptyShoppingCart(); + } + } + + #endregion + + #region Customer commands + + internal interface ICommand + { + + } + + internal class AddItem : ICommand + { + public AddItem(Item item) + { + Item = item; + } + + public Item Item { get; } + } + + internal class Buy + { + } + internal class Leave + { + } + internal class GetCurrentCart : ICommand + { + } + + #endregion + + + #region Customer domain events + internal interface IDomainEvent + { + + } + + internal class ItemAdded : IDomainEvent + { + public ItemAdded(Item item) + { + Item = item; + } + + public Item Item { get; } + } + + internal class OrderExecuted : IDomainEvent + { + } + internal class OrderDiscarded : IDomainEvent + { + } + #endregion + #region Side effects - report events to be sent to some + internal interface IReportEvent + { + + } + internal class PurchaseWasMade : IReportEvent + { + } + internal class ShoppingCardDiscarded : IReportEvent + { + } + #endregion +} diff --git a/src/core/Akka.Persistence/Akka.Persistence.csproj b/src/core/Akka.Persistence/Akka.Persistence.csproj index ce5c00155b4..929231bf356 100644 --- a/src/core/Akka.Persistence/Akka.Persistence.csproj +++ b/src/core/Akka.Persistence/Akka.Persistence.csproj @@ -47,6 +47,8 @@ + + diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs new file mode 100644 index 00000000000..36b2a5f513a --- /dev/null +++ b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs @@ -0,0 +1,682 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using Akka.Actor; +using Akka.Actor.Internal; +using Akka.Event; +using Akka.Persistence.Serialization; +using Akka.Routing; +using Akka.Util; +using Akka.Util.Internal; +using Akka.Util.Internal.Collections; + +namespace Akka.Persistence.Fsm +{ + /// + /// Finite state machine (FSM) persistent actor. + /// + /// The state name type + /// The state data type + /// The event data type + public abstract class PersistentFSM : PersistentFSMBase, IListeners + { + private readonly ILoggingAdapter _log = Context.GetLogger(); + protected PersistentFSM() + { + if (this is ILoggingFSM) + DebugEvent = Context.System.Settings.FsmDebugEvent; + } + + public delegate State StateFunction(FSMBase.Event fsmEvent, State state = null); + + public delegate void TransitionHandler(TState initialState, TState nextState); + + #region Finite State Machine Domain Specific Language (FSM DSL if you like acronyms) + + /// + /// Insert a new at the end of the processing chain for the + /// given state. If the stateTimeout parameter is set, entering this state without a + /// differing explicit timeout setting will trigger a . + /// + /// designator for the state + /// delegate describing this state's response to input + /// default timeout for this state + public void When(TState stateName, StateFunction func, TimeSpan? timeout = null) + { + Register(stateName, func, timeout); + } + + /// + /// Sets the initial state for this FSM. Call this method from the constructor before the method. + /// If different state is needed after a restart this method, followed by , can be used in the actor + /// life cycle hooks and . + /// + /// Initial state designator. + /// Initial state data. + /// State timeout for the initial state, overriding the default timeout for that state. + public void StartWith(TState stateName, TData stateData, TimeSpan? timeout = null) + { + _currentState = new State(stateName, stateData, timeout); + } + + /// + /// Produce transition to other state. Return this from a state function + /// in order to effect the transition. + /// + /// State designator for the next state + /// State transition descriptor + public State GoTo(TState nextStateName) + { + return new State(nextStateName, _currentState.StateData); + } + + /// + /// Produce transition to other state. Return this from a state function + /// in order to effect the transition. + /// + /// State designator for the next state + /// Data for next state + /// State transition descriptor + public State GoTo(TState nextStateName, TData stateData) + { + return new State(nextStateName, stateData); + } + + /// + /// Produce "empty" transition descriptor. Return this from a state function + /// when no state change is to be effected. + /// + /// Descriptor for staying in the current state. + public State Stay() + { + return GoTo(_currentState.StateName); + } + + /// + /// Produce change descriptor to stop this FSM actor with + /// + public State Stop() + { + return Stop(new FSMBase.Normal()); + } + + /// + /// Produce change descriptor to stop this FSM actor with the specified . + /// + public State Stop(FSMBase.Reason reason) + { + return Stop(reason, _currentState.StateData); + } + + public State Stop(FSMBase.Reason reason, TData stateData) + { + return Stay().Using(stateData).WithStopReason(reason); + } + + public sealed class TransformHelper + { + public TransformHelper(StateFunction func) + { + Func = func; + } + + public StateFunction Func { get; private set; } + + public StateFunction Using(Func, State> andThen) + { + StateFunction continuedDelegate = (@event, state) => andThen.Invoke(Func.Invoke(@event, state)); + return continuedDelegate; + } + } + + /// + /// Schedule named timer to deliver message after given delay, possibly repeating. + /// Any existing timer with the same name will automatically be canceled before adding + /// the new timer. + /// + /// identifier to be used with . + /// message to be delivered + /// delay of first message delivery and between subsequent messages. + /// send once if false, scheduleAtFixedRate if true + public void SetTimer(string name, object msg, TimeSpan timeout, bool repeat = false) + { + if (DebugEvent) + _log.Debug("setting " + (repeat ? "repeating" : "") + "timer '{0}' / {1}: {2}", name, timeout, msg); + if (_timers.ContainsKey(name)) + _timers[name].Cancel(); + var timer = new Timer(name, msg, repeat, _timerGen.Next(), Context, DebugEvent ? _log : null); + timer.Schedule(Self, timeout); + + if (!_timers.ContainsKey(name)) + _timers.Add(name, timer); + else + _timers[name] = timer; + } + + /// + /// Cancel a named , ensuring that the message is not subsequently delivered (no race.) + /// + /// The name of the timer to cancel. + public void CancelTimer(string name) + { + if (DebugEvent) + { + _log.Debug("Cancelling timer {0}", name); + } + + if (_timers.ContainsKey(name)) + { + _timers[name].Cancel(); + _timers.Remove(name); + } + } + + /// + /// Determines whether the named timer is still active. Returns true + /// unless the timer does not exist, has previously been cancelled, or + /// if it was a single-shot timer whose message was already received. + /// + public bool IsTimerActive(string name) + { + return _timers.ContainsKey(name); + } + + /// + /// Set the state timeout explicitly. This method can be safely used from + /// within a state handler. + /// + public void SetStateTimeout(TState state, TimeSpan? timeout) + { + if (!_stateTimeouts.ContainsKey(state)) + _stateTimeouts.Add(state, timeout); + else + _stateTimeouts[state] = timeout; + } + + + + /// + /// Set handler which is called upon each state transition, i.e. not when + /// staying in the same state. + /// + public void OnTransition(TransitionHandler transitionHandler) + { + _transitionEvent.Add(transitionHandler); + } + + /// + /// Set the handler which is called upon termination of this FSM actor. Calling this + /// method again will overwrite the previous contents. + /// + public void OnTermination(Action> terminationHandler) + { + _terminateEvent = terminationHandler; + } + + /// + /// Set handler which is called upon reception of unhandled FSM messages. Calling + /// this method again will overwrite the previous contents. + /// + /// + public void WhenUnhandled(StateFunction stateFunction) + { + HandleEvent = OrElse(stateFunction, HandleEventDefault); + } + + /// + /// Verify the existence of initial state and setup timers. This should be the + /// last call within the constructor or and + /// . + /// + public void Initialize() + { + MakeTransition(_currentState); + } + + /// + /// Current state name + /// + public TState StateName + { + get { return _currentState.StateName; } + } + + /// + /// Current state data + /// + public TData StateData + { + get { return _currentState.StateData; } + } + + /// + /// Return next state data (available in handlers) + /// + public TData NextStateData + { + get + { + if (_nextState == null) throw new InvalidOperationException("NextStateData is only available during OnTransition"); + return _nextState.StateData; + } + } + + public TransformHelper Transform(StateFunction func) { return new TransformHelper(func); } + + #endregion + + #region Internal implementation details + + private readonly ListenerSupport _listener = new ListenerSupport(); + public ListenerSupport Listeners { get { return _listener; } } + + /// + /// Can be set to enable debugging on certain actions taken by the FSM + /// + protected bool DebugEvent; + + /// + /// FSM state data and current timeout handling + /// + private State _currentState; + + private ICancelable _timeoutFuture; + private State _nextState; + private long _generation = 0L; + + /// + /// Timer handling + /// + private readonly IDictionary _timers = new Dictionary(); + private readonly AtomicCounter _timerGen = new AtomicCounter(0); + + /// + /// State definitions + /// + private readonly Dictionary _stateFunctions = new Dictionary(); + private readonly Dictionary _stateTimeouts = new Dictionary(); + + + private void Register(TState name, StateFunction function, TimeSpan? timeout) + { + if (_stateFunctions.ContainsKey(name)) + { + _stateFunctions[name] = OrElse(_stateFunctions[name], function); + _stateTimeouts[name] = _stateTimeouts[name] ?? timeout; + } + else + { + _stateFunctions.Add(name, function); + _stateTimeouts.Add(name, timeout); + } + } + + /// + /// Unhandled event handler + /// + private StateFunction HandleEventDefault + { + get + { + return delegate (FSMBase.Event @event, State state) + { + _log.Warning("unhandled event {0} in state {1}", @event.FsmEvent, StateName); + return Stay(); + }; + } + } + + private StateFunction _handleEvent; + + private StateFunction HandleEvent + { + get { return _handleEvent ?? (_handleEvent = HandleEventDefault); } + set { _handleEvent = value; } + } + + + /// + /// Termination handling + /// + private Action> _terminateEvent = @event => { }; + + /// + /// Transition handling + /// + private readonly IList _transitionEvent = new List(); + + private void HandleTransition(TState previous, TState next) + { + foreach (var tran in _transitionEvent) + { + tran.Invoke(previous, next); + } + } + + + + + /// + /// C# port of Scala's orElse method for partial function chaining. + /// + /// See http://scalachina.com/api/scala/PartialFunction.html + /// + /// The original to be called + /// The to be called if returns null + /// A which combines both the results of and + private static StateFunction OrElse(StateFunction original, StateFunction fallback) + { + StateFunction chained = delegate (FSMBase.Event @event, State state) + { + var originalResult = original.Invoke(@event, state); + if (originalResult == null) return fallback.Invoke(@event, state); + return originalResult; + }; + + return chained; + } + + #endregion + + #region Actor methods + + + public class StateChangeEvent : IMessage + { + public StateChangeEvent(string state, TimeSpan? timeOut) + { + State = state; + TimeOut = timeOut; + } + + public string State { get; private set; } + + public TimeSpan? TimeOut { get; private set; } + } + + private void ProcessMsg(object any, object source) + { + var fsmEvent = new FSMBase.Event(any, _currentState.StateData); + ProcessEvent(fsmEvent, source); + } + + private void ProcessEvent(FSMBase.Event fsmEvent, object source) + { + if (DebugEvent) + { + var srcStr = GetSourceString(source); + _log.Debug("processing {0} from {1}", fsmEvent, srcStr); + } + var stateFunc = _stateFunctions[_currentState.StateName]; + var oldState = _currentState; + State upcomingState = null; + + if (stateFunc != null) + { + upcomingState = stateFunc(fsmEvent); + } + + if (upcomingState == null) + { + upcomingState = HandleEvent(fsmEvent); + } + + ApplyState(upcomingState); + if (DebugEvent && !Equals(oldState, upcomingState)) + { + _log.Debug("transition {0} -> {1}", oldState, upcomingState); + } + } + + private string GetSourceString(object source) + { + var s = source as string; + if (s != null) return s; + var timer = source as Timer; + if (timer != null) return "timer '" + timer.Name + "'"; + var actorRef = source as IActorRef; + if (actorRef != null) return actorRef.ToString(); + return "unknown"; + } + + private void ApplyState(State upcomingState) + { + var eventsToPersist = new List(); + if (upcomingState.Notifies || upcomingState.Timeout.HasValue) + { + eventsToPersist.Add(new StateChangeEvent(upcomingState.StateName.ToString(), upcomingState.Timeout)); + } + if (upcomingState.DomainEvents == null || upcomingState.DomainEvents.IsEmpty) + { + BaseApplyState(upcomingState); + } + else + { + eventsToPersist.Add(upcomingState.DomainEvents); + + var nextData = upcomingState.StateData; + var handlersExecutedCounter = 0; + + Persist(eventsToPersist, @event => + { + handlersExecutedCounter++; + if (handlersExecutedCounter == upcomingState.DomainEvents.Count()) + { + BaseApplyState(upcomingState.Using(nextData)); + if (@event is TEvent) + { + nextData = ApplyEvent((TEvent)@event, nextData); + } + + if (upcomingState.AfterTransitionHandler != null) + { + upcomingState.AfterTransitionHandler(upcomingState.StateData); + } + + + } + }); + } + } + + protected abstract TData ApplyEvent(TEvent e, TData data); + + private void BaseApplyState(State upcomingState) + { + if (upcomingState.StopReason == null) + { + MakeTransition(upcomingState); + return; + } + var replies = upcomingState.Replies; + replies.Reverse(); + foreach (var reply in replies) + { + Sender.Tell(reply); + } + Terminate(upcomingState); + Context.Stop(Self); + } + + private void MakeTransition(State upcomingState) + { + if (!_stateFunctions.ContainsKey(upcomingState.StateName)) + { + Terminate( + Stay() + .WithStopReason( + new FSMBase.Failure(String.Format("Next state {0} does not exist", upcomingState.StateName)))); + } + else + { + var replies = upcomingState.Replies; + replies.Reverse(); + foreach (var r in replies) { Sender.Tell(r); } + if (!_currentState.StateName.Equals(upcomingState.StateName) || upcomingState.Notifies) + { + _nextState = upcomingState; + HandleTransition(_currentState.StateName, _nextState.StateName); + Listeners.Gossip(new FSMBase.Transition(Self, _currentState.StateName, _nextState.StateName)); + _nextState = null; + } + _currentState = upcomingState; + var timeout = _currentState.Timeout ?? _stateTimeouts[_currentState.StateName]; + if (timeout.HasValue) + { + var t = timeout.Value; + if (t < TimeSpan.MaxValue) + { + _timeoutFuture = Context.System.Scheduler.ScheduleTellOnceCancelable(t, Context.Self, new PersistentFSMBase.TimeoutMarker(_generation), Context.Self); + } + } + } + } + + private void Terminate(State upcomingState) + { + if (_currentState.StopReason == null) + { + var reason = upcomingState.StopReason; + LogTermination(reason); + foreach (var t in _timers) { t.Value.Cancel(); } + _timers.Clear(); + _currentState = upcomingState; + + var stopEvent = new FSMBase.StopEvent(reason, _currentState.StateName, _currentState.StateData); + _terminateEvent(stopEvent); + } + } + + /// + /// Call the hook if you want to retain this behavior. + /// When overriding make sure to call base.PostStop(); + /// + /// Please note that this method is called by default from so + /// override that one if shall not be called during restart. + /// + protected override void PostStop() + { + /* + * Setting this instance's state to Terminated does no harm during restart, since + * the new instance will initialize fresh using StartWith. + */ + Terminate(Stay().WithStopReason(new FSMBase.Shutdown())); + base.PostStop(); + } + + #endregion + + /// + /// By default, is logged at error level and other + /// reason types are not logged. It is possible to override this behavior. + /// + /// + protected virtual void LogTermination(FSMBase.Reason reason) + { + PatternMatch.Match(reason) + .With(f => + { + if (f.Cause is Exception) + { + _log.Error(f.Cause.AsInstanceOf(), "terminating due to Failure"); + } + else + { + _log.Error(f.Cause.ToString()); + } + }); + } + + + public bool IsStateTimerActive { get; } + protected override bool ReceiveRecover(object message) + { + var match = PatternMatch.Match(message) + .With(t => + { + Initialize(); + }).With(e => + { + StartWith(StateName, ApplyEvent(e, StateData)); + }).With(sce => + { + StartWith(StateName, StateData, sce.TimeOut); + }); + + return match.WasHandled; + } + + protected override bool ReceiveCommand(object message) + { + var match = PatternMatch.Match(message) + .With(marker => + { + if (_generation == marker.Generation) + { + ProcessMsg(new StateTimeout(), "state timeout"); + } + }) + .With(t => + { + if (_timers.ContainsKey(t.Name) && _timers[t.Name].Generation == t.Generation) + { + if (_timeoutFuture != null) + { + _timeoutFuture.Cancel(false); + _timeoutFuture = null; + } + _generation++; + if (!t.Repeat) + { + _timers.Remove(t.Name); + } + ProcessMsg(t.Message, t); + } + }) + .With(cb => + { + Context.Watch(cb.ActorRef); + Listeners.Add(cb.ActorRef); + //send the current state back as a reference point + cb.ActorRef.Tell(new FSMBase.CurrentState(Self, _currentState.StateName)); + }) + .With(l => + { + Context.Watch(l.Listener); + Listeners.Add(l.Listener); + l.Listener.Tell(new FSMBase.CurrentState(Self, _currentState.StateName)); + }) + .With(ucb => + { + Context.Unwatch(ucb.ActorRef); + Listeners.Remove(ucb.ActorRef); + }) + .With(d => + { + Context.Unwatch(d.Listener); + Listeners.Remove(d.Listener); + }) + .With(_ => { DebugEvent = true; }) + .Default(msg => + { + if (_timeoutFuture != null) + { + _timeoutFuture.Cancel(false); + _timeoutFuture = null; + } + _generation++; + ProcessMsg(msg, Sender); + }); + return match.WasHandled; + } + } +} + diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs b/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs new file mode 100644 index 00000000000..fa0834ae169 --- /dev/null +++ b/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs @@ -0,0 +1,215 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Akka.Actor; +using Akka.Dispatch.SysMsg; +using Akka.Event; +using Akka.Util; + +namespace Akka.Persistence.Fsm +{ + public abstract class PersistentFSMBase : PersistentActor + { + #region States + + + + /// + /// Used in the event of a timeout between transitions + /// + public class StateTimeout + { + } + + /* + * INTERNAL API - used for ensuring that state changes occur on-time + */ + + internal class TimeoutMarker + { + public TimeoutMarker(long generation) + { + Generation = generation; + } + + public long Generation { get; private set; } + } + + [DebuggerDisplay("Timer {Name,nq}, message: {Message")] + internal class Timer : INoSerializationVerificationNeeded + { + private readonly ILoggingAdapter _debugLog; + + public Timer(string name, object message, bool repeat, int generation, IActorContext context, + ILoggingAdapter debugLog) + { + _debugLog = debugLog; + Context = context; + Generation = generation; + Repeat = repeat; + Message = message; + Name = name; + var scheduler = context.System.Scheduler; + _scheduler = scheduler; + _ref = new Cancelable(scheduler); + } + + private readonly IScheduler _scheduler; + private readonly ICancelable _ref; + + public string Name { get; private set; } + + public object Message { get; private set; } + + public bool Repeat { get; private set; } + + public int Generation { get; private set; } + + public IActorContext Context { get; private set; } + + public void Schedule(IActorRef actor, TimeSpan timeout) + { + var name = Name; + var message = Message; + + Action send; + if (_debugLog != null) + send = () => + { + _debugLog.Debug("{0}Timer '{1}' went off. Sending {2} -> {3}", + _ref.IsCancellationRequested ? "Cancelled " : "", name, message, actor); + actor.Tell(this, Context.Self); + }; + else + send = () => actor.Tell(this, Context.Self); + + if (Repeat) _scheduler.Advanced.ScheduleRepeatedly(timeout, timeout, send, _ref); + else _scheduler.Advanced.ScheduleOnce(timeout, send, _ref); + } + + public void Cancel() + { + if (!_ref.IsCancellationRequested) + { + _ref.Cancel(false); + } + } + } + + + + /// + /// This captures all of the managed state of the : the state name, + /// the state data, possibly custom timeout, stop reason, and replies accumulated while + /// processing the last message. + /// + /// The name of the state + /// The data of the state + /// The event of the state + public class State : FSMBase.State + { + public Action AfterTransitionHandler { get; private set; } + + + public State(TS stateName, TD stateData, TimeSpan? timeout = null, FSMBase.Reason stopReason = null, + List replies = null, ILinearSeq domainEvents = null, Action afterTransitionDo = null) + : base(stateName, stateData, timeout, stopReason, replies) + { + AfterTransitionHandler = afterTransitionDo; + DomainEvents = domainEvents; + Notifies = true; + } + + public ILinearSeq DomainEvents { get; } + + public bool Notifies { get; set; } + + /// + /// Specify domain events to be applied when transitioning to the new state. + /// + /// + /// + public State Applying(ILinearSeq events) + { + if (DomainEvents == null) + { + return Copy(null, null, null, events); + } + return Copy(null, null, null, new ArrayLinearSeq(DomainEvents.Concat(events).ToArray())); + } + + + /// + /// Specify domain event to be applied when transitioning to the new state. + /// + /// + /// + public State Applying(TE e) + { + if (DomainEvents == null) + { + return Copy(null, null, null, new ArrayLinearSeq(new TE[] {e})); + } + var events = new List(); + events.AddRange(DomainEvents); + events.Add(e); + return Copy(null, null, null, new ArrayLinearSeq(DomainEvents.Concat(events).ToArray())); + } + + + /// + /// Register a handler to be triggered after the state has been persisted successfully + /// + /// + /// + public State AndThen(Action handler) + { + return Copy(null, null, null, null, handler); + } + + public State Copy(TimeSpan? timeout, FSMBase.Reason stopReason = null, + List replies = null, ILinearSeq domainEvents = null, Action afterTransitionDo = null) + { + return new State(StateName, StateData, timeout ?? Timeout, stopReason ?? StopReason, replies ?? Replies, + domainEvents ?? DomainEvents, afterTransitionDo ?? AfterTransitionHandler); + } + + /// + /// Modify state transition descriptor with new state data. The data will be set + /// when transitioning to the new state. + /// + public new State Using(TD nextStateData) + { + return new State(StateName, nextStateData, Timeout, StopReason, Replies); + } + + + public new State Replying(object replyValue) + { + + if (Replies == null) Replies = new List(); + var newReplies = Replies.ToArray().ToList(); + newReplies.Add(replyValue); + return Copy(Timeout, replies: newReplies); + } + + public new State ForMax(TimeSpan timeout) + { + if (timeout <= TimeSpan.MaxValue) return Copy(timeout); + return Copy(null); + } + + /// + /// INTERNAL API + /// + internal State WithStopReason(FSMBase.Reason reason) + { + return Copy(null, reason); + } + + + #endregion + } + } +} \ No newline at end of file diff --git a/src/core/Akka/Actor/FSM.cs b/src/core/Akka/Actor/FSM.cs index 6bd7dbe37fe..8c7542fe3b3 100644 --- a/src/core/Akka/Actor/FSM.cs +++ b/src/core/Akka/Actor/FSM.cs @@ -250,7 +250,7 @@ public State(TS stateName, TD stateData, TimeSpan? timeout = null, Reason stopRe public Reason StopReason { get; private set; } - public List Replies { get; private set; } + public List Replies { get; protected set; } public State Copy(TimeSpan? timeout, Reason stopReason = null, List replies = null) { From 6f6658c07e6742c0a9e2f82f100281122292d8f5 Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Sat, 31 Oct 2015 10:58:52 +0400 Subject: [PATCH 067/105] solved problem with events persist --- .../Akka.Persistence/Fsm/PersistentFSM.cs | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs index 36b2a5f513a..c0db9b3836a 100644 --- a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs +++ b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs @@ -391,13 +391,13 @@ private static StateFunction OrElse(StateFunction original, StateFunction fallba public class StateChangeEvent : IMessage { - public StateChangeEvent(string state, TimeSpan? timeOut) + public StateChangeEvent(TState state, TimeSpan? timeOut) { State = state; TimeOut = timeOut; } - public string State { get; private set; } + public TState State { get; private set; } public TimeSpan? TimeOut { get; private set; } } @@ -450,9 +450,9 @@ private string GetSourceString(object source) private void ApplyState(State upcomingState) { var eventsToPersist = new List(); - if (upcomingState.Notifies || upcomingState.Timeout.HasValue) + if ( upcomingState.Timeout.HasValue) { - eventsToPersist.Add(new StateChangeEvent(upcomingState.StateName.ToString(), upcomingState.Timeout)); + eventsToPersist.Add(new StateChangeEvent(upcomingState.StateName, upcomingState.Timeout)); } if (upcomingState.DomainEvents == null || upcomingState.DomainEvents.IsEmpty) { @@ -460,30 +460,36 @@ private void ApplyState(State upcomingState) } else { - eventsToPersist.Add(upcomingState.DomainEvents); + foreach (var domainEvent in upcomingState.DomainEvents) + { + eventsToPersist.Add(domainEvent); + } + - var nextData = upcomingState.StateData; + var nextData = StateData;// upcomingState.StateData; var handlersExecutedCounter = 0; - Persist(eventsToPersist, @event => - { - handlersExecutedCounter++; - if (handlersExecutedCounter == upcomingState.DomainEvents.Count()) + + Persist(eventsToPersist, @event => { - BaseApplyState(upcomingState.Using(nextData)); + handlersExecutedCounter++; if (@event is TEvent) { nextData = ApplyEvent((TEvent)@event, nextData); } - - if (upcomingState.AfterTransitionHandler != null) + if (handlersExecutedCounter == eventsToPersist.Count) { - upcomingState.AfterTransitionHandler(upcomingState.StateData); - } + BaseApplyState(upcomingState.Using(nextData)); + if (upcomingState.AfterTransitionHandler != null) + { + upcomingState.AfterTransitionHandler(upcomingState.StateData); + } + + + } + }); - } - }); } } @@ -520,7 +526,7 @@ private void MakeTransition(State upcomingState) var replies = upcomingState.Replies; replies.Reverse(); foreach (var r in replies) { Sender.Tell(r); } - if (!_currentState.StateName.Equals(upcomingState.StateName) || upcomingState.Notifies) + if (!_currentState.StateName.Equals(upcomingState.StateName)) { _nextState = upcomingState; HandleTransition(_currentState.StateName, _nextState.StateName); @@ -608,7 +614,7 @@ protected override bool ReceiveRecover(object message) StartWith(StateName, ApplyEvent(e, StateData)); }).With(sce => { - StartWith(StateName, StateData, sce.TimeOut); + StartWith(sce.State, StateData, sce.TimeOut); }); return match.WasHandled; From faaf5ba4827978e3e530393d82cca70f9ca1644d Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Sat, 31 Oct 2015 14:30:12 +0400 Subject: [PATCH 068/105] added tests --- .../Fsm/PersistentFSMSpec.cs | 314 ++++++++++++++++-- .../Akka.Persistence/Fsm/PersistentFSM.cs | 17 +- 2 files changed, 291 insertions(+), 40 deletions(-) diff --git a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs index 34d92827634..d41f82a591c 100644 --- a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs +++ b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs @@ -107,13 +107,6 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_data() fsmRef.Tell(new GetCurrentCart()); - //fsmRef.Tell(new AddItem(coat)); - //fsmRef.Tell(new GetCurrentCart()); - //fsmRef.Tell(new Buy()); - //fsmRef.Tell(new GetCurrentCart()); - //fsmRef.Tell(new Leave()); - - ExpectMsg>(); ExpectMsg(); ExpectMsg>(state => @@ -150,6 +143,213 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_data() ExpectTerminated(recoveredFsmRef); } + [Fact] + public void PersistentFSM_should_execute_the_defined_actions_following_successful_persistence_of_state_change() + { + var reportActorProbe = CreateTestProbe(Sys); + + var fsmRef = Sys.ActorOf(Props.Create(() => new WebStoreCustomerFSM(Name, reportActorProbe.Ref))); + + Watch(fsmRef); + fsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); + + var shirt = new Item("1", "Shirt", 59.99F); + var shoes = new Item("2", "Shoes", 89.99F); + var coat = new Item("3", "Coat", 119.99F); + + fsmRef.Tell(new AddItem(shirt)); + fsmRef.Tell(new AddItem(shoes)); + fsmRef.Tell(new AddItem(coat)); + fsmRef.Tell(new Buy()); + fsmRef.Tell(new Leave()); + + ExpectMsg>(state => + { + return state.State == UserState.LookingAround; + }); + ExpectMsg>(state => + { + return state.From == UserState.LookingAround && state.To == UserState.Shopping; + }); + ExpectMsg>(state => + { + return state.From == UserState.Shopping && state.To == UserState.Paid; + }); + reportActorProbe.ExpectMsg(); + ExpectTerminated(fsmRef); + } + + [Fact] + public void PersistentFSM_should_execute_the_defined_actions_following_successful_persistence_of_FSM_stop() + { + var reportActorProbe = CreateTestProbe(Sys); + + var fsmRef = Sys.ActorOf(Props.Create(() => new WebStoreCustomerFSM(Name, reportActorProbe.Ref))); + + Watch(fsmRef); + fsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); + + var shirt = new Item("1", "Shirt", 59.99F); + var shoes = new Item("2", "Shoes", 89.99F); + var coat = new Item("3", "Coat", 119.99F); + + fsmRef.Tell(new AddItem(shirt)); + fsmRef.Tell(new AddItem(shoes)); + fsmRef.Tell(new AddItem(coat)); + fsmRef.Tell(new Leave()); + + ExpectMsg>(state => + { + return state.State == UserState.LookingAround; + }); + ExpectMsg>(state => + { + return state.From == UserState.LookingAround && state.To == UserState.Shopping; + }); + reportActorProbe.ExpectMsg(); + ExpectTerminated(fsmRef); + } + + [Fact] + public void PersistentFSM_should_recover_successfully_with_correct_state_timeout() + { + var dummyReportActorRef = CreateTestProbe().Ref; + + var fsmRef = Sys.ActorOf(Props.Create(() => new WebStoreCustomerFSM(Name, dummyReportActorRef))); + + Watch(fsmRef); + fsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); + + var shirt = new Item("1", "Shirt", 59.99F); + + fsmRef.Tell(new AddItem(shirt)); + + ExpectMsg>(state => + { + return state.State == UserState.LookingAround; + }); + ExpectMsg>(state => + { + return state.From == UserState.LookingAround && state.To == UserState.Shopping; + + }); + + ExpectNoMsg(TimeSpan.FromSeconds(0.6)); + fsmRef.Tell(PoisonPill.Instance); + ExpectTerminated(fsmRef); + + var recoveredFsmRef = Sys.ActorOf(Props.Create(() => new WebStoreCustomerFSM(Name, dummyReportActorRef))); + Watch(recoveredFsmRef); + recoveredFsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); + + ExpectMsg>(state => + { + return state.State == UserState.Shopping; + }); + + + Within(TimeSpan.FromSeconds(0.9), TimeSpan.FromSeconds(1.9), () => + { + ExpectMsg>(state => + { + return state.From == UserState.Shopping && state.To == UserState.Inactive; + }); + return true; + }); + ExpectNoMsg(TimeSpan.FromSeconds(0.6)); + recoveredFsmRef.Tell(PoisonPill.Instance); + ExpectTerminated(recoveredFsmRef); + + recoveredFsmRef = Sys.ActorOf(Props.Create(() => new WebStoreCustomerFSM(Name, dummyReportActorRef))); + Watch(recoveredFsmRef); + recoveredFsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); + ExpectMsg>(state => + { + return state.State == UserState.Inactive; + }); + ExpectTerminated(recoveredFsmRef); + } + + [Fact] + public void PersistentFSM_should_not_trigger_onTransition_for_stay() + { + var reportActorProbe = CreateTestProbe(Sys); + + var fsmRef = Sys.ActorOf(Props.Create(() => new SimpleTransitionFSM(Name, reportActorProbe.Ref))); + + reportActorProbe.ExpectNoMsg(TimeSpan.FromSeconds(3)); + + fsmRef.Tell("goto(the same state)"); + + reportActorProbe.ExpectNoMsg(TimeSpan.FromSeconds(3)); + + fsmRef.Tell("stay"); + + reportActorProbe.ExpectNoMsg(TimeSpan.FromSeconds(3)); + } + + + [Fact] + public void PersistentFSM_should_not_persist_state_change_event_when_staying_in_the_same_state() + { + var dummyReportActorRef = CreateTestProbe().Ref; + + var fsmRef = Sys.ActorOf(Props.Create(Name, dummyReportActorRef), Name); + + Watch(fsmRef); + fsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); + + var shirt = new Item("1", "Shirt", 59.99F); + var shoes = new Item("2", "Shoes", 89.99F); + var coat = new Item("3", "Coat", 119.99F); + + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new AddItem(shirt)); + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new AddItem(shoes)); + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new AddItem(coat)); + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new Buy()); + fsmRef.Tell(new GetCurrentCart()); + fsmRef.Tell(new Leave()); + ExpectMsg>(state => state.State == UserState.LookingAround); + ExpectMsg(); + ExpectMsg>(state => state.From == UserState.LookingAround); + ExpectMsg(); + ExpectMsg(); + ExpectMsg(); + ExpectMsg>(); + ExpectMsg(); + ExpectTerminated(fsmRef); + + var persistentEventsStreamer = Sys.ActorOf(Props.Create(Name, TestActor), Name); + + ExpectMsg(); + ExpectMsg.StateChangeEvent>(); + + + ExpectMsg(); + ExpectMsg.StateChangeEvent>(); + + + ExpectMsg(); + ExpectMsg.StateChangeEvent>(); + + + ExpectMsg(); + ExpectMsg.StateChangeEvent>(); + + Watch(persistentEventsStreamer); + + persistentEventsStreamer.Tell(PoisonPill.Instance); + + ExpectTerminated(persistentEventsStreamer); + + } + + + internal class WebStoreCustomerFSM : PersistentFSM { private readonly string _persistenceId; @@ -255,30 +455,6 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) public override string PersistenceId { get { return _persistenceId; }} - - //protected override IShoppingCart ApplyEvent(IDomainEvent state, IShoppingCart data) - //{ - // if (state is ItemAdded) - // { - // return data.AddItem(((ItemAdded)state).Item); - // } - // if (state is OrderExecuted) - // { - // return data; - // } - // if (state is OrderDiscarded) - // { - // return data.Empty(); - // } - // return data; - //} - - - //protected override void OnRecoveryCompleted() - //{ - // // - //} - protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) { if (e is ItemAdded) @@ -301,8 +477,82 @@ protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) } + internal class SimpleTransitionFSM : PersistentFSM + { + private readonly string _persistenceId; + private readonly IActorRef _reportActor; + + public SimpleTransitionFSM(string persistenceId, IActorRef reportActor) + { + _persistenceId = persistenceId; + _reportActor = reportActor; + StartWith(UserState.LookingAround, new EmptyShoppingCart()); + + When(UserState.LookingAround, (@event, state) => + { + if ((string) @event.FsmEvent == "stay") + { + return Stay(); + } + return GoTo(UserState.LookingAround); + }); + OnTransition((state, nextState) => + { + _reportActor.Tell(string.Format("{0} -> {1}", state, nextState)); + }); + + + } + + public override string PersistenceId + { + get { return _persistenceId; } + } + + + protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) + { + + return data; + } + + + } + + internal class PersistentEventsStreamer : PersistentActor + { + private readonly string _persistenceId; + private readonly IActorRef _client; + + public PersistentEventsStreamer(string persistenceId, IActorRef client) + { + _persistenceId = persistenceId; + _client = client; + } + + public override string PersistenceId + { + get { return _persistenceId; } + } + + protected override bool ReceiveRecover(object message) + { + if (!(message is RecoveryCompleted)) + { + _client.Tell(message); + } + + return true; + } + + protected override bool ReceiveCommand(object message) + { + return true; + } + } + #region Custome States - internal enum UserState +internal enum UserState { Shopping, Inactive, diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs index c0db9b3836a..6cba5106d6e 100644 --- a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs +++ b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs @@ -450,22 +450,23 @@ private string GetSourceString(object source) private void ApplyState(State upcomingState) { var eventsToPersist = new List(); - if ( upcomingState.Timeout.HasValue) + if (upcomingState.DomainEvents != null) + { + foreach (var domainEvent in upcomingState.DomainEvents) + { + eventsToPersist.Add(domainEvent); + } + } + if (!StateName.Equals(upcomingState.StateName) || upcomingState.Timeout.HasValue) { eventsToPersist.Add(new StateChangeEvent(upcomingState.StateName, upcomingState.Timeout)); } - if (upcomingState.DomainEvents == null || upcomingState.DomainEvents.IsEmpty) + if (eventsToPersist.Count == 0) { BaseApplyState(upcomingState); } else { - foreach (var domainEvent in upcomingState.DomainEvents) - { - eventsToPersist.Add(domainEvent); - } - - var nextData = StateData;// upcomingState.StateData; var handlersExecutedCounter = 0; From c634bd43078630a442964ea7d8c5ac5a890db2b6 Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Sat, 31 Oct 2015 16:15:47 +0400 Subject: [PATCH 069/105] extracted methods to base class --- .../Akka.Persistence/Fsm/PersistentFSM.cs | 664 +----------------- .../Akka.Persistence/Fsm/PersistentFSMBase.cs | 645 ++++++++++++++++- 2 files changed, 649 insertions(+), 660 deletions(-) diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs index 6cba5106d6e..f526ff0e96e 100644 --- a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs +++ b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs @@ -5,451 +5,50 @@ // //----------------------------------------------------------------------- -using System; using System.Collections.Generic; -using System.Linq; -using System.Threading; using Akka.Actor; -using Akka.Actor.Internal; -using Akka.Event; -using Akka.Persistence.Serialization; -using Akka.Routing; -using Akka.Util; -using Akka.Util.Internal; -using Akka.Util.Internal.Collections; namespace Akka.Persistence.Fsm { /// - /// Finite state machine (FSM) persistent actor. + /// Finite state machine (FSM) persistent actor. /// /// The state name type /// The state data type /// The event data type - public abstract class PersistentFSM : PersistentFSMBase, IListeners + public abstract class PersistentFSM : PersistentFSMBase { - private readonly ILoggingAdapter _log = Context.GetLogger(); - protected PersistentFSM() - { - if (this is ILoggingFSM) - DebugEvent = Context.System.Settings.FsmDebugEvent; - } - - public delegate State StateFunction(FSMBase.Event fsmEvent, State state = null); - - public delegate void TransitionHandler(TState initialState, TState nextState); - - #region Finite State Machine Domain Specific Language (FSM DSL if you like acronyms) - - /// - /// Insert a new at the end of the processing chain for the - /// given state. If the stateTimeout parameter is set, entering this state without a - /// differing explicit timeout setting will trigger a . - /// - /// designator for the state - /// delegate describing this state's response to input - /// default timeout for this state - public void When(TState stateName, StateFunction func, TimeSpan? timeout = null) - { - Register(stateName, func, timeout); - } - - /// - /// Sets the initial state for this FSM. Call this method from the constructor before the method. - /// If different state is needed after a restart this method, followed by , can be used in the actor - /// life cycle hooks and . - /// - /// Initial state designator. - /// Initial state data. - /// State timeout for the initial state, overriding the default timeout for that state. - public void StartWith(TState stateName, TData stateData, TimeSpan? timeout = null) - { - _currentState = new State(stateName, stateData, timeout); - } - - /// - /// Produce transition to other state. Return this from a state function - /// in order to effect the transition. - /// - /// State designator for the next state - /// State transition descriptor - public State GoTo(TState nextStateName) - { - return new State(nextStateName, _currentState.StateData); - } - - /// - /// Produce transition to other state. Return this from a state function - /// in order to effect the transition. - /// - /// State designator for the next state - /// Data for next state - /// State transition descriptor - public State GoTo(TState nextStateName, TData stateData) - { - return new State(nextStateName, stateData); - } - - /// - /// Produce "empty" transition descriptor. Return this from a state function - /// when no state change is to be effected. - /// - /// Descriptor for staying in the current state. - public State Stay() - { - return GoTo(_currentState.StateName); - } - - /// - /// Produce change descriptor to stop this FSM actor with - /// - public State Stop() - { - return Stop(new FSMBase.Normal()); - } - - /// - /// Produce change descriptor to stop this FSM actor with the specified . - /// - public State Stop(FSMBase.Reason reason) - { - return Stop(reason, _currentState.StateData); - } - - public State Stop(FSMBase.Reason reason, TData stateData) - { - return Stay().Using(stateData).WithStopReason(reason); - } - - public sealed class TransformHelper - { - public TransformHelper(StateFunction func) - { - Func = func; - } - - public StateFunction Func { get; private set; } - - public StateFunction Using(Func, State> andThen) - { - StateFunction continuedDelegate = (@event, state) => andThen.Invoke(Func.Invoke(@event, state)); - return continuedDelegate; - } - } - - /// - /// Schedule named timer to deliver message after given delay, possibly repeating. - /// Any existing timer with the same name will automatically be canceled before adding - /// the new timer. - /// - /// identifier to be used with . - /// message to be delivered - /// delay of first message delivery and between subsequent messages. - /// send once if false, scheduleAtFixedRate if true - public void SetTimer(string name, object msg, TimeSpan timeout, bool repeat = false) - { - if (DebugEvent) - _log.Debug("setting " + (repeat ? "repeating" : "") + "timer '{0}' / {1}: {2}", name, timeout, msg); - if (_timers.ContainsKey(name)) - _timers[name].Cancel(); - var timer = new Timer(name, msg, repeat, _timerGen.Next(), Context, DebugEvent ? _log : null); - timer.Schedule(Self, timeout); - - if (!_timers.ContainsKey(name)) - _timers.Add(name, timer); - else - _timers[name] = timer; - } - - /// - /// Cancel a named , ensuring that the message is not subsequently delivered (no race.) - /// - /// The name of the timer to cancel. - public void CancelTimer(string name) - { - if (DebugEvent) - { - _log.Debug("Cancelling timer {0}", name); - } - - if (_timers.ContainsKey(name)) - { - _timers[name].Cancel(); - _timers.Remove(name); - } - } - - /// - /// Determines whether the named timer is still active. Returns true - /// unless the timer does not exist, has previously been cancelled, or - /// if it was a single-shot timer whose message was already received. - /// - public bool IsTimerActive(string name) - { - return _timers.ContainsKey(name); - } - - /// - /// Set the state timeout explicitly. This method can be safely used from - /// within a state handler. - /// - public void SetStateTimeout(TState state, TimeSpan? timeout) - { - if (!_stateTimeouts.ContainsKey(state)) - _stateTimeouts.Add(state, timeout); - else - _stateTimeouts[state] = timeout; - } - - - - /// - /// Set handler which is called upon each state transition, i.e. not when - /// staying in the same state. - /// - public void OnTransition(TransitionHandler transitionHandler) - { - _transitionEvent.Add(transitionHandler); - } - - /// - /// Set the handler which is called upon termination of this FSM actor. Calling this - /// method again will overwrite the previous contents. - /// - public void OnTermination(Action> terminationHandler) - { - _terminateEvent = terminationHandler; - } - - /// - /// Set handler which is called upon reception of unhandled FSM messages. Calling - /// this method again will overwrite the previous contents. - /// - /// - public void WhenUnhandled(StateFunction stateFunction) - { - HandleEvent = OrElse(stateFunction, HandleEventDefault); - } - - /// - /// Verify the existence of initial state and setup timers. This should be the - /// last call within the constructor or and - /// . - /// - public void Initialize() - { - MakeTransition(_currentState); - } - - /// - /// Current state name - /// - public TState StateName - { - get { return _currentState.StateName; } - } - - /// - /// Current state data - /// - public TData StateData - { - get { return _currentState.StateData; } - } - - /// - /// Return next state data (available in handlers) - /// - public TData NextStateData - { - get - { - if (_nextState == null) throw new InvalidOperationException("NextStateData is only available during OnTransition"); - return _nextState.StateData; - } - } - - public TransformHelper Transform(StateFunction func) { return new TransformHelper(func); } - - #endregion - - #region Internal implementation details - - private readonly ListenerSupport _listener = new ListenerSupport(); - public ListenerSupport Listeners { get { return _listener; } } - - /// - /// Can be set to enable debugging on certain actions taken by the FSM - /// - protected bool DebugEvent; - - /// - /// FSM state data and current timeout handling - /// - private State _currentState; - - private ICancelable _timeoutFuture; - private State _nextState; - private long _generation = 0L; - - /// - /// Timer handling - /// - private readonly IDictionary _timers = new Dictionary(); - private readonly AtomicCounter _timerGen = new AtomicCounter(0); - - /// - /// State definitions - /// - private readonly Dictionary _stateFunctions = new Dictionary(); - private readonly Dictionary _stateTimeouts = new Dictionary(); - - - private void Register(TState name, StateFunction function, TimeSpan? timeout) - { - if (_stateFunctions.ContainsKey(name)) - { - _stateFunctions[name] = OrElse(_stateFunctions[name], function); - _stateTimeouts[name] = _stateTimeouts[name] ?? timeout; - } - else - { - _stateFunctions.Add(name, function); - _stateTimeouts.Add(name, timeout); - } - } - - /// - /// Unhandled event handler - /// - private StateFunction HandleEventDefault - { - get - { - return delegate (FSMBase.Event @event, State state) - { - _log.Warning("unhandled event {0} in state {1}", @event.FsmEvent, StateName); - return Stay(); - }; - } - } - - private StateFunction _handleEvent; - - private StateFunction HandleEvent - { - get { return _handleEvent ?? (_handleEvent = HandleEventDefault); } - set { _handleEvent = value; } - } - - - /// - /// Termination handling - /// - private Action> _terminateEvent = @event => { }; - - /// - /// Transition handling - /// - private readonly IList _transitionEvent = new List(); - - private void HandleTransition(TState previous, TState next) - { - foreach (var tran in _transitionEvent) - { - tran.Invoke(previous, next); - } - } - - - - /// - /// C# port of Scala's orElse method for partial function chaining. - /// - /// See http://scalachina.com/api/scala/PartialFunction.html + /// Call the hook if you want to retain this behavior. + /// When overriding make sure to call base.PostStop(); + /// Please note that this method is called by default from so + /// override that one if shall not be called during restart. /// - /// The original to be called - /// The to be called if returns null - /// A which combines both the results of and - private static StateFunction OrElse(StateFunction original, StateFunction fallback) - { - StateFunction chained = delegate (FSMBase.Event @event, State state) - { - var originalResult = original.Invoke(@event, state); - if (originalResult == null) return fallback.Invoke(@event, state); - return originalResult; - }; - - return chained; - } - - #endregion - - #region Actor methods - - - public class StateChangeEvent : IMessage - { - public StateChangeEvent(TState state, TimeSpan? timeOut) - { - State = state; - TimeOut = timeOut; - } - - public TState State { get; private set; } - - public TimeSpan? TimeOut { get; private set; } - } - - private void ProcessMsg(object any, object source) + protected override void PostStop() { - var fsmEvent = new FSMBase.Event(any, _currentState.StateData); - ProcessEvent(fsmEvent, source); + /* + * Setting this instance's state to Terminated does no harm during restart, since + * the new instance will initialize fresh using StartWith. + */ + Terminate(Stay().WithStopReason(new FSMBase.Shutdown())); + base.PostStop(); } - private void ProcessEvent(FSMBase.Event fsmEvent, object source) + protected override bool ReceiveRecover(object message) { - if (DebugEvent) - { - var srcStr = GetSourceString(source); - _log.Debug("processing {0} from {1}", fsmEvent, srcStr); - } - var stateFunc = _stateFunctions[_currentState.StateName]; - var oldState = _currentState; - State upcomingState = null; + var match = message.Match() + .With(t => { Initialize(); }) + .With(e => { StartWith(StateName, ApplyEvent(e, StateData)); }) + .With(sce => { StartWith(sce.State, StateData, sce.TimeOut); }); - if (stateFunc != null) - { - upcomingState = stateFunc(fsmEvent); - } - - if (upcomingState == null) - { - upcomingState = HandleEvent(fsmEvent); - } - - ApplyState(upcomingState); - if (DebugEvent && !Equals(oldState, upcomingState)) - { - _log.Debug("transition {0} -> {1}", oldState, upcomingState); - } + return match.WasHandled; } - private string GetSourceString(object source) - { - var s = source as string; - if (s != null) return s; - var timer = source as Timer; - if (timer != null) return "timer '" + timer.Name + "'"; - var actorRef = source as IActorRef; - if (actorRef != null) return actorRef.ToString(); - return "unknown"; - } + protected abstract TData ApplyEvent(TEvent e, TData data); - private void ApplyState(State upcomingState) + protected override void ApplyState(State upcomingState) { - var eventsToPersist = new List(); + var eventsToPersist = new List(); if (upcomingState.DomainEvents != null) { foreach (var domainEvent in upcomingState.DomainEvents) @@ -463,227 +62,32 @@ private void ApplyState(State upcomingState) } if (eventsToPersist.Count == 0) { - BaseApplyState(upcomingState); + base.ApplyState(upcomingState); } else { - var nextData = StateData;// upcomingState.StateData; + var nextData = StateData; // upcomingState.StateData; var handlersExecutedCounter = 0; - - Persist(eventsToPersist, @event => - { - handlersExecutedCounter++; - if (@event is TEvent) - { - nextData = ApplyEvent((TEvent)@event, nextData); - } - if (handlersExecutedCounter == eventsToPersist.Count) - { - BaseApplyState(upcomingState.Using(nextData)); - - if (upcomingState.AfterTransitionHandler != null) - { - upcomingState.AfterTransitionHandler(upcomingState.StateData); - } - - } - }); - - } - } - - protected abstract TData ApplyEvent(TEvent e, TData data); - - private void BaseApplyState(State upcomingState) - { - if (upcomingState.StopReason == null) - { - MakeTransition(upcomingState); - return; - } - var replies = upcomingState.Replies; - replies.Reverse(); - foreach (var reply in replies) - { - Sender.Tell(reply); - } - Terminate(upcomingState); - Context.Stop(Self); - } - - private void MakeTransition(State upcomingState) - { - if (!_stateFunctions.ContainsKey(upcomingState.StateName)) - { - Terminate( - Stay() - .WithStopReason( - new FSMBase.Failure(String.Format("Next state {0} does not exist", upcomingState.StateName)))); - } - else - { - var replies = upcomingState.Replies; - replies.Reverse(); - foreach (var r in replies) { Sender.Tell(r); } - if (!_currentState.StateName.Equals(upcomingState.StateName)) - { - _nextState = upcomingState; - HandleTransition(_currentState.StateName, _nextState.StateName); - Listeners.Gossip(new FSMBase.Transition(Self, _currentState.StateName, _nextState.StateName)); - _nextState = null; - } - _currentState = upcomingState; - var timeout = _currentState.Timeout ?? _stateTimeouts[_currentState.StateName]; - if (timeout.HasValue) - { - var t = timeout.Value; - if (t < TimeSpan.MaxValue) - { - _timeoutFuture = Context.System.Scheduler.ScheduleTellOnceCancelable(t, Context.Self, new PersistentFSMBase.TimeoutMarker(_generation), Context.Self); - } - } - } - } - - private void Terminate(State upcomingState) - { - if (_currentState.StopReason == null) - { - var reason = upcomingState.StopReason; - LogTermination(reason); - foreach (var t in _timers) { t.Value.Cancel(); } - _timers.Clear(); - _currentState = upcomingState; - - var stopEvent = new FSMBase.StopEvent(reason, _currentState.StateName, _currentState.StateData); - _terminateEvent(stopEvent); - } - } - - /// - /// Call the hook if you want to retain this behavior. - /// When overriding make sure to call base.PostStop(); - /// - /// Please note that this method is called by default from so - /// override that one if shall not be called during restart. - /// - protected override void PostStop() - { - /* - * Setting this instance's state to Terminated does no harm during restart, since - * the new instance will initialize fresh using StartWith. - */ - Terminate(Stay().WithStopReason(new FSMBase.Shutdown())); - base.PostStop(); - } - - #endregion - - /// - /// By default, is logged at error level and other - /// reason types are not logged. It is possible to override this behavior. - /// - /// - protected virtual void LogTermination(FSMBase.Reason reason) - { - PatternMatch.Match(reason) - .With(f => + Persist(eventsToPersist, @event => { - if (f.Cause is Exception) + handlersExecutedCounter++; + if (@event is TEvent) { - _log.Error(f.Cause.AsInstanceOf(), "terminating due to Failure"); + nextData = ApplyEvent((TEvent) @event, nextData); } - else + if (handlersExecutedCounter == eventsToPersist.Count) { - _log.Error(f.Cause.ToString()); - } - }); - } - - - public bool IsStateTimerActive { get; } - protected override bool ReceiveRecover(object message) - { - var match = PatternMatch.Match(message) - .With(t => - { - Initialize(); - }).With(e => - { - StartWith(StateName, ApplyEvent(e, StateData)); - }).With(sce => - { - StartWith(sce.State, StateData, sce.TimeOut); - }); - - return match.WasHandled; - } + base.ApplyState(upcomingState.Using(nextData)); - protected override bool ReceiveCommand(object message) - { - var match = PatternMatch.Match(message) - .With(marker => - { - if (_generation == marker.Generation) - { - ProcessMsg(new StateTimeout(), "state timeout"); - } - }) - .With(t => - { - if (_timers.ContainsKey(t.Name) && _timers[t.Name].Generation == t.Generation) - { - if (_timeoutFuture != null) - { - _timeoutFuture.Cancel(false); - _timeoutFuture = null; - } - _generation++; - if (!t.Repeat) + if (upcomingState.AfterTransitionHandler != null) { - _timers.Remove(t.Name); + upcomingState.AfterTransitionHandler(upcomingState.StateData); } - ProcessMsg(t.Message, t); - } - }) - .With(cb => - { - Context.Watch(cb.ActorRef); - Listeners.Add(cb.ActorRef); - //send the current state back as a reference point - cb.ActorRef.Tell(new FSMBase.CurrentState(Self, _currentState.StateName)); - }) - .With(l => - { - Context.Watch(l.Listener); - Listeners.Add(l.Listener); - l.Listener.Tell(new FSMBase.CurrentState(Self, _currentState.StateName)); - }) - .With(ucb => - { - Context.Unwatch(ucb.ActorRef); - Listeners.Remove(ucb.ActorRef); - }) - .With(d => - { - Context.Unwatch(d.Listener); - Listeners.Remove(d.Listener); - }) - .With(_ => { DebugEvent = true; }) - .Default(msg => - { - if (_timeoutFuture != null) - { - _timeoutFuture.Cancel(false); - _timeoutFuture = null; } - _generation++; - ProcessMsg(msg, Sender); }); - return match.WasHandled; + } } } -} - +} \ No newline at end of file diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs b/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs index fa0834ae169..a35a216100b 100644 --- a/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs +++ b/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs @@ -1,22 +1,609 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Akka.Actor; -using Akka.Dispatch.SysMsg; +using Akka.Actor.Internal; using Akka.Event; +using Akka.Persistence.Serialization; +using Akka.Routing; using Akka.Util; +using Akka.Util.Internal; namespace Akka.Persistence.Fsm { - public abstract class PersistentFSMBase : PersistentActor + public abstract class PersistentFSMBase : PersistentActor, IListeners { - #region States + public delegate State StateFunction( + FSMBase.Event fsmEvent, State state = null); + + public delegate void TransitionHandler(TState initialState, TState nextState); + + protected readonly ListenerSupport _listener = new ListenerSupport(); + private readonly ILoggingAdapter _log = Context.GetLogger(); + + /// + /// State definitions + /// + private readonly Dictionary _stateFunctions = new Dictionary(); + + private readonly Dictionary _stateTimeouts = new Dictionary(); + + private readonly AtomicCounter _timerGen = new AtomicCounter(0); + + /// + /// Timer handling + /// + protected readonly IDictionary _timers = new Dictionary(); + + /// + /// Transition handling + /// + private readonly IList _transitionEvent = new List(); + + /// + /// FSM state data and current timeout handling + /// + protected State _currentState; + + protected long _generation; + private StateFunction _handleEvent; + private State _nextState; + + /// + /// Termination handling + /// + private Action> _terminateEvent = @event => { }; + + protected ICancelable _timeoutFuture; + + /// + /// Can be set to enable debugging on certain actions taken by the FSM + /// + protected bool DebugEvent; + + protected PersistentFSMBase() + { + if (this is ILoggingFSM) + DebugEvent = Context.System.Settings.FsmDebugEvent; + } + + /// + /// Current state name + /// + public TState StateName + { + get { return _currentState.StateName; } + } + + /// + /// Current state data + /// + public TData StateData + { + get { return _currentState.StateData; } + } + + /// + /// Return next state data (available in handlers) + /// + public TData NextStateData + { + get + { + if (_nextState == null) + throw new InvalidOperationException("NextStateData is only available during OnTransition"); + return _nextState.StateData; + } + } + + /// + /// Unhandled event handler + /// + private StateFunction HandleEventDefault + { + get + { + return delegate(FSMBase.Event @event, State state) + { + _log.Warning("unhandled event {0} in state {1}", @event.FsmEvent, StateName); + return Stay(); + }; + } + } + + private StateFunction HandleEvent + { + get { return _handleEvent ?? (_handleEvent = HandleEventDefault); } + set { _handleEvent = value; } + } + + public bool IsStateTimerActive { get; } + + public ListenerSupport Listeners + { + get { return _listener; } + } + + /// + /// Insert a new at the end of the processing chain for the + /// given state. If the stateTimeout parameter is set, entering this state without a + /// differing explicit timeout setting will trigger a . + /// + /// designator for the state + /// delegate describing this state's response to input + /// default timeout for this state + public void When(TState stateName, StateFunction func, TimeSpan? timeout = null) + { + Register(stateName, func, timeout); + } + + /// + /// Sets the initial state for this FSM. Call this method from the constructor before the + /// method. + /// If different state is needed after a restart this method, followed by , can be used in the + /// actor + /// life cycle hooks and . + /// + /// Initial state designator. + /// Initial state data. + /// State timeout for the initial state, overriding the default timeout for that state. + public void StartWith(TState stateName, TData stateData, TimeSpan? timeout = null) + { + _currentState = new State(stateName, stateData, timeout); + } + + /// + /// Produce transition to other state. Return this from a state function + /// in order to effect the transition. + /// + /// State designator for the next state + /// State transition descriptor + public State GoTo(TState nextStateName) + { + return new State(nextStateName, _currentState.StateData); + } + + /// + /// Produce transition to other state. Return this from a state function + /// in order to effect the transition. + /// + /// State designator for the next state + /// Data for next state + /// State transition descriptor + public State GoTo(TState nextStateName, TData stateData) + { + return new State(nextStateName, stateData); + } + + /// + /// Produce "empty" transition descriptor. Return this from a state function + /// when no state change is to be effected. + /// + /// Descriptor for staying in the current state. + public State Stay() + { + return GoTo(_currentState.StateName); + } + + /// + /// Produce change descriptor to stop this FSM actor with + /// + public State Stop() + { + return Stop(new FSMBase.Normal()); + } + + /// + /// Produce change descriptor to stop this FSM actor with the specified . + /// + public State Stop(FSMBase.Reason reason) + { + return Stop(reason, _currentState.StateData); + } + + public State Stop(FSMBase.Reason reason, TData stateData) + { + return Stay().Using(stateData).WithStopReason(reason); + } + + /// + /// Schedule named timer to deliver message after given delay, possibly repeating. + /// Any existing timer with the same name will automatically be canceled before adding + /// the new timer. + /// + /// identifier to be used with . + /// message to be delivered + /// delay of first message delivery and between subsequent messages. + /// send once if false, scheduleAtFixedRate if true + public void SetTimer(string name, object msg, TimeSpan timeout, bool repeat = false) + { + if (DebugEvent) + _log.Debug("setting " + (repeat ? "repeating" : "") + "timer '{0}' / {1}: {2}", name, timeout, msg); + if (_timers.ContainsKey(name)) + _timers[name].Cancel(); + var timer = new Timer(name, msg, repeat, _timerGen.Next(), Context, DebugEvent ? _log : null); + timer.Schedule(Self, timeout); + + if (!_timers.ContainsKey(name)) + _timers.Add(name, timer); + else + _timers[name] = timer; + } + + /// + /// Cancel a named , ensuring that the message is not subsequently delivered (no + /// race.) + /// + /// The name of the timer to cancel. + public void CancelTimer(string name) + { + if (DebugEvent) + { + _log.Debug("Cancelling timer {0}", name); + } + + if (_timers.ContainsKey(name)) + { + _timers[name].Cancel(); + _timers.Remove(name); + } + } + + /// + /// Determines whether the named timer is still active. Returns true + /// unless the timer does not exist, has previously been cancelled, or + /// if it was a single-shot timer whose message was already received. + /// + public bool IsTimerActive(string name) + { + return _timers.ContainsKey(name); + } + + /// + /// Set the state timeout explicitly. This method can be safely used from + /// within a state handler. + /// + public void SetStateTimeout(TState state, TimeSpan? timeout) + { + if (!_stateTimeouts.ContainsKey(state)) + _stateTimeouts.Add(state, timeout); + else + _stateTimeouts[state] = timeout; + } + + /// + /// Set handler which is called upon each state transition, i.e. not when + /// staying in the same state. + /// + public void OnTransition(TransitionHandler transitionHandler) + { + _transitionEvent.Add(transitionHandler); + } + + /// + /// Set the handler which is called upon termination of this FSM actor. Calling this + /// method again will overwrite the previous contents. + /// + public void OnTermination(Action> terminationHandler) + { + _terminateEvent = terminationHandler; + } + /// + /// Set handler which is called upon reception of unhandled FSM messages. Calling + /// this method again will overwrite the previous contents. + /// + /// + public void WhenUnhandled(StateFunction stateFunction) + { + HandleEvent = OrElse(stateFunction, HandleEventDefault); + } + /// + /// Verify the existence of initial state and setup timers. This should be the + /// last call within the constructor or and + /// . + /// + public void Initialize() + { + MakeTransition(_currentState); + } + + public TransformHelper Transform(StateFunction func) + { + return new TransformHelper(func); + } + + private void Register(TState name, StateFunction function, TimeSpan? timeout) + { + if (_stateFunctions.ContainsKey(name)) + { + _stateFunctions[name] = OrElse(_stateFunctions[name], function); + _stateTimeouts[name] = _stateTimeouts[name] ?? timeout; + } + else + { + _stateFunctions.Add(name, function); + _stateTimeouts.Add(name, timeout); + } + } + + private void HandleTransition(TState previous, TState next) + { + foreach (var tran in _transitionEvent) + { + tran.Invoke(previous, next); + } + } /// - /// Used in the event of a timeout between transitions + /// C# port of Scala's orElse method for partial function chaining. + /// See http://scalachina.com/api/scala/PartialFunction.html + /// + /// The original to be called + /// The to be called if returns null + /// + /// A which combines both the results of and + /// + /// + private static StateFunction OrElse(StateFunction original, StateFunction fallback) + { + StateFunction chained = delegate(FSMBase.Event @event, State state) + { + var originalResult = original.Invoke(@event, state); + if (originalResult == null) return fallback.Invoke(@event, state); + return originalResult; + }; + + return chained; + } + + protected void ProcessMsg(object any, object source) + { + var fsmEvent = new FSMBase.Event(any, _currentState.StateData); + ProcessEvent(fsmEvent, source); + } + + private void ProcessEvent(FSMBase.Event fsmEvent, object source) + { + if (DebugEvent) + { + var srcStr = GetSourceString(source); + _log.Debug("processing {0} from {1}", fsmEvent, srcStr); + } + var stateFunc = _stateFunctions[_currentState.StateName]; + var oldState = _currentState; + State upcomingState = null; + + if (stateFunc != null) + { + upcomingState = stateFunc(fsmEvent); + } + + if (upcomingState == null) + { + upcomingState = HandleEvent(fsmEvent); + } + + ApplyState(upcomingState); + if (DebugEvent && !Equals(oldState, upcomingState)) + { + _log.Debug("transition {0} -> {1}", oldState, upcomingState); + } + } + + private string GetSourceString(object source) + { + var s = source as string; + if (s != null) return s; + var timer = source as Timer; + if (timer != null) return "timer '" + timer.Name + "'"; + var actorRef = source as IActorRef; + if (actorRef != null) return actorRef.ToString(); + return "unknown"; + } + + + protected virtual void ApplyState(State upcomingState) + { + if (upcomingState.StopReason == null) + { + MakeTransition(upcomingState); + return; + } + var replies = upcomingState.Replies; + replies.Reverse(); + foreach (var reply in replies) + { + Sender.Tell(reply); + } + Terminate(upcomingState); + Context.Stop(Self); + } + + private void MakeTransition(State upcomingState) + { + if (!_stateFunctions.ContainsKey(upcomingState.StateName)) + { + Terminate( + Stay() + .WithStopReason( + new FSMBase.Failure(string.Format("Next state {0} does not exist", upcomingState.StateName)))); + } + else + { + var replies = upcomingState.Replies; + replies.Reverse(); + foreach (var r in replies) + { + Sender.Tell(r); + } + if (!_currentState.StateName.Equals(upcomingState.StateName)) + { + _nextState = upcomingState; + HandleTransition(_currentState.StateName, _nextState.StateName); + Listeners.Gossip(new FSMBase.Transition(Self, _currentState.StateName, _nextState.StateName)); + _nextState = null; + } + _currentState = upcomingState; + var timeout = _currentState.Timeout ?? _stateTimeouts[_currentState.StateName]; + if (timeout.HasValue) + { + var t = timeout.Value; + if (t < TimeSpan.MaxValue) + { + _timeoutFuture = Context.System.Scheduler.ScheduleTellOnceCancelable(t, Context.Self, + new TimeoutMarker(_generation), Context.Self); + } + } + } + } + + protected override bool ReceiveCommand(object message) + { + var match = message.Match() + .With(marker => + { + if (_generation == marker.Generation) + { + ProcessMsg(new StateTimeout(), "state timeout"); + } + }) + .With(t => + { + if (_timers.ContainsKey(t.Name) && _timers[t.Name].Generation == t.Generation) + { + if (_timeoutFuture != null) + { + _timeoutFuture.Cancel(false); + _timeoutFuture = null; + } + _generation++; + if (!t.Repeat) + { + _timers.Remove(t.Name); + } + ProcessMsg(t.Message, t); + } + }) + .With(cb => + { + Context.Watch(cb.ActorRef); + Listeners.Add(cb.ActorRef); + //send the current state back as a reference point + cb.ActorRef.Tell(new FSMBase.CurrentState(Self, _currentState.StateName)); + }) + .With(l => + { + Context.Watch(l.Listener); + Listeners.Add(l.Listener); + l.Listener.Tell(new FSMBase.CurrentState(Self, _currentState.StateName)); + }) + .With(ucb => + { + Context.Unwatch(ucb.ActorRef); + Listeners.Remove(ucb.ActorRef); + }) + .With(d => + { + Context.Unwatch(d.Listener); + Listeners.Remove(d.Listener); + }) + .With(_ => { DebugEvent = true; }) + .Default(msg => + { + if (_timeoutFuture != null) + { + _timeoutFuture.Cancel(false); + _timeoutFuture = null; + } + _generation++; + ProcessMsg(msg, Sender); + }); + return match.WasHandled; + } + + protected void Terminate(State upcomingState) + { + if (_currentState.StopReason == null) + { + var reason = upcomingState.StopReason; + LogTermination(reason); + foreach (var t in _timers) + { + t.Value.Cancel(); + } + _timers.Clear(); + _currentState = upcomingState; + + var stopEvent = new FSMBase.StopEvent(reason, _currentState.StateName, + _currentState.StateData); + _terminateEvent(stopEvent); + } + } + + /// + /// By default, is logged at error level and other + /// reason types are not logged. It is possible to override this behavior. + /// + /// + protected virtual void LogTermination(FSMBase.Reason reason) + { + reason.Match() + .With(f => + { + if (f.Cause is Exception) + { + _log.Error(f.Cause.AsInstanceOf(), "terminating due to Failure"); + } + else + { + _log.Error(f.Cause.ToString()); + } + }); + } + + public sealed class TransformHelper + { + public TransformHelper(StateFunction func) + { + Func = func; + } + + public StateFunction Func { get; } + + public StateFunction Using(Func, State> andThen) + { + StateFunction continuedDelegate = (@event, state) => andThen.Invoke(Func.Invoke(@event, state)); + return continuedDelegate; + } + } + + public class StateChangeEvent : IMessage + { + public StateChangeEvent(TState state, TimeSpan? timeOut) + { + State = state; + TimeOut = timeOut; + } + + public TState State { get; private set; } + + public TimeSpan? TimeOut { get; private set; } + } + + #region States + + /// + /// Used in the event of a timeout between transitions /// public class StateTimeout { @@ -33,13 +620,16 @@ public TimeoutMarker(long generation) Generation = generation; } - public long Generation { get; private set; } + public long Generation { get; } } [DebuggerDisplay("Timer {Name,nq}, message: {Message")] - internal class Timer : INoSerializationVerificationNeeded + public class Timer : INoSerializationVerificationNeeded { private readonly ILoggingAdapter _debugLog; + private readonly ICancelable _ref; + + private readonly IScheduler _scheduler; public Timer(string name, object message, bool repeat, int generation, IActorContext context, ILoggingAdapter debugLog) @@ -55,18 +645,15 @@ public Timer(string name, object message, bool repeat, int generation, IActorCon _ref = new Cancelable(scheduler); } - private readonly IScheduler _scheduler; - private readonly ICancelable _ref; - - public string Name { get; private set; } + public string Name { get; } - public object Message { get; private set; } + public object Message { get; } - public bool Repeat { get; private set; } + public bool Repeat { get; } - public int Generation { get; private set; } + public int Generation { get; } - public IActorContext Context { get; private set; } + public IActorContext Context { get; } public void Schedule(IActorRef actor, TimeSpan timeout) { @@ -98,18 +685,17 @@ public void Cancel() } - /// - /// This captures all of the managed state of the : the state name, - /// the state data, possibly custom timeout, stop reason, and replies accumulated while - /// processing the last message. + /// This captures all of the managed state of the : the state name, + /// the state data, possibly custom timeout, stop reason, and replies accumulated while + /// processing the last message. /// /// The name of the state /// The data of the state /// The event of the state public class State : FSMBase.State { - public Action AfterTransitionHandler { get; private set; } + public Action AfterTransitionHandler { get; } public State(TS stateName, TD stateData, TimeSpan? timeout = null, FSMBase.Reason stopReason = null, @@ -126,7 +712,7 @@ public State(TS stateName, TD stateData, TimeSpan? timeout = null, FSMBase.Reaso public bool Notifies { get; set; } /// - /// Specify domain events to be applied when transitioning to the new state. + /// Specify domain events to be applied when transitioning to the new state. /// /// /// @@ -141,7 +727,7 @@ public State Applying(ILinearSeq events) /// - /// Specify domain event to be applied when transitioning to the new state. + /// Specify domain event to be applied when transitioning to the new state. /// /// /// @@ -149,7 +735,7 @@ public State Applying(TE e) { if (DomainEvents == null) { - return Copy(null, null, null, new ArrayLinearSeq(new TE[] {e})); + return Copy(null, null, null, new ArrayLinearSeq(new[] {e})); } var events = new List(); events.AddRange(DomainEvents); @@ -159,7 +745,7 @@ public State Applying(TE e) /// - /// Register a handler to be triggered after the state has been persisted successfully + /// Register a handler to be triggered after the state has been persisted successfully /// /// /// @@ -171,13 +757,14 @@ public State AndThen(Action handler) public State Copy(TimeSpan? timeout, FSMBase.Reason stopReason = null, List replies = null, ILinearSeq domainEvents = null, Action afterTransitionDo = null) { - return new State(StateName, StateData, timeout ?? Timeout, stopReason ?? StopReason, replies ?? Replies, + return new State(StateName, StateData, timeout ?? Timeout, stopReason ?? StopReason, + replies ?? Replies, domainEvents ?? DomainEvents, afterTransitionDo ?? AfterTransitionHandler); } /// - /// Modify state transition descriptor with new state data. The data will be set - /// when transitioning to the new state. + /// Modify state transition descriptor with new state data. The data will be set + /// when transitioning to the new state. /// public new State Using(TD nextStateData) { @@ -187,28 +774,26 @@ public State Copy(TimeSpan? timeout, FSMBase.Reason stopReason = nul public new State Replying(object replyValue) { - if (Replies == null) Replies = new List(); var newReplies = Replies.ToArray().ToList(); newReplies.Add(replyValue); return Copy(Timeout, replies: newReplies); } - public new State ForMax(TimeSpan timeout) + public new State ForMax(TimeSpan timeout) { if (timeout <= TimeSpan.MaxValue) return Copy(timeout); return Copy(null); } /// - /// INTERNAL API + /// INTERNAL API /// internal State WithStopReason(FSMBase.Reason reason) { return Copy(null, reason); } - #endregion } } From 4b6c6499318f721052d8f7dd05b9e10ce7f29cee Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Sun, 1 Nov 2015 09:22:04 +0400 Subject: [PATCH 070/105] added OnRecoveryCompleted --- .../Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs | 10 ++++++++++ src/core/Akka.Persistence/Fsm/PersistentFSM.cs | 8 +++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs index d41f82a591c..2f9671edc59 100644 --- a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs +++ b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs @@ -455,6 +455,11 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) public override string PersistenceId { get { return _persistenceId; }} + protected override void OnRecoveryCompleted() + { + + } + protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) { if (e is ItemAdded) @@ -510,6 +515,11 @@ public override string PersistenceId } + protected override void OnRecoveryCompleted() + { + + } + protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) { diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs index f526ff0e96e..46b161a8df1 100644 --- a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs +++ b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs @@ -34,10 +34,16 @@ protected override void PostStop() base.PostStop(); } + protected abstract void OnRecoveryCompleted(); + protected override bool ReceiveRecover(object message) { var match = message.Match() - .With(t => { Initialize(); }) + .With(t => + { + Initialize(); + OnRecoveryCompleted(); + }) .With(e => { StartWith(StateName, ApplyEvent(e, StateData)); }) .With(sce => { StartWith(sce.State, StateData, sce.TimeOut); }); From 5d6b95400621b93a69b9ed46a9e0e82f1b227e33 Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Sun, 1 Nov 2015 10:01:43 +0400 Subject: [PATCH 071/105] added data tests --- .../Fsm/PersistentFSMSpec.cs | 92 ++++++++++++++----- .../Akka.Persistence/Fsm/PersistentFSM.cs | 16 +--- .../Akka.Persistence/Fsm/PersistentFSMBase.cs | 18 +++- 3 files changed, 86 insertions(+), 40 deletions(-) diff --git a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs index 2f9671edc59..e15ab45543f 100644 --- a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs +++ b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs @@ -8,11 +8,12 @@ using Akka.Persistence.Fsm; using Akka.TestKit; using Akka.Util; +using Akka.Util.Internal; using Xunit; namespace Akka.Persistence.Tests.Fsm { - public partial class PersistentFSMSpec : PersistenceSpec + public partial class PersistentFSMSpec : PersistenceSpec { private readonly Random _random = new Random(); public PersistentFSMSpec() @@ -47,9 +48,21 @@ public void PersistentFSM_should_has_function_as_regular_fsm() ExpectMsg>(state => state.State == UserState.LookingAround); ExpectMsg(); ExpectMsg>(state => state.From == UserState.LookingAround); - ExpectMsg(); - ExpectMsg(); - ExpectMsg(); + ExpectMsg(cart => + { + return cart.Items.Any(i => i.Name == "Shirt") && cart.Items.Count == 1; + + }); + ExpectMsg(cart => + { + return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; + + }); + ExpectMsg(cart => + { + return cart.Items.Any(i => i.Name == "Coat") && cart.Items.Count == 3; + + }); ExpectMsg>(); ExpectMsg(); ExpectTerminated(fsmRef); @@ -72,9 +85,9 @@ public void PersistentFSM_should_has_function_as_regular_fsm_on_state_timeout() ExpectMsg>(state => { return state.State == UserState.LookingAround; - + }); - + ExpectMsg>(); Within(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1.9), () => @@ -91,7 +104,7 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_data() { var dummyReportActorRef = CreateTestProbe().Ref; - var fsmRef = Sys.ActorOf(Props.Create(()=> new WebStoreCustomerFSM(Name, dummyReportActorRef))); + var fsmRef = Sys.ActorOf(Props.Create(() => new WebStoreCustomerFSM(Name, dummyReportActorRef))); Watch(fsmRef); fsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); @@ -112,10 +125,18 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_data() ExpectMsg>(state => { return state.From == UserState.LookingAround; - + + }); + ExpectMsg(cart => + { + return cart.Items.Any(i => i.Name == "Shirt") && cart.Items.Count == 1; + + }); + ExpectMsg(cart => + { + return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; + }); - ExpectMsg(); - ExpectMsg(); fsmRef.Tell(PoisonPill.Instance); ExpectTerminated(fsmRef); @@ -134,10 +155,18 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_data() ExpectMsg>(state => { return state.State == UserState.Shopping; - + + }); + ExpectMsg(cart => + { + return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; + + }); + ExpectMsg(cart => + { + return cart.Items.Any(i => i.Name == "Coat") && cart.Items.Count == 3; + }); - ExpectMsg(); - ExpectMsg(); ExpectMsg>(); ExpectMsg(); ExpectTerminated(recoveredFsmRef); @@ -361,11 +390,11 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) _reportActor = reportActor; StartWith(UserState.LookingAround, new EmptyShoppingCart()); - When(UserState.LookingAround, (@event,state) => + When(UserState.LookingAround, (@event, state) => { if (@event.FsmEvent is AddItem) { - var addItem = (AddItem) @event.FsmEvent; + var addItem = (AddItem)@event.FsmEvent; return GoTo(UserState.Shopping) .Applying(new ItemAdded(addItem.Item)).ForMax(TimeSpan.FromSeconds(1)); @@ -382,7 +411,7 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) { if (@event.FsmEvent is AddItem) { - var addItem = ((AddItem) @event.FsmEvent); + var addItem = ((AddItem)@event.FsmEvent); return Stay().Applying(new ItemAdded(addItem.Item)).ForMax(TimeSpan.FromSeconds(1)); } if (@event.FsmEvent is Buy) @@ -421,7 +450,7 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) { if (@event.FsmEvent is AddItem) { - var addItem = (AddItem) @event.FsmEvent; + var addItem = (AddItem)@event.FsmEvent; return GoTo(UserState.Shopping) .Applying(new ItemAdded(addItem.Item)) @@ -452,19 +481,19 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) }); } - public override string PersistenceId { get { return _persistenceId; }} + public override string PersistenceId { get { return _persistenceId; } } protected override void OnRecoveryCompleted() { - + } protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) { if (e is ItemAdded) { - var itemAdded = (ItemAdded) e; + var itemAdded = (ItemAdded)e; return data.AddItem(itemAdded.Item); } if (e is OrderExecuted) @@ -495,7 +524,7 @@ public SimpleTransitionFSM(string persistenceId, IActorRef reportActor) When(UserState.LookingAround, (@event, state) => { - if ((string) @event.FsmEvent == "stay") + if ((string)@event.FsmEvent == "stay") { return Stay(); } @@ -562,7 +591,7 @@ protected override bool ReceiveCommand(object message) } #region Custome States -internal enum UserState + internal enum UserState { Shopping, Inactive, @@ -592,25 +621,37 @@ internal interface IShoppingCart { IShoppingCart AddItem(Item item); IShoppingCart Empty(); + ICollection Items { get; set; } + } internal class EmptyShoppingCart : IShoppingCart { public IShoppingCart AddItem(Item item) { - return new NonEmptyShoppingCart(); + return new NonEmptyShoppingCart(item); } public IShoppingCart Empty() { return this; } + + public ICollection Items { get; set; } } internal class NonEmptyShoppingCart : IShoppingCart { + + public NonEmptyShoppingCart(Item item) + { + Items = new List(); + Items.Add(item); + } + public IShoppingCart AddItem(Item item) { + Items.Add(item); return this; } @@ -618,6 +659,9 @@ public IShoppingCart Empty() { return new EmptyShoppingCart(); } + + public ICollection Items { get; set; } + } #endregion @@ -665,7 +709,7 @@ public ItemAdded(Item item) Item = item; } - public Item Item { get; } + public Item Item { get; private set; } } internal class OrderExecuted : IDomainEvent diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs index 46b161a8df1..f370b3cfcc1 100644 --- a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs +++ b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs @@ -18,21 +18,7 @@ namespace Akka.Persistence.Fsm /// The event data type public abstract class PersistentFSM : PersistentFSMBase { - /// - /// Call the hook if you want to retain this behavior. - /// When overriding make sure to call base.PostStop(); - /// Please note that this method is called by default from so - /// override that one if shall not be called during restart. - /// - protected override void PostStop() - { - /* - * Setting this instance's state to Terminated does no harm during restart, since - * the new instance will initialize fresh using StartWith. - */ - Terminate(Stay().WithStopReason(new FSMBase.Shutdown())); - base.PostStop(); - } + protected abstract void OnRecoveryCompleted(); diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs b/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs index a35a216100b..30ac0cdd154 100644 --- a/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs +++ b/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs @@ -50,7 +50,7 @@ public delegate State StateFunction( /// /// FSM state data and current timeout handling - /// + /// a protected State _currentState; protected long _generation; @@ -550,6 +550,22 @@ protected void Terminate(State upcomingState) } } + /// + /// Call the hook if you want to retain this behavior. + /// When overriding make sure to call base.PostStop(); + /// Please note that this method is called by default from so + /// override that one if shall not be called during restart. + /// + protected override void PostStop() + { + /* + * Setting this instance's state to Terminated does no harm during restart, since + * the new instance will initialize fresh using StartWith. + */ + Terminate(Stay().WithStopReason(new FSMBase.Shutdown())); + base.PostStop(); + } + /// /// By default, is logged at error level and other /// reason types are not logged. It is possible to override this behavior. From d2668c67c3c3acb0a374b3dda239d4e4d4fe839c Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Sun, 1 Nov 2015 10:03:11 +0400 Subject: [PATCH 072/105] cleanup --- .../Fsm/PersistentFSMSpec.cs | 236 ++++++------------ .../Akka.Persistence/Fsm/PersistentFSM.cs | 3 - .../Akka.Persistence/Fsm/PersistentFSMBase.cs | 3 +- 3 files changed, 79 insertions(+), 163 deletions(-) diff --git a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs index e15ab45543f..7e88792b9b0 100644 --- a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs +++ b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs @@ -1,23 +1,18 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Akka.Actor; -using Akka.Dispatch.SysMsg; using Akka.Persistence.Fsm; -using Akka.TestKit; -using Akka.Util; -using Akka.Util.Internal; using Xunit; namespace Akka.Persistence.Tests.Fsm { - public partial class PersistentFSMSpec : PersistenceSpec + public class PersistentFSMSpec : PersistenceSpec { private readonly Random _random = new Random(); + public PersistentFSMSpec() - : base(PersistenceSpec.Configuration("inmem", "PersistentFSMSpec")) + : base(Configuration("inmem", "PersistentFSMSpec")) { } @@ -48,21 +43,12 @@ public void PersistentFSM_should_has_function_as_regular_fsm() ExpectMsg>(state => state.State == UserState.LookingAround); ExpectMsg(); ExpectMsg>(state => state.From == UserState.LookingAround); - ExpectMsg(cart => - { - return cart.Items.Any(i => i.Name == "Shirt") && cart.Items.Count == 1; - - }); - ExpectMsg(cart => - { - return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; - - }); - ExpectMsg(cart => - { - return cart.Items.Any(i => i.Name == "Coat") && cart.Items.Count == 3; - - }); + ExpectMsg( + cart => { return cart.Items.Any(i => i.Name == "Shirt") && cart.Items.Count == 1; }); + ExpectMsg( + cart => { return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; }); + ExpectMsg( + cart => { return cart.Items.Any(i => i.Name == "Coat") && cart.Items.Count == 3; }); ExpectMsg>(); ExpectMsg(); ExpectTerminated(fsmRef); @@ -82,11 +68,7 @@ public void PersistentFSM_should_has_function_as_regular_fsm_on_state_timeout() var shirt = new Item("1", "Shirt", 59.99F); fsmRef.Tell(new AddItem(shirt)); - ExpectMsg>(state => - { - return state.State == UserState.LookingAround; - - }); + ExpectMsg>(state => { return state.State == UserState.LookingAround; }); ExpectMsg>(); @@ -122,21 +104,11 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_data() ExpectMsg>(); ExpectMsg(); - ExpectMsg>(state => - { - return state.From == UserState.LookingAround; - - }); - ExpectMsg(cart => - { - return cart.Items.Any(i => i.Name == "Shirt") && cart.Items.Count == 1; - - }); - ExpectMsg(cart => - { - return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; - - }); + ExpectMsg>(state => { return state.From == UserState.LookingAround; }); + ExpectMsg( + cart => { return cart.Items.Any(i => i.Name == "Shirt") && cart.Items.Count == 1; }); + ExpectMsg( + cart => { return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; }); fsmRef.Tell(PoisonPill.Instance); ExpectTerminated(fsmRef); @@ -152,21 +124,11 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_data() recoveredFsmRef.Tell(new GetCurrentCart()); recoveredFsmRef.Tell(new Leave()); - ExpectMsg>(state => - { - return state.State == UserState.Shopping; - - }); - ExpectMsg(cart => - { - return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; - - }); - ExpectMsg(cart => - { - return cart.Items.Any(i => i.Name == "Coat") && cart.Items.Count == 3; - - }); + ExpectMsg>(state => { return state.State == UserState.Shopping; }); + ExpectMsg( + cart => { return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; }); + ExpectMsg( + cart => { return cart.Items.Any(i => i.Name == "Coat") && cart.Items.Count == 3; }); ExpectMsg>(); ExpectMsg(); ExpectTerminated(recoveredFsmRef); @@ -192,18 +154,11 @@ public void PersistentFSM_should_execute_the_defined_actions_following_successfu fsmRef.Tell(new Buy()); fsmRef.Tell(new Leave()); - ExpectMsg>(state => - { - return state.State == UserState.LookingAround; - }); - ExpectMsg>(state => - { - return state.From == UserState.LookingAround && state.To == UserState.Shopping; - }); - ExpectMsg>(state => - { - return state.From == UserState.Shopping && state.To == UserState.Paid; - }); + ExpectMsg>(state => { return state.State == UserState.LookingAround; }); + ExpectMsg>( + state => { return state.From == UserState.LookingAround && state.To == UserState.Shopping; }); + ExpectMsg>( + state => { return state.From == UserState.Shopping && state.To == UserState.Paid; }); reportActorProbe.ExpectMsg(); ExpectTerminated(fsmRef); } @@ -227,14 +182,9 @@ public void PersistentFSM_should_execute_the_defined_actions_following_successfu fsmRef.Tell(new AddItem(coat)); fsmRef.Tell(new Leave()); - ExpectMsg>(state => - { - return state.State == UserState.LookingAround; - }); - ExpectMsg>(state => - { - return state.From == UserState.LookingAround && state.To == UserState.Shopping; - }); + ExpectMsg>(state => { return state.State == UserState.LookingAround; }); + ExpectMsg>( + state => { return state.From == UserState.LookingAround && state.To == UserState.Shopping; }); reportActorProbe.ExpectMsg(); ExpectTerminated(fsmRef); } @@ -253,15 +203,9 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_timeout fsmRef.Tell(new AddItem(shirt)); - ExpectMsg>(state => - { - return state.State == UserState.LookingAround; - }); - ExpectMsg>(state => - { - return state.From == UserState.LookingAround && state.To == UserState.Shopping; - - }); + ExpectMsg>(state => { return state.State == UserState.LookingAround; }); + ExpectMsg>( + state => { return state.From == UserState.LookingAround && state.To == UserState.Shopping; }); ExpectNoMsg(TimeSpan.FromSeconds(0.6)); fsmRef.Tell(PoisonPill.Instance); @@ -271,18 +215,13 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_timeout Watch(recoveredFsmRef); recoveredFsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); - ExpectMsg>(state => - { - return state.State == UserState.Shopping; - }); + ExpectMsg>(state => { return state.State == UserState.Shopping; }); Within(TimeSpan.FromSeconds(0.9), TimeSpan.FromSeconds(1.9), () => { - ExpectMsg>(state => - { - return state.From == UserState.Shopping && state.To == UserState.Inactive; - }); + ExpectMsg>( + state => { return state.From == UserState.Shopping && state.To == UserState.Inactive; }); return true; }); ExpectNoMsg(TimeSpan.FromSeconds(0.6)); @@ -292,10 +231,7 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_timeout recoveredFsmRef = Sys.ActorOf(Props.Create(() => new WebStoreCustomerFSM(Name, dummyReportActorRef))); Watch(recoveredFsmRef); recoveredFsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); - ExpectMsg>(state => - { - return state.State == UserState.Inactive; - }); + ExpectMsg>(state => { return state.State == UserState.Inactive; }); ExpectTerminated(recoveredFsmRef); } @@ -355,38 +291,35 @@ public void PersistentFSM_should_not_persist_state_change_event_when_staying_in_ var persistentEventsStreamer = Sys.ActorOf(Props.Create(Name, TestActor), Name); ExpectMsg(); - ExpectMsg.StateChangeEvent>(); + ExpectMsg.StateChangeEvent>(); ExpectMsg(); - ExpectMsg.StateChangeEvent>(); + ExpectMsg.StateChangeEvent>(); ExpectMsg(); - ExpectMsg.StateChangeEvent>(); + ExpectMsg.StateChangeEvent>(); ExpectMsg(); - ExpectMsg.StateChangeEvent>(); + ExpectMsg.StateChangeEvent>(); Watch(persistentEventsStreamer); persistentEventsStreamer.Tell(PoisonPill.Instance); ExpectTerminated(persistentEventsStreamer); - } - internal class WebStoreCustomerFSM : PersistentFSM { - private readonly string _persistenceId; private readonly IActorRef _reportActor; public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) { - _persistenceId = persistenceId; + PersistenceId = persistenceId; _reportActor = reportActor; StartWith(UserState.LookingAround, new EmptyShoppingCart()); @@ -394,7 +327,7 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) { if (@event.FsmEvent is AddItem) { - var addItem = (AddItem)@event.FsmEvent; + var addItem = (AddItem) @event.FsmEvent; return GoTo(UserState.Shopping) .Applying(new ItemAdded(addItem.Item)).ForMax(TimeSpan.FromSeconds(1)); @@ -411,7 +344,7 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) { if (@event.FsmEvent is AddItem) { - var addItem = ((AddItem)@event.FsmEvent); + var addItem = ((AddItem) @event.FsmEvent); return Stay().Applying(new ItemAdded(addItem.Item)).ForMax(TimeSpan.FromSeconds(1)); } if (@event.FsmEvent is Buy) @@ -429,10 +362,10 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) } if (@event.FsmEvent is Leave) { - return Stop().Applying(new OrderDiscarded()).AndThen(cart => - { - _reportActor.Tell(new ShoppingCardDiscarded()); - }); + return + Stop() + .Applying(new OrderDiscarded()) + .AndThen(cart => { _reportActor.Tell(new ShoppingCardDiscarded()); }); } if (@event.FsmEvent is GetCurrentCart) { @@ -450,7 +383,7 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) { if (@event.FsmEvent is AddItem) { - var addItem = (AddItem)@event.FsmEvent; + var addItem = (AddItem) @event.FsmEvent; return GoTo(UserState.Shopping) .Applying(new ItemAdded(addItem.Item)) @@ -459,10 +392,10 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) if (@event.FsmEvent is StateTimeout) { //var addItem = ((AddItem)@event) - return Stop().Applying(new OrderDiscarded()).AndThen(cart => - { - _reportActor.Tell(new ShoppingCardDiscarded()); - }); + return + Stop() + .Applying(new OrderDiscarded()) + .AndThen(cart => { _reportActor.Tell(new ShoppingCardDiscarded()); }); } return state; }); @@ -481,19 +414,18 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) }); } - public override string PersistenceId { get { return _persistenceId; } } + public override string PersistenceId { get; } protected override void OnRecoveryCompleted() { - } protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) { if (e is ItemAdded) { - var itemAdded = (ItemAdded)e; + var itemAdded = (ItemAdded) e; return data.AddItem(itemAdded.Item); } if (e is OrderExecuted) @@ -508,71 +440,53 @@ protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) return data; } } - } internal class SimpleTransitionFSM : PersistentFSM { - private readonly string _persistenceId; private readonly IActorRef _reportActor; public SimpleTransitionFSM(string persistenceId, IActorRef reportActor) { - _persistenceId = persistenceId; + PersistenceId = persistenceId; _reportActor = reportActor; StartWith(UserState.LookingAround, new EmptyShoppingCart()); When(UserState.LookingAround, (@event, state) => { - if ((string)@event.FsmEvent == "stay") + if ((string) @event.FsmEvent == "stay") { return Stay(); } return GoTo(UserState.LookingAround); }); - OnTransition((state, nextState) => - { - _reportActor.Tell(string.Format("{0} -> {1}", state, nextState)); - }); - - + OnTransition((state, nextState) => { _reportActor.Tell(string.Format("{0} -> {1}", state, nextState)); }); } - public override string PersistenceId - { - get { return _persistenceId; } - } + public override string PersistenceId { get; } protected override void OnRecoveryCompleted() { - } protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) { - return data; } - - } internal class PersistentEventsStreamer : PersistentActor { - private readonly string _persistenceId; private readonly IActorRef _client; public PersistentEventsStreamer(string persistenceId, IActorRef client) { - _persistenceId = persistenceId; + PersistenceId = persistenceId; _client = client; } - public override string PersistenceId - { - get { return _persistenceId; } - } + public override string PersistenceId { get; } protected override bool ReceiveRecover(object message) { @@ -591,6 +505,7 @@ protected override bool ReceiveCommand(object message) } #region Custome States + internal enum UserState { Shopping, @@ -605,24 +520,23 @@ internal enum UserState internal class Item { - public string Id { get; } - public string Name { get; } - public float Price { get; } - public Item(string id, string name, float price) { Id = id; Name = name; Price = price; } + + public string Id { get; } + public string Name { get; } + public float Price { get; } } internal interface IShoppingCart { + ICollection Items { get; set; } IShoppingCart AddItem(Item item); IShoppingCart Empty(); - ICollection Items { get; set; } - } internal class EmptyShoppingCart : IShoppingCart @@ -642,7 +556,6 @@ public IShoppingCart Empty() internal class NonEmptyShoppingCart : IShoppingCart { - public NonEmptyShoppingCart(Item item) { Items = new List(); @@ -661,7 +574,6 @@ public IShoppingCart Empty() } public ICollection Items { get; set; } - } #endregion @@ -670,7 +582,6 @@ public IShoppingCart Empty() internal interface ICommand { - } internal class AddItem : ICommand @@ -686,20 +597,21 @@ public AddItem(Item item) internal class Buy { } + internal class Leave { } + internal class GetCurrentCart : ICommand { } #endregion - #region Customer domain events + internal interface IDomainEvent { - } internal class ItemAdded : IDomainEvent @@ -709,26 +621,32 @@ public ItemAdded(Item item) Item = item; } - public Item Item { get; private set; } + public Item Item { get; } } internal class OrderExecuted : IDomainEvent { } + internal class OrderDiscarded : IDomainEvent { } + #endregion + #region Side effects - report events to be sent to some + internal interface IReportEvent { - } + internal class PurchaseWasMade : IReportEvent { } + internal class ShoppingCardDiscarded : IReportEvent { } + #endregion -} +} \ No newline at end of file diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs index f370b3cfcc1..7295b1c28bb 100644 --- a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs +++ b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs @@ -6,7 +6,6 @@ //----------------------------------------------------------------------- using System.Collections.Generic; -using Akka.Actor; namespace Akka.Persistence.Fsm { @@ -18,8 +17,6 @@ namespace Akka.Persistence.Fsm /// The event data type public abstract class PersistentFSM : PersistentFSMBase { - - protected abstract void OnRecoveryCompleted(); protected override bool ReceiveRecover(object message) diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs b/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs index 30ac0cdd154..2c3116f4a10 100644 --- a/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs +++ b/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs @@ -50,7 +50,8 @@ public delegate State StateFunction( /// /// FSM state data and current timeout handling - /// a + /// + /// a protected State _currentState; protected long _generation; From 30e4142547e0cc492a828fc15c9bf86182dc00bb Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Mon, 2 Nov 2015 12:58:23 +0400 Subject: [PATCH 073/105] fix c# version --- .../Fsm/PersistentFSMSpec.cs | 78 +++++++++++-------- .../Akka.Persistence/Fsm/PersistentFSM.cs | 4 +- .../Akka.Persistence/Fsm/PersistentFSMBase.cs | 20 ++--- 3 files changed, 57 insertions(+), 45 deletions(-) diff --git a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs index 7e88792b9b0..1c021fdafac 100644 --- a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs +++ b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs @@ -44,11 +44,11 @@ public void PersistentFSM_should_has_function_as_regular_fsm() ExpectMsg(); ExpectMsg>(state => state.From == UserState.LookingAround); ExpectMsg( - cart => { return cart.Items.Any(i => i.Name == "Shirt") && cart.Items.Count == 1; }); + cart => cart.Items.Any(i => i.Name == "Shirt") && cart.Items.Count == 1); ExpectMsg( - cart => { return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; }); + cart => cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2); ExpectMsg( - cart => { return cart.Items.Any(i => i.Name == "Coat") && cart.Items.Count == 3; }); + cart => cart.Items.Any(i => i.Name == "Coat") && cart.Items.Count == 3); ExpectMsg>(); ExpectMsg(); ExpectTerminated(fsmRef); @@ -68,7 +68,7 @@ public void PersistentFSM_should_has_function_as_regular_fsm_on_state_timeout() var shirt = new Item("1", "Shirt", 59.99F); fsmRef.Tell(new AddItem(shirt)); - ExpectMsg>(state => { return state.State == UserState.LookingAround; }); + ExpectMsg>(state => state.State == UserState.LookingAround); ExpectMsg>(); @@ -104,11 +104,11 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_data() ExpectMsg>(); ExpectMsg(); - ExpectMsg>(state => { return state.From == UserState.LookingAround; }); + ExpectMsg>(state => state.From == UserState.LookingAround); ExpectMsg( - cart => { return cart.Items.Any(i => i.Name == "Shirt") && cart.Items.Count == 1; }); + cart => cart.Items.Any(i => i.Name == "Shirt") && cart.Items.Count == 1); ExpectMsg( - cart => { return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; }); + cart => cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2); fsmRef.Tell(PoisonPill.Instance); ExpectTerminated(fsmRef); @@ -124,11 +124,11 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_data() recoveredFsmRef.Tell(new GetCurrentCart()); recoveredFsmRef.Tell(new Leave()); - ExpectMsg>(state => { return state.State == UserState.Shopping; }); + ExpectMsg>(state => state.State == UserState.Shopping); ExpectMsg( - cart => { return cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2; }); + cart => cart.Items.Any(i => i.Name == "Shoes") && cart.Items.Count == 2); ExpectMsg( - cart => { return cart.Items.Any(i => i.Name == "Coat") && cart.Items.Count == 3; }); + cart => cart.Items.Any(i => i.Name == "Coat") && cart.Items.Count == 3); ExpectMsg>(); ExpectMsg(); ExpectTerminated(recoveredFsmRef); @@ -154,11 +154,11 @@ public void PersistentFSM_should_execute_the_defined_actions_following_successfu fsmRef.Tell(new Buy()); fsmRef.Tell(new Leave()); - ExpectMsg>(state => { return state.State == UserState.LookingAround; }); + ExpectMsg>(state => state.State == UserState.LookingAround); ExpectMsg>( - state => { return state.From == UserState.LookingAround && state.To == UserState.Shopping; }); + state => state.From == UserState.LookingAround && state.To == UserState.Shopping); ExpectMsg>( - state => { return state.From == UserState.Shopping && state.To == UserState.Paid; }); + state => state.From == UserState.Shopping && state.To == UserState.Paid); reportActorProbe.ExpectMsg(); ExpectTerminated(fsmRef); } @@ -182,9 +182,9 @@ public void PersistentFSM_should_execute_the_defined_actions_following_successfu fsmRef.Tell(new AddItem(coat)); fsmRef.Tell(new Leave()); - ExpectMsg>(state => { return state.State == UserState.LookingAround; }); + ExpectMsg>(state => state.State == UserState.LookingAround); ExpectMsg>( - state => { return state.From == UserState.LookingAround && state.To == UserState.Shopping; }); + state => state.From == UserState.LookingAround && state.To == UserState.Shopping); reportActorProbe.ExpectMsg(); ExpectTerminated(fsmRef); } @@ -203,9 +203,9 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_timeout fsmRef.Tell(new AddItem(shirt)); - ExpectMsg>(state => { return state.State == UserState.LookingAround; }); + ExpectMsg>(state => state.State == UserState.LookingAround); ExpectMsg>( - state => { return state.From == UserState.LookingAround && state.To == UserState.Shopping; }); + state => state.From == UserState.LookingAround && state.To == UserState.Shopping); ExpectNoMsg(TimeSpan.FromSeconds(0.6)); fsmRef.Tell(PoisonPill.Instance); @@ -215,7 +215,7 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_timeout Watch(recoveredFsmRef); recoveredFsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); - ExpectMsg>(state => { return state.State == UserState.Shopping; }); + ExpectMsg>(state => state.State == UserState.Shopping); Within(TimeSpan.FromSeconds(0.9), TimeSpan.FromSeconds(1.9), () => @@ -231,7 +231,7 @@ public void PersistentFSM_should_recover_successfully_with_correct_state_timeout recoveredFsmRef = Sys.ActorOf(Props.Create(() => new WebStoreCustomerFSM(Name, dummyReportActorRef))); Watch(recoveredFsmRef); recoveredFsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); - ExpectMsg>(state => { return state.State == UserState.Inactive; }); + ExpectMsg>(state => state.State == UserState.Inactive); ExpectTerminated(recoveredFsmRef); } @@ -316,10 +316,11 @@ public void PersistentFSM_should_not_persist_state_change_event_when_staying_in_ internal class WebStoreCustomerFSM : PersistentFSM { private readonly IActorRef _reportActor; + private readonly string _persistenceId; public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) { - PersistenceId = persistenceId; + _persistenceId = persistenceId; _reportActor = reportActor; StartWith(UserState.LookingAround, new EmptyShoppingCart()); @@ -365,7 +366,7 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) return Stop() .Applying(new OrderDiscarded()) - .AndThen(cart => { _reportActor.Tell(new ShoppingCardDiscarded()); }); + .AndThen(cart => _reportActor.Tell(new ShoppingCardDiscarded())); } if (@event.FsmEvent is GetCurrentCart) { @@ -395,7 +396,7 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) return Stop() .Applying(new OrderDiscarded()) - .AndThen(cart => { _reportActor.Tell(new ShoppingCardDiscarded()); }); + .AndThen(cart => _reportActor.Tell(new ShoppingCardDiscarded())); } return state; }); @@ -414,7 +415,10 @@ public WebStoreCustomerFSM(string persistenceId, IActorRef reportActor) }); } - public override string PersistenceId { get; } + public override string PersistenceId + { + get { return _persistenceId; } + } protected override void OnRecoveryCompleted() @@ -445,10 +449,11 @@ protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) internal class SimpleTransitionFSM : PersistentFSM { private readonly IActorRef _reportActor; + private readonly string _persistenceId; public SimpleTransitionFSM(string persistenceId, IActorRef reportActor) { - PersistenceId = persistenceId; + _persistenceId = persistenceId; _reportActor = reportActor; StartWith(UserState.LookingAround, new EmptyShoppingCart()); @@ -460,10 +465,13 @@ public SimpleTransitionFSM(string persistenceId, IActorRef reportActor) } return GoTo(UserState.LookingAround); }); - OnTransition((state, nextState) => { _reportActor.Tell(string.Format("{0} -> {1}", state, nextState)); }); + OnTransition((state, nextState) => _reportActor.Tell(string.Format("{0} -> {1}", state, nextState))); } - public override string PersistenceId { get; } + public override string PersistenceId + { + get { return _persistenceId; } + } protected override void OnRecoveryCompleted() @@ -479,14 +487,18 @@ protected override IShoppingCart ApplyEvent(IDomainEvent e, IShoppingCart data) internal class PersistentEventsStreamer : PersistentActor { private readonly IActorRef _client; + private readonly string _persistenceId; public PersistentEventsStreamer(string persistenceId, IActorRef client) { - PersistenceId = persistenceId; + _persistenceId = persistenceId; _client = client; } - public override string PersistenceId { get; } + public override string PersistenceId + { + get { return _persistenceId; } + } protected override bool ReceiveRecover(object message) { @@ -527,9 +539,9 @@ public Item(string id, string name, float price) Price = price; } - public string Id { get; } - public string Name { get; } - public float Price { get; } + public string Id { get; private set; } + public string Name { get; private set; } + public float Price { get; private set; } } internal interface IShoppingCart @@ -591,7 +603,7 @@ public AddItem(Item item) Item = item; } - public Item Item { get; } + public Item Item { get; private set; } } internal class Buy @@ -621,7 +633,7 @@ public ItemAdded(Item item) Item = item; } - public Item Item { get; } + public Item Item { get; private set; } } internal class OrderExecuted : IDomainEvent diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs index 7295b1c28bb..4e32617a303 100644 --- a/src/core/Akka.Persistence/Fsm/PersistentFSM.cs +++ b/src/core/Akka.Persistence/Fsm/PersistentFSM.cs @@ -27,8 +27,8 @@ protected override bool ReceiveRecover(object message) Initialize(); OnRecoveryCompleted(); }) - .With(e => { StartWith(StateName, ApplyEvent(e, StateData)); }) - .With(sce => { StartWith(sce.State, StateData, sce.TimeOut); }); + .With(e => StartWith(StateName, ApplyEvent(e, StateData))) + .With(sce => StartWith(sce.State, StateData, sce.TimeOut)); return match.WasHandled; } diff --git a/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs b/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs index 2c3116f4a10..fa8a2a1ac58 100644 --- a/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs +++ b/src/core/Akka.Persistence/Fsm/PersistentFSMBase.cs @@ -126,7 +126,7 @@ private StateFunction HandleEvent set { _handleEvent = value; } } - public bool IsStateTimerActive { get; } + public bool IsStateTimerActive { get; private set; } public ListenerSupport Listeners { @@ -595,7 +595,7 @@ public TransformHelper(StateFunction func) Func = func; } - public StateFunction Func { get; } + public StateFunction Func { get; private set; } public StateFunction Using(Func, State> andThen) { @@ -637,7 +637,7 @@ public TimeoutMarker(long generation) Generation = generation; } - public long Generation { get; } + public long Generation { get; private set; } } [DebuggerDisplay("Timer {Name,nq}, message: {Message")] @@ -662,15 +662,15 @@ public Timer(string name, object message, bool repeat, int generation, IActorCon _ref = new Cancelable(scheduler); } - public string Name { get; } + public string Name { get; private set; } - public object Message { get; } + public object Message { get; private set; } - public bool Repeat { get; } + public bool Repeat { get; private set; } - public int Generation { get; } + public int Generation { get; private set; } - public IActorContext Context { get; } + public IActorContext Context { get; private set; } public void Schedule(IActorRef actor, TimeSpan timeout) { @@ -712,7 +712,7 @@ public void Cancel() /// The event of the state public class State : FSMBase.State { - public Action AfterTransitionHandler { get; } + public Action AfterTransitionHandler { get; private set; } public State(TS stateName, TD stateData, TimeSpan? timeout = null, FSMBase.Reason stopReason = null, @@ -724,7 +724,7 @@ public State(TS stateName, TD stateData, TimeSpan? timeout = null, FSMBase.Reaso Notifies = true; } - public ILinearSeq DomainEvents { get; } + public ILinearSeq DomainEvents { get; private set; } public bool Notifies { get; set; } From aae048c24c121964940564fdb78e268e38ad5e17 Mon Sep 17 00:00:00 2001 From: tintoy Date: Tue, 3 Nov 2015 20:22:19 +1100 Subject: [PATCH 074/105] Implement enumerator for Composite ByteString. --- src/core/Akka/Util/ByteString.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/Akka/Util/ByteString.cs b/src/core/Akka/Util/ByteString.cs index 5cf6d722fbf..72d724a361f 100644 --- a/src/core/Akka/Util/ByteString.cs +++ b/src/core/Akka/Util/ByteString.cs @@ -273,7 +273,12 @@ public override ByteIterator Iterator() _byteStrings.Select(x => (ByteIterator.ByteArrayIterator) x.Iterator()).ToArray()); } - public override ByteString Concat(ByteString that) + public override IEnumerator GetEnumerator() + { + return _byteStrings.SelectMany(byteString => byteString).GetEnumerator(); + } + + public override ByteString Concat(ByteString that) { if (that.IsEmpty) { From b11dafc86eb9284c2d515fd9da3599fe463a5681 Mon Sep 17 00:00:00 2001 From: Bartosz Sypytkowski Date: Tue, 3 Nov 2015 22:50:36 +0100 Subject: [PATCH 075/105] Become and BecomeStacked for ReceivePersistentActor --- .../Akka.Persistence.Tests.csproj | 3 + .../ReceivePersistentActorTests.cs | 262 ++++++++++++++++++ .../ReceivePersistentActorTests_Become.cs | 146 ++++++++++ .../ReceivePersistentActorTests_LifeCycle.cs | 87 ++++++ src/core/Akka.Persistence/PersistentActor.cs | 37 +++ src/core/Akka/Actor/ActorBase.cs | 2 +- 6 files changed, 536 insertions(+), 1 deletion(-) create mode 100644 src/core/Akka.Persistence.Tests/ReceivePersistentActorTests.cs create mode 100644 src/core/Akka.Persistence.Tests/ReceivePersistentActorTests_Become.cs create mode 100644 src/core/Akka.Persistence.Tests/ReceivePersistentActorTests_LifeCycle.cs diff --git a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj index 5c1f6a1f2e9..5ad55a04a87 100644 --- a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj +++ b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj @@ -72,6 +72,9 @@ + + + diff --git a/src/core/Akka.Persistence.Tests/ReceivePersistentActorTests.cs b/src/core/Akka.Persistence.Tests/ReceivePersistentActorTests.cs new file mode 100644 index 00000000000..c6dc508138e --- /dev/null +++ b/src/core/Akka.Persistence.Tests/ReceivePersistentActorTests.cs @@ -0,0 +1,262 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using Akka.Actor; +using Akka.Event; +using Akka.TestKit; +using Akka.Util.Internal; +using Xunit; +using Xunit.Abstractions; + +namespace Akka.Persistence.Tests +{ + + public partial class ReceivePersistentActorTests : AkkaSpec + { + public ReceivePersistentActorTests(ITestOutputHelper output = null) : base(output: output) + { + } + + [Fact] + public void Given_persistent_actor_with_no_receive_command_specified_When_receiving_message_Then_it_should_be_unhandled() + { + //Given + var pid = "p-1"; + WriteEvents(pid, 1, 2, 3); + var actor = Sys.ActorOf(Props.Create(() => new NoCommandActor(pid)), "no-receive-specified"); + Sys.EventStream.Subscribe(TestActor, typeof(UnhandledMessage)); + + //When + actor.Tell("Something"); + + //Then + ExpectMsg(m => ((string)m.Message) == "Something" && Equals(m.Recipient, actor)); + Sys.EventStream.Unsubscribe(TestActor, typeof(UnhandledMessage)); + } + + [Fact] + public void Given_persistent_actor_with_no_receive_event_specified_When_receiving_message_Then_it_should_be_unhandled() + { + //Given + var pid = "p-2"; + WriteEvents(pid, "Something"); + + // when + var actor = Sys.ActorOf(Props.Create(() => new NoEventActor(pid)), "no-receive-specified"); + Sys.EventStream.Subscribe(TestActor, typeof(UnhandledMessage)); + + //Then + ExpectMsg(m => ((string)m.Message) == "Something" && Equals(m.Recipient, actor)); + Sys.EventStream.Unsubscribe(TestActor, typeof(UnhandledMessage)); + } + + [Fact] + public void Test_that_persistent_actor_cannot_call_receive_command_or_receive_event_out_of_construction_and_become() + { + //Given + var pid = "p-3"; + WriteEvents(pid, 1, 2, 3); + var actor = Sys.ActorOf(Props.Create(() => new CallReceiveWhenHandlingMessageActor(pid)),"receive-on-handling-message"); + + //When + actor.Tell("Something that will trigger the actor do call Receive", TestActor); + + //Then + //We expect a exception was thrown when the actor called Receive, and that it was sent back to us + ExpectMsg(); + } + + [Fact] + public void Given_a_persistent_actor_which_uses_predicates_When_sending_different_messages_Then_correct_handler_should_be_invoked() + { + //Given + var pid = "p-4"; + WriteEvents(pid, 1, 2, 3); + var actor = Sys.ActorOf(Props.Create(() => new IntPredicatesActor(pid)) , "predicates"); + + //When + actor.Tell(0, TestActor); + actor.Tell(5, TestActor); + actor.Tell(10, TestActor); + actor.Tell(15, TestActor); + + //Then + ExpectMsg((object) "int<5:0"); + ExpectMsg((object) "int<10:5"); + ExpectMsg((object) "int<15:10"); + ExpectMsg((object) "int:15"); + } + + [Fact] + public void Given_a_persistent_actor_that_uses_non_generic_and_predicates_When_sending_different_messages_Then_correct_handler_should_be_invoked() + { + //Given + var pid = "p-5"; + WriteEvents(pid, 1, 2, 3); + var actor = Sys.ActorOf(Props.Create(() => new TypePredicatesActor(pid)) , "predicates"); + + //When + actor.Tell(0, TestActor); + actor.Tell(5, TestActor); + actor.Tell(10, TestActor); + actor.Tell(15, TestActor); + actor.Tell("hello", TestActor); + + //Then + ExpectMsg((object) "int<5:0"); + ExpectMsg((object) "int<10:5"); + ExpectMsg((object) "int<15:10"); + ExpectMsg((object) "int:15"); + ExpectMsg((object) "string:hello"); + } + + + [Fact] + public void Given_a_persistent_actor_with_ReceiveAnyCommand_When_sending_different_messages_Then_correct_handler_should_be_invoked() + { + //Given + var pid = "p-6"; + WriteEvents(pid, 1, 2, 3); + var actor = Sys.ActorOf(Props.Create(() => new ReceiveAnyActor(pid)) , "matchany"); + + //When + actor.Tell(4711, TestActor); + actor.Tell("hello", TestActor); + + //Then + ExpectMsg((object)"int:4711"); + ExpectMsg((object)"any:hello"); + } + + private readonly AtomicCounterLong _seqNrCounter = new AtomicCounterLong(1L); + /// + /// Initialize test journal using provided events. + /// + private void WriteEvents(string pid, params object[] events) + { + var journalRef = Persistence.Instance.Apply(Sys).JournalFor(string.Empty); + var persistents = events + .Select(e => new Persistent(e, _seqNrCounter.GetAndIncrement(), e.GetType().FullName, pid)) + .ToArray(); + journalRef.Tell(new WriteMessages(persistents, TestActor, 1)); + + ExpectMsg(); + foreach (var p in persistents) + ExpectMsg(new WriteMessageSuccess(p, 1)); + } + + private abstract class TestReceivePersistentActor : ReceivePersistentActor + { + public readonly LinkedList State = new LinkedList(); + private readonly string _persistenceId; + + protected TestReceivePersistentActor(string persistenceId) + { + _persistenceId = persistenceId; + } + + public override string PersistenceId { get { return _persistenceId; } } + } + + private class NoCommandActor : TestReceivePersistentActor + { + public NoCommandActor(string pid) : base(pid) + { + RecoverAny(o => State.AddLast(o)); + // no command here + } + } + + private class NoEventActor : TestReceivePersistentActor + { + public NoEventActor(string pid) : base(pid) + { + CommandAny(msg => Sender.Tell(msg, Self)); + // no recover here + } + } + + private class CallReceiveWhenHandlingMessageActor : TestReceivePersistentActor + { + public CallReceiveWhenHandlingMessageActor(string pid) : base(pid) + { + Recover(i => State.AddLast(i)); + Command(m => + { + try + { + Command(i => Sender.Tell(i, Self)); + Sender.Tell(null, Self); + } + catch(Exception e) + { + Sender.Tell(e, Self); + } + }); + } + } + + private class IntPredicatesActor : TestReceivePersistentActor + { + public IntPredicatesActor(string pid) : base(pid) + { + Recover(i => State.AddLast(i)); + Command(i => i < 5, i => Sender.Tell("int<5:" + i, Self)); //Predicate first, when i < 5 + Command(i => Sender.Tell("int<10:" + i, Self), i => i < 10); //Predicate after, when 5 <= i < 10 + Command(i => + { + if(i < 15) + { + Sender.Tell("int<15:" + i, Self); + return true; + } + return false; + }); //Func, when 10 <= i < 15 + Command(i => Sender.Tell("int:" + i, Self), null); //Null predicate, when i >= 15 + Command(i => Sender.Tell("ShouldNeverMatch:" + i, Self)); //The handler above should never be invoked + } + } + + private class TypePredicatesActor : TestReceivePersistentActor + { + public TypePredicatesActor(string pid) : base(pid) + { + Recover(i => State.AddLast(i)); + Command(typeof(int), i => (int)i < 5, i => Sender.Tell("int<5:" + i, Self)); //Predicate first, when i < 5 + Command(typeof(int), i => Sender.Tell("int<10:" + i, Self), i => (int)i < 10); //Predicate after, when 5 <= i < 10 + Command(typeof(int), o => + { + var i = (int) o; + if(i < 15) + { + Sender.Tell("int<15:" + i, Self); + return true; + } + return false; + }); //Func, when 10 <= i < 15 + Command(typeof(int), i => Sender.Tell("int:" + i, Self), null); //Null predicate, when i >= 15 + Command(typeof(int), i => Sender.Tell("ShouldNeverMatch:" + i, Self)); //The handler above should never be invoked + Command(typeof(string), i => Sender.Tell("string:" + i)); + } + } + + + private class ReceiveAnyActor : TestReceivePersistentActor + { + public ReceiveAnyActor(string pid) : base(pid) + { + Command(i => Sender.Tell("int:" + i, Self)); + CommandAny(o => Sender.Tell("any:" + o, Self)); + } + } + + } +} + diff --git a/src/core/Akka.Persistence.Tests/ReceivePersistentActorTests_Become.cs b/src/core/Akka.Persistence.Tests/ReceivePersistentActorTests_Become.cs new file mode 100644 index 00000000000..ee0c58ec513 --- /dev/null +++ b/src/core/Akka.Persistence.Tests/ReceivePersistentActorTests_Become.cs @@ -0,0 +1,146 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using Akka.Actor; +using Akka.Event; +using Xunit; + +namespace Akka.Persistence.Tests +{ + public partial class ReceivePersistentActorTests + { + [Fact] + public void Given_persistent_actor_When_it_calls_Become_Then_it_switches_command_handler() + { + //Given + var pid = "p-21"; + WriteEvents(pid, 1, 2, 3); + var actor = Sys.ActorOf(Props.Create(() => new BecomeActor(pid)), "become"); + Sys.EventStream.Subscribe(TestActor, typeof(UnhandledMessage)); + + //When + actor.Tell("BECOME", TestActor); //Switch to state2 + actor.Tell("hello", TestActor); + actor.Tell(4711, TestActor); + //Then + ExpectMsg((object) "string2:hello"); + ExpectMsg( m => ((int)m.Message) == 4711 && m.Recipient == actor); + + //When + actor.Tell("BECOME", TestActor); //Switch to state3 + actor.Tell("hello", TestActor); + actor.Tell(4711, TestActor); + //Then + ExpectMsg((object) "string3:hello"); + ExpectMsg(m => ((int)m.Message) == 4711 && m.Recipient == actor); + } + + [Fact(Skip = "FIXME: stash dedupes based on reference equality causes this to fail")] + public void Given_persistent_actor_that_has_called_Become_When_it_calls_Unbecome_Then_it_switches_back_command_handler() + { + //Given + var pid = "p-22"; + WriteEvents(pid, 1, 2, 3); + var actor = Sys.ActorOf(Props.Create(() => new BecomeActor(pid)), "become"); + actor.Tell("BECOME", TestActor); //Switch to state2 + actor.Tell("BECOME", TestActor); //Switch to state3 + + //When + actor.Tell("UNBECOME", TestActor); //Switch back to state2 + actor.Tell("hello", TestActor); + + //Then + ExpectMsg((object) "string2:hello"); + } + + [Fact] + public void Given_persistent_actor_that_has_called_Become_at_construction_time_When_it_calls_Unbecome_Then_it_switches_back_command_handler() + { + //Given + var pid = "p-23"; + WriteEvents(pid, 1, 2, 3); + var actor = Sys.ActorOf(Props.Create(() => new BecomeDirectlyInConstructorActor(pid)), "become"); + + //When + actor.Tell("hello", TestActor); + //Then + ExpectMsg((object) "string3:hello"); + + //When + actor.Tell("UNBECOME", TestActor); //Switch back to state2 + actor.Tell("hello", TestActor); + //Then + ExpectMsg((object) "string2:hello"); + + //When + actor.Tell("UNBECOME", TestActor); //Switch back to state1 + actor.Tell("hello", TestActor); + //Then + ExpectMsg((object) "string1:hello"); + + //When + actor.Tell("UNBECOME", TestActor); //should still be in state1 + actor.Tell("hello", TestActor); + //Then + ExpectMsg((object) "string1:hello"); + } + + private class BecomeActor : TestReceivePersistentActor + { + public BecomeActor(string pid) : base(pid) + { + Recover(i => State.AddLast(i)); + Command(s => s == "UNBECOME", _ => UnbecomeStacked()); + Command(s => s == "BECOME", _ => BecomeStacked(State2)); + Command(s => Sender.Tell("string1:" + s, Self)); + Command(i => Sender.Tell("int1:" + i, Self)); + } + + private void State2() + { + Command(s => s == "UNBECOME", __ => UnbecomeStacked()); + Command(s => s == "BECOME", _ => BecomeStacked(State3)); + Command(s => Sender.Tell("string2:" + s, Self)); + } + + private void State3() + { + Command(s => s == "UNBECOME", __ => UnbecomeStacked()); + Command(s => Sender.Tell("string3:" + s, Self)); + } + } + + private class BecomeDirectlyInConstructorActor : TestReceivePersistentActor + { + public BecomeDirectlyInConstructorActor(string pid) : base(pid) + { + Recover(i => State.AddLast(i)); + Command(s => s == "UNBECOME", __ => UnbecomeStacked()); + Command(s => s == "BECOME", _ => BecomeStacked(State2)); + Command(s => Sender.Tell("string1:" + s, Self)); + Command(i => Sender.Tell("int1:" + i, Self)); + BecomeStacked(State2); + BecomeStacked(State3); + } + + private void State2() + { + Command(s => s == "UNBECOME", __ => UnbecomeStacked()); + Command(s => s == "BECOME", _ => BecomeStacked(State3)); + Command(s => Sender.Tell("string2:" + s, Self)); + } + + private void State3() + { + Command(s => s == "UNBECOME", __ => UnbecomeStacked()); + Command(s => Sender.Tell("string3:" + s, Self)); + } + } + + } +} + diff --git a/src/core/Akka.Persistence.Tests/ReceivePersistentActorTests_LifeCycle.cs b/src/core/Akka.Persistence.Tests/ReceivePersistentActorTests_LifeCycle.cs new file mode 100644 index 00000000000..8e5664a199e --- /dev/null +++ b/src/core/Akka.Persistence.Tests/ReceivePersistentActorTests_LifeCycle.cs @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using Akka.Actor; +using Xunit; + +namespace Akka.Persistence.Tests +{ + public partial class ReceivePersistentActorTests + { + [Fact] + public void Given_persistent_actor_When_it_restarts_Then_uses_the_handler() + { + //Given + var pid = "p-11"; + WriteEvents(pid, 1, 2, 3); + var actor = Sys.ActorOf(Props.Create(() => new CrashActor(pid)), "crash"); + + //When + actor.Tell("CRASH"); + + //Then + actor.Tell("hello", TestActor); + ExpectMsg((object) "1:hello"); + } + + [Fact] + public void Given_persistent_actor_that_has_replaced_its_initial_handler_When_it_restarts_Then_uses_the_initial_handler() + { + //Given + var pid = "p-12"; + WriteEvents(pid, 1, 2, 3); + var actor = Sys.ActorOf(Props.Create(() => new CrashActor(pid)), "crash"); + actor.Tell("BECOME-DISCARD"); + + //When + actor.Tell("CRASH", TestActor); + + //Then + actor.Tell("hello", TestActor); + ExpectMsg((object) "1:hello"); + } + + + [Fact] + public void Given_persistent_actor_that_has_pushed_a_new_handler_When_it_restarts_Then_uses_the_initial_handler() + { + //Given + var pid = "p-13"; + WriteEvents(pid, 1, 2, 3); + var actor = Sys.ActorOf(Props.Create(() => new CrashActor(pid)), "crash"); + actor.Tell("BECOME"); + + //When + actor.Tell("CRASH", TestActor); + + //Then + actor.Tell("hello", TestActor); + ExpectMsg((object) "1:hello"); + } + + private class CrashActor : TestReceivePersistentActor + { + public CrashActor(string pid) : base(pid) + { + Recover(i => State.AddLast(i)); + + Command(s => s == "CRASH", s => { throw new Exception("Crash!"); }); + Command(s => s == "BECOME", _ => BecomeStacked(State2)); + Command(s => s == "BECOME-DISCARD", _ => BecomeStacked(State2)); + Command(s => Sender.Tell("1:"+s)); + } + + private void State2() + { + Command(s => s == "CRASH", s => { throw new Exception("Crash!"); }); + Command(s => Sender.Tell("2:" + s)); + } + } + } +} + diff --git a/src/core/Akka.Persistence/PersistentActor.cs b/src/core/Akka.Persistence/PersistentActor.cs index b58069e36fd..719397df4ca 100644 --- a/src/core/Akka.Persistence/PersistentActor.cs +++ b/src/core/Akka.Persistence/PersistentActor.cs @@ -227,6 +227,29 @@ private void PrepareConfigureMessageHandlers() _matchRecoverBuilders.Push(new MatchBuilder(CachedMatchCompiler.Instance)); } + /// + /// Changes the actor's command behavior and replaces the current receive command handler with the specified handler. + /// + /// Configures the new handler by calling the different Receive overloads. + protected void Become(Action configure) + { + var newHandler = CreateNewHandler(configure); + base.Become(m => ExecutePartialMessageHandler(m, newHandler)); + } + + /// + /// Changes the actor's command behavior and replaces the current receive command handler with the specified handler. + /// The current handler is stored on a stack, and you can revert to it by calling + /// Please note, that in order to not leak memory, make sure every call to + /// is matched with a call to . + /// + /// Configures the new handler by calling the different Command overloads. + protected void BecomeStacked(Action configure) + { + var newHandler = CreateNewHandler(configure); + base.BecomeStacked(m => ExecutePartialMessageHandler(m, newHandler)); + } + protected sealed override void OnCommand(object message) { ExecutePartialMessageHandler(message, _partialReceiveCommand); @@ -342,6 +365,20 @@ protected void Command(Action handler) _matchCommandBuilders.Peek().MatchAny(handler); } + protected void CommandAny(Action handler) + { + EnsureMayConfigureCommandHandlers(); + _matchCommandBuilders.Peek().MatchAny(handler); + } + + private PartialAction CreateNewHandler(Action configure) + { + _matchCommandBuilders.Push(new MatchBuilder(CachedMatchCompiler.Instance)); + configure(); + var newHandler = BuildNewReceiveHandler(_matchCommandBuilders.Pop()); + return newHandler; + } + #endregion } } diff --git a/src/core/Akka/Actor/ActorBase.cs b/src/core/Akka/Actor/ActorBase.cs index 95d0913fa79..2c9b910d8f2 100644 --- a/src/core/Akka/Actor/ActorBase.cs +++ b/src/core/Akka/Actor/ActorBase.cs @@ -199,7 +199,7 @@ protected void Become(Receive receive, bool discardOld = true) } /// - /// Changes the actor's behavior and replaces the current receive handler with the specified handler. + /// Changes the actor's command behavior and replaces the current receive handler with the specified handler. /// /// The new message handler. protected void Become(Receive receive) From 7d21526b8efc2a720996428a8dc3587bb582a8d6 Mon Sep 17 00:00:00 2001 From: Graeme Bradbury Date: Thu, 22 Oct 2015 14:18:47 +0100 Subject: [PATCH 076/105] Multinode test runner alterations Refactored NodeTestRunner to allow MultinodeTestRunner to call it in two different manners. `build multinodetests` works in the same manner as in the past. Starting a seperate process for each node that needs to be created. Using `build multinodetests spec=` will limit the runner to starting just the named test. In addition, the nodes will be spun up inside isolated AppDomains rather than as seperate processes. The final difference between single test and multi test mode, is that the runner will call `Debugger.Launch()` to attach VS to the test. By automatically launching the debugger, I've been able to remove the `Thread.Sleep()`s that were needed previously, reducing the test run time by 50%-60%. --- .../Akka.MultiNodeTestRunner.csproj | 8 +- ...kka.MultiNodeTestRunner.csproj.DotSettings | 2 + src/core/Akka.MultiNodeTestRunner/App.config | 17 +- src/core/Akka.MultiNodeTestRunner/Program.cs | 203 +++++++++++++----- .../Akka.NodeTestRunner.csproj | 3 + .../Akka.NodeTestRunner.csproj.DotSettings | 2 + src/core/Akka.NodeTestRunner/App.config | 7 +- src/core/Akka.NodeTestRunner/ITestRunner.cs | 16 ++ .../Akka.NodeTestRunner/IsolatedTestRunner.cs | 58 +++++ src/core/Akka.NodeTestRunner/Program.cs | 65 +----- src/core/Akka.NodeTestRunner/TestRunner.cs | 82 +++++++ src/core/Akka.NodeTestRunner/paket.references | 2 +- .../Akka.Remote.TestKit.csproj | 2 +- src/core/Akka.Remote.TestKit/CommandLine.cs | 52 ----- src/core/Akka.Remote.TestKit/MultiNodeSpec.cs | 12 +- src/core/Akka.Remote.TestKit/TestSettings.cs | 73 +++++++ .../PiercingShouldKeepQuarantineSpec.cs | 2 +- 17 files changed, 420 insertions(+), 186 deletions(-) create mode 100644 src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj.DotSettings create mode 100644 src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj.DotSettings create mode 100644 src/core/Akka.NodeTestRunner/ITestRunner.cs create mode 100644 src/core/Akka.NodeTestRunner/IsolatedTestRunner.cs create mode 100644 src/core/Akka.NodeTestRunner/TestRunner.cs delete mode 100644 src/core/Akka.Remote.TestKit/CommandLine.cs create mode 100644 src/core/Akka.Remote.TestKit/TestSettings.cs diff --git a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj index 794443b1322..414b905fcda 100644 --- a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj +++ b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj @@ -40,15 +40,17 @@ - - CommandLine.cs + + TestSettings.cs - + + Designer + diff --git a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj.DotSettings b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj.DotSettings new file mode 100644 index 00000000000..662f95686eb --- /dev/null +++ b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp50 \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/App.config b/src/core/Akka.MultiNodeTestRunner/App.config index 5126174a197..7421531d914 100644 --- a/src/core/Akka.MultiNodeTestRunner/App.config +++ b/src/core/Akka.MultiNodeTestRunner/App.config @@ -1,16 +1,17 @@  - - - - + + + + + - + - + @@ -62,11 +63,11 @@ - + - + diff --git a/src/core/Akka.MultiNodeTestRunner/Program.cs b/src/core/Akka.MultiNodeTestRunner/Program.cs index 5ae1a09a5f1..ced7b026e4e 100644 --- a/src/core/Akka.MultiNodeTestRunner/Program.cs +++ b/src/core/Akka.MultiNodeTestRunner/Program.cs @@ -21,6 +21,8 @@ namespace Akka.MultiNodeTestRunner { + using Akka.NodeTestRunner; + /// /// Entry point for the MultiNodeTestRunner /// @@ -35,7 +37,10 @@ class Program /// /// MultiNodeTestRunner takes the following : /// - /// C:\> Akka.MultiNodeTestRunner.exe [assembly name] [-Dmultinode.enable-filesink=on] [-Dmultinode.output-directory={dir path}] + /// C:\> Akka.MultiNodeTestRunner.exe [assembly name] + /// [-Dmultinode.enable-filesink=on] + /// [-Dmultinode.output-directory={dir path}] + /// [-Dmultinode.test-spec={name of spec}] /// /// /// @@ -64,16 +69,30 @@ class Program /// as the test binary. /// /// + /// + /// -Dmultinode.test-spec + /// Setting this property means that only the test/s which match this name will be run. + /// Any other tests will be skipped. + /// + /// /// /// static void Main(string[] args) { + TestSettings.Initialize(args); + TestRunSystem = ActorSystem.Create("TestRunnerLogging"); SinkCoordinator = TestRunSystem.ActorOf(Props.Create(), "sinkCoordinator"); var assemblyName = Path.GetFullPath(args[0]); EnableAllSinks(assemblyName); - PublishRunnerMessage(String.Format("Running MultiNodeTests for {0}", assemblyName)); + PublishRunnerMessage(string.Format("Running MultiNodeTests for {0}", assemblyName)); + + var specificationName = TestSettings.GetProperty("multinode.test-spec"); + bool restrictToTestName = !string.IsNullOrEmpty(specificationName); + + var autoLoadDebugger = TestSettings.GetProperty("multinode.auto-debug") != string.Empty; + var useAppDomains = TestSettings.GetProperty("multinode.use-appdomains") != string.Empty; using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, assemblyName)) { @@ -90,60 +109,22 @@ static void Main(string[] args) continue; } - PublishRunnerMessage(string.Format("Starting test {0}", test.Value.First().MethodName)); - - var processes = new List(); + if ( restrictToTestName && string.Compare(test.Key, specificationName, StringComparison.OrdinalIgnoreCase) != 0) + { + PublishRunnerMessage(string.Format("Skipping test {0}.{1}. Reason - Doesn't match multinode.spec-name.", test.Value.First().TestName, test.Value.First().MethodName)); + continue; + } - StartNewSpec(test.Value); + PublishRunnerMessage(string.Format("Starting test {0}", test.Value.First().MethodName)); - foreach (var nodeTest in test.Value) + if (!useAppDomains) { - //Loop through each test, work out number of nodes to run on and kick off process - var process = new Process(); - processes.Add(process); - process.StartInfo.UseShellExecute = false; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.FileName = "Akka.NodeTestRunner.exe"; - process.StartInfo.Arguments = String.Format(@"-Dmultinode.test-assembly=""{0}"" -Dmultinode.test-class=""{1}"" -Dmultinode.test-method=""{2}"" -Dmultinode.max-nodes={3} -Dmultinode.server-host=""{4}"" -Dmultinode.host=""{5}"" -Dmultinode.index={6}", - assemblyName, nodeTest.TypeName, nodeTest.MethodName, test.Value.Count, "localhost", "localhost", nodeTest.Node - 1); - var nodeIndex = nodeTest.Node; - process.OutputDataReceived += - (sender, line) => - { - //ignore any trailing whitespace - if (string.IsNullOrEmpty(line.Data) || string.IsNullOrWhiteSpace(line.Data)) return; - string message = line.Data; - if (!message.StartsWith("[NODE", true, CultureInfo.InvariantCulture)) - { - message = "[NODE" + nodeIndex + "]" + message; - } - PublishToAllSinks(message); - }; - - var closureTest = nodeTest; - process.Exited += (sender, eventArgs) => - { - if (process.ExitCode == 0) - { - ReportSpecPassFromExitCode(nodeIndex, closureTest.TestName); - } - }; - process.Start(); - - process.BeginOutputReadLine(); - PublishRunnerMessage(string.Format("Started node {0} on pid {1}", nodeTest.Node, process.Id)); + RunNodesInSeperateProcesses(test, assemblyName); } - - foreach (var process in processes) + else { - process.WaitForExit(); - var exitCode = process.ExitCode; - process.Close(); + RunNodesInAppDomains(test, assemblyName, autoLoadDebugger); } - - PublishRunnerMessage("Waiting 3 seconds for all messages from all processes to be collected."); - Thread.Sleep(TimeSpan.FromSeconds(3)); - FinishSpec(); } } } @@ -159,13 +140,131 @@ static void Main(string[] args) Environment.Exit(ExitCodeContainer.ExitCode); } + private static void RunNodesInAppDomains(KeyValuePair> test, string assemblyName, bool autoLaunchDebugger) + { + var runners = new List>(); + + if (autoLaunchDebugger) + { + Debugger.Launch(); + } + + StartNewSpec(test.Value); + + foreach (var nodeTest in test.Value) + { + var testArguments = new[] + { + string.Format(@"-Dmultinode.test-assembly={0}", assemblyName), + string.Format(@"-Dmultinode.test-class={0}", nodeTest.TypeName), + string.Format(@"-Dmultinode.test-method={0}", nodeTest.MethodName), + string.Format(@"-Dmultinode.max-nodes={0}", test.Value.Count), + string.Format(@"-Dmultinode.server-host={0}", "localhost"), + string.Format(@"-Dmultinode.host={0}", "localhost"), + string.Format(@"-Dmultinode.index={0}", nodeTest.Node - 1), + }; + + var testRunner = new IsolatedTestRunner(); + testRunner.InitializeWithTestArgs(testArguments); + + var thread = new Thread(testRunner.Run); + runners.Add(new Tuple(nodeTest.Node, testRunner, thread)); + + //TODO: override console output + // Figure out how to add in any missing [NODE prefixes. + + thread.Start(); + + PublishRunnerMessage(string.Format("Started node {0} on thread id {1}", nodeTest.Node, thread.ManagedThreadId)); + } + + foreach (var process in runners) + { + process.Item3.Join(); + var noErrors = process.Item2.NoErrors; + if (noErrors) + { + ReportSpecPassFromExitCode(process.Item1, "Something Something"); + } + } + + PublishRunnerMessage("Waiting 3 seconds for all messages from all processes to be collected."); + Thread.Sleep(TimeSpan.FromSeconds(3)); + FinishSpec(); + } + + private static void RunNodesInSeperateProcesses(KeyValuePair> test, string assemblyName) + { + var processes = new List(); + + StartNewSpec(test.Value); + + foreach (var nodeTest in test.Value) + { + var testArguments = + string.Format( + @"-Dmultinode.test-assembly=""{0}"" -Dmultinode.test-class=""{1}"" -Dmultinode.test-method=""{2}"" -Dmultinode.max-nodes={3} -Dmultinode.server-host=""{4}"" -Dmultinode.host=""{5}"" -Dmultinode.index={6}", + assemblyName, + nodeTest.TypeName, + nodeTest.MethodName, + test.Value.Count, + "localhost", + "localhost", + nodeTest.Node - 1); + + //Loop through each test, work out number of nodes to run on and kick off process + var process = new Process(); + processes.Add(process); + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.FileName = "Akka.NodeTestRunner.exe"; + process.StartInfo.Arguments = testArguments; + var nodeIndex = nodeTest.Node; + process.OutputDataReceived += (sender, line) => + { + //ignore any trailing whitespace + if (string.IsNullOrEmpty(line.Data) || string.IsNullOrWhiteSpace(line.Data)) return; + string message = line.Data; + if (!message.StartsWith("[NODE", true, CultureInfo.InvariantCulture)) + { + message = "[NODE" + nodeIndex + "]" + message; + } + PublishToAllSinks(message); + }; + + var closureTest = nodeTest; + process.Exited += (sender, eventArgs) => + { + if (process.ExitCode == 0) + { + ReportSpecPassFromExitCode(nodeIndex, closureTest.TestName); + } + }; + process.Start(); + + process.BeginOutputReadLine(); + PublishRunnerMessage(string.Format("Started node {0} on pid {1}", nodeTest.Node, process.Id)); + } + + foreach (var process in processes) + { + process.WaitForExit(); + var exitCode = process.ExitCode; + process.Close(); + } + + PublishRunnerMessage("Waiting 3 seconds for all messages from all processes to be collected."); + Thread.Sleep(TimeSpan.FromSeconds(3)); + FinishSpec(); + } + static void EnableAllSinks(string assemblyName) { var now = DateTime.UtcNow; // if multinode.output-directory wasn't specified, the results files will be written // to the same directory as the test assembly. - var outputDirectory = CommandLine.GetProperty("multinode.output-directory"); + var outputDirectory = TestSettings.GetProperty("multinode.output-directory"); Func createJsonFileSink = () => { @@ -187,7 +286,7 @@ static void EnableAllSinks(string assemblyName) return new FileSystemMessageSink(visualizerProps); }; - var fileSystemSink = CommandLine.GetProperty("multinode.enable-filesink"); + var fileSystemSink = TestSettings.GetProperty("multinode.enable-filesink"); if (!string.IsNullOrEmpty(fileSystemSink)) { SinkCoordinator.Tell(new SinkCoordinator.EnableSink(createJsonFileSink())); diff --git a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj index cf995b9aaf1..95452d05c7e 100644 --- a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj +++ b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj @@ -53,9 +53,12 @@ + + + diff --git a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj.DotSettings b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj.DotSettings new file mode 100644 index 00000000000..662f95686eb --- /dev/null +++ b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp50 \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/App.config b/src/core/Akka.NodeTestRunner/App.config index 060f4e63806..2bc9ebaa0b1 100644 --- a/src/core/Akka.NodeTestRunner/App.config +++ b/src/core/Akka.NodeTestRunner/App.config @@ -12,7 +12,8 @@ - + + @@ -121,6 +122,10 @@ + + + + diff --git a/src/core/Akka.NodeTestRunner/ITestRunner.cs b/src/core/Akka.NodeTestRunner/ITestRunner.cs new file mode 100644 index 00000000000..1c091ac6227 --- /dev/null +++ b/src/core/Akka.NodeTestRunner/ITestRunner.cs @@ -0,0 +1,16 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace Akka.NodeTestRunner +{ + public interface ITestRunner + { + void Run(); + void InitializeWithTestArgs(string[] testArgs); + bool NoErrors { get; } + } +} \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/IsolatedTestRunner.cs b/src/core/Akka.NodeTestRunner/IsolatedTestRunner.cs new file mode 100644 index 00000000000..7947dd40935 --- /dev/null +++ b/src/core/Akka.NodeTestRunner/IsolatedTestRunner.cs @@ -0,0 +1,58 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +// -------------------------------------------------------------------------------------------------------------------- + +using System; + +namespace Akka.NodeTestRunner +{ + public class IsolatedTestRunner : IDisposable, ITestRunner + { + private readonly TestRunner _runner; + private AppDomain _domain; + + public IsolatedTestRunner() + { + var type = typeof (TestRunner); + var friendlyName = string.Format("TestRunner:{0}", Guid.NewGuid()); + + var appDomainSetup = AppDomain.CurrentDomain.SetupInformation; + appDomainSetup.DisallowBindingRedirects = true; + appDomainSetup.ConfigurationFile = string.Empty; + + _domain = AppDomain.CreateDomain( + friendlyName, + AppDomain.CurrentDomain.Evidence, + appDomainSetup); + + _runner = (TestRunner) _domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName); + } + + public void Dispose() + { + if (_domain != null) + { + AppDomain.Unload(_domain); + _domain = null; + } + } + + public void Run() + { + _runner.Run(); + } + + public void InitializeWithTestArgs(string[] testArgs) + { + _runner.InitializeWithTestArgs(testArgs); + } + + public bool NoErrors + { + get { return _runner.NoErrors; } + } + } +} \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/Program.cs b/src/core/Akka.NodeTestRunner/Program.cs index 77c13d8c773..1f5a4a166b9 100644 --- a/src/core/Akka.NodeTestRunner/Program.cs +++ b/src/core/Akka.NodeTestRunner/Program.cs @@ -6,10 +6,6 @@ //----------------------------------------------------------------------- using System; -using System.IO; -using System.Threading; -using Akka.Remote.TestKit; -using Xunit; namespace Akka.NodeTestRunner { @@ -17,63 +13,10 @@ class Program { static void Main(string[] args) { - var nodeIndex = CommandLine.GetInt32("multinode.index"); - var assemblyFileName = CommandLine.GetProperty("multinode.test-assembly"); - var typeName = CommandLine.GetProperty("multinode.test-class"); - var testName = CommandLine.GetProperty("multinode.test-method"); - var displayName = testName; - - Thread.Sleep(TimeSpan.FromSeconds(10)); - - using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, assemblyFileName)) - { - /* need to pass in just the assembly name to Discovery, not the full path - * i.e. "Akka.Cluster.Tests.MultiNode.dll" - * not "bin/Release/Akka.Cluster.Tests.MultiNode.dll" - this will cause - * the Discovery class to actually not find any indivudal specs to run - */ - var assemblyName = Path.GetFileName(assemblyFileName); - Console.WriteLine("Running specs for {0} [{1}]", assemblyName, assemblyFileName); - using (var discovery = new Discovery(assemblyName, typeName)) - { - using (var sink = new Sink(nodeIndex)) - { - Thread.Sleep(10000); - try - { - controller.Find(true, discovery, TestFrameworkOptions.ForDiscovery()); - discovery.Finished.WaitOne(); - controller.RunTests(discovery.TestCases, sink, TestFrameworkOptions.ForExecution()); - } - catch (AggregateException ex) - { - var specFail = new SpecFail(nodeIndex, displayName); - specFail.FailureExceptionTypes.Add(ex.GetType().ToString()); - specFail.FailureMessages.Add(ex.Message); - specFail.FailureStackTraces.Add(ex.StackTrace); - foreach (var innerEx in ex.Flatten().InnerExceptions) - { - specFail.FailureExceptionTypes.Add(innerEx.GetType().ToString()); - specFail.FailureMessages.Add(innerEx.Message); - specFail.FailureStackTraces.Add(innerEx.StackTrace); - } - Console.WriteLine(specFail); - Environment.Exit(1); //signal failure - } - catch (Exception ex) - { - var specFail = new SpecFail(nodeIndex, displayName); - specFail.FailureExceptionTypes.Add(ex.GetType().ToString()); - specFail.FailureMessages.Add(ex.Message); - specFail.FailureStackTraces.Add(ex.StackTrace); - Console.WriteLine(specFail); - Environment.Exit(1); //signal failure - } - sink.Finished.WaitOne(); - Environment.Exit(sink.Passed ? 0 : 1); - } - } - } + var runner = new TestRunner(); + runner.InitializeWithTestArgs(args); + runner.Run(); + Environment.Exit(runner.NoErrors ? 0 : 1); } } } diff --git a/src/core/Akka.NodeTestRunner/TestRunner.cs b/src/core/Akka.NodeTestRunner/TestRunner.cs new file mode 100644 index 00000000000..d6040f1b4be --- /dev/null +++ b/src/core/Akka.NodeTestRunner/TestRunner.cs @@ -0,0 +1,82 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +// -------------------------------------------------------------------------------------------------------------------- +namespace Akka.NodeTestRunner +{ + using System; + using System.IO; + + using Akka.Remote.TestKit; + + using Xunit; + + public class TestRunner : MarshalByRefObject, ITestRunner + { + public bool NoErrors { get; private set; } + + public void InitializeWithTestArgs(string[] testArgs) + { + TestSettings.Initialize(testArgs); + } + + public void Run() + { + + var nodeIndex = TestSettings.GetInt32("multinode.index"); + var assemblyFileName = TestSettings.GetProperty("multinode.test-assembly"); + var typeName = TestSettings.GetProperty("multinode.test-class"); + var displayName = TestSettings.GetProperty("multinode.test-method"); + + /* need to pass in just the assembly name to Discovery, not the full path + * i.e. "Akka.Cluster.Tests.MultiNode.dll" + * not "bin/Release/Akka.Cluster.Tests.MultiNode.dll" - this will cause + * the Discovery class to actually not find any individual specs to run + */ + var assemblyName = Path.GetFileName(assemblyFileName); + Console.WriteLine("Running specs for {0} [{1}]", assemblyName, assemblyFileName); + + using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, assemblyFileName)) + using (var discovery = new Discovery(assemblyName, typeName)) + using (var sink = new Sink(nodeIndex)) + { + try + { + controller.Find(true, discovery, TestFrameworkOptions.ForDiscovery()); + discovery.Finished.WaitOne(); + controller.RunTests(discovery.TestCases, sink, TestFrameworkOptions.ForExecution()); + } + catch (AggregateException ex) + { + var specFail = new SpecFail(nodeIndex, displayName); + specFail.FailureExceptionTypes.Add(ex.GetType().ToString()); + specFail.FailureMessages.Add(ex.Message); + specFail.FailureStackTraces.Add(ex.StackTrace); + foreach (var innerEx in ex.Flatten().InnerExceptions) + { + specFail.FailureExceptionTypes.Add(innerEx.GetType().ToString()); + specFail.FailureMessages.Add(innerEx.Message); + specFail.FailureStackTraces.Add(innerEx.StackTrace); + } + Console.WriteLine(specFail); + this.NoErrors = false; + return; + } + catch (Exception ex) + { + var specFail = new SpecFail(nodeIndex, displayName); + specFail.FailureExceptionTypes.Add(ex.GetType().ToString()); + specFail.FailureMessages.Add(ex.Message); + specFail.FailureStackTraces.Add(ex.StackTrace); + Console.WriteLine(specFail); + this.NoErrors = false; + return; + } + sink.Finished.WaitOne(); + this.NoErrors = sink.Passed; + } + } + } +} \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/paket.references b/src/core/Akka.NodeTestRunner/paket.references index d15f7ae54a1..13118143843 100644 --- a/src/core/Akka.NodeTestRunner/paket.references +++ b/src/core/Akka.NodeTestRunner/paket.references @@ -1,3 +1,3 @@ group Test xunit.abstractions -xunit.runner.utility \ No newline at end of file +xunit.runner.utility diff --git a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj index 32220732774..3a63828fb0a 100644 --- a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj +++ b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj @@ -59,7 +59,7 @@ - + diff --git a/src/core/Akka.Remote.TestKit/CommandLine.cs b/src/core/Akka.Remote.TestKit/CommandLine.cs deleted file mode 100644 index d785da35fa7..00000000000 --- a/src/core/Akka.Remote.TestKit/CommandLine.cs +++ /dev/null @@ -1,52 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (C) 2009-2015 Typesafe Inc. -// Copyright (C) 2013-2015 Akka.NET project -// -//----------------------------------------------------------------------- - -using System; -using System.Collections.Specialized; - -namespace Akka.Remote.TestKit -{ - //TODO: Needs some work - /// - /// Command line argument parser for individual node tests during a . - /// - /// Parses arguments from using the same conventions as canonical Akka. - /// - /// For example (from the Akka.NodeTestRunner source): - /// - /// var nodeIndex = CommandLine.GetInt32("multinode.index"); - /// var assemblyName = CommandLine.GetProperty("multinode.test-assembly"); - /// var typeName = CommandLine.GetProperty("multinode.test-class"); - /// var testName = CommandLine.GetProperty("multinode.test-method"); - /// - /// - public class CommandLine - { - private readonly static Lazy Values = new Lazy(() => - { - var dictionary = new StringDictionary(); - foreach (var arg in Environment.GetCommandLineArgs()) - { - if (!arg.StartsWith("-D")) continue; - var tokens = arg.Substring(2).Split('='); - dictionary.Add(tokens[0], tokens[1]); - } - return dictionary; - }); - - public static string GetProperty(string key) - { - return Values.Value[key]; - } - - public static int GetInt32(string key) - { - return Convert.ToInt32(GetProperty(key)); - } - } -} - diff --git a/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs b/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs index 2bb1b21285f..acb4950ae51 100644 --- a/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs +++ b/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs @@ -185,7 +185,7 @@ public static int MaxNodes { if (_maxNodes == MaxNodesUnset) { - _maxNodes = CommandLine.GetInt32("multinode.max-nodes"); + _maxNodes = TestSettings.GetInt32("multinode.max-nodes"); } if (_maxNodes <= 0) throw new InvalidOperationException("multinode.max-nodes must be greater than 0"); @@ -210,7 +210,7 @@ public static string SelfName { if (string.IsNullOrEmpty(_multiNodeHost)) { - _multiNodeHost = CommandLine.GetProperty("multinode.host"); + _multiNodeHost = TestSettings.GetProperty("multinode.host"); } //Run this assertion every time. Consistency is more important than performance. @@ -237,7 +237,7 @@ public static int SelfPort { if (_selfPort == SelfPortUnsetValue) //unset { - var selfPortStr = CommandLine.GetProperty("multinode.port"); + var selfPortStr = TestSettings.GetProperty("multinode.port"); _selfPort = string.IsNullOrEmpty(selfPortStr) ? 0 : Int32.Parse(selfPortStr); } @@ -259,7 +259,7 @@ public static string ServerName { if (string.IsNullOrEmpty(_serverName)) { - _serverName = CommandLine.GetProperty("multinode.server-host"); + _serverName = TestSettings.GetProperty("multinode.server-host"); } if (string.IsNullOrEmpty(_serverName)) throw new InvalidOperationException("multinode.server-host must not be empty"); return _serverName; @@ -289,7 +289,7 @@ public static int ServerPort { if (_serverPort == ServerPortUnsetValue) { - var serverPortStr = CommandLine.GetProperty("multinode.server-port"); + var serverPortStr = TestSettings.GetProperty("multinode.server-port"); _serverPort = string.IsNullOrEmpty(serverPortStr) ? ServerPortDefault : Int32.Parse(serverPortStr); } @@ -316,7 +316,7 @@ public static int SelfIndex { if (_selfIndex == SelfIndexUnset) { - _selfIndex = CommandLine.GetInt32("multinode.index"); + _selfIndex = TestSettings.GetInt32("multinode.index"); } if (!(_selfIndex >= 0 && _selfIndex < MaxNodes)) throw new InvalidOperationException("multinode.index is out of bounds: " + _selfIndex); diff --git a/src/core/Akka.Remote.TestKit/TestSettings.cs b/src/core/Akka.Remote.TestKit/TestSettings.cs new file mode 100644 index 00000000000..3713a8a654e --- /dev/null +++ b/src/core/Akka.Remote.TestKit/TestSettings.cs @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Remoting.Messaging; + +namespace Akka.Remote.TestKit +{ + /// + /// Test argument parser for indivudla node tests during a . + /// + /// Parses arguments using the same conventions as canonical Akka. + /// + /// Relies on being directly initialized rather than using Environment.GetCommandLineArgs(). + /// This allows us to abstract the runner (AppDomain or Process) from the test. + /// + public static class TestSettings + { + private const string CallContextName = "MultiNode settings CallContext"; + + public static void Initialize(string[] args) + { + var argsDictionary = new Dictionary(); + + args.Where(arg => arg.StartsWith("-D")) + .Select(arg => arg.Substring(2).Split('=')) + .Select(tokens => argsDictionary[tokens[0]] = tokens[1]) + .Ignore(); + + CallContext.LogicalSetData(CallContextName, argsDictionary); + } + + public static string GetProperty(string key) + { + try + { + var args =(Dictionary)CallContext.LogicalGetData(CallContextName); + return args[key]; + } + catch (KeyNotFoundException) + { + return string.Empty; + } + } + + public static int GetInt32(string key) + { + return Convert.ToInt32(GetProperty(key)); + } + } + + public static class EnumerableExtensions + { + /// + /// We just want the side effects. + /// + /// The source enumerable + public static void Ignore(this IEnumerable stream) + { + var enumerator = stream.GetEnumerator(); + while (enumerator.MoveNext()) + { + //nop + } + } + } +} \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs b/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs index bcb9d37f311..89847f1f3bd 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs +++ b/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs @@ -20,7 +20,7 @@ public PiercingShouldKeepQuarantineMultiNodeConfig() First = Role("first"); Second = Role("second"); - CommonConfig = DebugConfig(true) + CommonConfig = DebugConfig(false) .WithFallback(ConfigurationFactory.ParseString(@" akka.loglevel = INFO akka.remote.log-remote-lifecycle-events = INFO From 03105719a8866e8eadac268bc8f813e738f989b9 Mon Sep 17 00:00:00 2001 From: Bartosz Sypytkowski Date: Wed, 4 Nov 2015 22:56:46 +0100 Subject: [PATCH 077/105] Persistent actor stops on recovery failures --- .../Akka.Persistence/Eventsourced.Recovery.cs | 58 ++++--------------- src/core/Akka.Persistence/Eventsourced.cs | 28 ++++++--- src/core/Akka.Persistence/Persistence.cs | 13 +++-- 3 files changed, 38 insertions(+), 61 deletions(-) diff --git a/src/core/Akka.Persistence/Eventsourced.Recovery.cs b/src/core/Akka.Persistence/Eventsourced.Recovery.cs index 7a710c91626..c692b8b071e 100644 --- a/src/core/Akka.Persistence/Eventsourced.Recovery.cs +++ b/src/core/Akka.Persistence/Eventsourced.Recovery.cs @@ -123,10 +123,16 @@ private EventsourcedState ReplayStarted(Receive recoveryBehavior) UpdateLastSequenceNr(m.Persistent); base.AroundReceive(recoveryBehavior, m.Persistent); } - catch (Exception exc) + catch (Exception cause) { - var currentMessage = Context.AsInstanceOf().CurrentMessage; - ChangeState(ReplayFailed(exc, currentMessage)); + try + { + OnReplayFailure(cause, m.Persistent.Payload); + } + finally + { + Context.Stop(Self); + } } } else if (message is ReplayMessagesSuccess) @@ -138,7 +144,7 @@ private EventsourcedState ReplayStarted(Receive recoveryBehavior) else if (message is ReplayMessagesFailure) { var failure = (ReplayMessagesFailure)message; - OnReplayFailure(failure.Cause); + OnReplayFailure(failure.Cause, message: null); // FIXME what happens if RecoveryFailure is handled, i.e. actor is not stopped? base.AroundReceive(recoveryBehavior, new RecoveryFailure(failure.Cause)); } @@ -146,50 +152,6 @@ private EventsourcedState ReplayStarted(Receive recoveryBehavior) }); } - /// - /// Processes all remaining replayed messages and changes to . - /// Message that caused and exception during replay, is re-added to the mailbox and re-received - /// in state. - /// - private EventsourcedState ReplayFailed(Exception cause, object failureMessage) - { - return new EventsourcedState("replay failed", true, (receive, message) => - { - if (message is ReplayMessagesFailure) - { - ReplayCompleted(cause, failureMessage); - // journal couldn't tell the maximum stored sequence number, hence the next - // replay must be a full replay (up to the highest stored sequence number) - // Recover(lastSequenceNr) is sent by PreRestart - LastSequenceNr = long.MaxValue; - } - else if (message is ReplayMessagesSuccess) ReplayCompleted(cause, failureMessage); - else if (message is ReplayedMessage) UpdateLastSequenceNr(((ReplayedMessage)message).Persistent); - else if (message is Recover) return; // ignore - else _internalStash.Stash(); - }); - } - - private void ReplayCompleted(Exception cause, object failureMessage) - { - ChangeState(PrepareRestart(cause)); - - //TODO: this implementation requires mailbox.EnqueueFirst to be available, but that actually gives a large - // amount of composition constrains. If any of the casts below will go wrong, user-defined messages won't be handled by actors. - Context.EnqueueMessageFirst(failureMessage); - } - - /// - /// Re-receives replayed message that caused an exception and re-throws the . - /// - private EventsourcedState PrepareRestart(Exception cause) - { - return new EventsourcedState("prepare restart", true, (receive, message) => - { - if (message is ReplayedMessage) throw cause; - }); - } - /// /// Processes messages with the highest stored sequence number in the journal and then switches to /// state. All other messages are stashed. diff --git a/src/core/Akka.Persistence/Eventsourced.cs b/src/core/Akka.Persistence/Eventsourced.cs index b5d7cd1c2dd..dff7dfd80e2 100644 --- a/src/core/Akka.Persistence/Eventsourced.cs +++ b/src/core/Akka.Persistence/Eventsourced.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Linq; using Akka.Actor; +using Akka.Event; using Akka.Util.Internal; namespace Akka.Persistence @@ -73,6 +74,7 @@ public abstract partial class Eventsourced : ActorBase, IPersistentIdentity, IWi private LinkedList _pendingInvocations = new LinkedList(); protected readonly PersistenceExtension Extension; + private readonly ILoggingAdapter _log; protected Eventsourced() { @@ -83,8 +85,11 @@ protected Eventsourced() _maxMessageBatchSize = Extension.Settings.Journal.MaxMessageBatchSize; _currentState = RecoveryPending(); _internalStash = CreateStash(); + _log = Context.GetLogger(); } - + + protected virtual ILoggingAdapter Log { get { return _log; } } + /// /// Id of the persistent entity for which messages should be replayed. /// @@ -302,10 +307,22 @@ public void UnstashAll() protected virtual void OnReplaySuccess() { } /// - /// Called whenever a message replay fails. + /// Called whenever a message replay fails. By default it log the errors. /// /// Reason of failure - protected virtual void OnReplayFailure(Exception reason) { } + /// Message that caused a failure + protected virtual void OnReplayFailure(Exception reason, object message = null) + { + if (message != null) + { + _log.Error(reason, "Exception in ReceiveRecover when replaying event type [{0}] with sequence number [{1}] for persistenceId [{2}]", + message.GetType(), LastSequenceNr, PersistenceId); + } + else + { + _log.Error(reason, "Persistence failure when replaying events for persistenceId [{0}]. Last known sequence number [{1}]", PersistenceId, LastSequenceNr); + } + } private void ChangeState(EventsourcedState state) { @@ -333,11 +350,6 @@ private IStash CreateStash() { return Context.CreateStash(GetType()); } - - private static bool CanUnstashFilterPredicate(object message) - { - return !(message is WriteMessageSuccess || message is ReplayedMessage); - } } } diff --git a/src/core/Akka.Persistence/Persistence.cs b/src/core/Akka.Persistence/Persistence.cs index f2626f02055..3070112a953 100644 --- a/src/core/Akka.Persistence/Persistence.cs +++ b/src/core/Akka.Persistence/Persistence.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Concurrent; using System.Linq; +using System.Threading; using Akka.Actor; using Akka.Configuration; using Akka.Dispatch; @@ -52,14 +53,14 @@ public PersistenceExtension(ExtendedActorSystem system) var configPath = _config.GetString("journal.plugin"); if (string.IsNullOrEmpty(configPath)) throw new NullReferenceException("Default journal plugin is not configured"); return configPath; - }); + }, LazyThreadSafetyMode.ExecutionAndPublication); _defaultSnapshotPluginId = new Lazy(() => { var configPath = _config.GetString("snapshot-store.plugin"); if (string.IsNullOrEmpty(configPath)) throw new NullReferenceException("Default snapshot-store plugin is not configured"); return configPath; - }); + }, LazyThreadSafetyMode.ExecutionAndPublication); Settings = new PersistenceSettings(_system, _config); } @@ -81,7 +82,7 @@ public IActorRef SnapshotStoreFor(string snapshotPluginId) Lazy pluginContainer; if (!_snapshotPluginExtensionIds.TryGetValue(configPath, out pluginContainer)) { - var plugin = new Lazy(() => CreatePlugin(configPath, _ => DefaultPluginDispatcherId)); + var plugin = new Lazy(() => CreatePlugin(configPath, _ => DefaultPluginDispatcherId), LazyThreadSafetyMode.ExecutionAndPublication); pluginContainer = _snapshotPluginExtensionIds.AddOrUpdate(configPath, plugin, (key, old) => plugin); } @@ -101,7 +102,8 @@ public IActorRef JournalFor(string journalPluginId) var plugin = new Lazy(() => CreatePlugin(configPath, type => typeof (AsyncWriteJournal).IsAssignableFrom(type) ? Dispatchers.DefaultDispatcherId - : DefaultPluginDispatcherId)); + : DefaultPluginDispatcherId), + LazyThreadSafetyMode.ExecutionAndPublication); pluginContainer = _journalPluginExtensionIds.AddOrUpdate(configPath, plugin, (key, old) => plugin); } @@ -124,7 +126,8 @@ public EventAdapters AdaptersFor(string journalPluginId) var plugin = new Lazy(() => CreatePlugin(configPath, type => typeof (AsyncWriteJournal).IsAssignableFrom(type) ? Dispatchers.DefaultDispatcherId - : DefaultPluginDispatcherId)); + : DefaultPluginDispatcherId), + LazyThreadSafetyMode.ExecutionAndPublication); pluginContainer = _journalPluginExtensionIds.AddOrUpdate(configPath, plugin, (key, old) => plugin); } From f088f0c681fdc7ba1b4eaf7f823c2a9535d3045d Mon Sep 17 00:00:00 2001 From: Bartosz Sypytkowski Date: Thu, 5 Nov 2015 17:43:44 +0100 Subject: [PATCH 078/105] Fixed: data races inside sql journal engine --- .../Journal/JournalDbEngine.cs | 51 ++++--------------- 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/JournalDbEngine.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/JournalDbEngine.cs index 09ac0e8a386..12b9136bd3b 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/JournalDbEngine.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/JournalDbEngine.cs @@ -51,18 +51,14 @@ public abstract class JournalDbEngine : IDisposable /// Settings applied to journal mapped from HOCON config file. /// public readonly JournalSettings Settings; - - /// - /// List of cancellation tokens for each of the currently pending database operations. - /// - protected readonly LinkedList PendingOperations; - + /// /// Timestamp provider used for generation of timestamps for incoming persistent messages. /// protected readonly ITimestampProvider TimestampProvider; private readonly ActorSystem _system; + private readonly CancellationTokenSource _pendingRequestsCancellation; protected JournalDbEngine(ActorSystem system) { @@ -72,7 +68,7 @@ protected JournalDbEngine(ActorSystem system) QueryMapper = new DefaultJournalQueryMapper(_system.Serialization); TimestampProvider = CreateTimestampProvider(); - PendingOperations = new LinkedList(); + _pendingRequestsCancellation = new CancellationTokenSource(); } /// @@ -118,24 +114,7 @@ public DbConnection CreateDbConnection() /// public void Close() { - StopPendingOperations(); - } - - /// - /// Stops all currently executing database operations. - /// - protected void StopPendingOperations() - { - // stop all operations executed in the background - var node = PendingOperations.First; - while (node != null) - { - var curr = node; - node = node.Next; - - curr.Value.Cancel(); - PendingOperations.Remove(curr); - } + _pendingRequestsCancellation.Cancel(); } void IDisposable.Dispose() @@ -154,9 +133,8 @@ public async Task ReadEvents(object queryId, IEnumerable hints, IActorRef var sqlCommand = QueryBuilder.SelectEvents(hints); CompleteCommand(sqlCommand, connection); - - var tokenSource = GetCancellationTokenSource(); - var reader = await sqlCommand.ExecuteReaderAsync(tokenSource.Token); + + var reader = await sqlCommand.ExecuteReaderAsync(_pendingRequestsCancellation.Token); try { while (reader.Read()) @@ -168,7 +146,6 @@ public async Task ReadEvents(object queryId, IEnumerable hints, IActorRef } finally { - PendingOperations.Remove(tokenSource); reader.Close(); } } @@ -192,9 +169,8 @@ public async Task ReplayMessagesAsync(string persistenceId, long fromSequenceNr, var sqlCommand = QueryBuilder.SelectMessages(persistenceId, fromSequenceNr, toSequenceNr, max); CompleteCommand(sqlCommand, connection); - - var tokenSource = GetCancellationTokenSource(); - var reader = await sqlCommand.ExecuteReaderAsync(tokenSource.Token); + + var reader = await sqlCommand.ExecuteReaderAsync(_pendingRequestsCancellation.Token); try { @@ -207,7 +183,6 @@ public async Task ReplayMessagesAsync(string persistenceId, long fromSequenceNr, } finally { - PendingOperations.Remove(tokenSource); reader.Close(); } } @@ -224,9 +199,8 @@ public async Task ReadHighestSequenceNrAsync(string persistenceId, long fr var sqlCommand = QueryBuilder.SelectHighestSequenceNr(persistenceId); CompleteCommand(sqlCommand, connection); - var tokenSource = GetCancellationTokenSource(); - var seqNr = await sqlCommand.ExecuteScalarAsync(tokenSource.Token); + var seqNr = await sqlCommand.ExecuteScalarAsync(_pendingRequestsCancellation.Token); return seqNr is long ? Convert.ToInt64(seqNr) : 0L; } } @@ -290,13 +264,6 @@ private void CompleteCommand(DbCommand sqlCommand, DbConnection connection) sqlCommand.CommandTimeout = (int)Settings.ConnectionTimeout.TotalMilliseconds; } - private CancellationTokenSource GetCancellationTokenSource() - { - var source = new CancellationTokenSource(); - PendingOperations.AddLast(source); - return source; - } - private JournalEntry ToJournalEntry(IPersistentRepresentation message) { var payloadType = message.Payload.GetType(); From ac216e72cf5ff4ed8f288cbad663ac9aa6e4a0ac Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Wed, 11 Nov 2015 08:43:19 +0400 Subject: [PATCH 079/105] added Akka.Remote MultiNodeSpec: RemoteDeploymentDeathWatchSpec --- .../Akka.Remote.Tests.MultiNode.csproj | 1 + .../RemoteDeploymentDeathWatchSpec.cs | 161 ++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 src/core/Akka.Remote.Tests.MultiNode/RemoteDeploymentDeathWatchSpec.cs diff --git a/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj b/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj index 683cd3e2ab1..ca24d57a292 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj +++ b/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj @@ -46,6 +46,7 @@ + diff --git a/src/core/Akka.Remote.Tests.MultiNode/RemoteDeploymentDeathWatchSpec.cs b/src/core/Akka.Remote.Tests.MultiNode/RemoteDeploymentDeathWatchSpec.cs new file mode 100644 index 00000000000..d30964e26ab --- /dev/null +++ b/src/core/Akka.Remote.Tests.MultiNode/RemoteDeploymentDeathWatchSpec.cs @@ -0,0 +1,161 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + + +using System; +using System.Threading; +using Akka.Actor; +using Akka.Configuration; +using Akka.Remote.TestKit; +using Akka.TestKit; +using Akka.TestKit.Xunit2; +using Xunit; + +namespace Akka.Remote.Tests.MultiNode +{ + public abstract class RemoteDeploymentDeathWatchSpec : MultiNodeSpec + { + private readonly RemoteDeploymentDeathWatchSpecConfig _specConfig; + private readonly ITestKitAssertions _assertions; + + protected RemoteDeploymentDeathWatchSpec() + : this(new RemoteDeploymentDeathWatchSpecConfig()) + { + } + + protected RemoteDeploymentDeathWatchSpec(RemoteDeploymentDeathWatchSpecConfig specConfig) + : base(specConfig) + { + _specConfig = specConfig; + _assertions = new XunitAssertions(); + } + + protected override int InitialParticipantsValueFactory + { + get { return Roles.Count; } + } + + // Possible to override to let them heartbeat for a while. + protected virtual void Sleep() + { + } + + + protected virtual string Scenario + { + get { return string.Empty; } + } + + [MultiNodeFact] + public void AnActorSystemThatDeploysActorsOnAnotherNodeMustBeAbleToShutdownWhenRemoteNodeCrash() + { + RunOn(() => + { + var hello = Sys.ActorOf(Props.Create(() => new Hello()), "hello"); + hello.Path.Address.ShouldBe(Node(_specConfig.Third).Address); + EnterBarrier("hello-deployed"); + EnterBarrier("third-crashed"); + Sleep(); + + // if the remote deployed actor is not removed the system will not shutdown + var timeOut = RemainingOrDefault; + try + { + Sys.AwaitTermination(timeOut); + } + catch (TimeoutException ex) + { + //TODO: add printTree + + _assertions.Fail("Failed to stop {0} within {1} ", Sys.Name, timeOut); + } + }, _specConfig.Second); + + RunOn(() => + { + EnterBarrier("hello-deployed"); + EnterBarrier("third-crashed"); + }, _specConfig.Third); + + RunOn(() => + { + EnterBarrier("hello-deployed"); + Sleep(); + TestConductor.Exit(_specConfig.Third, 0).GetAwaiter().GetResult(); + EnterBarrier("third-crashed"); + + //second system will be shutdown + TestConductor.Shutdown(_specConfig.Second).GetAwaiter().GetResult(); + + EnterBarrier("after-3"); + }, _specConfig.First); + } + + internal class Hello : UntypedActor + { + protected override void OnReceive(object message) + { + } + } + } + + #region Several different variations of the test + public class RemoteDeploymentDeathWatchMultiNode1 : RemoteDeploymentDeathWatchSpec + { + } + + public class RemoteDeploymentDeathWatchMultiNode2 : RemoteDeploymentDeathWatchSpec + { + } + + public class RemoteDeploymentDeathWatchMultiNode3 : RemoteDeploymentDeathWatchSpec + { + } + + public class RemoteDeploymentNodeDeathWatchSlowSpec : RemoteDeploymentDeathWatchSpec + { + protected override void Sleep() + { + Thread.Sleep(3000); + } + + protected override string Scenario + { + get { return "slow"; } + } + } + + public class RemoteDeploymentNodeDeathWatchFastSpec : RemoteDeploymentDeathWatchSpec + { + protected override string Scenario + { + get { return "fast"; } + } + } + #endregion + + public class RemoteDeploymentDeathWatchSpecConfig : MultiNodeConfig + { + public RemoteDeploymentDeathWatchSpecConfig() : base() + { + First = Role("first"); + Second = Role("second"); + Third = Role("third"); + + CommonConfig = new Config(DebugConfig(false), ConfigurationFactory.ParseString( + @"akka.loglevel = INFO + akka.remote.log-remote-lifecycle-events = off" + )); + + DeployOn(Second, @"/hello.remote = ""@third@"""); + } + + public RoleName First { get; private set; } + public RoleName Second { get; private set; } + public RoleName Third { get; private set; } + } +} \ No newline at end of file From 409cd7f4ed0b285827b681685af59ec19c5a4b73 Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Mon, 16 Nov 2015 09:40:14 -0800 Subject: [PATCH 080/105] Fixed #1423 - Akka context props output to Serilog --- src/contrib/loggers/Akka.Logger.Serilog/SerilogLogger.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/contrib/loggers/Akka.Logger.Serilog/SerilogLogger.cs b/src/contrib/loggers/Akka.Logger.Serilog/SerilogLogger.cs index c0a1f985e94..67b86be40ab 100644 --- a/src/contrib/loggers/Akka.Logger.Serilog/SerilogLogger.cs +++ b/src/contrib/loggers/Akka.Logger.Serilog/SerilogLogger.cs @@ -30,9 +30,11 @@ private void WithSerilog(Action logStatement) private ILogger SetContextFromLogEvent(ILogger logger, LogEvent logEvent) { - logger.ForContext("Timestamp", logEvent.Timestamp); - logger.ForContext("LogSource", logEvent.LogSource); - logger.ForContext("Thread", logEvent.Thread); + logger = logger + .ForContext("Timestamp", logEvent.Timestamp) + .ForContext("LogSource", logEvent.LogSource) + .ForContext("Thread", logEvent.Thread.ManagedThreadId.ToString().PadLeft(4, '0')); + return logger; } From 22fd01a87ca67f7bfa00763a7258b85ec2a2abb9 Mon Sep 17 00:00:00 2001 From: Sean Gilliam Date: Mon, 16 Nov 2015 16:08:15 -0600 Subject: [PATCH 081/105] [api-docs] Documentation cleanup This PR cleans up a bit of the documentation. - Fleshed out the api docs for various Akka exceptions. - Cleaned up auto-generated api docs for configuration factory classes. - Added api docs for a couple of the serializers. - Added api docs for a couple of event listeners. --- .../Configuration/ClusterConfigFactory.cs | 15 +++--- .../Akka.Persistence/AtLeastOnceDelivery.cs | 12 ++++- .../Journal/AsyncWriteProxy.cs | 19 +++++++- src/core/Akka.Remote.TestKit/Controller.cs | 16 ++++++- .../Internals/TestConductorConfigFactory.cs | 14 +++--- src/core/Akka.Remote/AckedDelivery.cs | 18 ++++++++ .../Configuration/RemoteConfigFactory.cs | 15 +++--- src/core/Akka.Remote/RemoteSystemDaemon.cs | 2 +- src/core/Akka.Remote/RemoteTransport.cs | 12 ++++- .../DaemonMsgCreateSerializer.cs | 39 ++++++++++++++-- .../MessageContainerSerializer.cs | 28 ++++++++++- .../Serialization/ProtobufSerializer.cs | 36 +++++++++++++-- .../Akka.Remote/Transport/AkkaPduCodec.cs | 2 +- .../Transport/AkkaProtocolTransport.cs | 13 ++++-- .../FailureInjectorTransportAdapter.cs | 14 +++++- src/core/Akka.Remote/Transport/Transport.cs | 46 +++++++++++++++++-- .../Actor/Stash/StashOverflowException.cs | 13 +++++- .../Akka/Pattern/IllegalStateException.cs | 15 ++++-- src/core/Akka/Pattern/OpenCircuitException.cs | 35 ++++++++++---- 19 files changed, 302 insertions(+), 62 deletions(-) diff --git a/src/core/Akka.Cluster/Configuration/ClusterConfigFactory.cs b/src/core/Akka.Cluster/Configuration/ClusterConfigFactory.cs index 01c026aea9b..67f4b3ff673 100644 --- a/src/core/Akka.Cluster/Configuration/ClusterConfigFactory.cs +++ b/src/core/Akka.Cluster/Configuration/ClusterConfigFactory.cs @@ -12,24 +12,26 @@ namespace Akka.Cluster.Configuration { /// - /// Internal class used for loading akka-cluster configuration values + /// This class contains methods used to retrieve cluster configuration options from this assembly's resources. + /// + /// Note! Part of internal API. Breaking changes may occur without notice. Use at own risk. /// internal static class ClusterConfigFactory { /// - /// Defaults this instance. + /// Retrieves the default cluster options that Akka.NET uses when no configuration has been defined. /// - /// Config. + /// The configuration that contains default values for all cluster options. public static Config Default() { return FromResource("Akka.Cluster.Configuration.Cluster.conf"); } /// - /// Froms the resource. + /// Retrieves a configuration defined in a resource of the current executing assembly. /// - /// Name of the resource. - /// Config. + /// The name of the resource that contains the configuration. + /// The configuration defined in the current executing assembly. internal static Config FromResource(string resourceName) { var assembly = typeof(ClusterConfigFactory).Assembly; @@ -47,4 +49,3 @@ internal static Config FromResource(string resourceName) } } } - diff --git a/src/core/Akka.Persistence/AtLeastOnceDelivery.cs b/src/core/Akka.Persistence/AtLeastOnceDelivery.cs index 75873b45033..0d3ccb3da91 100644 --- a/src/core/Akka.Persistence/AtLeastOnceDelivery.cs +++ b/src/core/Akka.Persistence/AtLeastOnceDelivery.cs @@ -229,15 +229,25 @@ public override bool Equals(object obj) #endregion /// - /// An exception thrown, when threshold has been exceeded. + /// This exception is thrown when the threshold has been exceeded. /// public class MaxUnconfirmedMessagesExceededException : AkkaException { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception. public MaxUnconfirmedMessagesExceededException(string message, Exception cause = null) : base(message, cause) { } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected MaxUnconfirmedMessagesExceededException(SerializationInfo info, StreamingContext context) : base(info, context) { diff --git a/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs b/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs index 82f3f58ee66..bb2421572b1 100644 --- a/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs +++ b/src/core/Akka.Persistence/Journal/AsyncWriteProxy.cs @@ -14,18 +14,33 @@ namespace Akka.Persistence.Journal { + /// + /// This exception is thrown when the replay inactivity exceeds a specified timeout. + /// [Serializable] public class AsyncReplayTimeoutException : AkkaException { + /// + /// Initializes a new instance of the class. + /// public AsyncReplayTimeoutException() { } - public AsyncReplayTimeoutException(string msg) - : base(msg) + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public AsyncReplayTimeoutException(string message) + : base(message) { } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected AsyncReplayTimeoutException(SerializationInfo info, StreamingContext context) : base(info, context) { diff --git a/src/core/Akka.Remote.TestKit/Controller.cs b/src/core/Akka.Remote.TestKit/Controller.cs index 6c8f12cb321..950c14270a0 100644 --- a/src/core/Akka.Remote.TestKit/Controller.cs +++ b/src/core/Akka.Remote.TestKit/Controller.cs @@ -71,10 +71,22 @@ public override string ToString() } } + /// + /// This exception is thrown when a client has disconnected. + /// public class ClientDisconnectedException : AkkaException { - public ClientDisconnectedException(string msg) : base(msg){} - + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public ClientDisconnectedException(string message) : base(message){} + + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected ClientDisconnectedException(SerializationInfo info, StreamingContext context) : base(info, context) { } diff --git a/src/core/Akka.Remote.TestKit/Internals/TestConductorConfigFactory.cs b/src/core/Akka.Remote.TestKit/Internals/TestConductorConfigFactory.cs index 72dd2cef05a..c3c33eab9bd 100644 --- a/src/core/Akka.Remote.TestKit/Internals/TestConductorConfigFactory.cs +++ b/src/core/Akka.Remote.TestKit/Internals/TestConductorConfigFactory.cs @@ -12,25 +12,27 @@ namespace Akka.Remote.TestKit.Internals { /// - /// Loads required Multi-Node TestKit configuration values embedded into the assembly + /// This class contains methods used to retrieve Multi-Node TestKit configuration options from this assembly's resources /// and injects them in relevant tests. + /// + /// Note! Part of internal API. Breaking changes may occur without notice. Use at own risk. /// internal static class TestConductorConfigFactory { /// - /// Defaults this instance. + /// Retrieves the default Multi-Node TestKit options that Akka.NET uses when no configuration has been defined. /// - /// Config. + /// The configuration that contains default values for all Multi-Node TestKit options. public static Config Default() { return FromResource("Akka.Remote.TestKit.Internals.Reference.conf"); } /// - /// Froms the resource. + /// Retrieves a configuration defined in a resource of the current executing assembly. /// - /// Name of the resource. - /// Config. + /// The name of the resource that contains the configuration. + /// The configuration defined in the current executing assembly. internal static Config FromResource(string resourceName) { var assembly = typeof(TestConductorConfigFactory).Assembly; diff --git a/src/core/Akka.Remote/AckedDelivery.cs b/src/core/Akka.Remote/AckedDelivery.cs index b6febe0d06d..3fe022840a7 100644 --- a/src/core/Akka.Remote/AckedDelivery.cs +++ b/src/core/Akka.Remote/AckedDelivery.cs @@ -219,21 +219,39 @@ public override string ToString() } } + /// + /// This exception is thrown when the Resent buffer is filled beyond its capacity. + /// class ResendBufferCapacityReachedException : AkkaException { + /// + /// Initializes a new instance of the class. + /// + /// The capacity of the buffer public ResendBufferCapacityReachedException(int c) : base(string.Format("Resent buffer capacity of {0} has been reached.", c)) { } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected ResendBufferCapacityReachedException(SerializationInfo info, StreamingContext context) : base(info, context) { } } + /// + /// This exception is thrown when the system is unable to fulfill a resend request since negatively acknowledged payload is no longer in buffer. + /// class ResendUnfulfillableException : AkkaException { + /// + /// Initializes a new instance of the class. + /// public ResendUnfulfillableException() : base("Unable to fulfill resend request since negatively acknowledged payload is no longer in buffer. " + "The resend states between two systems are compromised and cannot be recovered") { } diff --git a/src/core/Akka.Remote/Configuration/RemoteConfigFactory.cs b/src/core/Akka.Remote/Configuration/RemoteConfigFactory.cs index 44d5fdf9c47..f29607ddce1 100644 --- a/src/core/Akka.Remote/Configuration/RemoteConfigFactory.cs +++ b/src/core/Akka.Remote/Configuration/RemoteConfigFactory.cs @@ -12,24 +12,26 @@ namespace Akka.Remote.Configuration { /// - /// Internal class used for loading remote configuration values + /// This class contains methods used to retrieve remote configuration options from this assembly's resources. + /// + /// Note! Part of internal API. Breaking changes may occur without notice. Use at own risk. /// internal static class RemoteConfigFactory { /// - /// Defaults this instance. + /// Retrieves the default remote options that Akka.NET uses when no configuration has been defined. /// - /// Config. + /// The configuration that contains default values for all remote options. public static Config Default() { return FromResource("Akka.Remote.Configuration.Remote.conf"); } /// - /// Froms the resource. + /// Retrieves a configuration defined in a resource of the current executing assembly. /// - /// Name of the resource. - /// Config. + /// The name of the resource that contains the configuration. + /// The configuration defined in the current executing assembly. internal static Config FromResource(string resourceName) { var assembly = typeof (RemoteConfigFactory).Assembly; @@ -47,4 +49,3 @@ internal static Config FromResource(string resourceName) } } } - diff --git a/src/core/Akka.Remote/RemoteSystemDaemon.cs b/src/core/Akka.Remote/RemoteSystemDaemon.cs index 12b9843a71f..f1517a810bc 100644 --- a/src/core/Akka.Remote/RemoteSystemDaemon.cs +++ b/src/core/Akka.Remote/RemoteSystemDaemon.cs @@ -73,7 +73,7 @@ public DaemonMsgCreate(Props props, Deploy deploy, string path, IActorRef superv /// /// Internal system "daemon" actor for remote internal communication. /// - /// It acts as the brain of the remote that response to system remote messages and executes actions accordingly. + /// It acts as the brain of the remote that responds to system remote messages and executes actions accordingly. /// internal class RemoteSystemDaemon : VirtualPathContainer { diff --git a/src/core/Akka.Remote/RemoteTransport.cs b/src/core/Akka.Remote/RemoteTransport.cs index 742f5036248..d5cba46e687 100644 --- a/src/core/Akka.Remote/RemoteTransport.cs +++ b/src/core/Akka.Remote/RemoteTransport.cs @@ -97,16 +97,26 @@ protected RemoteTransport(ExtendedActorSystem system, RemoteActorRefProvider pro } /// - /// Represents a general failure within a , such as + /// This exception is thrown when a general failure within a occurs, such as /// the inability to start, wrong configuration, etc... /// public class RemoteTransportException : AkkaException { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception. public RemoteTransportException(string message, Exception cause = null) : base(message, cause) { } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected RemoteTransportException(SerializationInfo info, StreamingContext context) : base(info, context) { diff --git a/src/core/Akka.Remote/Serialization/DaemonMsgCreateSerializer.cs b/src/core/Akka.Remote/Serialization/DaemonMsgCreateSerializer.cs index 569df12034c..b0cac6d8462 100644 --- a/src/core/Akka.Remote/Serialization/DaemonMsgCreateSerializer.cs +++ b/src/core/Akka.Remote/Serialization/DaemonMsgCreateSerializer.cs @@ -15,17 +15,33 @@ namespace Akka.Remote.Serialization { + /// + /// This is a special that serializes and deserializes only. + /// Serialization of contained , , and is done with the + /// configured serializer for those classes. + /// public class DaemonMsgCreateSerializer : Serializer { + /// + /// Initializes a new instance of the class. + /// + /// The actor system to associate with this serializer. public DaemonMsgCreateSerializer(ExtendedActorSystem system) : base(system) { } + /// + /// Completely unique value to identify this implementation of Serializer, used to optimize network traffic + /// Values from 0 to 16 is reserved for Akka internal usage + /// public override int Identifier { get { return 3; } } + /// + /// Returns whether this serializer needs a manifest in the fromBinary method + /// public override bool IncludeManifest { get { return false; } @@ -52,6 +68,12 @@ private object Deserialize(ByteString bytes, Type type) return o; } + /// + /// Serializes the given object into a byte array + /// + /// The object to serialize + /// A byte array containing the serialized object + /// Can't serialize a non- message using public override byte[] ToBinary(object obj) { var msg = obj as DaemonMsgCreate; @@ -78,7 +100,7 @@ private PropsData GetPropsData(Props props) .SetDeploy(GetDeployData(props.Deploy)); foreach (object arg in props.Arguments) - { + { if (arg == null) { builder = builder.AddArgs(ByteString.Empty); @@ -88,7 +110,7 @@ private PropsData GetPropsData(Props props) { builder = builder.AddArgs(Serialize(arg)); builder = builder.AddClasses(arg.GetType().AssemblyQualifiedName); - } + } } return builder.Build(); @@ -110,6 +132,16 @@ private DeployData GetDeployData(Deploy deploy) return res.Build(); } + /// + /// Deserializes a byte array into an object of type . + /// + /// The array containing the serialized object + /// The type of object contained in the array + /// The object contained in the array + /// + /// Could not find type on the remote system. + /// Ensure that the remote system has an assembly that contains the type in its assembly search path. + /// public override object FromBinary(byte[] bytes, Type type) { var proto = DaemonMsgCreateData.ParseFrom(bytes); @@ -172,7 +204,7 @@ private IEnumerable GetArgs(DaemonMsgCreateData proto) { var args = new object[proto.Props.ArgsCount]; for (int i = 0; i < args.Length; i++) - { + { var typeName = proto.Props.GetClasses(i); var arg = proto.Props.GetArgs(i); if (typeName == "" && ByteString.Empty.Equals(arg)) @@ -199,4 +231,3 @@ private IActorRef DeserializeActorRef(ActorRefData actorRefData) } } } - diff --git a/src/core/Akka.Remote/Serialization/MessageContainerSerializer.cs b/src/core/Akka.Remote/Serialization/MessageContainerSerializer.cs index 939ff1ca167..2d8c9d4135d 100644 --- a/src/core/Akka.Remote/Serialization/MessageContainerSerializer.cs +++ b/src/core/Akka.Remote/Serialization/MessageContainerSerializer.cs @@ -13,22 +13,42 @@ namespace Akka.Remote.Serialization { + /// + /// This is a special that serializes and deserializes only. + /// public class MessageContainerSerializer : Serializer { + /// + /// Initializes a new instance of the class. + /// + /// The actor system to associate with this serializer. public MessageContainerSerializer(ExtendedActorSystem system) : base(system) { } + /// + /// Completely unique value to identify this implementation of Serializer, used to optimize network traffic + /// Values from 0 to 16 is reserved for Akka internal usage + /// public override int Identifier { get { return 6; } } + /// + /// Returns whether this serializer needs a manifest in the fromBinary method + /// public override bool IncludeManifest { get { return false; } } + /// + /// Serializes the given object into a byte array + /// + /// The object to serialize + /// A byte array containing the serialized object + /// Object must be of type public override byte[] ToBinary(object obj) { if (!(obj is ActorSelectionMessage)) @@ -84,6 +104,13 @@ private byte[] SerializeActorSelectionMessage(ActorSelectionMessage sel) return builder.Build().ToByteArray(); } + /// + /// Deserializes a byte array into an object of type . + /// + /// The array containing the serialized object + /// The type of object contained in the array + /// The object contained in the array + /// Unknown SelectionEnvelope.Elements.Type public override object FromBinary(byte[] bytes, Type type) { SelectionEnvelope selectionEnvelope = SelectionEnvelope.ParseFrom(bytes); @@ -108,4 +135,3 @@ public override object FromBinary(byte[] bytes, Type type) } } } - diff --git a/src/core/Akka.Remote/Serialization/ProtobufSerializer.cs b/src/core/Akka.Remote/Serialization/ProtobufSerializer.cs index 64ca91d08c5..324dd30a77e 100644 --- a/src/core/Akka.Remote/Serialization/ProtobufSerializer.cs +++ b/src/core/Akka.Remote/Serialization/ProtobufSerializer.cs @@ -11,22 +11,42 @@ namespace Akka.Remote.Serialization { + /// + /// This is a special that serializes and deserializes Google protobuf messages only. + /// public class ProtobufSerializer : Serializer { + /// + /// Initializes a new instance of the class. + /// + /// The actor system to associate with this serializer. public ProtobufSerializer(ExtendedActorSystem system) : base(system) { } - public override bool IncludeManifest + /// + /// Completely unique value to identify this implementation of Serializer, used to optimize network traffic + /// Values from 0 to 16 is reserved for Akka internal usage + /// + public override int Identifier { - get { return true; } + get { return 2; } } - public override int Identifier + /// + /// Returns whether this serializer needs a manifest in the fromBinary method + /// + public override bool IncludeManifest { - get { return 2; } + get { return true; } } + /// + /// Serializes the given object into a byte array + /// + /// The object to serialize + /// A byte array containing the serialized object + /// This method is not currently implemented. public override byte[] ToBinary(object obj) { throw new NotImplementedException(); @@ -37,6 +57,13 @@ public override byte[] ToBinary(object obj) //} } + /// + /// Deserializes a byte array into an object of type . + /// + /// The array containing the serialized object + /// The type of object contained in the array + /// The object contained in the array + /// This method is not currently implemented. public override object FromBinary(byte[] bytes, Type type) { throw new NotImplementedException(); @@ -47,4 +74,3 @@ public override object FromBinary(byte[] bytes, Type type) } } } - diff --git a/src/core/Akka.Remote/Transport/AkkaPduCodec.cs b/src/core/Akka.Remote/Transport/AkkaPduCodec.cs index 0a45b7ef0ac..8edbb4ce4ac 100644 --- a/src/core/Akka.Remote/Transport/AkkaPduCodec.cs +++ b/src/core/Akka.Remote/Transport/AkkaPduCodec.cs @@ -105,7 +105,7 @@ public AckAndMessage(Ack ackOption, Message messageOption) /// /// INTERNAL API /// - /// A Codec that is able to convert Akka PDUs from and to + /// A codec that is able to convert Akka PDUs from and to /// internal abstract class AkkaPduCodec { diff --git a/src/core/Akka.Remote/Transport/AkkaProtocolTransport.cs b/src/core/Akka.Remote/Transport/AkkaProtocolTransport.cs index 4061dc76984..8b5916189d9 100644 --- a/src/core/Akka.Remote/Transport/AkkaProtocolTransport.cs +++ b/src/core/Akka.Remote/Transport/AkkaProtocolTransport.cs @@ -37,17 +37,22 @@ public ProtocolTransportAddressPair(AkkaProtocolTransport protocolTransport, Add } /// - /// An that can occur during the course of an Akka Protocol handshake. + /// This exception is thrown when an error occurred during the Akka protocol handshake. /// public class AkkaProtocolException : AkkaException { /// - /// Constructor. + /// Initializes a new instance of the class. /// - /// The error message. - /// The internal exception (null by default.) + /// The message that describes the error. + /// The exception that is the cause of the current exception. public AkkaProtocolException(string message, Exception cause = null) : base(message, cause) { } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected AkkaProtocolException(SerializationInfo info, StreamingContext context) : base(info, context) { diff --git a/src/core/Akka.Remote/Transport/FailureInjectorTransportAdapter.cs b/src/core/Akka.Remote/Transport/FailureInjectorTransportAdapter.cs index 203cf031c5f..4537682d2c1 100644 --- a/src/core/Akka.Remote/Transport/FailureInjectorTransportAdapter.cs +++ b/src/core/Akka.Remote/Transport/FailureInjectorTransportAdapter.cs @@ -29,20 +29,32 @@ public Transport Create(Transport wrappedTransport, ExtendedActorSystem system) } /// - /// The failure we're going to inject into a transport, of course :) + /// This exception is used to indicate a simulated failure in an association. /// public sealed class FailureInjectorException : AkkaException { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. public FailureInjectorException(string msg) { Msg = msg; } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. private FailureInjectorException(SerializationInfo info, StreamingContext context) : base(info, context) { } + /// + /// Retrieves the message of the simulated failure. + /// public string Msg { get; private set; } } diff --git a/src/core/Akka.Remote/Transport/Transport.cs b/src/core/Akka.Remote/Transport/Transport.cs index 62871f8a0b0..3e68988ad12 100644 --- a/src/core/Akka.Remote/Transport/Transport.cs +++ b/src/core/Akka.Remote/Transport/Transport.cs @@ -60,15 +60,25 @@ public virtual Task ManagementCommand(object message) } /// - /// Indicates that the association setup request is invalid and it is impossible to recover (malformed IP address, unknown hostname, etc...) + /// This exception is thrown when an association setup request is invalid and it is impossible to recover (malformed IP address, unknown hostname, etc...). /// public class InvalidAssociationException : AkkaException { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception. public InvalidAssociationException(string message, Exception cause = null) : base(message, cause) { } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected InvalidAssociationException(SerializationInfo info, StreamingContext context) : base(info, context) { @@ -139,22 +149,37 @@ public enum DisassociateInfo /// public interface IHandleEventListener { + /// + /// Notify the listener about an . + /// + /// The to notify the listener about void Notify(IHandleEvent ev); } /// - /// Converts an instance into an , so messages + /// Converts an into an , so messages /// can be passed directly to the Actor. /// public sealed class ActorHandleEventListener : IHandleEventListener { + /// + /// The Actor to notify about messages. + /// public readonly IActorRef Actor; + /// + /// Initializes a new instance of the class. + /// + /// The Actor to notify about messages. public ActorHandleEventListener(IActorRef actor) { Actor = actor; } + /// + /// Notify the Actor about an message. + /// + /// The message to notify the Actor about public void Notify(IHandleEvent ev) { Actor.Tell(ev); @@ -189,22 +214,37 @@ public InboundAssociation(AssociationHandle association) /// public interface IAssociationEventListener { + /// + /// Notify the listener about an message. + /// + /// The message to notify the listener about void Notify(IAssociationEvent ev); } /// - /// Converts an instance into an , so messages + /// Converts an into an , so messages /// can be passed directly to the Actor. /// public sealed class ActorAssociationEventListener : IAssociationEventListener { + /// + /// Initializes a new instance of the class. + /// + /// The Actor to notify about messages. public ActorAssociationEventListener(IActorRef actor) { Actor = actor; } + /// + /// The Actor to notify about messages. + /// public IActorRef Actor { get; private set; } + /// + /// Notify the Actor about an . + /// + /// The message to notify the Actor about public void Notify(IAssociationEvent ev) { Actor.Tell(ev); diff --git a/src/core/Akka/Actor/Stash/StashOverflowException.cs b/src/core/Akka/Actor/Stash/StashOverflowException.cs index 9dd0b1f3d1e..42e34d8e1ab 100644 --- a/src/core/Akka/Actor/Stash/StashOverflowException.cs +++ b/src/core/Akka/Actor/Stash/StashOverflowException.cs @@ -11,16 +11,25 @@ namespace Akka.Actor { /// - /// Is thrown when the size of the Stash exceeds the capacity of the stash + /// This exception is thrown when the size of the Stash exceeds the capacity of the stash. /// public class StashOverflowException : AkkaException { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception. public StashOverflowException(string message, Exception cause = null) : base(message, cause) { } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected StashOverflowException(SerializationInfo info, StreamingContext context) : base(info, context) { } } } - diff --git a/src/core/Akka/Pattern/IllegalStateException.cs b/src/core/Akka/Pattern/IllegalStateException.cs index f1a4c684170..0ffe86179d8 100644 --- a/src/core/Akka/Pattern/IllegalStateException.cs +++ b/src/core/Akka/Pattern/IllegalStateException.cs @@ -11,21 +11,26 @@ namespace Akka.Pattern { /// - /// Signals that a method has been invoked at an illegal or - /// inappropriate time. + /// This exception is thrown when a method has been invoked at an illegal or inappropriate time. /// public class IllegalStateException : AkkaException { - + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. public IllegalStateException(string message) : base(message) { - } + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. protected IllegalStateException(SerializationInfo info, StreamingContext context) : base(info, context) { } } } - diff --git a/src/core/Akka/Pattern/OpenCircuitException.cs b/src/core/Akka/Pattern/OpenCircuitException.cs index 8cc7d68fd0a..7b6f40d49b3 100644 --- a/src/core/Akka/Pattern/OpenCircuitException.cs +++ b/src/core/Akka/Pattern/OpenCircuitException.cs @@ -12,25 +12,42 @@ namespace Akka.Pattern { /// - /// Exception throws when CircuitBreaker is open + /// This exception is thrown when the CircuitBreaker is open. /// public class OpenCircuitException : AkkaException { - public OpenCircuitException( ) : base( "Circuit Breaker is open; calls are failing fast" ) { } + /// + /// Initializes a new instance of the class. + /// + public OpenCircuitException() : base("Circuit Breaker is open; calls are failing fast") { } - public OpenCircuitException( string message ) - : base( message ) + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public OpenCircuitException(string message) + : base(message) { } - public OpenCircuitException( string message, Exception innerException ) - : base( message, innerException ) + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception. + public OpenCircuitException(string message, Exception cause) + : base(message, cause) { } - protected OpenCircuitException( SerializationInfo info, StreamingContext context ) - : base( info, context ) + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + protected OpenCircuitException(SerializationInfo info, StreamingContext context) + : base(info, context) { } } -} \ No newline at end of file +} From 0f771efa6fae003393b8b56d9d3b0e4b1abf8d3c Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Tue, 17 Nov 2015 16:29:42 +0400 Subject: [PATCH 082/105] fix actor naming in the PersistentFSMSpec #1426 --- src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs index 1c021fdafac..7a777cc50f3 100644 --- a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs +++ b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs @@ -259,7 +259,7 @@ public void PersistentFSM_should_not_persist_state_change_event_when_staying_in_ { var dummyReportActorRef = CreateTestProbe().Ref; - var fsmRef = Sys.ActorOf(Props.Create(Name, dummyReportActorRef), Name); + var fsmRef = Sys.ActorOf(Props.Create(()=> new WebStoreCustomerFSM(Name, dummyReportActorRef))); Watch(fsmRef); fsmRef.Tell(new FSMBase.SubscribeTransitionCallBack(TestActor)); @@ -288,7 +288,8 @@ public void PersistentFSM_should_not_persist_state_change_event_when_staying_in_ ExpectMsg(); ExpectTerminated(fsmRef); - var persistentEventsStreamer = Sys.ActorOf(Props.Create(Name, TestActor), Name); + var persistentEventsStreamer = Sys.ActorOf(Props.Create(()=> new PersistentEventsStreamer(Name, TestActor))); + ExpectMsg(); ExpectMsg.StateChangeEvent>(); From 15772b9878c64b42d6a4d2051fbbf662a8dc3738 Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Tue, 17 Nov 2015 09:03:38 -0800 Subject: [PATCH 083/105] Removed files, not used in project anymore. Akka/Actor/LocalActorRefProvider Akka/Util/AtomicCounter.cs Akka/Util/AtomicCounterLong.cs --- src/core/Akka/Actor/LocalActorRefProvider.cs | 344 ------------------- src/core/Akka/Util/AtomicCounter.cs | 93 ----- src/core/Akka/Util/AtomicCounterLong.cs | 56 --- 3 files changed, 493 deletions(-) delete mode 100644 src/core/Akka/Actor/LocalActorRefProvider.cs delete mode 100644 src/core/Akka/Util/AtomicCounter.cs delete mode 100644 src/core/Akka/Util/AtomicCounterLong.cs diff --git a/src/core/Akka/Actor/LocalActorRefProvider.cs b/src/core/Akka/Actor/LocalActorRefProvider.cs deleted file mode 100644 index d4b559d470c..00000000000 --- a/src/core/Akka/Actor/LocalActorRefProvider.cs +++ /dev/null @@ -1,344 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (C) 2009-2015 Typesafe Inc. -// Copyright (C) 2013-2015 Akka.NET project -// -//----------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Akka.Actor.Internals; -using Akka.Dispatch; -using Akka.Dispatch.SysMsg; -using Akka.Event; -using Akka.Routing; -using Akka.Util; - -namespace Akka.Actor -{ - - /// - /// Class LocalActorRefProvider. This class cannot be inherited. - /// - public sealed class LocalActorRefProvider : ActorRefProvider - { - private readonly Settings _settings; - private readonly EventStream _eventStream; - private readonly Deployer _deployer; - private readonly InternalActorRef _deadLetters; - private readonly RootActorPath _rootPath; - private readonly LoggingAdapter _log; - private readonly AtomicCounterLong _tempNumber; - private readonly ActorPath _tempNode; - private ActorSystemImpl _system; - private readonly Dictionary _extraNames = new Dictionary(); - private readonly TaskCompletionSource _terminationPromise = new TaskCompletionSource(); - private SupervisorStrategy _systemGuardianStrategy; - private VirtualPathContainer _tempContainer; - private RootGuardianActorRef _rootGuardian; - private LocalActorRef _userGuardian; //This is called guardian in Akka - private Func _defaultMailbox; //TODO: switch to MailboxType - private LocalActorRef _systemGuardian; - - public LocalActorRefProvider(string systemName, Settings settings, EventStream eventStream) - : this(systemName, settings, eventStream, null, null) - { - //Intentionally left blank - } - - public LocalActorRefProvider(string systemName, Settings settings, EventStream eventStream, Deployer deployer, Func deadLettersFactory) - { - _settings = settings; - _eventStream = eventStream; - _deployer = deployer ?? new Deployer(settings); - _rootPath = new RootActorPath(new Address("akka", systemName)); - _log = Logging.GetLogger(eventStream, "LocalActorRefProvider(" + _rootPath.Address + ")"); - if (deadLettersFactory == null) - deadLettersFactory = p => new DeadLetterActorRef(this, p, _eventStream); - _deadLetters = deadLettersFactory(_rootPath / "deadLetters"); - _tempNumber = new AtomicCounterLong(1); - _tempNode = _rootPath / "temp"; - - //TODO: _guardianSupervisorStrategyConfigurator = dynamicAccess.createInstanceFor[SupervisorStrategyConfigurator](settings.SupervisorStrategyClass, EmptyImmutableSeq).get - _systemGuardianStrategy = SupervisorStrategy.DefaultStrategy; - - } - - public ActorRef DeadLetters { get { return _deadLetters; } } - - public Deployer Deployer { get { return _deployer; } } - - public InternalActorRef RootGuardian { get { return _rootGuardian; } } - - public ActorPath RootPath { get { return _rootPath; } } - - public Settings Settings { get { return _settings; } } - - public LocalActorRef SystemGuardian { get { return _systemGuardian; } } - - public InternalActorRef TempContainer { get { return _tempContainer; } } - - public Task TerminationTask { get { return _terminationPromise.Task; } } - - public LocalActorRef Guardian { get { return _userGuardian; } } - - private MessageDispatcher DefaultDispatcher { get { return _system.Dispatchers.DefaultGlobalDispatcher; } } - - private SupervisorStrategy UserGuardianSupervisorStrategy { get { return SupervisorStrategy.DefaultStrategy; } } //TODO: Implement Akka's _guardianSupervisorStrategyConfigurator.create() - - public ActorPath TempPath() - { - return _tempNode / GetNextTempName(); - } - - private string GetNextTempName() - { - return _tempNumber.GetAndIncrement().Base64Encode(); - } - - /// - /// Higher-level providers (or extensions) might want to register new synthetic - /// top-level paths for doing special stuff. This is the way to do just that. - /// Just be careful to complete all this before finishes, - /// or before you start your own auto-spawned actors. - /// - public void RegisterExtraName(string name, InternalActorRef actor) - { - _extraNames.Add(name, actor); - } - - - - private RootGuardianActorRef CreateRootGuardian(ActorSystemImpl system) - { - var supervisor = new RootGuardianSupervisor(_rootPath, this, _terminationPromise, _log); - var rootGuardianStrategy = new OneForOneStrategy(ex => - { - _log.Error(ex, "Guardian failed. Shutting down system"); - return Directive.Stop; - }); - var props = Props.Create(rootGuardianStrategy); - var rootGuardian = new RootGuardianActorRef(system, props, DefaultDispatcher, _defaultMailbox, supervisor, _rootPath, _deadLetters, _extraNames); - return rootGuardian; - } - - public ActorRef RootGuardianAt(Address address) - { - return address == _rootPath.Address ? _rootGuardian : _deadLetters; - } - - private LocalActorRef CreateUserGuardian(LocalActorRef rootGuardian, string name) //Corresponds to Akka's: override lazy val guardian: LocalActorRef - { - return CreateRootGuardianChild(rootGuardian, name, () => - { - var props = Props.Create(UserGuardianSupervisorStrategy); - - var userGuardian = new LocalActorRef(_system, props, DefaultDispatcher, _defaultMailbox, rootGuardian, RootPath / name); - return userGuardian; - }); - } - - private LocalActorRef CreateSystemGuardian(LocalActorRef rootGuardian, string name, LocalActorRef userGuardian) //Corresponds to Akka's: override lazy val guardian: systemGuardian - { - //TODO: When SystemGuardianActor has been implemented switch to this: - //return CreateRootGuardianChild(rootGuardian, name, () => - //{ - // var props = Props.Create(() => new SystemGuardianActor(userGuardian), _systemGuardianStrategy); - - // var systemGuardian = new LocalActorRef(_system, props, DefaultDispatcher, _defaultMailbox, rootGuardian, RootPath / name); - // return systemGuardian; - //}); - return (LocalActorRef)rootGuardian.Cell.ActorOf(name); - } - - private LocalActorRef CreateRootGuardianChild(LocalActorRef rootGuardian, string name, Func childCreator) - { - var cell = rootGuardian.Cell; - cell.ReserveChild(name); - var child = childCreator(); - cell.InitChild(child); - child.Start(); - return child; - } - - public void RegisterTempActor(InternalActorRef actorRef, ActorPath path) - { - if (path.Parent != _tempNode) - throw new Exception("Cannot RegisterTempActor() with anything not obtained from tempPath()"); - _tempContainer.AddChild(path.Name, actorRef); - } - - public void UnregisterTempActor(ActorPath path) - { - if (path.Parent != _tempNode) - throw new Exception("Cannot UnregisterTempActor() with anything not obtained from tempPath()"); - _tempContainer.RemoveChild(path.Name); - } - - public void Init(ActorSystemImpl system) - { - _system = system; - //The following are the lazy val statements in Akka - var defaultDispatcher = system.Dispatchers.DefaultGlobalDispatcher; - _defaultMailbox = () => new ConcurrentQueueMailbox(); //TODO:system.Mailboxes.FromConfig(Mailboxes.DefaultMailboxId) - _rootGuardian = CreateRootGuardian(system); - _tempContainer = new VirtualPathContainer(system.Provider, _tempNode, _rootGuardian, _log); - _rootGuardian.SetTempContainer(_tempContainer); - _userGuardian = CreateUserGuardian(_rootGuardian, "user"); - _systemGuardian = CreateSystemGuardian(_rootGuardian, "system", _userGuardian); - //End of lazy val - - _rootGuardian.Start(); - // chain death watchers so that killing guardian stops the application - _systemGuardian.Tell(new Watch(_userGuardian, _systemGuardian)); //Should be SendSystemMessage - _rootGuardian.Tell(new Watch(_systemGuardian, _rootGuardian)); //Should be SendSystemMessage - _eventStream.StartDefaultLoggers(_system); - } - - public ActorRef ResolveActorRef(string path) - { - ActorPath actorPath; - if (ActorPath.TryParse(path, out actorPath) && actorPath.Address == _rootPath.Address) - return ResolveActorRef(_rootGuardian, actorPath.Elements); - _log.Debug("Resolve of unknown path [{0}] failed. Invalid format.", path); - return _deadLetters; - } - - /// - /// Resolves the actor reference. - /// - /// The actor path. - /// ActorRef. - /// The provided actor path is not valid in the LocalActorRefProvider - public ActorRef ResolveActorRef(ActorPath path) - { - if (path.Root == _rootPath) - return ResolveActorRef(_rootGuardian, path.Elements); - _log.Debug("Resolve of foreign ActorPath [{0}] failed", path); - return _deadLetters; - - //Used to be this, but the code above is what Akka has - //if(_rootPath.Address==actorPath.Address) - //{ - // if(actorPath.Elements.Head() == "temp") - // { - // //skip ""/"temp", - // string[] parts = actorPath.Elements.Drop(1).ToArray(); - // return _tempContainer.GetChild(parts); - // } - // //standard - // ActorCell currentContext = _rootGuardian.Cell; - // foreach(string part in actorPath.Elements) - // { - // currentContext = ((LocalActorRef)currentContext.Child(part)).Cell; - // } - // return currentContext.Self; - //} - //throw new NotSupportedException("The provided actor path is not valid in the LocalActorRefProvider"); - } - - private ActorRef ResolveActorRef(InternalActorRef actorRef, IReadOnlyCollection pathElements) - { - if (pathElements.Count == 0) - { - _log.Debug("Resolve of empty path sequence fails (per definition)"); - return _deadLetters; - } - var child = actorRef.GetChild(pathElements); - if (child.IsNobody()) - { - _log.Debug("Resolve of path sequence [/{0}] failed", ActorPath.FormatPathElements(pathElements)); - return new EmptyLocalActorRef(_system.Provider, actorRef.Path / pathElements, _eventStream); - } - return child; - } - - - public InternalActorRef ActorOf(ActorSystemImpl system, Props props, InternalActorRef supervisor, ActorPath path, bool systemService, Deploy deploy, bool lookupDeploy, bool async) - { - //TODO: This does not match Akka's ActorOf at all - - Deploy configDeploy = _system.Provider.Deployer.Lookup(path); - deploy = configDeploy ?? props.Deploy ?? Deploy.None; - if (deploy.Mailbox != null) - props = props.WithMailbox(deploy.Mailbox); - if (deploy.Dispatcher != null) - props = props.WithDispatcher(deploy.Dispatcher); - if (deploy.Scope is RemoteScope) - { - - } - - if (string.IsNullOrEmpty(props.Mailbox)) - { - // throw new NotSupportedException("Mailbox can not be configured as null or empty"); - } - if (string.IsNullOrEmpty(props.Dispatcher)) - { - //TODO: fix this.. - // throw new NotSupportedException("Dispatcher can not be configured as null or empty"); - } - - - //TODO: how should this be dealt with? - //akka simply passes the "deploy" var from remote daemon to ActorOf - //so it atleast seems like they ignore if remote scope is provided here. - //leaving this for now since it does work - - //if (props.Deploy != null && props.Deploy.Scope is RemoteScope) - //{ - // throw new NotSupportedException("LocalActorRefProvider can not deploy remote"); - //} - - if (props.RouterConfig is NoRouter || props.RouterConfig == null) - { - - props = props.WithDeploy(deploy); - var dispatcher = system.Dispatchers.FromConfig(props.Dispatcher); - var mailbox = _system.Mailboxes.FromConfig(props.Mailbox); - //TODO: Should be: system.mailboxes.getMailboxType(props2, dispatcher.configurator.config) - - if (async) - { - var reActorRef = new RepointableActorRef(system, props, dispatcher, () => mailbox, supervisor, path); - reActorRef.Initialize(async: true); - return reActorRef; - } - return new LocalActorRef(system, props, dispatcher, () => mailbox, supervisor, path); - } - else - { - //if no Router config value was specified, override with procedural input - if (deploy.RouterConfig is NoRouter) - { - deploy = deploy.WithRouterConfig(props.RouterConfig); - } - var routerDispatcher = system.Dispatchers.FromConfig(props.RouterConfig.RouterDispatcher); - var routerMailbox = _system.Mailboxes.FromConfig(props.Mailbox); - //TODO: Should be val routerMailbox = system.mailboxes.getMailboxType(routerProps, routerDispatcher.configurator.config) - - // routers use context.actorOf() to create the routees, which does not allow us to pass - // these through, but obtain them here for early verification - var routerProps = Props.Empty.WithDeploy(deploy); - var routeeProps = props.WithRouter(RouterConfig.NoRouter); - - var routedActorRef = new RoutedActorRef(system, routerProps, routerDispatcher, () => routerMailbox, routeeProps, supervisor, path); - routedActorRef.Initialize(async); - return routedActorRef; - } - } - - public Address GetExternalAddressFor(Address address) - { - return address == _rootPath.Address ? address : null; - } - - public Address DefaultAddress { get { return _rootPath.Address; } } - - public LoggingAdapter Log { get { return _log; } } - } -} - diff --git a/src/core/Akka/Util/AtomicCounter.cs b/src/core/Akka/Util/AtomicCounter.cs deleted file mode 100644 index 1b5dfd78fc3..00000000000 --- a/src/core/Akka/Util/AtomicCounter.cs +++ /dev/null @@ -1,93 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (C) 2009-2015 Typesafe Inc. -// Copyright (C) 2013-2015 Akka.NET project -// -//----------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Akka.Actor; - -namespace Akka.Util -{ - /// - /// Class used for atomic counters and increments. - /// - public class AtomicCounter - { - /// - /// Creates a new instance initialized to the value specified by . - /// If is not specified it defaults to -1. - /// - /// - public AtomicCounter(int initialValue=-1) - { - _value = initialValue; - } - - private int _value; - - /// - /// Retrieves the current value of the counter - /// - public int Current { get { return _value; } } - - /// - /// Increments the counter and returns the next value - /// - public int Next - { - get - { - return Interlocked.Increment(ref _value); - } - } - - /// - /// Returns the current value while simultaneously incrementing the counter - /// - public int GetAndIncrement() - { - var nextValue = Next; - return nextValue-1; - } - - /// - /// Increments the counter and returns the new value - /// - public int IncrementAndGet() - { - var nextValue = Next; - return nextValue; - } - - /// - /// Returns the current value and adds the specified value to the counter. - /// - /// - /// - public int GetAndAdd(int amount) - { - var newValue=Interlocked.Add(ref _value, amount); - return newValue-amount; - } - - - /// - /// Adds the specified value to the counter and returns the new value - /// - /// - /// - public int AddAndGet(int amount) - { - var newValue = Interlocked.Add(ref _value, amount); - return newValue; - } - } -} - diff --git a/src/core/Akka/Util/AtomicCounterLong.cs b/src/core/Akka/Util/AtomicCounterLong.cs deleted file mode 100644 index a6ebda22f2c..00000000000 --- a/src/core/Akka/Util/AtomicCounterLong.cs +++ /dev/null @@ -1,56 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (C) 2009-2015 Typesafe Inc. -// Copyright (C) 2013-2015 Akka.NET project -// -//----------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace Akka.Util -{ - /// - /// Atomic counter that uses longs internally - /// - public class AtomicCounterLong - { - public AtomicCounterLong(long seed) - { - _seed = seed; - } - - private long _seed; - - /// - /// Retrieves the current value of the counter - /// - public long Current { get { return _seed; } } - - /// - /// Increments the counter and returns the next value - /// - public long Next - { - get - { - return Interlocked.Increment(ref _seed); - } - } - - /// - /// Returns the current value while simultaneously incrementing the counter - /// - public long GetAndIncrement() - { - var rValue = Current; - var nextValue = Next; - return rValue; - } - } -} - From e30e2dae1fa575bf14840931cb5b8b2e1cf73f86 Mon Sep 17 00:00:00 2001 From: Sean Gilliam Date: Wed, 18 Nov 2015 16:27:57 -0600 Subject: [PATCH 084/105] [misc] added missing copyright headers This PR adds copyright headers to source files that are missing them. --- .../AutoFacDependencyResolverSpecs.cs | 9 +++++++- .../CastleWindsorResolverSpec.cs | 9 +++++++- .../Akka.DI.Ninject.Tests/NinjectDiSpec.cs | 9 +++++++- .../StructureMapResolverSpec.cs | 9 +++++++- .../Akka.DI.TestKit/DiResolverSpec.cs | 9 +++++++- .../Properties/AssemblyInfo.cs | 9 +++++++- .../UnityDependencyResolverSpec.cs | 9 +++++++- .../Properties/AssemblyInfo.cs | 9 +++++++- .../Journal/ITimestampProvider.cs | 9 +++++++- .../Journal/SqlJournal.cs | 9 +++++++- .../Properties/AssemblyInfo.cs | 9 +++++++- .../Queries/Hints.cs | 9 +++++++- .../Queries/Query.cs | 9 +++++++- .../SqliteJournalQuerySpec.cs | 9 +++++++- .../SqliteJournalSpec.cs | 9 +++++++- .../SqliteSnapshotStoreSpec.cs | 9 +++++++- .../ConnectionContext.cs | 9 +++++++- .../Akka.Persistence.Sqlite/DbHelper.cs | 9 +++++++- .../Akka.Persistence.Sqlite/Extension.cs | 9 +++++++- .../Journal/SqliteJournal.cs | 9 +++++++- .../Journal/SqliteQueryBuilder.cs | 9 +++++++- .../Snapshot/QueryBuilder.cs | 9 +++++++- .../Snapshot/SqliteQueryMapper.cs | 9 +++++++- .../Snapshot/SqliteSnapshotStore.cs | 9 +++++++- .../Akka.TestKit.Xunit2/Internals/Loggers.cs | 9 +++++++- .../Routing/ClusterRouterAsk1343BugFixSpec.cs | 9 +++++++- .../Fsm/PersistentFSMSpec.cs | 9 +++++++- .../MemoryEventAdapterSpec.cs | 9 +++++++- .../LookupRemoteActorMultiNetSpec.cs | 21 ++++++++++++------- .../NewRemoteActorSpec.cs | 9 +++++++- .../PiercingShouldKeepQuarantineSpec.cs | 9 +++++++- .../RemoteDeliverySpec.cs | 9 +++++++- .../RemoteDeploymentDeathWatchSpec.cs | 1 - .../RemoteRandomSpec.cs | 9 +++++++- .../RemoteRoundRobinSpec.cs | 9 +++++++- .../Akka.Remote/RemoteDeploymentWatcher.cs | 9 +++++++- src/core/Akka.TestKit/Configs/TestConfigs.cs | 9 +++++++- src/core/Akka.TestKit/TestBreaker.cs | 9 +++++++- .../Akka.Tests/Actor/PipeToSupportSpec.cs | 9 +++++++- src/core/Akka.Tests/Util/ByteStringSpec.cs | 9 +++++++- src/core/Akka/Serialization/WireSerializer.cs | 9 +++++++- 41 files changed, 325 insertions(+), 48 deletions(-) diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/AutoFacDependencyResolverSpecs.cs b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/AutoFacDependencyResolverSpecs.cs index 74abc95e475..c5339306cda 100644 --- a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/AutoFacDependencyResolverSpecs.cs +++ b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/AutoFacDependencyResolverSpecs.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Diagnostics; using Akka.Actor; using Akka.DI.Core; diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/CastleWindsorResolverSpec.cs b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/CastleWindsorResolverSpec.cs index 742b7a8eee7..2255f1c4c09 100644 --- a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/CastleWindsorResolverSpec.cs +++ b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/CastleWindsorResolverSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Diagnostics; using Akka.Actor; using Akka.DI.Core; diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/NinjectDiSpec.cs b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/NinjectDiSpec.cs index a740d756dcb..09e2f622bcb 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/NinjectDiSpec.cs +++ b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/NinjectDiSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Diagnostics; using Akka.Actor; using Akka.DI.Core; diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/StructureMapResolverSpec.cs b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/StructureMapResolverSpec.cs index 2fb2fa246ff..2b16a3d39d9 100644 --- a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/StructureMapResolverSpec.cs +++ b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/StructureMapResolverSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Diagnostics; using Akka.Actor; using Akka.DI.Core; diff --git a/src/contrib/dependencyInjection/Akka.DI.TestKit/DiResolverSpec.cs b/src/contrib/dependencyInjection/Akka.DI.TestKit/DiResolverSpec.cs index 1b9c8d4ef41..86a8dff1770 100644 --- a/src/contrib/dependencyInjection/Akka.DI.TestKit/DiResolverSpec.cs +++ b/src/contrib/dependencyInjection/Akka.DI.TestKit/DiResolverSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Threading.Tasks; using Akka.Actor; using Akka.Configuration; diff --git a/src/contrib/dependencyInjection/Akka.DI.TestKit/Properties/AssemblyInfo.cs b/src/contrib/dependencyInjection/Akka.DI.TestKit/Properties/AssemblyInfo.cs index 90950fc57ec..2f18b47a754 100644 --- a/src/contrib/dependencyInjection/Akka.DI.TestKit/Properties/AssemblyInfo.cs +++ b/src/contrib/dependencyInjection/Akka.DI.TestKit/Properties/AssemblyInfo.cs @@ -1,4 +1,11 @@ -using System.Reflection; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/UnityDependencyResolverSpec.cs b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/UnityDependencyResolverSpec.cs index 4fb5814c130..ce367d9278b 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/UnityDependencyResolverSpec.cs +++ b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/UnityDependencyResolverSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Diagnostics; using Akka.Actor; using Akka.DI.Core; diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Properties/AssemblyInfo.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Properties/AssemblyInfo.cs index 6456fcd8179..c7e4a04c7d3 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Properties/AssemblyInfo.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Properties/AssemblyInfo.cs @@ -1,4 +1,11 @@ -using System.Reflection; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/ITimestampProvider.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/ITimestampProvider.cs index 5f4863ae8ce..489d65abbb2 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/ITimestampProvider.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/ITimestampProvider.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; namespace Akka.Persistence.Sql.Common.Journal { diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs index aa2ca187f06..717043ba8fa 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/SqlJournal.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Threading.Tasks; using Akka.Actor; diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Properties/AssemblyInfo.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Properties/AssemblyInfo.cs index e4be5070d3a..2a17173352c 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Properties/AssemblyInfo.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Properties/AssemblyInfo.cs @@ -1,4 +1,11 @@ -using System.Reflection; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Hints.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Hints.cs index 325de835ef5..fc689d8ab38 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Hints.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Hints.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using Akka.Persistence.Sql.Common.Journal; diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Query.cs b/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Query.cs index 426d2a015d0..0b4fbf00896 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Query.cs +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common/Queries/Query.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using Akka.Actor; diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalQuerySpec.cs b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalQuerySpec.cs index 8b52dc8aebd..dee6ead9ced 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalQuerySpec.cs +++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalQuerySpec.cs @@ -1,4 +1,11 @@ -using Akka.Configuration; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using Akka.Configuration; using Akka.Persistence.Sql.Common.TestKit; using Akka.Util.Internal; using Xunit.Abstractions; diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalSpec.cs b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalSpec.cs index 0e537f55ed4..d013853bb37 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalSpec.cs +++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteJournalSpec.cs @@ -1,4 +1,11 @@ -using Akka.Configuration; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using Akka.Configuration; using Akka.Persistence.TestKit.Journal; using Akka.Util.Internal; using Xunit.Abstractions; diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteSnapshotStoreSpec.cs b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteSnapshotStoreSpec.cs index 2274c9cee13..0ae89f72389 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteSnapshotStoreSpec.cs +++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/SqliteSnapshotStoreSpec.cs @@ -1,4 +1,11 @@ -using Akka.Configuration; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using Akka.Configuration; using Akka.Persistence.TestKit.Snapshot; using Akka.Util.Internal; using Xunit.Abstractions; diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/ConnectionContext.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/ConnectionContext.cs index 99415957e1d..1a3686d51da 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/ConnectionContext.cs +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/ConnectionContext.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Concurrent; using System.Data; using System.Data.SQLite; diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/DbHelper.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/DbHelper.cs index b18328b56b2..e38d7f5fd66 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/DbHelper.cs +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/DbHelper.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Data.SQLite; namespace Akka.Persistence.Sqlite diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Extension.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Extension.cs index 0a196992384..d39b34cd739 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/Extension.cs +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Extension.cs @@ -1,4 +1,11 @@ -using Akka.Actor; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using Akka.Actor; using Akka.Configuration; using Akka.Persistence.Sql.Common; diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteJournal.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteJournal.cs index a09049f50b6..9a57055fa5a 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteJournal.cs +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteJournal.cs @@ -1,4 +1,11 @@ -using System.Data.Common; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System.Data.Common; using System.Data.SQLite; using Akka.Actor; using Akka.Persistence.Sql.Common.Journal; diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteQueryBuilder.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteQueryBuilder.cs index 131f556445b..d211b021057 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteQueryBuilder.cs +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Journal/SqliteQueryBuilder.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Data; using System.Data.Common; diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/QueryBuilder.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/QueryBuilder.cs index 4f0a38f29ca..a17e63d2db6 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/QueryBuilder.cs +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/QueryBuilder.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Data; using System.Data.Common; using System.Data.SQLite; diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteQueryMapper.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteQueryMapper.cs index 4688bb53113..db8d6f20e64 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteQueryMapper.cs +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteQueryMapper.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Data.Common; using Akka.Persistence.Sql.Common.Snapshot; diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteSnapshotStore.cs b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteSnapshotStore.cs index 443cb44e37d..3fe65a3b3d7 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteSnapshotStore.cs +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Snapshot/SqliteSnapshotStore.cs @@ -1,4 +1,11 @@ -using System.Data.Common; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System.Data.Common; using System.Data.SQLite; using Akka.Persistence.Sql.Common; using Akka.Persistence.Sql.Common.Snapshot; diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/Loggers.cs b/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/Loggers.cs index a8339619bc6..4d4bff5202e 100644 --- a/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/Loggers.cs +++ b/src/contrib/testkits/Akka.TestKit.Xunit2/Internals/Loggers.cs @@ -1,4 +1,11 @@ -using Akka.Actor; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using Akka.Actor; using Akka.Event; using Xunit.Abstractions; diff --git a/src/core/Akka.Cluster.Tests/Routing/ClusterRouterAsk1343BugFixSpec.cs b/src/core/Akka.Cluster.Tests/Routing/ClusterRouterAsk1343BugFixSpec.cs index 49dd1ca7308..fd31ef6f2b0 100644 --- a/src/core/Akka.Cluster.Tests/Routing/ClusterRouterAsk1343BugFixSpec.cs +++ b/src/core/Akka.Cluster.Tests/Routing/ClusterRouterAsk1343BugFixSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs index 1c021fdafac..dcf893b304a 100644 --- a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs +++ b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Linq; using Akka.Actor; diff --git a/src/core/Akka.Persistence.Tests/MemoryEventAdapterSpec.cs b/src/core/Akka.Persistence.Tests/MemoryEventAdapterSpec.cs index 908a60f00c9..d1f297d74ef 100644 --- a/src/core/Akka.Persistence.Tests/MemoryEventAdapterSpec.cs +++ b/src/core/Akka.Persistence.Tests/MemoryEventAdapterSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Linq; using Akka.Actor; diff --git a/src/core/Akka.Remote.Tests.MultiNode/LookupRemoteActorMultiNetSpec.cs b/src/core/Akka.Remote.Tests.MultiNode/LookupRemoteActorMultiNetSpec.cs index 2da45e20c42..9f9c17006c8 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/LookupRemoteActorMultiNetSpec.cs +++ b/src/core/Akka.Remote.Tests.MultiNode/LookupRemoteActorMultiNetSpec.cs @@ -1,12 +1,17 @@ -namespace Akka.Remote.Tests.MultiNode +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using Akka.Actor; +using Akka.Remote.TestKit; +using Xunit; + +namespace Akka.Remote.Tests.MultiNode { - using System; - - using Akka.Actor; - using Akka.Remote.TestKit; - - using Xunit; - public class LookupRemoteActorMultiNetSpec : MultiNodeConfig { public RoleName Master { get; private set; } diff --git a/src/core/Akka.Remote.Tests.MultiNode/NewRemoteActorSpec.cs b/src/core/Akka.Remote.Tests.MultiNode/NewRemoteActorSpec.cs index 208db3b0983..d556fa6052d 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/NewRemoteActorSpec.cs +++ b/src/core/Akka.Remote.Tests.MultiNode/NewRemoteActorSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using Akka.Actor; using Akka.Configuration; using Akka.Remote.TestKit; diff --git a/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs b/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs index 89847f1f3bd..87033a9394b 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs +++ b/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/core/Akka.Remote.Tests.MultiNode/RemoteDeliverySpec.cs b/src/core/Akka.Remote.Tests.MultiNode/RemoteDeliverySpec.cs index 695a1adea2c..d820a161e90 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/RemoteDeliverySpec.cs +++ b/src/core/Akka.Remote.Tests.MultiNode/RemoteDeliverySpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Linq; using Akka.Actor; diff --git a/src/core/Akka.Remote.Tests.MultiNode/RemoteDeploymentDeathWatchSpec.cs b/src/core/Akka.Remote.Tests.MultiNode/RemoteDeploymentDeathWatchSpec.cs index d30964e26ab..6553b4a41f6 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/RemoteDeploymentDeathWatchSpec.cs +++ b/src/core/Akka.Remote.Tests.MultiNode/RemoteDeploymentDeathWatchSpec.cs @@ -5,7 +5,6 @@ // //----------------------------------------------------------------------- - using System; using System.Threading; using Akka.Actor; diff --git a/src/core/Akka.Remote.Tests.MultiNode/RemoteRandomSpec.cs b/src/core/Akka.Remote.Tests.MultiNode/RemoteRandomSpec.cs index 2371c5c7fde..c477e04b8a1 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/RemoteRandomSpec.cs +++ b/src/core/Akka.Remote.Tests.MultiNode/RemoteRandomSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; diff --git a/src/core/Akka.Remote.Tests.MultiNode/RemoteRoundRobinSpec.cs b/src/core/Akka.Remote.Tests.MultiNode/RemoteRoundRobinSpec.cs index 4eecdc98843..4f7495a1c18 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/RemoteRoundRobinSpec.cs +++ b/src/core/Akka.Remote.Tests.MultiNode/RemoteRoundRobinSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; diff --git a/src/core/Akka.Remote/RemoteDeploymentWatcher.cs b/src/core/Akka.Remote/RemoteDeploymentWatcher.cs index 0ec8aa3c01b..0668ee13ab1 100644 --- a/src/core/Akka.Remote/RemoteDeploymentWatcher.cs +++ b/src/core/Akka.Remote/RemoteDeploymentWatcher.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/core/Akka.TestKit/Configs/TestConfigs.cs b/src/core/Akka.TestKit/Configs/TestConfigs.cs index ad4540e4ae7..cb2866935f3 100644 --- a/src/core/Akka.TestKit/Configs/TestConfigs.cs +++ b/src/core/Akka.TestKit/Configs/TestConfigs.cs @@ -1,4 +1,11 @@ -using Akka.Configuration; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using Akka.Configuration; namespace Akka.TestKit.Configs { diff --git a/src/core/Akka.TestKit/TestBreaker.cs b/src/core/Akka.TestKit/TestBreaker.cs index ac188f853e4..1d3f858b98f 100644 --- a/src/core/Akka.TestKit/TestBreaker.cs +++ b/src/core/Akka.TestKit/TestBreaker.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Linq; using System.Runtime.Serialization; using System.Threading; diff --git a/src/core/Akka.Tests/Actor/PipeToSupportSpec.cs b/src/core/Akka.Tests/Actor/PipeToSupportSpec.cs index 57fc49173a3..2b07a60a66e 100644 --- a/src/core/Akka.Tests/Actor/PipeToSupportSpec.cs +++ b/src/core/Akka.Tests/Actor/PipeToSupportSpec.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Threading.Tasks; using Akka.Actor; using Akka.Event; diff --git a/src/core/Akka.Tests/Util/ByteStringSpec.cs b/src/core/Akka.Tests/Util/ByteStringSpec.cs index 7ce6cace1c6..ce5a3ca5f58 100644 --- a/src/core/Akka.Tests/Util/ByteStringSpec.cs +++ b/src/core/Akka.Tests/Util/ByteStringSpec.cs @@ -1,4 +1,11 @@ -using System.Linq; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System.Linq; using System.Text; using Akka.IO; using FsCheck; diff --git a/src/core/Akka/Serialization/WireSerializer.cs b/src/core/Akka/Serialization/WireSerializer.cs index 96775206791..3b2c5505d58 100644 --- a/src/core/Akka/Serialization/WireSerializer.cs +++ b/src/core/Akka/Serialization/WireSerializer.cs @@ -1,4 +1,11 @@ -using System; +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; using System.Collections.Generic; using System.IO; using System.Linq; From e10cfd1744d5d89352675bd53d9cfceac5280000 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Thu, 19 Nov 2015 14:14:55 -0800 Subject: [PATCH 085/105] Revert "Multinode test runner alterations" --- .../Akka.MultiNodeTestRunner.csproj | 8 +- ...kka.MultiNodeTestRunner.csproj.DotSettings | 2 - src/core/Akka.MultiNodeTestRunner/App.config | 17 +- src/core/Akka.MultiNodeTestRunner/Program.cs | 203 +++++------------- .../Akka.NodeTestRunner.csproj | 3 - .../Akka.NodeTestRunner.csproj.DotSettings | 2 - src/core/Akka.NodeTestRunner/App.config | 7 +- src/core/Akka.NodeTestRunner/ITestRunner.cs | 16 -- .../Akka.NodeTestRunner/IsolatedTestRunner.cs | 58 ----- src/core/Akka.NodeTestRunner/Program.cs | 65 +++++- src/core/Akka.NodeTestRunner/TestRunner.cs | 82 ------- src/core/Akka.NodeTestRunner/paket.references | 2 +- .../Akka.Remote.TestKit.csproj | 2 +- src/core/Akka.Remote.TestKit/CommandLine.cs | 52 +++++ src/core/Akka.Remote.TestKit/MultiNodeSpec.cs | 12 +- src/core/Akka.Remote.TestKit/TestSettings.cs | 73 ------- .../PiercingShouldKeepQuarantineSpec.cs | 2 +- 17 files changed, 186 insertions(+), 420 deletions(-) delete mode 100644 src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj.DotSettings delete mode 100644 src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj.DotSettings delete mode 100644 src/core/Akka.NodeTestRunner/ITestRunner.cs delete mode 100644 src/core/Akka.NodeTestRunner/IsolatedTestRunner.cs delete mode 100644 src/core/Akka.NodeTestRunner/TestRunner.cs create mode 100644 src/core/Akka.Remote.TestKit/CommandLine.cs delete mode 100644 src/core/Akka.Remote.TestKit/TestSettings.cs diff --git a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj index 414b905fcda..794443b1322 100644 --- a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj +++ b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj @@ -40,17 +40,15 @@ - - TestSettings.cs + + CommandLine.cs - - Designer - + diff --git a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj.DotSettings b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj.DotSettings deleted file mode 100644 index 662f95686eb..00000000000 --- a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj.DotSettings +++ /dev/null @@ -1,2 +0,0 @@ - - CSharp50 \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/App.config b/src/core/Akka.MultiNodeTestRunner/App.config index 7421531d914..5126174a197 100644 --- a/src/core/Akka.MultiNodeTestRunner/App.config +++ b/src/core/Akka.MultiNodeTestRunner/App.config @@ -1,17 +1,16 @@  - - - - - + + + + - + - + @@ -63,11 +62,11 @@ - + - + diff --git a/src/core/Akka.MultiNodeTestRunner/Program.cs b/src/core/Akka.MultiNodeTestRunner/Program.cs index ced7b026e4e..5ae1a09a5f1 100644 --- a/src/core/Akka.MultiNodeTestRunner/Program.cs +++ b/src/core/Akka.MultiNodeTestRunner/Program.cs @@ -21,8 +21,6 @@ namespace Akka.MultiNodeTestRunner { - using Akka.NodeTestRunner; - /// /// Entry point for the MultiNodeTestRunner /// @@ -37,10 +35,7 @@ class Program /// /// MultiNodeTestRunner takes the following : /// - /// C:\> Akka.MultiNodeTestRunner.exe [assembly name] - /// [-Dmultinode.enable-filesink=on] - /// [-Dmultinode.output-directory={dir path}] - /// [-Dmultinode.test-spec={name of spec}] + /// C:\> Akka.MultiNodeTestRunner.exe [assembly name] [-Dmultinode.enable-filesink=on] [-Dmultinode.output-directory={dir path}] /// /// /// @@ -69,30 +64,16 @@ class Program /// as the test binary. /// /// - /// - /// -Dmultinode.test-spec - /// Setting this property means that only the test/s which match this name will be run. - /// Any other tests will be skipped. - /// - /// /// /// static void Main(string[] args) { - TestSettings.Initialize(args); - TestRunSystem = ActorSystem.Create("TestRunnerLogging"); SinkCoordinator = TestRunSystem.ActorOf(Props.Create(), "sinkCoordinator"); var assemblyName = Path.GetFullPath(args[0]); EnableAllSinks(assemblyName); - PublishRunnerMessage(string.Format("Running MultiNodeTests for {0}", assemblyName)); - - var specificationName = TestSettings.GetProperty("multinode.test-spec"); - bool restrictToTestName = !string.IsNullOrEmpty(specificationName); - - var autoLoadDebugger = TestSettings.GetProperty("multinode.auto-debug") != string.Empty; - var useAppDomains = TestSettings.GetProperty("multinode.use-appdomains") != string.Empty; + PublishRunnerMessage(String.Format("Running MultiNodeTests for {0}", assemblyName)); using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, assemblyName)) { @@ -109,22 +90,60 @@ static void Main(string[] args) continue; } - if ( restrictToTestName && string.Compare(test.Key, specificationName, StringComparison.OrdinalIgnoreCase) != 0) - { - PublishRunnerMessage(string.Format("Skipping test {0}.{1}. Reason - Doesn't match multinode.spec-name.", test.Value.First().TestName, test.Value.First().MethodName)); - continue; - } - PublishRunnerMessage(string.Format("Starting test {0}", test.Value.First().MethodName)); - if (!useAppDomains) + var processes = new List(); + + StartNewSpec(test.Value); + + foreach (var nodeTest in test.Value) { - RunNodesInSeperateProcesses(test, assemblyName); + //Loop through each test, work out number of nodes to run on and kick off process + var process = new Process(); + processes.Add(process); + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.FileName = "Akka.NodeTestRunner.exe"; + process.StartInfo.Arguments = String.Format(@"-Dmultinode.test-assembly=""{0}"" -Dmultinode.test-class=""{1}"" -Dmultinode.test-method=""{2}"" -Dmultinode.max-nodes={3} -Dmultinode.server-host=""{4}"" -Dmultinode.host=""{5}"" -Dmultinode.index={6}", + assemblyName, nodeTest.TypeName, nodeTest.MethodName, test.Value.Count, "localhost", "localhost", nodeTest.Node - 1); + var nodeIndex = nodeTest.Node; + process.OutputDataReceived += + (sender, line) => + { + //ignore any trailing whitespace + if (string.IsNullOrEmpty(line.Data) || string.IsNullOrWhiteSpace(line.Data)) return; + string message = line.Data; + if (!message.StartsWith("[NODE", true, CultureInfo.InvariantCulture)) + { + message = "[NODE" + nodeIndex + "]" + message; + } + PublishToAllSinks(message); + }; + + var closureTest = nodeTest; + process.Exited += (sender, eventArgs) => + { + if (process.ExitCode == 0) + { + ReportSpecPassFromExitCode(nodeIndex, closureTest.TestName); + } + }; + process.Start(); + + process.BeginOutputReadLine(); + PublishRunnerMessage(string.Format("Started node {0} on pid {1}", nodeTest.Node, process.Id)); } - else + + foreach (var process in processes) { - RunNodesInAppDomains(test, assemblyName, autoLoadDebugger); + process.WaitForExit(); + var exitCode = process.ExitCode; + process.Close(); } + + PublishRunnerMessage("Waiting 3 seconds for all messages from all processes to be collected."); + Thread.Sleep(TimeSpan.FromSeconds(3)); + FinishSpec(); } } } @@ -140,131 +159,13 @@ static void Main(string[] args) Environment.Exit(ExitCodeContainer.ExitCode); } - private static void RunNodesInAppDomains(KeyValuePair> test, string assemblyName, bool autoLaunchDebugger) - { - var runners = new List>(); - - if (autoLaunchDebugger) - { - Debugger.Launch(); - } - - StartNewSpec(test.Value); - - foreach (var nodeTest in test.Value) - { - var testArguments = new[] - { - string.Format(@"-Dmultinode.test-assembly={0}", assemblyName), - string.Format(@"-Dmultinode.test-class={0}", nodeTest.TypeName), - string.Format(@"-Dmultinode.test-method={0}", nodeTest.MethodName), - string.Format(@"-Dmultinode.max-nodes={0}", test.Value.Count), - string.Format(@"-Dmultinode.server-host={0}", "localhost"), - string.Format(@"-Dmultinode.host={0}", "localhost"), - string.Format(@"-Dmultinode.index={0}", nodeTest.Node - 1), - }; - - var testRunner = new IsolatedTestRunner(); - testRunner.InitializeWithTestArgs(testArguments); - - var thread = new Thread(testRunner.Run); - runners.Add(new Tuple(nodeTest.Node, testRunner, thread)); - - //TODO: override console output - // Figure out how to add in any missing [NODE prefixes. - - thread.Start(); - - PublishRunnerMessage(string.Format("Started node {0} on thread id {1}", nodeTest.Node, thread.ManagedThreadId)); - } - - foreach (var process in runners) - { - process.Item3.Join(); - var noErrors = process.Item2.NoErrors; - if (noErrors) - { - ReportSpecPassFromExitCode(process.Item1, "Something Something"); - } - } - - PublishRunnerMessage("Waiting 3 seconds for all messages from all processes to be collected."); - Thread.Sleep(TimeSpan.FromSeconds(3)); - FinishSpec(); - } - - private static void RunNodesInSeperateProcesses(KeyValuePair> test, string assemblyName) - { - var processes = new List(); - - StartNewSpec(test.Value); - - foreach (var nodeTest in test.Value) - { - var testArguments = - string.Format( - @"-Dmultinode.test-assembly=""{0}"" -Dmultinode.test-class=""{1}"" -Dmultinode.test-method=""{2}"" -Dmultinode.max-nodes={3} -Dmultinode.server-host=""{4}"" -Dmultinode.host=""{5}"" -Dmultinode.index={6}", - assemblyName, - nodeTest.TypeName, - nodeTest.MethodName, - test.Value.Count, - "localhost", - "localhost", - nodeTest.Node - 1); - - //Loop through each test, work out number of nodes to run on and kick off process - var process = new Process(); - processes.Add(process); - process.StartInfo.UseShellExecute = false; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.FileName = "Akka.NodeTestRunner.exe"; - process.StartInfo.Arguments = testArguments; - var nodeIndex = nodeTest.Node; - process.OutputDataReceived += (sender, line) => - { - //ignore any trailing whitespace - if (string.IsNullOrEmpty(line.Data) || string.IsNullOrWhiteSpace(line.Data)) return; - string message = line.Data; - if (!message.StartsWith("[NODE", true, CultureInfo.InvariantCulture)) - { - message = "[NODE" + nodeIndex + "]" + message; - } - PublishToAllSinks(message); - }; - - var closureTest = nodeTest; - process.Exited += (sender, eventArgs) => - { - if (process.ExitCode == 0) - { - ReportSpecPassFromExitCode(nodeIndex, closureTest.TestName); - } - }; - process.Start(); - - process.BeginOutputReadLine(); - PublishRunnerMessage(string.Format("Started node {0} on pid {1}", nodeTest.Node, process.Id)); - } - - foreach (var process in processes) - { - process.WaitForExit(); - var exitCode = process.ExitCode; - process.Close(); - } - - PublishRunnerMessage("Waiting 3 seconds for all messages from all processes to be collected."); - Thread.Sleep(TimeSpan.FromSeconds(3)); - FinishSpec(); - } - static void EnableAllSinks(string assemblyName) { var now = DateTime.UtcNow; // if multinode.output-directory wasn't specified, the results files will be written // to the same directory as the test assembly. - var outputDirectory = TestSettings.GetProperty("multinode.output-directory"); + var outputDirectory = CommandLine.GetProperty("multinode.output-directory"); Func createJsonFileSink = () => { @@ -286,7 +187,7 @@ static void EnableAllSinks(string assemblyName) return new FileSystemMessageSink(visualizerProps); }; - var fileSystemSink = TestSettings.GetProperty("multinode.enable-filesink"); + var fileSystemSink = CommandLine.GetProperty("multinode.enable-filesink"); if (!string.IsNullOrEmpty(fileSystemSink)) { SinkCoordinator.Tell(new SinkCoordinator.EnableSink(createJsonFileSink())); diff --git a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj index 95452d05c7e..cf995b9aaf1 100644 --- a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj +++ b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj @@ -53,12 +53,9 @@ - - - diff --git a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj.DotSettings b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj.DotSettings deleted file mode 100644 index 662f95686eb..00000000000 --- a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj.DotSettings +++ /dev/null @@ -1,2 +0,0 @@ - - CSharp50 \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/App.config b/src/core/Akka.NodeTestRunner/App.config index 2bc9ebaa0b1..060f4e63806 100644 --- a/src/core/Akka.NodeTestRunner/App.config +++ b/src/core/Akka.NodeTestRunner/App.config @@ -12,8 +12,7 @@ - - + @@ -122,10 +121,6 @@ - - - - diff --git a/src/core/Akka.NodeTestRunner/ITestRunner.cs b/src/core/Akka.NodeTestRunner/ITestRunner.cs deleted file mode 100644 index 1c091ac6227..00000000000 --- a/src/core/Akka.NodeTestRunner/ITestRunner.cs +++ /dev/null @@ -1,16 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (C) 2009-2015 Typesafe Inc. -// Copyright (C) 2013-2015 Akka.NET project -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace Akka.NodeTestRunner -{ - public interface ITestRunner - { - void Run(); - void InitializeWithTestArgs(string[] testArgs); - bool NoErrors { get; } - } -} \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/IsolatedTestRunner.cs b/src/core/Akka.NodeTestRunner/IsolatedTestRunner.cs deleted file mode 100644 index 7947dd40935..00000000000 --- a/src/core/Akka.NodeTestRunner/IsolatedTestRunner.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (C) 2009-2015 Typesafe Inc. -// Copyright (C) 2013-2015 Akka.NET project -// -// -------------------------------------------------------------------------------------------------------------------- - -using System; - -namespace Akka.NodeTestRunner -{ - public class IsolatedTestRunner : IDisposable, ITestRunner - { - private readonly TestRunner _runner; - private AppDomain _domain; - - public IsolatedTestRunner() - { - var type = typeof (TestRunner); - var friendlyName = string.Format("TestRunner:{0}", Guid.NewGuid()); - - var appDomainSetup = AppDomain.CurrentDomain.SetupInformation; - appDomainSetup.DisallowBindingRedirects = true; - appDomainSetup.ConfigurationFile = string.Empty; - - _domain = AppDomain.CreateDomain( - friendlyName, - AppDomain.CurrentDomain.Evidence, - appDomainSetup); - - _runner = (TestRunner) _domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName); - } - - public void Dispose() - { - if (_domain != null) - { - AppDomain.Unload(_domain); - _domain = null; - } - } - - public void Run() - { - _runner.Run(); - } - - public void InitializeWithTestArgs(string[] testArgs) - { - _runner.InitializeWithTestArgs(testArgs); - } - - public bool NoErrors - { - get { return _runner.NoErrors; } - } - } -} \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/Program.cs b/src/core/Akka.NodeTestRunner/Program.cs index 1f5a4a166b9..77c13d8c773 100644 --- a/src/core/Akka.NodeTestRunner/Program.cs +++ b/src/core/Akka.NodeTestRunner/Program.cs @@ -6,6 +6,10 @@ //----------------------------------------------------------------------- using System; +using System.IO; +using System.Threading; +using Akka.Remote.TestKit; +using Xunit; namespace Akka.NodeTestRunner { @@ -13,10 +17,63 @@ class Program { static void Main(string[] args) { - var runner = new TestRunner(); - runner.InitializeWithTestArgs(args); - runner.Run(); - Environment.Exit(runner.NoErrors ? 0 : 1); + var nodeIndex = CommandLine.GetInt32("multinode.index"); + var assemblyFileName = CommandLine.GetProperty("multinode.test-assembly"); + var typeName = CommandLine.GetProperty("multinode.test-class"); + var testName = CommandLine.GetProperty("multinode.test-method"); + var displayName = testName; + + Thread.Sleep(TimeSpan.FromSeconds(10)); + + using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, assemblyFileName)) + { + /* need to pass in just the assembly name to Discovery, not the full path + * i.e. "Akka.Cluster.Tests.MultiNode.dll" + * not "bin/Release/Akka.Cluster.Tests.MultiNode.dll" - this will cause + * the Discovery class to actually not find any indivudal specs to run + */ + var assemblyName = Path.GetFileName(assemblyFileName); + Console.WriteLine("Running specs for {0} [{1}]", assemblyName, assemblyFileName); + using (var discovery = new Discovery(assemblyName, typeName)) + { + using (var sink = new Sink(nodeIndex)) + { + Thread.Sleep(10000); + try + { + controller.Find(true, discovery, TestFrameworkOptions.ForDiscovery()); + discovery.Finished.WaitOne(); + controller.RunTests(discovery.TestCases, sink, TestFrameworkOptions.ForExecution()); + } + catch (AggregateException ex) + { + var specFail = new SpecFail(nodeIndex, displayName); + specFail.FailureExceptionTypes.Add(ex.GetType().ToString()); + specFail.FailureMessages.Add(ex.Message); + specFail.FailureStackTraces.Add(ex.StackTrace); + foreach (var innerEx in ex.Flatten().InnerExceptions) + { + specFail.FailureExceptionTypes.Add(innerEx.GetType().ToString()); + specFail.FailureMessages.Add(innerEx.Message); + specFail.FailureStackTraces.Add(innerEx.StackTrace); + } + Console.WriteLine(specFail); + Environment.Exit(1); //signal failure + } + catch (Exception ex) + { + var specFail = new SpecFail(nodeIndex, displayName); + specFail.FailureExceptionTypes.Add(ex.GetType().ToString()); + specFail.FailureMessages.Add(ex.Message); + specFail.FailureStackTraces.Add(ex.StackTrace); + Console.WriteLine(specFail); + Environment.Exit(1); //signal failure + } + sink.Finished.WaitOne(); + Environment.Exit(sink.Passed ? 0 : 1); + } + } + } } } } diff --git a/src/core/Akka.NodeTestRunner/TestRunner.cs b/src/core/Akka.NodeTestRunner/TestRunner.cs deleted file mode 100644 index d6040f1b4be..00000000000 --- a/src/core/Akka.NodeTestRunner/TestRunner.cs +++ /dev/null @@ -1,82 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (C) 2009-2015 Typesafe Inc. -// Copyright (C) 2013-2015 Akka.NET project -// -// -------------------------------------------------------------------------------------------------------------------- -namespace Akka.NodeTestRunner -{ - using System; - using System.IO; - - using Akka.Remote.TestKit; - - using Xunit; - - public class TestRunner : MarshalByRefObject, ITestRunner - { - public bool NoErrors { get; private set; } - - public void InitializeWithTestArgs(string[] testArgs) - { - TestSettings.Initialize(testArgs); - } - - public void Run() - { - - var nodeIndex = TestSettings.GetInt32("multinode.index"); - var assemblyFileName = TestSettings.GetProperty("multinode.test-assembly"); - var typeName = TestSettings.GetProperty("multinode.test-class"); - var displayName = TestSettings.GetProperty("multinode.test-method"); - - /* need to pass in just the assembly name to Discovery, not the full path - * i.e. "Akka.Cluster.Tests.MultiNode.dll" - * not "bin/Release/Akka.Cluster.Tests.MultiNode.dll" - this will cause - * the Discovery class to actually not find any individual specs to run - */ - var assemblyName = Path.GetFileName(assemblyFileName); - Console.WriteLine("Running specs for {0} [{1}]", assemblyName, assemblyFileName); - - using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, assemblyFileName)) - using (var discovery = new Discovery(assemblyName, typeName)) - using (var sink = new Sink(nodeIndex)) - { - try - { - controller.Find(true, discovery, TestFrameworkOptions.ForDiscovery()); - discovery.Finished.WaitOne(); - controller.RunTests(discovery.TestCases, sink, TestFrameworkOptions.ForExecution()); - } - catch (AggregateException ex) - { - var specFail = new SpecFail(nodeIndex, displayName); - specFail.FailureExceptionTypes.Add(ex.GetType().ToString()); - specFail.FailureMessages.Add(ex.Message); - specFail.FailureStackTraces.Add(ex.StackTrace); - foreach (var innerEx in ex.Flatten().InnerExceptions) - { - specFail.FailureExceptionTypes.Add(innerEx.GetType().ToString()); - specFail.FailureMessages.Add(innerEx.Message); - specFail.FailureStackTraces.Add(innerEx.StackTrace); - } - Console.WriteLine(specFail); - this.NoErrors = false; - return; - } - catch (Exception ex) - { - var specFail = new SpecFail(nodeIndex, displayName); - specFail.FailureExceptionTypes.Add(ex.GetType().ToString()); - specFail.FailureMessages.Add(ex.Message); - specFail.FailureStackTraces.Add(ex.StackTrace); - Console.WriteLine(specFail); - this.NoErrors = false; - return; - } - sink.Finished.WaitOne(); - this.NoErrors = sink.Passed; - } - } - } -} \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/paket.references b/src/core/Akka.NodeTestRunner/paket.references index 13118143843..d15f7ae54a1 100644 --- a/src/core/Akka.NodeTestRunner/paket.references +++ b/src/core/Akka.NodeTestRunner/paket.references @@ -1,3 +1,3 @@ group Test xunit.abstractions -xunit.runner.utility +xunit.runner.utility \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj index 3a63828fb0a..32220732774 100644 --- a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj +++ b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj @@ -59,7 +59,7 @@ - + diff --git a/src/core/Akka.Remote.TestKit/CommandLine.cs b/src/core/Akka.Remote.TestKit/CommandLine.cs new file mode 100644 index 00000000000..d785da35fa7 --- /dev/null +++ b/src/core/Akka.Remote.TestKit/CommandLine.cs @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Specialized; + +namespace Akka.Remote.TestKit +{ + //TODO: Needs some work + /// + /// Command line argument parser for individual node tests during a . + /// + /// Parses arguments from using the same conventions as canonical Akka. + /// + /// For example (from the Akka.NodeTestRunner source): + /// + /// var nodeIndex = CommandLine.GetInt32("multinode.index"); + /// var assemblyName = CommandLine.GetProperty("multinode.test-assembly"); + /// var typeName = CommandLine.GetProperty("multinode.test-class"); + /// var testName = CommandLine.GetProperty("multinode.test-method"); + /// + /// + public class CommandLine + { + private readonly static Lazy Values = new Lazy(() => + { + var dictionary = new StringDictionary(); + foreach (var arg in Environment.GetCommandLineArgs()) + { + if (!arg.StartsWith("-D")) continue; + var tokens = arg.Substring(2).Split('='); + dictionary.Add(tokens[0], tokens[1]); + } + return dictionary; + }); + + public static string GetProperty(string key) + { + return Values.Value[key]; + } + + public static int GetInt32(string key) + { + return Convert.ToInt32(GetProperty(key)); + } + } +} + diff --git a/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs b/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs index acb4950ae51..2bb1b21285f 100644 --- a/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs +++ b/src/core/Akka.Remote.TestKit/MultiNodeSpec.cs @@ -185,7 +185,7 @@ public static int MaxNodes { if (_maxNodes == MaxNodesUnset) { - _maxNodes = TestSettings.GetInt32("multinode.max-nodes"); + _maxNodes = CommandLine.GetInt32("multinode.max-nodes"); } if (_maxNodes <= 0) throw new InvalidOperationException("multinode.max-nodes must be greater than 0"); @@ -210,7 +210,7 @@ public static string SelfName { if (string.IsNullOrEmpty(_multiNodeHost)) { - _multiNodeHost = TestSettings.GetProperty("multinode.host"); + _multiNodeHost = CommandLine.GetProperty("multinode.host"); } //Run this assertion every time. Consistency is more important than performance. @@ -237,7 +237,7 @@ public static int SelfPort { if (_selfPort == SelfPortUnsetValue) //unset { - var selfPortStr = TestSettings.GetProperty("multinode.port"); + var selfPortStr = CommandLine.GetProperty("multinode.port"); _selfPort = string.IsNullOrEmpty(selfPortStr) ? 0 : Int32.Parse(selfPortStr); } @@ -259,7 +259,7 @@ public static string ServerName { if (string.IsNullOrEmpty(_serverName)) { - _serverName = TestSettings.GetProperty("multinode.server-host"); + _serverName = CommandLine.GetProperty("multinode.server-host"); } if (string.IsNullOrEmpty(_serverName)) throw new InvalidOperationException("multinode.server-host must not be empty"); return _serverName; @@ -289,7 +289,7 @@ public static int ServerPort { if (_serverPort == ServerPortUnsetValue) { - var serverPortStr = TestSettings.GetProperty("multinode.server-port"); + var serverPortStr = CommandLine.GetProperty("multinode.server-port"); _serverPort = string.IsNullOrEmpty(serverPortStr) ? ServerPortDefault : Int32.Parse(serverPortStr); } @@ -316,7 +316,7 @@ public static int SelfIndex { if (_selfIndex == SelfIndexUnset) { - _selfIndex = TestSettings.GetInt32("multinode.index"); + _selfIndex = CommandLine.GetInt32("multinode.index"); } if (!(_selfIndex >= 0 && _selfIndex < MaxNodes)) throw new InvalidOperationException("multinode.index is out of bounds: " + _selfIndex); diff --git a/src/core/Akka.Remote.TestKit/TestSettings.cs b/src/core/Akka.Remote.TestKit/TestSettings.cs deleted file mode 100644 index 3713a8a654e..00000000000 --- a/src/core/Akka.Remote.TestKit/TestSettings.cs +++ /dev/null @@ -1,73 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (C) 2009-2015 Typesafe Inc. -// Copyright (C) 2013-2015 Akka.NET project -// -//----------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Remoting.Messaging; - -namespace Akka.Remote.TestKit -{ - /// - /// Test argument parser for indivudla node tests during a . - /// - /// Parses arguments using the same conventions as canonical Akka. - /// - /// Relies on being directly initialized rather than using Environment.GetCommandLineArgs(). - /// This allows us to abstract the runner (AppDomain or Process) from the test. - /// - public static class TestSettings - { - private const string CallContextName = "MultiNode settings CallContext"; - - public static void Initialize(string[] args) - { - var argsDictionary = new Dictionary(); - - args.Where(arg => arg.StartsWith("-D")) - .Select(arg => arg.Substring(2).Split('=')) - .Select(tokens => argsDictionary[tokens[0]] = tokens[1]) - .Ignore(); - - CallContext.LogicalSetData(CallContextName, argsDictionary); - } - - public static string GetProperty(string key) - { - try - { - var args =(Dictionary)CallContext.LogicalGetData(CallContextName); - return args[key]; - } - catch (KeyNotFoundException) - { - return string.Empty; - } - } - - public static int GetInt32(string key) - { - return Convert.ToInt32(GetProperty(key)); - } - } - - public static class EnumerableExtensions - { - /// - /// We just want the side effects. - /// - /// The source enumerable - public static void Ignore(this IEnumerable stream) - { - var enumerator = stream.GetEnumerator(); - while (enumerator.MoveNext()) - { - //nop - } - } - } -} \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs b/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs index 89847f1f3bd..bcb9d37f311 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs +++ b/src/core/Akka.Remote.Tests.MultiNode/PiercingShouldKeepQuarantineSpec.cs @@ -20,7 +20,7 @@ public PiercingShouldKeepQuarantineMultiNodeConfig() First = Role("first"); Second = Role("second"); - CommonConfig = DebugConfig(false) + CommonConfig = DebugConfig(true) .WithFallback(ConfigurationFactory.ParseString(@" akka.loglevel = INFO akka.remote.log-remote-lifecycle-events = INFO From 883a6a9afbeab49bd23ac15fb753bafa7c288070 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Wed, 18 Nov 2015 13:07:19 -0800 Subject: [PATCH 086/105] close #1399 - modified build script to download NuGet for package publishing --- .gitignore | 1 + build.cmd | 20 ++++++++++++++++++++ build.sh | 16 ++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/.gitignore b/.gitignore index a3df2da73d3..eb0f2f515c0 100644 --- a/.gitignore +++ b/.gitignore @@ -210,6 +210,7 @@ FakesAssemblies/ /src/.Akka.boltdata/TestResults.json resetdev.bat /src/packages/repositories.config +/src/.nuget # FAKE build folder .fake/ diff --git a/build.cmd b/build.cmd index cd4d166978f..c4b65f5327e 100644 --- a/build.cmd +++ b/build.cmd @@ -1,4 +1,24 @@ @echo off + +pushd %~dp0 + +SETLOCAL +SET CACHED_NUGET=%LocalAppData%\NuGet\NuGet.exe + +IF EXIST %CACHED_NUGET% goto copynuget +echo Downloading latest version of NuGet.exe... +IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet +@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://www.nuget.org/nuget.exe' -OutFile '%CACHED_NUGET%'" + +:copynuget +IF EXIST src\.nuget\nuget.exe goto restore +md src\.nuget +copy %CACHED_NUGET% src\.nuget\nuget.exe > nul + +:restore + +src\.nuget\NuGet.exe update -self + cls .paket\paket.bootstrapper.exe diff --git a/build.sh b/build.sh index ae147e64169..13ffcfe0218 100755 --- a/build.sh +++ b/build.sh @@ -1,4 +1,20 @@ #!/usr/bin/env bash +SCRIPT_PATH="${BASH_SOURCE[0]}"; +if ([ -h "${SCRIPT_PATH}" ]) then + while([ -h "${SCRIPT_PATH}" ]) do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done +fi +pushd . > /dev/null +cd `dirname ${SCRIPT_PATH}` > /dev/null +SCRIPT_PATH=`pwd`; +popd > /dev/null + +if ! [ -f $SCRIPT_PATH/src/.nuget/nuget.exe ] + then + wget "https://www.nuget.org/nuget.exe" -P $SCRIPT_PATH/src/.nuget/ +fi + +mono $SCRIPT_PATH/src/.nuget/nuget.exe update -self + if test "$OS" = "Windows_NT" then # use .Net From 8ea56977fd9d7bef39b27585059483bf38e011d8 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Thu, 19 Nov 2015 16:41:10 -0800 Subject: [PATCH 087/105] removed async/await from all DI tests --- .../Akka.DI.TestKit/DiResolverSpec.cs | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/contrib/dependencyInjection/Akka.DI.TestKit/DiResolverSpec.cs b/src/contrib/dependencyInjection/Akka.DI.TestKit/DiResolverSpec.cs index 1b9c8d4ef41..495783cb3cf 100644 --- a/src/contrib/dependencyInjection/Akka.DI.TestKit/DiResolverSpec.cs +++ b/src/contrib/dependencyInjection/Akka.DI.TestKit/DiResolverSpec.cs @@ -270,19 +270,21 @@ public void DependencyResolver_should_inject_new_instances_into_DiPerRequestActo } [Fact] - public async Task DependencyResolver_should_inject_new_instances_on_Restart() + public void DependencyResolver_should_inject_new_instances_on_Restart() { var disposableActorProps = Sys.DI().Props(); var disposableActor = Sys.ActorOf(disposableActorProps); - var originalHashCode = await disposableActor.Ask(new DisposableActor.GetHashCode(), TimeSpan.FromSeconds(1)); + disposableActor.Tell(new DisposableActor.GetHashCode()); + var originalHashCode = ExpectMsg(); disposableActor.Tell(new DisposableActor.Restart()); - var nextHashCode = await disposableActor.Ask(new DisposableActor.GetHashCode(), TimeSpan.FromSeconds(1)); + disposableActor.Tell(new DisposableActor.GetHashCode()); + var nextHashCode = ExpectMsg(); Assert.NotEqual(originalHashCode, nextHashCode); } [Fact] - public async Task DependencyResolver_should_inject_same_instance_into_DiSingletonActor() + public void DependencyResolver_should_inject_same_instance_into_DiSingletonActor() { var diActorProps = Sys.DI().Props(); var diActor1 = Sys.ActorOf(diActorProps); @@ -292,9 +294,10 @@ public async Task DependencyResolver_should_inject_same_instance_into_DiSingleto diActor1.Tell("increment 2"); diActor2.Tell("increment 1"); - var tasks = new[] { diActor1.Ask(new Identify(null), TimeSpan.FromSeconds(1)), diActor2.Ask(new Identify(null), TimeSpan.FromSeconds(1)) }; - - await Task.WhenAll(tasks); + diActor1.Tell(new Identify(null)); + diActor2.Tell(new Identify(null)); + ExpectMsg(); + ExpectMsg(); diActor1.Tell(new GetCallCount()); Assert.Equal(3, ExpectMsg()); @@ -351,13 +354,13 @@ public void DependencyResolver_should_inject_into_BoundedStash_Actor() } [Fact] - public async Task DependencyResolver_should_dispose_IDisposable_instances_on_Actor_Termination() + public void DependencyResolver_should_dispose_IDisposable_instances_on_Actor_Termination() { var disposableActorProps = Sys.DI().Props(); var disposableActor = Sys.ActorOf(disposableActorProps); var currentDisposeCounter = _disposeCounter.Current; - Assert.True(await disposableActor.GracefulStop(TimeSpan.FromSeconds(1))); + Assert.True(disposableActor.GracefulStop(TimeSpan.FromSeconds(1)).Result); AwaitAssert(() => Assert.True(currentDisposeCounter + 1 == _disposeCounter.Current), TimeSpan.FromSeconds(2), TimeSpan.FromMilliseconds(50)); } From 9308dfcb0504cf00ecd82648aee99a487b601542 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Sat, 21 Nov 2015 00:08:36 +0400 Subject: [PATCH 088/105] fix key absent in dictionary in ConductorHandler #1447 --- src/core/Akka.Remote.TestKit/Conductor.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/Akka.Remote.TestKit/Conductor.cs b/src/core/Akka.Remote.TestKit/Conductor.cs index 820a0196f4e..c835d73b32c 100644 --- a/src/core/Akka.Remote.TestKit/Conductor.cs +++ b/src/core/Akka.Remote.TestKit/Conductor.cs @@ -284,7 +284,11 @@ public void OnMessage(object message, IConnection responseChannel) _log.Debug("message from {0}: {1}", responseChannel.RemoteHost, message); if (message is INetworkOp) { - _clients[responseChannel].Tell(message); + IActorRef fsm; + if (_clients.TryGetValue(responseChannel, out fsm)) + { + fsm.Tell(message); + } } else { From 1aa6d1cfd1816d8f26b038cc277140cc5a20b70e Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Fri, 20 Nov 2015 15:26:14 -0800 Subject: [PATCH 089/105] fixed FAKE script to copy NuGet output to correct place --- build.fsx | 1 + 1 file changed, 1 insertion(+) diff --git a/build.fsx b/build.fsx index e82966c7213..8dfbf056c2d 100644 --- a/build.fsx +++ b/build.fsx @@ -319,6 +319,7 @@ let createNugetPackages _ = let project = Path.GetFileNameWithoutExtension nuspec let workingDir = workingDir project + let libDir = workingDir @"lib\net45\" CleanDir workingDir From 32a55c798eeb4ddfc569404abec52d425bd758f3 Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Sun, 22 Nov 2015 12:11:51 +0400 Subject: [PATCH 090/105] #1432 fix PersistentFSMSpec timing --- src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs index f5ba780748d..b0760e8e7db 100644 --- a/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs +++ b/src/core/Akka.Persistence.Tests/Fsm/PersistentFSMSpec.cs @@ -79,7 +79,7 @@ public void PersistentFSM_should_has_function_as_regular_fsm_on_state_timeout() ExpectMsg>(); - Within(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1.9), () => + Within(TimeSpan.FromSeconds(0.9), TimeSpan.FromSeconds(1.9), () => { ExpectMsg>(); return true; From 9b2fc4015d671c202710011de804e6861f2e6af5 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Fri, 20 Nov 2015 07:22:40 +0100 Subject: [PATCH 091/105] Update paket.bootstrapper and fix paket.targets --- .paket/paket.bootstrapper.exe | Bin 25600 -> 30768 bytes .paket/paket.targets | 3 ++- build.cmd | 17 ----------------- build.sh | 7 ------- .../PersistenceBenchmark.csproj | 1 - .../Akka.Persistence.Sqlite.csproj | 1 + .../Akka.MultiNodeTestRunner.csproj | 1 - .../Akka.Remote.TestKit.csproj | 2 -- 8 files changed, 3 insertions(+), 29 deletions(-) diff --git a/.paket/paket.bootstrapper.exe b/.paket/paket.bootstrapper.exe index 8d1cd1875aef2c564dd2cad24bdb855bc4e209cf..b8f431ff0e49bb77b15de75149d12fa2cdeeabfa 100644 GIT binary patch delta 11216 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 F{2!Qle~SPB delta 5874 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 S#DB8BGP+w|aDjE?tN#T{d`Q>; diff --git a/.paket/paket.targets b/.paket/paket.targets index cef47deebcd..5f6a886295e 100644 --- a/.paket/paket.targets +++ b/.paket/paket.targets @@ -20,6 +20,7 @@ $(MonoPath) --runtime=v4.0.30319 $(PaketBootStrapperExePath) $(MSBuildProjectDirectory)\paket.references + $(MSBuildStartupDirectory)\paket.references $(MSBuildProjectFullPath).paket.references $(PaketCommand) restore --references-files "$(PaketReferences)" $(PaketBootStrapperCommand) @@ -35,6 +36,6 @@ - + diff --git a/build.cmd b/build.cmd index c4b65f5327e..9ba5e40a669 100644 --- a/build.cmd +++ b/build.cmd @@ -2,23 +2,6 @@ pushd %~dp0 -SETLOCAL -SET CACHED_NUGET=%LocalAppData%\NuGet\NuGet.exe - -IF EXIST %CACHED_NUGET% goto copynuget -echo Downloading latest version of NuGet.exe... -IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet -@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://www.nuget.org/nuget.exe' -OutFile '%CACHED_NUGET%'" - -:copynuget -IF EXIST src\.nuget\nuget.exe goto restore -md src\.nuget -copy %CACHED_NUGET% src\.nuget\nuget.exe > nul - -:restore - -src\.nuget\NuGet.exe update -self - cls .paket\paket.bootstrapper.exe diff --git a/build.sh b/build.sh index 13ffcfe0218..9cc23f6086b 100755 --- a/build.sh +++ b/build.sh @@ -8,13 +8,6 @@ cd `dirname ${SCRIPT_PATH}` > /dev/null SCRIPT_PATH=`pwd`; popd > /dev/null -if ! [ -f $SCRIPT_PATH/src/.nuget/nuget.exe ] - then - wget "https://www.nuget.org/nuget.exe" -P $SCRIPT_PATH/src/.nuget/ -fi - -mono $SCRIPT_PATH/src/.nuget/nuget.exe update -self - if test "$OS" = "Windows_NT" then # use .Net diff --git a/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj b/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj index f95e1a9e4a0..f8d22e1659b 100644 --- a/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj +++ b/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj @@ -72,7 +72,6 @@ --> - diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj index 63fb2bc1f16..f826075c30b 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj @@ -79,6 +79,7 @@ --> + diff --git a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj index 794443b1322..f4683c43e8f 100644 --- a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj +++ b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj @@ -82,7 +82,6 @@ --> - diff --git a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj index 32220732774..04cbe2f76eb 100644 --- a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj +++ b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj @@ -130,7 +130,6 @@ - - From 941688aead57266b454b76530a7fb5446f68e15d Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Tue, 24 Nov 2015 21:56:14 +0400 Subject: [PATCH 092/105] #1443 fix for cluster shutdown --- src/core/Akka.Cluster/Cluster.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/Akka.Cluster/Cluster.cs b/src/core/Akka.Cluster/Cluster.cs index 5b9ce69bb32..6e4d6e1fe98 100644 --- a/src/core/Akka.Cluster/Cluster.cs +++ b/src/core/Akka.Cluster/Cluster.cs @@ -278,7 +278,11 @@ public void Shutdown() { LogInfo("Shutting down..."); System.Stop(_clusterDaemons); - _readView.Dispose(); + + if (_readView != null) + { + _readView.Dispose(); + } LogInfo("Successfully shut down"); } From b293dae377f9f90979a7c5a6819e7891b88395d2 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 24 Nov 2015 14:10:39 -0800 Subject: [PATCH 093/105] removed Paket --- .gitignore | 6 +- .paket/paket.bootstrapper.exe | Bin 30768 -> 0 bytes .paket/paket.targets | 41 -- build.cmd | 41 +- build.fsx | 32 +- build.sh | 64 +-- paket.dependencies | 50 -- paket.lock | 266 --------- src/.nuget/NuGet.Config | 9 + src/.nuget/NuGet.exe | Bin 0 -> 1686528 bytes src/.nuget/NuGet.targets | 144 +++++ src/.nuget/packages.config | 3 + src/Akka.sln | 12 +- src/benchmark/PersistenceBenchmark/App.config | 157 +----- .../PersistenceBenchmark.csproj | 166 +----- .../PersistenceBenchmark/packages.config | 5 + .../PersistenceBenchmark/paket.references | 2 - src/benchmark/PingPong/App.config | 155 +---- .../Akka.DI.AutoFac.Tests.csproj | 34 +- .../Akka.DI.AutoFac.Tests/packages.config | 4 + .../Akka.DI.AutoFac.Tests/paket.references | 1 - .../Akka.DI.AutoFac/Akka.DI.AutoFac.csproj | 34 +- .../Akka.DI.AutoFac/packages.config | 4 + .../Akka.DI.AutoFac/paket.references | 1 - .../Akka.DI.CastleWindsor.Tests.csproj | 117 +--- .../packages.config | 5 + .../paket.references | 1 - .../Akka.DI.CastleWindsor.csproj | 126 +---- .../Akka.DI.CastleWindsor/packages.config | 5 + .../Akka.DI.CastleWindsor/paket.references | 1 - .../Akka.DI.Ninject.Tests.csproj | 80 +-- .../Akka.DI.Ninject.Tests/packages.config | 4 + .../Akka.DI.Ninject.Tests/paket.references | 1 - .../Akka.DI.Ninject/Akka.DI.Ninject.csproj | 79 +-- .../Akka.DI.Ninject/packages.config | 4 + .../Akka.DI.Ninject/paket.references | 1 - .../Akka.DI.StructureMap.Tests.csproj | 70 +-- .../packages.config | 4 + .../paket.references | 1 - .../Akka.DI.StructureMap.csproj | 71 +-- .../Akka.DI.StructureMap/packages.config | 4 + .../Akka.DI.StructureMap/paket.references | 1 - .../Akka.DI.TestKit/Akka.DI.TestKit.csproj | 39 +- .../Akka.DI.TestKit/packages.config | 8 + .../Akka.DI.TestKit/paket.references | 2 - .../Akka.DI.Unity.Tests.csproj | 22 +- .../Akka.DI.Unity.Tests/packages.config | 4 + .../Akka.DI.Unity.Tests/paket.references | 1 - .../Akka.DI.Unity/Akka.DI.Unity.csproj | 22 +- .../Akka.DI.Unity/packages.config | 4 + .../Akka.DI.Unity/paket.references | 1 - .../Akka.Logger.NLog/Akka.Logger.NLog.csproj | 55 +- .../loggers/Akka.Logger.NLog/packages.config | 4 + .../loggers/Akka.Logger.NLog/paket.references | 1 - .../Akka.Logger.Serilog.csproj | 56 +- .../Akka.Logger.Serilog/packages.config | 4 + .../Akka.Logger.Serilog/paket.references | 1 - .../Akka.Logger.slf4net.csproj | 19 +- .../Akka.Logger.slf4net/packages.config | 4 + .../Akka.Logger.slf4net/paket.references | 1 - ...Akka.Persistence.Sql.Common.TestKit.csproj | 156 +---- .../packages.config | 8 + .../paket.references | 5 - .../Akka.Persistence.Sqlite.Tests.csproj | 242 +------- .../packages.config | 9 + .../paket.references | 6 - .../Akka.Persistence.Sqlite.csproj | 26 +- .../Akka.Persistence.Sqlite/packages.config | 4 + .../Akka.Persistence.Sqlite/paket.references | 1 - .../Akka.TestKit.NUnit.Tests.csproj | 21 +- .../Akka.TestKit.NUnit.Tests/packages.config | 4 + .../Akka.TestKit.NUnit.Tests/paket.references | 2 - .../Akka.TestKit.NUnit.csproj | 21 +- .../Akka.TestKit.NUnit/packages.config | 4 + .../Akka.TestKit.NUnit/paket.references | 2 - .../Akka.TestKit.Xunit.csproj | 31 +- .../Akka.TestKit.Xunit/packages.config | 4 + .../Akka.TestKit.Xunit/paket.references | 2 - .../Akka.TestKit.Xunit2.csproj | 166 +----- .../Akka.TestKit.Xunit2/packages.config | 8 + .../Akka.TestKit.Xunit2/paket.references | 3 - .../Akka.Remote.AkkaIOTransport.csproj | 20 +- .../packages.config | 4 + .../paket.references | 1 - .../Akka.Cluster.Tests.MultiNode.csproj | 183 +----- .../Akka.Cluster.Tests.MultiNode/app.config | 11 + .../packages.config | 9 + .../paket.references | 5 - .../Akka.Cluster.Tests.csproj | 400 ++----------- src/core/Akka.Cluster.Tests/CHANGES.txt | 99 ---- src/core/Akka.Cluster.Tests/app.config | 11 + .../Akka.Cluster.Tests/licenses/license.txt | 31 - .../licenses/protoc-license.txt | 36 -- src/core/Akka.Cluster.Tests/packages.config | 11 + src/core/Akka.Cluster.Tests/paket.references | 6 - .../google/protobuf/csharp_options.proto | 115 ---- .../protos/google/protobuf/descriptor.proto | 533 ------------------ .../protos/tutorial/addressbook.proto | 31 - src/core/Akka.Cluster/Akka.Cluster.csproj | 120 +--- src/core/Akka.Cluster/CHANGES.txt | 99 ---- src/core/Akka.Cluster/licenses/license.txt | 31 - .../Akka.Cluster/licenses/protoc-license.txt | 36 -- src/core/Akka.Cluster/packages.config | 5 + src/core/Akka.Cluster/paket.references | 2 - .../google/protobuf/csharp_options.proto | 115 ---- .../protos/google/protobuf/descriptor.proto | 533 ------------------ .../protos/tutorial/addressbook.proto | 31 - .../Akka.FSharp.Tests.fsproj | 289 ++-------- src/core/Akka.FSharp.Tests/app.config | 154 +---- src/core/Akka.FSharp.Tests/packages.config | 10 + src/core/Akka.FSharp.Tests/paket.references | 4 - src/core/Akka.FSharp/Akka.FSharp.fsproj | 151 +---- src/core/Akka.FSharp/FsApi.fs | 6 +- src/core/Akka.FSharp/app.config | 162 +----- src/core/Akka.FSharp/packages.config | 6 + src/core/Akka.FSharp/paket.references | 2 - ...ka.MultiNodeTestRunner.Shared.Tests.csproj | 188 +----- .../app.config | 11 + .../packages.config | 9 + .../paket.references | 4 - .../Akka.MultiNodeTestRunner.Shared.csproj | 71 +-- .../packages.config | 4 + .../paket.references | 1 - .../Akka.MultiNodeTestRunner.csproj | 225 +------- src/core/Akka.MultiNodeTestRunner/App.config | 145 +---- src/core/Akka.MultiNodeTestRunner/Program.cs | 2 +- .../Akka.MultiNodeTestRunner/packages.config | 7 + .../Akka.MultiNodeTestRunner/paket.references | 7 - src/core/Akka.MultiNodeTests/paket.references | 3 - .../Akka.NodeTestRunner.csproj | 59 +- src/core/Akka.NodeTestRunner/App.config | 163 +----- src/core/Akka.NodeTestRunner/Program.cs | 2 +- src/core/Akka.NodeTestRunner/packages.config | 5 + src/core/Akka.NodeTestRunner/paket.references | 3 - src/core/Akka.Persistence.FSharp/app.config | 162 +----- .../Akka.Persistence.TestKit.Tests.csproj | 164 +----- .../packages.config | 8 + .../paket.references | 3 - .../Akka.Persistence.TestKit.csproj | 162 +----- .../Akka.Persistence.TestKit/packages.config | 8 + .../Akka.Persistence.TestKit/paket.references | 3 - .../Akka.Persistence.Tests.csproj | 58 +- src/core/Akka.Persistence.Tests/CHANGES.txt | 99 ---- .../licenses/license.txt | 31 - .../licenses/protoc-license.txt | 36 -- .../Akka.Persistence.Tests/packages.config | 9 + .../Akka.Persistence.Tests/paket.references | 4 - .../google/protobuf/csharp_options.proto | 115 ---- .../protos/google/protobuf/descriptor.proto | 533 ------------------ .../protos/tutorial/addressbook.proto | 31 - .../Akka.Persistence/Akka.Persistence.csproj | 22 +- src/core/Akka.Persistence/CHANGES.txt | 99 ---- .../Akka.Persistence/licenses/license.txt | 31 - .../licenses/protoc-license.txt | 36 -- src/core/Akka.Persistence/packages.config | 5 + src/core/Akka.Persistence/paket.references | 2 - .../google/protobuf/csharp_options.proto | 115 ---- .../protos/google/protobuf/descriptor.proto | 533 ------------------ .../protos/tutorial/addressbook.proto | 31 - .../Akka.Remote.TestKit.Tests.csproj | 205 ++----- src/core/Akka.Remote.TestKit.Tests/app.config | 11 + .../Akka.Remote.TestKit.Tests/packages.config | 10 + .../paket.references | 5 - .../Akka.Remote.TestKit.csproj | 357 ++---------- src/core/Akka.Remote.TestKit/app.config | 11 + src/core/Akka.Remote.TestKit/packages.config | 10 + src/core/Akka.Remote.TestKit/paket.references | 7 - .../Akka.Remote.Tests.MultiNode.csproj | 180 +----- .../Akka.Remote.Tests.MultiNode/app.config | 11 + .../packages.config | 9 + .../paket.references | 7 - .../Akka.Remote.Tests.csproj | 67 ++- src/core/Akka.Remote.Tests/app.config | 154 +---- src/core/Akka.Remote.Tests/packages.config | 9 + src/core/Akka.Remote.Tests/paket.references | 4 - src/core/Akka.Remote/Akka.Remote.csproj | 17 +- src/core/Akka.Remote/CHANGES.txt | 99 ---- src/core/Akka.Remote/app.config | 162 +----- src/core/Akka.Remote/licenses/license.txt | 31 - .../Akka.Remote/licenses/protoc-license.txt | 36 -- src/core/Akka.Remote/packages.config | 5 + src/core/Akka.Remote/paket.references | 2 - .../google/protobuf/csharp_options.proto | 115 ---- .../protos/google/protobuf/descriptor.proto | 533 ------------------ .../protos/tutorial/addressbook.proto | 31 - .../Akka.TestKit.Tests.csproj | 163 +----- src/core/Akka.TestKit.Tests/packages.config | 8 + src/core/Akka.TestKit.Tests/paket.references | 3 - src/core/Akka.TestKit/Akka.TestKit.csproj | 2 + .../Akka.Tests.Shared.Internals.csproj | 162 +----- .../packages.config | 8 + .../paket.references | 3 - src/core/Akka.Tests/Akka.Tests.csproj | 464 ++------------- src/core/Akka.Tests/App.config | 149 +---- src/core/Akka.Tests/TestUtils/Comparable.cs | 4 +- src/core/Akka.Tests/packages.config | 14 + src/core/Akka.Tests/paket.references | 7 - src/core/Akka/Akka.csproj | 15 +- src/core/Akka/packages.config | 5 + src/core/Akka/paket.references | 2 - src/examples/Chat/ChatClient/App.config | 167 +----- .../Chat/ChatMessages/ChatMessages.csproj | 47 +- .../Chat/ChatMessages/packages.config | 8 + .../Chat/ChatMessages/paket.references | 2 - src/examples/Chat/ChatServer/App.config | 167 +----- .../Samples.Cluster.Transformation/App.config | 157 +----- .../Samples.Cluster.Transformation.csproj | 26 +- .../packages.config | 4 + .../paket.references | 1 - .../App.config | 157 +----- ...mples.Cluster.ConsistentHashRouting.csproj | 26 +- .../packages.config | 4 + .../paket.references | 1 - .../Cluster/Samples.Cluster.Simple/App.config | 157 +----- .../Samples.Cluster.Simple.csproj | 26 +- .../Samples.Cluster.Simple/packages.config | 4 + .../Samples.Cluster.Simple/paket.references | 1 - src/examples/FSharp.Api/App.config | 162 +----- src/examples/FSharp.Api/FSharp.Api.fsproj | 16 +- src/examples/FSharp.Api/packages.config | 4 + src/examples/FSharp.Api/paket.references | 2 - src/examples/FSharp.Deploy.Local/App.config | 162 +----- src/examples/FSharp.Deploy.Remote/App.config | 162 +----- src/examples/FaultTolerance/App.config | 157 +----- .../FaultTolerance/FaultTolerance.csproj | 71 +-- src/examples/FaultTolerance/packages.config | 4 + src/examples/FaultTolerance/paket.references | 1 - .../HelloWorld/FSharp.HelloAkka/App.config | 162 +----- src/examples/HelloWorld/HelloAkka/App.config | 157 +----- .../PersistenceExample.FsApi/App.config | 162 +----- .../PersistenceExample.FsApi.fsproj | 71 +-- .../PersistenceExample.FsApi/packages.config | 4 + .../PersistenceExample.FsApi/paket.references | 1 - src/examples/PersistenceExample/App.config | 157 +----- src/examples/RemoteDeploy/System1/App.config | 162 +----- .../RemoteDeploy/System1/System1.csproj | 9 +- src/examples/RemoteDeploy/System2/App.config | 162 +----- src/examples/Routing/App.config | 157 +----- .../SymbolLookup/Actors/TickerActors.cs | 3 +- src/examples/Stocks/SymbolLookup/App.config | 157 +----- .../Stocks/SymbolLookup/SymbolLookup.csproj | 134 +---- .../Stocks/SymbolLookup/packages.config | 6 + .../Stocks/SymbolLookup/paket.references | 3 - src/examples/TcpEchoService.Server/App.config | 157 +----- src/examples/TimeServer/TimeClient/App.config | 157 +----- .../TimeServer/TimeClient/TimeClient.csproj | 35 +- .../TimeServer/TimeClient/packages.config | 4 + .../TimeServer/TimeClient/paket.references | 1 - src/examples/TimeServer/TimeServer/App.config | 157 +----- .../TimeServer/TimeServer/TimeServer.csproj | 35 +- .../TimeServer/TimeServer/packages.config | 4 + .../TimeServer/TimeServer/paket.references | 1 - 252 files changed, 2000 insertions(+), 14101 deletions(-) delete mode 100644 .paket/paket.bootstrapper.exe delete mode 100644 .paket/paket.targets delete mode 100644 paket.dependencies delete mode 100644 paket.lock create mode 100644 src/.nuget/NuGet.Config create mode 100644 src/.nuget/NuGet.exe create mode 100644 src/.nuget/NuGet.targets create mode 100644 src/.nuget/packages.config create mode 100644 src/benchmark/PersistenceBenchmark/packages.config delete mode 100644 src/benchmark/PersistenceBenchmark/paket.references create mode 100644 src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/packages.config delete mode 100644 src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/paket.references create mode 100644 src/contrib/dependencyInjection/Akka.DI.AutoFac/packages.config delete mode 100644 src/contrib/dependencyInjection/Akka.DI.AutoFac/paket.references create mode 100644 src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/packages.config delete mode 100644 src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/paket.references create mode 100644 src/contrib/dependencyInjection/Akka.DI.CastleWindsor/packages.config delete mode 100644 src/contrib/dependencyInjection/Akka.DI.CastleWindsor/paket.references create mode 100644 src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/packages.config delete mode 100644 src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/paket.references create mode 100644 src/contrib/dependencyInjection/Akka.DI.Ninject/packages.config delete mode 100644 src/contrib/dependencyInjection/Akka.DI.Ninject/paket.references create mode 100644 src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/packages.config delete mode 100644 src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/paket.references create mode 100644 src/contrib/dependencyInjection/Akka.DI.StructureMap/packages.config delete mode 100644 src/contrib/dependencyInjection/Akka.DI.StructureMap/paket.references create mode 100644 src/contrib/dependencyInjection/Akka.DI.TestKit/packages.config delete mode 100644 src/contrib/dependencyInjection/Akka.DI.TestKit/paket.references create mode 100644 src/contrib/dependencyInjection/Akka.DI.Unity.Tests/packages.config delete mode 100644 src/contrib/dependencyInjection/Akka.DI.Unity.Tests/paket.references create mode 100644 src/contrib/dependencyInjection/Akka.DI.Unity/packages.config delete mode 100644 src/contrib/dependencyInjection/Akka.DI.Unity/paket.references create mode 100644 src/contrib/loggers/Akka.Logger.NLog/packages.config delete mode 100644 src/contrib/loggers/Akka.Logger.NLog/paket.references create mode 100644 src/contrib/loggers/Akka.Logger.Serilog/packages.config delete mode 100644 src/contrib/loggers/Akka.Logger.Serilog/paket.references create mode 100644 src/contrib/loggers/Akka.Logger.slf4net/packages.config delete mode 100644 src/contrib/loggers/Akka.Logger.slf4net/paket.references create mode 100644 src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/packages.config delete mode 100644 src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/paket.references create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite.Tests/packages.config delete mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite.Tests/paket.references create mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/packages.config delete mode 100644 src/contrib/persistence/Akka.Persistence.Sqlite/paket.references create mode 100644 src/contrib/testkits/Akka.TestKit.NUnit.Tests/packages.config delete mode 100644 src/contrib/testkits/Akka.TestKit.NUnit.Tests/paket.references create mode 100644 src/contrib/testkits/Akka.TestKit.NUnit/packages.config delete mode 100644 src/contrib/testkits/Akka.TestKit.NUnit/paket.references create mode 100644 src/contrib/testkits/Akka.TestKit.Xunit/packages.config delete mode 100644 src/contrib/testkits/Akka.TestKit.Xunit/paket.references create mode 100644 src/contrib/testkits/Akka.TestKit.Xunit2/packages.config delete mode 100644 src/contrib/testkits/Akka.TestKit.Xunit2/paket.references create mode 100644 src/contrib/transports/Akka.Remote.AkkaIOTransport/packages.config delete mode 100644 src/contrib/transports/Akka.Remote.AkkaIOTransport/paket.references create mode 100644 src/core/Akka.Cluster.Tests.MultiNode/app.config create mode 100644 src/core/Akka.Cluster.Tests.MultiNode/packages.config delete mode 100644 src/core/Akka.Cluster.Tests.MultiNode/paket.references delete mode 100644 src/core/Akka.Cluster.Tests/CHANGES.txt create mode 100644 src/core/Akka.Cluster.Tests/app.config delete mode 100644 src/core/Akka.Cluster.Tests/licenses/license.txt delete mode 100644 src/core/Akka.Cluster.Tests/licenses/protoc-license.txt create mode 100644 src/core/Akka.Cluster.Tests/packages.config delete mode 100644 src/core/Akka.Cluster.Tests/paket.references delete mode 100644 src/core/Akka.Cluster.Tests/protos/google/protobuf/csharp_options.proto delete mode 100644 src/core/Akka.Cluster.Tests/protos/google/protobuf/descriptor.proto delete mode 100644 src/core/Akka.Cluster.Tests/protos/tutorial/addressbook.proto delete mode 100644 src/core/Akka.Cluster/CHANGES.txt delete mode 100644 src/core/Akka.Cluster/licenses/license.txt delete mode 100644 src/core/Akka.Cluster/licenses/protoc-license.txt create mode 100644 src/core/Akka.Cluster/packages.config delete mode 100644 src/core/Akka.Cluster/paket.references delete mode 100644 src/core/Akka.Cluster/protos/google/protobuf/csharp_options.proto delete mode 100644 src/core/Akka.Cluster/protos/google/protobuf/descriptor.proto delete mode 100644 src/core/Akka.Cluster/protos/tutorial/addressbook.proto create mode 100644 src/core/Akka.FSharp.Tests/packages.config delete mode 100644 src/core/Akka.FSharp.Tests/paket.references create mode 100644 src/core/Akka.FSharp/packages.config delete mode 100644 src/core/Akka.FSharp/paket.references create mode 100644 src/core/Akka.MultiNodeTestRunner.Shared.Tests/app.config create mode 100644 src/core/Akka.MultiNodeTestRunner.Shared.Tests/packages.config delete mode 100644 src/core/Akka.MultiNodeTestRunner.Shared.Tests/paket.references create mode 100644 src/core/Akka.MultiNodeTestRunner.Shared/packages.config delete mode 100644 src/core/Akka.MultiNodeTestRunner.Shared/paket.references create mode 100644 src/core/Akka.MultiNodeTestRunner/packages.config delete mode 100644 src/core/Akka.MultiNodeTestRunner/paket.references delete mode 100644 src/core/Akka.MultiNodeTests/paket.references create mode 100644 src/core/Akka.NodeTestRunner/packages.config delete mode 100644 src/core/Akka.NodeTestRunner/paket.references create mode 100644 src/core/Akka.Persistence.TestKit.Tests/packages.config delete mode 100644 src/core/Akka.Persistence.TestKit.Tests/paket.references create mode 100644 src/core/Akka.Persistence.TestKit/packages.config delete mode 100644 src/core/Akka.Persistence.TestKit/paket.references delete mode 100644 src/core/Akka.Persistence.Tests/CHANGES.txt delete mode 100644 src/core/Akka.Persistence.Tests/licenses/license.txt delete mode 100644 src/core/Akka.Persistence.Tests/licenses/protoc-license.txt create mode 100644 src/core/Akka.Persistence.Tests/packages.config delete mode 100644 src/core/Akka.Persistence.Tests/paket.references delete mode 100644 src/core/Akka.Persistence.Tests/protos/google/protobuf/csharp_options.proto delete mode 100644 src/core/Akka.Persistence.Tests/protos/google/protobuf/descriptor.proto delete mode 100644 src/core/Akka.Persistence.Tests/protos/tutorial/addressbook.proto delete mode 100644 src/core/Akka.Persistence/CHANGES.txt delete mode 100644 src/core/Akka.Persistence/licenses/license.txt delete mode 100644 src/core/Akka.Persistence/licenses/protoc-license.txt create mode 100644 src/core/Akka.Persistence/packages.config delete mode 100644 src/core/Akka.Persistence/paket.references delete mode 100644 src/core/Akka.Persistence/protos/google/protobuf/csharp_options.proto delete mode 100644 src/core/Akka.Persistence/protos/google/protobuf/descriptor.proto delete mode 100644 src/core/Akka.Persistence/protos/tutorial/addressbook.proto create mode 100644 src/core/Akka.Remote.TestKit.Tests/app.config create mode 100644 src/core/Akka.Remote.TestKit.Tests/packages.config delete mode 100644 src/core/Akka.Remote.TestKit.Tests/paket.references create mode 100644 src/core/Akka.Remote.TestKit/app.config create mode 100644 src/core/Akka.Remote.TestKit/packages.config delete mode 100644 src/core/Akka.Remote.TestKit/paket.references create mode 100644 src/core/Akka.Remote.Tests.MultiNode/app.config create mode 100644 src/core/Akka.Remote.Tests.MultiNode/packages.config delete mode 100644 src/core/Akka.Remote.Tests.MultiNode/paket.references create mode 100644 src/core/Akka.Remote.Tests/packages.config delete mode 100644 src/core/Akka.Remote.Tests/paket.references delete mode 100644 src/core/Akka.Remote/CHANGES.txt delete mode 100644 src/core/Akka.Remote/licenses/license.txt delete mode 100644 src/core/Akka.Remote/licenses/protoc-license.txt create mode 100644 src/core/Akka.Remote/packages.config delete mode 100644 src/core/Akka.Remote/paket.references delete mode 100644 src/core/Akka.Remote/protos/google/protobuf/csharp_options.proto delete mode 100644 src/core/Akka.Remote/protos/google/protobuf/descriptor.proto delete mode 100644 src/core/Akka.Remote/protos/tutorial/addressbook.proto create mode 100644 src/core/Akka.TestKit.Tests/packages.config delete mode 100644 src/core/Akka.TestKit.Tests/paket.references create mode 100644 src/core/Akka.Tests.Shared.Internals/packages.config delete mode 100644 src/core/Akka.Tests.Shared.Internals/paket.references create mode 100644 src/core/Akka.Tests/packages.config delete mode 100644 src/core/Akka.Tests/paket.references create mode 100644 src/core/Akka/packages.config delete mode 100644 src/core/Akka/paket.references create mode 100644 src/examples/Chat/ChatMessages/packages.config delete mode 100644 src/examples/Chat/ChatMessages/paket.references create mode 100644 src/examples/Cluster/Roles/Samples.Cluster.Transformation/packages.config delete mode 100644 src/examples/Cluster/Roles/Samples.Cluster.Transformation/paket.references create mode 100644 src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/packages.config delete mode 100644 src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/paket.references create mode 100644 src/examples/Cluster/Samples.Cluster.Simple/packages.config delete mode 100644 src/examples/Cluster/Samples.Cluster.Simple/paket.references create mode 100644 src/examples/FSharp.Api/packages.config delete mode 100644 src/examples/FSharp.Api/paket.references create mode 100644 src/examples/FaultTolerance/packages.config delete mode 100644 src/examples/FaultTolerance/paket.references create mode 100644 src/examples/PersistenceExample.FsApi/packages.config delete mode 100644 src/examples/PersistenceExample.FsApi/paket.references create mode 100644 src/examples/Stocks/SymbolLookup/packages.config delete mode 100644 src/examples/Stocks/SymbolLookup/paket.references create mode 100644 src/examples/TimeServer/TimeClient/packages.config delete mode 100644 src/examples/TimeServer/TimeClient/paket.references create mode 100644 src/examples/TimeServer/TimeServer/packages.config delete mode 100644 src/examples/TimeServer/TimeServer/paket.references diff --git a/.gitignore b/.gitignore index eb0f2f515c0..aab78dc4dff 100644 --- a/.gitignore +++ b/.gitignore @@ -154,6 +154,10 @@ publish/ *.nupkg # The packages folder can be ignored because of Package Restore **/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# If using the old MSBuild-Integrated Package Restore, uncomment this: +!**/packages/repositories.config # Windows Azure Build Output csx/ @@ -217,5 +221,3 @@ resetdev.bat # Akka.Persistence Test Output target/ -# paket tool -.paket/paket.exe diff --git a/.paket/paket.bootstrapper.exe b/.paket/paket.bootstrapper.exe deleted file mode 100644 index b8f431ff0e49bb77b15de75149d12fa2cdeeabfa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30768 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 d*>>hjPY)B;J{7y*g8H - - - - true - - true - $(MSBuildThisFileDirectory) - $(MSBuildThisFileDirectory)..\ - /Library/Frameworks/Mono.framework/Commands/mono - mono - - - - $(PaketToolsPath)paket.exe - $(PaketToolsPath)paket.bootstrapper.exe - "$(PaketExePath)" - $(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)" - "$(PaketBootStrapperExePath)" - $(MonoPath) --runtime=v4.0.30319 $(PaketBootStrapperExePath) - - $(MSBuildProjectDirectory)\paket.references - $(MSBuildStartupDirectory)\paket.references - $(MSBuildProjectFullPath).paket.references - $(PaketCommand) restore --references-files "$(PaketReferences)" - $(PaketBootStrapperCommand) - - RestorePackages; $(BuildDependsOn); - - - - - - - - - - - - - diff --git a/build.cmd b/build.cmd index 9ba5e40a669..2d3c363daa4 100644 --- a/build.cmd +++ b/build.cmd @@ -2,16 +2,39 @@ pushd %~dp0 -cls +SETLOCAL +SET CACHED_NUGET=%LocalAppData%\NuGet\NuGet.exe -.paket\paket.bootstrapper.exe -if errorlevel 1 ( - exit /b %errorlevel% -) +IF EXIST %CACHED_NUGET% goto copynuget +echo Downloading latest version of NuGet.exe... +IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet +@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://www.nuget.org/nuget.exe' -OutFile '%CACHED_NUGET%'" + +:copynuget +IF EXIST src\.nuget\nuget.exe goto restore +md src\.nuget +copy %CACHED_NUGET% src\.nuget\nuget.exe > nul + +:restore -.paket\paket.exe restore -if errorlevel 1 ( - exit /b %errorlevel% +src\.nuget\NuGet.exe update -self + + +pushd %~dp0 + +src\.nuget\NuGet.exe update -self + +src\.nuget\NuGet.exe install FAKE -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion -Version 4.1.0 + +src\.nuget\NuGet.exe install xunit.runner.console -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages\FAKE -ExcludeVersion -Version 2.0.0 +src\.nuget\NuGet.exe install nunit.runners -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages\FAKE -ExcludeVersion -Version 2.6.4 + +if not exist src\packages\SourceLink.Fake\tools\SourceLink.fsx ( + src\.nuget\nuget.exe install SourceLink.Fake -ConfigFile src\.nuget\Nuget.Config -OutputDirectory src\packages -ExcludeVersion ) +rem cls + +set encoding=utf-8 +src\packages\FAKE\tools\FAKE.exe build.fsx %* -packages\build\FAKE\tools\FAKE.exe build.fsx %* +popd diff --git a/build.fsx b/build.fsx index 8dfbf056c2d..a7a3075593a 100644 --- a/build.fsx +++ b/build.fsx @@ -1,4 +1,4 @@ -#I @"packages/build/FAKE/tools" +#I @"src/packages/FAKE/tools" #r "FakeLib.dll" #r "System.Xml.Linq" @@ -59,6 +59,14 @@ let libDir = workingDir @@ @"lib\net45\" let nugetExe = FullName @"src\.nuget\NuGet.exe" let docDir = "bin" @@ "doc" +open Fake.RestorePackageHelper +Target "RestorePackages" (fun _ -> + "./src/Akka.sln" + |> RestoreMSSolutionPackages (fun p -> + { p with + OutputPath = "./src/packages" + Retries = 4 }) + ) //-------------------------------------------------------------------------------- // Clean build results @@ -221,22 +229,22 @@ Target "RunTests" <| fun _ -> {p with DisableShadowCopy = true; OutputFile = testOutput + @"\NUnitTestResults.xml"}) - let xunitToolPath = findToolInSubPath "xunit.console.exe" "src/packages/xunit.runner.console*/tools" + let xunitToolPath = findToolInSubPath "xunit.console.exe" "src/packages/xunit.runner.console*/tools" + printfn "Using XUnit runner: %s" xunitToolPath xUnit2 (fun p -> { p with XmlOutputPath = Some (testOutput + @"\XUnitTestResults.xml"); HtmlOutputPath = Some (testOutput + @"\XUnitTestResults.HTML"); ToolPath = xunitToolPath; TimeOut = System.TimeSpan.FromMinutes 30.0; Parallel = ParallelMode.NoParallelization }) - xunitTestAssemblies Target "RunTestsMono" <| fun _ -> let xunitTestAssemblies = !! "src/**/bin/Release Mono/*.Tests.dll" mkdir testOutput - let xunitToolPath = findToolInSubPath "xunit.console.exe" "src/packages/xunit.runner.console*/tools" + let xunitToolPath = findToolInSubPath "xunit.console.exe" "src/packages/xunit.runner.console*/tools" + printfn "Using XUnit runner: %s" xunitToolPath xUnit2 (fun p -> { p with XmlOutputPath = Some (testOutput + @"\XUnitTestResults.xml"); HtmlOutputPath = Some (testOutput + @"\XUnitTestResults.HTML"); ToolPath = xunitToolPath; TimeOut = System.TimeSpan.FromMinutes 30.0; Parallel = ParallelMode.NoParallelization }) - xunitTestAssemblies Target "MultiNodeTests" <| fun _ -> @@ -315,19 +323,15 @@ let createNugetPackages _ = ensureDirectory nugetDir for nuspec in !! "src/**/*.nuspec" do printfn "Creating nuget packages for %s" nuspec - - let project = Path.GetFileNameWithoutExtension nuspec - let workingDir = workingDir project - let libDir = workingDir @"lib\net45\" - CleanDir workingDir + let project = Path.GetFileNameWithoutExtension nuspec let projectDir = Path.GetDirectoryName nuspec let projectFile = (!! (projectDir @@ project + ".*sproj")) |> Seq.head let releaseDir = projectDir @@ @"bin\Release" - let packages = projectDir @@ "paket.references" - let packageDependencies = if (fileExists packages) then (Paket.GetDependenciesForReferencesFile packages |> Seq.toList) else [] + let packages = projectDir @@ "packages.config" + let packageDependencies = if (fileExists packages) then (getDependencies packages) else [] let dependencies = packageDependencies @ getAkkaDependency project let releaseVersion = getProjectVersion project @@ -374,6 +378,8 @@ let createNugetPackages _ = // Create both normal nuget package and symbols nuget package. // Uses the files we copied to workingDir and outputs to nugetdir pack nugetDir NugetSymbolPackage.Nuspec + + removeDir workingDir let publishNugetPackages _ = let rec publishPackage url accessKey trialsLeft packageFile = @@ -542,7 +548,7 @@ Target "HelpMultiNodeTests" <| fun _ -> //-------------------------------------------------------------------------------- // build dependencies -"Clean" ==> "AssemblyInfo" ==> "Build" ==> "CopyOutput" ==> "BuildRelease" +"Clean" ==> "AssemblyInfo" ==> "RestorePackages" ==> "Build" ==> "CopyOutput" ==> "BuildRelease" // tests dependencies "CleanTests" ==> "RunTests" diff --git a/build.sh b/build.sh index 9cc23f6086b..7004e2907eb 100755 --- a/build.sh +++ b/build.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/bash SCRIPT_PATH="${BASH_SOURCE[0]}"; if ([ -h "${SCRIPT_PATH}" ]) then while([ -h "${SCRIPT_PATH}" ]) do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done @@ -8,35 +8,35 @@ cd `dirname ${SCRIPT_PATH}` > /dev/null SCRIPT_PATH=`pwd`; popd > /dev/null -if test "$OS" = "Windows_NT" -then - # use .Net - - .paket/paket.bootstrapper.exe - exit_code=$? - if [ $exit_code -ne 0 ]; then - exit $exit_code - fi - - .paket/paket.exe restore - exit_code=$? - if [ $exit_code -ne 0 ]; then - exit $exit_code - fi - - packages/build/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx -else - # use mono - mono .paket/paket.bootstrapper.exe - exit_code=$? - if [ $exit_code -ne 0 ]; then - exit $exit_code - fi - - mono .paket/paket.exe restore - exit_code=$? - if [ $exit_code -ne 0 ]; then - exit $exit_code - fi - mono packages/build/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx +if ! [ -f $SCRIPT_PATH/src/.nuget/nuget.exe ] + then + wget "https://www.nuget.org/nuget.exe" -P $SCRIPT_PATH/src/.nuget/ fi + +mono $SCRIPT_PATH/src/.nuget/nuget.exe update -self + + +SCRIPT_PATH="${BASH_SOURCE[0]}"; +if ([ -h "${SCRIPT_PATH}" ]) then + while([ -h "${SCRIPT_PATH}" ]) do SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done +fi +pushd . > /dev/null +cd `dirname ${SCRIPT_PATH}` > /dev/null +SCRIPT_PATH=`pwd`; +popd > /dev/null + +mono $SCRIPT_PATH/src/.nuget/NuGet.exe update -self + +mono $SCRIPT_PATH/src/.nuget/NuGet.exe install FAKE -OutputDirectory $SCRIPT_PATH/src/packages -ExcludeVersion -Version 3.28.8 + +mono $SCRIPT_PATH/src/.nuget/NuGet.exe install xunit.runners -OutputDirectory $SCRIPT_PATH/src/packages/FAKE -ExcludeVersion -Version 2.0.0 +mono $SCRIPT_PATH/src/.nuget/NuGet.exe install nunit.runners -OutputDirectory $SCRIPT_PATH/src/packages/FAKE -ExcludeVersion -Version 2.6.4 + +if ! [ -e $SCRIPT_PATH/src/packages/SourceLink.Fake/tools/SourceLink.fsx ] ; then + mono $SCRIPT_PATH/src/.nuget/NuGet.exe install SourceLink.Fake -OutputDirectory $SCRIPT_PATH/src/packages -ExcludeVersion + +fi + +export encoding=utf-8 + +mono $SCRIPT_PATH/src/packages/FAKE/tools/FAKE.exe build.fsx "$@" diff --git a/paket.dependencies b/paket.dependencies deleted file mode 100644 index 1fd178c8cd2..00000000000 --- a/paket.dependencies +++ /dev/null @@ -1,50 +0,0 @@ -source https://www.nuget.org/api/v2/ - -nuget Autofac -nuget Castle.Windsor -nuget faker-csharp -nuget FsPickler >= 1.2 -nuget FSPowerPack.Linq.Community -nuget Google.ProtocolBuffers 2.4.1.521 framework: >= net45 -nuget Google.ProtocolBuffersLite -nuget Helios -nuget Nuget.CommandLine -nuget System.Collections.Immutable -nuget Newtonsoft.Json 7.0.1 -nuget Ninject -nuget NLog -nuget qdfeed -nuget Serilog -nuget slf4net -nuget structuremap -nuget System.Data.SQLite.Core -nuget Unity -nuget Wire 0.0.4 framework: >= net45 -nuget xunit 2.0.0 framework: >= net45 -nuget xunit.abstractions 2.0.0 framework: >= net45 -nuget xunit.assert 2.0.0 framework: >= net45 -nuget xunit.core 2.0.0 framework: >= net45 -nuget xunit.extensibility.core 2.0.0 framework: >= net45 - -group Test -source https://www.nuget.org/api/v2/ -nuget NUnit -nuget NUnit.Runners -nuget FluentAssertions ~> 3 -nuget FsCheck.Xunit -nuget xunit.core >= 2.1 -nuget xunit.assert -nuget xunit.extensions -nuget xunit.runner.console -nuget xunit.runner.utility -nuget xunit.runner.visualstudio - -group Build -source https://www.nuget.org/api/v2/ -nuget Nuget.CommandLine -nuget FAKE -nuget SourceLink.Fake - -group Legacy -source https://www.nuget.org/api/v2/ -nuget xunit 1.9.2 \ No newline at end of file diff --git a/paket.lock b/paket.lock deleted file mode 100644 index 82eed47eb2c..00000000000 --- a/paket.lock +++ /dev/null @@ -1,266 +0,0 @@ -NUGET - remote: https://nuget.org/api/v2 - specs: - Autofac (3.5.2) - Castle.Core (3.3.3) - Castle.Windsor (3.3.0) - Castle.Core (>= 3.3.0) - CommonServiceLocator (1.3.0) - faker-csharp (1.2.0) - FsPickler (1.4.0) - FSPowerPack.Core.Community (3.0.0) - FSPowerPack.Linq.Community (3.0.0) - FSPowerPack.Core.Community - Google.ProtocolBuffers (2.4.1.521) - framework: >= net45 - Google.ProtocolBuffersLite (2.4.1.555) - Helios (1.4.1) - Newtonsoft.Json (7.0.1) - Ninject (3.2.2) - NLog (4.1.2) - NuGet.CommandLine (2.8.6) - qdfeed (1.1.0) - Serilog (1.5.11) - slf4net (0.1.32.1) - structuremap (3.1.6.186) - System.Collections (4.0.10) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.0) - System.Resources.ResourceManager (>= 4.0.0) - System.Runtime (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Runtime.Extensions (>= 4.0.0) - System.Threading (>= 4.0.0) - System.Collections.Immutable (1.1.37) - System.Collections (>= 4.0.0) - System.Diagnostics.Debug (>= 4.0.0) - System.Globalization (>= 4.0.0) - System.Linq (>= 4.0.0) - System.Resources.ResourceManager (>= 4.0.0) - System.Runtime (>= 4.0.0) - System.Runtime.Extensions (>= 4.0.0) - System.Threading (>= 4.0.0) - System.Data.SQLite.Core (1.0.98.1) - System.Diagnostics.Debug (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.Globalization (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.IO (4.0.10) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Text.Encoding (>= 4.0.0) - System.Text.Encoding (>= 4.0.10) - System.Text.Encoding.Extensions (>= 4.0.0) - System.Threading (>= 4.0.0) - System.Threading.Tasks (>= 4.0.0) - System.Linq (4.0.0) - framework: dnxcore50 - System.Collections (>= 4.0.10) - System.Diagnostics.Debug (>= 4.0.10) - System.Resources.ResourceManager (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Runtime.Extensions (>= 4.0.10) - System.Private.Uri (4.0.0) - framework: dnxcore50 - System.Reflection (4.0.10) - framework: dnxcore50 - System.IO (>= 4.0.0) - System.Reflection.Primitives (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Reflection.Primitives (4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.Threading (>= 4.0.0) - System.Resources.ResourceManager (4.0.0) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - System.Reflection (>= 4.0.0) - System.Reflection (>= 4.0.10) - System.Runtime (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Runtime (4.0.20) - framework: dnxcore50 - System.Private.Uri (>= 4.0.0) - System.Runtime.Extensions (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - System.Text.Encoding (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.Text.Encoding.Extensions (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.Text.Encoding (>= 4.0.10) - System.Threading (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.Threading.Tasks (>= 4.0.0) - System.Threading.Tasks (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - Unity (4.0.1) - CommonServiceLocator (>= 1.3.0) - Wire (0.0.4) - framework: >= net45 - xunit (2.0.0) - framework: >= net45 - xunit.assert (2.0.0) - xunit.core (2.0.0) - xunit.abstractions (2.0.0) - framework: >= net45 - xunit.assert (2.0.0) - framework: >= net45 - xunit.core (2.0.0) - framework: >= net45 - xunit.extensibility.core (2.0.0) - xunit.extensibility.core (2.0.0) - framework: >= net45 - xunit.abstractions (2.0.0) - -GROUP Build -NUGET - remote: https://nuget.org/api/v2 - specs: - FAKE (4.5.2) - NuGet.CommandLine (2.8.6) - SourceLink.Fake (1.1.0) - -GROUP Legacy -NUGET - remote: https://nuget.org/api/v2 - specs: - xunit (1.9.2) - -GROUP Test -NUGET - remote: https://nuget.org/api/v2 - specs: - FluentAssertions (3.5.0) - FsCheck (2.1.0) - FSharp.Core (>= 3.1.2.5) - FsCheck.Xunit (2.1.0) - FsCheck (>= 2.1.0) - xunit.extensibility.execution (>= 2.1.0) - FSharp.Core (4.0.0.1) - NUnit (2.6.4) - NUnit.Runners (2.6.4) - System.Collections (4.0.10) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.0) - System.Resources.ResourceManager (>= 4.0.0) - System.Runtime (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Runtime.Extensions (>= 4.0.0) - System.Threading (>= 4.0.0) - System.Diagnostics.Contracts (4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.Diagnostics.Debug (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.Globalization (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.IO (4.0.10) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Text.Encoding (>= 4.0.0) - System.Text.Encoding (>= 4.0.10) - System.Text.Encoding.Extensions (>= 4.0.0) - System.Threading (>= 4.0.0) - System.Threading.Tasks (>= 4.0.0) - System.Linq (4.0.0) - framework: dnxcore50 - System.Collections (>= 4.0.10) - System.Diagnostics.Debug (>= 4.0.10) - System.Resources.ResourceManager (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Runtime.Extensions (>= 4.0.10) - System.ObjectModel (4.0.10) - framework: dnxcore50 - System.Collections (>= 4.0.10) - System.Diagnostics.Debug (>= 4.0.10) - System.Resources.ResourceManager (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Threading (>= 4.0.10) - System.Private.Uri (4.0.0) - framework: dnxcore50 - System.Reflection (4.0.10) - framework: dnxcore50 - System.IO (>= 4.0.0) - System.Reflection.Primitives (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Reflection.Extensions (4.0.0) - framework: dnxcore50 - System.Diagnostics.Debug (>= 4.0.10) - System.Reflection (>= 4.0.0) - System.Reflection (>= 4.0.10) - System.Reflection.Primitives (>= 4.0.0) - System.Reflection.TypeExtensions (>= 4.0.0) - System.Resources.ResourceManager (>= 4.0.0) - System.Runtime (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Runtime.Extensions (>= 4.0.10) - System.Reflection.Primitives (4.0.0) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.Threading (>= 4.0.0) - System.Reflection.TypeExtensions (4.0.0) - framework: dnxcore50 - System.Diagnostics.Contracts (>= 4.0.0) - System.Diagnostics.Debug (>= 4.0.10) - System.Linq (>= 4.0.0) - System.Reflection (>= 4.0.0) - System.Reflection (>= 4.0.10) - System.Reflection.Primitives (>= 4.0.0) - System.Resources.ResourceManager (>= 4.0.0) - System.Runtime (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Runtime.Extensions (>= 4.0.10) - System.Resources.ResourceManager (4.0.0) - framework: dnxcore50 - System.Globalization (>= 4.0.0) - System.Reflection (>= 4.0.0) - System.Reflection (>= 4.0.10) - System.Runtime (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Runtime (4.0.20) - framework: dnxcore50 - System.Private.Uri (>= 4.0.0) - System.Runtime.Extensions (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.20) - System.Text.Encoding (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.Text.Encoding.Extensions (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.Text.Encoding (>= 4.0.10) - System.Text.RegularExpressions (4.0.10) - framework: dnxcore50 - System.Collections (>= 4.0.10) - System.Globalization (>= 4.0.10) - System.Resources.ResourceManager (>= 4.0.0) - System.Runtime (>= 4.0.20) - System.Runtime.Extensions (>= 4.0.10) - System.Threading (>= 4.0.10) - System.Threading (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - System.Threading.Tasks (>= 4.0.0) - System.Threading.Tasks (4.0.10) - framework: dnxcore50 - System.Runtime (>= 4.0.0) - xunit (1.9.2) - xunit.abstractions (2.0.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 - xunit.assert (2.1.0) - System.Collections (>= 4.0.0) - System.Diagnostics.Debug (>= 4.0.0) - System.Globalization (>= 4.0.0) - System.Linq (>= 4.0.0) - System.ObjectModel (>= 4.0.0) - System.Reflection (>= 4.0.0) - System.Reflection.Extensions (>= 4.0.0) - System.Runtime (>= 4.0.0) - System.Runtime.Extensions (>= 4.0.0) - System.Text.RegularExpressions (>= 4.0.0) - System.Threading.Tasks (>= 4.0.0) - xunit.core (2.1.0) - System.Collections (>= 4.0.0) - System.Diagnostics.Debug (>= 4.0.0) - System.Globalization (>= 4.0.0) - System.Linq (>= 4.0.0) - System.Reflection (>= 4.0.0) - System.Reflection.Extensions (>= 4.0.0) - System.Runtime (>= 4.0.0) - System.Runtime.Extensions (>= 4.0.0) - System.Threading.Tasks (>= 4.0.0) - xunit.abstractions (>= 2.0.0) - xunit.extensibility.core (2.1.0) - xunit.extensibility.execution (2.1.0) - xunit.extensibility.core (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 - xunit.abstractions (2.0.0) - xunit.extensibility.execution (2.1.0) - framework: dnx451, dnxcore50, monoandroid, monotouch, xamarinios, winv4.5, wpv8.0, portable-net45+win80+wp80+wpa81, >= net45 - xunit.extensibility.core (2.1.0) - xunit.extensions (1.9.2) - xunit (1.9.2) - xunit.runner.console (2.1.0) - xunit.runner.utility (2.1.0) - System.Collections (>= 4.0.0) - System.Diagnostics.Debug (>= 4.0.0) - System.Globalization (>= 4.0.0) - System.IO (>= 4.0.0) - System.Linq (>= 4.0.0) - System.Reflection (>= 4.0.0) - System.Reflection.Extensions (>= 4.0.0) - System.Runtime (>= 4.0.0) - System.Runtime.Extensions (>= 4.0.0) - System.Text.RegularExpressions (>= 4.0.0) - System.Threading (>= 4.0.0) - System.Threading.Tasks (>= 4.0.0) - xunit.abstractions (>= 2.0.0) - xunit.abstractions (2.0.0) - xunit.runner.visualstudio (2.1.0) diff --git a/src/.nuget/NuGet.Config b/src/.nuget/NuGet.Config new file mode 100644 index 00000000000..58b08e6dd81 --- /dev/null +++ b/src/.nuget/NuGet.Config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/.nuget/NuGet.exe b/src/.nuget/NuGet.exe new file mode 100644 index 0000000000000000000000000000000000000000..324daa842c51a9936d8baeabbc21da1e01bc9a4d GIT binary patch literal 1686528 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 J|995F{{fUW9S8sb literal 0 HcmV?d00001 diff --git a/src/.nuget/NuGet.targets b/src/.nuget/NuGet.targets new file mode 100644 index 00000000000..3f8c37b22cd --- /dev/null +++ b/src/.nuget/NuGet.targets @@ -0,0 +1,144 @@ + + + + $(MSBuildProjectDirectory)\..\ + + + false + + + false + + + true + + + false + + + + + + + + + + + $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) + + + + + $(SolutionDir).nuget + + + + $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config + $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config + + + + $(MSBuildProjectDirectory)\packages.config + $(PackagesProjectConfig) + + + + + $(NuGetToolsPath)\NuGet.exe + @(PackageSource) + + "$(NuGetExePath)" + mono --runtime=v4.0.30319 "$(NuGetExePath)" + + $(TargetDir.Trim('\\')) + + -RequireConsent + -NonInteractive + + "$(SolutionDir) " + "$(SolutionDir)" + + + $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) + $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols + + + + RestorePackages; + $(BuildDependsOn); + + + + + $(BuildDependsOn); + BuildPackage; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/.nuget/packages.config b/src/.nuget/packages.config new file mode 100644 index 00000000000..569e1bea867 --- /dev/null +++ b/src/.nuget/packages.config @@ -0,0 +1,3 @@ + + + diff --git a/src/Akka.sln b/src/Akka.sln index eec542968e5..a1c730d72c5 100644 --- a/src/Akka.sln +++ b/src/Akka.sln @@ -3,11 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{00569E53-0F1E-4ECC-BAEE-8DFF37AB007A}" - ProjectSection(SolutionItems) = preProject - ..\paket.dependencies = ..\paket.dependencies - EndProjectSection -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{69279534-1DBA-4115-BF8B-03F77FC8125E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Chat", "Chat", "{3AA1E79A-F641-4115-BF84-96ECE552EC95}" @@ -137,6 +132,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Protobuf", "Protobuf", "{98 core\protobuf\WireFormats.proto = core\protobuf\WireFormats.proto EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{8A15341C-5596-4F4D-949D-2CD9A0006E12}" + ProjectSection(SolutionItems) = preProject + .nuget\NuGet.Config = .nuget\NuGet.Config + .nuget\nuget.exe = .nuget\nuget.exe + .nuget\NuGet.targets = .nuget\NuGet.targets + EndProjectSection +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{10C5B1E8-15B5-4EB3-81AE-1FC054FE1305}" ProjectSection(SolutionItems) = preProject ..\build.fsx = ..\build.fsx diff --git a/src/benchmark/PersistenceBenchmark/App.config b/src/benchmark/PersistenceBenchmark/App.config index e28ac54bd91..8e15646352e 100644 --- a/src/benchmark/PersistenceBenchmark/App.config +++ b/src/benchmark/PersistenceBenchmark/App.config @@ -1,159 +1,6 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj b/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj index f8d22e1659b..11b1a369112 100644 --- a/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj +++ b/src/benchmark/PersistenceBenchmark/PersistenceBenchmark.csproj @@ -1,4 +1,4 @@ - + @@ -34,6 +34,18 @@ 4 + + ..\..\packages\Google.ProtocolBuffersLite.2.4.1.555\lib\net40\Google.ProtocolBuffersLite.dll + True + + + ..\..\packages\Google.ProtocolBuffersLite.2.4.1.555\lib\net40\Google.ProtocolBuffersLite.Serialization.dll + True + + + ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + True + @@ -51,7 +63,7 @@ - + @@ -64,7 +76,13 @@ - + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\net35\Google.ProtocolBuffersLite.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\net35\Google.ProtocolBuffersLite.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\net20\Google.ProtocolBuffersLite.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\net20\Google.ProtocolBuffersLite.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\net40\Google.ProtocolBuffersLite.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\net40\Google.ProtocolBuffersLite.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\sl30\Google.ProtocolBuffersLite.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\sl30\Google.ProtocolBuffersLite.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\sl40\Google.ProtocolBuffersLite.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\sl40\Google.ProtocolBuffersLite.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffersLite.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffersLite\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffersLite.dll - True - True - - - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - True - True - - - - \ No newline at end of file diff --git a/src/benchmark/PersistenceBenchmark/packages.config b/src/benchmark/PersistenceBenchmark/packages.config new file mode 100644 index 00000000000..2b3a26f2d02 --- /dev/null +++ b/src/benchmark/PersistenceBenchmark/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/benchmark/PersistenceBenchmark/paket.references b/src/benchmark/PersistenceBenchmark/paket.references deleted file mode 100644 index 73c061bddbc..00000000000 --- a/src/benchmark/PersistenceBenchmark/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -Google.ProtocolBuffersLite -Newtonsoft.Json \ No newline at end of file diff --git a/src/benchmark/PingPong/App.config b/src/benchmark/PingPong/App.config index 955b940cb6d..3523773e4ca 100644 --- a/src/benchmark/PingPong/App.config +++ b/src/benchmark/PingPong/App.config @@ -5,158 +5,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/Akka.DI.AutoFac.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/Akka.DI.AutoFac.Tests.csproj index cdd9860cf18..7c114dd0a26 100644 --- a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/Akka.DI.AutoFac.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/Akka.DI.AutoFac.Tests.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true 90620b22 @@ -32,6 +33,9 @@ 4 + + ..\..\..\packages\Autofac.3.5.2\lib\net40\Autofac.dll + @@ -71,9 +75,16 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\Autofac\lib\net40\Autofac.dll - True - True - - - - - - - ..\..\..\..\packages\Autofac\lib\portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\Autofac.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/packages.config b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/packages.config new file mode 100644 index 00000000000..f94275189e5 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/paket.references b/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/paket.references deleted file mode 100644 index 4ab2ac0970e..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.AutoFac.Tests/paket.references +++ /dev/null @@ -1 +0,0 @@ -Autofac \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac/Akka.DI.AutoFac.csproj b/src/contrib/dependencyInjection/Akka.DI.AutoFac/Akka.DI.AutoFac.csproj index 6f277e0f3f3..8629834eb56 100644 --- a/src/contrib/dependencyInjection/Akka.DI.AutoFac/Akka.DI.AutoFac.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.AutoFac/Akka.DI.AutoFac.csproj @@ -13,6 +13,7 @@ 512 ..\..\..\ + true true @@ -35,6 +36,9 @@ bin\Release\Akka.DI.AutoFac.xml + + ..\..\..\packages\Autofac.3.5.2\lib\net40\Autofac.dll + @@ -58,10 +62,17 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\Autofac\lib\net40\Autofac.dll - True - True - - - - - - - ..\..\..\..\packages\Autofac\lib\portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\Autofac.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac/packages.config b/src/contrib/dependencyInjection/Akka.DI.AutoFac/packages.config new file mode 100644 index 00000000000..f94275189e5 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.AutoFac/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.AutoFac/paket.references b/src/contrib/dependencyInjection/Akka.DI.AutoFac/paket.references deleted file mode 100644 index 4ab2ac0970e..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.AutoFac/paket.references +++ /dev/null @@ -1 +0,0 @@ -Autofac \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/Akka.DI.CastleWindsor.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/Akka.DI.CastleWindsor.Tests.csproj index 4bf22c25821..e1b388c58a9 100644 --- a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/Akka.DI.CastleWindsor.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/Akka.DI.CastleWindsor.Tests.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true 661b9909 @@ -32,6 +33,12 @@ 4 + + ..\..\..\packages\Castle.Core.3.3.0\lib\net45\Castle.Core.dll + + + ..\..\..\packages\Castle.Windsor.3.3.0\lib\net45\Castle.Windsor.dll + @@ -71,9 +78,16 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\Castle.Core\lib\net35\Castle.Core.dll - True - True - - - - - - - ..\..\..\..\packages\Castle.Core\lib\net40-client\Castle.Core.dll - True - True - - - - - - - ..\..\..\..\packages\Castle.Core\lib\net45\Castle.Core.dll - True - True - - - - - - - ..\..\..\..\packages\Castle.Core\lib\sl4\Castle.Core.dll - True - True - - - - - - - ..\..\..\..\packages\Castle.Core\lib\sl5\Castle.Core.dll - True - True - - - - - - - - - ..\..\..\..\packages\Castle.Windsor\lib\net35\Castle.Windsor.dll - True - True - - - - - - - ..\..\..\..\packages\Castle.Windsor\lib\net40\Castle.Windsor.dll - True - True - - - - - - - ..\..\..\..\packages\Castle.Windsor\lib\net45\Castle.Windsor.dll - True - True - - - - - - - ..\..\..\..\packages\Castle.Windsor\lib\sl4\Castle.Windsor.dll - True - True - - - True - - - - - - - ..\..\..\..\packages\Castle.Windsor\lib\sl5\Castle.Windsor.dll - True - True - - - True - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/packages.config b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/packages.config new file mode 100644 index 00000000000..010612fa8b0 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/paket.references b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/paket.references deleted file mode 100644 index 5957c632f29..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor.Tests/paket.references +++ /dev/null @@ -1 +0,0 @@ -Castle.Windsor \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/Akka.DI.CastleWindsor.csproj b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/Akka.DI.CastleWindsor.csproj index c2855776332..d8ae7d05c70 100644 --- a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/Akka.DI.CastleWindsor.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/Akka.DI.CastleWindsor.csproj @@ -13,6 +13,7 @@ 512 ..\..\..\ + true true @@ -35,6 +36,12 @@ bin\Release\Akka.DI.CastleWindsor.xml + + ..\..\..\packages\Castle.Core.3.3.0\lib\net45\Castle.Core.dll + + + ..\..\..\packages\Castle.Windsor.3.3.0\lib\net45\Castle.Windsor.dll + @@ -58,10 +65,17 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\Castle.Core\lib\net35\Castle.Core.dll - True - True - - - - - - - ..\..\..\..\packages\Castle.Core\lib\net40-client\Castle.Core.dll - True - True - - - - - - - ..\..\..\..\packages\Castle.Core\lib\net45\Castle.Core.dll - True - True - - - - - - - ..\..\..\..\packages\Castle.Core\lib\sl4\Castle.Core.dll - True - True - - - - - - - ..\..\..\..\packages\Castle.Core\lib\sl5\Castle.Core.dll - True - True - - - - - - - - - ..\..\..\..\packages\Castle.Windsor\lib\net35\Castle.Windsor.dll - True - True - - - True - - - - - - - ..\..\..\..\packages\Castle.Windsor\lib\net40\Castle.Windsor.dll - True - True - - - True - - - - - - - ..\..\..\..\packages\Castle.Windsor\lib\net45\Castle.Windsor.dll - True - True - - - True - - - - - - - ..\..\..\..\packages\Castle.Windsor\lib\sl4\Castle.Windsor.dll - True - True - - - True - - - - - - - ..\..\..\..\packages\Castle.Windsor\lib\sl5\Castle.Windsor.dll - True - True - - - True - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/packages.config b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/packages.config new file mode 100644 index 00000000000..010612fa8b0 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/paket.references b/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/paket.references deleted file mode 100644 index 5957c632f29..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.CastleWindsor/paket.references +++ /dev/null @@ -1 +0,0 @@ -Castle.Windsor \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/Akka.DI.Ninject.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/Akka.DI.Ninject.Tests.csproj index 493c8dd6c86..bbf08c22602 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/Akka.DI.Ninject.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/Akka.DI.Ninject.Tests.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true 42a2ce59 @@ -32,6 +33,10 @@ 4 + + ..\..\..\packages\Ninject.3.2.2.0\lib\net45-full\Ninject.dll + True + @@ -71,9 +76,16 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\Ninject\lib\net35\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\net40\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\net45-full\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\sl3\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\sl4\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\sl5\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\sl4-windowsphone71\Ninject.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/packages.config b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/packages.config new file mode 100644 index 00000000000..32203c61ad6 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/paket.references b/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/paket.references deleted file mode 100644 index a04c4b923f7..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.Ninject.Tests/paket.references +++ /dev/null @@ -1 +0,0 @@ -Ninject \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject/Akka.DI.Ninject.csproj b/src/contrib/dependencyInjection/Akka.DI.Ninject/Akka.DI.Ninject.csproj index 16b3354ac0e..93dc1bce87b 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Ninject/Akka.DI.Ninject.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Ninject/Akka.DI.Ninject.csproj @@ -13,6 +13,7 @@ 512 ..\..\..\ + true true @@ -35,6 +36,9 @@ bin\Release\Akka.DI.Ninject.xml + + ..\..\..\packages\Ninject.3.2.2.0\lib\net45-full\Ninject.dll + @@ -58,10 +62,17 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\Ninject\lib\net35\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\net40\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\net45-full\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\sl3\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\sl4\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\sl5\Ninject.dll - True - True - - - - - - - ..\..\..\..\packages\Ninject\lib\sl4-windowsphone71\Ninject.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject/packages.config b/src/contrib/dependencyInjection/Akka.DI.Ninject/packages.config new file mode 100644 index 00000000000..32203c61ad6 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.Ninject/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Ninject/paket.references b/src/contrib/dependencyInjection/Akka.DI.Ninject/paket.references deleted file mode 100644 index a04c4b923f7..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.Ninject/paket.references +++ /dev/null @@ -1 +0,0 @@ -Ninject \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/Akka.DI.StructureMap.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/Akka.DI.StructureMap.Tests.csproj index 57accfe4343..e0d7686af39 100644 --- a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/Akka.DI.StructureMap.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/Akka.DI.StructureMap.Tests.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true true @@ -31,6 +32,13 @@ 4 + + ..\..\..\packages\structuremap.3.1.5.154\lib\net40\StructureMap.dll + True + + + ..\..\..\packages\structuremap.3.1.5.154\lib\net40\StructureMap.Net4.dll + @@ -70,9 +78,16 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\structuremap\lib\net40\StructureMap.Net4.dll - True - True - - - ..\..\..\..\packages\structuremap\lib\net40\StructureMap.dll - True - True - - - - - - - ..\..\..\..\packages\structuremap\lib\wp80\StructureMap.dll - True - True - - - - - - - ..\..\..\..\packages\structuremap\lib\portable-net45+win+wp81\StructureMap.dll - True - True - - - - - - - ..\..\..\..\packages\structuremap\lib\portable-net4+netcore45+MonoAndroid1+MonoTouch1\StructureMap.dll - True - True - - - - - - - ..\..\..\..\packages\structuremap\lib\portable-win+net40+wp8\StructureMap.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/packages.config b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/packages.config new file mode 100644 index 00000000000..0374f33be6e --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/paket.references b/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/paket.references deleted file mode 100644 index cfcfcec02d0..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.StructureMap.Tests/paket.references +++ /dev/null @@ -1 +0,0 @@ -structuremap \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap/Akka.DI.StructureMap.csproj b/src/contrib/dependencyInjection/Akka.DI.StructureMap/Akka.DI.StructureMap.csproj index 93bcb308fc6..6c4863922dc 100644 --- a/src/contrib/dependencyInjection/Akka.DI.StructureMap/Akka.DI.StructureMap.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.StructureMap/Akka.DI.StructureMap.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true true @@ -31,6 +32,14 @@ 4 + + ..\..\..\packages\structuremap.3.1.5.154\lib\net40\StructureMap.dll + True + + + ..\..\..\packages\structuremap.3.1.5.154\lib\net40\StructureMap.Net4.dll + True + @@ -54,10 +63,17 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\structuremap\lib\net40\StructureMap.Net4.dll - True - True - - - ..\..\..\..\packages\structuremap\lib\net40\StructureMap.dll - True - True - - - - - - - ..\..\..\..\packages\structuremap\lib\wp80\StructureMap.dll - True - True - - - - - - - ..\..\..\..\packages\structuremap\lib\portable-net45+win+wp81\StructureMap.dll - True - True - - - - - - - ..\..\..\..\packages\structuremap\lib\portable-net4+netcore45+MonoAndroid1+MonoTouch1\StructureMap.dll - True - True - - - - - - - ..\..\..\..\packages\structuremap\lib\portable-win+net40+wp8\StructureMap.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap/packages.config b/src/contrib/dependencyInjection/Akka.DI.StructureMap/packages.config new file mode 100644 index 00000000000..0374f33be6e --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.StructureMap/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.StructureMap/paket.references b/src/contrib/dependencyInjection/Akka.DI.StructureMap/paket.references deleted file mode 100644 index cfcfcec02d0..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.StructureMap/paket.references +++ /dev/null @@ -1 +0,0 @@ -structuremap \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj b/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj index b7680fdbbf7..aea4363d66e 100644 --- a/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.TestKit/Akka.DI.TestKit.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ v4.5 512 ..\..\..\ - ac72c8df + true + + true @@ -39,6 +42,18 @@ + + ..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -67,9 +82,17 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\..\packages\test\xunit\lib\net20\xunit.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.TestKit/packages.config b/src/contrib/dependencyInjection/Akka.DI.TestKit/packages.config new file mode 100644 index 00000000000..3109db107fb --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.TestKit/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.TestKit/paket.references b/src/contrib/dependencyInjection/Akka.DI.TestKit/paket.references deleted file mode 100644 index 4bf78cf8fea..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.TestKit/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -group Test -xunit \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj index f7e7f77448c..5bd7265e038 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true true @@ -31,6 +32,16 @@ 4 + + ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.dll + True + + + ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.Configuration.dll + + + ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll + @@ -70,9 +81,16 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - + diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/packages.config b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/packages.config new file mode 100644 index 00000000000..75adcfb3762 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/paket.references b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/paket.references deleted file mode 100644 index f3ae0350f80..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/paket.references +++ /dev/null @@ -1 +0,0 @@ -Unity \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj b/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj index ee4e5d4d066..f3dfc59dff1 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\ + true true @@ -31,6 +32,16 @@ 4 + + ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.dll + + + ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.Configuration.dll + + + ..\..\..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll + True + @@ -54,10 +65,17 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - + diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity/packages.config b/src/contrib/dependencyInjection/Akka.DI.Unity/packages.config new file mode 100644 index 00000000000..75adcfb3762 --- /dev/null +++ b/src/contrib/dependencyInjection/Akka.DI.Unity/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity/paket.references b/src/contrib/dependencyInjection/Akka.DI.Unity/paket.references deleted file mode 100644 index f3ae0350f80..00000000000 --- a/src/contrib/dependencyInjection/Akka.DI.Unity/paket.references +++ /dev/null @@ -1 +0,0 @@ -Unity \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.NLog/Akka.Logger.NLog.csproj b/src/contrib/loggers/Akka.Logger.NLog/Akka.Logger.NLog.csproj index 42b643d4475..7b08686e5e5 100644 --- a/src/contrib/loggers/Akka.Logger.NLog/Akka.Logger.NLog.csproj +++ b/src/contrib/loggers/Akka.Logger.NLog/Akka.Logger.NLog.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\ + true true @@ -32,6 +33,9 @@ bin\Release\Akka.Logger.NLog.xml + + ..\..\..\packages\NLog.3.0.0.0\lib\net45\NLog.dll + @@ -54,9 +58,10 @@ Always - + + - - - - - - ..\..\..\..\packages\NLog\lib\net35\NLog.dll - True - True - - - - - - - ..\..\..\..\packages\NLog\lib\net40\NLog.dll - True - True - - - - - - - ..\..\..\..\packages\NLog\lib\net45\NLog.dll - True - True - - - - - - - ..\..\..\..\packages\NLog\lib\sl4\NLog.dll - True - True - - - - - - - ..\..\..\..\packages\NLog\lib\sl5\NLog.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.NLog/packages.config b/src/contrib/loggers/Akka.Logger.NLog/packages.config new file mode 100644 index 00000000000..e017f470208 --- /dev/null +++ b/src/contrib/loggers/Akka.Logger.NLog/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.NLog/paket.references b/src/contrib/loggers/Akka.Logger.NLog/paket.references deleted file mode 100644 index 0178a2ad4b8..00000000000 --- a/src/contrib/loggers/Akka.Logger.NLog/paket.references +++ /dev/null @@ -1 +0,0 @@ -NLog \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.Serilog/Akka.Logger.Serilog.csproj b/src/contrib/loggers/Akka.Logger.Serilog/Akka.Logger.Serilog.csproj index 379df9397b0..4798be337d2 100644 --- a/src/contrib/loggers/Akka.Logger.Serilog/Akka.Logger.Serilog.csproj +++ b/src/contrib/loggers/Akka.Logger.Serilog/Akka.Logger.Serilog.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true true @@ -32,6 +33,12 @@ bin\Release\Akka.Logger.Serilog.xml + + ..\..\..\packages\Serilog.1.3.43\lib\net45\Serilog.dll + + + ..\..\..\packages\Serilog.1.3.43\lib\net45\Serilog.FullNetFx.dll + @@ -54,9 +61,16 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\Serilog\lib\net40\Serilog.FullNetFx.dll - True - True - - - ..\..\..\..\packages\Serilog\lib\net40\Serilog.dll - True - True - - - - - - - ..\..\..\..\packages\Serilog\lib\net45\Serilog.FullNetFx.dll - True - True - - - ..\..\..\..\packages\Serilog\lib\net45\Serilog.dll - True - True - - - - - - - ..\..\..\..\packages\Serilog\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+MonoTouch10\Serilog.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.Serilog/packages.config b/src/contrib/loggers/Akka.Logger.Serilog/packages.config new file mode 100644 index 00000000000..d6ccb175dae --- /dev/null +++ b/src/contrib/loggers/Akka.Logger.Serilog/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.Serilog/paket.references b/src/contrib/loggers/Akka.Logger.Serilog/paket.references deleted file mode 100644 index 55deb233588..00000000000 --- a/src/contrib/loggers/Akka.Logger.Serilog/paket.references +++ /dev/null @@ -1 +0,0 @@ -Serilog \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.slf4net/Akka.Logger.slf4net.csproj b/src/contrib/loggers/Akka.Logger.slf4net/Akka.Logger.slf4net.csproj index 78b01059f88..1db2a92deca 100644 --- a/src/contrib/loggers/Akka.Logger.slf4net/Akka.Logger.slf4net.csproj +++ b/src/contrib/loggers/Akka.Logger.slf4net/Akka.Logger.slf4net.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\ + true true @@ -53,6 +54,9 @@ false + + ..\..\..\packages\slf4net.0.1.32.1\lib\net35\slf4net.dll + @@ -66,7 +70,7 @@ - + @@ -75,6 +79,7 @@ + - - - - - - ..\..\..\..\packages\slf4net\lib\net35\slf4net.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.slf4net/packages.config b/src/contrib/loggers/Akka.Logger.slf4net/packages.config new file mode 100644 index 00000000000..492f7656a1b --- /dev/null +++ b/src/contrib/loggers/Akka.Logger.slf4net/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/loggers/Akka.Logger.slf4net/paket.references b/src/contrib/loggers/Akka.Logger.slf4net/paket.references deleted file mode 100644 index b0b617e8486..00000000000 --- a/src/contrib/loggers/Akka.Logger.slf4net/paket.references +++ /dev/null @@ -1 +0,0 @@ -slf4net \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Akka.Persistence.Sql.Common.TestKit.csproj b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Akka.Persistence.Sql.Common.TestKit.csproj index 968958e2a94..0ec49470e3e 100644 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Akka.Persistence.Sql.Common.TestKit.csproj +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/Akka.Persistence.Sql.Common.TestKit.csproj @@ -1,5 +1,6 @@  + Debug @@ -40,6 +41,18 @@ + + ..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -72,9 +85,15 @@ - + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/packages.config b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/packages.config new file mode 100644 index 00000000000..3109db107fb --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/paket.references b/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/paket.references deleted file mode 100644 index aa6e6065aa7..00000000000 --- a/src/contrib/persistence/Akka.Persistence.Sql.Common.TestKit/paket.references +++ /dev/null @@ -1,5 +0,0 @@ -group Test -xunit.abstractions -xunit.assert -xunit.core -xunit.extensibility.core \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj index 4189fe6273a..2b9d576cba9 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj +++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/Akka.Persistence.Sqlite.Tests.csproj @@ -1,5 +1,6 @@  + Debug @@ -11,6 +12,8 @@ Akka.Persistence.Sqlite.Tests v4.5 512 + + true @@ -32,12 +35,28 @@ + + ..\..\..\packages\System.Data.SQLite.Core.1.0.98.1\lib\net45\System.Data.SQLite.dll + True + + + ..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -45,9 +64,6 @@ - - - {ad9418b6-c452-4169-94fb-d43de0bfa966} @@ -82,7 +98,18 @@ Akka.Persistence.Sqlite + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - ..\..\..\..\packages\System.Data.SQLite.Core\lib\net45\System.Data.SQLite.dll - True - True - - - - - - - ..\..\..\..\packages\System.Data.SQLite.Core\lib\net46\System.Data.SQLite.dll - True - True - - - - - - - ..\..\..\..\packages\System.Data.SQLite.Core\lib\net20\System.Data.SQLite.dll - True - True - - - - - - - ..\..\..\..\packages\System.Data.SQLite.Core\lib\net40\System.Data.SQLite.dll - True - True - - - - - - - ..\..\..\..\packages\System.Data.SQLite.Core\lib\net451\System.Data.SQLite.dll - True - True - - - - - - - - <__paket__System_Data_SQLite_Core_targets>net45\System.Data.SQLite.Core - - - - - <__paket__System_Data_SQLite_Core_targets>net46\System.Data.SQLite.Core - - - - - <__paket__System_Data_SQLite_Core_targets>net20\System.Data.SQLite.Core - - - - - <__paket__System_Data_SQLite_Core_targets>net40\System.Data.SQLite.Core - - - - - <__paket__System_Data_SQLite_Core_targets>net451\System.Data.SQLite.Core - - - - - - - - - ..\..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/packages.config b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/packages.config new file mode 100644 index 00000000000..39b7f0fdb27 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/paket.references b/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/paket.references deleted file mode 100644 index 16f189cb292..00000000000 --- a/src/contrib/persistence/Akka.Persistence.Sqlite.Tests/paket.references +++ /dev/null @@ -1,6 +0,0 @@ -System.Data.SQLite.Core - -group Test -xunit.core -xunit.assert -xunit.abstractions \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj index f826075c30b..899b65bcfd4 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj @@ -11,6 +11,8 @@ Akka.Persistence.Sqlite v4.5 512 + + true @@ -32,6 +34,10 @@ + + ..\..\..\packages\System.Data.SQLite.Core.1.0.98.1\lib\net45\System.Data.SQLite.dll + True + @@ -52,7 +58,7 @@ - + Always @@ -79,17 +85,8 @@ --> - - - - - ..\..\..\..\packages\System.Data.SQLite.Core\lib\net45\System.Data.SQLite.dll - True - True - - - + @@ -155,4 +152,11 @@ + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/packages.config b/src/contrib/persistence/Akka.Persistence.Sqlite/packages.config new file mode 100644 index 00000000000..038e00b11e3 --- /dev/null +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/paket.references b/src/contrib/persistence/Akka.Persistence.Sqlite/paket.references deleted file mode 100644 index e72d54b641b..00000000000 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/paket.references +++ /dev/null @@ -1 +0,0 @@ -System.Data.SQLite.Core \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit.Tests/Akka.TestKit.NUnit.Tests.csproj b/src/contrib/testkits/Akka.TestKit.NUnit.Tests/Akka.TestKit.NUnit.Tests.csproj index d0e87adeb32..a5f010ce778 100644 --- a/src/contrib/testkits/Akka.TestKit.NUnit.Tests/Akka.TestKit.NUnit.Tests.csproj +++ b/src/contrib/testkits/Akka.TestKit.NUnit.Tests/Akka.TestKit.NUnit.Tests.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true true @@ -31,6 +32,9 @@ 4 + + ..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll + @@ -46,7 +50,7 @@ - + @@ -66,6 +70,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - ..\..\..\..\packages\test\NUnit\lib\nunit.framework.dll - True - True - - \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit.Tests/packages.config b/src/contrib/testkits/Akka.TestKit.NUnit.Tests/packages.config new file mode 100644 index 00000000000..c714ef3a23e --- /dev/null +++ b/src/contrib/testkits/Akka.TestKit.NUnit.Tests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit.Tests/paket.references b/src/contrib/testkits/Akka.TestKit.NUnit.Tests/paket.references deleted file mode 100644 index 9e41999fc79..00000000000 --- a/src/contrib/testkits/Akka.TestKit.NUnit.Tests/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -group Test -NUnit \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit/Akka.TestKit.NUnit.csproj b/src/contrib/testkits/Akka.TestKit.NUnit/Akka.TestKit.NUnit.csproj index 2790c745467..366fcd95e1e 100644 --- a/src/contrib/testkits/Akka.TestKit.NUnit/Akka.TestKit.NUnit.csproj +++ b/src/contrib/testkits/Akka.TestKit.NUnit/Akka.TestKit.NUnit.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true true @@ -32,6 +33,9 @@ bin\Release\Akka.TestKit.NUnit.xml + + ..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll + @@ -49,7 +53,7 @@ - + @@ -62,6 +66,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - ..\..\..\..\packages\test\NUnit\lib\nunit.framework.dll - True - True - - \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit/packages.config b/src/contrib/testkits/Akka.TestKit.NUnit/packages.config new file mode 100644 index 00000000000..c714ef3a23e --- /dev/null +++ b/src/contrib/testkits/Akka.TestKit.NUnit/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.NUnit/paket.references b/src/contrib/testkits/Akka.TestKit.NUnit/paket.references deleted file mode 100644 index 9e41999fc79..00000000000 --- a/src/contrib/testkits/Akka.TestKit.NUnit/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -group Test -NUnit \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit/Akka.TestKit.Xunit.csproj b/src/contrib/testkits/Akka.TestKit.Xunit/Akka.TestKit.Xunit.csproj index 67fed050be7..1a0b02d4d71 100644 --- a/src/contrib/testkits/Akka.TestKit.Xunit/Akka.TestKit.Xunit.csproj +++ b/src/contrib/testkits/Akka.TestKit.Xunit/Akka.TestKit.Xunit.csproj @@ -1,4 +1,4 @@ - + @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true a4af550d @@ -36,6 +37,10 @@ + + ..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll + True + @@ -48,9 +53,6 @@ - - - {0D3CBAD0-BBDB-43E5-AFC4-ED1D3ECDC224} @@ -61,7 +63,17 @@ Akka + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - ..\..\..\..\packages\legacy\xunit\lib\net20\xunit.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit/packages.config b/src/contrib/testkits/Akka.TestKit.Xunit/packages.config new file mode 100644 index 00000000000..3eb1f079098 --- /dev/null +++ b/src/contrib/testkits/Akka.TestKit.Xunit/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit/paket.references b/src/contrib/testkits/Akka.TestKit.Xunit/paket.references deleted file mode 100644 index 81437c4a85e..00000000000 --- a/src/contrib/testkits/Akka.TestKit.Xunit/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -group Legacy -xunit \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj b/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj index e0ecbfe8b60..07f3e43d953 100644 --- a/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj +++ b/src/contrib/testkits/Akka.TestKit.Xunit2/Akka.TestKit.Xunit2.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ v4.5 512 ..\..\..\ - 6577902d + true + + true @@ -34,6 +37,18 @@ + + ..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -47,9 +62,6 @@ - - - {0d3cbad0-bbdb-43e5-afc4-ed1d3ecdc224} @@ -60,7 +72,18 @@ Akka + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/packages.config b/src/contrib/testkits/Akka.TestKit.Xunit2/packages.config new file mode 100644 index 00000000000..3109db107fb --- /dev/null +++ b/src/contrib/testkits/Akka.TestKit.Xunit2/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/contrib/testkits/Akka.TestKit.Xunit2/paket.references b/src/contrib/testkits/Akka.TestKit.Xunit2/paket.references deleted file mode 100644 index f1e55442a7e..00000000000 --- a/src/contrib/testkits/Akka.TestKit.Xunit2/paket.references +++ /dev/null @@ -1,3 +0,0 @@ -group Test -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj b/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj index fcc08ba79e7..c45e38b20e8 100644 --- a/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true true @@ -49,6 +50,12 @@ True + + ..\..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll + + + ..\..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll + @@ -72,9 +79,16 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - + @@ -141,4 +155,4 @@ - \ No newline at end of file + diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/packages.config b/src/contrib/transports/Akka.Remote.AkkaIOTransport/packages.config new file mode 100644 index 00000000000..5948219c6c9 --- /dev/null +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/paket.references b/src/contrib/transports/Akka.Remote.AkkaIOTransport/paket.references deleted file mode 100644 index 07508816865..00000000000 --- a/src/contrib/transports/Akka.Remote.AkkaIOTransport/paket.references +++ /dev/null @@ -1 +0,0 @@ -Google.ProtocolBuffers \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj b/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj index 2787b4f2c13..ef0c889964a 100644 --- a/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj +++ b/src/core/Akka.Cluster.Tests.MultiNode/Akka.Cluster.Tests.MultiNode.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ v4.5 512 ..\..\ - 1a218765 + true + + true @@ -33,12 +36,28 @@ + + ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -54,9 +73,6 @@ - - - {7dbd5c17-5e9d-40c4-9201-d092751532a7} @@ -88,12 +104,21 @@ - + - + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests.MultiNode/app.config b/src/core/Akka.Cluster.Tests.MultiNode/app.config new file mode 100644 index 00000000000..f0bd3189cf4 --- /dev/null +++ b/src/core/Akka.Cluster.Tests.MultiNode/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests.MultiNode/packages.config b/src/core/Akka.Cluster.Tests.MultiNode/packages.config new file mode 100644 index 00000000000..15502b4d7f9 --- /dev/null +++ b/src/core/Akka.Cluster.Tests.MultiNode/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests.MultiNode/paket.references b/src/core/Akka.Cluster.Tests.MultiNode/paket.references deleted file mode 100644 index b678a533d76..00000000000 --- a/src/core/Akka.Cluster.Tests.MultiNode/paket.references +++ /dev/null @@ -1,5 +0,0 @@ -System.Collections.Immutable - -group Test -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj b/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj index eb8385511dd..da9c4c5db4d 100644 --- a/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj +++ b/src/core/Akka.Cluster.Tests/Akka.Cluster.Tests.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -11,7 +12,9 @@ v4.5 512 ..\..\ - d8ea7d64 + true + + true @@ -31,27 +34,41 @@ 4 - - True - - - True - - - True - - - True - - - True - - - True - + + ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.dll + True + + + ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.Core.dll + True + + + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll + True + + + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + + + ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -59,6 +76,7 @@ + @@ -117,10 +135,19 @@ - + - + + + + + + + + + + @@ -142,6 +169,14 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll - True - True - - - - - - - - - ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - True - - - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\win8\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\win8\FluentAssertions.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\net40\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\net40\FluentAssertions.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\net45\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\net45\FluentAssertions.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\sl5\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\sl5\FluentAssertions.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\sl5\Microsoft.CSharp.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\sl5\Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\wp8\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\wp8\FluentAssertions.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\portable-monotouch+monoandroid+xamarin.ios\FluentAssertions.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\portable-win81+wpa81\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\portable-win81+wpa81\FluentAssertions.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\portable-net40+sl5+win8+wp8+wpa81\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\portable-net40+sl5+win8+wp8+wpa81\FluentAssertions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/CHANGES.txt b/src/core/Akka.Cluster.Tests/CHANGES.txt deleted file mode 100644 index d80368c78f2..00000000000 --- a/src/core/Akka.Cluster.Tests/CHANGES.txt +++ /dev/null @@ -1,99 +0,0 @@ -=============================================================================== -Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet -(skeet@pobox.com) based on the work of many talented people. - -For more information about this port, visit its homepage: -http://protobuf-csharp-port.googlecode.com - -For more information about Protocol Buffers in general, visit the project page -for the C++, Java and Python project: -http://protobuf.googlecode.com -=============================================================================== -RELEASE NOTES - Version 2.4.1.473 -=============================================================================== - -Features: -- Added option service_generator_type to control service generation with - NONE, GENERIC, INTERFACE, or IRPCDISPATCH -- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking - services and implementations. -- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the - location of protoc.exe. -- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow - custom implementation of writers with both speed and size optimizations. -- Addition of the "Google.ProtoBuffers.Serialization" assembly to support - reading and writing messages to/from XML, JSON, IDictionary<,> and others. -- Several performance related fixes and tweeks -- Issue 3: Add option to mark generated code with attribute -- Issue 20: Support for decorating classes [Serializable] -- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] -- Issue 22: Reusable Builder classes -- Issue 24: Support for using Json/Xml formats with ICodedInputStream -- Issue 25: Added support for NuGet packages -- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 - -Fixes: -- Issue 13: Message with Field same name as message causes uncompilable .cs -- Issue 16: Does not integrate well with other tooling -- Issue 19: Support for negative enum values -- Issue 26: AddRange in GeneratedBuilder iterates twice. -- Issue 27: Remove XML documentation output from test projects to clear - warnings/errors. -- Issue 28: Circular message dependencies result in null default values for - Message fields. -- Issue 29: Message classes generated have a public default constructor. You - can disable private ctor generation with the option generate_private_ctor. -- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ -- Big-endian support for float, and double on Silverlight -- Packed and Unpacked parsing allow for all repeated, as per version 2.3 -- Fix for leaving Builder a public ctor on internal classes for use with - generic "where T: new()" constraints. - -Other: -- Changed the code signing key to a privately held key -- Reformatted all code and line-endings to C# defaults -- Reworking of performance benchmarks to produce reliable results, option /v2 -- Issue 34: Silverlight assemblies are now unit tested - -=============================================================================== -RELEASE NOTES - Version 2.3.0.277 -=============================================================================== - -Features: -- Added cls_compliance option to generate attributes indicating - non-CLS-compliance. -- Added file_extension option to control the generated output file's extension. -- Added umbrella_namespace option to place the umbrella class into a nested - namespace to address issues with proto files having the same name as a - message it contains. -- Added output_directory option to set the output path for the source file(s). -- Added ignore_google_protobuf option to avoid generating code for includes - from the google.protobuf package. -- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to - generate code with "option optimize_for = LITE_RUNTIME;". -- Added ability to invoke protoc.exe from within ProtoGen.exe. -- Upgraded to protoc.exe (2.3) compiler. - -Fixes: -- Issue 9: Class cannot be static and sealed error -- Issue 12: default value for enumerate fields must be filled out - -Other: -- Rewrite of build using MSBbuild instead of NAnt -- Moved to NUnit Version 2.2.8.0 -- Changed to using secure .snk for releases - -=============================================================================== -RELEASE NOTES - Version 0.9.1 -=============================================================================== - -Fixes: -- issue 10: Incorrect encoding of packed fields when serialized - -=============================================================================== -RELEASE NOTES - Version 0.9.0 -=============================================================================== - -- Initial release - -=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/app.config b/src/core/Akka.Cluster.Tests/app.config new file mode 100644 index 00000000000..f0bd3189cf4 --- /dev/null +++ b/src/core/Akka.Cluster.Tests/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/licenses/license.txt b/src/core/Akka.Cluster.Tests/licenses/license.txt deleted file mode 100644 index b8e773b2e05..00000000000 --- a/src/core/Akka.Cluster.Tests/licenses/license.txt +++ /dev/null @@ -1,31 +0,0 @@ -Protocol Buffers - Google's data interchange format -Copyright 2008-2010 Google Inc. All rights reserved. -http://github.com/jskeet/dotnet-protobufs/ -Original C++/Java/Python code: -http://code.google.com/p/protobuf/ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Cluster.Tests/licenses/protoc-license.txt b/src/core/Akka.Cluster.Tests/licenses/protoc-license.txt deleted file mode 100644 index c779cb0e1ed..00000000000 --- a/src/core/Akka.Cluster.Tests/licenses/protoc-license.txt +++ /dev/null @@ -1,36 +0,0 @@ -protoc.exe was built from the original source at http://code.google.com/p/protobuf/ -The licence for this code is as follows: - -Copyright 2008, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Code generated by the Protocol Buffer compiler is owned by the owner -of the input file used when generating it. This code is not -standalone and requires a support library to be linked with it. This -support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/packages.config b/src/core/Akka.Cluster.Tests/packages.config new file mode 100644 index 00000000000..b603d1619c6 --- /dev/null +++ b/src/core/Akka.Cluster.Tests/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/paket.references b/src/core/Akka.Cluster.Tests/paket.references deleted file mode 100644 index 743b6c0b38f..00000000000 --- a/src/core/Akka.Cluster.Tests/paket.references +++ /dev/null @@ -1,6 +0,0 @@ -Google.ProtocolBuffers -System.Collections.Immutable -group Test -FluentAssertions -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Cluster.Tests/protos/google/protobuf/csharp_options.proto deleted file mode 100644 index 152df766f03..00000000000 --- a/src/core/Akka.Cluster.Tests/protos/google/protobuf/csharp_options.proto +++ /dev/null @@ -1,115 +0,0 @@ -// Extra options for C# generator - -import "google/protobuf/descriptor.proto"; - -package google.protobuf; - -message CSharpFileOptions { - - // Namespace for generated classes; defaults to the package. - optional string namespace = 1; - - // Name of the "umbrella" class used for metadata about all - // the messages within this file. Default is based on the name - // of the file. - optional string umbrella_classname = 2; - - // Whether classes should be public (true) or internal (false) - optional bool public_classes = 3 [default = true]; - - // Whether to generate a single file for everything within the - // .proto file (false), or one file per message (true). - // This option is not currently honored; please log a feature - // request if you really want it. - optional bool multiple_files = 4; - - // Whether to nest messages within a single umbrella class (true) - // or create the umbrella class as a peer, with messages as - // top-level classes in the namespace (false) - optional bool nest_classes = 5; - - // Generate appropriate support for Code Contracts - // (Ongoing; support should improve over time) - optional bool code_contracts = 6; - - // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" - // would generate files within [output directory]/Foo/Bar - optional bool expand_namespace_directories = 7; - - // Generate attributes indicating non-CLS-compliance - optional bool cls_compliance = 8 [default = true]; - - // Generate messages/builders with the [Serializable] attribute - optional bool add_serializable = 9 [default = false]; - - // Generates a private ctor for Message types - optional bool generate_private_ctor = 10 [default = true]; - - // The extension that should be appended to the umbrella_classname when creating files. - optional string file_extension = 221 [default = ".cs"]; - - // A nested namespace for the umbrella class. Helpful for name collisions caused by - // umbrella_classname conflicting with an existing type. This will be automatically - // set to 'Proto' if a collision is detected with types being generated. This value - // is ignored when nest_classes == true - optional string umbrella_namespace = 222; - - // The output path for the source file(s) generated - optional string output_directory = 223 [default = "."]; - - // Will ignore the type generations and remove dependencies for the descriptor proto - // files that declare their package to be "google.protobuf" - optional bool ignore_google_protobuf = 224 [default = false]; - - // Controls how services are generated, GENERIC is the deprecated original implementation - // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and - // implementations using the included Windows RPC interop libarary. - optional CSharpServiceType service_generator_type = 225 [default = NONE]; - - // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and - // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. - optional bool generated_code_attributes = 226 [default = false]; -} - -enum CSharpServiceType { - // Services are ignored by the generator - NONE = 0; - // Generates the original Java generic service implementations - GENERIC = 1; - // Generates an interface for the service and nothing else - INTERFACE = 2; - // Generates an interface for the service and client/server wrappers for the interface - IRPCDISPATCH = 3; -} - -extend FileOptions { - optional CSharpFileOptions csharp_file_options = 1000; -} - -extend FieldOptions { - optional CSharpFieldOptions csharp_field_options = 1000; -} - -message CSharpFieldOptions { - // Provides the ability to override the name of the property - // generated for this field. This is applied to all properties - // and methods to do with this field, including HasFoo, FooCount, - // FooList etc. - optional string property_name = 1; -} - -message CSharpServiceOptions { - optional string interface_id = 1; -} - -extend ServiceOptions { - optional CSharpServiceOptions csharp_service_options = 1000; -} - -message CSharpMethodOptions { - optional int32 dispatch_id = 1; -} - -extend MethodOptions { - optional CSharpMethodOptions csharp_method_options = 1000; -} \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests/protos/google/protobuf/descriptor.proto b/src/core/Akka.Cluster.Tests/protos/google/protobuf/descriptor.proto deleted file mode 100644 index 233f879410e..00000000000 --- a/src/core/Akka.Cluster.Tests/protos/google/protobuf/descriptor.proto +++ /dev/null @@ -1,533 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. -// -// The messages in this file describe the definitions found in .proto files. -// A valid .proto file can be translated directly to a FileDescriptorProto -// without any other information (e.g. without reading its imports). - - - -package google.protobuf; -option java_package = "com.google.protobuf"; -option java_outer_classname = "DescriptorProtos"; - -// descriptor.proto must be optimized for speed because reflection-based -// algorithms don't work during bootstrapping. -option optimize_for = SPEED; - -// The protocol compiler can output a FileDescriptorSet containing the .proto -// files it parses. -message FileDescriptorSet { - repeated FileDescriptorProto file = 1; -} - -// Describes a complete .proto file. -message FileDescriptorProto { - optional string name = 1; // file name, relative to root of source tree - optional string package = 2; // e.g. "foo", "foo.bar", etc. - - // Names of files imported by this file. - repeated string dependency = 3; - - // All top-level definitions in this file. - repeated DescriptorProto message_type = 4; - repeated EnumDescriptorProto enum_type = 5; - repeated ServiceDescriptorProto service = 6; - repeated FieldDescriptorProto extension = 7; - - optional FileOptions options = 8; - - // This field contains optional information about the original source code. - // You may safely remove this entire field whithout harming runtime - // functionality of the descriptors -- the information is needed only by - // development tools. - optional SourceCodeInfo source_code_info = 9; -} - -// Describes a message type. -message DescriptorProto { - optional string name = 1; - - repeated FieldDescriptorProto field = 2; - repeated FieldDescriptorProto extension = 6; - - repeated DescriptorProto nested_type = 3; - repeated EnumDescriptorProto enum_type = 4; - - message ExtensionRange { - optional int32 start = 1; - optional int32 end = 2; - } - repeated ExtensionRange extension_range = 5; - - optional MessageOptions options = 7; -} - -// Describes a field within a message. -message FieldDescriptorProto { - enum Type { - // 0 is reserved for errors. - // Order is weird for historical reasons. - TYPE_DOUBLE = 1; - TYPE_FLOAT = 2; - TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT64 if negative - // values are likely. - TYPE_UINT64 = 4; - TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT32 if negative - // values are likely. - TYPE_FIXED64 = 6; - TYPE_FIXED32 = 7; - TYPE_BOOL = 8; - TYPE_STRING = 9; - TYPE_GROUP = 10; // Tag-delimited aggregate. - TYPE_MESSAGE = 11; // Length-delimited aggregate. - - // New in version 2. - TYPE_BYTES = 12; - TYPE_UINT32 = 13; - TYPE_ENUM = 14; - TYPE_SFIXED32 = 15; - TYPE_SFIXED64 = 16; - TYPE_SINT32 = 17; // Uses ZigZag encoding. - TYPE_SINT64 = 18; // Uses ZigZag encoding. - }; - - enum Label { - // 0 is reserved for errors - LABEL_OPTIONAL = 1; - LABEL_REQUIRED = 2; - LABEL_REPEATED = 3; - // TODO(sanjay): Should we add LABEL_MAP? - }; - - optional string name = 1; - optional int32 number = 3; - optional Label label = 4; - - // If type_name is set, this need not be set. If both this and type_name - // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. - optional Type type = 5; - - // For message and enum types, this is the name of the type. If the name - // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping - // rules are used to find the type (i.e. first the nested types within this - // message are searched, then within the parent, on up to the root - // namespace). - optional string type_name = 6; - - // For extensions, this is the name of the type being extended. It is - // resolved in the same manner as type_name. - optional string extendee = 2; - - // For numeric types, contains the original text representation of the value. - // For booleans, "true" or "false". - // For strings, contains the default text contents (not escaped in any way). - // For bytes, contains the C escaped value. All bytes >= 128 are escaped. - // TODO(kenton): Base-64 encode? - optional string default_value = 7; - - optional FieldOptions options = 8; -} - -// Describes an enum type. -message EnumDescriptorProto { - optional string name = 1; - - repeated EnumValueDescriptorProto value = 2; - - optional EnumOptions options = 3; -} - -// Describes a value within an enum. -message EnumValueDescriptorProto { - optional string name = 1; - optional int32 number = 2; - - optional EnumValueOptions options = 3; -} - -// Describes a service. -message ServiceDescriptorProto { - optional string name = 1; - repeated MethodDescriptorProto method = 2; - - optional ServiceOptions options = 3; -} - -// Describes a method of a service. -message MethodDescriptorProto { - optional string name = 1; - - // Input and output type names. These are resolved in the same way as - // FieldDescriptorProto.type_name, but must refer to a message type. - optional string input_type = 2; - optional string output_type = 3; - - optional MethodOptions options = 4; -} - -// =================================================================== -// Options - -// Each of the definitions above may have "options" attached. These are -// just annotations which may cause code to be generated slightly differently -// or may contain hints for code that manipulates protocol messages. -// -// Clients may define custom options as extensions of the *Options messages. -// These extensions may not yet be known at parsing time, so the parser cannot -// store the values in them. Instead it stores them in a field in the *Options -// message called uninterpreted_option. This field must have the same name -// across all *Options messages. We then use this field to populate the -// extensions when we build a descriptor, at which point all protos have been -// parsed and so all extensions are known. -// -// Extension numbers for custom options may be chosen as follows: -// * For options which will only be used within a single application or -// organization, or for experimental options, use field numbers 50000 -// through 99999. It is up to you to ensure that you do not use the -// same number for multiple options. -// * For options which will be published and used publicly by multiple -// independent entities, e-mail kenton@google.com to reserve extension -// numbers. Simply tell me how many you need and I'll send you back a -// set of numbers to use -- there's no need to explain how you intend to -// use them. If this turns out to be popular, a web service will be set up -// to automatically assign option numbers. - - -message FileOptions { - - // Sets the Java package where classes generated from this .proto will be - // placed. By default, the proto package is used, but this is often - // inappropriate because proto packages do not normally start with backwards - // domain names. - optional string java_package = 1; - - - // If set, all the classes from the .proto file are wrapped in a single - // outer class with the given name. This applies to both Proto1 - // (equivalent to the old "--one_java_file" option) and Proto2 (where - // a .proto always translates to a single class, but you may want to - // explicitly choose the class name). - optional string java_outer_classname = 8; - - // If set true, then the Java code generator will generate a separate .java - // file for each top-level message, enum, and service defined in the .proto - // file. Thus, these types will *not* be nested inside the outer class - // named by java_outer_classname. However, the outer class will still be - // generated to contain the file's getDescriptor() method as well as any - // top-level extensions defined in the file. - optional bool java_multiple_files = 10 [default=false]; - - // If set true, then the Java code generator will generate equals() and - // hashCode() methods for all messages defined in the .proto file. This is - // purely a speed optimization, as the AbstractMessage base class includes - // reflection-based implementations of these methods. - optional bool java_generate_equals_and_hash = 20 [default=false]; - - // Generated classes can be optimized for speed or code size. - enum OptimizeMode { - SPEED = 1; // Generate complete code for parsing, serialization, - // etc. - CODE_SIZE = 2; // Use ReflectionOps to implement these methods. - LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. - } - optional OptimizeMode optimize_for = 9 [default=SPEED]; - - - - - // Should generic services be generated in each language? "Generic" services - // are not specific to any particular RPC system. They are generated by the - // main code generators in each language (without additional plugins). - // Generic services were the only kind of service generation supported by - // early versions of proto2. - // - // Generic services are now considered deprecated in favor of using plugins - // that generate code specific to your particular RPC system. Therefore, - // these default to false. Old code which depends on generic services should - // explicitly set them to true. - optional bool cc_generic_services = 16 [default=false]; - optional bool java_generic_services = 17 [default=false]; - optional bool py_generic_services = 18 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MessageOptions { - // Set true to use the old proto1 MessageSet wire format for extensions. - // This is provided for backwards-compatibility with the MessageSet wire - // format. You should not use this for any other reason: It's less - // efficient, has fewer features, and is more complicated. - // - // The message must be defined exactly as follows: - // message Foo { - // option message_set_wire_format = true; - // extensions 4 to max; - // } - // Note that the message cannot have any defined fields; MessageSets only - // have extensions. - // - // All extensions of your type must be singular messages; e.g. they cannot - // be int32s, enums, or repeated messages. - // - // Because this is an option, the above two restrictions are not enforced by - // the protocol compiler. - optional bool message_set_wire_format = 1 [default=false]; - - // Disables the generation of the standard "descriptor()" accessor, which can - // conflict with a field of the same name. This is meant to make migration - // from proto1 easier; new code should avoid fields named "descriptor". - optional bool no_standard_descriptor_accessor = 2 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message FieldOptions { - // The ctype option instructs the C++ code generator to use a different - // representation of the field than it normally would. See the specific - // options below. This option is not yet implemented in the open source - // release -- sorry, we'll try to include it in a future version! - optional CType ctype = 1 [default = STRING]; - enum CType { - // Default mode. - STRING = 0; - - CORD = 1; - - STRING_PIECE = 2; - } - // The packed option can be enabled for repeated primitive fields to enable - // a more efficient representation on the wire. Rather than repeatedly - // writing the tag and type for each element, the entire array is encoded as - // a single length-delimited blob. - optional bool packed = 2; - - - // Is this field deprecated? - // Depending on the target platform, this can emit Deprecated annotations - // for accessors, or it will be completely ignored; in the very least, this - // is a formalization for deprecating fields. - optional bool deprecated = 3 [default=false]; - - // EXPERIMENTAL. DO NOT USE. - // For "map" fields, the name of the field in the enclosed type that - // is the key for this map. For example, suppose we have: - // message Item { - // required string name = 1; - // required string value = 2; - // } - // message Config { - // repeated Item items = 1 [experimental_map_key="name"]; - // } - // In this situation, the map key for Item will be set to "name". - // TODO: Fully-implement this, then remove the "experimental_" prefix. - optional string experimental_map_key = 9; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumOptions { - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumValueOptions { - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message ServiceOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MethodOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -// A message representing a option the parser does not recognize. This only -// appears in options protos created by the compiler::Parser class. -// DescriptorPool resolves these when building Descriptor objects. Therefore, -// options protos in descriptor objects (e.g. returned by Descriptor::options(), -// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions -// in them. -message UninterpretedOption { - // The name of the uninterpreted option. Each string represents a segment in - // a dot-separated name. is_extension is true iff a segment represents an - // extension (denoted with parentheses in options specs in .proto files). - // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents - // "foo.(bar.baz).qux". - message NamePart { - required string name_part = 1; - required bool is_extension = 2; - } - repeated NamePart name = 2; - - // The value of the uninterpreted option, in whatever type the tokenizer - // identified it as during parsing. Exactly one of these should be set. - optional string identifier_value = 3; - optional uint64 positive_int_value = 4; - optional int64 negative_int_value = 5; - optional double double_value = 6; - optional bytes string_value = 7; - optional string aggregate_value = 8; -} - -// =================================================================== -// Optional source code info - -// Encapsulates information about the original source file from which a -// FileDescriptorProto was generated. -message SourceCodeInfo { - // A Location identifies a piece of source code in a .proto file which - // corresponds to a particular definition. This information is intended - // to be useful to IDEs, code indexers, documentation generators, and similar - // tools. - // - // For example, say we have a file like: - // message Foo { - // optional string foo = 1; - // } - // Let's look at just the field definition: - // optional string foo = 1; - // ^ ^^ ^^ ^ ^^^ - // a bc de f ghi - // We have the following locations: - // span path represents - // [a,i) [ 4, 0, 2, 0 ] The whole field definition. - // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). - // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). - // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). - // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). - // - // Notes: - // - A location may refer to a repeated field itself (i.e. not to any - // particular index within it). This is used whenever a set of elements are - // logically enclosed in a single code segment. For example, an entire - // extend block (possibly containing multiple extension definitions) will - // have an outer location whose path refers to the "extensions" repeated - // field without an index. - // - Multiple locations may have the same path. This happens when a single - // logical declaration is spread out across multiple places. The most - // obvious example is the "extend" block again -- there may be multiple - // extend blocks in the same scope, each of which will have the same path. - // - A location's span is not always a subset of its parent's span. For - // example, the "extendee" of an extension declaration appears at the - // beginning of the "extend" block and is shared by all extensions within - // the block. - // - Just because a location's span is a subset of some other location's span - // does not mean that it is a descendent. For example, a "group" defines - // both a type and a field in a single declaration. Thus, the locations - // corresponding to the type and field and their components will overlap. - // - Code which tries to interpret locations should probably be designed to - // ignore those that it doesn't understand, as more types of locations could - // be recorded in the future. - repeated Location location = 1; - message Location { - // Identifies which part of the FileDescriptorProto was defined at this - // location. - // - // Each element is a field number or an index. They form a path from - // the root FileDescriptorProto to the place where the definition. For - // example, this path: - // [ 4, 3, 2, 7, 1 ] - // refers to: - // file.message_type(3) // 4, 3 - // .field(7) // 2, 7 - // .name() // 1 - // This is because FileDescriptorProto.message_type has field number 4: - // repeated DescriptorProto message_type = 4; - // and DescriptorProto.field has field number 2: - // repeated FieldDescriptorProto field = 2; - // and FieldDescriptorProto.name has field number 1: - // optional string name = 1; - // - // Thus, the above path gives the location of a field name. If we removed - // the last element: - // [ 4, 3, 2, 7 ] - // this path refers to the whole field declaration (from the beginning - // of the label to the terminating semicolon). - repeated int32 path = 1 [packed=true]; - - // Always has exactly three or four elements: start line, start column, - // end line (optional, otherwise assumed same as start line), end column. - // These are packed into a single field for efficiency. Note that line - // and column numbers are zero-based -- typically you will want to add - // 1 to each before displaying to a user. - repeated int32 span = 2 [packed=true]; - - // TODO(kenton): Record comments appearing before and after the - // declaration. - } -} diff --git a/src/core/Akka.Cluster.Tests/protos/tutorial/addressbook.proto b/src/core/Akka.Cluster.Tests/protos/tutorial/addressbook.proto deleted file mode 100644 index 5abe35ce39b..00000000000 --- a/src/core/Akka.Cluster.Tests/protos/tutorial/addressbook.proto +++ /dev/null @@ -1,31 +0,0 @@ -package tutorial; - -import "google/protobuf/csharp_options.proto"; -option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; -option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; - -option optimize_for = SPEED; - -message Person { - required string name = 1; - required int32 id = 2; // Unique ID number for this person. - optional string email = 3; - - enum PhoneType { - MOBILE = 0; - HOME = 1; - WORK = 2; - } - - message PhoneNumber { - required string number = 1; - optional PhoneType type = 2 [default = HOME]; - } - - repeated PhoneNumber phone = 4; -} - -// Our address book file is just one of these. -message AddressBook { - repeated Person person = 1; -} diff --git a/src/core/Akka.Cluster/Akka.Cluster.csproj b/src/core/Akka.Cluster/Akka.Cluster.csproj index 8d7342e988a..f368cd524ce 100644 --- a/src/core/Akka.Cluster/Akka.Cluster.csproj +++ b/src/core/Akka.Cluster/Akka.Cluster.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\ + true true @@ -49,26 +50,22 @@ bin\Release\Akka.Cluster.xml - - True - - - True - - - True - - - True - - - True - - - True - + + False + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll + True + + + False + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + + + ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + @@ -110,9 +107,24 @@ - + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll - True - True - - - - - - - - - ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Cluster/CHANGES.txt b/src/core/Akka.Cluster/CHANGES.txt deleted file mode 100644 index d80368c78f2..00000000000 --- a/src/core/Akka.Cluster/CHANGES.txt +++ /dev/null @@ -1,99 +0,0 @@ -=============================================================================== -Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet -(skeet@pobox.com) based on the work of many talented people. - -For more information about this port, visit its homepage: -http://protobuf-csharp-port.googlecode.com - -For more information about Protocol Buffers in general, visit the project page -for the C++, Java and Python project: -http://protobuf.googlecode.com -=============================================================================== -RELEASE NOTES - Version 2.4.1.473 -=============================================================================== - -Features: -- Added option service_generator_type to control service generation with - NONE, GENERIC, INTERFACE, or IRPCDISPATCH -- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking - services and implementations. -- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the - location of protoc.exe. -- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow - custom implementation of writers with both speed and size optimizations. -- Addition of the "Google.ProtoBuffers.Serialization" assembly to support - reading and writing messages to/from XML, JSON, IDictionary<,> and others. -- Several performance related fixes and tweeks -- Issue 3: Add option to mark generated code with attribute -- Issue 20: Support for decorating classes [Serializable] -- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] -- Issue 22: Reusable Builder classes -- Issue 24: Support for using Json/Xml formats with ICodedInputStream -- Issue 25: Added support for NuGet packages -- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 - -Fixes: -- Issue 13: Message with Field same name as message causes uncompilable .cs -- Issue 16: Does not integrate well with other tooling -- Issue 19: Support for negative enum values -- Issue 26: AddRange in GeneratedBuilder iterates twice. -- Issue 27: Remove XML documentation output from test projects to clear - warnings/errors. -- Issue 28: Circular message dependencies result in null default values for - Message fields. -- Issue 29: Message classes generated have a public default constructor. You - can disable private ctor generation with the option generate_private_ctor. -- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ -- Big-endian support for float, and double on Silverlight -- Packed and Unpacked parsing allow for all repeated, as per version 2.3 -- Fix for leaving Builder a public ctor on internal classes for use with - generic "where T: new()" constraints. - -Other: -- Changed the code signing key to a privately held key -- Reformatted all code and line-endings to C# defaults -- Reworking of performance benchmarks to produce reliable results, option /v2 -- Issue 34: Silverlight assemblies are now unit tested - -=============================================================================== -RELEASE NOTES - Version 2.3.0.277 -=============================================================================== - -Features: -- Added cls_compliance option to generate attributes indicating - non-CLS-compliance. -- Added file_extension option to control the generated output file's extension. -- Added umbrella_namespace option to place the umbrella class into a nested - namespace to address issues with proto files having the same name as a - message it contains. -- Added output_directory option to set the output path for the source file(s). -- Added ignore_google_protobuf option to avoid generating code for includes - from the google.protobuf package. -- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to - generate code with "option optimize_for = LITE_RUNTIME;". -- Added ability to invoke protoc.exe from within ProtoGen.exe. -- Upgraded to protoc.exe (2.3) compiler. - -Fixes: -- Issue 9: Class cannot be static and sealed error -- Issue 12: default value for enumerate fields must be filled out - -Other: -- Rewrite of build using MSBbuild instead of NAnt -- Moved to NUnit Version 2.2.8.0 -- Changed to using secure .snk for releases - -=============================================================================== -RELEASE NOTES - Version 0.9.1 -=============================================================================== - -Fixes: -- issue 10: Incorrect encoding of packed fields when serialized - -=============================================================================== -RELEASE NOTES - Version 0.9.0 -=============================================================================== - -- Initial release - -=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Cluster/licenses/license.txt b/src/core/Akka.Cluster/licenses/license.txt deleted file mode 100644 index b8e773b2e05..00000000000 --- a/src/core/Akka.Cluster/licenses/license.txt +++ /dev/null @@ -1,31 +0,0 @@ -Protocol Buffers - Google's data interchange format -Copyright 2008-2010 Google Inc. All rights reserved. -http://github.com/jskeet/dotnet-protobufs/ -Original C++/Java/Python code: -http://code.google.com/p/protobuf/ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Cluster/licenses/protoc-license.txt b/src/core/Akka.Cluster/licenses/protoc-license.txt deleted file mode 100644 index c779cb0e1ed..00000000000 --- a/src/core/Akka.Cluster/licenses/protoc-license.txt +++ /dev/null @@ -1,36 +0,0 @@ -protoc.exe was built from the original source at http://code.google.com/p/protobuf/ -The licence for this code is as follows: - -Copyright 2008, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Code generated by the Protocol Buffer compiler is owned by the owner -of the input file used when generating it. This code is not -standalone and requires a support library to be linked with it. This -support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Cluster/packages.config b/src/core/Akka.Cluster/packages.config new file mode 100644 index 00000000000..9a9d74d4213 --- /dev/null +++ b/src/core/Akka.Cluster/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/core/Akka.Cluster/paket.references b/src/core/Akka.Cluster/paket.references deleted file mode 100644 index b4721cd0526..00000000000 --- a/src/core/Akka.Cluster/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -Google.ProtocolBuffers -System.Collections.Immutable \ No newline at end of file diff --git a/src/core/Akka.Cluster/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Cluster/protos/google/protobuf/csharp_options.proto deleted file mode 100644 index 152df766f03..00000000000 --- a/src/core/Akka.Cluster/protos/google/protobuf/csharp_options.proto +++ /dev/null @@ -1,115 +0,0 @@ -// Extra options for C# generator - -import "google/protobuf/descriptor.proto"; - -package google.protobuf; - -message CSharpFileOptions { - - // Namespace for generated classes; defaults to the package. - optional string namespace = 1; - - // Name of the "umbrella" class used for metadata about all - // the messages within this file. Default is based on the name - // of the file. - optional string umbrella_classname = 2; - - // Whether classes should be public (true) or internal (false) - optional bool public_classes = 3 [default = true]; - - // Whether to generate a single file for everything within the - // .proto file (false), or one file per message (true). - // This option is not currently honored; please log a feature - // request if you really want it. - optional bool multiple_files = 4; - - // Whether to nest messages within a single umbrella class (true) - // or create the umbrella class as a peer, with messages as - // top-level classes in the namespace (false) - optional bool nest_classes = 5; - - // Generate appropriate support for Code Contracts - // (Ongoing; support should improve over time) - optional bool code_contracts = 6; - - // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" - // would generate files within [output directory]/Foo/Bar - optional bool expand_namespace_directories = 7; - - // Generate attributes indicating non-CLS-compliance - optional bool cls_compliance = 8 [default = true]; - - // Generate messages/builders with the [Serializable] attribute - optional bool add_serializable = 9 [default = false]; - - // Generates a private ctor for Message types - optional bool generate_private_ctor = 10 [default = true]; - - // The extension that should be appended to the umbrella_classname when creating files. - optional string file_extension = 221 [default = ".cs"]; - - // A nested namespace for the umbrella class. Helpful for name collisions caused by - // umbrella_classname conflicting with an existing type. This will be automatically - // set to 'Proto' if a collision is detected with types being generated. This value - // is ignored when nest_classes == true - optional string umbrella_namespace = 222; - - // The output path for the source file(s) generated - optional string output_directory = 223 [default = "."]; - - // Will ignore the type generations and remove dependencies for the descriptor proto - // files that declare their package to be "google.protobuf" - optional bool ignore_google_protobuf = 224 [default = false]; - - // Controls how services are generated, GENERIC is the deprecated original implementation - // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and - // implementations using the included Windows RPC interop libarary. - optional CSharpServiceType service_generator_type = 225 [default = NONE]; - - // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and - // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. - optional bool generated_code_attributes = 226 [default = false]; -} - -enum CSharpServiceType { - // Services are ignored by the generator - NONE = 0; - // Generates the original Java generic service implementations - GENERIC = 1; - // Generates an interface for the service and nothing else - INTERFACE = 2; - // Generates an interface for the service and client/server wrappers for the interface - IRPCDISPATCH = 3; -} - -extend FileOptions { - optional CSharpFileOptions csharp_file_options = 1000; -} - -extend FieldOptions { - optional CSharpFieldOptions csharp_field_options = 1000; -} - -message CSharpFieldOptions { - // Provides the ability to override the name of the property - // generated for this field. This is applied to all properties - // and methods to do with this field, including HasFoo, FooCount, - // FooList etc. - optional string property_name = 1; -} - -message CSharpServiceOptions { - optional string interface_id = 1; -} - -extend ServiceOptions { - optional CSharpServiceOptions csharp_service_options = 1000; -} - -message CSharpMethodOptions { - optional int32 dispatch_id = 1; -} - -extend MethodOptions { - optional CSharpMethodOptions csharp_method_options = 1000; -} \ No newline at end of file diff --git a/src/core/Akka.Cluster/protos/google/protobuf/descriptor.proto b/src/core/Akka.Cluster/protos/google/protobuf/descriptor.proto deleted file mode 100644 index 233f879410e..00000000000 --- a/src/core/Akka.Cluster/protos/google/protobuf/descriptor.proto +++ /dev/null @@ -1,533 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. -// -// The messages in this file describe the definitions found in .proto files. -// A valid .proto file can be translated directly to a FileDescriptorProto -// without any other information (e.g. without reading its imports). - - - -package google.protobuf; -option java_package = "com.google.protobuf"; -option java_outer_classname = "DescriptorProtos"; - -// descriptor.proto must be optimized for speed because reflection-based -// algorithms don't work during bootstrapping. -option optimize_for = SPEED; - -// The protocol compiler can output a FileDescriptorSet containing the .proto -// files it parses. -message FileDescriptorSet { - repeated FileDescriptorProto file = 1; -} - -// Describes a complete .proto file. -message FileDescriptorProto { - optional string name = 1; // file name, relative to root of source tree - optional string package = 2; // e.g. "foo", "foo.bar", etc. - - // Names of files imported by this file. - repeated string dependency = 3; - - // All top-level definitions in this file. - repeated DescriptorProto message_type = 4; - repeated EnumDescriptorProto enum_type = 5; - repeated ServiceDescriptorProto service = 6; - repeated FieldDescriptorProto extension = 7; - - optional FileOptions options = 8; - - // This field contains optional information about the original source code. - // You may safely remove this entire field whithout harming runtime - // functionality of the descriptors -- the information is needed only by - // development tools. - optional SourceCodeInfo source_code_info = 9; -} - -// Describes a message type. -message DescriptorProto { - optional string name = 1; - - repeated FieldDescriptorProto field = 2; - repeated FieldDescriptorProto extension = 6; - - repeated DescriptorProto nested_type = 3; - repeated EnumDescriptorProto enum_type = 4; - - message ExtensionRange { - optional int32 start = 1; - optional int32 end = 2; - } - repeated ExtensionRange extension_range = 5; - - optional MessageOptions options = 7; -} - -// Describes a field within a message. -message FieldDescriptorProto { - enum Type { - // 0 is reserved for errors. - // Order is weird for historical reasons. - TYPE_DOUBLE = 1; - TYPE_FLOAT = 2; - TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT64 if negative - // values are likely. - TYPE_UINT64 = 4; - TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT32 if negative - // values are likely. - TYPE_FIXED64 = 6; - TYPE_FIXED32 = 7; - TYPE_BOOL = 8; - TYPE_STRING = 9; - TYPE_GROUP = 10; // Tag-delimited aggregate. - TYPE_MESSAGE = 11; // Length-delimited aggregate. - - // New in version 2. - TYPE_BYTES = 12; - TYPE_UINT32 = 13; - TYPE_ENUM = 14; - TYPE_SFIXED32 = 15; - TYPE_SFIXED64 = 16; - TYPE_SINT32 = 17; // Uses ZigZag encoding. - TYPE_SINT64 = 18; // Uses ZigZag encoding. - }; - - enum Label { - // 0 is reserved for errors - LABEL_OPTIONAL = 1; - LABEL_REQUIRED = 2; - LABEL_REPEATED = 3; - // TODO(sanjay): Should we add LABEL_MAP? - }; - - optional string name = 1; - optional int32 number = 3; - optional Label label = 4; - - // If type_name is set, this need not be set. If both this and type_name - // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. - optional Type type = 5; - - // For message and enum types, this is the name of the type. If the name - // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping - // rules are used to find the type (i.e. first the nested types within this - // message are searched, then within the parent, on up to the root - // namespace). - optional string type_name = 6; - - // For extensions, this is the name of the type being extended. It is - // resolved in the same manner as type_name. - optional string extendee = 2; - - // For numeric types, contains the original text representation of the value. - // For booleans, "true" or "false". - // For strings, contains the default text contents (not escaped in any way). - // For bytes, contains the C escaped value. All bytes >= 128 are escaped. - // TODO(kenton): Base-64 encode? - optional string default_value = 7; - - optional FieldOptions options = 8; -} - -// Describes an enum type. -message EnumDescriptorProto { - optional string name = 1; - - repeated EnumValueDescriptorProto value = 2; - - optional EnumOptions options = 3; -} - -// Describes a value within an enum. -message EnumValueDescriptorProto { - optional string name = 1; - optional int32 number = 2; - - optional EnumValueOptions options = 3; -} - -// Describes a service. -message ServiceDescriptorProto { - optional string name = 1; - repeated MethodDescriptorProto method = 2; - - optional ServiceOptions options = 3; -} - -// Describes a method of a service. -message MethodDescriptorProto { - optional string name = 1; - - // Input and output type names. These are resolved in the same way as - // FieldDescriptorProto.type_name, but must refer to a message type. - optional string input_type = 2; - optional string output_type = 3; - - optional MethodOptions options = 4; -} - -// =================================================================== -// Options - -// Each of the definitions above may have "options" attached. These are -// just annotations which may cause code to be generated slightly differently -// or may contain hints for code that manipulates protocol messages. -// -// Clients may define custom options as extensions of the *Options messages. -// These extensions may not yet be known at parsing time, so the parser cannot -// store the values in them. Instead it stores them in a field in the *Options -// message called uninterpreted_option. This field must have the same name -// across all *Options messages. We then use this field to populate the -// extensions when we build a descriptor, at which point all protos have been -// parsed and so all extensions are known. -// -// Extension numbers for custom options may be chosen as follows: -// * For options which will only be used within a single application or -// organization, or for experimental options, use field numbers 50000 -// through 99999. It is up to you to ensure that you do not use the -// same number for multiple options. -// * For options which will be published and used publicly by multiple -// independent entities, e-mail kenton@google.com to reserve extension -// numbers. Simply tell me how many you need and I'll send you back a -// set of numbers to use -- there's no need to explain how you intend to -// use them. If this turns out to be popular, a web service will be set up -// to automatically assign option numbers. - - -message FileOptions { - - // Sets the Java package where classes generated from this .proto will be - // placed. By default, the proto package is used, but this is often - // inappropriate because proto packages do not normally start with backwards - // domain names. - optional string java_package = 1; - - - // If set, all the classes from the .proto file are wrapped in a single - // outer class with the given name. This applies to both Proto1 - // (equivalent to the old "--one_java_file" option) and Proto2 (where - // a .proto always translates to a single class, but you may want to - // explicitly choose the class name). - optional string java_outer_classname = 8; - - // If set true, then the Java code generator will generate a separate .java - // file for each top-level message, enum, and service defined in the .proto - // file. Thus, these types will *not* be nested inside the outer class - // named by java_outer_classname. However, the outer class will still be - // generated to contain the file's getDescriptor() method as well as any - // top-level extensions defined in the file. - optional bool java_multiple_files = 10 [default=false]; - - // If set true, then the Java code generator will generate equals() and - // hashCode() methods for all messages defined in the .proto file. This is - // purely a speed optimization, as the AbstractMessage base class includes - // reflection-based implementations of these methods. - optional bool java_generate_equals_and_hash = 20 [default=false]; - - // Generated classes can be optimized for speed or code size. - enum OptimizeMode { - SPEED = 1; // Generate complete code for parsing, serialization, - // etc. - CODE_SIZE = 2; // Use ReflectionOps to implement these methods. - LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. - } - optional OptimizeMode optimize_for = 9 [default=SPEED]; - - - - - // Should generic services be generated in each language? "Generic" services - // are not specific to any particular RPC system. They are generated by the - // main code generators in each language (without additional plugins). - // Generic services were the only kind of service generation supported by - // early versions of proto2. - // - // Generic services are now considered deprecated in favor of using plugins - // that generate code specific to your particular RPC system. Therefore, - // these default to false. Old code which depends on generic services should - // explicitly set them to true. - optional bool cc_generic_services = 16 [default=false]; - optional bool java_generic_services = 17 [default=false]; - optional bool py_generic_services = 18 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MessageOptions { - // Set true to use the old proto1 MessageSet wire format for extensions. - // This is provided for backwards-compatibility with the MessageSet wire - // format. You should not use this for any other reason: It's less - // efficient, has fewer features, and is more complicated. - // - // The message must be defined exactly as follows: - // message Foo { - // option message_set_wire_format = true; - // extensions 4 to max; - // } - // Note that the message cannot have any defined fields; MessageSets only - // have extensions. - // - // All extensions of your type must be singular messages; e.g. they cannot - // be int32s, enums, or repeated messages. - // - // Because this is an option, the above two restrictions are not enforced by - // the protocol compiler. - optional bool message_set_wire_format = 1 [default=false]; - - // Disables the generation of the standard "descriptor()" accessor, which can - // conflict with a field of the same name. This is meant to make migration - // from proto1 easier; new code should avoid fields named "descriptor". - optional bool no_standard_descriptor_accessor = 2 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message FieldOptions { - // The ctype option instructs the C++ code generator to use a different - // representation of the field than it normally would. See the specific - // options below. This option is not yet implemented in the open source - // release -- sorry, we'll try to include it in a future version! - optional CType ctype = 1 [default = STRING]; - enum CType { - // Default mode. - STRING = 0; - - CORD = 1; - - STRING_PIECE = 2; - } - // The packed option can be enabled for repeated primitive fields to enable - // a more efficient representation on the wire. Rather than repeatedly - // writing the tag and type for each element, the entire array is encoded as - // a single length-delimited blob. - optional bool packed = 2; - - - // Is this field deprecated? - // Depending on the target platform, this can emit Deprecated annotations - // for accessors, or it will be completely ignored; in the very least, this - // is a formalization for deprecating fields. - optional bool deprecated = 3 [default=false]; - - // EXPERIMENTAL. DO NOT USE. - // For "map" fields, the name of the field in the enclosed type that - // is the key for this map. For example, suppose we have: - // message Item { - // required string name = 1; - // required string value = 2; - // } - // message Config { - // repeated Item items = 1 [experimental_map_key="name"]; - // } - // In this situation, the map key for Item will be set to "name". - // TODO: Fully-implement this, then remove the "experimental_" prefix. - optional string experimental_map_key = 9; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumOptions { - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumValueOptions { - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message ServiceOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MethodOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -// A message representing a option the parser does not recognize. This only -// appears in options protos created by the compiler::Parser class. -// DescriptorPool resolves these when building Descriptor objects. Therefore, -// options protos in descriptor objects (e.g. returned by Descriptor::options(), -// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions -// in them. -message UninterpretedOption { - // The name of the uninterpreted option. Each string represents a segment in - // a dot-separated name. is_extension is true iff a segment represents an - // extension (denoted with parentheses in options specs in .proto files). - // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents - // "foo.(bar.baz).qux". - message NamePart { - required string name_part = 1; - required bool is_extension = 2; - } - repeated NamePart name = 2; - - // The value of the uninterpreted option, in whatever type the tokenizer - // identified it as during parsing. Exactly one of these should be set. - optional string identifier_value = 3; - optional uint64 positive_int_value = 4; - optional int64 negative_int_value = 5; - optional double double_value = 6; - optional bytes string_value = 7; - optional string aggregate_value = 8; -} - -// =================================================================== -// Optional source code info - -// Encapsulates information about the original source file from which a -// FileDescriptorProto was generated. -message SourceCodeInfo { - // A Location identifies a piece of source code in a .proto file which - // corresponds to a particular definition. This information is intended - // to be useful to IDEs, code indexers, documentation generators, and similar - // tools. - // - // For example, say we have a file like: - // message Foo { - // optional string foo = 1; - // } - // Let's look at just the field definition: - // optional string foo = 1; - // ^ ^^ ^^ ^ ^^^ - // a bc de f ghi - // We have the following locations: - // span path represents - // [a,i) [ 4, 0, 2, 0 ] The whole field definition. - // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). - // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). - // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). - // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). - // - // Notes: - // - A location may refer to a repeated field itself (i.e. not to any - // particular index within it). This is used whenever a set of elements are - // logically enclosed in a single code segment. For example, an entire - // extend block (possibly containing multiple extension definitions) will - // have an outer location whose path refers to the "extensions" repeated - // field without an index. - // - Multiple locations may have the same path. This happens when a single - // logical declaration is spread out across multiple places. The most - // obvious example is the "extend" block again -- there may be multiple - // extend blocks in the same scope, each of which will have the same path. - // - A location's span is not always a subset of its parent's span. For - // example, the "extendee" of an extension declaration appears at the - // beginning of the "extend" block and is shared by all extensions within - // the block. - // - Just because a location's span is a subset of some other location's span - // does not mean that it is a descendent. For example, a "group" defines - // both a type and a field in a single declaration. Thus, the locations - // corresponding to the type and field and their components will overlap. - // - Code which tries to interpret locations should probably be designed to - // ignore those that it doesn't understand, as more types of locations could - // be recorded in the future. - repeated Location location = 1; - message Location { - // Identifies which part of the FileDescriptorProto was defined at this - // location. - // - // Each element is a field number or an index. They form a path from - // the root FileDescriptorProto to the place where the definition. For - // example, this path: - // [ 4, 3, 2, 7, 1 ] - // refers to: - // file.message_type(3) // 4, 3 - // .field(7) // 2, 7 - // .name() // 1 - // This is because FileDescriptorProto.message_type has field number 4: - // repeated DescriptorProto message_type = 4; - // and DescriptorProto.field has field number 2: - // repeated FieldDescriptorProto field = 2; - // and FieldDescriptorProto.name has field number 1: - // optional string name = 1; - // - // Thus, the above path gives the location of a field name. If we removed - // the last element: - // [ 4, 3, 2, 7 ] - // this path refers to the whole field declaration (from the beginning - // of the label to the terminating semicolon). - repeated int32 path = 1 [packed=true]; - - // Always has exactly three or four elements: start line, start column, - // end line (optional, otherwise assumed same as start line), end column. - // These are packed into a single field for efficiency. Note that line - // and column numbers are zero-based -- typically you will want to add - // 1 to each before displaying to a user. - repeated int32 span = 2 [packed=true]; - - // TODO(kenton): Record comments appearing before and after the - // declaration. - } -} diff --git a/src/core/Akka.Cluster/protos/tutorial/addressbook.proto b/src/core/Akka.Cluster/protos/tutorial/addressbook.proto deleted file mode 100644 index 5abe35ce39b..00000000000 --- a/src/core/Akka.Cluster/protos/tutorial/addressbook.proto +++ /dev/null @@ -1,31 +0,0 @@ -package tutorial; - -import "google/protobuf/csharp_options.proto"; -option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; -option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; - -option optimize_for = SPEED; - -message Person { - required string name = 1; - required int32 id = 2; // Unique ID number for this person. - optional string email = 3; - - enum PhoneType { - MOBILE = 0; - HOME = 1; - WORK = 2; - } - - message PhoneNumber { - required string number = 1; - optional PhoneType type = 2 [default = HOME]; - } - - repeated PhoneNumber phone = 4; -} - -// Our address book file is just one of these. -message AddressBook { - repeated Person person = 1; -} diff --git a/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj b/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj index 8cd3f694aff..d219f39613c 100644 --- a/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj +++ b/src/core/Akka.FSharp.Tests/Akka.FSharp.Tests.fsproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ 4.3.1.0 Akka.FSharp.Tests ..\..\ - 802fc494 + true + + true @@ -39,6 +42,7 @@ + 11 @@ -56,16 +60,31 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - + + + ..\..\packages\FsCheck.0.9.4.0\lib\net40-Client\FsCheck.dll + True + + + ..\..\packages\FsCheck.Xunit.0.4.1.0\lib\net40-Client\FsCheck.Xunit.dll + True + @@ -91,6 +110,21 @@ Akka {5DEDDF90-37F0-48D3-A0B0-A5CBD8A7E377} + + True + + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + - - - - - - ..\..\..\packages\test\FsCheck\lib\net45\FsCheck.dll - True - True - - - - - - - ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45\FsCheck.dll - True - True - - - - - - - ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45+wp8\FsCheck.dll - True - True - - - - - - - ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45+wpa81+wp8\FsCheck.dll - True - True - - - - - - - - - ..\..\..\packages\test\FsCheck.Xunit\lib\net45\FsCheck.Xunit.dll - True - True - - - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\net20\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\net40\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\portable-net45+monoandroid10+monotouch10+xamarinios10\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\portable-net45+sl5+netcore45\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45+wp8\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45+wpa81+wp8\FSharp.Core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.FSharp.Tests/app.config b/src/core/Akka.FSharp.Tests/app.config index 9efc87884ed..d3bd7964d53 100644 --- a/src/core/Akka.FSharp.Tests/app.config +++ b/src/core/Akka.FSharp.Tests/app.config @@ -15,151 +15,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.FSharp.Tests/packages.config b/src/core/Akka.FSharp.Tests/packages.config new file mode 100644 index 00000000000..5a0f41a0faf --- /dev/null +++ b/src/core/Akka.FSharp.Tests/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.FSharp.Tests/paket.references b/src/core/Akka.FSharp.Tests/paket.references deleted file mode 100644 index fa04e6f8f0d..00000000000 --- a/src/core/Akka.FSharp.Tests/paket.references +++ /dev/null @@ -1,4 +0,0 @@ -group Test -FsCheck.Xunit -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.FSharp/Akka.FSharp.fsproj b/src/core/Akka.FSharp/Akka.FSharp.fsproj index be6288d9c5a..5c9f8051acf 100644 --- a/src/core/Akka.FSharp/Akka.FSharp.fsproj +++ b/src/core/Akka.FSharp/Akka.FSharp.fsproj @@ -12,6 +12,7 @@ 4.3.1.0 Akka.FSharp ..\..\ + true true @@ -67,16 +68,33 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - + + + ..\..\packages\FSPowerPack.Core.Community.3.0.0.0\Lib\Net40\FSharp.PowerPack.dll + + + ..\..\packages\FSPowerPack.Linq.Community.3.0.0.0\Lib\Net40\FSharp.PowerPack.Linq.dll + + + ..\..\packages\FsPickler.1.2.21\lib\net45\FsPickler.dll + True + @@ -98,135 +116,4 @@ --> - - - - - - ..\..\..\packages\FsPickler\lib\net35\FsPickler.dll - True - True - - - - - - - ..\..\..\packages\FsPickler\lib\net40\FsPickler.dll - True - True - - - - - - - ..\..\..\packages\FsPickler\lib\net45\FsPickler.dll - True - True - - - - - - - - - ..\..\..\packages\FSPowerPack.Core.Community\Lib\Net20\FSharp.PowerPack.dll - True - True - - - - - - - ..\..\..\packages\FSPowerPack.Core.Community\Lib\Net40\FSharp.PowerPack.dll - True - True - - - - - - - ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl3\FSharp.PowerPack.Compatibility.dll - True - True - - - ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl3\FSharp.PowerPack.dll - True - True - - - - - - - ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl4\FSharp.PowerPack.Compatibility.dll - True - True - - - ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl4\FSharp.PowerPack.dll - True - True - - - - - - - ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl5\FSharp.PowerPack.Compatibility.dll - True - True - - - ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl5\FSharp.PowerPack.Linq.dll - True - True - - - ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl5\FSharp.PowerPack.dll - True - True - - - - - - - ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl4-windowsphone71\FSharp.PowerPack.Compatibility.dll - True - True - - - ..\..\..\packages\FSPowerPack.Core.Community\Lib\sl4-windowsphone71\FSharp.PowerPack.dll - True - True - - - - - - - - - ..\..\..\packages\FSPowerPack.Linq.Community\Lib\Net20\FSharp.PowerPack.Linq.dll - True - True - - - - - - - ..\..\..\packages\FSPowerPack.Linq.Community\Lib\Net40\FSharp.PowerPack.Linq.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.FSharp/FsApi.fs b/src/core/Akka.FSharp/FsApi.fs index 56eb68f26bd..7044cc60d22 100644 --- a/src/core/Akka.FSharp/FsApi.fs +++ b/src/core/Akka.FSharp/FsApi.fs @@ -44,7 +44,7 @@ module Serialization = // used for top level serialization type ExprSerializer(system) = inherit Serializer(system) - let fsp = FsPickler.CreateBinarySerializer() + let fsp = FsPickler.CreateBinary() override __.Identifier = 9 override __.IncludeManifest = true override __.ToBinary(o) = serializeToBinary fsp o @@ -420,7 +420,7 @@ type ExprDeciderSurrogate(serializedExpr: byte array) = member __.SerializedExpr = serializedExpr interface ISurrogate with member this.FromSurrogate _ = - let fsp = Nessos.FsPickler.FsPickler.CreateBinarySerializer() + let fsp = Nessos.FsPickler.FsPickler.CreateBinary() let expr = (Serialization.deserializeFromBinaryDirective)>> fsp (this.SerializedExpr)) ExprDecider(expr) :> ISurrogated @@ -431,7 +431,7 @@ and ExprDecider (expr: Expr<(exn->Directive)>) = member this.Decide (e: exn): Directive = this.Compiled.Value (e) interface ISurrogated with member this.ToSurrogate _ = - let fsp = Nessos.FsPickler.FsPickler.CreateBinarySerializer() + let fsp = Nessos.FsPickler.FsPickler.CreateBinary() ExprDeciderSurrogate(Serialization.serializeToBinary fsp this.Expr) :> ISurrogate type Strategy = diff --git a/src/core/Akka.FSharp/app.config b/src/core/Akka.FSharp/app.config index 27ad5b4a789..bb9b825d392 100644 --- a/src/core/Akka.FSharp/app.config +++ b/src/core/Akka.FSharp/app.config @@ -1,159 +1,11 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.FSharp/packages.config b/src/core/Akka.FSharp/packages.config new file mode 100644 index 00000000000..7b95c7adab6 --- /dev/null +++ b/src/core/Akka.FSharp/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/core/Akka.FSharp/paket.references b/src/core/Akka.FSharp/paket.references deleted file mode 100644 index a70343f1d50..00000000000 --- a/src/core/Akka.FSharp/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -FsPickler -FSPowerPack.Linq.Community \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj index 4d5e46cfdc6..bfb895e3fce 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj +++ b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/Akka.MultiNodeTestRunner.Shared.Tests.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ v4.5 512 ..\..\ - 46f5f680 + true + + true @@ -32,9 +35,25 @@ 4 + + ..\..\packages\faker-csharp.1.2.0\lib\net4\Faker.dll + True + + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -73,12 +92,22 @@ - + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\packages\faker-csharp\lib\net35\Faker.Net35.dll - True - True - - - - - - - ..\..\..\packages\faker-csharp\lib\net4\Faker.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/app.config b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/app.config new file mode 100644 index 00000000000..f0bd3189cf4 --- /dev/null +++ b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/packages.config b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/packages.config new file mode 100644 index 00000000000..b7134ca0954 --- /dev/null +++ b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/paket.references b/src/core/Akka.MultiNodeTestRunner.Shared.Tests/paket.references deleted file mode 100644 index 329cdebecfc..00000000000 --- a/src/core/Akka.MultiNodeTestRunner.Shared.Tests/paket.references +++ /dev/null @@ -1,4 +0,0 @@ -faker-csharp -group Test -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj b/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj index 11e5d887e7d..dc72f3b9170 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj +++ b/src/core/Akka.MultiNodeTestRunner.Shared/Akka.MultiNodeTestRunner.Shared.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\ + true true @@ -32,6 +33,10 @@ 4 + + False + ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + @@ -75,7 +80,7 @@ - + @@ -87,6 +92,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/packages.config b/src/core/Akka.MultiNodeTestRunner.Shared/packages.config new file mode 100644 index 00000000000..505e58836ba --- /dev/null +++ b/src/core/Akka.MultiNodeTestRunner.Shared/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/paket.references b/src/core/Akka.MultiNodeTestRunner.Shared/paket.references deleted file mode 100644 index 1063d003b92..00000000000 --- a/src/core/Akka.MultiNodeTestRunner.Shared/paket.references +++ /dev/null @@ -1 +0,0 @@ -Newtonsoft.Json \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj index f4683c43e8f..dd8a6c268d4 100644 --- a/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj +++ b/src/core/Akka.MultiNodeTestRunner/Akka.MultiNodeTestRunner.csproj @@ -38,6 +38,17 @@ + + False + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + + + False + ..\..\packages\xunit.runner.utility.2.1.0-beta2-build2981\lib\net35\xunit.runner.utility.desktop.dll + @@ -49,7 +60,7 @@ - + @@ -73,8 +84,16 @@ Akka + - + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - ..\..\..\packages\test\xunit\lib\net20\xunit.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensions\lib\net20\xunit.extensions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.runner.utility\lib\net35\xunit.runner.utility.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.runner.utility\lib\portable-net45+win8+wp8+wpa81\xunit.runner.utility.dotnet.dll - True - True - - - - - - - - <__paket__xunit_runner_visualstudio_props>win81\xunit.runner.visualstudio - <__paket__xunit_runner_visualstudio_targets>win81\xunit.runner.visualstudio - - - - - <__paket__xunit_runner_visualstudio_props>net20\xunit.runner.visualstudio - - - - - <__paket__xunit_runner_visualstudio_props>wpa81\xunit.runner.visualstudio - <__paket__xunit_runner_visualstudio_targets>wpa81\xunit.runner.visualstudio - - - - - <__paket__xunit_runner_visualstudio_props>portable-net45+win8+wp8+wpa81\xunit.runner.visualstudio - - - - - \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/App.config b/src/core/Akka.MultiNodeTestRunner/App.config index 5126174a197..8e15646352e 100644 --- a/src/core/Akka.MultiNodeTestRunner/App.config +++ b/src/core/Akka.MultiNodeTestRunner/App.config @@ -1,147 +1,6 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/Program.cs b/src/core/Akka.MultiNodeTestRunner/Program.cs index 5ae1a09a5f1..d624817c443 100644 --- a/src/core/Akka.MultiNodeTestRunner/Program.cs +++ b/src/core/Akka.MultiNodeTestRunner/Program.cs @@ -75,7 +75,7 @@ static void Main(string[] args) EnableAllSinks(assemblyName); PublishRunnerMessage(String.Format("Running MultiNodeTests for {0}", assemblyName)); - using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, assemblyName)) + using (var controller = new XunitFrontController(assemblyName)) { using (var discovery = new Discovery()) { diff --git a/src/core/Akka.MultiNodeTestRunner/packages.config b/src/core/Akka.MultiNodeTestRunner/packages.config new file mode 100644 index 00000000000..ea90325cbbf --- /dev/null +++ b/src/core/Akka.MultiNodeTestRunner/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTestRunner/paket.references b/src/core/Akka.MultiNodeTestRunner/paket.references deleted file mode 100644 index 89febfd4dc5..00000000000 --- a/src/core/Akka.MultiNodeTestRunner/paket.references +++ /dev/null @@ -1,7 +0,0 @@ -group Test -xunit.core -xunit.assert -xunit.extensions -xunit.runner.console -xunit.runner.utility -xunit.runner.visualstudio \ No newline at end of file diff --git a/src/core/Akka.MultiNodeTests/paket.references b/src/core/Akka.MultiNodeTests/paket.references deleted file mode 100644 index 26d1c8e78f3..00000000000 --- a/src/core/Akka.MultiNodeTests/paket.references +++ /dev/null @@ -1,3 +0,0 @@ -Microsoft.Bcl.Immutable -group Test -xunit \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj index cf995b9aaf1..e3721881d32 100644 --- a/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj +++ b/src/core/Akka.NodeTestRunner/Akka.NodeTestRunner.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\ + true publish\ true Disk @@ -50,6 +51,14 @@ + + False + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + + + False + ..\..\packages\xunit.runner.utility.2.1.0-beta2-build2981\lib\net35\xunit.runner.utility.desktop.dll + @@ -59,7 +68,7 @@ - + @@ -89,6 +98,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.runner.utility\lib\net35\xunit.runner.utility.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.runner.utility\lib\portable-net45+win8+wp8+wpa81\xunit.runner.utility.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/App.config b/src/core/Akka.NodeTestRunner/App.config index 060f4e63806..0b6fda4dfdf 100644 --- a/src/core/Akka.NodeTestRunner/App.config +++ b/src/core/Akka.NodeTestRunner/App.config @@ -12,157 +12,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/Program.cs b/src/core/Akka.NodeTestRunner/Program.cs index 77c13d8c773..88767b12295 100644 --- a/src/core/Akka.NodeTestRunner/Program.cs +++ b/src/core/Akka.NodeTestRunner/Program.cs @@ -25,7 +25,7 @@ static void Main(string[] args) Thread.Sleep(TimeSpan.FromSeconds(10)); - using (var controller = new XunitFrontController(AppDomainSupport.IfAvailable, assemblyFileName)) + using (var controller = new XunitFrontController(assemblyFileName)) { /* need to pass in just the assembly name to Discovery, not the full path * i.e. "Akka.Cluster.Tests.MultiNode.dll" diff --git a/src/core/Akka.NodeTestRunner/packages.config b/src/core/Akka.NodeTestRunner/packages.config new file mode 100644 index 00000000000..b4605234264 --- /dev/null +++ b/src/core/Akka.NodeTestRunner/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/core/Akka.NodeTestRunner/paket.references b/src/core/Akka.NodeTestRunner/paket.references deleted file mode 100644 index d15f7ae54a1..00000000000 --- a/src/core/Akka.NodeTestRunner/paket.references +++ /dev/null @@ -1,3 +0,0 @@ -group Test -xunit.abstractions -xunit.runner.utility \ No newline at end of file diff --git a/src/core/Akka.Persistence.FSharp/app.config b/src/core/Akka.Persistence.FSharp/app.config index 27ad5b4a789..bb9b825d392 100644 --- a/src/core/Akka.Persistence.FSharp/app.config +++ b/src/core/Akka.Persistence.FSharp/app.config @@ -1,159 +1,11 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj b/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj index 13b75f4f925..9d280f22f3a 100644 --- a/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj +++ b/src/core/Akka.Persistence.TestKit.Tests/Akka.Persistence.TestKit.Tests.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ v4.5 512 ..\..\ - b3f6fdc7 + true + + true @@ -38,6 +41,18 @@ + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -68,12 +83,20 @@ - + - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit.Tests/packages.config b/src/core/Akka.Persistence.TestKit.Tests/packages.config new file mode 100644 index 00000000000..3109db107fb --- /dev/null +++ b/src/core/Akka.Persistence.TestKit.Tests/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit.Tests/paket.references b/src/core/Akka.Persistence.TestKit.Tests/paket.references deleted file mode 100644 index f1e55442a7e..00000000000 --- a/src/core/Akka.Persistence.TestKit.Tests/paket.references +++ /dev/null @@ -1,3 +0,0 @@ -group Test -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj b/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj index dd9685f772d..7ef04888116 100644 --- a/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj +++ b/src/core/Akka.Persistence.TestKit/Akka.Persistence.TestKit.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ v4.5 512 ..\..\ - f8afe7eb + true + + true @@ -39,6 +42,18 @@ + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -69,9 +84,17 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit/packages.config b/src/core/Akka.Persistence.TestKit/packages.config new file mode 100644 index 00000000000..3109db107fb --- /dev/null +++ b/src/core/Akka.Persistence.TestKit/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence.TestKit/paket.references b/src/core/Akka.Persistence.TestKit/paket.references deleted file mode 100644 index f1e55442a7e..00000000000 --- a/src/core/Akka.Persistence.TestKit/paket.references +++ /dev/null @@ -1,3 +0,0 @@ -group Test -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj index 5ad55a04a87..1e9f1591a8a 100644 --- a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj +++ b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ v4.5 512 ..\ - fb9ab2f3 + true + + true @@ -32,30 +35,43 @@ 4 - - True - - - True - True True - - True - - - True - + + False + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll + True + + + False + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + + + False + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + False + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + False + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -103,12 +119,23 @@ - - + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - diff --git a/src/core/Akka.Persistence.Tests/CHANGES.txt b/src/core/Akka.Persistence.Tests/CHANGES.txt deleted file mode 100644 index d80368c78f2..00000000000 --- a/src/core/Akka.Persistence.Tests/CHANGES.txt +++ /dev/null @@ -1,99 +0,0 @@ -=============================================================================== -Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet -(skeet@pobox.com) based on the work of many talented people. - -For more information about this port, visit its homepage: -http://protobuf-csharp-port.googlecode.com - -For more information about Protocol Buffers in general, visit the project page -for the C++, Java and Python project: -http://protobuf.googlecode.com -=============================================================================== -RELEASE NOTES - Version 2.4.1.473 -=============================================================================== - -Features: -- Added option service_generator_type to control service generation with - NONE, GENERIC, INTERFACE, or IRPCDISPATCH -- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking - services and implementations. -- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the - location of protoc.exe. -- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow - custom implementation of writers with both speed and size optimizations. -- Addition of the "Google.ProtoBuffers.Serialization" assembly to support - reading and writing messages to/from XML, JSON, IDictionary<,> and others. -- Several performance related fixes and tweeks -- Issue 3: Add option to mark generated code with attribute -- Issue 20: Support for decorating classes [Serializable] -- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] -- Issue 22: Reusable Builder classes -- Issue 24: Support for using Json/Xml formats with ICodedInputStream -- Issue 25: Added support for NuGet packages -- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 - -Fixes: -- Issue 13: Message with Field same name as message causes uncompilable .cs -- Issue 16: Does not integrate well with other tooling -- Issue 19: Support for negative enum values -- Issue 26: AddRange in GeneratedBuilder iterates twice. -- Issue 27: Remove XML documentation output from test projects to clear - warnings/errors. -- Issue 28: Circular message dependencies result in null default values for - Message fields. -- Issue 29: Message classes generated have a public default constructor. You - can disable private ctor generation with the option generate_private_ctor. -- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ -- Big-endian support for float, and double on Silverlight -- Packed and Unpacked parsing allow for all repeated, as per version 2.3 -- Fix for leaving Builder a public ctor on internal classes for use with - generic "where T: new()" constraints. - -Other: -- Changed the code signing key to a privately held key -- Reformatted all code and line-endings to C# defaults -- Reworking of performance benchmarks to produce reliable results, option /v2 -- Issue 34: Silverlight assemblies are now unit tested - -=============================================================================== -RELEASE NOTES - Version 2.3.0.277 -=============================================================================== - -Features: -- Added cls_compliance option to generate attributes indicating - non-CLS-compliance. -- Added file_extension option to control the generated output file's extension. -- Added umbrella_namespace option to place the umbrella class into a nested - namespace to address issues with proto files having the same name as a - message it contains. -- Added output_directory option to set the output path for the source file(s). -- Added ignore_google_protobuf option to avoid generating code for includes - from the google.protobuf package. -- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to - generate code with "option optimize_for = LITE_RUNTIME;". -- Added ability to invoke protoc.exe from within ProtoGen.exe. -- Upgraded to protoc.exe (2.3) compiler. - -Fixes: -- Issue 9: Class cannot be static and sealed error -- Issue 12: default value for enumerate fields must be filled out - -Other: -- Rewrite of build using MSBbuild instead of NAnt -- Moved to NUnit Version 2.2.8.0 -- Changed to using secure .snk for releases - -=============================================================================== -RELEASE NOTES - Version 0.9.1 -=============================================================================== - -Fixes: -- issue 10: Incorrect encoding of packed fields when serialized - -=============================================================================== -RELEASE NOTES - Version 0.9.0 -=============================================================================== - -- Initial release - -=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/licenses/license.txt b/src/core/Akka.Persistence.Tests/licenses/license.txt deleted file mode 100644 index b8e773b2e05..00000000000 --- a/src/core/Akka.Persistence.Tests/licenses/license.txt +++ /dev/null @@ -1,31 +0,0 @@ -Protocol Buffers - Google's data interchange format -Copyright 2008-2010 Google Inc. All rights reserved. -http://github.com/jskeet/dotnet-protobufs/ -Original C++/Java/Python code: -http://code.google.com/p/protobuf/ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Persistence.Tests/licenses/protoc-license.txt b/src/core/Akka.Persistence.Tests/licenses/protoc-license.txt deleted file mode 100644 index c779cb0e1ed..00000000000 --- a/src/core/Akka.Persistence.Tests/licenses/protoc-license.txt +++ /dev/null @@ -1,36 +0,0 @@ -protoc.exe was built from the original source at http://code.google.com/p/protobuf/ -The licence for this code is as follows: - -Copyright 2008, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Code generated by the Protocol Buffer compiler is owned by the owner -of the input file used when generating it. This code is not -standalone and requires a support library to be linked with it. This -support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/packages.config b/src/core/Akka.Persistence.Tests/packages.config new file mode 100644 index 00000000000..33c0ad1013c --- /dev/null +++ b/src/core/Akka.Persistence.Tests/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/paket.references b/src/core/Akka.Persistence.Tests/paket.references deleted file mode 100644 index a94200f76e5..00000000000 --- a/src/core/Akka.Persistence.Tests/paket.references +++ /dev/null @@ -1,4 +0,0 @@ -Google.ProtocolBuffers -group Test -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Persistence.Tests/protos/google/protobuf/csharp_options.proto deleted file mode 100644 index 152df766f03..00000000000 --- a/src/core/Akka.Persistence.Tests/protos/google/protobuf/csharp_options.proto +++ /dev/null @@ -1,115 +0,0 @@ -// Extra options for C# generator - -import "google/protobuf/descriptor.proto"; - -package google.protobuf; - -message CSharpFileOptions { - - // Namespace for generated classes; defaults to the package. - optional string namespace = 1; - - // Name of the "umbrella" class used for metadata about all - // the messages within this file. Default is based on the name - // of the file. - optional string umbrella_classname = 2; - - // Whether classes should be public (true) or internal (false) - optional bool public_classes = 3 [default = true]; - - // Whether to generate a single file for everything within the - // .proto file (false), or one file per message (true). - // This option is not currently honored; please log a feature - // request if you really want it. - optional bool multiple_files = 4; - - // Whether to nest messages within a single umbrella class (true) - // or create the umbrella class as a peer, with messages as - // top-level classes in the namespace (false) - optional bool nest_classes = 5; - - // Generate appropriate support for Code Contracts - // (Ongoing; support should improve over time) - optional bool code_contracts = 6; - - // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" - // would generate files within [output directory]/Foo/Bar - optional bool expand_namespace_directories = 7; - - // Generate attributes indicating non-CLS-compliance - optional bool cls_compliance = 8 [default = true]; - - // Generate messages/builders with the [Serializable] attribute - optional bool add_serializable = 9 [default = false]; - - // Generates a private ctor for Message types - optional bool generate_private_ctor = 10 [default = true]; - - // The extension that should be appended to the umbrella_classname when creating files. - optional string file_extension = 221 [default = ".cs"]; - - // A nested namespace for the umbrella class. Helpful for name collisions caused by - // umbrella_classname conflicting with an existing type. This will be automatically - // set to 'Proto' if a collision is detected with types being generated. This value - // is ignored when nest_classes == true - optional string umbrella_namespace = 222; - - // The output path for the source file(s) generated - optional string output_directory = 223 [default = "."]; - - // Will ignore the type generations and remove dependencies for the descriptor proto - // files that declare their package to be "google.protobuf" - optional bool ignore_google_protobuf = 224 [default = false]; - - // Controls how services are generated, GENERIC is the deprecated original implementation - // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and - // implementations using the included Windows RPC interop libarary. - optional CSharpServiceType service_generator_type = 225 [default = NONE]; - - // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and - // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. - optional bool generated_code_attributes = 226 [default = false]; -} - -enum CSharpServiceType { - // Services are ignored by the generator - NONE = 0; - // Generates the original Java generic service implementations - GENERIC = 1; - // Generates an interface for the service and nothing else - INTERFACE = 2; - // Generates an interface for the service and client/server wrappers for the interface - IRPCDISPATCH = 3; -} - -extend FileOptions { - optional CSharpFileOptions csharp_file_options = 1000; -} - -extend FieldOptions { - optional CSharpFieldOptions csharp_field_options = 1000; -} - -message CSharpFieldOptions { - // Provides the ability to override the name of the property - // generated for this field. This is applied to all properties - // and methods to do with this field, including HasFoo, FooCount, - // FooList etc. - optional string property_name = 1; -} - -message CSharpServiceOptions { - optional string interface_id = 1; -} - -extend ServiceOptions { - optional CSharpServiceOptions csharp_service_options = 1000; -} - -message CSharpMethodOptions { - optional int32 dispatch_id = 1; -} - -extend MethodOptions { - optional CSharpMethodOptions csharp_method_options = 1000; -} \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/protos/google/protobuf/descriptor.proto b/src/core/Akka.Persistence.Tests/protos/google/protobuf/descriptor.proto deleted file mode 100644 index 233f879410e..00000000000 --- a/src/core/Akka.Persistence.Tests/protos/google/protobuf/descriptor.proto +++ /dev/null @@ -1,533 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. -// -// The messages in this file describe the definitions found in .proto files. -// A valid .proto file can be translated directly to a FileDescriptorProto -// without any other information (e.g. without reading its imports). - - - -package google.protobuf; -option java_package = "com.google.protobuf"; -option java_outer_classname = "DescriptorProtos"; - -// descriptor.proto must be optimized for speed because reflection-based -// algorithms don't work during bootstrapping. -option optimize_for = SPEED; - -// The protocol compiler can output a FileDescriptorSet containing the .proto -// files it parses. -message FileDescriptorSet { - repeated FileDescriptorProto file = 1; -} - -// Describes a complete .proto file. -message FileDescriptorProto { - optional string name = 1; // file name, relative to root of source tree - optional string package = 2; // e.g. "foo", "foo.bar", etc. - - // Names of files imported by this file. - repeated string dependency = 3; - - // All top-level definitions in this file. - repeated DescriptorProto message_type = 4; - repeated EnumDescriptorProto enum_type = 5; - repeated ServiceDescriptorProto service = 6; - repeated FieldDescriptorProto extension = 7; - - optional FileOptions options = 8; - - // This field contains optional information about the original source code. - // You may safely remove this entire field whithout harming runtime - // functionality of the descriptors -- the information is needed only by - // development tools. - optional SourceCodeInfo source_code_info = 9; -} - -// Describes a message type. -message DescriptorProto { - optional string name = 1; - - repeated FieldDescriptorProto field = 2; - repeated FieldDescriptorProto extension = 6; - - repeated DescriptorProto nested_type = 3; - repeated EnumDescriptorProto enum_type = 4; - - message ExtensionRange { - optional int32 start = 1; - optional int32 end = 2; - } - repeated ExtensionRange extension_range = 5; - - optional MessageOptions options = 7; -} - -// Describes a field within a message. -message FieldDescriptorProto { - enum Type { - // 0 is reserved for errors. - // Order is weird for historical reasons. - TYPE_DOUBLE = 1; - TYPE_FLOAT = 2; - TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT64 if negative - // values are likely. - TYPE_UINT64 = 4; - TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT32 if negative - // values are likely. - TYPE_FIXED64 = 6; - TYPE_FIXED32 = 7; - TYPE_BOOL = 8; - TYPE_STRING = 9; - TYPE_GROUP = 10; // Tag-delimited aggregate. - TYPE_MESSAGE = 11; // Length-delimited aggregate. - - // New in version 2. - TYPE_BYTES = 12; - TYPE_UINT32 = 13; - TYPE_ENUM = 14; - TYPE_SFIXED32 = 15; - TYPE_SFIXED64 = 16; - TYPE_SINT32 = 17; // Uses ZigZag encoding. - TYPE_SINT64 = 18; // Uses ZigZag encoding. - }; - - enum Label { - // 0 is reserved for errors - LABEL_OPTIONAL = 1; - LABEL_REQUIRED = 2; - LABEL_REPEATED = 3; - // TODO(sanjay): Should we add LABEL_MAP? - }; - - optional string name = 1; - optional int32 number = 3; - optional Label label = 4; - - // If type_name is set, this need not be set. If both this and type_name - // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. - optional Type type = 5; - - // For message and enum types, this is the name of the type. If the name - // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping - // rules are used to find the type (i.e. first the nested types within this - // message are searched, then within the parent, on up to the root - // namespace). - optional string type_name = 6; - - // For extensions, this is the name of the type being extended. It is - // resolved in the same manner as type_name. - optional string extendee = 2; - - // For numeric types, contains the original text representation of the value. - // For booleans, "true" or "false". - // For strings, contains the default text contents (not escaped in any way). - // For bytes, contains the C escaped value. All bytes >= 128 are escaped. - // TODO(kenton): Base-64 encode? - optional string default_value = 7; - - optional FieldOptions options = 8; -} - -// Describes an enum type. -message EnumDescriptorProto { - optional string name = 1; - - repeated EnumValueDescriptorProto value = 2; - - optional EnumOptions options = 3; -} - -// Describes a value within an enum. -message EnumValueDescriptorProto { - optional string name = 1; - optional int32 number = 2; - - optional EnumValueOptions options = 3; -} - -// Describes a service. -message ServiceDescriptorProto { - optional string name = 1; - repeated MethodDescriptorProto method = 2; - - optional ServiceOptions options = 3; -} - -// Describes a method of a service. -message MethodDescriptorProto { - optional string name = 1; - - // Input and output type names. These are resolved in the same way as - // FieldDescriptorProto.type_name, but must refer to a message type. - optional string input_type = 2; - optional string output_type = 3; - - optional MethodOptions options = 4; -} - -// =================================================================== -// Options - -// Each of the definitions above may have "options" attached. These are -// just annotations which may cause code to be generated slightly differently -// or may contain hints for code that manipulates protocol messages. -// -// Clients may define custom options as extensions of the *Options messages. -// These extensions may not yet be known at parsing time, so the parser cannot -// store the values in them. Instead it stores them in a field in the *Options -// message called uninterpreted_option. This field must have the same name -// across all *Options messages. We then use this field to populate the -// extensions when we build a descriptor, at which point all protos have been -// parsed and so all extensions are known. -// -// Extension numbers for custom options may be chosen as follows: -// * For options which will only be used within a single application or -// organization, or for experimental options, use field numbers 50000 -// through 99999. It is up to you to ensure that you do not use the -// same number for multiple options. -// * For options which will be published and used publicly by multiple -// independent entities, e-mail kenton@google.com to reserve extension -// numbers. Simply tell me how many you need and I'll send you back a -// set of numbers to use -- there's no need to explain how you intend to -// use them. If this turns out to be popular, a web service will be set up -// to automatically assign option numbers. - - -message FileOptions { - - // Sets the Java package where classes generated from this .proto will be - // placed. By default, the proto package is used, but this is often - // inappropriate because proto packages do not normally start with backwards - // domain names. - optional string java_package = 1; - - - // If set, all the classes from the .proto file are wrapped in a single - // outer class with the given name. This applies to both Proto1 - // (equivalent to the old "--one_java_file" option) and Proto2 (where - // a .proto always translates to a single class, but you may want to - // explicitly choose the class name). - optional string java_outer_classname = 8; - - // If set true, then the Java code generator will generate a separate .java - // file for each top-level message, enum, and service defined in the .proto - // file. Thus, these types will *not* be nested inside the outer class - // named by java_outer_classname. However, the outer class will still be - // generated to contain the file's getDescriptor() method as well as any - // top-level extensions defined in the file. - optional bool java_multiple_files = 10 [default=false]; - - // If set true, then the Java code generator will generate equals() and - // hashCode() methods for all messages defined in the .proto file. This is - // purely a speed optimization, as the AbstractMessage base class includes - // reflection-based implementations of these methods. - optional bool java_generate_equals_and_hash = 20 [default=false]; - - // Generated classes can be optimized for speed or code size. - enum OptimizeMode { - SPEED = 1; // Generate complete code for parsing, serialization, - // etc. - CODE_SIZE = 2; // Use ReflectionOps to implement these methods. - LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. - } - optional OptimizeMode optimize_for = 9 [default=SPEED]; - - - - - // Should generic services be generated in each language? "Generic" services - // are not specific to any particular RPC system. They are generated by the - // main code generators in each language (without additional plugins). - // Generic services were the only kind of service generation supported by - // early versions of proto2. - // - // Generic services are now considered deprecated in favor of using plugins - // that generate code specific to your particular RPC system. Therefore, - // these default to false. Old code which depends on generic services should - // explicitly set them to true. - optional bool cc_generic_services = 16 [default=false]; - optional bool java_generic_services = 17 [default=false]; - optional bool py_generic_services = 18 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MessageOptions { - // Set true to use the old proto1 MessageSet wire format for extensions. - // This is provided for backwards-compatibility with the MessageSet wire - // format. You should not use this for any other reason: It's less - // efficient, has fewer features, and is more complicated. - // - // The message must be defined exactly as follows: - // message Foo { - // option message_set_wire_format = true; - // extensions 4 to max; - // } - // Note that the message cannot have any defined fields; MessageSets only - // have extensions. - // - // All extensions of your type must be singular messages; e.g. they cannot - // be int32s, enums, or repeated messages. - // - // Because this is an option, the above two restrictions are not enforced by - // the protocol compiler. - optional bool message_set_wire_format = 1 [default=false]; - - // Disables the generation of the standard "descriptor()" accessor, which can - // conflict with a field of the same name. This is meant to make migration - // from proto1 easier; new code should avoid fields named "descriptor". - optional bool no_standard_descriptor_accessor = 2 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message FieldOptions { - // The ctype option instructs the C++ code generator to use a different - // representation of the field than it normally would. See the specific - // options below. This option is not yet implemented in the open source - // release -- sorry, we'll try to include it in a future version! - optional CType ctype = 1 [default = STRING]; - enum CType { - // Default mode. - STRING = 0; - - CORD = 1; - - STRING_PIECE = 2; - } - // The packed option can be enabled for repeated primitive fields to enable - // a more efficient representation on the wire. Rather than repeatedly - // writing the tag and type for each element, the entire array is encoded as - // a single length-delimited blob. - optional bool packed = 2; - - - // Is this field deprecated? - // Depending on the target platform, this can emit Deprecated annotations - // for accessors, or it will be completely ignored; in the very least, this - // is a formalization for deprecating fields. - optional bool deprecated = 3 [default=false]; - - // EXPERIMENTAL. DO NOT USE. - // For "map" fields, the name of the field in the enclosed type that - // is the key for this map. For example, suppose we have: - // message Item { - // required string name = 1; - // required string value = 2; - // } - // message Config { - // repeated Item items = 1 [experimental_map_key="name"]; - // } - // In this situation, the map key for Item will be set to "name". - // TODO: Fully-implement this, then remove the "experimental_" prefix. - optional string experimental_map_key = 9; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumOptions { - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumValueOptions { - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message ServiceOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MethodOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -// A message representing a option the parser does not recognize. This only -// appears in options protos created by the compiler::Parser class. -// DescriptorPool resolves these when building Descriptor objects. Therefore, -// options protos in descriptor objects (e.g. returned by Descriptor::options(), -// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions -// in them. -message UninterpretedOption { - // The name of the uninterpreted option. Each string represents a segment in - // a dot-separated name. is_extension is true iff a segment represents an - // extension (denoted with parentheses in options specs in .proto files). - // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents - // "foo.(bar.baz).qux". - message NamePart { - required string name_part = 1; - required bool is_extension = 2; - } - repeated NamePart name = 2; - - // The value of the uninterpreted option, in whatever type the tokenizer - // identified it as during parsing. Exactly one of these should be set. - optional string identifier_value = 3; - optional uint64 positive_int_value = 4; - optional int64 negative_int_value = 5; - optional double double_value = 6; - optional bytes string_value = 7; - optional string aggregate_value = 8; -} - -// =================================================================== -// Optional source code info - -// Encapsulates information about the original source file from which a -// FileDescriptorProto was generated. -message SourceCodeInfo { - // A Location identifies a piece of source code in a .proto file which - // corresponds to a particular definition. This information is intended - // to be useful to IDEs, code indexers, documentation generators, and similar - // tools. - // - // For example, say we have a file like: - // message Foo { - // optional string foo = 1; - // } - // Let's look at just the field definition: - // optional string foo = 1; - // ^ ^^ ^^ ^ ^^^ - // a bc de f ghi - // We have the following locations: - // span path represents - // [a,i) [ 4, 0, 2, 0 ] The whole field definition. - // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). - // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). - // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). - // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). - // - // Notes: - // - A location may refer to a repeated field itself (i.e. not to any - // particular index within it). This is used whenever a set of elements are - // logically enclosed in a single code segment. For example, an entire - // extend block (possibly containing multiple extension definitions) will - // have an outer location whose path refers to the "extensions" repeated - // field without an index. - // - Multiple locations may have the same path. This happens when a single - // logical declaration is spread out across multiple places. The most - // obvious example is the "extend" block again -- there may be multiple - // extend blocks in the same scope, each of which will have the same path. - // - A location's span is not always a subset of its parent's span. For - // example, the "extendee" of an extension declaration appears at the - // beginning of the "extend" block and is shared by all extensions within - // the block. - // - Just because a location's span is a subset of some other location's span - // does not mean that it is a descendent. For example, a "group" defines - // both a type and a field in a single declaration. Thus, the locations - // corresponding to the type and field and their components will overlap. - // - Code which tries to interpret locations should probably be designed to - // ignore those that it doesn't understand, as more types of locations could - // be recorded in the future. - repeated Location location = 1; - message Location { - // Identifies which part of the FileDescriptorProto was defined at this - // location. - // - // Each element is a field number or an index. They form a path from - // the root FileDescriptorProto to the place where the definition. For - // example, this path: - // [ 4, 3, 2, 7, 1 ] - // refers to: - // file.message_type(3) // 4, 3 - // .field(7) // 2, 7 - // .name() // 1 - // This is because FileDescriptorProto.message_type has field number 4: - // repeated DescriptorProto message_type = 4; - // and DescriptorProto.field has field number 2: - // repeated FieldDescriptorProto field = 2; - // and FieldDescriptorProto.name has field number 1: - // optional string name = 1; - // - // Thus, the above path gives the location of a field name. If we removed - // the last element: - // [ 4, 3, 2, 7 ] - // this path refers to the whole field declaration (from the beginning - // of the label to the terminating semicolon). - repeated int32 path = 1 [packed=true]; - - // Always has exactly three or four elements: start line, start column, - // end line (optional, otherwise assumed same as start line), end column. - // These are packed into a single field for efficiency. Note that line - // and column numbers are zero-based -- typically you will want to add - // 1 to each before displaying to a user. - repeated int32 span = 2 [packed=true]; - - // TODO(kenton): Record comments appearing before and after the - // declaration. - } -} diff --git a/src/core/Akka.Persistence.Tests/protos/tutorial/addressbook.proto b/src/core/Akka.Persistence.Tests/protos/tutorial/addressbook.proto deleted file mode 100644 index 5abe35ce39b..00000000000 --- a/src/core/Akka.Persistence.Tests/protos/tutorial/addressbook.proto +++ /dev/null @@ -1,31 +0,0 @@ -package tutorial; - -import "google/protobuf/csharp_options.proto"; -option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; -option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; - -option optimize_for = SPEED; - -message Person { - required string name = 1; - required int32 id = 2; // Unique ID number for this person. - optional string email = 3; - - enum PhoneType { - MOBILE = 0; - HOME = 1; - WORK = 2; - } - - message PhoneNumber { - required string number = 1; - optional PhoneType type = 2 [default = HOME]; - } - - repeated PhoneNumber phone = 4; -} - -// Our address book file is just one of these. -message AddressBook { - repeated Person person = 1; -} diff --git a/src/core/Akka.Persistence/Akka.Persistence.csproj b/src/core/Akka.Persistence/Akka.Persistence.csproj index d33b27b744f..b035ce6cd76 100644 --- a/src/core/Akka.Persistence/Akka.Persistence.csproj +++ b/src/core/Akka.Persistence/Akka.Persistence.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\ + true true @@ -50,6 +51,16 @@ True + + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll + + + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll + + + False + ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + @@ -94,7 +105,7 @@ - + @@ -105,6 +116,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - + diff --git a/src/core/Akka.Persistence/CHANGES.txt b/src/core/Akka.Persistence/CHANGES.txt deleted file mode 100644 index d80368c78f2..00000000000 --- a/src/core/Akka.Persistence/CHANGES.txt +++ /dev/null @@ -1,99 +0,0 @@ -=============================================================================== -Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet -(skeet@pobox.com) based on the work of many talented people. - -For more information about this port, visit its homepage: -http://protobuf-csharp-port.googlecode.com - -For more information about Protocol Buffers in general, visit the project page -for the C++, Java and Python project: -http://protobuf.googlecode.com -=============================================================================== -RELEASE NOTES - Version 2.4.1.473 -=============================================================================== - -Features: -- Added option service_generator_type to control service generation with - NONE, GENERIC, INTERFACE, or IRPCDISPATCH -- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking - services and implementations. -- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the - location of protoc.exe. -- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow - custom implementation of writers with both speed and size optimizations. -- Addition of the "Google.ProtoBuffers.Serialization" assembly to support - reading and writing messages to/from XML, JSON, IDictionary<,> and others. -- Several performance related fixes and tweeks -- Issue 3: Add option to mark generated code with attribute -- Issue 20: Support for decorating classes [Serializable] -- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] -- Issue 22: Reusable Builder classes -- Issue 24: Support for using Json/Xml formats with ICodedInputStream -- Issue 25: Added support for NuGet packages -- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 - -Fixes: -- Issue 13: Message with Field same name as message causes uncompilable .cs -- Issue 16: Does not integrate well with other tooling -- Issue 19: Support for negative enum values -- Issue 26: AddRange in GeneratedBuilder iterates twice. -- Issue 27: Remove XML documentation output from test projects to clear - warnings/errors. -- Issue 28: Circular message dependencies result in null default values for - Message fields. -- Issue 29: Message classes generated have a public default constructor. You - can disable private ctor generation with the option generate_private_ctor. -- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ -- Big-endian support for float, and double on Silverlight -- Packed and Unpacked parsing allow for all repeated, as per version 2.3 -- Fix for leaving Builder a public ctor on internal classes for use with - generic "where T: new()" constraints. - -Other: -- Changed the code signing key to a privately held key -- Reformatted all code and line-endings to C# defaults -- Reworking of performance benchmarks to produce reliable results, option /v2 -- Issue 34: Silverlight assemblies are now unit tested - -=============================================================================== -RELEASE NOTES - Version 2.3.0.277 -=============================================================================== - -Features: -- Added cls_compliance option to generate attributes indicating - non-CLS-compliance. -- Added file_extension option to control the generated output file's extension. -- Added umbrella_namespace option to place the umbrella class into a nested - namespace to address issues with proto files having the same name as a - message it contains. -- Added output_directory option to set the output path for the source file(s). -- Added ignore_google_protobuf option to avoid generating code for includes - from the google.protobuf package. -- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to - generate code with "option optimize_for = LITE_RUNTIME;". -- Added ability to invoke protoc.exe from within ProtoGen.exe. -- Upgraded to protoc.exe (2.3) compiler. - -Fixes: -- Issue 9: Class cannot be static and sealed error -- Issue 12: default value for enumerate fields must be filled out - -Other: -- Rewrite of build using MSBbuild instead of NAnt -- Moved to NUnit Version 2.2.8.0 -- Changed to using secure .snk for releases - -=============================================================================== -RELEASE NOTES - Version 0.9.1 -=============================================================================== - -Fixes: -- issue 10: Incorrect encoding of packed fields when serialized - -=============================================================================== -RELEASE NOTES - Version 0.9.0 -=============================================================================== - -- Initial release - -=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Persistence/licenses/license.txt b/src/core/Akka.Persistence/licenses/license.txt deleted file mode 100644 index b8e773b2e05..00000000000 --- a/src/core/Akka.Persistence/licenses/license.txt +++ /dev/null @@ -1,31 +0,0 @@ -Protocol Buffers - Google's data interchange format -Copyright 2008-2010 Google Inc. All rights reserved. -http://github.com/jskeet/dotnet-protobufs/ -Original C++/Java/Python code: -http://code.google.com/p/protobuf/ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Persistence/licenses/protoc-license.txt b/src/core/Akka.Persistence/licenses/protoc-license.txt deleted file mode 100644 index c779cb0e1ed..00000000000 --- a/src/core/Akka.Persistence/licenses/protoc-license.txt +++ /dev/null @@ -1,36 +0,0 @@ -protoc.exe was built from the original source at http://code.google.com/p/protobuf/ -The licence for this code is as follows: - -Copyright 2008, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Code generated by the Protocol Buffer compiler is owned by the owner -of the input file used when generating it. This code is not -standalone and requires a support library to be linked with it. This -support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Persistence/packages.config b/src/core/Akka.Persistence/packages.config new file mode 100644 index 00000000000..f138ea9a2ef --- /dev/null +++ b/src/core/Akka.Persistence/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence/paket.references b/src/core/Akka.Persistence/paket.references deleted file mode 100644 index 0a488371f3d..00000000000 --- a/src/core/Akka.Persistence/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -Google.ProtocolBuffers -Newtonsoft.Json \ No newline at end of file diff --git a/src/core/Akka.Persistence/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Persistence/protos/google/protobuf/csharp_options.proto deleted file mode 100644 index 152df766f03..00000000000 --- a/src/core/Akka.Persistence/protos/google/protobuf/csharp_options.proto +++ /dev/null @@ -1,115 +0,0 @@ -// Extra options for C# generator - -import "google/protobuf/descriptor.proto"; - -package google.protobuf; - -message CSharpFileOptions { - - // Namespace for generated classes; defaults to the package. - optional string namespace = 1; - - // Name of the "umbrella" class used for metadata about all - // the messages within this file. Default is based on the name - // of the file. - optional string umbrella_classname = 2; - - // Whether classes should be public (true) or internal (false) - optional bool public_classes = 3 [default = true]; - - // Whether to generate a single file for everything within the - // .proto file (false), or one file per message (true). - // This option is not currently honored; please log a feature - // request if you really want it. - optional bool multiple_files = 4; - - // Whether to nest messages within a single umbrella class (true) - // or create the umbrella class as a peer, with messages as - // top-level classes in the namespace (false) - optional bool nest_classes = 5; - - // Generate appropriate support for Code Contracts - // (Ongoing; support should improve over time) - optional bool code_contracts = 6; - - // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" - // would generate files within [output directory]/Foo/Bar - optional bool expand_namespace_directories = 7; - - // Generate attributes indicating non-CLS-compliance - optional bool cls_compliance = 8 [default = true]; - - // Generate messages/builders with the [Serializable] attribute - optional bool add_serializable = 9 [default = false]; - - // Generates a private ctor for Message types - optional bool generate_private_ctor = 10 [default = true]; - - // The extension that should be appended to the umbrella_classname when creating files. - optional string file_extension = 221 [default = ".cs"]; - - // A nested namespace for the umbrella class. Helpful for name collisions caused by - // umbrella_classname conflicting with an existing type. This will be automatically - // set to 'Proto' if a collision is detected with types being generated. This value - // is ignored when nest_classes == true - optional string umbrella_namespace = 222; - - // The output path for the source file(s) generated - optional string output_directory = 223 [default = "."]; - - // Will ignore the type generations and remove dependencies for the descriptor proto - // files that declare their package to be "google.protobuf" - optional bool ignore_google_protobuf = 224 [default = false]; - - // Controls how services are generated, GENERIC is the deprecated original implementation - // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and - // implementations using the included Windows RPC interop libarary. - optional CSharpServiceType service_generator_type = 225 [default = NONE]; - - // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and - // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. - optional bool generated_code_attributes = 226 [default = false]; -} - -enum CSharpServiceType { - // Services are ignored by the generator - NONE = 0; - // Generates the original Java generic service implementations - GENERIC = 1; - // Generates an interface for the service and nothing else - INTERFACE = 2; - // Generates an interface for the service and client/server wrappers for the interface - IRPCDISPATCH = 3; -} - -extend FileOptions { - optional CSharpFileOptions csharp_file_options = 1000; -} - -extend FieldOptions { - optional CSharpFieldOptions csharp_field_options = 1000; -} - -message CSharpFieldOptions { - // Provides the ability to override the name of the property - // generated for this field. This is applied to all properties - // and methods to do with this field, including HasFoo, FooCount, - // FooList etc. - optional string property_name = 1; -} - -message CSharpServiceOptions { - optional string interface_id = 1; -} - -extend ServiceOptions { - optional CSharpServiceOptions csharp_service_options = 1000; -} - -message CSharpMethodOptions { - optional int32 dispatch_id = 1; -} - -extend MethodOptions { - optional CSharpMethodOptions csharp_method_options = 1000; -} \ No newline at end of file diff --git a/src/core/Akka.Persistence/protos/google/protobuf/descriptor.proto b/src/core/Akka.Persistence/protos/google/protobuf/descriptor.proto deleted file mode 100644 index 233f879410e..00000000000 --- a/src/core/Akka.Persistence/protos/google/protobuf/descriptor.proto +++ /dev/null @@ -1,533 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. -// -// The messages in this file describe the definitions found in .proto files. -// A valid .proto file can be translated directly to a FileDescriptorProto -// without any other information (e.g. without reading its imports). - - - -package google.protobuf; -option java_package = "com.google.protobuf"; -option java_outer_classname = "DescriptorProtos"; - -// descriptor.proto must be optimized for speed because reflection-based -// algorithms don't work during bootstrapping. -option optimize_for = SPEED; - -// The protocol compiler can output a FileDescriptorSet containing the .proto -// files it parses. -message FileDescriptorSet { - repeated FileDescriptorProto file = 1; -} - -// Describes a complete .proto file. -message FileDescriptorProto { - optional string name = 1; // file name, relative to root of source tree - optional string package = 2; // e.g. "foo", "foo.bar", etc. - - // Names of files imported by this file. - repeated string dependency = 3; - - // All top-level definitions in this file. - repeated DescriptorProto message_type = 4; - repeated EnumDescriptorProto enum_type = 5; - repeated ServiceDescriptorProto service = 6; - repeated FieldDescriptorProto extension = 7; - - optional FileOptions options = 8; - - // This field contains optional information about the original source code. - // You may safely remove this entire field whithout harming runtime - // functionality of the descriptors -- the information is needed only by - // development tools. - optional SourceCodeInfo source_code_info = 9; -} - -// Describes a message type. -message DescriptorProto { - optional string name = 1; - - repeated FieldDescriptorProto field = 2; - repeated FieldDescriptorProto extension = 6; - - repeated DescriptorProto nested_type = 3; - repeated EnumDescriptorProto enum_type = 4; - - message ExtensionRange { - optional int32 start = 1; - optional int32 end = 2; - } - repeated ExtensionRange extension_range = 5; - - optional MessageOptions options = 7; -} - -// Describes a field within a message. -message FieldDescriptorProto { - enum Type { - // 0 is reserved for errors. - // Order is weird for historical reasons. - TYPE_DOUBLE = 1; - TYPE_FLOAT = 2; - TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT64 if negative - // values are likely. - TYPE_UINT64 = 4; - TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT32 if negative - // values are likely. - TYPE_FIXED64 = 6; - TYPE_FIXED32 = 7; - TYPE_BOOL = 8; - TYPE_STRING = 9; - TYPE_GROUP = 10; // Tag-delimited aggregate. - TYPE_MESSAGE = 11; // Length-delimited aggregate. - - // New in version 2. - TYPE_BYTES = 12; - TYPE_UINT32 = 13; - TYPE_ENUM = 14; - TYPE_SFIXED32 = 15; - TYPE_SFIXED64 = 16; - TYPE_SINT32 = 17; // Uses ZigZag encoding. - TYPE_SINT64 = 18; // Uses ZigZag encoding. - }; - - enum Label { - // 0 is reserved for errors - LABEL_OPTIONAL = 1; - LABEL_REQUIRED = 2; - LABEL_REPEATED = 3; - // TODO(sanjay): Should we add LABEL_MAP? - }; - - optional string name = 1; - optional int32 number = 3; - optional Label label = 4; - - // If type_name is set, this need not be set. If both this and type_name - // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. - optional Type type = 5; - - // For message and enum types, this is the name of the type. If the name - // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping - // rules are used to find the type (i.e. first the nested types within this - // message are searched, then within the parent, on up to the root - // namespace). - optional string type_name = 6; - - // For extensions, this is the name of the type being extended. It is - // resolved in the same manner as type_name. - optional string extendee = 2; - - // For numeric types, contains the original text representation of the value. - // For booleans, "true" or "false". - // For strings, contains the default text contents (not escaped in any way). - // For bytes, contains the C escaped value. All bytes >= 128 are escaped. - // TODO(kenton): Base-64 encode? - optional string default_value = 7; - - optional FieldOptions options = 8; -} - -// Describes an enum type. -message EnumDescriptorProto { - optional string name = 1; - - repeated EnumValueDescriptorProto value = 2; - - optional EnumOptions options = 3; -} - -// Describes a value within an enum. -message EnumValueDescriptorProto { - optional string name = 1; - optional int32 number = 2; - - optional EnumValueOptions options = 3; -} - -// Describes a service. -message ServiceDescriptorProto { - optional string name = 1; - repeated MethodDescriptorProto method = 2; - - optional ServiceOptions options = 3; -} - -// Describes a method of a service. -message MethodDescriptorProto { - optional string name = 1; - - // Input and output type names. These are resolved in the same way as - // FieldDescriptorProto.type_name, but must refer to a message type. - optional string input_type = 2; - optional string output_type = 3; - - optional MethodOptions options = 4; -} - -// =================================================================== -// Options - -// Each of the definitions above may have "options" attached. These are -// just annotations which may cause code to be generated slightly differently -// or may contain hints for code that manipulates protocol messages. -// -// Clients may define custom options as extensions of the *Options messages. -// These extensions may not yet be known at parsing time, so the parser cannot -// store the values in them. Instead it stores them in a field in the *Options -// message called uninterpreted_option. This field must have the same name -// across all *Options messages. We then use this field to populate the -// extensions when we build a descriptor, at which point all protos have been -// parsed and so all extensions are known. -// -// Extension numbers for custom options may be chosen as follows: -// * For options which will only be used within a single application or -// organization, or for experimental options, use field numbers 50000 -// through 99999. It is up to you to ensure that you do not use the -// same number for multiple options. -// * For options which will be published and used publicly by multiple -// independent entities, e-mail kenton@google.com to reserve extension -// numbers. Simply tell me how many you need and I'll send you back a -// set of numbers to use -- there's no need to explain how you intend to -// use them. If this turns out to be popular, a web service will be set up -// to automatically assign option numbers. - - -message FileOptions { - - // Sets the Java package where classes generated from this .proto will be - // placed. By default, the proto package is used, but this is often - // inappropriate because proto packages do not normally start with backwards - // domain names. - optional string java_package = 1; - - - // If set, all the classes from the .proto file are wrapped in a single - // outer class with the given name. This applies to both Proto1 - // (equivalent to the old "--one_java_file" option) and Proto2 (where - // a .proto always translates to a single class, but you may want to - // explicitly choose the class name). - optional string java_outer_classname = 8; - - // If set true, then the Java code generator will generate a separate .java - // file for each top-level message, enum, and service defined in the .proto - // file. Thus, these types will *not* be nested inside the outer class - // named by java_outer_classname. However, the outer class will still be - // generated to contain the file's getDescriptor() method as well as any - // top-level extensions defined in the file. - optional bool java_multiple_files = 10 [default=false]; - - // If set true, then the Java code generator will generate equals() and - // hashCode() methods for all messages defined in the .proto file. This is - // purely a speed optimization, as the AbstractMessage base class includes - // reflection-based implementations of these methods. - optional bool java_generate_equals_and_hash = 20 [default=false]; - - // Generated classes can be optimized for speed or code size. - enum OptimizeMode { - SPEED = 1; // Generate complete code for parsing, serialization, - // etc. - CODE_SIZE = 2; // Use ReflectionOps to implement these methods. - LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. - } - optional OptimizeMode optimize_for = 9 [default=SPEED]; - - - - - // Should generic services be generated in each language? "Generic" services - // are not specific to any particular RPC system. They are generated by the - // main code generators in each language (without additional plugins). - // Generic services were the only kind of service generation supported by - // early versions of proto2. - // - // Generic services are now considered deprecated in favor of using plugins - // that generate code specific to your particular RPC system. Therefore, - // these default to false. Old code which depends on generic services should - // explicitly set them to true. - optional bool cc_generic_services = 16 [default=false]; - optional bool java_generic_services = 17 [default=false]; - optional bool py_generic_services = 18 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MessageOptions { - // Set true to use the old proto1 MessageSet wire format for extensions. - // This is provided for backwards-compatibility with the MessageSet wire - // format. You should not use this for any other reason: It's less - // efficient, has fewer features, and is more complicated. - // - // The message must be defined exactly as follows: - // message Foo { - // option message_set_wire_format = true; - // extensions 4 to max; - // } - // Note that the message cannot have any defined fields; MessageSets only - // have extensions. - // - // All extensions of your type must be singular messages; e.g. they cannot - // be int32s, enums, or repeated messages. - // - // Because this is an option, the above two restrictions are not enforced by - // the protocol compiler. - optional bool message_set_wire_format = 1 [default=false]; - - // Disables the generation of the standard "descriptor()" accessor, which can - // conflict with a field of the same name. This is meant to make migration - // from proto1 easier; new code should avoid fields named "descriptor". - optional bool no_standard_descriptor_accessor = 2 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message FieldOptions { - // The ctype option instructs the C++ code generator to use a different - // representation of the field than it normally would. See the specific - // options below. This option is not yet implemented in the open source - // release -- sorry, we'll try to include it in a future version! - optional CType ctype = 1 [default = STRING]; - enum CType { - // Default mode. - STRING = 0; - - CORD = 1; - - STRING_PIECE = 2; - } - // The packed option can be enabled for repeated primitive fields to enable - // a more efficient representation on the wire. Rather than repeatedly - // writing the tag and type for each element, the entire array is encoded as - // a single length-delimited blob. - optional bool packed = 2; - - - // Is this field deprecated? - // Depending on the target platform, this can emit Deprecated annotations - // for accessors, or it will be completely ignored; in the very least, this - // is a formalization for deprecating fields. - optional bool deprecated = 3 [default=false]; - - // EXPERIMENTAL. DO NOT USE. - // For "map" fields, the name of the field in the enclosed type that - // is the key for this map. For example, suppose we have: - // message Item { - // required string name = 1; - // required string value = 2; - // } - // message Config { - // repeated Item items = 1 [experimental_map_key="name"]; - // } - // In this situation, the map key for Item will be set to "name". - // TODO: Fully-implement this, then remove the "experimental_" prefix. - optional string experimental_map_key = 9; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumOptions { - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumValueOptions { - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message ServiceOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MethodOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -// A message representing a option the parser does not recognize. This only -// appears in options protos created by the compiler::Parser class. -// DescriptorPool resolves these when building Descriptor objects. Therefore, -// options protos in descriptor objects (e.g. returned by Descriptor::options(), -// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions -// in them. -message UninterpretedOption { - // The name of the uninterpreted option. Each string represents a segment in - // a dot-separated name. is_extension is true iff a segment represents an - // extension (denoted with parentheses in options specs in .proto files). - // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents - // "foo.(bar.baz).qux". - message NamePart { - required string name_part = 1; - required bool is_extension = 2; - } - repeated NamePart name = 2; - - // The value of the uninterpreted option, in whatever type the tokenizer - // identified it as during parsing. Exactly one of these should be set. - optional string identifier_value = 3; - optional uint64 positive_int_value = 4; - optional int64 negative_int_value = 5; - optional double double_value = 6; - optional bytes string_value = 7; - optional string aggregate_value = 8; -} - -// =================================================================== -// Optional source code info - -// Encapsulates information about the original source file from which a -// FileDescriptorProto was generated. -message SourceCodeInfo { - // A Location identifies a piece of source code in a .proto file which - // corresponds to a particular definition. This information is intended - // to be useful to IDEs, code indexers, documentation generators, and similar - // tools. - // - // For example, say we have a file like: - // message Foo { - // optional string foo = 1; - // } - // Let's look at just the field definition: - // optional string foo = 1; - // ^ ^^ ^^ ^ ^^^ - // a bc de f ghi - // We have the following locations: - // span path represents - // [a,i) [ 4, 0, 2, 0 ] The whole field definition. - // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). - // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). - // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). - // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). - // - // Notes: - // - A location may refer to a repeated field itself (i.e. not to any - // particular index within it). This is used whenever a set of elements are - // logically enclosed in a single code segment. For example, an entire - // extend block (possibly containing multiple extension definitions) will - // have an outer location whose path refers to the "extensions" repeated - // field without an index. - // - Multiple locations may have the same path. This happens when a single - // logical declaration is spread out across multiple places. The most - // obvious example is the "extend" block again -- there may be multiple - // extend blocks in the same scope, each of which will have the same path. - // - A location's span is not always a subset of its parent's span. For - // example, the "extendee" of an extension declaration appears at the - // beginning of the "extend" block and is shared by all extensions within - // the block. - // - Just because a location's span is a subset of some other location's span - // does not mean that it is a descendent. For example, a "group" defines - // both a type and a field in a single declaration. Thus, the locations - // corresponding to the type and field and their components will overlap. - // - Code which tries to interpret locations should probably be designed to - // ignore those that it doesn't understand, as more types of locations could - // be recorded in the future. - repeated Location location = 1; - message Location { - // Identifies which part of the FileDescriptorProto was defined at this - // location. - // - // Each element is a field number or an index. They form a path from - // the root FileDescriptorProto to the place where the definition. For - // example, this path: - // [ 4, 3, 2, 7, 1 ] - // refers to: - // file.message_type(3) // 4, 3 - // .field(7) // 2, 7 - // .name() // 1 - // This is because FileDescriptorProto.message_type has field number 4: - // repeated DescriptorProto message_type = 4; - // and DescriptorProto.field has field number 2: - // repeated FieldDescriptorProto field = 2; - // and FieldDescriptorProto.name has field number 1: - // optional string name = 1; - // - // Thus, the above path gives the location of a field name. If we removed - // the last element: - // [ 4, 3, 2, 7 ] - // this path refers to the whole field declaration (from the beginning - // of the label to the terminating semicolon). - repeated int32 path = 1 [packed=true]; - - // Always has exactly three or four elements: start line, start column, - // end line (optional, otherwise assumed same as start line), end column. - // These are packed into a single field for efficiency. Note that line - // and column numbers are zero-based -- typically you will want to add - // 1 to each before displaying to a user. - repeated int32 span = 2 [packed=true]; - - // TODO(kenton): Record comments appearing before and after the - // declaration. - } -} diff --git a/src/core/Akka.Persistence/protos/tutorial/addressbook.proto b/src/core/Akka.Persistence/protos/tutorial/addressbook.proto deleted file mode 100644 index 5abe35ce39b..00000000000 --- a/src/core/Akka.Persistence/protos/tutorial/addressbook.proto +++ /dev/null @@ -1,31 +0,0 @@ -package tutorial; - -import "google/protobuf/csharp_options.proto"; -option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; -option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; - -option optimize_for = SPEED; - -message Person { - required string name = 1; - required int32 id = 2; // Unique ID number for this person. - optional string email = 3; - - enum PhoneType { - MOBILE = 0; - HOME = 1; - WORK = 2; - } - - message PhoneNumber { - required string number = 1; - optional PhoneType type = 2 [default = HOME]; - } - - repeated PhoneNumber phone = 4; -} - -// Our address book file is just one of these. -message AddressBook { - repeated Person person = 1; -} diff --git a/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj b/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj index 47cbd7c306b..f524ad54eda 100644 --- a/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj +++ b/src/core/Akka.Remote.TestKit.Tests/Akka.Remote.TestKit.Tests.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ v4.5 512 ..\..\ - bbb6736c + true + + true @@ -32,9 +35,28 @@ 4 + + ..\..\packages\Helios.1.4.1\lib\net45\Helios.dll + True + + + ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + - + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -68,12 +90,21 @@ - + - + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\packages\Helios\lib\net40\Helios.NET40.dll - True - True - - - - - - - ..\..\..\packages\Helios\lib\net45\Helios.dll - True - True - - - - - - - - - ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit.Tests/app.config b/src/core/Akka.Remote.TestKit.Tests/app.config new file mode 100644 index 00000000000..f0bd3189cf4 --- /dev/null +++ b/src/core/Akka.Remote.TestKit.Tests/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit.Tests/packages.config b/src/core/Akka.Remote.TestKit.Tests/packages.config new file mode 100644 index 00000000000..a56f6ab0c95 --- /dev/null +++ b/src/core/Akka.Remote.TestKit.Tests/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit.Tests/paket.references b/src/core/Akka.Remote.TestKit.Tests/paket.references deleted file mode 100644 index aef171068ca..00000000000 --- a/src/core/Akka.Remote.TestKit.Tests/paket.references +++ /dev/null @@ -1,5 +0,0 @@ -Helios -System.Collections.Immutable -group Test -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj index 04cbe2f76eb..df76ce64f86 100644 --- a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj +++ b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj @@ -14,7 +14,8 @@ 512 ..\..\ true - 439bf89e + + true @@ -35,27 +36,42 @@ bin\Release\Akka.Remote.TestKit.xml - - True - - - True - - - True - - - True - - - True - - - True - + + False + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll + True + + + False + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + + + False + ..\..\packages\Helios.1.4.1\lib\net45\Helios.dll + True + + + False + ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + True + + + ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + + + False + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -79,6 +95,7 @@ + @@ -109,7 +126,18 @@ - + + + + + + + + + + + + @@ -130,7 +158,15 @@ - + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll - True - True - - - - - - - - - ..\..\..\packages\Helios\lib\net40\Helios.NET40.dll - True - True - - - - - - - ..\..\..\packages\Helios\lib\net45\Helios.dll - True - True - - - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - True - True - - - - - - - - - ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/app.config b/src/core/Akka.Remote.TestKit/app.config new file mode 100644 index 00000000000..f0bd3189cf4 --- /dev/null +++ b/src/core/Akka.Remote.TestKit/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/packages.config b/src/core/Akka.Remote.TestKit/packages.config new file mode 100644 index 00000000000..d425f928973 --- /dev/null +++ b/src/core/Akka.Remote.TestKit/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.TestKit/paket.references b/src/core/Akka.Remote.TestKit/paket.references deleted file mode 100644 index f29ac52b610..00000000000 --- a/src/core/Akka.Remote.TestKit/paket.references +++ /dev/null @@ -1,7 +0,0 @@ -Google.ProtocolBuffers -Helios -System.Collections.Immutable -Newtonsoft.Json -group Test -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj b/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj index ca24d57a292..e3ed929fd23 100644 --- a/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj +++ b/src/core/Akka.Remote.Tests.MultiNode/Akka.Remote.Tests.MultiNode.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ v4.5 512 ..\..\ - 39dbaf16 + true + + true @@ -33,12 +36,28 @@ + + ..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -77,12 +96,21 @@ - + - + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests.MultiNode/app.config b/src/core/Akka.Remote.Tests.MultiNode/app.config new file mode 100644 index 00000000000..f0bd3189cf4 --- /dev/null +++ b/src/core/Akka.Remote.Tests.MultiNode/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests.MultiNode/packages.config b/src/core/Akka.Remote.Tests.MultiNode/packages.config new file mode 100644 index 00000000000..15502b4d7f9 --- /dev/null +++ b/src/core/Akka.Remote.Tests.MultiNode/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests.MultiNode/paket.references b/src/core/Akka.Remote.Tests.MultiNode/paket.references deleted file mode 100644 index 311dd9d2427..00000000000 --- a/src/core/Akka.Remote.Tests.MultiNode/paket.references +++ /dev/null @@ -1,7 +0,0 @@ -System.Collections.Immutable - -group Test -xunit.abstractions -xunit.assert -xunit.core -xunit.extensibility.core \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj index 562732f4c6c..50ed318b920 100644 --- a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj +++ b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -11,7 +12,9 @@ v4.5 512 ..\..\ - 338f57d2 + true + + true @@ -52,25 +55,32 @@ false - - True - - - True - - - True - - - True - - - True - - - True - + + False + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll + True + + + False + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + + + False + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + False + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + False + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -78,6 +88,7 @@ + @@ -124,11 +135,19 @@ - + + + + + + + + + @@ -149,6 +168,7 @@ + - @@ -349,4 +368,10 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/app.config b/src/core/Akka.Remote.Tests/app.config index 012b4e29c9d..a01ef9c6f2d 100644 --- a/src/core/Akka.Remote.Tests/app.config +++ b/src/core/Akka.Remote.Tests/app.config @@ -1,151 +1,11 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/packages.config b/src/core/Akka.Remote.Tests/packages.config new file mode 100644 index 00000000000..33c0ad1013c --- /dev/null +++ b/src/core/Akka.Remote.Tests/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/paket.references b/src/core/Akka.Remote.Tests/paket.references deleted file mode 100644 index a94200f76e5..00000000000 --- a/src/core/Akka.Remote.Tests/paket.references +++ /dev/null @@ -1,4 +0,0 @@ -Google.ProtocolBuffers -group Test -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Remote/Akka.Remote.csproj b/src/core/Akka.Remote/Akka.Remote.csproj index e0e44254cee..a4ce051cd81 100644 --- a/src/core/Akka.Remote/Akka.Remote.csproj +++ b/src/core/Akka.Remote/Akka.Remote.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\ + true true @@ -68,6 +69,17 @@ True + + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll + + + ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.Serialization.dll + + + False + ..\..\packages\Helios.1.4.1\lib\net45\Helios.dll + True + @@ -123,7 +135,7 @@ - + @@ -132,6 +144,7 @@ + - + diff --git a/src/core/Akka.Remote/CHANGES.txt b/src/core/Akka.Remote/CHANGES.txt deleted file mode 100644 index d80368c78f2..00000000000 --- a/src/core/Akka.Remote/CHANGES.txt +++ /dev/null @@ -1,99 +0,0 @@ -=============================================================================== -Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet -(skeet@pobox.com) based on the work of many talented people. - -For more information about this port, visit its homepage: -http://protobuf-csharp-port.googlecode.com - -For more information about Protocol Buffers in general, visit the project page -for the C++, Java and Python project: -http://protobuf.googlecode.com -=============================================================================== -RELEASE NOTES - Version 2.4.1.473 -=============================================================================== - -Features: -- Added option service_generator_type to control service generation with - NONE, GENERIC, INTERFACE, or IRPCDISPATCH -- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking - services and implementations. -- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the - location of protoc.exe. -- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow - custom implementation of writers with both speed and size optimizations. -- Addition of the "Google.ProtoBuffers.Serialization" assembly to support - reading and writing messages to/from XML, JSON, IDictionary<,> and others. -- Several performance related fixes and tweeks -- Issue 3: Add option to mark generated code with attribute -- Issue 20: Support for decorating classes [Serializable] -- Issue 21: Decorate fields with [deprecated=true] as [System.Obsolete] -- Issue 22: Reusable Builder classes -- Issue 24: Support for using Json/Xml formats with ICodedInputStream -- Issue 25: Added support for NuGet packages -- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1 - -Fixes: -- Issue 13: Message with Field same name as message causes uncompilable .cs -- Issue 16: Does not integrate well with other tooling -- Issue 19: Support for negative enum values -- Issue 26: AddRange in GeneratedBuilder iterates twice. -- Issue 27: Remove XML documentation output from test projects to clear - warnings/errors. -- Issue 28: Circular message dependencies result in null default values for - Message fields. -- Issue 29: Message classes generated have a public default constructor. You - can disable private ctor generation with the option generate_private_ctor. -- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \ -- Big-endian support for float, and double on Silverlight -- Packed and Unpacked parsing allow for all repeated, as per version 2.3 -- Fix for leaving Builder a public ctor on internal classes for use with - generic "where T: new()" constraints. - -Other: -- Changed the code signing key to a privately held key -- Reformatted all code and line-endings to C# defaults -- Reworking of performance benchmarks to produce reliable results, option /v2 -- Issue 34: Silverlight assemblies are now unit tested - -=============================================================================== -RELEASE NOTES - Version 2.3.0.277 -=============================================================================== - -Features: -- Added cls_compliance option to generate attributes indicating - non-CLS-compliance. -- Added file_extension option to control the generated output file's extension. -- Added umbrella_namespace option to place the umbrella class into a nested - namespace to address issues with proto files having the same name as a - message it contains. -- Added output_directory option to set the output path for the source file(s). -- Added ignore_google_protobuf option to avoid generating code for includes - from the google.protobuf package. -- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to - generate code with "option optimize_for = LITE_RUNTIME;". -- Added ability to invoke protoc.exe from within ProtoGen.exe. -- Upgraded to protoc.exe (2.3) compiler. - -Fixes: -- Issue 9: Class cannot be static and sealed error -- Issue 12: default value for enumerate fields must be filled out - -Other: -- Rewrite of build using MSBbuild instead of NAnt -- Moved to NUnit Version 2.2.8.0 -- Changed to using secure .snk for releases - -=============================================================================== -RELEASE NOTES - Version 0.9.1 -=============================================================================== - -Fixes: -- issue 10: Incorrect encoding of packed fields when serialized - -=============================================================================== -RELEASE NOTES - Version 0.9.0 -=============================================================================== - -- Initial release - -=============================================================================== \ No newline at end of file diff --git a/src/core/Akka.Remote/app.config b/src/core/Akka.Remote/app.config index 3db760888d4..a01ef9c6f2d 100644 --- a/src/core/Akka.Remote/app.config +++ b/src/core/Akka.Remote/app.config @@ -1,159 +1,11 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote/licenses/license.txt b/src/core/Akka.Remote/licenses/license.txt deleted file mode 100644 index b8e773b2e05..00000000000 --- a/src/core/Akka.Remote/licenses/license.txt +++ /dev/null @@ -1,31 +0,0 @@ -Protocol Buffers - Google's data interchange format -Copyright 2008-2010 Google Inc. All rights reserved. -http://github.com/jskeet/dotnet-protobufs/ -Original C++/Java/Python code: -http://code.google.com/p/protobuf/ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/Akka.Remote/licenses/protoc-license.txt b/src/core/Akka.Remote/licenses/protoc-license.txt deleted file mode 100644 index c779cb0e1ed..00000000000 --- a/src/core/Akka.Remote/licenses/protoc-license.txt +++ /dev/null @@ -1,36 +0,0 @@ -protoc.exe was built from the original source at http://code.google.com/p/protobuf/ -The licence for this code is as follows: - -Copyright 2008, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Code generated by the Protocol Buffer compiler is owned by the owner -of the input file used when generating it. This code is not -standalone and requires a support library to be linked with it. This -support library is itself covered by the above license. \ No newline at end of file diff --git a/src/core/Akka.Remote/packages.config b/src/core/Akka.Remote/packages.config new file mode 100644 index 00000000000..59ca935b9db --- /dev/null +++ b/src/core/Akka.Remote/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/core/Akka.Remote/paket.references b/src/core/Akka.Remote/paket.references deleted file mode 100644 index b0ac4e292a0..00000000000 --- a/src/core/Akka.Remote/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -Google.ProtocolBuffers -Helios \ No newline at end of file diff --git a/src/core/Akka.Remote/protos/google/protobuf/csharp_options.proto b/src/core/Akka.Remote/protos/google/protobuf/csharp_options.proto deleted file mode 100644 index 152df766f03..00000000000 --- a/src/core/Akka.Remote/protos/google/protobuf/csharp_options.proto +++ /dev/null @@ -1,115 +0,0 @@ -// Extra options for C# generator - -import "google/protobuf/descriptor.proto"; - -package google.protobuf; - -message CSharpFileOptions { - - // Namespace for generated classes; defaults to the package. - optional string namespace = 1; - - // Name of the "umbrella" class used for metadata about all - // the messages within this file. Default is based on the name - // of the file. - optional string umbrella_classname = 2; - - // Whether classes should be public (true) or internal (false) - optional bool public_classes = 3 [default = true]; - - // Whether to generate a single file for everything within the - // .proto file (false), or one file per message (true). - // This option is not currently honored; please log a feature - // request if you really want it. - optional bool multiple_files = 4; - - // Whether to nest messages within a single umbrella class (true) - // or create the umbrella class as a peer, with messages as - // top-level classes in the namespace (false) - optional bool nest_classes = 5; - - // Generate appropriate support for Code Contracts - // (Ongoing; support should improve over time) - optional bool code_contracts = 6; - - // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" - // would generate files within [output directory]/Foo/Bar - optional bool expand_namespace_directories = 7; - - // Generate attributes indicating non-CLS-compliance - optional bool cls_compliance = 8 [default = true]; - - // Generate messages/builders with the [Serializable] attribute - optional bool add_serializable = 9 [default = false]; - - // Generates a private ctor for Message types - optional bool generate_private_ctor = 10 [default = true]; - - // The extension that should be appended to the umbrella_classname when creating files. - optional string file_extension = 221 [default = ".cs"]; - - // A nested namespace for the umbrella class. Helpful for name collisions caused by - // umbrella_classname conflicting with an existing type. This will be automatically - // set to 'Proto' if a collision is detected with types being generated. This value - // is ignored when nest_classes == true - optional string umbrella_namespace = 222; - - // The output path for the source file(s) generated - optional string output_directory = 223 [default = "."]; - - // Will ignore the type generations and remove dependencies for the descriptor proto - // files that declare their package to be "google.protobuf" - optional bool ignore_google_protobuf = 224 [default = false]; - - // Controls how services are generated, GENERIC is the deprecated original implementation - // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and - // implementations using the included Windows RPC interop libarary. - optional CSharpServiceType service_generator_type = 225 [default = NONE]; - - // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and - // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. - optional bool generated_code_attributes = 226 [default = false]; -} - -enum CSharpServiceType { - // Services are ignored by the generator - NONE = 0; - // Generates the original Java generic service implementations - GENERIC = 1; - // Generates an interface for the service and nothing else - INTERFACE = 2; - // Generates an interface for the service and client/server wrappers for the interface - IRPCDISPATCH = 3; -} - -extend FileOptions { - optional CSharpFileOptions csharp_file_options = 1000; -} - -extend FieldOptions { - optional CSharpFieldOptions csharp_field_options = 1000; -} - -message CSharpFieldOptions { - // Provides the ability to override the name of the property - // generated for this field. This is applied to all properties - // and methods to do with this field, including HasFoo, FooCount, - // FooList etc. - optional string property_name = 1; -} - -message CSharpServiceOptions { - optional string interface_id = 1; -} - -extend ServiceOptions { - optional CSharpServiceOptions csharp_service_options = 1000; -} - -message CSharpMethodOptions { - optional int32 dispatch_id = 1; -} - -extend MethodOptions { - optional CSharpMethodOptions csharp_method_options = 1000; -} \ No newline at end of file diff --git a/src/core/Akka.Remote/protos/google/protobuf/descriptor.proto b/src/core/Akka.Remote/protos/google/protobuf/descriptor.proto deleted file mode 100644 index 233f879410e..00000000000 --- a/src/core/Akka.Remote/protos/google/protobuf/descriptor.proto +++ /dev/null @@ -1,533 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. -// -// The messages in this file describe the definitions found in .proto files. -// A valid .proto file can be translated directly to a FileDescriptorProto -// without any other information (e.g. without reading its imports). - - - -package google.protobuf; -option java_package = "com.google.protobuf"; -option java_outer_classname = "DescriptorProtos"; - -// descriptor.proto must be optimized for speed because reflection-based -// algorithms don't work during bootstrapping. -option optimize_for = SPEED; - -// The protocol compiler can output a FileDescriptorSet containing the .proto -// files it parses. -message FileDescriptorSet { - repeated FileDescriptorProto file = 1; -} - -// Describes a complete .proto file. -message FileDescriptorProto { - optional string name = 1; // file name, relative to root of source tree - optional string package = 2; // e.g. "foo", "foo.bar", etc. - - // Names of files imported by this file. - repeated string dependency = 3; - - // All top-level definitions in this file. - repeated DescriptorProto message_type = 4; - repeated EnumDescriptorProto enum_type = 5; - repeated ServiceDescriptorProto service = 6; - repeated FieldDescriptorProto extension = 7; - - optional FileOptions options = 8; - - // This field contains optional information about the original source code. - // You may safely remove this entire field whithout harming runtime - // functionality of the descriptors -- the information is needed only by - // development tools. - optional SourceCodeInfo source_code_info = 9; -} - -// Describes a message type. -message DescriptorProto { - optional string name = 1; - - repeated FieldDescriptorProto field = 2; - repeated FieldDescriptorProto extension = 6; - - repeated DescriptorProto nested_type = 3; - repeated EnumDescriptorProto enum_type = 4; - - message ExtensionRange { - optional int32 start = 1; - optional int32 end = 2; - } - repeated ExtensionRange extension_range = 5; - - optional MessageOptions options = 7; -} - -// Describes a field within a message. -message FieldDescriptorProto { - enum Type { - // 0 is reserved for errors. - // Order is weird for historical reasons. - TYPE_DOUBLE = 1; - TYPE_FLOAT = 2; - TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT64 if negative - // values are likely. - TYPE_UINT64 = 4; - TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers - // take 10 bytes. Use TYPE_SINT32 if negative - // values are likely. - TYPE_FIXED64 = 6; - TYPE_FIXED32 = 7; - TYPE_BOOL = 8; - TYPE_STRING = 9; - TYPE_GROUP = 10; // Tag-delimited aggregate. - TYPE_MESSAGE = 11; // Length-delimited aggregate. - - // New in version 2. - TYPE_BYTES = 12; - TYPE_UINT32 = 13; - TYPE_ENUM = 14; - TYPE_SFIXED32 = 15; - TYPE_SFIXED64 = 16; - TYPE_SINT32 = 17; // Uses ZigZag encoding. - TYPE_SINT64 = 18; // Uses ZigZag encoding. - }; - - enum Label { - // 0 is reserved for errors - LABEL_OPTIONAL = 1; - LABEL_REQUIRED = 2; - LABEL_REPEATED = 3; - // TODO(sanjay): Should we add LABEL_MAP? - }; - - optional string name = 1; - optional int32 number = 3; - optional Label label = 4; - - // If type_name is set, this need not be set. If both this and type_name - // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. - optional Type type = 5; - - // For message and enum types, this is the name of the type. If the name - // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping - // rules are used to find the type (i.e. first the nested types within this - // message are searched, then within the parent, on up to the root - // namespace). - optional string type_name = 6; - - // For extensions, this is the name of the type being extended. It is - // resolved in the same manner as type_name. - optional string extendee = 2; - - // For numeric types, contains the original text representation of the value. - // For booleans, "true" or "false". - // For strings, contains the default text contents (not escaped in any way). - // For bytes, contains the C escaped value. All bytes >= 128 are escaped. - // TODO(kenton): Base-64 encode? - optional string default_value = 7; - - optional FieldOptions options = 8; -} - -// Describes an enum type. -message EnumDescriptorProto { - optional string name = 1; - - repeated EnumValueDescriptorProto value = 2; - - optional EnumOptions options = 3; -} - -// Describes a value within an enum. -message EnumValueDescriptorProto { - optional string name = 1; - optional int32 number = 2; - - optional EnumValueOptions options = 3; -} - -// Describes a service. -message ServiceDescriptorProto { - optional string name = 1; - repeated MethodDescriptorProto method = 2; - - optional ServiceOptions options = 3; -} - -// Describes a method of a service. -message MethodDescriptorProto { - optional string name = 1; - - // Input and output type names. These are resolved in the same way as - // FieldDescriptorProto.type_name, but must refer to a message type. - optional string input_type = 2; - optional string output_type = 3; - - optional MethodOptions options = 4; -} - -// =================================================================== -// Options - -// Each of the definitions above may have "options" attached. These are -// just annotations which may cause code to be generated slightly differently -// or may contain hints for code that manipulates protocol messages. -// -// Clients may define custom options as extensions of the *Options messages. -// These extensions may not yet be known at parsing time, so the parser cannot -// store the values in them. Instead it stores them in a field in the *Options -// message called uninterpreted_option. This field must have the same name -// across all *Options messages. We then use this field to populate the -// extensions when we build a descriptor, at which point all protos have been -// parsed and so all extensions are known. -// -// Extension numbers for custom options may be chosen as follows: -// * For options which will only be used within a single application or -// organization, or for experimental options, use field numbers 50000 -// through 99999. It is up to you to ensure that you do not use the -// same number for multiple options. -// * For options which will be published and used publicly by multiple -// independent entities, e-mail kenton@google.com to reserve extension -// numbers. Simply tell me how many you need and I'll send you back a -// set of numbers to use -- there's no need to explain how you intend to -// use them. If this turns out to be popular, a web service will be set up -// to automatically assign option numbers. - - -message FileOptions { - - // Sets the Java package where classes generated from this .proto will be - // placed. By default, the proto package is used, but this is often - // inappropriate because proto packages do not normally start with backwards - // domain names. - optional string java_package = 1; - - - // If set, all the classes from the .proto file are wrapped in a single - // outer class with the given name. This applies to both Proto1 - // (equivalent to the old "--one_java_file" option) and Proto2 (where - // a .proto always translates to a single class, but you may want to - // explicitly choose the class name). - optional string java_outer_classname = 8; - - // If set true, then the Java code generator will generate a separate .java - // file for each top-level message, enum, and service defined in the .proto - // file. Thus, these types will *not* be nested inside the outer class - // named by java_outer_classname. However, the outer class will still be - // generated to contain the file's getDescriptor() method as well as any - // top-level extensions defined in the file. - optional bool java_multiple_files = 10 [default=false]; - - // If set true, then the Java code generator will generate equals() and - // hashCode() methods for all messages defined in the .proto file. This is - // purely a speed optimization, as the AbstractMessage base class includes - // reflection-based implementations of these methods. - optional bool java_generate_equals_and_hash = 20 [default=false]; - - // Generated classes can be optimized for speed or code size. - enum OptimizeMode { - SPEED = 1; // Generate complete code for parsing, serialization, - // etc. - CODE_SIZE = 2; // Use ReflectionOps to implement these methods. - LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. - } - optional OptimizeMode optimize_for = 9 [default=SPEED]; - - - - - // Should generic services be generated in each language? "Generic" services - // are not specific to any particular RPC system. They are generated by the - // main code generators in each language (without additional plugins). - // Generic services were the only kind of service generation supported by - // early versions of proto2. - // - // Generic services are now considered deprecated in favor of using plugins - // that generate code specific to your particular RPC system. Therefore, - // these default to false. Old code which depends on generic services should - // explicitly set them to true. - optional bool cc_generic_services = 16 [default=false]; - optional bool java_generic_services = 17 [default=false]; - optional bool py_generic_services = 18 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MessageOptions { - // Set true to use the old proto1 MessageSet wire format for extensions. - // This is provided for backwards-compatibility with the MessageSet wire - // format. You should not use this for any other reason: It's less - // efficient, has fewer features, and is more complicated. - // - // The message must be defined exactly as follows: - // message Foo { - // option message_set_wire_format = true; - // extensions 4 to max; - // } - // Note that the message cannot have any defined fields; MessageSets only - // have extensions. - // - // All extensions of your type must be singular messages; e.g. they cannot - // be int32s, enums, or repeated messages. - // - // Because this is an option, the above two restrictions are not enforced by - // the protocol compiler. - optional bool message_set_wire_format = 1 [default=false]; - - // Disables the generation of the standard "descriptor()" accessor, which can - // conflict with a field of the same name. This is meant to make migration - // from proto1 easier; new code should avoid fields named "descriptor". - optional bool no_standard_descriptor_accessor = 2 [default=false]; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message FieldOptions { - // The ctype option instructs the C++ code generator to use a different - // representation of the field than it normally would. See the specific - // options below. This option is not yet implemented in the open source - // release -- sorry, we'll try to include it in a future version! - optional CType ctype = 1 [default = STRING]; - enum CType { - // Default mode. - STRING = 0; - - CORD = 1; - - STRING_PIECE = 2; - } - // The packed option can be enabled for repeated primitive fields to enable - // a more efficient representation on the wire. Rather than repeatedly - // writing the tag and type for each element, the entire array is encoded as - // a single length-delimited blob. - optional bool packed = 2; - - - // Is this field deprecated? - // Depending on the target platform, this can emit Deprecated annotations - // for accessors, or it will be completely ignored; in the very least, this - // is a formalization for deprecating fields. - optional bool deprecated = 3 [default=false]; - - // EXPERIMENTAL. DO NOT USE. - // For "map" fields, the name of the field in the enclosed type that - // is the key for this map. For example, suppose we have: - // message Item { - // required string name = 1; - // required string value = 2; - // } - // message Config { - // repeated Item items = 1 [experimental_map_key="name"]; - // } - // In this situation, the map key for Item will be set to "name". - // TODO: Fully-implement this, then remove the "experimental_" prefix. - optional string experimental_map_key = 9; - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumOptions { - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message EnumValueOptions { - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message ServiceOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -message MethodOptions { - - // Note: Field numbers 1 through 32 are reserved for Google's internal RPC - // framework. We apologize for hoarding these numbers to ourselves, but - // we were already using them long before we decided to release Protocol - // Buffers. - - // The parser stores options it doesn't recognize here. See above. - repeated UninterpretedOption uninterpreted_option = 999; - - // Clients can define custom options in extensions of this message. See above. - extensions 1000 to max; -} - -// A message representing a option the parser does not recognize. This only -// appears in options protos created by the compiler::Parser class. -// DescriptorPool resolves these when building Descriptor objects. Therefore, -// options protos in descriptor objects (e.g. returned by Descriptor::options(), -// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions -// in them. -message UninterpretedOption { - // The name of the uninterpreted option. Each string represents a segment in - // a dot-separated name. is_extension is true iff a segment represents an - // extension (denoted with parentheses in options specs in .proto files). - // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents - // "foo.(bar.baz).qux". - message NamePart { - required string name_part = 1; - required bool is_extension = 2; - } - repeated NamePart name = 2; - - // The value of the uninterpreted option, in whatever type the tokenizer - // identified it as during parsing. Exactly one of these should be set. - optional string identifier_value = 3; - optional uint64 positive_int_value = 4; - optional int64 negative_int_value = 5; - optional double double_value = 6; - optional bytes string_value = 7; - optional string aggregate_value = 8; -} - -// =================================================================== -// Optional source code info - -// Encapsulates information about the original source file from which a -// FileDescriptorProto was generated. -message SourceCodeInfo { - // A Location identifies a piece of source code in a .proto file which - // corresponds to a particular definition. This information is intended - // to be useful to IDEs, code indexers, documentation generators, and similar - // tools. - // - // For example, say we have a file like: - // message Foo { - // optional string foo = 1; - // } - // Let's look at just the field definition: - // optional string foo = 1; - // ^ ^^ ^^ ^ ^^^ - // a bc de f ghi - // We have the following locations: - // span path represents - // [a,i) [ 4, 0, 2, 0 ] The whole field definition. - // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). - // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). - // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). - // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). - // - // Notes: - // - A location may refer to a repeated field itself (i.e. not to any - // particular index within it). This is used whenever a set of elements are - // logically enclosed in a single code segment. For example, an entire - // extend block (possibly containing multiple extension definitions) will - // have an outer location whose path refers to the "extensions" repeated - // field without an index. - // - Multiple locations may have the same path. This happens when a single - // logical declaration is spread out across multiple places. The most - // obvious example is the "extend" block again -- there may be multiple - // extend blocks in the same scope, each of which will have the same path. - // - A location's span is not always a subset of its parent's span. For - // example, the "extendee" of an extension declaration appears at the - // beginning of the "extend" block and is shared by all extensions within - // the block. - // - Just because a location's span is a subset of some other location's span - // does not mean that it is a descendent. For example, a "group" defines - // both a type and a field in a single declaration. Thus, the locations - // corresponding to the type and field and their components will overlap. - // - Code which tries to interpret locations should probably be designed to - // ignore those that it doesn't understand, as more types of locations could - // be recorded in the future. - repeated Location location = 1; - message Location { - // Identifies which part of the FileDescriptorProto was defined at this - // location. - // - // Each element is a field number or an index. They form a path from - // the root FileDescriptorProto to the place where the definition. For - // example, this path: - // [ 4, 3, 2, 7, 1 ] - // refers to: - // file.message_type(3) // 4, 3 - // .field(7) // 2, 7 - // .name() // 1 - // This is because FileDescriptorProto.message_type has field number 4: - // repeated DescriptorProto message_type = 4; - // and DescriptorProto.field has field number 2: - // repeated FieldDescriptorProto field = 2; - // and FieldDescriptorProto.name has field number 1: - // optional string name = 1; - // - // Thus, the above path gives the location of a field name. If we removed - // the last element: - // [ 4, 3, 2, 7 ] - // this path refers to the whole field declaration (from the beginning - // of the label to the terminating semicolon). - repeated int32 path = 1 [packed=true]; - - // Always has exactly three or four elements: start line, start column, - // end line (optional, otherwise assumed same as start line), end column. - // These are packed into a single field for efficiency. Note that line - // and column numbers are zero-based -- typically you will want to add - // 1 to each before displaying to a user. - repeated int32 span = 2 [packed=true]; - - // TODO(kenton): Record comments appearing before and after the - // declaration. - } -} diff --git a/src/core/Akka.Remote/protos/tutorial/addressbook.proto b/src/core/Akka.Remote/protos/tutorial/addressbook.proto deleted file mode 100644 index 5abe35ce39b..00000000000 --- a/src/core/Akka.Remote/protos/tutorial/addressbook.proto +++ /dev/null @@ -1,31 +0,0 @@ -package tutorial; - -import "google/protobuf/csharp_options.proto"; -option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; -option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; - -option optimize_for = SPEED; - -message Person { - required string name = 1; - required int32 id = 2; // Unique ID number for this person. - optional string email = 3; - - enum PhoneType { - MOBILE = 0; - HOME = 1; - WORK = 2; - } - - message PhoneNumber { - required string number = 1; - optional PhoneType type = 2 [default = HOME]; - } - - repeated PhoneNumber phone = 4; -} - -// Our address book file is just one of these. -message AddressBook { - repeated Person person = 1; -} diff --git a/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj b/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj index d559989b9ab..a371197b9ec 100644 --- a/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj +++ b/src/core/Akka.TestKit.Tests/Akka.TestKit.Tests.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -11,7 +12,9 @@ v4.5 512 ..\..\ - 71eec8b3 + true + + true @@ -32,6 +35,18 @@ + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -39,6 +54,7 @@ + @@ -99,7 +115,7 @@ - + @@ -121,6 +137,14 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.TestKit.Tests/packages.config b/src/core/Akka.TestKit.Tests/packages.config new file mode 100644 index 00000000000..3109db107fb --- /dev/null +++ b/src/core/Akka.TestKit.Tests/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.TestKit.Tests/paket.references b/src/core/Akka.TestKit.Tests/paket.references deleted file mode 100644 index f1e55442a7e..00000000000 --- a/src/core/Akka.TestKit.Tests/paket.references +++ /dev/null @@ -1,3 +0,0 @@ -group Test -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.TestKit/Akka.TestKit.csproj b/src/core/Akka.TestKit/Akka.TestKit.csproj index dda406a5efa..21e25311a7b 100644 --- a/src/core/Akka.TestKit/Akka.TestKit.csproj +++ b/src/core/Akka.TestKit/Akka.TestKit.csproj @@ -62,6 +62,7 @@ + @@ -145,6 +146,7 @@ + TextTemplatingFileGenerator diff --git a/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj b/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj index 2447a50e155..40c5822ac6f 100644 --- a/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj +++ b/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ v4.5 512 ..\..\ - 39789108 + true + + true @@ -37,6 +40,18 @@ + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -51,7 +66,7 @@ - + @@ -69,6 +84,14 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Tests.Shared.Internals/packages.config b/src/core/Akka.Tests.Shared.Internals/packages.config new file mode 100644 index 00000000000..3109db107fb --- /dev/null +++ b/src/core/Akka.Tests.Shared.Internals/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Tests.Shared.Internals/paket.references b/src/core/Akka.Tests.Shared.Internals/paket.references deleted file mode 100644 index f1e55442a7e..00000000000 --- a/src/core/Akka.Tests.Shared.Internals/paket.references +++ /dev/null @@ -1,3 +0,0 @@ -group Test -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka.Tests/Akka.Tests.csproj b/src/core/Akka.Tests/Akka.Tests.csproj index 90ce68cabf6..130e568c8d7 100644 --- a/src/core/Akka.Tests/Akka.Tests.csproj +++ b/src/core/Akka.Tests/Akka.Tests.csproj @@ -1,5 +1,7 @@  + + Debug AnyCPU @@ -11,7 +13,9 @@ v4.5 512 ..\..\ - 1318f3e8 + true + + true @@ -52,11 +56,43 @@ false + + ..\..\packages\fastJSON.2.0.27.1\lib\net40\fastjson.dll + True + + + ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.dll + True + + + ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.Core.dll + True + + + ..\..\packages\FsCheck.2.0.5\lib\net45\FsCheck.dll + True + + + ..\..\packages\FSharp.Core.3.1.2.5\lib\net40\FSharp.Core.dll + True + + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + @@ -64,6 +100,7 @@ + @@ -178,11 +215,13 @@ Always - + + + @@ -203,6 +242,14 @@ + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - True - True - - - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\win8\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\win8\FluentAssertions.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\net40\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\net40\FluentAssertions.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\net45\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\net45\FluentAssertions.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\sl5\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\sl5\FluentAssertions.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\sl5\Microsoft.CSharp.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\sl5\Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\wp8\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\wp8\FluentAssertions.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\portable-monotouch+monoandroid+xamarin.ios\FluentAssertions.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\portable-win81+wpa81\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\portable-win81+wpa81\FluentAssertions.dll - True - True - - - - - - - ..\..\..\packages\test\FluentAssertions\lib\portable-net40+sl5+win8+wp8+wpa81\FluentAssertions.Core.dll - True - True - - - ..\..\..\packages\test\FluentAssertions\lib\portable-net40+sl5+win8+wp8+wpa81\FluentAssertions.dll - True - True - - - - - - - - - ..\..\..\packages\test\FsCheck\lib\net45\FsCheck.dll - True - True - - - - - - - ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45\FsCheck.dll - True - True - - - - - - - ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45+wp8\FsCheck.dll - True - True - - - - - - - ..\..\..\packages\test\FsCheck\lib\portable-net45+netcore45+wpa81+wp8\FsCheck.dll - True - True - - - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\net20\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\net40\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\portable-net45+monoandroid10+monotouch10+xamarinios10\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\portable-net45+sl5+netcore45\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45+wp8\FSharp.Core.dll - True - True - - - - - - - ..\..\..\packages\test\FSharp.Core\lib\portable-net45+netcore45+wpa81+wp8\FSharp.Core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Tests/App.config b/src/core/Akka.Tests/App.config index 84d31f6d694..886d119fefe 100644 --- a/src/core/Akka.Tests/App.config +++ b/src/core/Akka.Tests/App.config @@ -1,4 +1,4 @@ - +
@@ -24,149 +24,4 @@ ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/core/Akka.Tests/TestUtils/Comparable.cs b/src/core/Akka.Tests/TestUtils/Comparable.cs index 2a824c27c90..bd1c47f0362 100644 --- a/src/core/Akka.Tests/TestUtils/Comparable.cs +++ b/src/core/Akka.Tests/TestUtils/Comparable.cs @@ -5,8 +5,6 @@ // //----------------------------------------------------------------------- -using Newtonsoft.Json; - namespace Akka.Tests.TestUtils { public class Comparable @@ -25,7 +23,7 @@ public override int GetHashCode() public override string ToString() { - var res = JsonConvert.SerializeObject(this); + var res = fastJSON.JSON.Instance.ToJSON(this); return res; } } diff --git a/src/core/Akka.Tests/packages.config b/src/core/Akka.Tests/packages.config new file mode 100644 index 00000000000..09bb0a85065 --- /dev/null +++ b/src/core/Akka.Tests/packages.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/Akka.Tests/paket.references b/src/core/Akka.Tests/paket.references deleted file mode 100644 index b802fa0b5c0..00000000000 --- a/src/core/Akka.Tests/paket.references +++ /dev/null @@ -1,7 +0,0 @@ -Newtonsoft.Json - -group Test -FluentAssertions -FsCheck -xunit.core -xunit.assert \ No newline at end of file diff --git a/src/core/Akka/Akka.csproj b/src/core/Akka/Akka.csproj index 052e93c0ae5..ed1868443db 100644 --- a/src/core/Akka/Akka.csproj +++ b/src/core/Akka/Akka.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\ + true true @@ -53,11 +54,19 @@ false + + False + ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + + ..\..\packages\Wire.0.0.4\lib\Wire.dll + True + @@ -368,7 +377,7 @@ - + @@ -376,7 +385,9 @@ Always + + - + diff --git a/src/core/Akka/packages.config b/src/core/Akka/packages.config new file mode 100644 index 00000000000..d601d5faa6e --- /dev/null +++ b/src/core/Akka/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/core/Akka/paket.references b/src/core/Akka/paket.references deleted file mode 100644 index 03830501c65..00000000000 --- a/src/core/Akka/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -Newtonsoft.Json -Wire \ No newline at end of file diff --git a/src/examples/Chat/ChatClient/App.config b/src/examples/Chat/ChatClient/App.config index 2c2edeeba16..dd008ecefcc 100644 --- a/src/examples/Chat/ChatClient/App.config +++ b/src/examples/Chat/ChatClient/App.config @@ -5,159 +5,16 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/Chat/ChatMessages/ChatMessages.csproj b/src/examples/Chat/ChatMessages/ChatMessages.csproj index 359c93b1cd0..bb36171c085 100644 --- a/src/examples/Chat/ChatMessages/ChatMessages.csproj +++ b/src/examples/Chat/ChatMessages/ChatMessages.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,7 +13,9 @@ v4.5 512 ..\..\..\ - ac874559 + true + + true @@ -53,28 +56,48 @@ false + + ..\..\..\packages\fastJSON.2.0.27.1\lib\net40\fastjson.dll + True + - - ..\..\..\packages\fastJSON.2.0.27.1\lib\net40\fastjson.dll + + ..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True - - - {5DEDDF90-37F0-48D3-A0B0-A5CBD8A7E377} Akka + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\test\xunit\lib\net20\xunit.dll - True - True - - - - \ No newline at end of file diff --git a/src/examples/Chat/ChatMessages/packages.config b/src/examples/Chat/ChatMessages/packages.config new file mode 100644 index 00000000000..fda430cff2d --- /dev/null +++ b/src/examples/Chat/ChatMessages/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/examples/Chat/ChatMessages/paket.references b/src/examples/Chat/ChatMessages/paket.references deleted file mode 100644 index 4bf78cf8fea..00000000000 --- a/src/examples/Chat/ChatMessages/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -group Test -xunit \ No newline at end of file diff --git a/src/examples/Chat/ChatServer/App.config b/src/examples/Chat/ChatServer/App.config index 2c2edeeba16..dd008ecefcc 100644 --- a/src/examples/Chat/ChatServer/App.config +++ b/src/examples/Chat/ChatServer/App.config @@ -5,159 +5,16 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config index 61fb7b251d8..ac5cd466feb 100644 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/App.config @@ -1,4 +1,4 @@ - +
@@ -33,157 +33,4 @@ ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj index fd2e90c81ee..286cd23f4a4 100644 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/Samples.Cluster.Transformation.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\..\ + true AnyCPU @@ -34,6 +35,10 @@ + + ..\..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + @@ -47,7 +52,7 @@ - + @@ -60,6 +65,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - True - - - - \ No newline at end of file diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/packages.config b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/packages.config new file mode 100644 index 00000000000..8a2bcdbc2dd --- /dev/null +++ b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/paket.references b/src/examples/Cluster/Roles/Samples.Cluster.Transformation/paket.references deleted file mode 100644 index 1bfbdbed4d6..00000000000 --- a/src/examples/Cluster/Roles/Samples.Cluster.Transformation/paket.references +++ /dev/null @@ -1 +0,0 @@ -System.Collections.Immutable \ No newline at end of file diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config index 193c2a22e74..0fa1de829b9 100644 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/App.config @@ -1,4 +1,4 @@ - +
@@ -34,157 +34,4 @@ ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj index c26bc14b252..4314cc9a1fa 100644 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/Samples.Cluster.ConsistentHashRouting.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\..\ + true AnyCPU @@ -34,6 +35,10 @@ + + ..\..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + @@ -47,7 +52,7 @@ - + @@ -64,6 +69,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - True - - - - \ No newline at end of file diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/packages.config b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/packages.config new file mode 100644 index 00000000000..8a2bcdbc2dd --- /dev/null +++ b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/paket.references b/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/paket.references deleted file mode 100644 index 1bfbdbed4d6..00000000000 --- a/src/examples/Cluster/Routing/Samples.Cluster.ConsistentHashRouting/paket.references +++ /dev/null @@ -1 +0,0 @@ -System.Collections.Immutable \ No newline at end of file diff --git a/src/examples/Cluster/Samples.Cluster.Simple/App.config b/src/examples/Cluster/Samples.Cluster.Simple/App.config index 72f33902f02..702c085578b 100644 --- a/src/examples/Cluster/Samples.Cluster.Simple/App.config +++ b/src/examples/Cluster/Samples.Cluster.Simple/App.config @@ -1,4 +1,4 @@ - +
@@ -33,157 +33,4 @@ ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj b/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj index 96f7e7ef7c2..1b142a16c8e 100644 --- a/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj +++ b/src/examples/Cluster/Samples.Cluster.Simple/Samples.Cluster.Simple.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true AnyCPU @@ -34,6 +35,10 @@ + + ..\..\..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + @@ -46,7 +51,7 @@ - + @@ -63,6 +68,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - True - - - - \ No newline at end of file diff --git a/src/examples/Cluster/Samples.Cluster.Simple/packages.config b/src/examples/Cluster/Samples.Cluster.Simple/packages.config new file mode 100644 index 00000000000..8a2bcdbc2dd --- /dev/null +++ b/src/examples/Cluster/Samples.Cluster.Simple/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/examples/Cluster/Samples.Cluster.Simple/paket.references b/src/examples/Cluster/Samples.Cluster.Simple/paket.references deleted file mode 100644 index 1bfbdbed4d6..00000000000 --- a/src/examples/Cluster/Samples.Cluster.Simple/paket.references +++ /dev/null @@ -1 +0,0 @@ -System.Collections.Immutable \ No newline at end of file diff --git a/src/examples/FSharp.Api/App.config b/src/examples/FSharp.Api/App.config index 2e989121800..a338d00a376 100644 --- a/src/examples/FSharp.Api/App.config +++ b/src/examples/FSharp.Api/App.config @@ -4,159 +4,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/examples/FSharp.Api/FSharp.Api.fsproj b/src/examples/FSharp.Api/FSharp.Api.fsproj index 2a92d343bf9..1ea6a1d9451 100644 --- a/src/examples/FSharp.Api/FSharp.Api.fsproj +++ b/src/examples/FSharp.Api/FSharp.Api.fsproj @@ -13,6 +13,7 @@ 4.3.1.0 FSharp.Api ..\..\ + true true @@ -76,16 +77,27 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - + + + ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + True + @@ -108,7 +120,7 @@ --> - + diff --git a/src/examples/FSharp.Api/packages.config b/src/examples/FSharp.Api/packages.config new file mode 100644 index 00000000000..505e58836ba --- /dev/null +++ b/src/examples/FSharp.Api/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/examples/FSharp.Api/paket.references b/src/examples/FSharp.Api/paket.references deleted file mode 100644 index 03830501c65..00000000000 --- a/src/examples/FSharp.Api/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -Newtonsoft.Json -Wire \ No newline at end of file diff --git a/src/examples/FSharp.Deploy.Local/App.config b/src/examples/FSharp.Deploy.Local/App.config index 2e989121800..a338d00a376 100644 --- a/src/examples/FSharp.Deploy.Local/App.config +++ b/src/examples/FSharp.Deploy.Local/App.config @@ -4,159 +4,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/examples/FSharp.Deploy.Remote/App.config b/src/examples/FSharp.Deploy.Remote/App.config index 2e989121800..a338d00a376 100644 --- a/src/examples/FSharp.Deploy.Remote/App.config +++ b/src/examples/FSharp.Deploy.Remote/App.config @@ -4,159 +4,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/examples/FaultTolerance/App.config b/src/examples/FaultTolerance/App.config index e28ac54bd91..8e15646352e 100644 --- a/src/examples/FaultTolerance/App.config +++ b/src/examples/FaultTolerance/App.config @@ -1,159 +1,6 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/examples/FaultTolerance/FaultTolerance.csproj b/src/examples/FaultTolerance/FaultTolerance.csproj index 6cf2d93482d..e7b7753e67b 100644 --- a/src/examples/FaultTolerance/FaultTolerance.csproj +++ b/src/examples/FaultTolerance/FaultTolerance.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\ + true AnyCPU @@ -33,6 +34,10 @@ 4 + + False + ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + @@ -43,7 +48,7 @@ - + @@ -52,6 +57,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - True - True - - - - \ No newline at end of file diff --git a/src/examples/FaultTolerance/packages.config b/src/examples/FaultTolerance/packages.config new file mode 100644 index 00000000000..505e58836ba --- /dev/null +++ b/src/examples/FaultTolerance/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/examples/FaultTolerance/paket.references b/src/examples/FaultTolerance/paket.references deleted file mode 100644 index 1063d003b92..00000000000 --- a/src/examples/FaultTolerance/paket.references +++ /dev/null @@ -1 +0,0 @@ -Newtonsoft.Json \ No newline at end of file diff --git a/src/examples/HelloWorld/FSharp.HelloAkka/App.config b/src/examples/HelloWorld/FSharp.HelloAkka/App.config index 2e989121800..a338d00a376 100644 --- a/src/examples/HelloWorld/FSharp.HelloAkka/App.config +++ b/src/examples/HelloWorld/FSharp.HelloAkka/App.config @@ -4,159 +4,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/examples/HelloWorld/HelloAkka/App.config b/src/examples/HelloWorld/HelloAkka/App.config index e28ac54bd91..8e15646352e 100644 --- a/src/examples/HelloWorld/HelloAkka/App.config +++ b/src/examples/HelloWorld/HelloAkka/App.config @@ -1,159 +1,6 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/examples/PersistenceExample.FsApi/App.config b/src/examples/PersistenceExample.FsApi/App.config index 2e989121800..a338d00a376 100644 --- a/src/examples/PersistenceExample.FsApi/App.config +++ b/src/examples/PersistenceExample.FsApi/App.config @@ -4,159 +4,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/examples/PersistenceExample.FsApi/PersistenceExample.FsApi.fsproj b/src/examples/PersistenceExample.FsApi/PersistenceExample.FsApi.fsproj index 443bd1e5416..9f66e90a0b1 100644 --- a/src/examples/PersistenceExample.FsApi/PersistenceExample.FsApi.fsproj +++ b/src/examples/PersistenceExample.FsApi/PersistenceExample.FsApi.fsproj @@ -13,6 +13,7 @@ 4.3.1.0 PersistenceExample.FsApi ..\ + true true @@ -53,13 +54,24 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - + + + ..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + True + @@ -90,61 +102,4 @@ --> - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - True - True - - - - \ No newline at end of file diff --git a/src/examples/PersistenceExample.FsApi/packages.config b/src/examples/PersistenceExample.FsApi/packages.config new file mode 100644 index 00000000000..505e58836ba --- /dev/null +++ b/src/examples/PersistenceExample.FsApi/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/examples/PersistenceExample.FsApi/paket.references b/src/examples/PersistenceExample.FsApi/paket.references deleted file mode 100644 index 1063d003b92..00000000000 --- a/src/examples/PersistenceExample.FsApi/paket.references +++ /dev/null @@ -1 +0,0 @@ -Newtonsoft.Json \ No newline at end of file diff --git a/src/examples/PersistenceExample/App.config b/src/examples/PersistenceExample/App.config index e28ac54bd91..8e15646352e 100644 --- a/src/examples/PersistenceExample/App.config +++ b/src/examples/PersistenceExample/App.config @@ -1,159 +1,6 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/examples/RemoteDeploy/System1/App.config b/src/examples/RemoteDeploy/System1/App.config index 8961a671524..a2dd99c6b4c 100644 --- a/src/examples/RemoteDeploy/System1/App.config +++ b/src/examples/RemoteDeploy/System1/App.config @@ -4,159 +4,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/src/examples/RemoteDeploy/System1/System1.csproj b/src/examples/RemoteDeploy/System1/System1.csproj index 17496aea8be..3dcf4fc5dc1 100644 --- a/src/examples/RemoteDeploy/System1/System1.csproj +++ b/src/examples/RemoteDeploy/System1/System1.csproj @@ -1,4 +1,4 @@ - + @@ -83,6 +83,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - True - True - - - - - - - - - ..\..\..\..\packages\qdfeed\lib\net35\QDFeedParser.dll - True - True - - - - - - - ..\..\..\..\packages\qdfeed\lib\net45\QDFeedParser.dll - True - True - - - - - - - ..\..\..\..\packages\qdfeed\lib\sl40\QDFeedParser.Silverlight.dll - True - True - - - - - - - ..\..\..\..\packages\qdfeed\lib\wp71\QDFeedParser.Mobile.dll - True - True - - - - - - - ..\..\..\..\packages\qdfeed\lib\windowsphone8\QDFeedParser.Mobile.dll - True - True - - - - - - - - - ..\..\..\..\packages\System.Collections.Immutable\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll - True - True - - - - \ No newline at end of file diff --git a/src/examples/Stocks/SymbolLookup/packages.config b/src/examples/Stocks/SymbolLookup/packages.config new file mode 100644 index 00000000000..6aa2a478aed --- /dev/null +++ b/src/examples/Stocks/SymbolLookup/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/examples/Stocks/SymbolLookup/paket.references b/src/examples/Stocks/SymbolLookup/paket.references deleted file mode 100644 index 2f15ac5d44d..00000000000 --- a/src/examples/Stocks/SymbolLookup/paket.references +++ /dev/null @@ -1,3 +0,0 @@ -Newtonsoft.Json -System.Collections.Immutable -qdfeed \ No newline at end of file diff --git a/src/examples/TcpEchoService.Server/App.config b/src/examples/TcpEchoService.Server/App.config index e28ac54bd91..8e15646352e 100644 --- a/src/examples/TcpEchoService.Server/App.config +++ b/src/examples/TcpEchoService.Server/App.config @@ -1,159 +1,6 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeClient/App.config b/src/examples/TimeServer/TimeClient/App.config index ebd328d8d80..b8c84fb9a0c 100644 --- a/src/examples/TimeServer/TimeClient/App.config +++ b/src/examples/TimeServer/TimeClient/App.config @@ -1,4 +1,4 @@ - +
@@ -52,157 +52,4 @@ ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeClient/TimeClient.csproj b/src/examples/TimeServer/TimeClient/TimeClient.csproj index 1e5e4a75b30..ac2cc61fe08 100644 --- a/src/examples/TimeServer/TimeClient/TimeClient.csproj +++ b/src/examples/TimeServer/TimeClient/TimeClient.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true AnyCPU @@ -33,6 +34,10 @@ 4 + + ..\..\..\packages\Helios.1.4.1\lib\net45\Helios.dll + True + @@ -43,7 +48,7 @@ - + @@ -56,6 +61,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\Helios\lib\net40\Helios.NET40.dll - True - True - - - - - - - ..\..\..\..\packages\Helios\lib\net45\Helios.dll - True - True - - - - \ No newline at end of file diff --git a/src/examples/TimeServer/TimeClient/packages.config b/src/examples/TimeServer/TimeClient/packages.config new file mode 100644 index 00000000000..04c0607cbc1 --- /dev/null +++ b/src/examples/TimeServer/TimeClient/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeClient/paket.references b/src/examples/TimeServer/TimeClient/paket.references deleted file mode 100644 index c3d91cab15d..00000000000 --- a/src/examples/TimeServer/TimeClient/paket.references +++ /dev/null @@ -1 +0,0 @@ -Helios \ No newline at end of file diff --git a/src/examples/TimeServer/TimeServer/App.config b/src/examples/TimeServer/TimeServer/App.config index 36b9693ef4f..be06f62e62c 100644 --- a/src/examples/TimeServer/TimeServer/App.config +++ b/src/examples/TimeServer/TimeServer/App.config @@ -1,4 +1,4 @@ - +
@@ -52,157 +52,4 @@ ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeServer/TimeServer.csproj b/src/examples/TimeServer/TimeServer/TimeServer.csproj index 67f61bd3137..19662bafc96 100644 --- a/src/examples/TimeServer/TimeServer/TimeServer.csproj +++ b/src/examples/TimeServer/TimeServer/TimeServer.csproj @@ -12,6 +12,7 @@ v4.5 512 ..\..\..\ + true AnyCPU @@ -33,6 +34,10 @@ 4 + + False + ..\..\..\packages\Helios.1.4.1\lib\net45\Helios.dll + @@ -43,7 +48,7 @@ - + @@ -56,6 +61,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - - - - - - ..\..\..\..\packages\Helios\lib\net40\Helios.NET40.dll - True - True - - - - - - - ..\..\..\..\packages\Helios\lib\net45\Helios.dll - True - True - - - - \ No newline at end of file diff --git a/src/examples/TimeServer/TimeServer/packages.config b/src/examples/TimeServer/TimeServer/packages.config new file mode 100644 index 00000000000..04c0607cbc1 --- /dev/null +++ b/src/examples/TimeServer/TimeServer/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/examples/TimeServer/TimeServer/paket.references b/src/examples/TimeServer/TimeServer/paket.references deleted file mode 100644 index c3d91cab15d..00000000000 --- a/src/examples/TimeServer/TimeServer/paket.references +++ /dev/null @@ -1 +0,0 @@ -Helios \ No newline at end of file From b0ac559aed14028aed2d355b4f3b86bb6836a859 Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Fri, 27 Nov 2015 15:57:12 +0400 Subject: [PATCH 094/105] #1464 added RemoteConsistentHashingRouterSpec --- .../Akka.Remote.Tests.csproj | 4 ++ .../RemoteConsistentHashingRouterSpec.cs | 50 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/core/Akka.Remote.Tests/RemoteConsistentHashingRouterSpec.cs diff --git a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj index 50ed318b920..6c97b63bec3 100644 --- a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj +++ b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj @@ -55,6 +55,9 @@ false + + ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.dll + False ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll @@ -100,6 +103,7 @@ + diff --git a/src/core/Akka.Remote.Tests/RemoteConsistentHashingRouterSpec.cs b/src/core/Akka.Remote.Tests/RemoteConsistentHashingRouterSpec.cs new file mode 100644 index 00000000000..08c76abd4f6 --- /dev/null +++ b/src/core/Akka.Remote.Tests/RemoteConsistentHashingRouterSpec.cs @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System.Collections.Generic; +using System.Linq; +using Akka.Actor; +using Akka.Routing; +using Akka.TestKit; +using FluentAssertions; +using Xunit; + +namespace Akka.Remote.Tests +{ + + public class RemoteConsistentHashingRouterSpec : AkkaSpec + { + + public RemoteConsistentHashingRouterSpec() + : base(@"akka.actor.provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""") + { + + } + + [Fact] + public void ConsistentHashingGroup_must_use_same_hash_ring_indepenent_of_self_address() + { + // simulating running router on two different nodes (a1, a2) with target routees on 3 other nodes (s1, s2, s3) + var a1 = new Address("akka.tcp", "Sys", "client1", 2552); + var a2 = new Address("akka.tcp", "Sys", "client2", 2552); + var s1 = new ActorSelectionRoutee(Sys.ActorSelection("akka.tcp://Sys@server1:2552/user/a/b")); + var s2 = new ActorSelectionRoutee(Sys.ActorSelection("akka.tcp://Sys@server2:2552/user/a/b")); + var s3 = new ActorSelectionRoutee(Sys.ActorSelection("akka.tcp://Sys@server3:2552/user/a/b")); + var nodes1 = new List(new [] { new ConsistentRoutee(s1, a1), new ConsistentRoutee(s2, a1), new ConsistentRoutee(s3, a1)}); + var nodes2 = + new List(new[] + {new ConsistentRoutee(s1, a2), new ConsistentRoutee(s2, a2), new ConsistentRoutee(s3, a2)}); + var consistentHash1 = ConsistentHash.Create(nodes1, 10); + var consistentHash2 = ConsistentHash.Create(nodes2, 10); + var keys = new List(new [] { "A", "B", "C", "D", "E", "F", "G"}); + var result1 = keys.Select(k => consistentHash1.NodeFor(k).Routee); + var result2 = keys.Select(k => consistentHash2.NodeFor(k).Routee); + result1.ShouldBeEquivalentTo(result2); + } + } +} + From 913b098a3956074260ad17689a566282b13da112 Mon Sep 17 00:00:00 2001 From: rogeralsing Date: Sun, 29 Nov 2015 10:37:45 +0100 Subject: [PATCH 095/105] aaaaa --- src/core/Akka/Akka.csproj | 68 --------------------------------------- 1 file changed, 68 deletions(-) diff --git a/src/core/Akka/Akka.csproj b/src/core/Akka/Akka.csproj index ed1868443db..086c63447f7 100644 --- a/src/core/Akka/Akka.csproj +++ b/src/core/Akka/Akka.csproj @@ -395,72 +395,4 @@ --> - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - True - True - - - - - - - - - ..\..\..\packages\Wire\lib\Wire.dll - True - True - - - - \ No newline at end of file From 17542e918d776fa0540dd4efecbea874e92a1678 Mon Sep 17 00:00:00 2001 From: rogeralsing Date: Sun, 29 Nov 2015 10:55:23 +0100 Subject: [PATCH 096/105] remove paket madness 2 --- .../Akka.Persistence/Akka.Persistence.csproj | 133 ------------------ 1 file changed, 133 deletions(-) diff --git a/src/core/Akka.Persistence/Akka.Persistence.csproj b/src/core/Akka.Persistence/Akka.Persistence.csproj index b035ce6cd76..1eddee4b7e7 100644 --- a/src/core/Akka.Persistence/Akka.Persistence.csproj +++ b/src/core/Akka.Persistence/Akka.Persistence.csproj @@ -33,24 +33,6 @@ bin\Release\Akka.Persistence.xml - - True - - - True - - - True - - - True - - - True - - - True - ..\..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll @@ -63,7 +45,6 @@ - @@ -131,118 +112,4 @@ --> - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll - True - True - - - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - True - True - - - - \ No newline at end of file From 7ace1db0981ee696553270e5f05b33c1e1c4d14f Mon Sep 17 00:00:00 2001 From: Jeff Cyr Date: Sun, 29 Nov 2015 15:21:53 -0500 Subject: [PATCH 097/105] ActorTaskScheduler refactoring --- .../Akka.Tests/Dispatch/AsyncAwaitSpec.cs | 157 ++++++++++++++++-- .../Akka/Actor/ActorCell.DefaultMessages.cs | 15 +- src/core/Akka/Actor/ActorCell.cs | 15 ++ src/core/Akka/Actor/PipeToSupport.cs | 5 +- src/core/Akka/Dispatch/ActorTaskScheduler.cs | 150 ++++++++--------- .../Akka/Dispatch/SysMsg/ISystemMessage.cs | 35 ++-- 6 files changed, 269 insertions(+), 108 deletions(-) diff --git a/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs b/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs index 53d49d538ed..7706e9e03cb 100644 --- a/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs +++ b/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs @@ -6,6 +6,7 @@ //----------------------------------------------------------------------- using System; +using System.Threading; using System.Threading.Tasks; using Akka.Actor; using Akka.TestKit; @@ -25,7 +26,7 @@ public ReceiveTimeoutAsyncActor() Receive(async s => { _replyTo = Sender; - + await Task.Delay(TimeSpan.FromMilliseconds(100)); SetReceiveTimeout(TimeSpan.FromMilliseconds(100)); }); @@ -35,7 +36,7 @@ class AsyncActor : ReceiveActor { public AsyncActor() { - Receive( async s => + Receive(async s => { await Task.Yield(); await Task.Delay(TimeSpan.FromMilliseconds(100)); @@ -210,9 +211,9 @@ public AsyncTplActor() Receive(m => { //this is also safe, all tasks complete in the actor context - RunTask(() => + RunTask(async () => { - Task.Delay(TimeSpan.FromSeconds(1)) + await Task.Delay(TimeSpan.FromSeconds(1)) .ContinueWith(t => { Sender.Tell("done"); }); }); }); @@ -228,11 +229,11 @@ public AsyncTplExceptionActor(IActorRef callback) _callback = callback; Receive(m => { - RunTask(() => + RunTask(async () => { - Task.Delay(TimeSpan.FromSeconds(1)) + await Task.Delay(TimeSpan.FromSeconds(1)) .ContinueWith(t => { throw new Exception("foo"); }); - }); + }); }); } @@ -243,6 +244,16 @@ protected override void PostRestart(Exception reason) } } + public class RestartMessage + { + public object Message { get; private set; } + + public RestartMessage(object message) + { + Message = message; + } + } + public class ActorAsyncAwaitSpec : AkkaSpec { [Fact] @@ -280,8 +291,8 @@ public async Task Actors_should_be_able_to_async_await_ask_message_loop() [Fact] public async Task Actors_should_be_able_to_block_ask_message_loop() { - var actor = Sys.ActorOf(Props.Create().WithDispatcher("akka.actor.task-dispatcher"),"Worker"); - var asker =Sys.ActorOf(Props.Create(() => new BlockingAsker(actor)).WithDispatcher("akka.actor.task-dispatcher"),"Asker"); + var actor = Sys.ActorOf(Props.Create().WithDispatcher("akka.actor.task-dispatcher"), "Worker"); + var asker = Sys.ActorOf(Props.Create(() => new BlockingAsker(actor)).WithDispatcher("akka.actor.task-dispatcher"), "Asker"); var task = asker.Ask("start", TimeSpan.FromSeconds(5)); actor.Tell(123, ActorRefs.NoSender); var res = await task; @@ -291,7 +302,7 @@ public async Task Actors_should_be_able_to_block_ask_message_loop() [Fact(Skip = "Maybe not possible to solve")] public async Task Actors_should_be_able_to_block_ask_self_message_loop() { - var asker = Sys.ActorOf(Props.Create(() => new BlockingAskSelf()),"Asker"); + var asker = Sys.ActorOf(Props.Create(() => new BlockingAskSelf()), "Asker"); var task = asker.Ask("start", TimeSpan.FromSeconds(5)); var res = await task; Assert.Equal("done", res); @@ -344,7 +355,6 @@ public async Task Actor_should_be_able_to_resume_suspend() res.ShouldBe("done"); } - [Fact] public void Actor_should_be_able_to_ReceiveTimeout_after_async_operation() { @@ -353,6 +363,131 @@ public void Actor_should_be_able_to_ReceiveTimeout_after_async_operation() actor.Tell("hello"); ExpectMsg(m => m == "GotIt"); } + + public class AsyncExceptionCatcherActor : ReceiveActor + { + private string _lastMessage; + + public AsyncExceptionCatcherActor() + { + Receive(async m => + { + _lastMessage = m; + try + { + // Throw an exception in the ActorTaskScheduler + await Task.Factory.StartNew(() => + { + throw new Exception("should not restart"); + }); + } + catch (Exception) + { + } + }); + + Receive(_ => Sender.Tell(_lastMessage, Self)); + } + } + + [Fact] + public async Task Actor_should_not_restart_if_exception_is_catched() + { + var actor = Sys.ActorOf(); + + actor.Tell("hello"); + + var lastMessage = await actor.Ask(123); + + lastMessage.ShouldBe("hello"); + } + + public class AsyncFailingActor : ReceiveActor + { + public AsyncFailingActor() + { + Receive(async m => + { + ThrowException(); + }); + } + + protected override void PreRestart(Exception reason, object message) + { + Sender.Tell(new RestartMessage(message), Self); + + base.PreRestart(reason, message); + } + + private static void ThrowException() + { + throw new Exception("foo"); + } + } + + [Fact] + public void Actor_PreRestart_should_give_the_failing_message() + { + var actor = Sys.ActorOf(); + + actor.Tell("hello"); + + ExpectMsg(m => "hello".Equals(m.Message)); + } + + public class AsyncPipeToDelayActor : ReceiveActor + { + public AsyncPipeToDelayActor() + { + Receive(async msg => + { + Task.Run(() => + { + Thread.Sleep(10); + return msg; + }).PipeTo(Sender, Self); //LogicalContext is lost?!? + + Thread.Sleep(3000); + }); + } + } + + public class AsyncReentrantActor : ReceiveActor + { + public AsyncReentrantActor() + { + Receive(async msg => + { + var sender = Sender; + Task.Run(() => + { + //Sleep to make sure the task is not completed when ContinueWith is called + Thread.Sleep(100); + return msg; + }).ContinueWith(_ => sender.Tell(msg)); // ContinueWith will schedule with the implicit ActorTaskScheduler + + Thread.Sleep(3000); + }); + } + } + + [Fact] + public void ActorTaskScheduler_reentrancy_should_not_be_possible() + { + var actor = Sys.ActorOf(); + actor.Tell("hello"); + + ExpectNoMsg(1000); + } + + [Fact] + public void Actor_PipeTo_should_not_be_delayed_by_async_receive() + { + var actor = Sys.ActorOf(); + + actor.Tell("hello"); + ExpectMsg(m => "hello".Equals(m), TimeSpan.FromMilliseconds(1000)); + } } } diff --git a/src/core/Akka/Actor/ActorCell.DefaultMessages.cs b/src/core/Akka/Actor/ActorCell.DefaultMessages.cs index dc56e895449..50c1a4f12dd 100644 --- a/src/core/Akka/Actor/ActorCell.DefaultMessages.cs +++ b/src/core/Akka/Actor/ActorCell.DefaultMessages.cs @@ -165,7 +165,7 @@ public void SystemInvoke(Envelope envelope) { var m = envelope.Message; - if (m is CompleteTask) HandleCompleteTask(m as CompleteTask); + if (m is ActorTaskSchedulerMessage) HandleActorTaskSchedulerMessage(m as ActorTaskSchedulerMessage); else if (m is Failed) HandleFailed(m as Failed); else if (m is DeathWatchNotification) { @@ -203,12 +203,17 @@ public void SystemInvoke(Envelope envelope) } } - private void HandleCompleteTask(CompleteTask task) + private void HandleActorTaskSchedulerMessage(ActorTaskSchedulerMessage m) { - CurrentMessage = task.State.Message; - Sender = task.State.Sender; - task.SetResult(); + if (m.Exception != null) + { + HandleInvokeFailure(m.Exception); + return; + } + + m.ExecuteTask(); } + public void SwapMailbox(DeadLetterMailbox mailbox) { Mailbox.DebugPrint("{0} Swapping mailbox to DeadLetterMailbox", Self); diff --git a/src/core/Akka/Actor/ActorCell.cs b/src/core/Akka/Actor/ActorCell.cs index 40dfdfdc9f3..17f4fff635c 100644 --- a/src/core/Akka/Actor/ActorCell.cs +++ b/src/core/Akka/Actor/ActorCell.cs @@ -30,6 +30,7 @@ public partial class ActorCell : IUntypedActorContext, ICell private bool _actorHasBeenCleared; private Mailbox _mailbox; private readonly ActorSystemImpl _systemImpl; + private ActorTaskScheduler m_taskScheduler; public ActorCell(ActorSystemImpl system, IInternalActorRef self, Props props, MessageDispatcher dispatcher, IInternalActorRef parent) @@ -66,6 +67,20 @@ internal static ActorCell Current internal bool ActorHasBeenCleared { get { return _actorHasBeenCleared; } } internal static Props TerminatedProps { get { return terminatedProps; } } + public ActorTaskScheduler TaskScheduler + { + get + { + var taskScheduler = Volatile.Read(ref m_taskScheduler); + + if (taskScheduler != null) + return taskScheduler; + + taskScheduler = new ActorTaskScheduler(this); + return Interlocked.CompareExchange(ref m_taskScheduler, taskScheduler, null) ?? taskScheduler; + } + } + public void Init(bool sendSupervise, Func createMailbox /*, MailboxType mailboxType*/) //TODO: switch from Func createMailbox to MailboxType mailboxType { var mailbox = createMailbox(); //Akka: dispatcher.createMailbox(this, mailboxType) diff --git a/src/core/Akka/Actor/PipeToSupport.cs b/src/core/Akka/Actor/PipeToSupport.cs index ea1eb5cd79f..19ac16ed247 100644 --- a/src/core/Akka/Actor/PipeToSupport.cs +++ b/src/core/Akka/Actor/PipeToSupport.cs @@ -6,6 +6,7 @@ //----------------------------------------------------------------------- using System; +using System.Threading; using System.Threading.Tasks; namespace Akka.Actor @@ -33,7 +34,7 @@ public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActor recipient.Tell(success != null ? success(tresult.Result) : tresult.Result, sender); - }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); + }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); } /// @@ -47,7 +48,7 @@ public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActorRef se { if (tresult.IsCanceled || tresult.IsFaulted) recipient.Tell(new Status.Failure(tresult.Exception), sender); - }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); + }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); } } } diff --git a/src/core/Akka/Dispatch/ActorTaskScheduler.cs b/src/core/Akka/Dispatch/ActorTaskScheduler.cs index 550d664c496..7bc078d38b6 100644 --- a/src/core/Akka/Dispatch/ActorTaskScheduler.cs +++ b/src/core/Akka/Dispatch/ActorTaskScheduler.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; -using System.Runtime.Remoting.Messaging; using System.Threading; using System.Threading.Tasks; using Akka.Actor; @@ -15,29 +14,13 @@ namespace Akka.Dispatch { - public class AmbientState - { - public IActorRef Self { get; set; } - public IActorRef Sender { get; set; } - public object Message { get; set; } - } - public class ActorTaskScheduler : TaskScheduler { - public static readonly TaskScheduler Instance = new ActorTaskScheduler(); - public static readonly TaskFactory TaskFactory = new TaskFactory(Instance); - public static readonly string StateKey = "akka.state"; - private const string Faulted = "faulted"; - private static readonly object Outer = new object(); + private readonly ActorCell _actorCell; - public static void SetCurrentState(IActorRef self, IActorRef sender, object message) + internal ActorTaskScheduler(ActorCell actorCell) { - CallContext.LogicalSetData(StateKey, new AmbientState - { - Sender = sender, - Self = self, - Message = message - }); + _actorCell = actorCell; } protected override IEnumerable GetScheduledTasks() @@ -47,46 +30,44 @@ protected override IEnumerable GetScheduledTasks() protected override void QueueTask(Task task) { - var s = CallContext.LogicalGetData(StateKey) as AmbientState; - if (task.AsyncState == Outer || s == null) + if ((task.CreationOptions & TaskCreationOptions.LongRunning) == TaskCreationOptions.LongRunning) { - TryExecuteTask(task); + Thread t = new Thread(state => + { + ScheduleTask((Task)state); + }); + t.IsBackground = true; + t.Name = "ActorTaskScheduler LongRunning"; + t.Start(task); + return; } - //we get here if the task needs to be marshalled back to the mailbox - //e.g. if previous task was an IO completion - s = CallContext.LogicalGetData(StateKey) as AmbientState; - - s.Self.Tell(new CompleteTask(s, () => + // Schedule the task execution, run inline if we are already in the actor context. + if (ActorCell.Current == _actorCell) { - SetCurrentState(s.Self,s.Sender,s.Message); TryExecuteTask(task); - if (task.IsFaulted) - Rethrow(task, null); + } + else + { + ScheduleTask(task); + } + } - }), ActorRefs.NoSender); + private void ScheduleTask(Task task) + { + _actorCell.Self.Tell(new ActorTaskSchedulerMessage(this, task), ActorRefs.NoSender); } - protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) + internal void ExecuteTask(Task task) { - if (taskWasPreviouslyQueued) - return false; - - var s = CallContext.LogicalGetData(StateKey) as AmbientState; - var cell = ActorCell.Current; - - //Is the current cell and the current state the same? - if (cell != null && - s != null && - Equals(cell.Self, s.Self) && - Equals(cell.Sender, s.Sender) && - cell.CurrentMessage == s.Message) - { - var res = TryExecuteTask(task); - return res; - } + TryExecuteTask(task); + } + protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) + { + // Prevent inline execution, it will execute inline anyway in QueueTask if we + // are already in the actor context. return false; } @@ -99,47 +80,62 @@ public static void RunTask(Action action) }); } - public static void RunTask(Func action) + public static void RunTask(Func asyncAction) { var context = ActorCell.Current; + + if (context == null) + throw new InvalidOperationException("RunTask must be call from an actor context."); + var mailbox = context.Mailbox; //suspend the mailbox mailbox.Suspend(MailboxSuspendStatus.AwaitingTask); - SetCurrentState(context.Self, context.Sender, null); - - //wrap our action inside a task, so that everything executing - //directly or indirectly from the action is executed on our task scheduler + ActorTaskScheduler actorScheduler = context.TaskScheduler; + + Task.Factory.StartNew(() => asyncAction(), CancellationToken.None, TaskCreationOptions.None, actorScheduler) + .Unwrap() + .ContinueWith(parent => + { + Exception exception = GetTaskException(parent); + + if (exception == null) + { + mailbox.Resume(MailboxSuspendStatus.AwaitingTask); + context.CheckReceiveTimeout(); + } + else + { + context.Self.Tell(new ActorTaskSchedulerMessage(exception), ActorRefs.NoSender); + } + + }, actorScheduler); + } - Task.Factory.StartNew(async _ => + private static Exception GetTaskException(Task task) + { + switch (task.Status) { + case TaskStatus.Canceled: + return new TaskCanceledException(); + + case TaskStatus.Faulted: + return TryUnwrapAggregateException(task.Exception); + } - //start executing our action and potential promise style - //tasks - await action() - //we need to use ContinueWith so that any exception is - //thrown inside the actor context. - //this is needed for IO completion tasks that execute out of context - .ContinueWith( - Rethrow, - Faulted, - TaskContinuationOptions.None); - - //if mailbox was suspended, make sure we re-enable message processing again - mailbox.Resume(MailboxSuspendStatus.AwaitingTask); - context.CheckReceiveTimeout(); - }, - Outer, - CancellationToken.None, - TaskCreationOptions.None, - Instance); + return null; } - private static void Rethrow(Task x, object s) + private static Exception TryUnwrapAggregateException(AggregateException aggregateException) { - //this just rethrows the exception the task contains - x.Wait(); + if (aggregateException == null) + return null; + + if (aggregateException.InnerExceptions.Count == 1) + return aggregateException.InnerExceptions[0]; + + return aggregateException; } } } diff --git a/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs b/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs index b0b112b8395..0d6c66b80a5 100644 --- a/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs +++ b/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs @@ -243,30 +243,39 @@ public ActorTask(Task task) public Task Task { get; private set; } } - public sealed class CompleteTask : ISystemMessage + internal sealed class ActorTaskSchedulerMessage : ISystemMessage { + private readonly ActorTaskScheduler _scheduler; + private readonly Task _task; + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// - /// The action. - public CompleteTask(AmbientState state, Action action) + public ActorTaskSchedulerMessage(ActorTaskScheduler scheduler, Task task) { - State = state; - SetResult = action; + _scheduler = scheduler; + _task = task; } - public AmbientState State { get; private set; } - /// - /// Gets the set result. + /// Initializes a new instance of the class. /// - /// The set result. - public Action SetResult { get; private set; } + /// The exception. + public ActorTaskSchedulerMessage(Exception exception) + { + Exception = exception; + } + + public Exception Exception { get; private set; } + + public void ExecuteTask() + { + _scheduler.ExecuteTask(_task); + } public override string ToString() { - return "CompleteTask - AmbientState: " + State; + return ""; } } From e6b7702ba841bf864094cb3fbf5e6fa40db1dab2 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Sun, 29 Nov 2015 14:34:14 -0800 Subject: [PATCH 098/105] Revert "Actor task scheduler refactoring" --- .../Akka.Tests/Dispatch/AsyncAwaitSpec.cs | 157 ++---------------- .../Akka/Actor/ActorCell.DefaultMessages.cs | 15 +- src/core/Akka/Actor/ActorCell.cs | 15 -- src/core/Akka/Actor/PipeToSupport.cs | 5 +- src/core/Akka/Dispatch/ActorTaskScheduler.cs | 150 +++++++++-------- .../Akka/Dispatch/SysMsg/ISystemMessage.cs | 35 ++-- 6 files changed, 108 insertions(+), 269 deletions(-) diff --git a/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs b/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs index 7706e9e03cb..53d49d538ed 100644 --- a/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs +++ b/src/core/Akka.Tests/Dispatch/AsyncAwaitSpec.cs @@ -6,7 +6,6 @@ //----------------------------------------------------------------------- using System; -using System.Threading; using System.Threading.Tasks; using Akka.Actor; using Akka.TestKit; @@ -26,7 +25,7 @@ public ReceiveTimeoutAsyncActor() Receive(async s => { _replyTo = Sender; - + await Task.Delay(TimeSpan.FromMilliseconds(100)); SetReceiveTimeout(TimeSpan.FromMilliseconds(100)); }); @@ -36,7 +35,7 @@ class AsyncActor : ReceiveActor { public AsyncActor() { - Receive(async s => + Receive( async s => { await Task.Yield(); await Task.Delay(TimeSpan.FromMilliseconds(100)); @@ -211,9 +210,9 @@ public AsyncTplActor() Receive(m => { //this is also safe, all tasks complete in the actor context - RunTask(async () => + RunTask(() => { - await Task.Delay(TimeSpan.FromSeconds(1)) + Task.Delay(TimeSpan.FromSeconds(1)) .ContinueWith(t => { Sender.Tell("done"); }); }); }); @@ -229,11 +228,11 @@ public AsyncTplExceptionActor(IActorRef callback) _callback = callback; Receive(m => { - RunTask(async () => + RunTask(() => { - await Task.Delay(TimeSpan.FromSeconds(1)) + Task.Delay(TimeSpan.FromSeconds(1)) .ContinueWith(t => { throw new Exception("foo"); }); - }); + }); }); } @@ -244,16 +243,6 @@ protected override void PostRestart(Exception reason) } } - public class RestartMessage - { - public object Message { get; private set; } - - public RestartMessage(object message) - { - Message = message; - } - } - public class ActorAsyncAwaitSpec : AkkaSpec { [Fact] @@ -291,8 +280,8 @@ public async Task Actors_should_be_able_to_async_await_ask_message_loop() [Fact] public async Task Actors_should_be_able_to_block_ask_message_loop() { - var actor = Sys.ActorOf(Props.Create().WithDispatcher("akka.actor.task-dispatcher"), "Worker"); - var asker = Sys.ActorOf(Props.Create(() => new BlockingAsker(actor)).WithDispatcher("akka.actor.task-dispatcher"), "Asker"); + var actor = Sys.ActorOf(Props.Create().WithDispatcher("akka.actor.task-dispatcher"),"Worker"); + var asker =Sys.ActorOf(Props.Create(() => new BlockingAsker(actor)).WithDispatcher("akka.actor.task-dispatcher"),"Asker"); var task = asker.Ask("start", TimeSpan.FromSeconds(5)); actor.Tell(123, ActorRefs.NoSender); var res = await task; @@ -302,7 +291,7 @@ public async Task Actors_should_be_able_to_block_ask_message_loop() [Fact(Skip = "Maybe not possible to solve")] public async Task Actors_should_be_able_to_block_ask_self_message_loop() { - var asker = Sys.ActorOf(Props.Create(() => new BlockingAskSelf()), "Asker"); + var asker = Sys.ActorOf(Props.Create(() => new BlockingAskSelf()),"Asker"); var task = asker.Ask("start", TimeSpan.FromSeconds(5)); var res = await task; Assert.Equal("done", res); @@ -355,6 +344,7 @@ public async Task Actor_should_be_able_to_resume_suspend() res.ShouldBe("done"); } + [Fact] public void Actor_should_be_able_to_ReceiveTimeout_after_async_operation() { @@ -363,131 +353,6 @@ public void Actor_should_be_able_to_ReceiveTimeout_after_async_operation() actor.Tell("hello"); ExpectMsg(m => m == "GotIt"); } - - public class AsyncExceptionCatcherActor : ReceiveActor - { - private string _lastMessage; - - public AsyncExceptionCatcherActor() - { - Receive(async m => - { - _lastMessage = m; - try - { - // Throw an exception in the ActorTaskScheduler - await Task.Factory.StartNew(() => - { - throw new Exception("should not restart"); - }); - } - catch (Exception) - { - } - }); - - Receive(_ => Sender.Tell(_lastMessage, Self)); - } - } - - [Fact] - public async Task Actor_should_not_restart_if_exception_is_catched() - { - var actor = Sys.ActorOf(); - - actor.Tell("hello"); - - var lastMessage = await actor.Ask(123); - - lastMessage.ShouldBe("hello"); - } - - public class AsyncFailingActor : ReceiveActor - { - public AsyncFailingActor() - { - Receive(async m => - { - ThrowException(); - }); - } - - protected override void PreRestart(Exception reason, object message) - { - Sender.Tell(new RestartMessage(message), Self); - - base.PreRestart(reason, message); - } - - private static void ThrowException() - { - throw new Exception("foo"); - } - } - - [Fact] - public void Actor_PreRestart_should_give_the_failing_message() - { - var actor = Sys.ActorOf(); - - actor.Tell("hello"); - - ExpectMsg(m => "hello".Equals(m.Message)); - } - - public class AsyncPipeToDelayActor : ReceiveActor - { - public AsyncPipeToDelayActor() - { - Receive(async msg => - { - Task.Run(() => - { - Thread.Sleep(10); - return msg; - }).PipeTo(Sender, Self); //LogicalContext is lost?!? - - Thread.Sleep(3000); - }); - } - } - - public class AsyncReentrantActor : ReceiveActor - { - public AsyncReentrantActor() - { - Receive(async msg => - { - var sender = Sender; - Task.Run(() => - { - //Sleep to make sure the task is not completed when ContinueWith is called - Thread.Sleep(100); - return msg; - }).ContinueWith(_ => sender.Tell(msg)); // ContinueWith will schedule with the implicit ActorTaskScheduler - - Thread.Sleep(3000); - }); - } - } - - [Fact] - public void ActorTaskScheduler_reentrancy_should_not_be_possible() - { - var actor = Sys.ActorOf(); - actor.Tell("hello"); - - ExpectNoMsg(1000); - } - - [Fact] - public void Actor_PipeTo_should_not_be_delayed_by_async_receive() - { - var actor = Sys.ActorOf(); - - actor.Tell("hello"); - ExpectMsg(m => "hello".Equals(m), TimeSpan.FromMilliseconds(1000)); - } } } diff --git a/src/core/Akka/Actor/ActorCell.DefaultMessages.cs b/src/core/Akka/Actor/ActorCell.DefaultMessages.cs index 50c1a4f12dd..dc56e895449 100644 --- a/src/core/Akka/Actor/ActorCell.DefaultMessages.cs +++ b/src/core/Akka/Actor/ActorCell.DefaultMessages.cs @@ -165,7 +165,7 @@ public void SystemInvoke(Envelope envelope) { var m = envelope.Message; - if (m is ActorTaskSchedulerMessage) HandleActorTaskSchedulerMessage(m as ActorTaskSchedulerMessage); + if (m is CompleteTask) HandleCompleteTask(m as CompleteTask); else if (m is Failed) HandleFailed(m as Failed); else if (m is DeathWatchNotification) { @@ -203,17 +203,12 @@ public void SystemInvoke(Envelope envelope) } } - private void HandleActorTaskSchedulerMessage(ActorTaskSchedulerMessage m) + private void HandleCompleteTask(CompleteTask task) { - if (m.Exception != null) - { - HandleInvokeFailure(m.Exception); - return; - } - - m.ExecuteTask(); + CurrentMessage = task.State.Message; + Sender = task.State.Sender; + task.SetResult(); } - public void SwapMailbox(DeadLetterMailbox mailbox) { Mailbox.DebugPrint("{0} Swapping mailbox to DeadLetterMailbox", Self); diff --git a/src/core/Akka/Actor/ActorCell.cs b/src/core/Akka/Actor/ActorCell.cs index 17f4fff635c..40dfdfdc9f3 100644 --- a/src/core/Akka/Actor/ActorCell.cs +++ b/src/core/Akka/Actor/ActorCell.cs @@ -30,7 +30,6 @@ public partial class ActorCell : IUntypedActorContext, ICell private bool _actorHasBeenCleared; private Mailbox _mailbox; private readonly ActorSystemImpl _systemImpl; - private ActorTaskScheduler m_taskScheduler; public ActorCell(ActorSystemImpl system, IInternalActorRef self, Props props, MessageDispatcher dispatcher, IInternalActorRef parent) @@ -67,20 +66,6 @@ internal static ActorCell Current internal bool ActorHasBeenCleared { get { return _actorHasBeenCleared; } } internal static Props TerminatedProps { get { return terminatedProps; } } - public ActorTaskScheduler TaskScheduler - { - get - { - var taskScheduler = Volatile.Read(ref m_taskScheduler); - - if (taskScheduler != null) - return taskScheduler; - - taskScheduler = new ActorTaskScheduler(this); - return Interlocked.CompareExchange(ref m_taskScheduler, taskScheduler, null) ?? taskScheduler; - } - } - public void Init(bool sendSupervise, Func createMailbox /*, MailboxType mailboxType*/) //TODO: switch from Func createMailbox to MailboxType mailboxType { var mailbox = createMailbox(); //Akka: dispatcher.createMailbox(this, mailboxType) diff --git a/src/core/Akka/Actor/PipeToSupport.cs b/src/core/Akka/Actor/PipeToSupport.cs index 19ac16ed247..ea1eb5cd79f 100644 --- a/src/core/Akka/Actor/PipeToSupport.cs +++ b/src/core/Akka/Actor/PipeToSupport.cs @@ -6,7 +6,6 @@ //----------------------------------------------------------------------- using System; -using System.Threading; using System.Threading.Tasks; namespace Akka.Actor @@ -34,7 +33,7 @@ public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActor recipient.Tell(success != null ? success(tresult.Result) : tresult.Result, sender); - }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); + }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); } /// @@ -48,7 +47,7 @@ public static Task PipeTo(this Task taskToPipe, ICanTell recipient, IActorRef se { if (tresult.IsCanceled || tresult.IsFaulted) recipient.Tell(new Status.Failure(tresult.Exception), sender); - }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); + }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); } } } diff --git a/src/core/Akka/Dispatch/ActorTaskScheduler.cs b/src/core/Akka/Dispatch/ActorTaskScheduler.cs index 7bc078d38b6..550d664c496 100644 --- a/src/core/Akka/Dispatch/ActorTaskScheduler.cs +++ b/src/core/Akka/Dispatch/ActorTaskScheduler.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; +using System.Runtime.Remoting.Messaging; using System.Threading; using System.Threading.Tasks; using Akka.Actor; @@ -14,13 +15,29 @@ namespace Akka.Dispatch { + public class AmbientState + { + public IActorRef Self { get; set; } + public IActorRef Sender { get; set; } + public object Message { get; set; } + } + public class ActorTaskScheduler : TaskScheduler { - private readonly ActorCell _actorCell; + public static readonly TaskScheduler Instance = new ActorTaskScheduler(); + public static readonly TaskFactory TaskFactory = new TaskFactory(Instance); + public static readonly string StateKey = "akka.state"; + private const string Faulted = "faulted"; + private static readonly object Outer = new object(); - internal ActorTaskScheduler(ActorCell actorCell) + public static void SetCurrentState(IActorRef self, IActorRef sender, object message) { - _actorCell = actorCell; + CallContext.LogicalSetData(StateKey, new AmbientState + { + Sender = sender, + Self = self, + Message = message + }); } protected override IEnumerable GetScheduledTasks() @@ -30,44 +47,46 @@ protected override IEnumerable GetScheduledTasks() protected override void QueueTask(Task task) { - if ((task.CreationOptions & TaskCreationOptions.LongRunning) == TaskCreationOptions.LongRunning) + var s = CallContext.LogicalGetData(StateKey) as AmbientState; + if (task.AsyncState == Outer || s == null) { - Thread t = new Thread(state => - { - ScheduleTask((Task)state); - }); - t.IsBackground = true; - t.Name = "ActorTaskScheduler LongRunning"; - t.Start(task); - + TryExecuteTask(task); return; } - // Schedule the task execution, run inline if we are already in the actor context. - if (ActorCell.Current == _actorCell) + //we get here if the task needs to be marshalled back to the mailbox + //e.g. if previous task was an IO completion + s = CallContext.LogicalGetData(StateKey) as AmbientState; + + s.Self.Tell(new CompleteTask(s, () => { + SetCurrentState(s.Self,s.Sender,s.Message); TryExecuteTask(task); - } - else - { - ScheduleTask(task); - } - } + if (task.IsFaulted) + Rethrow(task, null); - private void ScheduleTask(Task task) - { - _actorCell.Self.Tell(new ActorTaskSchedulerMessage(this, task), ActorRefs.NoSender); - } - - internal void ExecuteTask(Task task) - { - TryExecuteTask(task); + }), ActorRefs.NoSender); } protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) { - // Prevent inline execution, it will execute inline anyway in QueueTask if we - // are already in the actor context. + if (taskWasPreviouslyQueued) + return false; + + var s = CallContext.LogicalGetData(StateKey) as AmbientState; + var cell = ActorCell.Current; + + //Is the current cell and the current state the same? + if (cell != null && + s != null && + Equals(cell.Self, s.Self) && + Equals(cell.Sender, s.Sender) && + cell.CurrentMessage == s.Message) + { + var res = TryExecuteTask(task); + return res; + } + return false; } @@ -80,62 +99,47 @@ public static void RunTask(Action action) }); } - public static void RunTask(Func asyncAction) + public static void RunTask(Func action) { var context = ActorCell.Current; - - if (context == null) - throw new InvalidOperationException("RunTask must be call from an actor context."); - var mailbox = context.Mailbox; //suspend the mailbox mailbox.Suspend(MailboxSuspendStatus.AwaitingTask); - ActorTaskScheduler actorScheduler = context.TaskScheduler; - - Task.Factory.StartNew(() => asyncAction(), CancellationToken.None, TaskCreationOptions.None, actorScheduler) - .Unwrap() - .ContinueWith(parent => - { - Exception exception = GetTaskException(parent); - - if (exception == null) - { - mailbox.Resume(MailboxSuspendStatus.AwaitingTask); - context.CheckReceiveTimeout(); - } - else - { - context.Self.Tell(new ActorTaskSchedulerMessage(exception), ActorRefs.NoSender); - } - - }, actorScheduler); - } + SetCurrentState(context.Self, context.Sender, null); - private static Exception GetTaskException(Task task) - { - switch (task.Status) - { - case TaskStatus.Canceled: - return new TaskCanceledException(); + //wrap our action inside a task, so that everything executing + //directly or indirectly from the action is executed on our task scheduler - case TaskStatus.Faulted: - return TryUnwrapAggregateException(task.Exception); - } + Task.Factory.StartNew(async _ => + { - return null; + //start executing our action and potential promise style + //tasks + await action() + //we need to use ContinueWith so that any exception is + //thrown inside the actor context. + //this is needed for IO completion tasks that execute out of context + .ContinueWith( + Rethrow, + Faulted, + TaskContinuationOptions.None); + + //if mailbox was suspended, make sure we re-enable message processing again + mailbox.Resume(MailboxSuspendStatus.AwaitingTask); + context.CheckReceiveTimeout(); + }, + Outer, + CancellationToken.None, + TaskCreationOptions.None, + Instance); } - private static Exception TryUnwrapAggregateException(AggregateException aggregateException) + private static void Rethrow(Task x, object s) { - if (aggregateException == null) - return null; - - if (aggregateException.InnerExceptions.Count == 1) - return aggregateException.InnerExceptions[0]; - - return aggregateException; + //this just rethrows the exception the task contains + x.Wait(); } } } diff --git a/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs b/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs index 0d6c66b80a5..b0b112b8395 100644 --- a/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs +++ b/src/core/Akka/Dispatch/SysMsg/ISystemMessage.cs @@ -243,39 +243,30 @@ public ActorTask(Task task) public Task Task { get; private set; } } - internal sealed class ActorTaskSchedulerMessage : ISystemMessage + public sealed class CompleteTask : ISystemMessage { - private readonly ActorTaskScheduler _scheduler; - private readonly Task _task; - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public ActorTaskSchedulerMessage(ActorTaskScheduler scheduler, Task task) + /// + /// The action. + public CompleteTask(AmbientState state, Action action) { - _scheduler = scheduler; - _task = task; + State = state; + SetResult = action; } + public AmbientState State { get; private set; } + /// - /// Initializes a new instance of the class. + /// Gets the set result. /// - /// The exception. - public ActorTaskSchedulerMessage(Exception exception) - { - Exception = exception; - } - - public Exception Exception { get; private set; } - - public void ExecuteTask() - { - _scheduler.ExecuteTask(_task); - } + /// The set result. + public Action SetResult { get; private set; } public override string ToString() { - return ""; + return "CompleteTask - AmbientState: " + State; } } From 4d1d79b568bdae6565423c3ed914f8a9606dc0e8 Mon Sep 17 00:00:00 2001 From: "maxim.salamatko" Date: Sat, 21 Nov 2015 08:37:25 +0400 Subject: [PATCH 099/105] #1416 created ReceiveActor implementation of AtLeastOnceDeliveryActor base class --- .../Akka.Persistence.Tests.csproj | 1 + .../AtLeastOnceDeliveryReceiveActorSpec.cs | 562 ++++++++++++++++++ .../AtLeastOnceDeliverySpec.cs | 11 +- .../Akka.Persistence/Akka.Persistence.csproj | 116 ++++ .../Akka.Persistence/AtLeastOnceDelivery.cs | 481 +++------------ .../AtLeastOnceDeliveryReceiveActor.cs | 164 +++++ .../AtLeastOnceDeliverySemantic.cs | 513 ++++++++++++++++ src/core/Akka.Persistence/Persistence.cs | 59 ++ 8 files changed, 1508 insertions(+), 399 deletions(-) create mode 100644 src/core/Akka.Persistence.Tests/AtLeastOnceDeliveryReceiveActorSpec.cs create mode 100644 src/core/Akka.Persistence/AtLeastOnceDeliveryReceiveActor.cs create mode 100644 src/core/Akka.Persistence/AtLeastOnceDeliverySemantic.cs diff --git a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj index 1e9f1591a8a..39c87ab7801 100644 --- a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj +++ b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj @@ -76,6 +76,7 @@ + diff --git a/src/core/Akka.Persistence.Tests/AtLeastOnceDeliveryReceiveActorSpec.cs b/src/core/Akka.Persistence.Tests/AtLeastOnceDeliveryReceiveActorSpec.cs new file mode 100644 index 00000000000..e1c312830d5 --- /dev/null +++ b/src/core/Akka.Persistence.Tests/AtLeastOnceDeliveryReceiveActorSpec.cs @@ -0,0 +1,562 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using Akka.Actor; +using Akka.Event; +using Akka.TestKit; +using Xunit; + +namespace Akka.Persistence.Tests +{ + public class AtLeastOnceDeliveryReceiveActorSpec : PersistenceSpec + { + #region internal test classes + + [Serializable] + private sealed class AcceptedReq : IEvt + { + public AcceptedReq(string payload, string destinationPath) + { + Payload = payload; + DestinationPath = destinationPath; + } + + public string Payload { get; private set; } + + //FIXME: change to Akka.Actor.ActorPath when serialization problems will be solved + public string DestinationPath { get; private set; } + } + + [Serializable] + private sealed class Action : IEquatable + { + public Action(long id, string payload) + { + Id = id; + Payload = payload; + } + + public long Id { get; private set; } + public string Payload { get; private set; } + + public bool Equals(Action other) + { + return Id == other.Id && string.Equals(Payload, other.Payload); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is Action && Equals((Action) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (Id.GetHashCode()*397) ^ (Payload != null ? Payload.GetHashCode() : 0); + } + } + } + + [Serializable] + private sealed class ActionAck : IEquatable + { + public ActionAck(long id) + { + Id = id; + } + + public long Id { get; private set; } + + public bool Equals(ActionAck other) + { + return other != null && other.Id == Id; + } + } + + [Serializable] + private sealed class Boom + { + public static readonly Boom Instance = new Boom(); + } + + private class Destination : ReceiveActor + { + private readonly ISet _allReceived; + + public Destination(IActorRef testActor) + { + _allReceived = new HashSet(); + Receive(a => + { + if (!_allReceived.Contains(a.Id)) + { + testActor.Tell(a); + + _allReceived.Add(a.Id); + } + Sender.Tell(new ActionAck(a.Id)); + }); + } + } + + private interface IEvt + { + } + + [Serializable] + private sealed class InvalidReq + { + public static readonly InvalidReq Instance = new InvalidReq(); + + private InvalidReq() + { + } + + public override bool Equals(object obj) + { + return obj is InvalidReq; + } + } + + internal class Receiver : AtLeastOnceDeliveryReceiveActor + { + private readonly IDictionary _destinations; + private readonly bool _isAsync; + private readonly ILoggingAdapter _log; + private readonly IActorRef _testActor; + private IActorRef _lastSnapshotAskedForBy; + private readonly string _name; + + public Receiver(IActorRef testActor, string name, TimeSpan redeliverInterval, int warn, + int redeliveryBurstLimit, bool isAsync, IDictionary destinations) + : base(new PersistenceSettings.AtLeastOnceDeliverySettings(redeliverInterval, redeliveryBurstLimit, warn, 100000)) + { + _testActor = testActor; + _name = name; + _isAsync = isAsync; + _destinations = destinations; + _log = Context.GetLogger(); + + + Command(req => + { + if (string.IsNullOrEmpty(req.Payload)) Sender.Tell(InvalidReq.Instance); + else + { + char c = char.ToUpper(req.Payload[0]); + ActorPath destination = _destinations[c.ToString()]; + if (_isAsync) + PersistAsync(new AcceptedReq(req.Payload, destination.ToString()), e => + { + UpdateState(e); + Sender.Tell(ReqAck.Instance); + }); + else + Persist(new AcceptedReq(req.Payload, destination.ToString()), e => + { + UpdateState(e); + Sender.Tell(ReqAck.Instance); + }); + } + }); + Command(ack => + { + _log.Debug("Sender got ack: {0}", ack.Id); + if (ConfirmDelivery(ack.Id)) + { + if (_isAsync) + { + PersistAsync(new ReqDone(ack.Id), UpdateState); + } + else + { + Persist(new ReqDone(ack.Id), UpdateState); + } + } + }); + + Command(boom => + { + _log.Debug("Boom!"); + throw new Exception("boom"); + }); + + Command(save => + { + _log.Debug("Save snapshot"); + _lastSnapshotAskedForBy = Sender; + SaveSnapshot(new Snap(GetDeliverySnapshot())); + }); + + + Command(succ => + { + _log.Debug("Save snapshot success!"); + if (_lastSnapshotAskedForBy != null) + _lastSnapshotAskedForBy.Tell(succ); + }); + + Command(unconfirmedWarn => + { + _log.Debug("Sender got unconfirmed warning: unconfirmed deliveries count {0}", + unconfirmedWarn.UnconfirmedDeliveries.Count()); + _testActor.Tell(unconfirmedWarn); + }); + + Recover(evt => UpdateState(evt)); + + Recover(o => + { + var snap = (Snap) o.Snapshot; + SetDeliverySnapshot(snap.DeliverySnapshot); + }); + } + + public override string PersistenceId + { + get { return _name; } + } + + + + private void UpdateState(IEvt evt) + { + evt.Match() + .With(a => + { + _log.Debug("Deliver(destination, deliveryId => Action(deliveryId, {0})), recovering: {1}", + a.Payload, IsRecovering); + Deliver(ActorPath.Parse(a.DestinationPath), deliveryId => new Action(deliveryId, a.Payload)); + }) + .With(r => + { + _log.Debug("ConfirmDelivery({0}), recovering: {1}", r.Id, IsRecovering); + ConfirmDelivery(r.Id); + }); + } + } + + [Serializable] + private sealed class Req + { + public Req(string payload) + { + Payload = payload; + } + + public string Payload { get; private set; } + } + + [Serializable] + private sealed class ReqAck + { + public static readonly ReqAck Instance = new ReqAck(); + + private ReqAck() + { + } + + public override bool Equals(object obj) + { + return obj is ReqAck; + } + } + + [Serializable] + private sealed class ReqDone : IEvt, IEquatable + { + public ReqDone(long id) + { + Id = id; + } + + public long Id { get; private set; } + + public bool Equals(ReqDone other) + { + return other != null && other.Id == Id; + } + } + + [Serializable] + private sealed class SaveSnap + { + public static readonly SaveSnap Instance = new SaveSnap(); + } + + [Serializable] + private sealed class Snap + { + public Snap(AtLeastOnceDeliverySnapshot deliverySnapshot) + { + DeliverySnapshot = deliverySnapshot; + } + + public AtLeastOnceDeliverySnapshot DeliverySnapshot { get; private set; } + } + + private class Unreliable : ReceiveActor + { + private int _count; + + public Unreliable(int dropMod, IActorRef target) + { + Receive(message => + { + _count++; + if (_count%dropMod != 0) + { + target.Forward(message); + } + return true; + }); + } + } + + #endregion + + public AtLeastOnceDeliveryReceiveActorSpec() + : base(Configuration("inmem", "AtLeastOnceDeliveryReceiveActorSpec")) + { + } + + [Fact] + public void PersistentReceive_must_deliver_messages_in_order_when_nothing_is_lost() + { + TestProbe probe = CreateTestProbe(); + var destinations = new Dictionary + { + {"A", Sys.ActorOf(Props.Create(() => new Destination(probe.Ref))).Path} + }; + IActorRef sender = + Sys.ActorOf( + Props.Create( + () => + new Receiver(TestActor, Name, TimeSpan.FromMilliseconds(500), 5, 1000, false, destinations)), + Name); + + sender.Tell(new Req("a")); + ExpectMsg(ReqAck.Instance); + probe.ExpectMsg(a => a.Id == 1 && a.Payload == "a"); + probe.ExpectNoMsg(TimeSpan.FromSeconds(1)); + } + + [Fact] + public void PersistentReceive_must_redeliver_lost_messages() + { + TestProbe probe = CreateTestProbe(); + IActorRef dest = Sys.ActorOf(Props.Create(() => new Destination(probe.Ref))); + var destinations = new Dictionary + { + {"A", Sys.ActorOf(Props.Create(() => new Unreliable(3, dest))).Path} + }; + IActorRef sender = + Sys.ActorOf( + Props.Create( + () => + new Receiver(TestActor, Name, TimeSpan.FromMilliseconds(500), 5, 1000, false, destinations)), + Name); + + sender.Tell(new Req("a-1")); + ExpectMsg(ReqAck.Instance); + probe.ExpectMsg(a => a.Id == 1 && a.Payload == "a-1"); + + sender.Tell(new Req("a-2")); + ExpectMsg(ReqAck.Instance); + probe.ExpectMsg(a => a.Id == 2 && a.Payload == "a-2"); + + sender.Tell(new Req("a-3")); + sender.Tell(new Req("a-4")); + ExpectMsg(ReqAck.Instance); + ExpectMsg(ReqAck.Instance); + // a-3 was lost ... + probe.ExpectMsg(a => a.Id == 4 && a.Payload == "a-4"); + // ... and then redelivered + probe.ExpectMsg(a => a.Id == 3 && a.Payload == "a-3"); + probe.ExpectNoMsg(TimeSpan.FromSeconds(1)); + } + + [Fact] + public void PersistentReceive_must_redeliver_lost_messages_after_restart() + { + TestProbe probe = CreateTestProbe(); + IActorRef dest = Sys.ActorOf(Props.Create(() => new Destination(probe.Ref))); + var destinations = new Dictionary + { + {"A", Sys.ActorOf(Props.Create(() => new Unreliable(3, dest))).Path} + }; + IActorRef sender = + Sys.ActorOf( + Props.Create( + () => + new Receiver(TestActor, Name, TimeSpan.FromMilliseconds(500), 5, 1000, false, destinations)), + Name); + + sender.Tell(new Req("a-1")); + ExpectMsg(ReqAck.Instance); + probe.ExpectMsg(a => a.Id == 1 && a.Payload == "a-1"); + + sender.Tell(new Req("a-2")); + ExpectMsg(ReqAck.Instance); + probe.ExpectMsg(a => a.Id == 2 && a.Payload == "a-2"); + + sender.Tell(new Req("a-3")); + sender.Tell(new Req("a-4")); + ExpectMsg(ReqAck.Instance); + ExpectMsg(ReqAck.Instance); + // a-3 was lost ... + probe.ExpectMsg(a => a.Id == 4 && a.Payload == "a-4"); + // ... trigger restart ... + sender.Tell(Boom.Instance); + // ... and then redeliver + probe.ExpectMsg(a => a.Id == 3 && a.Payload == "a-3"); + + sender.Tell(new Req("a-5")); + ExpectMsg(ReqAck.Instance); + probe.ExpectMsg(a => a.Id == 5 && a.Payload == "a-5"); + + probe.ExpectNoMsg(TimeSpan.FromSeconds(1)); + } + + [Fact] + public void + PersistentReceive_must_resend_replayed_deliveries_with_an_initially_in_order_strategy_before_delivering_fresh_messages + () + { + TestProbe probe = CreateTestProbe(); + IActorRef dest = Sys.ActorOf(Props.Create(() => new Destination(probe.Ref))); + var destinations = new Dictionary + { + {"A", Sys.ActorOf(Props.Create(() => new Unreliable(2, dest))).Path} + }; + IActorRef sender = + Sys.ActorOf( + Props.Create( + () => + new Receiver(TestActor, Name, TimeSpan.FromMilliseconds(500), 5, 1000, false, destinations)), + Name); + + sender.Tell(new Req("a-1")); + ExpectMsg(ReqAck.Instance); + probe.ExpectMsg(a => a.Id == 1 && a.Payload == "a-1"); + + sender.Tell(new Req("a-2")); + ExpectMsg(ReqAck.Instance); + // a-2 was lost + + sender.Tell(new Req("a-3")); + ExpectMsg(ReqAck.Instance); + probe.ExpectMsg(a => a.Id == 3 && a.Payload == "a-3"); + + sender.Tell(new Req("a-4")); + ExpectMsg(ReqAck.Instance); + // a-4 was lost + + // trigger restart + sender.Tell(Boom.Instance); + sender.Tell(new Req("a-5")); + ExpectMsg(ReqAck.Instance); + + // and redeliver + probe.ExpectMsg(a => a.Id == 2 && a.Payload == "a-2"); // redelivered + // a-4 was redelivered but lost again + probe.ExpectMsg(a => a.Id == 5 && a.Payload == "a-5"); // redelivered + //FIXME: expression below works, just for some reason won't fit in 10 sec. interval + probe.ExpectMsg(a => a.Id == 4 && a.Payload == "a-4", TimeSpan.FromSeconds(20)); + // redelivered, 3th time + + probe.ExpectNoMsg(TimeSpan.FromSeconds(1)); + } + + [Fact] + public void PersistentReceive_must_restore_state_from_snapshot() + { + TestProbe probe = CreateTestProbe(); + IActorRef dest = Sys.ActorOf(Props.Create(() => new Destination(probe.Ref))); + var destinations = new Dictionary + { + {"A", Sys.ActorOf(Props.Create(() => new Unreliable(3, dest))).Path} + }; + IActorRef sender = + Sys.ActorOf( + Props.Create( + () => + new Receiver(TestActor, Name, TimeSpan.FromMilliseconds(500), 5, 1000, false, destinations)), + Name); + + sender.Tell(new Req("a-1")); + ExpectMsg(ReqAck.Instance); + probe.ExpectMsg(a => a.Id == 1 && a.Payload == "a-1"); + + sender.Tell(new Req("a-2")); + ExpectMsg(ReqAck.Instance); + probe.ExpectMsg(a => a.Id == 2 && a.Payload == "a-2"); + + sender.Tell(new Req("a-3")); + sender.Tell(new Req("a-4")); + sender.Tell(SaveSnap.Instance); + ExpectMsg(ReqAck.Instance); + ExpectMsg(ReqAck.Instance); + // a-3 was lost + + probe.ExpectMsg(a => a.Id == 4 && a.Payload == "a-4"); + + // after snapshot succeed + ExpectMsg(); + // trigger restart + sender.Tell(Boom.Instance); + // and then redelivered + probe.ExpectMsg(a => a.Id == 3 && a.Payload == "a-3"); + + sender.Tell(new Req("a-5")); + ExpectMsg(ReqAck.Instance); + probe.ExpectMsg(a => a.Id == 5 && a.Payload == "a-5"); + + probe.ExpectNoMsg(TimeSpan.FromSeconds(1)); + } + + [Fact] + public void PersistentReceive_must_warn_about_unconfirmed_messages() + { + TestProbe probeA = CreateTestProbe(); + TestProbe probeB = CreateTestProbe(); + + var destinations = new Dictionary {{"A", probeA.Ref.Path}, {"B", probeB.Ref.Path}}; + IActorRef sender = + Sys.ActorOf( + Props.Create( + () => + new Receiver(TestActor, Name, TimeSpan.FromMilliseconds(500), 3, 1000, false, destinations)), + Name); + + sender.Tell(new Req("a-1")); + sender.Tell(new Req("b-1")); + sender.Tell(new Req("b-2")); + ExpectMsg(ReqAck.Instance); + ExpectMsg(ReqAck.Instance); + ExpectMsg(ReqAck.Instance); + + UnconfirmedDelivery[] unconfirmed = ReceiveWhile(TimeSpan.FromSeconds(3), x => + x is UnconfirmedWarning + ? ((UnconfirmedWarning) x).UnconfirmedDeliveries + : Enumerable.Empty()) + .SelectMany(e => e).ToArray(); + + ActorPath[] resultDestinations = unconfirmed.Select(x => x.Destination).Distinct().ToArray(); + resultDestinations.ShouldOnlyContainInOrder(probeA.Ref.Path, probeB.Ref.Path); + object[] resultMessages = unconfirmed.Select(x => x.Message).Distinct().ToArray(); + resultMessages.ShouldOnlyContainInOrder(new Action(1, "a-1"), new Action(2, "b-1"), new Action(3, "b-2")); + + Sys.Stop(sender); + } + } +} \ No newline at end of file diff --git a/src/core/Akka.Persistence.Tests/AtLeastOnceDeliverySpec.cs b/src/core/Akka.Persistence.Tests/AtLeastOnceDeliverySpec.cs index bc3784c40b3..619768eeb6b 100644 --- a/src/core/Akka.Persistence.Tests/AtLeastOnceDeliverySpec.cs +++ b/src/core/Akka.Persistence.Tests/AtLeastOnceDeliverySpec.cs @@ -24,31 +24,22 @@ class Sender : AtLeastOnceDeliveryActor { private readonly IActorRef _testActor; private readonly string _name; - private readonly TimeSpan _redeliverInterval; - private readonly int _warn; - private readonly int _redeliveryBurstLimit; private readonly bool _isAsync; private readonly IDictionary _destinations; private readonly ILoggingAdapter _log; private IActorRef _lastSnapshotAskedForBy; public Sender(IActorRef testActor, string name, TimeSpan redeliverInterval, int warn, int redeliveryBurstLimit, bool isAsync, IDictionary destinations) - : base() + : base(new PersistenceSettings.AtLeastOnceDeliverySettings(redeliverInterval, redeliveryBurstLimit, warn, 100000)) { _testActor = testActor; _name = name; - _redeliverInterval = redeliverInterval; - _warn = warn; - _redeliveryBurstLimit = redeliveryBurstLimit; _isAsync = isAsync; _destinations = destinations; _log = Context.GetLogger(); } public override string PersistenceId { get { return _name; } } - public override TimeSpan RedeliverInterval { get { return _redeliverInterval; } } - public override int UnconfirmedDeliveryAttemptsToWarn { get { return _warn; } } - public override int RedeliveryBurstLimit { get { return _redeliveryBurstLimit; } } protected override bool ReceiveRecover(object message) { diff --git a/src/core/Akka.Persistence/Akka.Persistence.csproj b/src/core/Akka.Persistence/Akka.Persistence.csproj index 1eddee4b7e7..c97b3f82ce2 100644 --- a/src/core/Akka.Persistence/Akka.Persistence.csproj +++ b/src/core/Akka.Persistence/Akka.Persistence.csproj @@ -53,6 +53,8 @@ Properties\SharedAssemblyInfo.cs + + @@ -112,4 +114,118 @@ --> + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll + True + True + + + + + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll + True + True + + + ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll + True + True + + + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll + True + True + + + + + + + ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll + True + True + + + + \ No newline at end of file diff --git a/src/core/Akka.Persistence/AtLeastOnceDelivery.cs b/src/core/Akka.Persistence/AtLeastOnceDelivery.cs index 0d3ccb3da91..47a36d490cb 100644 --- a/src/core/Akka.Persistence/AtLeastOnceDelivery.cs +++ b/src/core/Akka.Persistence/AtLeastOnceDelivery.cs @@ -6,468 +6,171 @@ //----------------------------------------------------------------------- using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; using Akka.Actor; using Akka.Actor.Internal; -using Akka.Persistence.Serialization; namespace Akka.Persistence { - #region Messages - /// - /// Snapshot of a current state. Can be retrieved with - /// and saved with . - /// During recovery the snapshot received in should be sent with - /// . + /// Persistent actor type, that sends messages with at-least-once delivery semantics to it's destinations. + /// It takes care of re-sending messages when they haven't been confirmed withing expected timeout. The same + /// message may be send twice or more to the same destination as a result of possible resends. + /// Use a method to send a message to a destination. Call the + /// + /// method once destination has replied with a confirmation message. The interval between redelivery attempts + /// can be defined with . After a number of delivery attempts an + /// message will be sent to . The resending will + /// continue, + /// but you may choose to cancel resending. + /// This actor type has state consisting of unconfirmed messages and a sequence number. It doesn't store it by + /// itself, so you must persist corresponding events so that state can be restored by calling the same + /// delivery-related methods during recovery phase of the persistent actor. During recovery calls to + /// won't send out a message, but it will be sent later if no + /// + /// call was performed. + /// Support for snapshot is provided by get and set delivery snapshot methods. These snapshots contains full + /// delivery state including unconfirmed messages. For custom snapshots remember to include those delivery ones. /// - [Serializable] - public sealed class AtLeastOnceDeliverySnapshot : IMessage, IEquatable - { - public AtLeastOnceDeliverySnapshot(long deliveryId, UnconfirmedDelivery[] unconfirmedDeliveries) - { - if(unconfirmedDeliveries == null) - throw new ArgumentNullException("unconfirmedDeliveries", "AtLeastOnceDeliverySnapshot expects not null array of unconfirmed deliveries"); - - DeliveryId = deliveryId; - UnconfirmedDeliveries = unconfirmedDeliveries; - } - - public readonly long DeliveryId; - public readonly UnconfirmedDelivery[] UnconfirmedDeliveries; - - public bool Equals(AtLeastOnceDeliverySnapshot other) - { - if (ReferenceEquals(other, null)) return false; - if (ReferenceEquals(this, other)) return true; - - return Equals(DeliveryId, other.DeliveryId) - && Equals(UnconfirmedDeliveries, UnconfirmedDeliveries); - } - - public override bool Equals(object obj) - { - return Equals(obj as AtLeastOnceDeliverySnapshot); - } - - public override int GetHashCode() - { - unchecked - { - return (DeliveryId.GetHashCode() * 397) ^ (UnconfirmedDeliveries != null ? UnconfirmedDeliveries.GetHashCode() : 0); - } - } - - public override string ToString() - { - return string.Format("AtLeastOnceDeliverySnapshot", DeliveryId, UnconfirmedDeliveries.Length); - } - } - - /// - /// message should be sent after - /// limit will be reached. - /// - [Serializable] - public sealed class UnconfirmedWarning : IEquatable - { - public UnconfirmedWarning(UnconfirmedDelivery[] unconfirmedDeliveries) - { - if(unconfirmedDeliveries == null) - throw new ArgumentNullException("unconfirmedDeliveries", "UnconfirmedWarning expects not null array of unconfirmed deliveries"); - - UnconfirmedDeliveries = unconfirmedDeliveries; - } - - public readonly UnconfirmedDelivery[] UnconfirmedDeliveries; - - public bool Equals(UnconfirmedWarning other) - { - if (ReferenceEquals(other, null)) return false; - if (ReferenceEquals(this, other)) return true; - - return Equals(UnconfirmedDeliveries, other.UnconfirmedDeliveries); - } - - public override bool Equals(object obj) - { - return Equals(obj as UnconfirmedWarning); - } - - public override int GetHashCode() - { - return (UnconfirmedDeliveries != null ? UnconfirmedDeliveries.GetHashCode() : 0); - } - - public override string ToString() - { - return string.Format("UnconfirmedWarning", UnconfirmedDeliveries.Length); - } - } - - /// - /// contains details about unconfirmed messages. - /// It's included inside and . - /// - [Serializable] - public sealed class UnconfirmedDelivery : IEquatable - { - public UnconfirmedDelivery(long deliveryId, ActorPath destination, object message) - { - DeliveryId = deliveryId; - Destination = destination; - Message = message; - } - - public readonly long DeliveryId; - public readonly ActorPath Destination; - public readonly object Message; - - public bool Equals(UnconfirmedDelivery other) - { - if (ReferenceEquals(other, null)) return false; - if (ReferenceEquals(this, other)) return true; - - return Equals(DeliveryId, other.DeliveryId) - && Equals(Destination, other.Destination) - && Equals(Message, other.Message); - } - - public override bool Equals(object obj) - { - return Equals(obj as UnconfirmedDelivery); - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = DeliveryId.GetHashCode(); - hashCode = (hashCode * 397) ^ (Destination != null ? Destination.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (Message != null ? Message.GetHashCode() : 0); - return hashCode; - } - } - - public override string ToString() - { - return string.Format("UnconfirmedDelivery", DeliveryId, Destination, Message); - } - } - - [Serializable] - internal sealed class Delivery : IEquatable + public abstract class AtLeastOnceDeliveryActor : PersistentActor, IInitializableActor { - public Delivery(ActorPath destination, object message, DateTime timestamp, int attempt) - { - Destination = destination; - Message = message; - Timestamp = timestamp; - Attempt = attempt; - } - - public readonly ActorPath Destination; - public readonly object Message; - public readonly DateTime Timestamp; - public readonly int Attempt; - - public Delivery IncrementedCopy() - { - return new Delivery(Destination, Message, Timestamp, Attempt + 1); - } - - public bool Equals(Delivery other) - { - if (ReferenceEquals(other, null)) return false; - if (ReferenceEquals(this, other)) return true; - - return Equals(Attempt, other.Attempt) - && Equals(Timestamp, other.Timestamp) - && Equals(Destination, other.Destination) - && Equals(Message, other.Message); - } - - public override bool Equals(object obj) - { - return Equals(obj as Delivery); - } + private readonly AtLeastOnceDeliverySemantic _atLeastOnceDeliverySemantic; - public override int GetHashCode() + protected AtLeastOnceDeliveryActor() { - unchecked - { - var hashCode = (Destination != null ? Destination.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (Message != null ? Message.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ Timestamp.GetHashCode(); - hashCode = (hashCode * 397) ^ Attempt; - return hashCode; - } + _atLeastOnceDeliverySemantic = new AtLeastOnceDeliverySemantic(Context, Extension.Settings.AtLeastOnceDelivery); } - public override string ToString() - { - return string.Format("Delivery - /// This exception is thrown when the threshold has been exceeded. - /// - public class MaxUnconfirmedMessagesExceededException : AkkaException - { /// - /// Initializes a new instance of the class. + /// Interval between redelivery attempts. /// - /// The message that describes the error. - /// The exception that is the cause of the current exception. - public MaxUnconfirmedMessagesExceededException(string message, Exception cause = null) - : base(message, cause) + public TimeSpan RedeliverInterval { + get { return _atLeastOnceDeliverySemantic.RedeliverInterval; } } /// - /// Initializes a new instance of the class. + /// Maximum number of unconfirmed messages that will be sent at each redelivery burst. This is to help to + /// prevent overflowing amount of messages to be sent at once, for eg. when destination cannot be reached for a long + /// time. /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - protected MaxUnconfirmedMessagesExceededException(SerializationInfo info, StreamingContext context) - : base(info, context) + public int RedeliveryBurstLimit { + get { return _atLeastOnceDeliverySemantic.RedeliveryBurstLimit; } } - } - /// - /// Persistent actor type, that sends messages with at-least-once delivery semantics to it's destinations. - /// It takes care of re-sending messages when they haven't been confirmed withing expected timeout. The same - /// message may be send twice or more to the same destination as a result of possible resends. - /// - /// Use a method to send a message to a destination. Call the - /// method once destination has replied with a confirmation message. The interval between redelivery attempts - /// can be defined with . After a number of delivery attempts an - /// message will be sent to . The resending will continue, - /// but you may choose to cancel resending. - /// - /// This actor type has state consisting of unconfirmed messages and a sequence number. It doesn't store it by - /// itself, so you must persist corresponding events so that state can be restored by calling the same - /// delivery-related methods during recovery phase of the persistent actor. During recovery calls to - /// won't send out a message, but it will be sent later if no - /// call was performed. - /// - /// Support for snapshot is provided by get and set delivery snapshot methods. These snapshots contains full - /// delivery state including unconfirmed messages. For custom snapshots remember to include those delivery ones. - /// - public abstract class AtLeastOnceDeliveryActor : PersistentActor, IInitializableActor - { - private ICancelable _redeliverScheduleCancelable; - private long _deliverySequenceNr = 0L; - private ConcurrentDictionary _unconfirmed = new ConcurrentDictionary(); - /// - /// Invoked after actor has been created and all of it's fields have been initialized. + /// After this number of delivery attempts a message will be sent to + /// . + /// The count is reset after restart. /// - public void Init() + public int UnconfirmedDeliveryAttemptsToWarn { - _redeliverScheduleCancelable = ScheduleRedelivery(); + get { return _atLeastOnceDeliverySemantic.UnconfirmedDeliveryAttemptsToWarn; } } - /// - /// Interval between redelivery attempts. + /// Maximum number of unconfirmed messages, that this actor is allowed to hold in the memory. When this + /// number is exceed, will throw + /// + /// instead of accepting messages. /// - public virtual TimeSpan RedeliverInterval { get { return DefaultRedeliverInterval; } } - protected TimeSpan DefaultRedeliverInterval { get { return Extension.Settings.AtLeastOnceDelivery.RedeliverInterval; } } - - /// - /// Maximum number of unconfirmed messages that will be sent at each redelivery burst. This is to help to - /// prevent overflowing amount of messages to be sent at once, for eg. when destination cannot be reached for a long time. - /// - public virtual int RedeliveryBurstLimit { get { return DefaultRedeliveryBurstLimit; } } - protected int DefaultRedeliveryBurstLimit { get { return Extension.Settings.AtLeastOnceDelivery.RedeliveryBurstLimit; } } - - /// - /// After this number of delivery attempts a message will be sent to . - /// The count is reset after restart. - /// - public virtual int UnconfirmedDeliveryAttemptsToWarn { get { return DefaultUnconfirmedDeliveryAttemptsToWarn; } } - protected int DefaultUnconfirmedDeliveryAttemptsToWarn { get { return Extension.Settings.AtLeastOnceDelivery.UnconfirmedAttemptsToWarn; } } - - /// - /// Maximum number of unconfirmed messages, that this actor is allowed to hold in the memory. When this - /// number is exceed, will throw - /// instead of accepting messages. - /// - public virtual int MaxUnconfirmedMessages { get { return DefaultMaxUnconfirmedMessages; } } - protected int DefaultMaxUnconfirmedMessages { get { return Extension.Settings.AtLeastOnceDelivery.MaxUnconfirmedMessages; } } - - /// - /// Number of messages, that have not been confirmed yet. - /// - public int UnconfirmedCount { get { return _unconfirmed.Count; } } - - /// - /// Send the message created with function to the - /// actor. It will retry sending the message until the delivery is confirmed with . - /// Correlation between these two methods is performed by delivery id - parameter of . - /// Usually it's passed inside the message to the destination, which replies with the message having the same id. - /// - /// During recovery this method won't send out any message, but it will be sent later until corresponding - /// method will be invoked. - /// - /// - /// Thrown when is greater than or equal to . - /// - public void Deliver(ActorPath destination, Func deliveryMessageMapper) + public int MaxUnconfirmedMessages { - if (UnconfirmedCount >= MaxUnconfirmedMessages) - { - throw new MaxUnconfirmedMessagesExceededException(string.Format("{0} has too many unconfirmed messages. Maximum allowed is {1}", PersistenceId, MaxUnconfirmedMessages)); - } - - var deliveryId = NextDeliverySequenceNr(); - var now = IsRecovering ? DateTime.UtcNow - RedeliverInterval : DateTime.UtcNow; - var delivery = new Delivery(destination, deliveryMessageMapper(deliveryId), now, attempt: 0); - - if (IsRecovering) - { - _unconfirmed.AddOrUpdate(deliveryId, delivery, (id, d) => delivery); - } - else - { - Send(deliveryId, delivery, now); - } + get { return _atLeastOnceDeliverySemantic.MaxUnconfirmedMessages; } } + /// - /// Call this method to confirm that message with has been sent - /// or to cancel redelivery attempts. + /// Number of messages, that have not been confirmed yet. /// - /// True if delivery was confirmed first time, false for duplicate confirmations. - public bool ConfirmDelivery(long deliveryId) + public int UnconfirmedCount { - Delivery delivery; - return _unconfirmed.TryRemove(deliveryId, out delivery); + get { return _atLeastOnceDeliverySemantic.UnconfirmedCount; } } - /// - /// Returns full state of the current delivery actor. Could be saved using method. - /// During recovery a snapshot received in should be set with . - /// - public AtLeastOnceDeliverySnapshot GetDeliverySnapshot() + public void Init() { - var unconfirmedDeliveries = _unconfirmed - .Select(e => new UnconfirmedDelivery(e.Key, e.Value.Destination, e.Value.Message)) - .ToArray(); - - return new AtLeastOnceDeliverySnapshot(_deliverySequenceNr, unconfirmedDeliveries); + _atLeastOnceDeliverySemantic.Init(); } - /// - /// If snapshot from was saved, it will be received during recovery phase in a - /// message and should be set with this method. - /// - /// - public void SetDeliverySnapshot(AtLeastOnceDeliverySnapshot snapshot) - { - _deliverySequenceNr = snapshot.DeliveryId; - var now = DateTime.UtcNow; - var unconfirmedDeliveries = snapshot.UnconfirmedDeliveries - .Select(u => new KeyValuePair(u.DeliveryId, new Delivery(u.Destination, u.Message, now, 0))); - - _unconfirmed = new ConcurrentDictionary(unconfirmedDeliveries); - } public override void AroundPostRestart(Exception cause, object message) { - _redeliverScheduleCancelable.Cancel(); + _atLeastOnceDeliverySemantic.Cancel(); base.AroundPostRestart(cause, message); } public override void AroundPostStop() { - _redeliverScheduleCancelable.Cancel(); + _atLeastOnceDeliverySemantic.Cancel(); base.AroundPostStop(); } protected override void OnReplaySuccess() { - RedeliverOverdue(); - base.OnReplaySuccess(); + _atLeastOnceDeliverySemantic.OnReplaySuccess(); } protected override bool AroundReceive(Receive receive, object message) { - if (message is RedeliveryTick) - { - RedeliverOverdue(); - return true; - } - - return base.AroundReceive(receive, message); + return _atLeastOnceDeliverySemantic.AroundReceive(receive, message) || base.AroundReceive(receive, message); } - private void Send(long deliveryId, Delivery delivery, DateTime timestamp) + /// + /// If snapshot from was saved, it will be received during recovery phase in a + /// message and should be set with this method. + /// + /// + public void SetDeliverySnapshot(AtLeastOnceDeliverySnapshot snapshot) { - var destination = Context.ActorSelection(delivery.Destination); - destination.Tell(delivery.Message); - - var dcopy = new Delivery(delivery.Destination, delivery.Message, timestamp, delivery.Attempt + 1); - _unconfirmed.AddOrUpdate(deliveryId, dcopy, (id, d) => dcopy); + _atLeastOnceDeliverySemantic.SetDeliverySnapshot(snapshot); } - private void RedeliverOverdue() + /// + /// Call this method to confirm that message with has been sent + /// or to cancel redelivery attempts. + /// + /// True if delivery was confirmed first time, false for duplicate confirmations. + public bool ConfirmDelivery(long deliveryId) { - var now = DateTime.UtcNow; - var deadline = now - RedeliverInterval; - var warnings = new List(); - - foreach (var entry in _unconfirmed.Where(e => e.Value.Timestamp <= deadline).Take(RedeliveryBurstLimit).ToArray()) - { - var deliveryId = entry.Key; - var unconfirmedDelivery = entry.Value; - - Send(deliveryId, unconfirmedDelivery, now); - - if (unconfirmedDelivery.Attempt == UnconfirmedDeliveryAttemptsToWarn) - { - warnings.Add(new UnconfirmedDelivery(deliveryId, unconfirmedDelivery.Destination, unconfirmedDelivery.Message)); - } - } - - if (warnings.Count != 0) - { - Self.Tell(new UnconfirmedWarning(warnings.ToArray())); - } + return _atLeastOnceDeliverySemantic.ConfirmDelivery(deliveryId); } - private long NextDeliverySequenceNr() + + /// + /// Returns full state of the current delivery actor. Could be saved using + /// method. + /// During recovery a snapshot received in should be set with + /// . + /// + public AtLeastOnceDeliverySnapshot GetDeliverySnapshot() { - return (++_deliverySequenceNr); + return _atLeastOnceDeliverySemantic.GetDeliverySnapshot(); } - private ICancelable ScheduleRedelivery() + /// + /// Send the message created with function to the + /// + /// actor. It will retry sending the message until the delivery is confirmed with . + /// Correlation between these two methods is performed by delivery id - parameter of + /// . + /// Usually it's passed inside the message to the destination, which replies with the message having the same id. + /// During recovery this method won't send out any message, but it will be sent later until corresponding + /// method will be invoked. + /// + /// + /// Thrown when is greater than or equal to . + /// + public void Deliver(ActorPath destination, Func deliveryMessageMapper) { - var interval = new TimeSpan(RedeliverInterval.Ticks / 2); - return Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(interval, interval, Self, RedeliveryTick.Instance, Self); + _atLeastOnceDeliverySemantic.Deliver(destination, deliveryMessageMapper, IsRecovering); } } -} - +} \ No newline at end of file diff --git a/src/core/Akka.Persistence/AtLeastOnceDeliveryReceiveActor.cs b/src/core/Akka.Persistence/AtLeastOnceDeliveryReceiveActor.cs new file mode 100644 index 00000000000..88ad476e3db --- /dev/null +++ b/src/core/Akka.Persistence/AtLeastOnceDeliveryReceiveActor.cs @@ -0,0 +1,164 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Akka.Actor; +using Akka.Actor.Internal; +using Akka.Dispatch; +using Akka.Tools.MatchHandler; + +namespace Akka.Persistence +{ + /// + /// Receive persistent actor type, that sends messages with at-least-once delivery semantics to it's destinations. + /// + public abstract class AtLeastOnceDeliveryReceiveActor : ReceivePersistentActor + { + private readonly AtLeastOnceDeliverySemantic _atLeastOnceDeliverySemantic; + + protected AtLeastOnceDeliveryReceiveActor() + : base() + { + _atLeastOnceDeliverySemantic = new AtLeastOnceDeliverySemantic(Context, Extension.Settings.AtLeastOnceDelivery); + _atLeastOnceDeliverySemantic.Init(); + + } + protected AtLeastOnceDeliveryReceiveActor(PersistenceSettings.AtLeastOnceDeliverySettings settings) + : base() + { + _atLeastOnceDeliverySemantic = new AtLeastOnceDeliverySemantic(Context, settings); + _atLeastOnceDeliverySemantic.Init(); + + } + + /// + /// Interval between redelivery attempts. + /// + public virtual TimeSpan RedeliverInterval + { + get { return _atLeastOnceDeliverySemantic.RedeliverInterval; ; } + } + + + /// + /// Maximum number of unconfirmed messages that will be sent at each redelivery burst. This is to help to + /// prevent overflowing amount of messages to be sent at once, for eg. when destination cannot be reached for a long + /// time. + /// + public int RedeliveryBurstLimit + { + get { return _atLeastOnceDeliverySemantic.RedeliveryBurstLimit; } + } + + /// + /// After this number of delivery attempts a message will be sent to + /// . + /// The count is reset after restart. + /// + public int UnconfirmedDeliveryAttemptsToWarn + { + get { return _atLeastOnceDeliverySemantic.UnconfirmedDeliveryAttemptsToWarn; } + } + + /// + /// Maximum number of unconfirmed messages, that this actor is allowed to hold in the memory. When this + /// number is exceed, will throw + /// + /// instead of accepting messages. + /// + public int MaxUnconfirmedMessages + { + get { return _atLeastOnceDeliverySemantic.MaxUnconfirmedMessages; } + } + + /// + /// Number of messages, that have not been confirmed yet. + /// + public int UnconfirmedCount + { + get { return _atLeastOnceDeliverySemantic.UnconfirmedCount; } + } + + + public override void AroundPostRestart(Exception cause, object message) + { + _atLeastOnceDeliverySemantic.Cancel(); + base.AroundPostRestart(cause, message); + } + + public override void AroundPostStop() + { + _atLeastOnceDeliverySemantic.Cancel(); + base.AroundPostStop(); + } + + + protected override void OnReplaySuccess() + { + _atLeastOnceDeliverySemantic.OnReplaySuccess(); + } + + protected override bool AroundReceive(Receive receive, object message) + { + return _atLeastOnceDeliverySemantic.AroundReceive(receive, message) || base.AroundReceive(receive, message); + } + + /// + /// If snapshot from was saved, it will be received during recovery phase in a + /// message and should be set with this method. + /// + /// + public void SetDeliverySnapshot(AtLeastOnceDeliverySnapshot snapshot) + { + _atLeastOnceDeliverySemantic.SetDeliverySnapshot(snapshot); + } + + /// + /// Call this method to confirm that message with has been sent + /// or to cancel redelivery attempts. + /// + /// True if delivery was confirmed first time, false for duplicate confirmations. + public bool ConfirmDelivery(long deliveryId) + { + return _atLeastOnceDeliverySemantic.ConfirmDelivery(deliveryId); + } + + + /// + /// Returns full state of the current delivery actor. Could be saved using + /// method. + /// During recovery a snapshot received in should be set with + /// . + /// + public AtLeastOnceDeliverySnapshot GetDeliverySnapshot() + { + return _atLeastOnceDeliverySemantic.GetDeliverySnapshot(); + } + + /// + /// Send the message created with function to the + /// + /// actor. It will retry sending the message until the delivery is confirmed with . + /// Correlation between these two methods is performed by delivery id - parameter of + /// . + /// Usually it's passed inside the message to the destination, which replies with the message having the same id. + /// During recovery this method won't send out any message, but it will be sent later until corresponding + /// method will be invoked. + /// + /// + /// Thrown when is greater than or equal to . + /// + public void Deliver(ActorPath destination, Func deliveryMessageMapper) + { + _atLeastOnceDeliverySemantic.Deliver(destination, deliveryMessageMapper, IsRecovering); + } + + + } +} \ No newline at end of file diff --git a/src/core/Akka.Persistence/AtLeastOnceDeliverySemantic.cs b/src/core/Akka.Persistence/AtLeastOnceDeliverySemantic.cs new file mode 100644 index 00000000000..b751c037898 --- /dev/null +++ b/src/core/Akka.Persistence/AtLeastOnceDeliverySemantic.cs @@ -0,0 +1,513 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2015 Typesafe Inc. +// Copyright (C) 2013-2015 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using Akka.Actor; +using Akka.Persistence.Serialization; + +namespace Akka.Persistence +{ + + #region Messages + + /// + /// Snapshot of a current state. Can be retrieved with + /// and saved with + /// . + /// During recovery the snapshot received in should be sent with + /// . + /// + public sealed class AtLeastOnceDeliverySnapshot : IMessage, IEquatable + { + public readonly long DeliveryId; + public readonly UnconfirmedDelivery[] UnconfirmedDeliveries; + + public AtLeastOnceDeliverySnapshot(long deliveryId, UnconfirmedDelivery[] unconfirmedDeliveries) + { + if (unconfirmedDeliveries == null) + throw new ArgumentNullException("unconfirmedDeliveries", + "AtLeastOnceDeliverySnapshot expects not null array of unconfirmed deliveries"); + + DeliveryId = deliveryId; + UnconfirmedDeliveries = unconfirmedDeliveries; + } + + public bool Equals(AtLeastOnceDeliverySnapshot other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(DeliveryId, other.DeliveryId) + && Equals(UnconfirmedDeliveries, UnconfirmedDeliveries); + } + + public override bool Equals(object obj) + { + return Equals(obj as AtLeastOnceDeliverySnapshot); + } + + public override int GetHashCode() + { + unchecked + { + return (DeliveryId.GetHashCode()*397) ^ + (UnconfirmedDeliveries != null ? UnconfirmedDeliveries.GetHashCode() : 0); + } + } + + public override string ToString() + { + return string.Format("AtLeastOnceDeliverySnapshot", DeliveryId, + UnconfirmedDeliveries.Length); + } + } + + /// + /// contains details about unconfirmed messages. + /// It's included inside and . + /// + [Serializable] + public sealed class UnconfirmedDelivery : IEquatable + { + public readonly long DeliveryId; + public readonly ActorPath Destination; + public readonly object Message; + + public UnconfirmedDelivery(long deliveryId, ActorPath destination, object message) + { + DeliveryId = deliveryId; + Destination = destination; + Message = message; + } + + public bool Equals(UnconfirmedDelivery other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(DeliveryId, other.DeliveryId) + && Equals(Destination, other.Destination) + && Equals(Message, other.Message); + } + + public override bool Equals(object obj) + { + return Equals(obj as UnconfirmedDelivery); + } + + public override int GetHashCode() + { + unchecked + { + int hashCode = DeliveryId.GetHashCode(); + hashCode = (hashCode*397) ^ (Destination != null ? Destination.GetHashCode() : 0); + hashCode = (hashCode*397) ^ (Message != null ? Message.GetHashCode() : 0); + return hashCode; + } + } + + public override string ToString() + { + return string.Format("UnconfirmedDelivery", DeliveryId, + Destination, Message); + } + } + + /// + /// message should be sent after + /// limit will be reached. + /// + [Serializable] + public sealed class UnconfirmedWarning : IEquatable + { + public readonly UnconfirmedDelivery[] UnconfirmedDeliveries; + + public UnconfirmedWarning(UnconfirmedDelivery[] unconfirmedDeliveries) + { + if (unconfirmedDeliveries == null) + throw new ArgumentNullException("unconfirmedDeliveries", + "UnconfirmedWarning expects not null array of unconfirmed deliveries"); + + UnconfirmedDeliveries = unconfirmedDeliveries; + } + + public bool Equals(UnconfirmedWarning other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(UnconfirmedDeliveries, other.UnconfirmedDeliveries); + } + + public override bool Equals(object obj) + { + return Equals(obj as UnconfirmedWarning); + } + + public override int GetHashCode() + { + return (UnconfirmedDeliveries != null ? UnconfirmedDeliveries.GetHashCode() : 0); + } + + public override string ToString() + { + return string.Format("UnconfirmedWarning", UnconfirmedDeliveries.Length); + } + } + + + [Serializable] + internal sealed class Delivery : IEquatable + { + public readonly int Attempt; + public readonly ActorPath Destination; + public readonly object Message; + public readonly DateTime Timestamp; + + public Delivery(ActorPath destination, object message, DateTime timestamp, int attempt) + { + Destination = destination; + Message = message; + Timestamp = timestamp; + Attempt = attempt; + } + + public bool Equals(Delivery other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + + return Equals(Attempt, other.Attempt) + && Equals(Timestamp, other.Timestamp) + && Equals(Destination, other.Destination) + && Equals(Message, other.Message); + } + + public Delivery IncrementedCopy() + { + return new Delivery(Destination, Message, Timestamp, Attempt + 1); + } + + public override bool Equals(object obj) + { + return Equals(obj as Delivery); + } + + public override int GetHashCode() + { + unchecked + { + int hashCode = (Destination != null ? Destination.GetHashCode() : 0); + hashCode = (hashCode*397) ^ (Message != null ? Message.GetHashCode() : 0); + hashCode = (hashCode*397) ^ Timestamp.GetHashCode(); + hashCode = (hashCode*397) ^ Attempt; + return hashCode; + } + } + + public override string ToString() + { + return string.Format("Delivery + /// This exception is thrown when the threshold has been exceeded. + /// + public class MaxUnconfirmedMessagesExceededException : AkkaException + { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception. + public MaxUnconfirmedMessagesExceededException(string message, Exception cause = null) + : base(message, cause) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The that holds the serialized object data about the exception being + /// thrown. + /// + /// + /// The that contains contextual information about the source or + /// destination. + /// + protected MaxUnconfirmedMessagesExceededException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } + + internal sealed class RedeliveryTick + { + public static readonly RedeliveryTick Instance = new RedeliveryTick(); + + private RedeliveryTick() + { + } + + public override bool Equals(object obj) + { + return obj is RedeliveryTick; + } + } + + #region actor methods + + private readonly IActorContext _context; + private long _deliverySequenceNr; + private ICancelable _redeliverScheduleCancelable; + private readonly PersistenceSettings.AtLeastOnceDeliverySettings _settings; + private ConcurrentDictionary _unconfirmed = new ConcurrentDictionary(); + + + public AtLeastOnceDeliverySemantic(IActorContext context, PersistenceSettings.AtLeastOnceDeliverySettings settings) + { + _context = context; + _settings = settings; + } + + + /// + /// Interval between redelivery attempts. + /// + public virtual TimeSpan RedeliverInterval + { + get { return DefaultRedeliverInterval; } + } + + protected TimeSpan DefaultRedeliverInterval + { + get { return _settings.RedeliverInterval; } + } + + /// + /// Maximum number of unconfirmed messages that will be sent at each redelivery burst. This is to help to + /// prevent overflowing amount of messages to be sent at once, for eg. when destination cannot be reached for a long + /// time. + /// + public virtual int RedeliveryBurstLimit + { + get { return DefaultRedeliveryBurstLimit; } + } + + protected int DefaultRedeliveryBurstLimit + { + get { return _settings.RedeliveryBurstLimit; } + } + + /// + /// After this number of delivery attempts a message will be sent to + /// . + /// The count is reset after restart. + /// + public virtual int UnconfirmedDeliveryAttemptsToWarn + { + get { return DefaultUnconfirmedDeliveryAttemptsToWarn; } + } + + protected int DefaultUnconfirmedDeliveryAttemptsToWarn + { + get { return _settings.UnconfirmedAttemptsToWarn; } + } + + /// + /// Maximum number of unconfirmed messages, that this actor is allowed to hold in the memory. When this + /// number is exceed, will throw + /// instead of accepting messages. + /// + public virtual int MaxUnconfirmedMessages + { + get { return DefaultMaxUnconfirmedMessages; } + } + + protected int DefaultMaxUnconfirmedMessages + { + get { return _settings.MaxUnconfirmedMessages; } + } + + /// + /// Number of messages, that have not been confirmed yet. + /// + public int UnconfirmedCount + { + get { return _unconfirmed.Count; } + } + + /// + /// Invoked after actor has been created and all of it's fields have been initialized. + /// + public void Init() + { + _redeliverScheduleCancelable = ScheduleRedelivery(); + } + + /// + /// Send the message created with function to the + /// + /// actor. It will retry sending the message until the delivery is confirmed with . + /// Correlation between these two methods is performed by delivery id - parameter of + /// . + /// Usually it's passed inside the message to the destination, which replies with the message having the same id. + /// During recovery this method won't send out any message, but it will be sent later until corresponding + /// method will be invoked. + /// + /// + /// Thrown when is greater than or equal to . + /// + public void Deliver(ActorPath destination, Func deliveryMessageMapper, bool isRecovering = false) + { + if (UnconfirmedCount >= MaxUnconfirmedMessages) + { + throw new MaxUnconfirmedMessagesExceededException( + string.Format("{0} has too many unconfirmed messages. Maximum allowed is {1}", _context.Self, + MaxUnconfirmedMessages)); + } + + long deliveryId = NextDeliverySequenceNr(); + DateTime now = isRecovering ? DateTime.UtcNow - RedeliverInterval : DateTime.UtcNow; + var delivery = new Delivery(destination, deliveryMessageMapper(deliveryId), now, 0); + + if (isRecovering) + { + _unconfirmed.AddOrUpdate(deliveryId, delivery, (id, d) => delivery); + } + else + { + Send(deliveryId, delivery, now); + } + } + + /// + /// Call this method to confirm that message with has been sent + /// or to cancel redelivery attempts. + /// + /// True if delivery was confirmed first time, false for duplicate confirmations. + public bool ConfirmDelivery(long deliveryId) + { + Delivery delivery; + return _unconfirmed.TryRemove(deliveryId, out delivery); + } + + /// + /// Returns full state of the current delivery actor. Could be saved using + /// method. + /// During recovery a snapshot received in should be set with + /// . + /// + public AtLeastOnceDeliverySnapshot GetDeliverySnapshot() + { + UnconfirmedDelivery[] unconfirmedDeliveries = _unconfirmed + .Select(e => new UnconfirmedDelivery(e.Key, e.Value.Destination, e.Value.Message)) + .ToArray(); + + return new AtLeastOnceDeliverySnapshot(_deliverySequenceNr, unconfirmedDeliveries); + } + + /// + /// If snapshot from was saved, it will be received during recovery phase in a + /// message and should be set with this method. + /// + /// + public void SetDeliverySnapshot(AtLeastOnceDeliverySnapshot snapshot) + { + _deliverySequenceNr = snapshot.DeliveryId; + DateTime now = DateTime.UtcNow; + IEnumerable> unconfirmedDeliveries = snapshot.UnconfirmedDeliveries + .Select( + u => new KeyValuePair(u.DeliveryId, new Delivery(u.Destination, u.Message, now, 0))); + + _unconfirmed = new ConcurrentDictionary(unconfirmedDeliveries); + } + + public void Cancel() + { + _redeliverScheduleCancelable.Cancel(); + } + + + public void OnReplaySuccess() + { + RedeliverOverdue(); + } + + public bool AroundReceive(Receive receive, object message) + { + if (message is RedeliveryTick) + { + RedeliverOverdue(); + return true; + } + return false; + } + + private void Send(long deliveryId, Delivery delivery, DateTime timestamp) + { + ActorSelection destination = _context.ActorSelection(delivery.Destination); + destination.Tell(delivery.Message); + + var dcopy = new Delivery(delivery.Destination, delivery.Message, timestamp, delivery.Attempt + 1); + _unconfirmed.AddOrUpdate(deliveryId, dcopy, (id, d) => dcopy); + } + + private void RedeliverOverdue() + { + DateTime now = DateTime.UtcNow; + DateTime deadline = now - RedeliverInterval; + var warnings = new List(); + + foreach ( + var entry in _unconfirmed.Where(e => e.Value.Timestamp <= deadline).Take(RedeliveryBurstLimit).ToArray() + ) + { + long deliveryId = entry.Key; + Delivery unconfirmedDelivery = entry.Value; + + Send(deliveryId, unconfirmedDelivery, now); + + if (unconfirmedDelivery.Attempt == UnconfirmedDeliveryAttemptsToWarn) + { + warnings.Add(new UnconfirmedDelivery(deliveryId, unconfirmedDelivery.Destination, + unconfirmedDelivery.Message)); + } + } + + if (warnings.Count != 0) + { + _context.Self.Tell(new UnconfirmedWarning(warnings.ToArray())); + } + } + + private long NextDeliverySequenceNr() + { + return (++_deliverySequenceNr); + } + + private ICancelable ScheduleRedelivery() + { + var interval = new TimeSpan(RedeliverInterval.Ticks/2); + return _context.System.Scheduler.ScheduleTellRepeatedlyCancelable(interval, interval, _context.Self, + RedeliveryTick.Instance, _context.Self); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/core/Akka.Persistence/Persistence.cs b/src/core/Akka.Persistence/Persistence.cs index 3070112a953..8eb7d639fc9 100644 --- a/src/core/Akka.Persistence/Persistence.cs +++ b/src/core/Akka.Persistence/Persistence.cs @@ -235,6 +235,15 @@ public ViewSettings(Config config) public AtLeastOnceDeliverySettings AtLeastOnceDelivery { get; set; } public class AtLeastOnceDeliverySettings { + public AtLeastOnceDeliverySettings(TimeSpan redeliverInterval, int redeliveryBurstLimit, + int unconfirmedAttemptsToWarn, int maxUnconfirmedMessages) + { + RedeliverInterval = redeliverInterval; + RedeliveryBurstLimit = redeliveryBurstLimit; + UnconfirmedAttemptsToWarn = unconfirmedAttemptsToWarn; + MaxUnconfirmedMessages = maxUnconfirmedMessages; + } + public AtLeastOnceDeliverySettings(Config config) { RedeliverInterval = config.GetTimeSpan("at-least-once-delivery.redeliver-interval"); @@ -243,10 +252,60 @@ public AtLeastOnceDeliverySettings(Config config) RedeliveryBurstLimit = config.GetInt("at-least-once-delivery.redelivery-burst-limit"); } + /// + /// Interval between redelivery attempts. + /// public TimeSpan RedeliverInterval { get; private set; } + + /// + /// Maximum number of unconfirmed messages, that this actor is allowed to hold in the memory. When this + /// number is exceed, will throw + /// + /// instead of accepting messages. + /// public int MaxUnconfirmedMessages { get; private set; } + + /// + /// After this number of delivery attempts a message will be sent to + /// . + /// The count is reset after restart. + /// public int UnconfirmedAttemptsToWarn { get; private set; } + /// + /// Maximum number of unconfirmed messages that will be sent at each redelivery burst. This is to help to + /// prevent overflowing amount of messages to be sent at once, for eg. when destination cannot be reached for a long + /// time. + /// public int RedeliveryBurstLimit { get; private set; } + + + public AtLeastOnceDeliverySettings WithRedeliverInterval(TimeSpan redeliverInterval) + { + return Copy(redeliverInterval); + } + + public AtLeastOnceDeliverySettings WithMaxUnconfirmedMessages(int maxUnconfirmedMessages) + { + return Copy(null, null, null, maxUnconfirmedMessages); + } + + public AtLeastOnceDeliverySettings WithRedeliveryBurstLimit(int redeliveryBurstLimit) + { + return Copy(null, redeliveryBurstLimit); + } + + public AtLeastOnceDeliverySettings WithUnconfirmedAttemptsToWarn(int unconfirmedAttemptsToWarn) + { + return Copy(null, null, unconfirmedAttemptsToWarn); + } + + private AtLeastOnceDeliverySettings Copy(TimeSpan? redeliverInterval = null, int? redeliveryBurstLimit = null, + int? unconfirmedAttemptsToWarn = null, int? maxUnconfirmedMessages = null) + { + return new AtLeastOnceDeliverySettings(redeliverInterval ?? RedeliverInterval, + redeliveryBurstLimit ?? RedeliveryBurstLimit, unconfirmedAttemptsToWarn ?? UnconfirmedAttemptsToWarn, + maxUnconfirmedMessages ?? MaxUnconfirmedMessages); + } } public InternalSettings Internal { get; private set; } From 37538ce32f8fb6e15925fed4752a1bac7a18cebe Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Sat, 28 Nov 2015 18:01:41 +0400 Subject: [PATCH 100/105] #1445 fix for building options for the VisualizerRuntimeTemplate --- .../VisualizerRuntimeTemplate.Tree.cs | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.Tree.cs b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.Tree.cs index 7d33c529091..087ff7df83c 100644 --- a/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.Tree.cs +++ b/src/core/Akka.MultiNodeTestRunner.Shared/Persistence/VisualizerRuntimeTemplate.Tree.cs @@ -77,31 +77,41 @@ public string BuildOptions(FactData spec) nodeMessage.TimeStamp)) .ToList(); - var firstEventTimeStamp = events.Aggregate( - (aggregate, nextValue) => - aggregate > nextValue - ? nextValue - : aggregate); + var startEventTimeParameter = "null"; + var endEventTimeParameter = "null"; + + if (events.Count > 0) + { + var firstEventTimeStamp = events.Aggregate( + (aggregate, nextValue) => + aggregate > nextValue + ? nextValue + : aggregate); + + var lastEventTimeStamp = events.Aggregate( + (aggregate, nextValue) => + aggregate < nextValue + ? nextValue + : aggregate); - var lastEventTimeStamp = events.Aggregate( - (aggregate, nextValue) => - aggregate < nextValue - ? nextValue - : aggregate); + var startEventTime = new DateTime(firstEventTimeStamp); + var endDisplayTime = new DateTime(lastEventTimeStamp); - var startEventTime = new DateTime(firstEventTimeStamp); - var endDisplayTime = new DateTime(lastEventTimeStamp); + // TODO: Find a better way of calculating additional time from message length + // The last message is the 3 second wait. Which is about half the delta from start to end in length. + var startEndDelta = (endDisplayTime - startEventTime).Ticks / 2; + endDisplayTime = endDisplayTime.AddTicks(startEndDelta); + + startEventTimeParameter = string.Format("'{0}'", startEventTime.ToString("o")); + endEventTimeParameter = string.Format("'{0}'", endDisplayTime.ToString("o")); + } - // TODO: Find a better way of calculating additional time from message length - // The last message is the 3 second wait. Which is about half the delta from start to end in length. - var startEndDelta = (endDisplayTime - startEventTime).Ticks/2; - endDisplayTime = endDisplayTime.AddTicks(startEndDelta); return string.Format( - "{{ start:'{0}', end:'{1}', align:'left', clickToUse:true }}", - startEventTime.ToString("o"), - endDisplayTime.ToString("o")); + "{{ start:{0}, end:{1}, align:'left', clickToUse:true }}", + startEventTimeParameter, + endEventTimeParameter); } private static string LongestCommonPrefix(IReadOnlyList strings) From 866071fba856e97a3d210728404a417ccbe201c4 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 1 Dec 2015 13:38:22 -0800 Subject: [PATCH 101/105] close #1485 removed block from Akka.DI.Unity.csproj removed block from Akka.Persistence.Sqlite.csproj removed block from Akka.Remote.AkkaIOTransport.csproj removed block from Akka.Persistence.Tests.csproj removed block from Akka.Persistence.csproj removed block from Akka.Remote.csproj and Akka.Remote.Tests.csproj removed block from FSharp.Api.fsproj --- .../Akka.DI.Unity.Tests.csproj | 70 ------- .../Akka.DI.Unity/Akka.DI.Unity.csproj | 70 ------- .../Akka.Persistence.Sqlite.csproj | 68 ------- .../Akka.Remote.AkkaIOTransport.csproj | 59 ------ .../Akka.Persistence.Tests.csproj | 192 ------------------ .../Akka.Persistence/Akka.Persistence.csproj | 115 ----------- .../Akka.Remote.Tests.csproj | 192 ------------------ src/core/Akka.Remote/Akka.Remote.csproj | 79 ------- src/examples/FSharp.Api/FSharp.Api.fsproj | 68 ------- 9 files changed, 913 deletions(-) diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj index 5bd7265e038..db8bb33809f 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Unity.Tests/Akka.DI.Unity.Tests.csproj @@ -98,74 +98,4 @@ --> - - - - - - ..\..\..\..\packages\CommonServiceLocator\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll - True - True - - - - - - - - - ..\..\..\..\packages\Unity\lib\win8\Microsoft.Practices.Unity.RegistrationByConvention.dll - True - True - - - ..\..\..\..\packages\Unity\lib\win8\Microsoft.Practices.Unity.dll - True - True - - - - - - - ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.Configuration.dll - True - True - - - ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll - True - True - - - ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.dll - True - True - - - - - - - ..\..\..\..\packages\Unity\lib\wp80\Microsoft.Practices.Unity.RegistrationByConvention.dll - True - True - - - ..\..\..\..\packages\Unity\lib\wp80\Microsoft.Practices.Unity.dll - True - True - - - - - - - ..\..\..\..\packages\Unity\lib\portable-net45+wp80+win8+wpa81+MonoAndroid10+MonoTouch10\Microsoft.Practices.Unity.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj b/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj index f3dfc59dff1..7f802562a1b 100644 --- a/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj +++ b/src/contrib/dependencyInjection/Akka.DI.Unity/Akka.DI.Unity.csproj @@ -83,74 +83,4 @@ --> - - - - - - ..\..\..\..\packages\CommonServiceLocator\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll - True - True - - - - - - - - - ..\..\..\..\packages\Unity\lib\win8\Microsoft.Practices.Unity.RegistrationByConvention.dll - True - True - - - ..\..\..\..\packages\Unity\lib\win8\Microsoft.Practices.Unity.dll - True - True - - - - - - - ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.Configuration.dll - True - True - - - ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll - True - True - - - ..\..\..\..\packages\Unity\lib\net45\Microsoft.Practices.Unity.dll - True - True - - - - - - - ..\..\..\..\packages\Unity\lib\wp80\Microsoft.Practices.Unity.RegistrationByConvention.dll - True - True - - - ..\..\..\..\packages\Unity\lib\wp80\Microsoft.Practices.Unity.dll - True - True - - - - - - - ..\..\..\..\packages\Unity\lib\portable-net45+wp80+win8+wpa81+MonoAndroid10+MonoTouch10\Microsoft.Practices.Unity.dll - True - True - - - - \ No newline at end of file diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj index 899b65bcfd4..add2bd97214 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/Akka.Persistence.Sqlite.csproj @@ -85,74 +85,6 @@ --> - - - - - - ..\..\..\..\packages\System.Data.SQLite.Core\lib\net46\System.Data.SQLite.dll - True - True - - - - - - - ..\..\..\..\packages\System.Data.SQLite.Core\lib\net20\System.Data.SQLite.dll - True - True - - - - - - - ..\..\..\..\packages\System.Data.SQLite.Core\lib\net40\System.Data.SQLite.dll - True - True - - - - - - - ..\..\..\..\packages\System.Data.SQLite.Core\lib\net451\System.Data.SQLite.dll - True - True - - - - - - - - <__paket__System_Data_SQLite_Core_targets>net45\System.Data.SQLite.Core - - - - - <__paket__System_Data_SQLite_Core_targets>net46\System.Data.SQLite.Core - - - - - <__paket__System_Data_SQLite_Core_targets>net20\System.Data.SQLite.Core - - - - - <__paket__System_Data_SQLite_Core_targets>net40\System.Data.SQLite.Core - - - - - <__paket__System_Data_SQLite_Core_targets>net451\System.Data.SQLite.Core - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. diff --git a/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj b/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj index c45e38b20e8..25a411138a0 100644 --- a/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj +++ b/src/contrib/transports/Akka.Remote.AkkaIOTransport/Akka.Remote.AkkaIOTransport.csproj @@ -96,63 +96,4 @@ --> - - - - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll - True - True - - - - diff --git a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj index 39c87ab7801..c7249b8f0c2 100644 --- a/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj +++ b/src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj @@ -144,196 +144,4 @@ --> - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Persistence/Akka.Persistence.csproj b/src/core/Akka.Persistence/Akka.Persistence.csproj index c97b3f82ce2..cb7582a4212 100644 --- a/src/core/Akka.Persistence/Akka.Persistence.csproj +++ b/src/core/Akka.Persistence/Akka.Persistence.csproj @@ -113,119 +113,4 @@ --> - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll - True - True - - - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - True - True - - - - \ No newline at end of file diff --git a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj index 6c97b63bec3..859cd12742b 100644 --- a/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj +++ b/src/core/Akka.Remote.Tests/Akka.Remote.Tests.csproj @@ -180,198 +180,6 @@ --> - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.abstractions\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.abstractions.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.assert\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll - True - True - - - - - - - - <__paket__xunit_core_props>win81\xunit.core - - - - - <__paket__xunit_core_props>wpa81\xunit.core - - - - - <__paket__xunit_core_props>portable-net45+win8+wp8+wpa81\xunit.core - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.core\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll - True - True - - - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\win8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\net45\xunit.execution.desktop.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monoandroid\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\monotouch\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wp8\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\wpa81\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\xamarinios\xunit.execution.dotnet.dll - True - True - - - - - - - ..\..\..\packages\test\xunit.extensibility.execution\lib\portable-net45+win8+wp8+wpa81\xunit.execution.dotnet.dll - True - True - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. diff --git a/src/core/Akka.Remote/Akka.Remote.csproj b/src/core/Akka.Remote/Akka.Remote.csproj index a4ce051cd81..7a2d6e37faf 100644 --- a/src/core/Akka.Remote/Akka.Remote.csproj +++ b/src/core/Akka.Remote/Akka.Remote.csproj @@ -152,83 +152,4 @@ --> - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\net40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl30\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\sl40\Google.ProtocolBuffers.dll - True - True - - - - - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.Serialization.dll - True - True - - - ..\..\..\packages\Google.ProtocolBuffers\lib\portable-net40+sl4+sl5+wp7+wp8+win8\Google.ProtocolBuffers.dll - True - True - - - - - - - - - ..\..\..\packages\Helios\lib\net40\Helios.NET40.dll - True - True - - - - - - - ..\..\..\packages\Helios\lib\net45\Helios.dll - True - True - - - - \ No newline at end of file diff --git a/src/examples/FSharp.Api/FSharp.Api.fsproj b/src/examples/FSharp.Api/FSharp.Api.fsproj index 1ea6a1d9451..cef1eb9b943 100644 --- a/src/examples/FSharp.Api/FSharp.Api.fsproj +++ b/src/examples/FSharp.Api/FSharp.Api.fsproj @@ -120,72 +120,4 @@ --> - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net35\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net20\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net40\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\net45\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll - True - True - - - - - - - ..\..\..\packages\Newtonsoft.Json\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - True - True - - - - - - - - - ..\..\..\packages\Wire\lib\Wire.dll - True - True - - - - \ No newline at end of file From 2744318d7956ef288b193c71314904789775f608 Mon Sep 17 00:00:00 2001 From: rogeralsing Date: Wed, 2 Dec 2015 08:18:33 +0100 Subject: [PATCH 102/105] Removed wire serializer --- src/core/Akka.FSharp.Tests/ApiTests.fs | 72 +++++++++---------- src/core/Akka/Akka.csproj | 5 -- src/core/Akka/Configuration/Pigeon.conf | 1 - src/core/Akka/Serialization/WireSerializer.cs | 59 --------------- src/core/Akka/packages.config | 3 +- 5 files changed, 37 insertions(+), 103 deletions(-) delete mode 100644 src/core/Akka/Serialization/WireSerializer.cs diff --git a/src/core/Akka.FSharp.Tests/ApiTests.fs b/src/core/Akka.FSharp.Tests/ApiTests.fs index f07d79b499a..5511865c1fb 100644 --- a/src/core/Akka.FSharp.Tests/ApiTests.fs +++ b/src/core/Akka.FSharp.Tests/ApiTests.fs @@ -38,42 +38,42 @@ type TestUnion = type TestUnion2 = | C of string * TestUnion | D of int - -[] -let ``can serialize and deserialize discriminated unions over remote nodes using wire serializer`` () = - let remoteConfig port = - sprintf """ - akka { - actor { - ask-timeout = 5s - provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote" - serialization-bindings { - "System.Object" = wire - } - } - remote { - helios.tcp { - port = %i - hostname = localhost - } - } - } - """ port - |> Configuration.parse - - use server = System.create "server-system" (remoteConfig 9911) - use client = System.create "client-system" (remoteConfig 0) - - let aref = - spawne client "a-1" <@ actorOf2 (fun mailbox msg -> - match msg with - | C("a-11", B(11, "a-12")) -> mailbox.Sender() mailbox.Unhandled msg) @> - [SpawnOption.Deploy (Deploy(RemoteScope (Address.Parse "akka.tcp://server-system@localhost:9911")))] - let msg = C("a-11", B(11, "a-12")) - let response = aref Async.RunSynchronously - response - |> equals msg +// +//[] +//let ``can serialize and deserialize discriminated unions over remote nodes using wire serializer`` () = +// let remoteConfig port = +// sprintf """ +// akka { +// actor { +// ask-timeout = 5s +// provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote" +// serialization-bindings { +// "System.Object" = wire +// } +// } +// remote { +// helios.tcp { +// port = %i +// hostname = localhost +// } +// } +// } +// """ port +// |> Configuration.parse +// +// use server = System.create "server-system" (remoteConfig 9911) +// use client = System.create "client-system" (remoteConfig 0) +// +// let aref = +// spawne client "a-1" <@ actorOf2 (fun mailbox msg -> +// match msg with +// | C("a-11", B(11, "a-12")) -> mailbox.Sender() mailbox.Unhandled msg) @> +// [SpawnOption.Deploy (Deploy(RemoteScope (Address.Parse "akka.tcp://server-system@localhost:9911")))] +// let msg = C("a-11", B(11, "a-12")) +// let response = aref Async.RunSynchronously +// response +// |> equals msg //[] // FAILS diff --git a/src/core/Akka/Akka.csproj b/src/core/Akka/Akka.csproj index 086c63447f7..6c29d125ad2 100644 --- a/src/core/Akka/Akka.csproj +++ b/src/core/Akka/Akka.csproj @@ -63,10 +63,6 @@ - - ..\..\packages\Wire.0.0.4\lib\Wire.dll - True - @@ -271,7 +267,6 @@ - diff --git a/src/core/Akka/Configuration/Pigeon.conf b/src/core/Akka/Configuration/Pigeon.conf index 6bbc6c0ff7b..fa015552137 100644 --- a/src/core/Akka/Configuration/Pigeon.conf +++ b/src/core/Akka/Configuration/Pigeon.conf @@ -391,7 +391,6 @@ akka { serializers { json = "Akka.Serialization.NewtonSoftJsonSerializer" - wire = "Akka.Serialization.WireSerializer" java = "Akka.Serialization.JavaSerializer" # not used, reserves java serializer identifier bytes = "Akka.Serialization.ByteArraySerializer" } diff --git a/src/core/Akka/Serialization/WireSerializer.cs b/src/core/Akka/Serialization/WireSerializer.cs deleted file mode 100644 index 3b2c5505d58..00000000000 --- a/src/core/Akka/Serialization/WireSerializer.cs +++ /dev/null @@ -1,59 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (C) 2009-2015 Typesafe Inc. -// Copyright (C) 2013-2015 Akka.NET project -// -//----------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Akka.Actor; -using Akka.Util; -using Wire; - -namespace Akka.Serialization -{ - public class WireSerializer : Serializer - { - private readonly Wire.Serializer _seralizer; - - public WireSerializer(ExtendedActorSystem system) : base(system) - { - var akkaSurrogate = Surrogate.Create(from => from.ToSurrogate(system),to => to.FromSurrogate(system)); - _seralizer = new Wire.Serializer(new SerializerOptions(preserveObjectReferences: true, versionTolerance:true,surrogates: new Surrogate[]{ akkaSurrogate })); - } - public override int Identifier - { - get { return -4; } - } - - public override bool IncludeManifest - { - get { return false; } - } - - public override byte[] ToBinary(object obj) - { - using (var ms = new MemoryStream()) - { - _seralizer.Serialize(obj,ms); - return ms.ToArray(); - } - } - - public override object FromBinary(byte[] bytes, Type type) - { - using (var ms = new MemoryStream()) - { - ms.Write(bytes,0,bytes.Length); - ms.Position = 0; - var res = _seralizer.Deserialize(ms); - return res; - } - } - } -} diff --git a/src/core/Akka/packages.config b/src/core/Akka/packages.config index d601d5faa6e..505e58836ba 100644 --- a/src/core/Akka/packages.config +++ b/src/core/Akka/packages.config @@ -1,5 +1,4 @@ - + - \ No newline at end of file From c7e925ba624eee7e386855251169aecbafd6ae7d Mon Sep 17 00:00:00 2001 From: Silv3rcircl3 Date: Wed, 2 Dec 2015 15:44:16 +0100 Subject: [PATCH 103/105] fixe sqlite.conf and readme --- .../Akka.Persistence.Sqlite/README.md | 6 ++--- .../Akka.Persistence.Sqlite/sqlite.conf | 26 +++++++++++-------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/README.md b/src/contrib/persistence/Akka.Persistence.Sqlite/README.md index 5eaad2d2cb7..974908dfed7 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/README.md +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/README.md @@ -1,6 +1,6 @@ ## Akka.Persistence.Sqlite -Akka Persistence journal and snapshot store backed by SQL Server database. +Akka Persistence journal and snapshot store backed by SQLite database. **WARNING: Akka.Persistence.Sqlite plugin is still in beta and it's mechanics described bellow may be still subject to change**. @@ -13,7 +13,7 @@ akka.persistence.journal.plugin = "akka.persistence.journal.sqlite" akka.persistence.journal.sqlite.connection-string = "" ``` -Similar configuration may be used to setup a SQL Server snapshot store: +Similar configuration may be used to setup a SQLite snapshot store: ``` akka.persistence.snapshot-store.plugin = "akka.persistence.snapshot-store.sqlite" @@ -28,7 +28,7 @@ Both journal and snapshot store share the same configuration keys (however they - `class` (string with fully qualified type name) - determines class to be used as a persistent journal. Default: *Akka.Persistence.Sqlite.Journal.SqliteJournal, Akka.Persistence.Sqlite* (for journal) and *Akka.Persistence.Sqlite.Snapshot.SqliteSnapshotStore, Akka.Persistence.Sqlite* (for snapshot store). - `plugin-dispatcher` (string with configuration path) - describes a message dispatcher for persistent journal. Default: *akka.actor.default-dispatcher* -- `connection-string` - connection string used to access SQL Server database. Default: *none*. +- `connection-string` - connection string used to access SQLite database. Default: *none*. - `connection-timeout` - timespan determining default connection timeouts on database-related operations. Default: *30s* - `table-name` - name of the table used by either journal or snapshot store. Default: *event_journal* (for journal) or *snapshot_store* (for snapshot store) - `auto-initialize` - flag determining if journal or snapshot store related tables should by automatically created when they have not been found in connected database. Default: *false* diff --git a/src/contrib/persistence/Akka.Persistence.Sqlite/sqlite.conf b/src/contrib/persistence/Akka.Persistence.Sqlite/sqlite.conf index 23e99edc74a..cce8b8c9b42 100644 --- a/src/contrib/persistence/Akka.Persistence.Sqlite/sqlite.conf +++ b/src/contrib/persistence/Akka.Persistence.Sqlite/sqlite.conf @@ -1,10 +1,11 @@ akka.persistence{ journal { + sqlite { - # qualified type name of the SQL Server persistence journal actor - class = "Akka.Persistence.SqlServer.Journal.SqlServerJournal, Akka.Persistence.SqlServer" + # qualified type name of the SQLite persistence journal actor + class = "Akka.Persistence.Sqlite.Journal.SqliteJournal, Akka.Persistence.Sqlite" # dispatcher used to drive journal actor plugin-dispatcher = "akka.actor.default-dispatcher" @@ -15,13 +16,13 @@ # connection string name for .config file used when no connection string has been provided connection-string-name = "" - # default SQL commands timeout + # default SQLite commands timeout connection-timeout = 30s - # SQL server schema name to table corresponding with persistent journal + # SQLite schema name to table corresponding with persistent journal schema-name = dbo - # SQL server table corresponding with persistent journal + # SQLite table corresponding with persistent journal table-name = event_journal # should corresponding journal table be initialized automatically @@ -29,17 +30,19 @@ # timestamp provider used for generation of journal entries timestamps timestamp-provider = "Akka.Persistence.Sql.Common.Journal.DefaultTimestampProvider, Akka.Persistence.Sql.Common" + } } snapshot-store { + sqlite { - # qualified type name of the SQL Server persistence journal actor - class = "Akka.Persistence.SqlServer.Snapshot.SqlServerSnapshotStore, Akka.Persistence.SqlServer" + # qualified type name of the SQLite persistence journal actor + class = "Akka.Persistence.Sqlite.Snapshot.SqliteSnapshotStore, Akka.Persistence.Sqlite" # dispatcher used to drive journal actor - plugin-dispatcher = ""akka.actor.default-dispatcher"" + plugin-dispatcher = "akka.actor.default-dispatcher" # connection string used for database access connection-string = "" @@ -47,17 +50,18 @@ # connection string name for .config file used when no connection string has been provided connection-string-name = "" - # default SQL commands timeout + # default SQLite commands timeout connection-timeout = 30s - # SQL server schema name to table corresponding with persistent journal + # SQLite schema name to table corresponding with persistent journal schema-name = dbo - # SQL server table corresponding with persistent journal + # SQLite table corresponding with persistent journal table-name = snapshot_store # should corresponding journal table be initialized automatically auto-initialize = off + } } } \ No newline at end of file From 16427000db67397a30104b7ff44bf55e32eaefba Mon Sep 17 00:00:00 2001 From: Silv3rcircl3 Date: Thu, 3 Dec 2015 15:11:53 +0100 Subject: [PATCH 104/105] wrapped the nuget and symbol package upload in a try/catch block to continue with the next package if the upload failed --- build.fsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/build.fsx b/build.fsx index a7a3075593a..0ba301dad97 100644 --- a/build.fsx +++ b/build.fsx @@ -411,12 +411,18 @@ let publishNugetPackages _ = !! (nugetDir @@ "*.nupkg") -- (nugetDir @@ "*.symbols.nupkg") |> Seq.sortBy(fun x -> x.ToLower()) for package in normalPackages do - publishPackage (getBuildParamOrDefault "nugetpublishurl" "") (getBuildParam "nugetkey") 3 package + try + publishPackage (getBuildParamOrDefault "nugetpublishurl" "") (getBuildParam "nugetkey") 3 package + with exn -> + printfn "%s" exn.Message if shouldPushSymbolsPackages then let symbolPackages= !! (nugetDir @@ "*.symbols.nupkg") |> Seq.sortBy(fun x -> x.ToLower()) for package in symbolPackages do - publishPackage (getBuildParam "symbolspublishurl") (getBuildParam "symbolskey") 3 package + try + publishPackage (getBuildParam "symbolspublishurl") (getBuildParam "symbolskey") 3 package + with exn -> + printfn "%s" exn.Message Target "Nuget" <| fun _ -> From c0b2f57fb33f5aa860816eae21be80c6bf95a083 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Thu, 3 Dec 2015 10:40:00 -0800 Subject: [PATCH 105/105] updated release notes for Akka.NET v1.0.5 --- RELEASE_NOTES.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index ad90545c6f4..0cadbf7ecc6 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,4 +1,72 @@ -#### 1.0.5 August 07 2015 #### +#### 1.0.5 December 3 2015 #### +**Maintenance release for Akka.NET v1.0.4** +This release is a collection of bug fixes, performance enhancements, and general improvements contributed by 29 individual contributors. + +**Fixes & Changes - Akka.NET Core** +* [Bugfix: Make the Put on the SimpleDnsCache idempotent](https://github.com/akkadotnet/akka.net/commit/2ed1d574f76491707deac236db3fd7c1e5af5757) +* [Add CircuitBreaker Initial based on akka 2.0.5](https://github.com/akkadotnet/akka.net/commit/7e16834ef0ff8551cdd3530eacb1016d40cb1cb8) +* [Fix for receive timeout in async await actor](https://github.com/akkadotnet/akka.net/commit/6474bd7dc3d27756e255d12ef21f331108d9922d) +* [akka-io: fixed High CPU load using the Akka.IO TCP server](https://github.com/akkadotnet/akka.net/commit/4af2cfbcaafa33ea04a1a8b1aa6486e78bd6f821) +* [akka-io: Stop select loop on idle](https://github.com/akkadotnet/akka.net/commit/e545780d36cfb805b2014746a2e97006894c2e00) +* [Serialization fixes](https://github.com/akkadotnet/akka.net/commit/6385cc20a3d310efc0bb2f9e29710c5b7bceaa87) +* [Fix issue #1301 - inprecise resizing of resizable routers](https://github.com/akkadotnet/akka.net/commit/cf714333b25190249f01d79bad606d4ce5863e47) +* [Stashing now checks message equality by reference](https://github.com/akkadotnet/akka.net/commit/884330dfb5d69b523f25a59b98450322fe3b34f4) +* [rewrote ActorPath.TryParseAddrss to now test Uris by try / catch and use Uri.TryCreate instead](https://github.com/akkadotnet/akka.net/commit/8eaf32147a08f213db818bf19d74ed9d1aadaed2) +* [Port EventBusUnsubscribers](https://github.com/akkadotnet/akka.net/commit/bd91bcd50d918e5e8ee4b085e53d603cfd46c89a) +* [Add optional PipeTo completion handlers](https://github.com/akkadotnet/akka.net/commit/dfb7f61026d5d0b2d23efe1dd73af820f70a1d1c) +* [Akka context props output to Serilog](https://github.com/akkadotnet/akka.net/commit/409cd7f4ed0b285827b681685af59ec19c5a4b73) + + +**Fixes & Changes - Akka.Remote, Akka.Cluster** +* [MultiNode tests can now be skipped by specifying a SkipReason](https://github.com/akkadotnet/akka.net/commit/75f966cb7d2f2c0d859e0e3a90a38d251a10c5e5) +* [Akka.Remote: Discard msg if payload size > max allowed.](https://github.com/akkadotnet/akka.net/commit/05f57b9b1ff256145bc085f94d49a591e51e1304) +* [Throw `TypeLoadException` when an actor type or dependency cannot be found in a remote actor deploy scenario](https://github.com/akkadotnet/akka.net/commit/ffed3eb088bc00f90a5e4b7367d4598fda007401) +* [MultiNode Test Visualizer](https://github.com/akkadotnet/akka.net/commit/7706bb242719b7f7197058e89f8579af5b82dfc3) +* [Fix for Akka.Cluster.Routing.ClusterRouterGroupSettings Mono Linux issue](https://github.com/akkadotnet/akka.net/commit/dbbd2ac9b16772af8f8e35d3d1c8bf5dcf354f42) +* [Added RemoteDeploymentWatcher](https://github.com/akkadotnet/akka.net/commit/44c29ccefaeca0abdc4fd1f81daf1dc27a285f66) +* [Akka IO Transport: framing support](https://github.com/akkadotnet/akka.net/commit/60b5d2a318b485652e0888190aaa930fe43b1bbc) +* [#1443 fix for cluster shutdown](https://github.com/akkadotnet/akka.net/commit/941688aead57266b454b76530a7fb5446f68e15d) + +**Fixes & Changes - Akka.Persistence** +* [Fixes the NullReferenceException in #1235 and appears to adhere to the practice of including an addres with the serialized binary.](https://github.com/akkadotnet/akka.net/commit/3df119ff614c3298299f863e18efd6e0fa848858) +* [Port Finite State Machine DSL to Akka.Persistence](https://github.com/akkadotnet/akka.net/commit/dce684d907df86f5039eb2ca20727ab48d4b218a) +* [Become and BecomeStacked for ReceivePersistentActor](https://github.com/akkadotnet/akka.net/commit/b11dafc86eb9284c2d515fd9da3599fe463a5681) +* [Persistent actor stops on recovery failures](https://github.com/akkadotnet/akka.net/commit/03105719a8866e8eadac268bc8f813e738f989b9) +* [Fixed: data races inside sql journal engine](https://github.com/akkadotnet/akka.net/commit/f088f0c681fdc7ba1b4eaf7f823c2a9535d3045d) +* [fix sqlite.conf and readme](https://github.com/akkadotnet/akka.net/commit/c7e925ba624eee7e386855251169aecbafd6ae7d) +* [#1416 created ReceiveActor implementation of AtLeastOnceDeliveryActor base class](https://github.com/akkadotnet/akka.net/commit/4d1d79b568bdae6565423c3ed914f8a9606dc0e8) + +A special thanks to all of our contributors, organized below by the number of changes made: + +23369 5258 18111 Aaron Stannard +18827 16329 2498 Bartosz Sypytkowski +11994 9496 2498 Steffen Forkmann +6031 4637 1394 maxim.salamatko +1987 1667 320 Graeme Bradbury +1556 1149 407 Sean Gilliam +1118 1118 0 moliver +706 370 336 rogeralsing +616 576 40 Marek Kadek +501 5 496 Alex Koshelev +377 269 108 Jeff Cyr +280 208 72 willieferguson +150 98 52 Christian Palmstierna +85 63 22 Willie Ferguson +77 71 6 Emil Ingerslev +66 61 5 Grover Jackson +60 39 21 Alexander Pantyukhin +56 33 23 Uladzimir Makarau +55 54 1 rdavisau +51 18 33 alex-kondrashov +42 26 16 Silv3rcircl3 +36 30 6 evertmulder +33 19 14 Filip Malachowicz +13 11 2 Suhas Chatekar +7 6 1 tintoy +4 2 2 Jonathan +2 1 1 neekgreen +2 1 1 Christopher Martin +2 1 1 Artem Borzilov #### 1.0.4 August 07 2015 #### **Maintenance release for Akka.NET v1.0.3**