Beispiel #1
0
        public void TestExists()
        {
            using (var requestHandler = new TestRequestHandler())
                using (var client = new RingMasterClient(requestHandler))
                {
                    string path         = this.GetRandomString();
                    var    version      = this.GetRandomInt();
                    var    watcher      = new TestWatcher(this.GetRandomInt());
                    var    expectedStat = new Stat()
                    {
                        Version = this.GetRandomInt()
                    };

                    requestHandler.Implementation = request =>
                    {
                        Assert.IsTrue(request is RequestExists);
                        var existsRequest = (RequestExists)request;
                        Assert.AreEqual(path, existsRequest.Path);
                        Assert.AreEqual(watcher.Id, existsRequest.Watcher.Id);

                        return(new RequestResponse()
                        {
                            ResultCode = (int)RingMasterException.Code.Ok,
                            Content = expectedStat
                        });
                    };

                    client.SetWatcher(watcher);

                    IStat stat = client.Exists(path, watch: true).Result;
                    Assert.IsNotNull(stat);
                    Assert.AreEqual(expectedStat.Version, stat.Version);
                }
        }
Beispiel #2
0
        /// <summary>
        /// Thread to mock a NSM / LNM which is publishing VNET data
        /// </summary>
        /// <param name="cancel">Cancellation token</param>
        /// <param name="threadId">Thread sequence number</param>
        /// <param name="operationCount">Object to store operation statistics</param>
        private void MockLnmThread(CancellationToken cancel, int threadId, OperationCount operationCount)
        {
            using (var client = new RingMasterClient(serverAddress, null, null, 10000))
            {
                var rnd = new Random();

                while (!cancel.IsCancellationRequested)
                {
                    Task.Run(async() =>
                    {
                        try
                        {
                            var vnet = $"/mud/vnets/{CreateSpanningVnetId(threadId)}";
                            var stat = await client.Exists(vnet, null, true);
                            var ops  = new List <Op>();

                            if (stat == null)
                            {
                                ops.Add(Op.Create($"{vnet}/mappings/v4ca", null, null, CreateMode.PersistentAllowPathCreation));
                                ops.Add(Op.Create($"{vnet}/lnms/thread-{threadId}", null, null, CreateMode.PersistentAllowPathCreation));

                                await client.Multi(ops, true);
                                ops.Clear();

                                operationCount.AddCreate(2);
                            }

                            var mappingCount = rnd.Next(1, 1024 * 8);
                            for (int i = 0; i < mappingCount; i++)
                            {
                                ops.Add(Op.Create($"{vnet}/mappings/v4ca/{i}", null, null, CreateMode.PersistentAllowPathCreation));
                                operationCount.AddCreate(1);
                            }

                            await client.Multi(ops, true);
                            ops.Clear();

                            for (int i = 0; i < mappingCount; i++)
                            {
                                var data = new byte[rnd.Next(minPayloadSize, maxPayloadSize)];
                                ops.Add(Op.SetData($"{vnet}/mappings/v4ca/{i}", data, -1));
                                operationCount.AddSet(1);
                                operationCount.AddData(data.Length);
                            }

                            await client.Multi(ops, true);
                            ops.Clear();
                        }
                        catch (Exception ex)
                        {
                            operationCount.IncrementFailure();

                            // Ignore and keep going
                            log($"FAIL in {threadId}: {ex.Message}");
                        }
                    }).GetAwaiter().GetResult();
                }
            }
        }
        private void ConnectPerformanceTest(ConfigurationSection config, CancellationToken cancellationToken)
        {
            try
            {
                var instrumentation = new ConnectPerformanceInstrumentation(this.MetricsFactory);
                var random          = new Random();

                string connectionString = config.GetStringValue("TargetConnectionString");
                connectionString = Helpers.GetServerAddressIfNotProvided(connectionString);
                IPEndPoint[] endpoints                    = SecureTransport.ParseConnectionString(connectionString);
                string       testPath                     = config.GetStringValue("TestPath");
                int          numConnections               = config.GetIntValue("NumberOfConnections");
                int          maxConcurrentRequests        = config.GetIntValue("MaxConcurrentRequests");
                int          minConnectionLifetimeSeconds = config.GetIntValue("MinConnectionLifetimeSeconds");
                int          maxConnectionLifetimeSeconds = config.GetIntValue("MaxConnectionLifetimeSeconds");

                Func <IRingMasterRequestHandler> createConnection = () =>
                {
                    var connectionConfiguration = new SecureTransport.Configuration
                    {
                        UseSecureConnection          = false,
                        CommunicationProtocolVersion = RingMasterCommunicationProtocol.MaximumSupportedVersion,
                        MaxConnectionLifespan        = TimeSpan.FromSeconds(random.Next(minConnectionLifetimeSeconds, maxConnectionLifetimeSeconds))
                    };

                    var protocol  = new RingMasterCommunicationProtocol();
                    var transport = new SecureTransport(connectionConfiguration, instrumentation, cancellationToken);
                    var client    = new RingMasterClient(protocol, transport);
                    transport.StartClient(endpoints);

                    ConnectionStressServiceEventSource.Log.CreateConnection(
                        connectionConfiguration.UseSecureConnection,
                        connectionConfiguration.CommunicationProtocolVersion,
                        (long)connectionConfiguration.MaxConnectionLifespan.TotalSeconds);

                    client.Exists("/", watcher: null).Wait();
                    return((IRingMasterRequestHandler)client);
                };

                using (var connectPerformanceTest = new ConnectPerformance(instrumentation, maxConcurrentRequests, cancellationToken))
                {
                    ConnectionStressServiceEventSource.Log.ConnectPerformanceTestStarted(testPath, numConnections, minConnectionLifetimeSeconds, maxConnectionLifetimeSeconds);

                    connectPerformanceTest.EstablishConnections(createConnection, numConnections);

                    connectPerformanceTest.QueueRequests(testPath);
                }

                ConnectionStressServiceEventSource.Log.ConnectPerformanceTestCompleted();
            }
            catch (Exception ex)
            {
                ConnectionStressServiceEventSource.Log.ConnectPerformanceTestFailed(ex.ToString());
            }
        }
        private void ConnectPerformanceTest(SecureTransport.Configuration configuration, IPEndPoint[] endpoints, int numConnections)
        {
            var instrumentation = new ConnectPerformanceInstrumentation();
            var random          = new Random();

            int minConnectionLifetimeSeconds = int.Parse(appSettings["ConnectPerformance.MinConnectionLifetimeSeconds"]);
            int maxConnectionLifetimeSeconds = int.Parse(appSettings["ConnectPerformance.MaxConnectionLifetimeSeconds"]);

            Func <IRingMasterRequestHandler> createConnection = () =>
            {
                var connectionConfiguration = new SecureTransport.Configuration
                {
                    UseSecureConnection          = configuration.UseSecureConnection,
                    ClientCertificates           = configuration.ClientCertificates,
                    ServerCertificates           = configuration.ServerCertificates,
                    CommunicationProtocolVersion = configuration.CommunicationProtocolVersion,
                    MaxConnectionLifespan        = TimeSpan.FromSeconds(random.Next(minConnectionLifetimeSeconds, maxConnectionLifetimeSeconds)),
                };

                var protocol  = new RingMasterCommunicationProtocol();
                var transport = new SecureTransport(connectionConfiguration, instrumentation, CancellationToken.None);
                var client    = new RingMasterClient(protocol, transport);
                transport.StartClient(endpoints);

                client.Exists("/", watcher: null).Wait();
                return((IRingMasterRequestHandler)client);
            };

            using (var connectPerformanceTest = new ConnectPerformance(instrumentation, this.MaxConcurrency, CancellationToken.None))
            {
                Trace.TraceInformation($"Connect performance test numConnections={numConnections}, path={this.TestPath}, minConnectionLifetimeSeconds={minConnectionLifetimeSeconds}, maxConnectionLifetimeSeconds={maxConnectionLifetimeSeconds}");

                connectPerformanceTest.EstablishConnections(createConnection, numConnections);

                var task = Task.Run(() => connectPerformanceTest.QueueRequests(this.TestPath));

                long lastSuccessCount = 0;
                var  timer            = Stopwatch.StartNew();
                while (!task.Wait(5000))
                {
                    timer.Stop();
                    long rate = (long)((instrumentation.Success - lastSuccessCount) * 1000) / timer.ElapsedMilliseconds;
                    Trace.TraceInformation($"Connections created={instrumentation.ConnectionCreatedCount}, closed={instrumentation.ConnectionClosedCount}, requestSuccess={instrumentation.Success}, requestFailure={instrumentation.Failure}, rate={rate}");
                    timer.Restart();
                    lastSuccessCount = instrumentation.Success;
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Wait until a stable connection can be established with the given ringmaster.
        /// </summary>
        /// <param name="ringMaster">RingMaster client</param>
        /// <param name="maxAttempts">Maximum number of attempts</param>
        /// <returns>A Task that resolves to <c>true</c> if the connection was successful</returns>
        private static async Task <bool> WaitForStableConnection(RingMasterClient ringMaster, int maxAttempts)
        {
            for (int retryCount = 0; retryCount < maxAttempts; retryCount++)
            {
                try
                {
                    await ringMaster.Exists("/", watcher : null);

                    return(true);
                }
                catch (Exception ex)
                {
                    Trace.TraceError("WaitForStableConnection. exception={0}, retryCount={1}, maxAttempts={2}", ex.Message, retryCount, maxAttempts);
                }

                await Task.Delay(1000);
            }

            return(false);
        }
Beispiel #6
0
        public void TestWrongChildrenCountAfterFailedMulti()
        {
            TestWrongNumChildrenInStastAsync().GetAwaiter().GetResult();

            async Task TestWrongNumChildrenInStastAsync()
            {
                const string path = "/$rmbvt/test";
                var          stop = false;

                // Create a parent node with 3 children. During the test, the number of children is not expected
                // to change.
                using (var rm = new RingMasterClient(serverAddress, null, null, 10000))
                {
                    var ops = new List <Op>
                    {
                        Op.Create($"{path}/parent/child1", null, null, CreateMode.PersistentAllowPathCreation),
                        Op.Create($"{path}/parent/child2", null, null, CreateMode.PersistentAllowPathCreation),
                        Op.Create($"{path}/parent/child3", null, null, CreateMode.PersistentAllowPathCreation),
                    };

                    await rm.Multi(ops);
                }

                // Start multiple threads to stress the backend
                var tasks = Enumerable.Range(0, 2).Select(_ => Task.Run(async() =>
                {
                    using (var rm = new RingMasterClient(serverAddress, null, null, 10000))
                    {
                        var ops = new List <Op>();

                        while (!stop)
                        {
                            // Randomly add or delete children in Multi
                            ops.Clear();
                            ops.AddRange(
                                Enumerable.Range(1, 3).Select(
                                    x => Op.Delete($"{path}/parent/child{x}", -1, false)));

                            // Add one more operation to fail the multi, so nothing get committed, in other words the
                            // locklist will always abort.
                            ops.Add(Op.GetData(
                                        $"{path}/parent/nonexisting/node",
                                        Azure.Networking.Infrastructure.RingMaster.Requests.RequestGetData.GetDataOptions.None,
                                        null));
                            var result = (await rm.Multi(ops)).Last();
                            Assert.AreEqual(OpCode.Error, result.ResultType);
                            Assert.AreEqual(RingMasterException.Code.Nonode, result.ErrCode);

                            var children = await rm.GetChildren($"{path}/parent", null);
                            var stat     = await rm.Exists($"{path}/parent", null);

                            Assert.AreEqual(
                                children.Count,
                                stat.NumChildren,
                                $"Children count {children.Count} should be consistent with Stat {stat.NumChildren}");
                            Assert.AreEqual(
                                3,
                                stat.NumChildren,
                                "Number of children returned by Exists should not change");
                        }
                    }
                })).ToArray();

                var clock = Stopwatch.StartNew();

                while (clock.Elapsed.TotalMinutes < 60)
                {
                    await Task.Delay(1000);

                    if (tasks.Any(t => t.IsCompleted))
                    {
                        break;
                    }
                }

                stop = true;
                await Task.WhenAll(tasks);
            }
        }
Beispiel #7
0
        public void TestConflictingCreateDeleteExists()
        {
            TestConflictingCreateDeleteExistsAsync().GetAwaiter().GetResult();

            async Task TestConflictingCreateDeleteExistsAsync()
            {
                const string path  = "/$rmbvt/test";
                var          stop  = false;
                var          taskW = Task.Run(async() =>
                {
                    while (!stop)
                    {
                        try
                        {
                            using (var rm = new RingMasterClient(serverAddress, null, null, 10000))
                            {
                                while (!stop)
                                {
                                    await rm.Create(path, null, null, CreateMode.PersistentAllowPathCreation | CreateMode.SuccessEvenIfNodeExistsFlag);
                                    await rm.Delete(path, -1, DeleteMode.SuccessEvenIfNodeDoesntExist);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            var rmException = ex as RingMasterException;
                            if (rmException != null && rmException.ErrorCode == RingMasterException.Code.Operationtimeout)
                            {
                                // Do thing. Continue test.
                            }
                            else
                            {
                                stop = true;
                                throw;
                            }
                        }
                    }
                });

                var taskR = Task.Run(async() =>
                {
                    while (!stop)
                    {
                        try
                        {
                            using (var rm = new RingMasterClient(serverAddress, null, null, 10000))
                            {
                                while (!stop)
                                {
                                    await Task.WhenAll(
                                        rm.Exists(path, null, true));
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            var rmException = ex as RingMasterException;
                            if (rmException != null && rmException.ErrorCode == RingMasterException.Code.Operationtimeout)
                            {
                                // Do thing. Continue test.
                            }
                            else
                            {
                                stop = true;
                                throw;
                            }
                        }
                    }
                });

                var clock = Stopwatch.StartNew();

                SpinWait.SpinUntil(() => clock.Elapsed.TotalSeconds >= 3600 || stop);

                stop = true;
                await Task.WhenAll(taskW, taskR).ContinueWith(t => log(t.Exception?.ToString()));
            }
        }