Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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();
            }
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        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());
        }
Exemplo n.º 6
0
        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);
                }
        }
Exemplo n.º 8
0
        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();
        }