protected Node(NodeInfo identity, NodeConfiguration config) { Logger = config.LoggerDelegate; SeedNode = config.SeedNode; SuccessorCount = config.SuccessorCount; Serializer = config.Serializer; Marshaller = new NodeMarshaller(Serializer, config.HashingService); MessageBus = new MemoryBus(); // We can change the publishing strategy factory so we can log everything... InitHandlers(); Identity = identity; Successor = identity; Predecessor = null; SocketFactory = config.NodeSocketFactory; HashingService = config.HashingService; CorrelationFactory = config.CorrelationFactory; Clock = config.Clock; Janitor = new DisposableStack(); Poller = Janitor.Push(new NetMQPoller()); InitTimer = CreateInitTimer(); ListeningSocket = Janitor.Push(SocketFactory.CreateBindingSocket(Identity.HostAndPort)); InitListeningSocket(); ForwardingSockets = Janitor.Push(new SocketCache(SocketFactory, Clock)); Actor = Janitor.Push(CreateActor()); InitTimer.Elapsed += (sender, args) => { Publish(new NodeReady(Identity.RoutingHash)); }; FingerTable = new FingerTable(Identity, Identity.RoutingHash.BitCount); SuccessorTable = new SuccessorTable(Identity, config.SuccessorCount); }
public async Task UpgradedConnectionsCountsAgainstDifferentLimit() { using (var server = CreateServerWithMaxConnections(async context => { var feature = context.Features.Get <IHttpUpgradeFeature>(); if (feature.IsUpgradableRequest) { var stream = await feature.UpgradeAsync(); // keep it running until aborted while (!context.RequestAborted.IsCancellationRequested) { await Task.Delay(100); } } }, max: 1)) { using (var disposables = new DisposableStack <InMemoryConnection>()) { var upgraded = server.CreateConnection(); disposables.Push(upgraded); await upgraded.SendEmptyGetWithUpgrade(); await upgraded.Receive("HTTP/1.1 101"); // once upgraded, normal connection limit is decreased to allow room for more "normal" connections var connection = server.CreateConnection(); disposables.Push(connection); await connection.SendEmptyGetAsKeepAlive(); await connection.Receive("HTTP/1.1 200 OK"); using (var rejected = server.CreateConnection()) { try { // this may throw IOException, depending on how fast Kestrel closes the socket await rejected.SendEmptyGetAsKeepAlive(); } catch { } // connection should close without sending any data await rejected.WaitForConnectionClose(); } } await server.StopAsync(); } }
private bool TryAddTree(Address trackedTree) { bool treeAdded = false; bool wasUntracked = _trackingOverrides.TryGetValue(trackedTree, out bool result) && result; if (!wasUntracked) { if (_stateReader.GetCode(_blockFinder.Head.StateRoot, trackedTree).Length != 0) { ShaBaselineTree tree = new(_baselineDb, _metadataBaselineDb, trackedTree.Bytes, TruncationLength, _logger); treeAdded = _baselineTrees.TryAdd(trackedTree, tree); if (treeAdded) { BaselineTreeTracker?tracker = new(trackedTree, tree, _blockProcessor, _baselineTreeHelper, _blockFinder, _logger); _disposableStack.Push(tracker); } } _trackingOverrides.TryAdd(trackedTree, false); } else { treeAdded = _trackingOverrides.TryUpdate(trackedTree, false, true); } return(treeAdded); }
public async Task RejectsUpgradeWhenLimitReached() { const int limit = 10; var upgradeTcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); var serviceContext = new TestServiceContext(LoggerFactory); serviceContext.ConnectionManager = new ConnectionManager(serviceContext.Log, ResourceCounter.Quota(limit)); using (var server = new TestServer(async context => { var feature = context.Features.Get <IHttpUpgradeFeature>(); if (feature.IsUpgradableRequest) { try { var stream = await feature.UpgradeAsync(); while (!context.RequestAborted.IsCancellationRequested) { await Task.Delay(100); } } catch (InvalidOperationException ex) { upgradeTcs.TrySetException(ex); } } }, serviceContext)) { using (var disposables = new DisposableStack <InMemoryConnection>()) { for (var i = 0; i < limit; i++) { var connection = server.CreateConnection(); disposables.Push(connection); await connection.SendEmptyGetWithUpgradeAndKeepAlive(); await connection.Receive("HTTP/1.1 101"); } using (var connection = server.CreateConnection()) { await connection.SendEmptyGetWithUpgradeAndKeepAlive(); await connection.Receive("HTTP/1.1 200"); } } await server.StopAsync(); } var exception = await Assert.ThrowsAsync <InvalidOperationException>(async() => await upgradeTcs.Task.TimeoutAfter(TimeSpan.FromSeconds(60))); Assert.Equal(CoreStrings.UpgradedConnectionLimitReached, exception.Message); }
protected Node(NodeInfo identity, NodeConfiguration config) { Config = config; Identity = identity; Predecessor = Identity; Clock = Config.Clock; CorrelationFactory = Config.CorrelationFactory; Janitor = new DisposableStack(); MessageBus = new MemoryBus(); Poller = Janitor.Push(new NetMQPoller()); Logger = Config.LoggerDelegate; Marshaller = Config.MarshallerFactory.Create(); ExpiryCalculator = Config.ExpiryCalculator; Log($"Binding to {Config.NodeSocketFactory.BindingConnectionString(Identity.HostAndPort)}"); ListeningSocket = Janitor.Push(Config.NodeSocketFactory.CreateBindingSocket(Identity.HostAndPort)); ForwardingSockets = Janitor.Push(new SocketCache(Config.NodeSocketFactory, Clock)); // Chicken and egg scenario where we require an actor! CommunicationManager = config.CommunicationManagerFactory.Create(Identity, Marshaller, ForwardingSockets, MessageBus, Log); Actor = Janitor.Push(CreateActor()); ForwardingSockets.AddActor(Identity.HostAndPort, Actor); Janitor.Push(new DisposableAction(() => { Poller.Remove(ListeningSocket); })); Janitor.Push(new DisposableAction( () => { ListeningSocket.ReceiveReady += ListeningSocketReceiveReady; }, () => { ListeningSocket.ReceiveReady -= ListeningSocketReceiveReady; })); ActionScheduler = Janitor.Push(new NodeActionScheduler(Clock, Config.ActionTimerFactory.Create(), Marshaller, Actor)); MessageBus.Subscribe(new NodeHandler(this, ActionScheduler)); var awaitHandler = Janitor.Push(new AwaitAckHandler(ActionScheduler, ExpiryCalculator, Marshaller, Actor, Log, Config.AwaitSettings)); MessageBus.Subscribe(awaitHandler); MessageBus.Subscribe(new JoinNetworkHandler(this, CommunicationManager)); MessageBus.Subscribe(new StabilizeHandler(this, CommunicationManager)); MessageBus.Subscribe(new RectifyHandler(this, CommunicationManager)); MessageBus.Subscribe(new NotifyHandler(this, CommunicationManager)); FingerTable = new FingerTable(Identity, Identity.RoutingHash.BitCount); SuccessorTable = new SuccessorTable(Identity, Config.SuccessorCount); // Let everything know we're ready to go. CommunicationManager.SendInternal(new NodeInitialised()); }
public async Task RejectsConnectionsWhenLimitReached() { const int max = 10; var requestTcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); using (var server = CreateServerWithMaxConnections(async context => { await context.Response.WriteAsync("Hello"); await requestTcs.Task; }, max)) { using (var disposables = new DisposableStack <InMemoryConnection>()) { for (var i = 0; i < max; i++) { var connection = server.CreateConnection(); disposables.Push(connection); await connection.SendEmptyGetAsKeepAlive(); await connection.Receive("HTTP/1.1 200 OK"); } // limit has been reached for (var i = 0; i < 10; i++) { using (var connection = server.CreateConnection()) { try { // this may throw IOException, depending on how fast Kestrel closes the socket await connection.SendEmptyGetAsKeepAlive(); } catch { } // connection should close without sending any data await connection.WaitForConnectionClose(); } } requestTcs.TrySetResult(null); } await server.StopAsync(); } }
public async Task RejectsConnectionsWhenLimitReached() { const int max = 10; var(serviceContext, _) = SetupMaxConnections(max); var requestTcs = new TaskCompletionSource <object>(); using (var server = new TestServer(async context => { await context.Response.WriteAsync("Hello"); await requestTcs.Task; }, serviceContext)) using (var disposables = new DisposableStack <TestConnection>()) { for (var i = 0; i < max; i++) { var connection = server.CreateConnection(); disposables.Push(connection); await connection.SendEmptyGetAsKeepAlive(); await connection.Receive("HTTP/1.1 200 OK"); } // limit has been reached for (var i = 0; i < 10; i++) { using (var connection = server.CreateConnection()) { try { // this may throw IOException, depending on how fast Kestrel closes the socket await connection.SendEmptyGetAsKeepAlive(); } catch { } // connection should close without sending any data await connection.WaitForConnectionClose().TimeoutAfter(TimeSpan.FromSeconds(15)); } } requestTcs.TrySetResult(null); } }
void Run(string[] args) { using (var janitor = new DisposableStack()) { var logger = janitor.Push(new FileLogger()); var hostEntry = _dnsProvider.GetHostEntry("localhost"); var config = new MyAppNodeConfiguration { HashingService = _hashingService, Serializer = _msgSerializer, NodeSocketFactory = _nodeSocketFactory, Clock = _clock, CorrelationFactory = _correlationFactory, SuccessorCount = 2, SeedNode = $"{hostEntry.HostName}:{SeedPort}", LoggerDelegate = logger.WriteLine, ExpiryCalculator = _expiryCalculator, Random = _random, ActionTimerFactory = _actionTimerFactory, MarshallerFactory = _marshallerFactory, CommunicationManagerFactory = _communicationManagerFactory, }; var factory = new MyAppNodeFactory(config); var hostAndPort0 = $"{hostEntry.HostName}:{SeedPort}"; var id0 = Node.CreateIdentifier(hostAndPort0); var nodes = new List <Node>(); nodes.Add(janitor.Push(factory.CreateNode(id0, hostAndPort0))); for (int i = 9001; i < 9003; ++i) { var hostAndPort = $"{hostEntry.HostName}:{i}"; var id = Node.CreateIdentifier(hostAndPort); nodes.Add(janitor.Push(factory.CreateNode(id, hostAndPort))); Thread.Sleep(1500); } Thread.Sleep(1000); Console.WriteLine("***** Connectivity Summary *****"); Console.ReadKey(); foreach (var node in nodes) { Console.WriteLine($"{node.Identity}\tS: {node.Successor}\tP: {node.Predecessor}"); } Console.ReadKey(); //var terminate = new TerminateNode(node0.Identity.RoutingHash); //node0.Publish(terminate); //terminate = new TerminateNode(node1.Identity.RoutingHash); //node1.Publish(terminate); //terminate = new TerminateNode(node2.Identity.RoutingHash); //node2.Publish(terminate); } Console.ReadKey(); }