Permalink
Browse files

Merge branch 'dev' of github.com:/EventStore/EventStore into dev

  • Loading branch information...
2 parents b5c2eab + 5ad7572 commit 8a7c6eff7db6847a096237e8981aca4b4f5f60e4 @kpyatkivskyy kpyatkivskyy committed Nov 12, 2012
Showing with 816 additions and 359 deletions.
  1. +49 −0 src/EventStore/EventStore.ClientAPI/Common/Utils/Tasks.cs
  2. +178 −0 src/EventStore/EventStore.ClientAPI/Connection/ClusterExplorer.cs
  3. +5 −39 src/EventStore/EventStore.ClientAPI/{Configure.cs → ConnectionSettings.cs}
  4. +4 −2 src/EventStore/EventStore.ClientAPI/EventStore.ClientAPI.csproj
  5. +0 −100 src/EventStore/EventStore.ClientAPI/EventStore.cs
  6. +133 −33 src/EventStore/EventStore.ClientAPI/EventStoreConnection.cs
  7. +83 −0 src/EventStore/EventStore.ClientAPI/Messages/ClusterMessages.cs
  8. +20 −10 src/EventStore/EventStore.Core.Tests/ClientAPI/AllEvents/read_all_events_backward_should.cs
  9. +23 −12 src/EventStore/EventStore.Core.Tests/ClientAPI/AllEvents/read_all_events_forward_should.cs
  10. +7 −4 src/EventStore/EventStore.Core.Tests/ClientAPI/AllEvents/subscribe_to_all_should.cs
  11. +20 −10 src/EventStore/EventStore.Core.Tests/ClientAPI/append_to_stream.cs
  12. +8 −4 src/EventStore/EventStore.Core.Tests/ClientAPI/creating_stream.cs
  13. +10 −5 src/EventStore/EventStore.Core.Tests/ClientAPI/deleting_stream.cs
  14. +20 −10 src/EventStore/EventStore.Core.Tests/ClientAPI/read_event_stream_backward_should.cs
  15. +24 −12 src/EventStore/EventStore.Core.Tests/ClientAPI/read_event_stream_forward_should.cs
  16. +13 −7 src/EventStore/EventStore.Core.Tests/ClientAPI/subscribe_should.cs
  17. +38 −15 src/EventStore/EventStore.Core.Tests/ClientAPI/transaction.cs
  18. +2 −2 src/EventStore/EventStore.Core.Tests/Index/MemTableTests.cs
  19. +1 −1 src/EventStore/EventStore.Core.Tests/Services/Storage/ReadIndexTestScenario.cs
  20. +1 −1 ....Tests/Services/Storage/Transactions/when_rebuilding_index_for_partially_persisted_transaction.cs
  21. +5 −14 src/EventStore/EventStore.Core/DataStructures/ILRUCache.cs
  22. +29 −1 src/EventStore/EventStore.Core/DataStructures/LRUCache.cs
  23. +21 −0 src/EventStore/EventStore.Core/DataStructures/NoLRUCache.cs
  24. +2 −0 src/EventStore/EventStore.Core/EventStore.Core.csproj
  25. +6 −2 src/EventStore/EventStore.Core/Index/HashListMemTable.cs
  26. +87 −70 src/EventStore/EventStore.Core/Services/Storage/ReaderIndex/ReadIndex.cs
  27. +14 −0 src/EventStore/EventStore.Core/Services/Storage/ReaderIndex/StreamCacheInfo.cs
  28. +2 −2 src/EventStore/EventStore.Core/Services/Storage/StorageWriter.cs
  29. +1 −1 src/EventStore/EventStore.Core/SingleVNode.cs
  30. +2 −1 src/EventStore/EventStore.Padmin/Program.cs
  31. +2 −1 src/EventStore/EventStore.TestClient/Commands/RunTestScenarios/ScenarioBase.cs
  32. +6 −0 src/EventStore/Projections.Dev.WindowsOnly.sln.DotSettings
@@ -0,0 +1,49 @@
+// Copyright (c) 2012, Event Store LLP
+// 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 the Event Store LLP 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
+// HOLDER 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.
+//
+
+using System.Threading.Tasks;
+
+namespace EventStore.ClientAPI.Common.Utils
+{
+ internal static class Tasks
+ {
+ public static Task CreateCompleted()
+ {
+ var source = new TaskCompletionSource<object>();
+ source.SetResult(null);
+ return source.Task;
+ }
+
+ public static Task<TResult> CreateCompleted<TResult>(TResult result)
+ {
+ var source = new TaskCompletionSource<TResult>();
+ source.SetResult(result);
+ return source.Task;
+ }
+ }
+}
@@ -0,0 +1,178 @@
+// Copyright (c) 2012, Event Store LLP
+// 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 the Event Store LLP 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
+// HOLDER 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.
+//
+
+using System;
+using System.IO;
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Xml.Serialization;
+using EventStore.ClientAPI.Common.Log;
+using EventStore.ClientAPI.Exceptions;
+using EventStore.ClientAPI.Messages;
+using EventStore.ClientAPI.SystemData;
+using EventStore.ClientAPI.Transport.Http;
+using HttpStatusCode = EventStore.ClientAPI.Transport.Http.HttpStatusCode;
+using System.Linq;
+
+namespace EventStore.ClientAPI.Connection
+{
+ internal class ClusterExplorer
+ {
+ private readonly ILogger _log;
+ private readonly HttpAsyncClient _client = new HttpAsyncClient();
+
+ private readonly bool _allowForwarding;
+ private readonly int _maxAttempts;
+ private readonly int _port;
+
+ public ClusterExplorer(bool allowForwarding, int maxAttempts, int port)
+ {
+ _log = LogManager.GetLogger();
+
+ _allowForwarding = allowForwarding;
+ _maxAttempts = maxAttempts;
+ _port = port;
+ }
+
+ public Task<EndpointsPair?> Resolve(string dns)
+ {
+ var resolve = Task.Factory.StartNew(() => Dns.GetHostAddresses(dns));
+ return resolve.ContinueWith(addresses => DiscoverCLuster(addresses.Result, _maxAttempts));
+ }
+
+ private EndpointsPair? DiscoverCLuster(IPAddress[] managers, int maxAttempts)
+ {
+ if (managers == null || managers.Length == 0)
+ throw new CannotEstablishConnectionException("DNS entry resolved in empty ip addresses list");
+
+ var info = GetClusterInfo(managers, maxAttempts);
+ if (info != null && info.Members != null && info.Members.Any())
+ {
+ var alive = info.Members.Where(m => m.IsAlive).ToArray();
+ if (!_allowForwarding)
+ {
+ _log.Info("Forwarding denied. Looking for master...");
+ var master = alive.FirstOrDefault(m => m.State == ClusterMessages.VNodeState.Master);
+ if (master == null)
+ {
+ _log.Info("Master not found");
+ return null;
+ }
+ _log.Info("Master found on [{0}:{1}, {2}:{3}]", master.ExternalTcpIp, master.ExternalTcpPort, master.ExternalHttpIp, master.ExternalHttpPort);
+ return new EndpointsPair(new IPEndPoint(IPAddress.Parse(master.ExternalTcpIp), master.ExternalTcpPort),
+ new IPEndPoint(IPAddress.Parse(master.ExternalHttpIp), master.ExternalHttpPort));
+ }
+
+ var node = alive.FirstOrDefault(m => m.State == ClusterMessages.VNodeState.Master) ??
+ alive.FirstOrDefault(m => m.State == ClusterMessages.VNodeState.Slave) ??
+ alive.FirstOrDefault(m => m.State == ClusterMessages.VNodeState.Clone);
+
+ if (node == null)
+ {
+ _log.Info("Unable to locate master, slave or clone node");
+ return null;
+ }
+ _log.Info("Best choise found, it's {0} on [{1}:{2}, {3}:{4}]",
+ node.State,
+ node.ExternalTcpIp,
+ node.ExternalTcpPort,
+ node.ExternalHttpIp,
+ node.ExternalHttpPort);
+ return new EndpointsPair(new IPEndPoint(IPAddress.Parse(node.ExternalTcpIp), node.ExternalTcpPort),
+ new IPEndPoint(IPAddress.Parse(node.ExternalHttpIp), node.ExternalHttpPort));
+ }
+
+ _log.Info("Failed to discover cluster. No information available");
+ return null;
+ }
+
+ private ClusterMessages.ClusterInfoDto GetClusterInfo(IPAddress[] managers, int maxAttempts)
+ {
+ var attempt = 0;
+ var random = new Random();
+ while (attempt < maxAttempts)
+ {
+ _log.Info("Discovering cluster. Attempt {0}...", attempt + 1);
+ var i = random.Next(0, managers.Length);
+ _log.Info("Picked [{0}]", managers[i]);
+ var info = ClusterInfoOrDefault(managers[i]);
+ if(info != null)
+ {
+ _log.Info("Going to select node based on info from [{0}]", managers[i]);
+ return info;
+ }
+
+ _log.Info("Failed to get cluster info from [{0}]. Attempt {1} of {2}", attempt + 1, maxAttempts);
+ attempt++;
+ Thread.Sleep(TimeSpan.FromSeconds(1));
+ }
+ return null;
+ }
+
+ private ClusterMessages.ClusterInfoDto ClusterInfoOrDefault(IPAddress manager)
+ {
+ ClusterMessages.ClusterInfoDto info = null;
+ var completed = new ManualResetEvent(false);
+
+ Action<HttpResponse> success = response =>
+ {
+ _log.Info("Got response from manager on [{0}]", manager);
+ if (response.HttpStatusCode != HttpStatusCode.OK)
+ {
+ _log.Info("Manager responded with {0} ({1})", response.HttpStatusCode, response.StatusDescription);
+ completed.Set();
+ return;
+ }
+ try
+ {
+ using (var reader = new StringReader(response.Body))
+ info = (ClusterMessages.ClusterInfoDto)new XmlSerializer(typeof(ClusterMessages.ClusterInfoDto)).Deserialize(reader);
+ }
+ catch (Exception e)
+ {
+ _log.Info(e, "Failed to get cluster info from manager on [{0}]. Deserialization error", manager);
+ }
+ completed.Set();
+ };
+
+ Action<Exception> error = e =>
+ {
+ _log.Info(e, "Failed to get cluster info from manager on [{0}]. Request failed");
+ completed.Set();
+ };
+
+ var url = new IPEndPoint(manager, _port).ToHttpUrl("/gossip?format=xml");
+ _log.Info("Sending gossip request to {0}...", url);
+ _client.Get(url, success, error);
+
+ completed.WaitOne();
+ return info;
+ }
+ }
+}
@@ -25,47 +25,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
-using System;
-using System.Net;
namespace EventStore.ClientAPI
{
- public class Configure
+ public enum Mode
{
- internal IPAddress _address;
- internal int _port;
- internal string _name;
-
- private Configure(string name, IPAddress ipaddress, int port)
- {
- _name = name;
- _address = ipaddress;
- _port = port;
- }
-
- public static Configure AsDefault()
- {
- return new Configure("Default", IPAddress.Loopback, 1113);
- }
-
- public static Configure Named(string name)
- {
- return new Configure(name, IPAddress.Loopback, 1113);
- }
-
- public Configure ToServerNamed(string name)
- {
- var addresses = Dns.GetHostAddresses(name);
- if (addresses.Length == 0) throw new HostNotFoundException(name);
-
- return new Configure(_name, addresses[0], _port);
- }
- }
-
- public class HostNotFoundException : Exception
- {
- public HostNotFoundException(string name) : base("Host with name " + name + " not found")
- {
- }
+ FullConsistency,
+ ConsistentWrites,
+ ConsistentReads,
}
-}
+}
@@ -85,6 +85,9 @@
<Compile Include="ClientOperations\StartTransactionOperation.cs" />
<Compile Include="ClientOperations\TransactionalWriteOperation.cs" />
<Compile Include="Common\Log\DefaultLogger.cs" />
+ <Compile Include="Common\Utils\Tasks.cs" />
+ <Compile Include="ConnectionSettings.cs" />
+ <Compile Include="Connection\ClusterExplorer.cs" />
<Compile Include="Connection\ProjectionsManager.cs" />
<Compile Include="Connection\Subscription.cs" />
<Compile Include="Connection\SubscriptionsChannel.cs" />
@@ -109,7 +112,6 @@
<Compile Include="Common\Utils\BytesFormatter.cs" />
<Compile Include="Common\ConcurrentCollections\ConcurrentQueue.cs" />
<Compile Include="Common\ConcurrentCollections\ConcurrentStack.cs" />
- <Compile Include="Configure.cs" />
<Compile Include="ClientOperations\DeleteStreamOperation.cs" />
<Compile Include="ClientOperations\IClientOperation.cs" />
<Compile Include="ClientOperations\ReadStreamEventsForwardOperation.cs" />
@@ -118,6 +120,7 @@
<Compile Include="IProjectionsManagement.cs" />
<Compile Include="AllEventsSlice.cs" />
<Compile Include="Messages\ClientMessagesExtensions.cs" />
+ <Compile Include="Messages\ClusterMessages.cs" />
<Compile Include="Position.cs" />
<Compile Include="RecordedEvent.cs" />
<Compile Include="StreamPosition.cs" />
@@ -151,7 +154,6 @@
<Compile Include="Transport.Tcp\TcpConnector.cs" />
<Compile Include="Transport.Tcp\TcpTypedConnection.cs" />
<Compile Include="EventStoreConnection.cs" />
- <Compile Include="EventStore.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Transport.Tcp\TcpClientConnector.cs" />
<Compile Include="Transport.Tcp\IMonitoredTcpConnection.cs" />
Oops, something went wrong.

0 comments on commit 8a7c6ef

Please sign in to comment.