コード例 #1
0
        public void TestSyn()
        {
            const string node1Endpoint = "192.168.1.1:18841";
            const string node2Endpoint = "192.168.1.2:18841";

            var node1 = CreateNode(node1Endpoint, new[] { node2Endpoint }.Concat(SeedsEndpoint));
            var node2 = CreateNode(node2Endpoint, new[] { node1Endpoint }.Concat(SeedsEndpoint));

            var synRequest = new Ping1Request();

            synRequest.NodesSynopsis.AddRange(node1.GetNodesSynposis());

            var synResponse = node2.Syn(synRequest);

            Assert.Equal(
                new NodeInformationSynopsis
            {
                Endpoint = node1.EndPoint,
                LastKnownPropertyVersion = 0,
                NodeVersion = 0
            },
                synResponse.RequiredNodesSynopsis.Single());
            Assert.Equal(
                node2.nodeInformationDictionary[node2.EndPoint],
                synResponse.UpdatedNodes.Single());
        }
コード例 #2
0
        public Ping1Response Syn(Ping1Request syn)
        {
            lock (lockObject)
            {
                var response = new Ping1Response();
                FillRequiredOrUpdatedNodes(
                    syn.NodesSynopsis,
                    response.RequiredNodesSynopsis,
                    response.UpdatedNodes);

                return(response);
            }
        }
コード例 #3
0
        public void PrintMessageSizeForClusterSize()
        {
            var node          = CreateNode(SelfEndpoint, SeedsEndpoint);
            var baseIpAddress = IPAddress.Parse("192.168.1.1");

            for (int i = 0; i < 10000; i++)
            {
#pragma warning disable CS0618
                baseIpAddress.Address++;
#pragma warning restore CS0618
                var endpoint = baseIpAddress.ToString() + ":19999";
                node.nodeInformationDictionary.Add(
                    endpoint,
                    NodeInformation.CreateSelfNode(endpoint));
            }

            var ping1Request = new Ping1Request
            {
                NodesSynopsis = { node.GetNodesSynposis() }
            };
            logger.LogInformation("Ping1 request size: {0}", ping1Request.CalculateSize());
        }
コード例 #4
0
 public override Task <Ping1Response> Ping1(Ping1Request request, ServerCallContext context)
 {
     return(Task.FromResult(node.Syn(request)));
 }
コード例 #5
0
        public void TestFullSyncBasic()
        {
            const string node1Endpoint = "192.168.1.1:18841";
            const string node2Endpoint = "192.168.1.2:18841";

            var node1 = CreateNode(node1Endpoint, new[] { node2Endpoint }.Concat(SeedsEndpoint));
            var node2 = CreateNode(node2Endpoint, new[] { node1Endpoint }.Concat(SeedsEndpoint));

            var synRequest = new Ping1Request();

            synRequest.NodesSynopsis.AddRange(node1.GetNodesSynposis());

            var synResponse = node2.Syn(synRequest);

            var ack2Request  = node1.Ack1(synResponse);
            var ack2Response = node2.Ack2(ack2Request);

            Assert.Equal(new Ping2Response(), ack2Response);

            Assert.Equal(
                new NodeInformation
            {
                Endpoint          = node1Endpoint,
                NodeStateProperty = new VersionedProperty
                {
                    StateProperty = NodeState.Live,
                    Version       = 2
                },
                NodeVersion = GetNodeVersion(),
            },
                node1.nodeInformationDictionary[node1Endpoint]);
            Assert.Equal(
                new NodeInformation
            {
                Endpoint          = node2Endpoint,
                NodeStateProperty = new VersionedProperty
                {
                    StateProperty = NodeState.Live,
                    Version       = 2
                },
                NodeVersion = GetNodeVersion(),
            },
                node1.nodeInformationDictionary[node2Endpoint]);
            foreach (var e in SeedsEndpoint)
            {
                Assert.Equal(
                    NodeInformation.CreateSeedNode(e),
                    node1.nodeInformationDictionary[e]);
            }

            Assert.Equal(
                new NodeInformation
            {
                Endpoint          = node1Endpoint,
                NodeStateProperty = new VersionedProperty
                {
                    StateProperty = NodeState.Live,
                    Version       = 2
                },
                NodeVersion = GetNodeVersion(),
            },
                node2.nodeInformationDictionary[node1Endpoint]);
            Assert.Equal(
                new NodeInformation
            {
                Endpoint          = node2Endpoint,
                NodeStateProperty = new VersionedProperty
                {
                    StateProperty = NodeState.Live,
                    Version       = 2
                },
                NodeVersion = GetNodeVersion(),
            },
                node2.nodeInformationDictionary[node2Endpoint]);
            foreach (var e in SeedsEndpoint)
            {
                Assert.Equal(
                    NodeInformation.CreateSeedNode(e),
                    node2.nodeInformationDictionary[e]);
            }
        }
コード例 #6
0
        private async Task SyncWithPeerAsync(string peerEndpoint, Random random, CancellationToken cancellationToken)
        {
            var client  = clientFactory.Invoke(peerEndpoint);
            var options = optionsMonitor.CurrentValue;

            var synRequest = new Ping1Request();

            synRequest.NodesSynopsis.AddRange(node.GetNodesSynposis());

            bool failed = false;

            try
            {
                var synResponse = await client.Ping1Async(
                    synRequest,
                    deadline : DateTime.UtcNow + TimeSpan.FromMilliseconds(options.PingTimeoutMilliseconds),
                    cancellationToken : cancellationToken);

                var ack2Request = node.Ack1(synResponse);

                var ack2Response = await client.Ping2Async(
                    ack2Request,
                    deadline : DateTime.UtcNow + TimeSpan.FromMilliseconds(options.PingTimeoutMilliseconds),
                    cancellationToken : cancellationToken);
            }
            catch (GrpcException ex)
            {
                logger.LogError(ex, "Cannot ping peer {0} because {1}", peerEndpoint, ex.Message);
                failed = true;
            }

            if (failed)
            {
                // TODO: pick k nodes & forward ping concurrently, currently only implement k = 1
                var forwarderEndpoint = RandomPickNode(random, node.LiveEndpoints, new List <string>());
                if (forwarderEndpoint == null)
                {
                    throw new InvalidOperationException("Cannot pick a node for forwarder");
                }

                logger.LogInformation("Pick peer {0} as forwarder to connect peer {1}", forwarderEndpoint, peerEndpoint);
                client = clientFactory.Invoke(forwarderEndpoint);

                var forwardedSynResponse = await client.ForwardAsync(
                    new ForwardRequest
                {
                    TargetEndpoint = peerEndpoint,
                    TargetMethod   = nameof(client.Ping1),
                    Ping1Request   = synRequest
                },
                    deadline : DateTime.UtcNow + TimeSpan.FromMilliseconds(options.ForwardTimeoutMilliseconds),
                    cancellationToken : cancellationToken);

                Ping1Response synResponse;
                switch (forwardedSynResponse.ResponseCase)
                {
                case ForwardResponse.ResponseOneofCase.ErrorMessage:
                    throw new RpcRemoteException(forwardedSynResponse.ErrorMessage);

                case ForwardResponse.ResponseOneofCase.None:
                    throw new RpcInvalidResponseException("Forward response not set content from remote");

                case ForwardResponse.ResponseOneofCase.Ping1Response:
                    synResponse = forwardedSynResponse.Ping1Response;
                    break;

                default:
                    throw new RpcInvalidResponseException("Unknown response type");
                }

                var ack2Request           = node.Ack1(synResponse);
                var forwardedAck2Response = await client.ForwardAsync(
                    new ForwardRequest
                {
                    TargetEndpoint = peerEndpoint,
                    TargetMethod   = nameof(client.Ping2),
                    Ping2Request   = ack2Request
                },
                    deadline : DateTime.UtcNow + TimeSpan.FromMilliseconds(options.ForwardTimeoutMilliseconds),
                    cancellationToken : cancellationToken);

                Ping2Response ack2Response;
                switch (forwardedAck2Response.ResponseCase)
                {
                case ForwardResponse.ResponseOneofCase.ErrorMessage:
                    throw new RpcRemoteException(forwardedSynResponse.ErrorMessage);

                case ForwardResponse.ResponseOneofCase.None:
                    throw new RpcInvalidResponseException("Forward response not set content from remote");

                case ForwardResponse.ResponseOneofCase.Ping2Response:
                    ack2Response = forwardedAck2Response.Ping2Response;
                    break;

                default:
                    throw new RpcInvalidResponseException("Unknown response type");
                }
            }
        }