protected override bool InspectPackage(TcpPackage package, out InspectionResult result)
        {
            if (package.Command == TcpCommand.PersistentSubscriptionConfirmation)
            {
                var dto = package.Data.Deserialize <ClientMessage.PersistentSubscriptionConfirmation>();
                ConfirmSubscription(dto.LastCommitPosition, dto.LastEventNumber);
                result          = new InspectionResult(InspectionDecision.Subscribed, "SubscriptionConfirmation");
                _subscriptionId = dto.SubscriptionId;
                return(true);
            }

            if (package.Command == TcpCommand.PersistentSubscriptionStreamEventAppeared)
            {
                var dto = package.Data.Deserialize <ClientMessage.PersistentSubscriptionStreamEventAppeared>();
                EventAppeared(new PersistentSubscriptionResolvedEvent(new ResolvedEvent(dto.Event), dto.RetryCount));
                result = new InspectionResult(InspectionDecision.DoNothing, "StreamEventAppeared");
                return(true);
            }

            if (package.Command == TcpCommand.SubscriptionDropped)
            {
                var dto = package.Data.Deserialize <ClientMessage.SubscriptionDropped>();
                if (dto.Reason == ClientMessage.SubscriptionDropped.SubscriptionDropReason.AccessDenied)
                {
                    DropSubscription(SubscriptionDropReason.AccessDenied,
                                     new AccessDeniedException("You do not have access to the stream."));
                    result = new InspectionResult(InspectionDecision.EndOperation, "SubscriptionDropped");
                    return(true);
                }

                if (dto.Reason == ClientMessage.SubscriptionDropped.SubscriptionDropReason.NotFound)
                {
                    DropSubscription(SubscriptionDropReason.NotFound, new ArgumentException("Subscription not found"));
                    result = new InspectionResult(InspectionDecision.EndOperation, "SubscriptionDropped");
                    return(true);
                }

                if (dto.Reason == ClientMessage.SubscriptionDropped.SubscriptionDropReason
                    .PersistentSubscriptionDeleted)
                {
                    DropSubscription(SubscriptionDropReason.PersistentSubscriptionDeleted,
                                     new PersistentSubscriptionDeletedException());
                    result = new InspectionResult(InspectionDecision.EndOperation, "SubscriptionDropped");
                    return(true);
                }

                if (dto.Reason == ClientMessage.SubscriptionDropped.SubscriptionDropReason.SubscriberMaxCountReached)
                {
                    DropSubscription(SubscriptionDropReason.MaxSubscribersReached,
                                     new MaximumSubscribersReachedException());
                    result = new InspectionResult(InspectionDecision.EndOperation, "SubscriptionDropped");
                    return(true);
                }

                DropSubscription((SubscriptionDropReason)dto.Reason, null, _getConnection());
                result = new InspectionResult(InspectionDecision.EndOperation, "SubscriptionDropped");
                return(true);
            }

            result = null;
            return(false);
        }
Beispiel #2
0
        private void Write(Status status, int writerIdx, CommandProcessorContext context, int requests,
                           ManualResetEventSlim finish)
        {
            TcpTypedConnection <byte[]> connection;
            var iteration = new AutoResetEvent(false);

            var sent = 0;

            var prepareTimeouts      = 0;
            var commitTimeouts       = 0;
            var forwardTimeouts      = 0;
            var wrongExpectedVersion = 0;
            var streamsDeleted       = 0;

            var failed = 0;

            var rnd = new Random(writerIdx);

            var streamIdx = -1;
            var head      = -1;

            Action <TcpTypedConnection <byte[]>, TcpPackage> packageHandler = (conn, pkg) => {
                var dto = pkg.Data.Deserialize <TcpClientMessageDto.WriteEventsCompleted>();
                switch (dto.Result)
                {
                case TcpClientMessageDto.OperationResult.Success:
                    lock (_heads) {
                        var currentHead = _heads[streamIdx];
                        Ensure.Equal(currentHead, head, "currentHead");
                        _heads[streamIdx]++;
                    }

                    break;

                case TcpClientMessageDto.OperationResult.PrepareTimeout:
                    prepareTimeouts++;
                    failed++;
                    break;

                case TcpClientMessageDto.OperationResult.CommitTimeout:
                    commitTimeouts++;
                    failed++;
                    break;

                case TcpClientMessageDto.OperationResult.ForwardTimeout:
                    forwardTimeouts++;
                    failed++;
                    break;

                case TcpClientMessageDto.OperationResult.WrongExpectedVersion:
                    wrongExpectedVersion++;
                    failed++;
                    break;

                case TcpClientMessageDto.OperationResult.StreamDeleted:
                    streamsDeleted++;
                    failed++;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                sent++;
                if (sent % 1000 == 0)
                {
                    status.ReportWritesProgress(writerIdx, sent, prepareTimeouts, commitTimeouts, forwardTimeouts,
                                                wrongExpectedVersion, streamsDeleted, failed, requests);
                }
                iteration.Set();
            };

            Action <TcpTypedConnection <byte[]> >             established = _ => { };
            Action <TcpTypedConnection <byte[]>, SocketError> closed      = null;

            closed = (_, __) => {
                if (!context._tcpTestClient.Options.Reconnect)
                {
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
                connection =
                    context._tcpTestClient.CreateTcpConnection(context, packageHandler, cn => iteration.Set(), closed, false);
            };

            connection = context._tcpTestClient.CreateTcpConnection(context, packageHandler, established, closed, false);

            for (var i = 0; i < requests; ++i)
            {
                streamIdx = NextStreamForWriting(rnd, writerIdx);
                lock (_heads) {
                    head = _heads[streamIdx];
                }

                var evnt  = CreateEvent(_streams[streamIdx], head + 1);
                var write = new TcpClientMessageDto.WriteEvents(
                    _streams[streamIdx],
                    head,
                    new[] {
                    new TcpClientMessageDto.NewEvent(evnt.EventId.ToByteArray(), evnt.EventType,
                                                     evnt.IsJson ? 1 : 0, 0, evnt.Data, evnt.Metadata)
                },
                    false);

                var package = new TcpPackage(TcpCommand.WriteEvents, Guid.NewGuid(), write.Serialize());
                connection.EnqueueSend(package.AsByteArray());
                iteration.WaitOne();
            }

            status.ReportWritesProgress(writerIdx, sent, prepareTimeouts, commitTimeouts, forwardTimeouts,
                                        wrongExpectedVersion, streamsDeleted, failed, requests);
            status.FinilizeStatus(writerIdx, failed != sent);
            context._tcpTestClient.Options.Reconnect = false;
            connection.Close();
            finish.Set();
        }
Beispiel #3
0
        public bool Execute(CommandProcessorContext context, string[] args)
        {
            bool forward        = true;
            long commitPos      = 0;
            long preparePos     = 0;
            bool posOverriden   = false;
            bool resolveLinkTos = false;
            bool requireLeader  = false;

            if (args.Length > 0)
            {
                if (args.Length != 1 && args.Length != 3 && args.Length != 4)
                {
                    return(false);
                }

                if (args[0].ToUpper() == "F")
                {
                    forward = true;
                }
                else if (args[0].ToUpper() == "B")
                {
                    forward = false;
                }
                else
                {
                    return(false);
                }

                if (args.Length >= 3)
                {
                    posOverriden = true;
                    if (!long.TryParse(args[1], out commitPos) || !long.TryParse(args[2], out preparePos))
                    {
                        return(false);
                    }
                }

                if (args.Length >= 4)
                {
                    requireLeader = bool.Parse(args[3]);
                }
            }

            if (!posOverriden)
            {
                commitPos  = forward ? 0 : -1;
                preparePos = forward ? 0 : -1;
            }

            context.IsAsync();

            int total               = 0;
            var sw                  = new Stopwatch();
            var tcpCommand          = forward ? TcpCommand.ReadAllEventsForward : TcpCommand.ReadAllEventsBackward;
            var tcpCommandToReceive = forward ? TcpCommand.ReadAllEventsForwardCompleted : TcpCommand.ReadAllEventsBackwardCompleted;

            context._tcpTestClient.CreateTcpConnection(
                context,
                connectionEstablished: conn => {
                context.Log.Information("[{remoteEndPoint}, L{localEndPoint}]: Reading all {readDirection}...",
                                        conn.RemoteEndPoint, conn.LocalEndPoint, forward ? "FORWARD" : "BACKWARD");

                var readDto =
                    new TcpClientMessageDto.ReadAllEvents(commitPos, preparePos, 10, resolveLinkTos, requireLeader);
                var package = new TcpPackage(tcpCommand, Guid.NewGuid(), readDto.Serialize()).AsByteArray();
                sw.Start();
                conn.EnqueueSend(package);
            },
                handlePackage: (conn, pkg) => {
                if (pkg.Command != tcpCommandToReceive)
                {
                    context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                    return;
                }

                var dto = pkg.Data.Deserialize <TcpClientMessageDto.ReadAllEventsCompleted>();
                if (dto.Events.IsEmpty())
                {
                    sw.Stop();
                    context.Log.Information("=== Reading ALL {readDirection} completed in {elapsed}. Total read: {total}",
                                            forward ? "FORWARD" : "BACKWARD", sw.Elapsed, total);
                    context.Success();
                    conn.Close();
                    return;
                }

                var sb = new StringBuilder();
                for (int i = 0; i < dto.Events.Length; ++i)
                {
                    var evnt = dto.Events[i].Event;
                    sb.AppendFormat(
                        "\n{0}:\tStreamId: {1},\n\tEventNumber: {2},\n\tData:\n{3},\n\tEventType: {4}\n",
                        total,
                        evnt.EventStreamId,
                        evnt.EventNumber,
                        Helper.UTF8NoBom.GetString(evnt.Data),
                        evnt.EventType);
                    total += 1;
                }

                context.Log.Information("Next {count} events read:\n{events}", dto.Events.Length, sb.ToString());

                var readDto = new TcpClientMessageDto.ReadAllEvents(dto.NextCommitPosition, dto.NextPreparePosition,
                                                                    10, resolveLinkTos, requireLeader);
                var package = new TcpPackage(tcpCommand, Guid.NewGuid(), readDto.Serialize()).AsByteArray();
                conn.EnqueueSend(package);
            },
                connectionClosed: (connection, error) => context.Fail(reason: "Connection was closed prematurely."));

            context.WaitForCompletion();
            return(true);
        }
Beispiel #4
0
        private void PingFloodWaiting(CommandProcessorContext context, int clientsCnt, long requestsCnt)
        {
            context.IsAsync();

            var  clients     = new List <TcpTypedConnection <byte[]> >();
            var  threads     = new List <Thread>();
            var  doneEvent   = new ManualResetEventSlim(false);
            var  clientsDone = 0;
            long all         = 0;

            for (int i = 0; i < clientsCnt; i++)
            {
                var autoResetEvent = new AutoResetEvent(false);
                var client         = context.Client.CreateTcpConnection(
                    context,
                    (_, __) => {
                    Interlocked.Increment(ref all);
                    autoResetEvent.Set();
                },
                    connectionClosed: (conn, err) => context.Fail(reason: "Connection was closed prematurely."));
                clients.Add(client);

                var count = requestsCnt / clientsCnt + ((i == clientsCnt - 1) ? requestsCnt % clientsCnt : 0);
                threads.Add(new Thread(() => {
                    for (int j = 0; j < count; ++j)
                    {
                        var package = new TcpPackage(TcpCommand.Ping, Guid.NewGuid(), null);
                        client.EnqueueSend(package.AsByteArray());
                        autoResetEvent.WaitOne();
                    }

                    if (Interlocked.Increment(ref clientsDone) == clientsCnt)
                    {
                        context.Success();
                        doneEvent.Set();
                    }
                })
                {
                    IsBackground = true
                });
            }

            var sw = Stopwatch.StartNew();

            threads.ForEach(thread => thread.Start());
            doneEvent.Wait();
            sw.Stop();
            clients.ForEach(x => x.Close());

            var reqPerSec = (all + 0.0) / sw.ElapsedMilliseconds * 1000;

            context.Log.Information("{requests} requests completed in {elapsed}ms ({rate:0.00} reqs per sec).", all,
                                    sw.ElapsedMilliseconds, reqPerSec);
            PerfUtils.LogData(Keyword,
                              PerfUtils.Row(PerfUtils.Col("clientsCnt", clientsCnt),
                                            PerfUtils.Col("requestsCnt", requestsCnt),
                                            PerfUtils.Col("ElapsedMilliseconds", sw.ElapsedMilliseconds)));
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-reqPerSec", Keyword, clientsCnt, requestsCnt),
                                           (int)reqPerSec);
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword),
                                           (int)Math.Round(sw.Elapsed.TotalMilliseconds / all));

            if (Interlocked.Read(ref all) == requestsCnt)
            {
                context.Success();
            }
            else
            {
                context.Fail();
            }
        }
Beispiel #5
0
        private void Write(Status status, int writerIdx, CommandProcessorContext context, int requests, AutoResetEvent finish)
        {
            TcpTypedConnection <byte[]> connection;
            var iteration = new AutoResetEvent(false);

            var sent = 0;

            var prepareTimeouts     = 0;
            var commitTimeouts      = 0;
            var forwardTimeouts     = 0;
            var wrongExpctdVersions = 0;
            var streamsDeleted      = 0;

            var failed = 0;

            var rnd = new Random();

            var streamIdx = -1;
            var head      = -1;

            Action <TcpTypedConnection <byte[]>, TcpPackage> packageHandler = (conn, pkg) =>
            {
                var dto = pkg.Data.Deserialize <ClientMessageDto.WriteEventsCompleted>();
                switch ((OperationErrorCode)dto.ErrorCode)
                {
                case OperationErrorCode.Success:
                    lock (_heads)
                    {
                        var currentHead = _heads[streamIdx];
                        Ensure.Equal(currentHead, head);
                        _heads[streamIdx]++;
                    }
                    break;

                case OperationErrorCode.PrepareTimeout:
                    prepareTimeouts++;
                    failed++;
                    break;

                case OperationErrorCode.CommitTimeout:
                    commitTimeouts++;
                    failed++;
                    break;

                case OperationErrorCode.ForwardTimeout:
                    forwardTimeouts++;
                    failed++;
                    break;

                case OperationErrorCode.WrongExpectedVersion:
                    wrongExpctdVersions++;
                    failed++;
                    break;

                case OperationErrorCode.StreamDeleted:
                    streamsDeleted++;
                    failed++;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                sent++;
                if (sent % 1000 == 0)
                {
                    status.ReportWritesProgress(writerIdx, sent, prepareTimeouts, commitTimeouts, forwardTimeouts,
                                                wrongExpctdVersions, streamsDeleted, failed, requests);
                }
                if (sent == requests)
                {
                    finish.Set();
                }

                iteration.Set();
            };

            Action <TcpTypedConnection <byte[]> >             established = _ => { };
            Action <TcpTypedConnection <byte[]>, SocketError> closed      = null;

            closed = (_, __) =>
            {
                Thread.Sleep(TimeSpan.FromSeconds(1));
                connection = context.Client.CreateTcpConnection(context, packageHandler, cn => iteration.Set(), closed, false);
            };

            connection = context.Client.CreateTcpConnection(context, packageHandler, established, closed, false);

            for (var i = 0; i < requests; ++i)
            {
                streamIdx = NextStreamForWriting(rnd, writerIdx);
                lock (_heads)
                    head = _heads[streamIdx];

                var evnt  = CreateEvent(_streams[streamIdx], head + 2);
                var write = new ClientMessageDto.WriteEvents(Guid.Empty,
                                                             _streams[streamIdx],
                                                             head == -1 ? head : head + 1,
                                                             new[] { new ClientMessageDto.Event(evnt) });

                var package = new TcpPackage(TcpCommand.WriteEvents, write.Serialize());
                connection.EnqueueSend(package.AsByteArray());
                iteration.WaitOne();
            }

            status.ReportWritesProgress(writerIdx, sent, prepareTimeouts, commitTimeouts, forwardTimeouts,
                                        wrongExpctdVersions, streamsDeleted, failed, requests);
            status.FinilizeStatus(writerIdx, failed != sent);
            connection.Close();
        }
Beispiel #6
0
        public bool Execute(CommandProcessorContext context, string[] args)
        {
            var eventStreamId   = "test-stream";
            var expectedVersion = ExpectedVersion.Any;
            int eventsCnt       = 10;

            if (args.Length > 0)
            {
                if (args.Length > 3)
                {
                    return(false);
                }
                eventStreamId = args[0];
                if (args.Length > 1)
                {
                    expectedVersion = args[1].ToUpper() == "ANY" ? ExpectedVersion.Any : int.Parse(args[1]);
                }
                if (args.Length > 2)
                {
                    eventsCnt = int.Parse(args[1]);
                }
            }

            context.IsAsync();

            var  sw            = new Stopwatch();
            var  stage         = Stage.AcquiringTransactionId;
            long transactionId = -1;
            var  writtenEvents = 0;

            context.Client.CreateTcpConnection(
                context,
                connectionEstablished: conn =>
            {
                context.Log.Info("[{0}, L{1}]: Starting transaction...", conn.RemoteEndPoint, conn.LocalEndPoint);
                sw.Start();

                var tranStart = new TcpClientMessageDto.TransactionStart(eventStreamId, expectedVersion, false);
                var package   = new TcpPackage(TcpCommand.TransactionStart, Guid.NewGuid(), tranStart.Serialize());
                conn.EnqueueSend(package.AsByteArray());
            },
                handlePackage: (conn, pkg) =>
            {
                switch (stage)
                {
                case Stage.AcquiringTransactionId:
                    {
                        if (pkg.Command != TcpCommand.TransactionStartCompleted)
                        {
                            context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                            return;
                        }

                        var dto = pkg.Data.Deserialize <TcpClientMessageDto.TransactionStartCompleted>();
                        if (dto.Result != TcpClientMessageDto.OperationResult.Success)
                        {
                            var msg = string.Format("Error while starting transaction: {0} ({1}).", dto.Message, dto.Result);
                            context.Log.Info(msg);
                            context.Fail(reason: msg);
                        }
                        else
                        {
                            context.Log.Info("Successfully started transaction. TransactionId: {0}.", dto.TransactionId);
                            context.Log.Info("Now sending transactional events...", dto.TransactionId);

                            transactionId = dto.TransactionId;
                            stage         = Stage.Writing;
                            for (int i = 0; i < eventsCnt; ++i)
                            {
                                var writeDto = new TcpClientMessageDto.TransactionWrite(
                                    transactionId,
                                    new[]
                                {
                                    new TcpClientMessageDto.NewEvent(Guid.NewGuid().ToByteArray(),
                                                                     "TakeSomeSpaceEvent",
                                                                     0, 0,
                                                                     Common.Utils.Helper.UTF8NoBom.GetBytes(Guid.NewGuid().ToString()),
                                                                     Common.Utils.Helper.UTF8NoBom.GetBytes(Guid.NewGuid().ToString()))
                                },
                                    false);
                                var package = new TcpPackage(TcpCommand.TransactionWrite, Guid.NewGuid(), writeDto.Serialize());
                                conn.EnqueueSend(package.AsByteArray());
                            }
                        }

                        break;
                    }

                case Stage.Writing:
                    {
                        if (pkg.Command != TcpCommand.TransactionWriteCompleted)
                        {
                            context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                            return;
                        }

                        var dto = pkg.Data.Deserialize <TcpClientMessageDto.TransactionWriteCompleted>();
                        if (dto.Result != TcpClientMessageDto.OperationResult.Success)
                        {
                            var msg = string.Format("Error while writing transactional event: {0} ({1}).", dto.Message, dto.Result);
                            context.Log.Info(msg);
                            context.Fail(reason: msg);
                        }
                        else
                        {
                            writtenEvents += 1;
                            if (writtenEvents == eventsCnt)
                            {
                                context.Log.Info("Written all events. Committing...");

                                stage         = Stage.Committing;
                                var commitDto = new TcpClientMessageDto.TransactionCommit(transactionId, false);
                                var package   = new TcpPackage(TcpCommand.TransactionCommit, Guid.NewGuid(), commitDto.Serialize());
                                conn.EnqueueSend(package.AsByteArray());
                            }
                        }
                        break;
                    }

                case Stage.Committing:
                    {
                        if (pkg.Command != TcpCommand.TransactionCommitCompleted)
                        {
                            context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                            return;
                        }

                        sw.Stop();

                        var dto = pkg.Data.Deserialize <TcpClientMessageDto.TransactionCommitCompleted>();
                        if (dto.Result != TcpClientMessageDto.OperationResult.Success)
                        {
                            var msg = string.Format("Error while committing transaction: {0} ({1}).", dto.Message, dto.Result);
                            context.Log.Info(msg);
                            context.Log.Info("Transaction took: {0}.", sw.Elapsed);
                            context.Fail(reason: msg);
                        }
                        else
                        {
                            context.Log.Info("Successfully committed transaction [{0}]!", dto.TransactionId);
                            context.Log.Info("Transaction took: {0}.", sw.Elapsed);
                            PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword), (int)sw.ElapsedMilliseconds);
                            context.Success();
                        }
                        conn.Close();
                        break;
                    }

                default:
                    throw new ArgumentOutOfRangeException();
                }
            },
                connectionClosed: (connection, error) => context.Fail(reason: "Connection was closed prematurely."));
            context.WaitForCompletion();
            return(true);
        }
Beispiel #7
0
        public bool Execute(CommandProcessorContext context, string[] args)
        {
            var    eventStreamId   = "test-stream";
            var    expectedVersion = ExpectedVersion.Any;
            var    data            = "test-data";
            string metadata        = null;
            bool   isJson          = false;
            string login           = null;
            string pass            = null;

            if (args.Length > 0)
            {
                if (args.Length < 3 || args.Length > 7 || args.Length == 6)
                {
                    return(false);
                }
                eventStreamId   = args[0];
                expectedVersion = args[1].ToUpper() == "ANY" ? ExpectedVersion.Any : int.Parse(args[1]);
                data            = args[2];
                if (args.Length >= 4)
                {
                    metadata = args[3];
                }
                if (args.Length >= 5)
                {
                    isJson = bool.Parse(args[4]);
                }
                if (args.Length >= 7)
                {
                    login = args[5];
                    pass  = args[6];
                }
            }

            context.IsAsync();
            var sw = new Stopwatch();

            context.Client.CreateTcpConnection(
                context,
                connectionEstablished: conn => {
                context.Log.Information("[{remoteEndPoint}, L{localEndPoint}]: Writing...", conn.RemoteEndPoint,
                                        conn.LocalEndPoint);
                var writeDto = new TcpClientMessageDto.WriteEvents(
                    eventStreamId,
                    expectedVersion,
                    new[] {
                    new TcpClientMessageDto.NewEvent(Guid.NewGuid().ToByteArray(),
                                                     "TakeSomeSpaceEvent",
                                                     isJson ? 1 : 0, 0,
                                                     Helper.UTF8NoBom.GetBytes(data),
                                                     Helper.UTF8NoBom.GetBytes(metadata ?? string.Empty))
                },
                    false);
                var package = new TcpPackage(TcpCommand.WriteEvents,
                                             login == null ? TcpFlags.None : TcpFlags.Authenticated,
                                             Guid.NewGuid(),
                                             login,
                                             pass,
                                             writeDto.Serialize()).AsByteArray();
                sw.Start();
                conn.EnqueueSend(package);
            },
                handlePackage: (conn, pkg) => {
                sw.Stop();
                context.Log.Information("Write request took: {elapsed}.", sw.Elapsed);

                if (pkg.Command != TcpCommand.WriteEventsCompleted)
                {
                    context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                    return;
                }

                var dto = pkg.Data.Deserialize <TcpClientMessageDto.WriteEventsCompleted>();
                if (dto.Result == TcpClientMessageDto.OperationResult.Success)
                {
                    context.Log.Information("Successfully written.");
                    PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword),
                                                   (int)Math.Round(sw.Elapsed.TotalMilliseconds));
                    context.Success();
                }
                else
                {
                    context.Log.Information("Error while writing: {message} ({e}).", dto.Message, dto.Result);
                    context.Fail();
                }

                conn.Close();
            },
                connectionClosed: (connection, error) => context.Fail(reason: "Connection was closed prematurely."));

            context.WaitForCompletion();
            return(true);
        }
Beispiel #8
0
        private void PingFloodWaiting(CommandProcessorContext context, int clientsCnt, int requestsCnt)
        {
            context.IsAsync();

            var clients     = new List <TcpTypedConnection <byte[]> >();
            var threads     = new List <Thread>();
            var doneEvent   = new AutoResetEvent(false);
            var clientsDone = 0;

            for (int i = 0; i < clientsCnt; i++)
            {
                var autoResetEvent = new AutoResetEvent(false);
                var client         = context.Client.CreateTcpConnection(
                    context,
                    (_, __) => autoResetEvent.Set(),
                    connectionClosed: (conn, err) =>
                {
                    if (clientsDone < clientsCnt)
                    {
                        context.Fail(null, "Socket was closed, but not all requests were completed.");
                    }
                    else
                    {
                        context.Success();
                    }
                });
                clients.Add(client);
                var count = requestsCnt / clientsCnt + ((i == clientsCnt - 1) ? requestsCnt % clientsCnt : 0);

                threads.Add(new Thread(() =>
                {
                    for (int j = 0; j < count; ++j)
                    {
                        //TODO GFY ping needs correlation id
                        var package = new TcpPackage(TcpCommand.Ping, Guid.NewGuid(), null);
                        client.EnqueueSend(package.AsByteArray());

                        autoResetEvent.WaitOne();
                    }
                    if (Interlocked.Increment(ref clientsDone) == clientsCnt)
                    {
                        doneEvent.Set();
                    }
                }));
            }

            var sw = Stopwatch.StartNew();

            foreach (var thread in threads)
            {
                thread.IsBackground = true;
                thread.Start();
            }

            doneEvent.WaitOne();
            sw.Stop();

            clients.ForEach(x => x.Close());

            var reqPerSec = (requestsCnt + 0.0) / sw.ElapsedMilliseconds * 1000;

            context.Log.Info("{0} requests completed in {1}ms ({2:0.00} reqs per sec).",
                             requestsCnt,
                             sw.ElapsedMilliseconds,
                             reqPerSec);

            PerfUtils.LogData(
                Keyword,
                PerfUtils.Row(PerfUtils.Col("clientsCnt", clientsCnt),
                              PerfUtils.Col("requestsCnt", requestsCnt),
                              PerfUtils.Col("ElapsedMilliseconds", sw.ElapsedMilliseconds))
                );

            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-reqPerSec", Keyword, clientsCnt, requestsCnt),
                                           (int)reqPerSec);

            PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword),
                                           (int)(sw.ElapsedMilliseconds / requestsCnt));

            context.Success();
        }
        public void should_throw_argument_exception_on_serialization_when_password_too_long()
        {
            var pkg = new TcpPackage(TcpCommand.BadRequest, TcpFlags.Authenticated, Guid.NewGuid(), "login", new string('*', 256), new byte[] { 1, 2, 3 });

            Assert.Throws <ArgumentException>(() => pkg.AsByteArray());
        }
Beispiel #10
0
        public bool Execute(CommandProcessorContext context, string[] args)
        {
            var          eventStreamId   = "test-stream";
            const string data            = "test-data";
            var          writeCount      = 10;
            var          expectedVersion = ExpectedVersion.Any;

            if (args.Length > 0)
            {
                if (args.Length > 3)
                {
                    return(false);
                }
                writeCount = int.Parse(args[0]);
                if (args.Length >= 2)
                {
                    eventStreamId = args[1];
                }
                if (args.Length >= 3)
                {
                    expectedVersion = args[2].Trim().ToUpper() == "ANY" ? ExpectedVersion.Any : int.Parse(args[2].Trim());
                }
            }

            context.IsAsync();
            var writeDto = new TcpClientMessageDto.WriteEvents(
                eventStreamId,
                expectedVersion,
                Enumerable.Range(0, writeCount).Select(x =>
                                                       new TcpClientMessageDto.ClientEvent(Guid.NewGuid().ToByteArray(),
                                                                                           "type",
                                                                                           false,
                                                                                           Encoding.UTF8.GetBytes(data),
                                                                                           new byte[0])).ToArray(),
                true);

            var package = new TcpPackage(TcpCommand.WriteEvents, Guid.NewGuid(), writeDto.Serialize());

            var sw = new Stopwatch();

            context.Client.CreateTcpConnection(
                context,
                connectionEstablished: conn =>
            {
                context.Log.Info("[{0}]: Writing...", conn.EffectiveEndPoint);
                sw.Start();
                conn.EnqueueSend(package.AsByteArray());
            },
                handlePackage: (conn, pkg) =>
            {
                if (pkg.Command != TcpCommand.WriteEventsCompleted)
                {
                    context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                    return;
                }

                sw.Stop();

                var dto = pkg.Data.Deserialize <TcpClientMessageDto.WriteEventsCompleted>();
                if (dto.ErrorCode == (int)OperationErrorCode.Success)
                {
                    context.Log.Info("Successfully written {0} events. CorrelationId: {1}.", writeCount, package.CorrelationId);
                    PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword), (int)sw.ElapsedMilliseconds);
                }
                else
                {
                    context.Log.Info("Error while writing: {0}. CorrelationId: {1}.", dto.Error, package.CorrelationId);
                }
                context.Log.Info("Write request took: {0}.", sw.Elapsed);

                conn.Close();
                context.Success();
            },
                connectionClosed: (connection, error) =>
            {
                if (error == SocketError.Success)
                {
                    context.Success();
                }
                else
                {
                    context.Fail();
                }
            });

            context.WaitForCompletion();
            return(true);
        }
Beispiel #11
0
 public HandleTcpPackageMessage(TcpPackageConnection connection, TcpPackage package)
 {
     Connection = connection;
     Package    = package;
 }
        private void Flood(CommandProcessorContext context,
                           string eventStreamId,
                           int clientsCnt,
                           int minPerSecond,
                           int maxPerSecond,
                           int runTimeMinutes)
        {
            context.IsAsync();

            var clients   = new List <TcpTypedConnection <byte[]> >();
            var threads   = new List <Thread>();
            var doneEvent = new ManualResetEvent(false);
            var done      = false;

            var succ = 0;
            var fail = 0;

            var requestsCnt = 0;

            int sent     = 0;
            int received = 0;

            var watchLockRoot = new object();
            var sw            = Stopwatch.StartNew();

            for (int i = 0; i < clientsCnt; i++)
            {
                var esId = eventStreamId ?? "Stream-" + Thread.CurrentThread.ManagedThreadId % 3;

                var client = context.Client.CreateTcpConnection(
                    context,
                    (conn, pkg) =>
                {
                    if (pkg.Command != TcpCommand.WriteEventsCompleted)
                    {
                        context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                        return;
                    }

                    var dto = pkg.Data.Deserialize <TcpClientMessageDto.WriteEventsCompleted>();
                    if (dto.Result == TcpClientMessageDto.OperationResult.Success)
                    {
                        var succDone = Interlocked.Increment(ref succ);
                        if (succDone % maxPerSecond == 0)
                        {
                            Console.Write(".");
                        }

                        Interlocked.Increment(ref requestsCnt);
                    }
                    else
                    {
                        Interlocked.Increment(ref fail);
                    }

                    Interlocked.Increment(ref received);
                },
                    connectionClosed: (conn, err) =>
                {
                    if (!done)
                    {
                        context.Fail(reason: "Socket was closed, but not all requests were completed.");
                    }
                    else
                    {
                        context.Success();
                    }
                });
                clients.Add(client);

                threads.Add(new Thread(() =>
                {
                    var sentCount = 0;
                    var sleepTime = 0;

                    var dataSizeCoefficient = 1;
                    var currentMinute       = -1;

                    while (true)
                    {
                        TimeSpan elapsed;
                        lock (watchLockRoot)
                            elapsed = sw.Elapsed;

                        if (elapsed.TotalMinutes > runTimeMinutes)
                        {
                            done = true;
                            doneEvent.Set();
                            break;
                        }

                        if (sentCount == 0)
                        {
                            int elapsedMinutesInt = (int)elapsed.TotalMinutes;
                            lock (_randomLockRoot)
                            {
                                sentCount = minPerSecond == maxPerSecond
                                            ? maxPerSecond : _random.Next(minPerSecond, maxPerSecond);
                                dataSizeCoefficient = _random.Next(8, 256);
                            }

                            if (currentMinute != elapsedMinutesInt)
                            {
                                currentMinute = elapsedMinutesInt;
                                context.Log.Info("\nElapsed {elapsed} of {runTime} minutes, sent {sent}; next block coef. {dataSizeCoefficient}",
                                                 elapsedMinutesInt,
                                                 runTimeMinutes,
                                                 sent,
                                                 dataSizeCoefficient);
                            }

                            sleepTime = 1000 / sentCount;
                        }

                        var dataSize = dataSizeCoefficient * 8;
                        var write    = new TcpClientMessageDto.WriteEvents(
                            esId,
                            ExpectedVersion.Any,
                            new[]
                        {
                            new TcpClientMessageDto.NewEvent(
                                Guid.NewGuid().ToByteArray(),
                                "TakeSomeSpaceEvent",
                                0, 0,
                                Helper.UTF8NoBom.GetBytes("DATA" + dataSize.ToString(" 00000 ") + new string('*', dataSize)),
                                Helper.UTF8NoBom.GetBytes("METADATA" + new string('$', 100)))
                        },
                            false);
                        var package = new TcpPackage(TcpCommand.WriteEvents, Guid.NewGuid(), write.Serialize());
                        client.EnqueueSend(package.AsByteArray());

                        Interlocked.Increment(ref sent);

                        Thread.Sleep(sleepTime);
                        sentCount -= 1;

                        while (sent - received > context.Client.Options.WriteWindow / clientsCnt)
                        {
                            Thread.Sleep(1);
                        }
                    }
                }));
            }

            foreach (var thread in threads)
            {
                thread.IsBackground = true;
                thread.Start();
            }

            doneEvent.WaitOne();
            sw.Stop();

            foreach (var client in clients)
            {
                client.Close();
            }

            context.Log.Info("Completed. Successes: {success}, failures: {failures}", succ, fail);
            var reqPerSec = (requestsCnt + 0.0) / sw.ElapsedMilliseconds * 1000;

            context.Log.Info("{requests} requests completed in {elapsed}ms ({rate:0.00} reqs per sec).",
                             requestsCnt,
                             sw.ElapsedMilliseconds,
                             reqPerSec);

            PerfUtils.LogData(
                Keyword,
                PerfUtils.Row(PerfUtils.Col("clientsCnt", clientsCnt),
                              PerfUtils.Col("requestsCnt", requestsCnt),
                              PerfUtils.Col("ElapsedMilliseconds", sw.ElapsedMilliseconds)),
                PerfUtils.Row(PerfUtils.Col("successes", succ), PerfUtils.Col("failures", fail))
                );

            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-reqPerSec", Keyword, clientsCnt, requestsCnt),
                                           (int)reqPerSec);

            PerfUtils.LogTeamCityGraphData(
                string.Format("{0}-{1}-{2}-failureSuccessRate", Keyword, clientsCnt, requestsCnt),
                100 * fail / (fail + succ));

            context.Success();
        }
Beispiel #13
0
        public bool Execute(CommandProcessorContext context, string[] args)
        {
            var    eventStreamId   = "test-stream";
            var    expectedVersion = ExpectedVersion.Any;
            var    data            = "test-data";
            string metadata        = null;

            if (args.Length > 0)
            {
                if (args.Length < 3 || args.Length > 4)
                {
                    return(false);
                }
                eventStreamId   = args[0];
                expectedVersion = args[1].ToUpper() == "ANY" ? ExpectedVersion.Any : int.Parse(args[1]);
                data            = args[2];
                if (args.Length == 4)
                {
                    metadata = args[3];
                }
            }

            context.IsAsync();
            var corrid   = Guid.NewGuid();
            var writeDto = new ClientMessageDto.WriteEvents(
                corrid,
                eventStreamId,
                expectedVersion,
                new[]
            {
                new ClientMessageDto.Event(Guid.NewGuid(),
                                           "TakeSomeSpaceEvent",
                                           Encoding.UTF8.GetBytes(data),
                                           Encoding.UTF8.GetBytes(metadata ?? string.Empty))
            });
            var package = new TcpPackage(TcpCommand.WriteEvents, corrid, writeDto.Serialize());

            var sw = new Stopwatch();

            context.Client.CreateTcpConnection(
                context,
                connectionEstablished: conn =>
            {
                context.Log.Info("[{0}]: Writing...", conn.EffectiveEndPoint);
                sw.Start();
                conn.EnqueueSend(package.AsByteArray());
            },
                handlePackage: (conn, pkg) =>
            {
                if (pkg.Command != TcpCommand.WriteEventsCompleted)
                {
                    context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                    return;
                }

                sw.Stop();

                var dto = pkg.Data.Deserialize <ClientMessageDto.WriteEventsCompleted>();
                if ((OperationErrorCode)dto.ErrorCode == OperationErrorCode.Success)
                {
                    context.Log.Info("Successfully written. EventId: {0}.", dto.CorrelationId);
                    PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword), (int)sw.ElapsedMilliseconds);
                }
                else
                {
                    context.Log.Info("Error while writing: {0} ({1}). EventId: {2}.",
                                     dto.Error,
                                     (OperationErrorCode)dto.ErrorCode,
                                     dto.CorrelationId);
                }

                context.Log.Info("Write request took: {0}.", sw.Elapsed);
                conn.Close();
                context.Success();
            },
                connectionClosed: (connection, error) =>
            {
                if (error == SocketError.Success)
                {
                    context.Success();
                }
                else
                {
                    context.Fail();
                }
            });

            context.WaitForCompletion();
            return(true);
        }
Beispiel #14
0
        private void ReadFlood(CommandProcessorContext context, string eventStreamId, int clientsCnt, long requestsCnt,
                               bool resolveLinkTos, bool requireMaster)
        {
            context.IsAsync();

            var  clients   = new List <TcpTypedConnection <byte[]> >();
            var  threads   = new List <Thread>();
            var  doneEvent = new ManualResetEventSlim(false);
            var  sw2       = new Stopwatch();
            long succ      = 0;
            long fail      = 0;
            long all       = 0;

            for (int i = 0; i < clientsCnt; i++)
            {
                var  count    = requestsCnt / clientsCnt + ((i == clientsCnt - 1) ? requestsCnt % clientsCnt : 0);
                long received = 0;
                long sent     = 0;
                var  client   = context.Client.CreateTcpConnection(
                    context,
                    (conn, pkg) =>
                {
                    if (pkg.Command != TcpCommand.ReadEventCompleted)
                    {
                        context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                        return;
                    }

                    var dto = pkg.Data.Deserialize <TcpClientMessageDto.ReadEventCompleted>();
                    _monitor.EndOperation(pkg.CorrelationId);
                    if (dto.Result == TcpClientMessageDto.ReadEventCompleted.ReadEventResult.Success)
                    {
                        if (Interlocked.Increment(ref succ) % 1000 == 0)
                        {
                            Console.Write(".");
                        }
                    }
                    else
                    {
                        if (Interlocked.Increment(ref fail) % 1000 == 0)
                        {
                            Console.Write("#");
                        }
                    }

                    Interlocked.Increment(ref received);
                    var localAll = Interlocked.Increment(ref all);
                    if (localAll % 100000 == 0)
                    {
                        var elapsed = sw2.Elapsed;
                        sw2.Restart();
                        context.Log.Trace("\nDONE TOTAL {reads} READS IN {elapsed} ({rate:0.0}/s).", localAll, elapsed, 1000.0 * 100000 / elapsed.TotalMilliseconds);
                    }
                    if (localAll == requestsCnt)
                    {
                        context.Success();
                        doneEvent.Set();
                    }
                },
                    connectionClosed: (conn, err) => context.Fail(reason: "Connection was closed prematurely."));
                clients.Add(client);

                threads.Add(new Thread(() =>
                {
                    for (int j = 0; j < count; ++j)
                    {
                        var corrId  = Guid.NewGuid();
                        var read    = new TcpClientMessageDto.ReadEvent(eventStreamId, 0, resolveLinkTos, requireMaster);
                        var package = new TcpPackage(TcpCommand.ReadEvent, corrId, read.Serialize());
                        _monitor.StartOperation(corrId);
                        client.EnqueueSend(package.AsByteArray());

                        var localSent = Interlocked.Increment(ref sent);
                        while (localSent - Interlocked.Read(ref received) > context.Client.Options.ReadWindow / clientsCnt)
                        {
                            Thread.Sleep(1);
                        }
                    }
                })
                {
                    IsBackground = true
                });
            }

            var sw = Stopwatch.StartNew();

            sw2.Start();
            threads.ForEach(thread => thread.Start());
            doneEvent.Wait();
            sw.Stop();
            clients.ForEach(client => client.Close());

            var reqPerSec = (all + 0.0) / sw.ElapsedMilliseconds * 1000;

            context.Log.Info("Completed. READS succ: {success}, fail: {failures}.", Interlocked.Read(ref succ), Interlocked.Read(ref fail));
            context.Log.Info("{requests} requests completed in {elapsed}ms ({rate:0.00} reqs per sec).", all, sw.ElapsedMilliseconds, reqPerSec);
            _monitor.GetMeasurementDetails();
            PerfUtils.LogData(Keyword,
                              PerfUtils.Row(PerfUtils.Col("clientsCnt", clientsCnt),
                                            PerfUtils.Col("requestsCnt", requestsCnt),
                                            PerfUtils.Col("ElapsedMilliseconds", sw.ElapsedMilliseconds)),
                              PerfUtils.Row(PerfUtils.Col("readsCnt", all)));
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-reqPerSec", Keyword, clientsCnt, requestsCnt), (int)reqPerSec);

            if (succ != requestsCnt)
            {
                context.Fail(reason: "There were errors or not all requests completed.");
            }
            else
            {
                context.Success();
            }
        }
        private void ReadFlood(CommandProcessorContext context, string eventStreamId, int clientsCnt, long requestsCnt)
        {
            context.IsAsync();

            var clients        = new List <TcpTypedConnection <byte[]> >();
            var threads        = new List <Thread>();
            var autoResetEvent = new AutoResetEvent(false);
            var sw2            = new Stopwatch();

            long all = 0;

            for (int i = 0; i < clientsCnt; i++)
            {
                var count = requestsCnt / clientsCnt + ((i == clientsCnt - 1) ? requestsCnt % clientsCnt : 0);

                int sent     = 0;
                int received = 0;

                var client = context.Client.CreateTcpConnection(
                    context,
                    (conn, pkg) =>
                {
                    Interlocked.Increment(ref received);

                    var localAll = Interlocked.Increment(ref all);
                    if (localAll % 1000 == 0)
                    {
                        Console.Write(".");
                    }
                    if (localAll % 100000 == 0)
                    {
                        var elapsed = sw2.Elapsed;
                        sw2.Restart();
                        context.Log.Trace("\nDONE TOTAL {0} READS IN {1} ({2:0.0}/s).",
                                          localAll,
                                          elapsed,
                                          1000.0 * 100000 / elapsed.TotalMilliseconds);
                    }
                    if (localAll == requestsCnt)
                    {
                        autoResetEvent.Set();
                    }
                },
                    connectionClosed: (conn, err) =>
                {
                    if (all < requestsCnt)
                    {
                        context.Fail(null, "Socket was closed, but not all requests were completed.");
                    }
                    else
                    {
                        context.Success();
                    }
                });

                client.ConnectionClosed += (_, __) => context.Log.Debug("READS sent: {0}, received: {1}", sent, received);
                clients.Add(client);

                threads.Add(new Thread(() =>
                {
                    for (int j = 0; j < count; ++j)
                    {
                        var corrid  = Guid.NewGuid();
                        var read    = new TcpClientMessageDto.ReadEvent(eventStreamId, 0, resolveLinkTos: false);
                        var package = new TcpPackage(TcpCommand.ReadEvent, corrid, read.Serialize());
                        client.EnqueueSend(package.AsByteArray());

                        Interlocked.Increment(ref sent);
                        while (sent - received > context.Client.Options.ReadWindow)
                        {
                            Thread.Sleep(1);
                        }
                    }
                }));
            }

            var sw = Stopwatch.StartNew();

            sw2.Start();
            foreach (var thread in threads)
            {
                thread.IsBackground = true;
                thread.Start();
            }

            autoResetEvent.WaitOne();
            sw.Stop();

            foreach (var client in clients)
            {
                client.Close();
            }

            context.Log.Info("Completed. READS done: {0}.", all);

            var reqPerSec = (requestsCnt + 0.0) / sw.ElapsedMilliseconds * 1000;

            context.Log.Info("{0} requests completed in {1}ms ({2:0.00} reqs per sec).",
                             requestsCnt,
                             sw.ElapsedMilliseconds,
                             reqPerSec);

            PerfUtils.LogData(
                Keyword,
                PerfUtils.Row(PerfUtils.Col("clientsCnt", clientsCnt),
                              PerfUtils.Col("requestsCnt", requestsCnt),
                              PerfUtils.Col("ElapsedMilliseconds", sw.ElapsedMilliseconds)),
                PerfUtils.Row(PerfUtils.Col("readsCnt", all))
                );

            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-reqPerSec", Keyword, clientsCnt, requestsCnt),
                                           (int)reqPerSec);

            context.Success();
        }
Beispiel #16
0
        public bool Execute(CommandProcessorContext context, string[] args)
        {
            const string data            = "test-data";
            var          eventStreamId   = "test-stream";
            var          writeCount      = 10;
            var          expectedVersion = ExpectedVersion.Any;

            if (args.Length > 0)
            {
                if (args.Length > 3)
                {
                    return(false);
                }
                writeCount = int.Parse(args[0]);
                if (args.Length >= 2)
                {
                    eventStreamId = args[1];
                }
                if (args.Length >= 3)
                {
                    expectedVersion = args[2].Trim().ToUpper() == "ANY"
                                                ? ExpectedVersion.Any
                                                : int.Parse(args[2].Trim());
                }
            }

            context.IsAsync();
            var sw = new Stopwatch();

            context.Client.CreateTcpConnection(
                context,
                connectionEstablished: conn => {
                context.Log.Info("[{remoteEndPoint}, L{localEndPoint}]: Writing...", conn.RemoteEndPoint,
                                 conn.LocalEndPoint);
                var writeDto = new TcpClientMessageDto.WriteEvents(
                    eventStreamId,
                    expectedVersion,
                    Enumerable.Range(0, writeCount).Select(x => new TcpClientMessageDto.NewEvent(
                                                               Guid.NewGuid().ToByteArray(),
                                                               "type",
                                                               0, 0,
                                                               Helper.UTF8NoBom.GetBytes(data),
                                                               new byte[0])).ToArray(),
                    false);
                var package = new TcpPackage(TcpCommand.WriteEvents, Guid.NewGuid(), writeDto.Serialize())
                              .AsByteArray();
                sw.Start();
                conn.EnqueueSend(package);
            },
                handlePackage: (conn, pkg) => {
                sw.Stop();
                context.Log.Info("Write request took: {elapsed}.", sw.Elapsed);

                if (pkg.Command != TcpCommand.WriteEventsCompleted)
                {
                    context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                    return;
                }

                var dto = pkg.Data.Deserialize <TcpClientMessageDto.WriteEventsCompleted>();
                if (dto.Result == TcpClientMessageDto.OperationResult.Success)
                {
                    context.Log.Info("Successfully written {writeCount} events.", writeCount);
                    PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword),
                                                   (int)Math.Round(sw.Elapsed.TotalMilliseconds));
                    context.Success();
                }
                else
                {
                    context.Log.Info("Error while writing: {e}.", dto.Result);
                    context.Fail();
                }

                conn.Close();
            },
                connectionClosed: (connection, error) => context.Fail(reason: "Connection was closed prematurely."));

            context.WaitForCompletion();
            return(true);
        }
        private void WriteFlood(CommandProcessorContext context, int clientsCnt, int requestsCnt, int payloadSize)
        {
            context.IsAsync();

            var dataSize     = Math.Max(0, payloadSize - 100);
            var metadataSize = Math.Min(100, payloadSize);

            var clients   = new List <TcpTypedConnection <byte[]> >();
            var threads   = new List <Thread>();
            var doneEvent = new ManualResetEventSlim(false);
            var succ      = 0;
            var fail      = 0;
            var all       = 0;

            for (int i = 0; i < clientsCnt; i++)
            {
                var count         = requestsCnt / clientsCnt + ((i == clientsCnt - 1) ? requestsCnt % clientsCnt : 0);
                var autoEvent     = new AutoResetEvent(false);
                var eventStreamId = "es" + Guid.NewGuid();
                var received      = 0;
                var client        = context.Client.CreateTcpConnection(
                    context,
                    (conn, pkg) =>
                {
                    if (pkg.Command != TcpCommand.WriteEventsCompleted)
                    {
                        context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                        return;
                    }

                    Interlocked.Increment(ref received);
                    var dto = pkg.Data.Deserialize <TcpClientMessageDto.WriteEventsCompleted>();
                    if (dto.Result == TcpClientMessageDto.OperationResult.Success)
                    {
                        if (Interlocked.Increment(ref succ) % 1000 == 0)
                        {
                            Console.Write(".");
                        }
                    }
                    else
                    {
                        if (Interlocked.Increment(ref fail) % 1000 == 0)
                        {
                            Console.Write("#");
                        }
                    }

                    if (Interlocked.Increment(ref all) == requestsCnt)
                    {
                        context.Success();
                        doneEvent.Set();
                    }
                    autoEvent.Set();
                },
                    connectionClosed: (conn, err) => context.Fail(reason: "Connection was closed prematurely."));
                clients.Add(client);

                threads.Add(new Thread(() =>
                {
                    for (int j = 0; j < count; ++j)
                    {
                        var write = new TcpClientMessageDto.WriteEvents(
                            eventStreamId,
                            ExpectedVersion.Any,
                            new[]
                        {
                            new TcpClientMessageDto.NewEvent(Guid.NewGuid().ToByteArray(),
                                                             "TakeSomeSpaceEvent",
                                                             0, 0,
                                                             Common.Utils.Helper.UTF8NoBom.GetBytes("DATA" + new string('*', dataSize)),
                                                             Common.Utils.Helper.UTF8NoBom.GetBytes("METADATA" + new string('$', metadataSize)))
                        },
                            false);
                        var package = new TcpPackage(TcpCommand.WriteEvents, Guid.NewGuid(), write.Serialize());
                        client.EnqueueSend(package.AsByteArray());
                        autoEvent.WaitOne();
                    }
                })
                {
                    IsBackground = true
                });
            }

            var sw = Stopwatch.StartNew();

            threads.ForEach(thread => thread.Start());
            doneEvent.Wait();
            sw.Stop();
            clients.ForEach(client => client.Close());

            var reqPerSec = (all + 0.0) / sw.ElapsedMilliseconds * 1000;

            context.Log.Info("Completed. Successes: {success}, failures: {failures}", succ, fail);
            context.Log.Info("{requests} requests completed in {elapsed}ms ({rate:0.00} reqs per sec, latency: {latency:0.00} ms).",
                             all, sw.ElapsedMilliseconds, reqPerSec, (sw.Elapsed.TotalMilliseconds + 0.0) / requestsCnt);
            PerfUtils.LogData(Keyword,
                              PerfUtils.Row(PerfUtils.Col("clientsCnt", clientsCnt),
                                            PerfUtils.Col("requestsCnt", requestsCnt),
                                            PerfUtils.Col("ElapsedMilliseconds", sw.ElapsedMilliseconds)),
                              PerfUtils.Row(PerfUtils.Col("successes", succ), PerfUtils.Col("failures", fail)));
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-reqPerSec", Keyword, clientsCnt, requestsCnt), (int)reqPerSec);
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-failureSuccessRate", Keyword, clientsCnt, requestsCnt), (int)(100.0 * fail / (fail + succ)));
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword), (int)Math.Round(sw.Elapsed.TotalMilliseconds / requestsCnt));

            if (succ != requestsCnt)
            {
                context.Fail(reason: "There were errors or not all requests completed.");
            }
            else
            {
                context.Success();
            }
        }
        private void HandleTcpPackage(TcpPackageConnection connection, TcpPackage package)
        {
            if (_connection != connection || _state == ConnectionState.Closed || _state == ConnectionState.Init)
            {
                LogDebug("IGNORED: HandleTcpPackage connId {0}, package {1}, {2}.", connection.ConnectionId, package.Command, package.CorrelationId);
                return;
            }

            LogDebug("HandleTcpPackage connId {0}, package {1}, {2}.", _connection.ConnectionId, package.Command, package.CorrelationId);
            _packageNumber += 1;

            if (package.Command == TcpCommand.HeartbeatResponseCommand)
            {
                return;
            }
            if (package.Command == TcpCommand.HeartbeatRequestCommand)
            {
                _connection.EnqueueSend(new TcpPackage(TcpCommand.HeartbeatResponseCommand, package.CorrelationId, null));
                return;
            }

            if (package.Command == TcpCommand.Authenticated || package.Command == TcpCommand.NotAuthenticated)
            {
                if (_state == ConnectionState.Connecting &&
                    _connectingPhase == ConnectingPhase.Authentication &&
                    _authInfo.CorrelationId == package.CorrelationId)
                {
                    if (package.Command == TcpCommand.NotAuthenticated)
                    {
                        RaiseAuthenticationFailed("Not authenticated");
                    }

                    GoToConnectedState();
                    return;
                }
            }

            if (package.Command == TcpCommand.BadRequest && package.CorrelationId == Guid.Empty)
            {
                string message = Helper.EatException(() => Helper.UTF8NoBom.GetString(package.Data.Array, package.Data.Offset, package.Data.Count));
                var    exc     = new EventStoreConnectionException(
                    string.Format("Bad request received from server. Error: {0}", string.IsNullOrEmpty(message) ? "<no message>" : message));
                CloseConnection("Connection-wide BadRequest received. Too dangerous to continue.", exc);
                return;
            }

            OperationItem    operation;
            SubscriptionItem subscription;

            if (_operations.TryGetActiveOperation(package.CorrelationId, out operation))
            {
                var result = operation.Operation.InspectPackage(package);
                LogDebug("HandleTcpPackage OPERATION DECISION {0} ({1}), {2}", result.Decision, result.Description, operation);
                switch (result.Decision)
                {
                case InspectionDecision.DoNothing: break;

                case InspectionDecision.EndOperation:
                    _operations.RemoveOperation(operation);
                    break;

                case InspectionDecision.Retry:
                    _operations.ScheduleOperationRetry(operation);
                    break;

                case InspectionDecision.Reconnect:
                    ReconnectTo(new NodeEndPoints(result.TcpEndPoint, result.SecureTcpEndPoint));
                    _operations.ScheduleOperationRetry(operation);
                    break;

                default: throw new Exception(string.Format("Unknown InspectionDecision: {0}", result.Decision));
                }
                if (_state == ConnectionState.Connected)
                {
                    _operations.ScheduleWaitingOperations(connection);
                }
            }
            else if (_subscriptions.TryGetActiveSubscription(package.CorrelationId, out subscription))
            {
                var result = subscription.Operation.InspectPackage(package);
                LogDebug("HandleTcpPackage SUBSCRIPTION DECISION {0} ({1}), {2}", result.Decision, result.Description, subscription);
                switch (result.Decision)
                {
                case InspectionDecision.DoNothing: break;

                case InspectionDecision.EndOperation:
                    _subscriptions.RemoveSubscription(subscription);
                    break;

                case InspectionDecision.Retry:
                    _subscriptions.ScheduleSubscriptionRetry(subscription);
                    break;

                case InspectionDecision.Reconnect:
                    ReconnectTo(new NodeEndPoints(result.TcpEndPoint, result.SecureTcpEndPoint));
                    _subscriptions.ScheduleSubscriptionRetry(subscription);
                    break;

                case InspectionDecision.Subscribed:
                    subscription.IsSubscribed = true;
                    break;

                default: throw new Exception(string.Format("Unknown InspectionDecision: {0}", result.Decision));
                }
            }
            else
            {
                LogDebug("HandleTcpPackage UNMAPPED PACKAGE with CorrelationId {0:B}, Command: {1}", package.CorrelationId, package.Command);
            }
        }
Beispiel #19
0
        public Connection CreateTcpConnection(CommandProcessorContext context,
                                              Action <Connection, TcpPackage> handlePackage,
                                              Action <Connection> connectionEstablished         = null,
                                              Action <Connection, SocketError> connectionClosed = null,
                                              bool failContextOnError = true,
                                              IPEndPoint tcpEndPoint  = null)
        {
            var        connectionCreatedEvent = new ManualResetEventSlim(false);
            Connection typedConnection        = null;

            var connection = _connector.ConnectTo(
                Guid.NewGuid(),
                tcpEndPoint ?? TcpEndpoint,
                TcpConnectionManager.ConnectionTimeout,
                conn =>
            {
                // we execute callback on ThreadPool because on FreeBSD it can be called synchronously
                // causing deadlock
                ThreadPool.QueueUserWorkItem(_ =>
                {
                    if (!InteractiveMode)
                    {
                        Log.Info("TcpTypedConnection: connected to [{0}, L{1}, {2:B}].", conn.RemoteEndPoint, conn.LocalEndPoint, conn.ConnectionId);
                    }
                    if (connectionEstablished != null)
                    {
                        if (!connectionCreatedEvent.Wait(10000))
                        {
                            throw new Exception("TcpTypedConnection: creation took too long!");
                        }
                        connectionEstablished(typedConnection);
                    }
                });
            },
                (conn, error) =>
            {
                var message = string.Format("TcpTypedConnection: connection to [{0}, L{1}, {2:B}] failed. Error: {3}.",
                                            conn.RemoteEndPoint, conn.LocalEndPoint, conn.ConnectionId, error);
                Log.Error(message);

                if (connectionClosed != null)
                {
                    connectionClosed(null, error);
                }

                if (failContextOnError)
                {
                    context.Fail(reason: string.Format("Socket connection failed with error {0}.", error));
                }
            },
                verbose: !InteractiveMode);

            typedConnection = new Connection(connection, new RawMessageFormatter(_bufferManager), new LengthPrefixMessageFramer());
            typedConnection.ConnectionClosed +=
                (conn, error) =>
            {
                if (!InteractiveMode || error != SocketError.Success)
                {
                    Log.Info("TcpTypedConnection: connection [{0}, L{1}] was closed {2}",
                             conn.RemoteEndPoint, conn.LocalEndPoint,
                             error == SocketError.Success ? "cleanly." : "with error: " + error + ".");
                }

                if (connectionClosed != null)
                {
                    connectionClosed(conn, error);
                }
                else
                {
                    Log.Info("connectionClosed callback was null");
                }
            };
            connectionCreatedEvent.Set();

            typedConnection.ReceiveAsync(
                (conn, pkg) =>
            {
                var package       = new TcpPackage();
                bool validPackage = false;
                try
                {
                    package      = TcpPackage.FromArraySegment(new ArraySegment <byte>(pkg));
                    validPackage = true;

                    if (package.Command == TcpCommand.HeartbeatRequestCommand)
                    {
                        var resp = new TcpPackage(TcpCommand.HeartbeatResponseCommand, Guid.NewGuid(), null);
                        conn.EnqueueSend(resp.AsByteArray());
                        return;
                    }

                    handlePackage(conn, package);
                }
                catch (Exception ex)
                {
                    Log.InfoException(ex,
                                      "TcpTypedConnection: [{0}, L{1}] ERROR for {2}. Connection will be closed.",
                                      conn.RemoteEndPoint, conn.LocalEndPoint,
                                      validPackage ? package.Command as object : "<invalid package>");
                    conn.Close(ex.Message);

                    if (failContextOnError)
                    {
                        context.Fail(ex);
                    }
                }
            });

            return(typedConnection);
        }
 protected void EnqueueSend(TcpPackage package)
 {
     _getConnection().EnqueueSend(package);
 }
        private void WriteFlood(CommandProcessorContext context, int clientsCnt, int requestsCnt)
        {
            context.IsAsync();

            var clients        = new List <TcpTypedConnection <byte[]> >();
            var threads        = new List <Thread>();
            var autoResetEvent = new AutoResetEvent(false);

            var succ = 0;
            var fail = 0;
            var all  = 0;

            for (int i = 0; i < clientsCnt; i++)
            {
                var count = requestsCnt / clientsCnt + ((i == clientsCnt - 1) ? requestsCnt % clientsCnt : 0);

                var autoEvent     = new AutoResetEvent(false);
                var eventStreamId = "es" + Guid.NewGuid();

                var client = context.Client.CreateTcpConnection(
                    context,
                    (conn, pkg) =>
                {
                    if (pkg.Command != TcpCommand.WriteEventsCompleted)
                    {
                        context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                        return;
                    }

                    var dto = pkg.Data.Deserialize <TcpClientMessageDto.WriteEventsCompleted>();
                    if (dto.ErrorCode == (int)OperationErrorCode.Success)
                    {
                        if (Interlocked.Increment(ref succ) % 1000 == 0)
                        {
                            Console.Write(".");
                        }
                    }
                    else
                    {
                        Interlocked.Increment(ref fail);
                    }

                    if (Interlocked.Increment(ref all) == requestsCnt)
                    {
                        autoResetEvent.Set();
                    }
                    autoEvent.Set();
                },
                    connectionClosed: (conn, err) =>
                {
                    if (all < requestsCnt)
                    {
                        context.Fail(null, "Socket was closed, but not all requests were completed.");
                    }
                    else
                    {
                        context.Success();
                    }
                });
                clients.Add(client);

                threads.Add(new Thread(() =>
                {
                    for (int j = 0; j < count; ++j)
                    {
                        var write = new TcpClientMessageDto.WriteEvents(
                            eventStreamId,
                            ExpectedVersion.Any,
                            new[]
                        {
                            new TcpClientMessageDto.ClientEvent(Guid.NewGuid().ToByteArray(),
                                                                "TakeSomeSpaceEvent",
                                                                false,
                                                                Encoding.UTF8.GetBytes("DATA" + new string('*', 256)),
                                                                Encoding.UTF8.GetBytes("METADATA" + new string('$', 100)))
                        },
                            true);
                        var package = new TcpPackage(TcpCommand.WriteEvents, Guid.NewGuid(), write.Serialize());
                        client.EnqueueSend(package.AsByteArray());
                        autoEvent.WaitOne();
                    }
                }));
            }

            var sw = Stopwatch.StartNew();

            foreach (var thread in threads)
            {
                thread.IsBackground = true;
                thread.Start();
            }
            autoResetEvent.WaitOne();
            sw.Stop();

            foreach (var client in clients)
            {
                client.Close();
            }

            context.Log.Info("Completed. Successes: {0}, failures: {1}", succ, fail);

            var reqPerSec = (requestsCnt + 0.0) / sw.ElapsedMilliseconds * 1000;

            context.Log.Info("{0} requests completed in {1}ms ({2:0.00} reqs per sec).",
                             all,
                             sw.ElapsedMilliseconds,
                             reqPerSec);

            PerfUtils.LogData(
                Keyword,
                PerfUtils.Row(PerfUtils.Col("clientsCnt", clientsCnt),
                              PerfUtils.Col("requestsCnt", requestsCnt),
                              PerfUtils.Col("ElapsedMilliseconds", sw.ElapsedMilliseconds)),
                PerfUtils.Row(PerfUtils.Col("successes", succ), PerfUtils.Col("failures", fail)));

            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-reqPerSec", Keyword, clientsCnt, requestsCnt),
                                           (int)reqPerSec);

            PerfUtils.LogTeamCityGraphData(
                string.Format("{0}-{1}-{2}-failureSuccessRate", Keyword, clientsCnt, requestsCnt),
                100 * fail / (fail + succ));

            PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword),
                                           (int)(sw.ElapsedMilliseconds / requestsCnt));

            if (succ < fail)
            {
                context.Fail(reason: "Number of failures is greater than number of successes");
            }
            else
            {
                context.Success();
            }
        }
 protected abstract bool InspectPackage(TcpPackage package, out InspectionResult result);
Beispiel #23
0
        public bool Execute(CommandProcessorContext context, string[] args)
        {
            var eventStreamId = "test-stream";
            var fromNumber    = 0;

            if (args.Length > 0)
            {
                if (args.Length > 2)
                {
                    return(false);
                }

                eventStreamId = args[0];

                if (args.Length == 2)
                {
                    fromNumber = int.Parse(args[1]);
                }
            }

            context.IsAsync();

            var readDto = new ClientMessageDto.ReadEvent(Guid.NewGuid(), eventStreamId, fromNumber);
            var package = new TcpPackage(TcpCommand.ReadEvent, readDto.Serialize());

            var sw = new Stopwatch();

            context.Client.CreateTcpConnection(
                context,
                connectionEstablished: conn =>
            {
                context.Log.Info("[{0}]: Reading...", conn.EffectiveEndPoint);
                sw.Start();
                conn.EnqueueSend(package.AsByteArray());
            },
                handlePackage: (conn, pkg) =>
            {
                if (pkg.Command != TcpCommand.ReadEventCompleted)
                {
                    context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                    return;
                }

                sw.Stop();

                var dto = pkg.Data.Deserialize <ClientMessageDto.ReadEventCompleted>();

                context.Log.Info("READ events from <{0}>:\n\n"
                                 + "\tCorrelationId: {1}\n"
                                 + "\tEventStreamId: {2}\n"
                                 + "\tEventNumber:   {3}\n"
                                 + "\tReadResult:    {4}\n"
                                 + "\tEventType:     {5}\n"
                                 + "\tData:          {6}\n"
                                 + "\tMetadata:      {7}\n",
                                 eventStreamId,
                                 dto.CorrelationId,
                                 dto.EventStreamId,
                                 dto.EventNumber,
                                 (SingleReadResult)dto.Result,
                                 dto.EventType,
                                 Encoding.UTF8.GetString(dto.Data ?? new byte[0]),
                                 Encoding.UTF8.GetString(dto.Metadata ?? new byte[0]));

                context.Log.Info("Read request took: {0}.", sw.Elapsed);

                PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword), (int)sw.ElapsedMilliseconds);

                conn.Close();
                context.Success();
            },
                connectionClosed: (connection, error) =>
            {
                if (error == SocketError.Success)
                {
                    context.Success();
                }
                else
                {
                    context.Fail();
                }
            });

            context.WaitForCompletion();
            return(true);
        }
        public InspectionResult InspectPackage(TcpPackage package)
        {
            try
            {
                InspectionResult result;
                if (InspectPackage(package, out result))
                {
                    return(result);
                }

                switch (package.Command)
                {
                case TcpCommand.StreamEventAppeared:
                {
                    var dto = package.Data.Deserialize <ClientMessage.StreamEventAppeared>();
                    EventAppeared(new ResolvedEvent(dto.Event));
                    return(new InspectionResult(InspectionDecision.DoNothing, "StreamEventAppeared"));
                }

                case TcpCommand.SubscriptionDropped:
                {
                    var dto = package.Data.Deserialize <ClientMessage.SubscriptionDropped>();
                    switch (dto.Reason)
                    {
                    case ClientMessage.SubscriptionDropped.SubscriptionDropReason.Unsubscribed:
                        DropSubscription(SubscriptionDropReason.UserInitiated, null);
                        break;

                    case ClientMessage.SubscriptionDropped.SubscriptionDropReason.AccessDenied:
                        DropSubscription(SubscriptionDropReason.AccessDenied,
                                         new AccessDeniedException(string.Format("Subscription to '{0}' failed due to access denied.", _streamId == string.Empty ? "<all>" : _streamId)));
                        break;

                    case ClientMessage.SubscriptionDropped.SubscriptionDropReason.NotFound:
                        DropSubscription(SubscriptionDropReason.NotFound,
                                         new ArgumentException(string.Format("Subscription to '{0}' failed due to not found.", _streamId == string.Empty ? "<all>" : _streamId)));
                        break;

                    default:
                        if (_verboseLogging)
                        {
                            _log.Debug("Subscription dropped by server. Reason: {0}.", dto.Reason);
                        }
                        DropSubscription(SubscriptionDropReason.Unknown,
                                         new CommandNotExpectedException(string.Format("Unsubscribe reason: '{0}'.", dto.Reason)));
                        break;
                    }
                    return(new InspectionResult(InspectionDecision.EndOperation, string.Format("SubscriptionDropped: {0}", dto.Reason)));
                }

                case TcpCommand.NotAuthenticated:
                {
                    string message = Helper.EatException(() => Helper.UTF8NoBom.GetString(package.Data.Array, package.Data.Offset, package.Data.Count));
                    DropSubscription(SubscriptionDropReason.NotAuthenticated,
                                     new NotAuthenticatedException(string.IsNullOrEmpty(message) ? "Authentication error" : message));
                    return(new InspectionResult(InspectionDecision.EndOperation, "NotAuthenticated"));
                }

                case TcpCommand.BadRequest:
                {
                    string message = Helper.EatException(() => Helper.UTF8NoBom.GetString(package.Data.Array, package.Data.Offset, package.Data.Count));
                    DropSubscription(SubscriptionDropReason.ServerError,
                                     new ServerErrorException(string.IsNullOrEmpty(message) ? "<no message>" : message));
                    return(new InspectionResult(InspectionDecision.EndOperation, string.Format("BadRequest: {0}", message)));
                }

                case TcpCommand.NotHandled:
                {
                    if (_subscription != null)
                    {
                        throw new Exception("NotHandled command appeared while we were already subscribed.");
                    }

                    var message = package.Data.Deserialize <ClientMessage.NotHandled>();
                    switch (message.Reason)
                    {
                    case ClientMessage.NotHandled.NotHandledReason.NotReady:
                        return(new InspectionResult(InspectionDecision.Retry, "NotHandled - NotReady"));

                    case ClientMessage.NotHandled.NotHandledReason.TooBusy:
                        return(new InspectionResult(InspectionDecision.Retry, "NotHandled - TooBusy"));

                    case ClientMessage.NotHandled.NotHandledReason.NotMaster:
                        var masterInfo = message.AdditionalInfo.Deserialize <ClientMessage.NotHandled.MasterInfo>();
                        return(new InspectionResult(InspectionDecision.Reconnect, "NotHandled - NotMaster",
                                                    masterInfo.ExternalTcpEndPoint, masterInfo.ExternalSecureTcpEndPoint));

                    default:
                        _log.Error("Unknown NotHandledReason: {0}.", message.Reason);
                        return(new InspectionResult(InspectionDecision.Retry, "NotHandled - <unknown>"));
                    }
                }

                default:
                {
                    DropSubscription(SubscriptionDropReason.ServerError,
                                     new CommandNotExpectedException(package.Command.ToString()));
                    return(new InspectionResult(InspectionDecision.EndOperation, package.Command.ToString()));
                }
                }
            }
            catch (Exception e)
            {
                DropSubscription(SubscriptionDropReason.Unknown, e);
                return(new InspectionResult(InspectionDecision.EndOperation, string.Format("Exception - {0}", e.Message)));
            }
        }
        private void WriteFlood(CommandProcessorContext context, int clientsCnt, long requestsCnt, int streamsCnt, int size, int batchSize)
        {
            context.IsAsync();

            var doneEvent = new ManualResetEventSlim(false);
            var clients   = new List <TcpTypedConnection <byte[]> >();
            var threads   = new List <Thread>();

            long succ            = 0;
            long last            = 0;
            long fail            = 0;
            long prepTimeout     = 0;
            long commitTimeout   = 0;
            long forwardTimeout  = 0;
            long wrongExpVersion = 0;
            long streamDeleted   = 0;
            long all             = 0;

            var streams = Enumerable.Range(0, streamsCnt).Select(x => Guid.NewGuid().ToString()).ToArray();
            //var streams = Enumerable.Range(0, streamsCnt).Select(x => string.Format("stream-{0}", x)).ToArray();
            var sw2 = new Stopwatch();

            for (int i = 0; i < clientsCnt; i++)
            {
                var  count    = requestsCnt / clientsCnt + ((i == clientsCnt - 1) ? requestsCnt % clientsCnt : 0);
                long sent     = 0;
                long received = 0;
                var  rnd      = new Random();
                var  client   = context.Client.CreateTcpConnection(
                    context,
                    (conn, pkg) =>
                {
                    if (pkg.Command != TcpCommand.WriteEventsCompleted)
                    {
                        context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                        return;
                    }

                    var dto = pkg.Data.Deserialize <TcpClientMessageDto.WriteEventsCompleted>();
                    _monitor.EndOperation(pkg.CorrelationId);
                    switch (dto.Result)
                    {
                    case TcpClientMessageDto.OperationResult.Success:
                        Interlocked.Add(ref succ, batchSize);
                        if (succ - last > 1000)
                        {
                            last = succ;
                            Console.Write(".");
                        }
                        break;

                    case TcpClientMessageDto.OperationResult.PrepareTimeout:
                        Interlocked.Increment(ref prepTimeout);
                        break;

                    case TcpClientMessageDto.OperationResult.CommitTimeout:
                        Interlocked.Increment(ref commitTimeout);
                        break;

                    case TcpClientMessageDto.OperationResult.ForwardTimeout:
                        Interlocked.Increment(ref forwardTimeout);
                        break;

                    case TcpClientMessageDto.OperationResult.WrongExpectedVersion:
                        Interlocked.Increment(ref wrongExpVersion);
                        break;

                    case TcpClientMessageDto.OperationResult.StreamDeleted:
                        Interlocked.Increment(ref streamDeleted);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                    if (dto.Result != TcpClientMessageDto.OperationResult.Success)
                    {
                        if (Interlocked.Increment(ref fail) % 1000 == 0)
                        {
                            Console.Write('#');
                        }
                    }
                    Interlocked.Increment(ref received);
                    var localAll = Interlocked.Add(ref all, batchSize);
                    if (localAll % 100000 == 0)
                    {
                        var elapsed = sw2.Elapsed;
                        sw2.Restart();
                        context.Log.Trace("\nDONE TOTAL {writes} WRITES IN {elapsed} ({rate:0.0}/s) [S:{success}, F:{failures} (WEV:{wrongExpectedVersion}, P:{prepareTimeout}, C:{commitTimeout}, F:{forwardTimeout}, D:{streamDeleted})].",
                                          localAll, elapsed, 1000.0 * 100000 / elapsed.TotalMilliseconds,
                                          succ, fail,
                                          wrongExpVersion, prepTimeout, commitTimeout, forwardTimeout, streamDeleted);
                    }
                    if (localAll >= requestsCnt)
                    {
                        context.Success();
                        doneEvent.Set();
                    }
                },
                    connectionClosed: (conn, err) => context.Fail(reason: "Connection was closed prematurely."));
                clients.Add(client);

                threads.Add(new Thread(() =>
                {
                    for (int j = 0; j < count; ++j)
                    {
                        var events = new TcpClientMessageDto.NewEvent[batchSize];
                        for (int q = 0; q < batchSize; q++)
                        {
                            events[q] = new TcpClientMessageDto.NewEvent(Guid.NewGuid().ToByteArray(),
                                                                         "TakeSomeSpaceEvent",
                                                                         1, 0,
                                                                         Common.Utils.Helper.UTF8NoBom.GetBytes("{ \"DATA\" : \"" + new string('*', size) + "\"}"),
                                                                         Common.Utils.Helper.UTF8NoBom.GetBytes("{ \"METADATA\" : \"" + new string('$', 100) + "\"}"));
                        }
                        var corrid = Guid.NewGuid();
                        var write  = new TcpClientMessageDto.WriteEvents(
                            streams[rnd.Next(streamsCnt)],
                            ExpectedVersion.Any,
                            events,
                            false);
                        var package = new TcpPackage(TcpCommand.WriteEvents, corrid, write.Serialize());
                        _monitor.StartOperation(corrid);
                        client.EnqueueSend(package.AsByteArray());

                        var localSent = Interlocked.Increment(ref sent);
                        while (localSent - Interlocked.Read(ref received) > context.Client.Options.WriteWindow / clientsCnt)
                        {
                            Thread.Sleep(1);
                        }
                    }
                })
                {
                    IsBackground = true
                });
            }

            var sw = Stopwatch.StartNew();

            sw2.Start();
            threads.ForEach(thread => thread.Start());
            doneEvent.Wait();
            sw.Stop();
            clients.ForEach(client => client.Close());

            context.Log.Info("Completed. Successes: {success}, failures: {failures} (WRONG VERSION: {wrongExpectedVersion}, P: {prepareTimeout}, C: {commitTimeout}, F: {forwardTimeout}, D: {streamDeleted})",
                             succ, fail,
                             wrongExpVersion, prepTimeout, commitTimeout, forwardTimeout, streamDeleted);

            var reqPerSec = (all + 0.0) / sw.ElapsedMilliseconds * 1000;

            context.Log.Info("{requests} requests completed in {elapsed}ms ({rate:0.00} reqs per sec).", all, sw.ElapsedMilliseconds, reqPerSec);

            PerfUtils.LogData(
                Keyword,
                PerfUtils.Row(PerfUtils.Col("clientsCnt", clientsCnt),
                              PerfUtils.Col("requestsCnt", requestsCnt),
                              PerfUtils.Col("ElapsedMilliseconds", sw.ElapsedMilliseconds)),
                PerfUtils.Row(PerfUtils.Col("successes", succ), PerfUtils.Col("failures", fail)));

            var failuresRate = (int)(100 * fail / (fail + succ));

            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-reqPerSec", Keyword, clientsCnt, requestsCnt), (int)reqPerSec);
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-failureSuccessRate", Keyword, clientsCnt, requestsCnt), failuresRate);
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-c{1}-r{2}-st{3}-s{4}-reqPerSec", Keyword, clientsCnt, requestsCnt, streamsCnt, size), (int)reqPerSec);
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-c{1}-r{2}-st{3}-s{4}-failureSuccessRate", Keyword, clientsCnt, requestsCnt, streamsCnt, size), failuresRate);
            _monitor.GetMeasurementDetails();
            if (Interlocked.Read(ref succ) != requestsCnt)
            {
                context.Fail(reason: "There were errors or not all requests completed.");
            }
            else
            {
                context.Success();
            }
        }
        private void PingFlood(CommandProcessorContext context, int clientsCnt, long requestsCnt)
        {
            context.IsAsync();

            var  doneEvent = new ManualResetEventSlim(false);
            var  clients   = new List <TcpTypedConnection <byte[]> >();
            var  threads   = new List <Thread>();
            long all       = 0;

            for (int i = 0; i < clientsCnt; i++)
            {
                var  count    = requestsCnt / clientsCnt + ((i == clientsCnt - 1) ? requestsCnt % clientsCnt : 0);
                long received = 0;
                long sent     = 0;
                var  client   = context.Client.CreateTcpConnection(
                    context,
                    (conn, msg) => {
                    Interlocked.Increment(ref received);
                    var pongs = Interlocked.Increment(ref all);
                    if (pongs % 10000 == 0)
                    {
                        Console.Write('.');
                    }
                    if (pongs == requestsCnt)
                    {
                        context.Success();
                        doneEvent.Set();
                    }
                },
                    connectionClosed: (conn, err) => context.Fail(reason: "Connection was closed prematurely."));
                clients.Add(client);

                threads.Add(new Thread(() => {
                    for (int j = 0; j < count; ++j)
                    {
                        var package = new TcpPackage(TcpCommand.Ping, Guid.NewGuid(), Payload);
                        client.EnqueueSend(package.AsByteArray());

                        var localSent = Interlocked.Increment(ref sent);
                        while (localSent - Interlocked.Read(ref received) >
                               context.Client.Options.PingWindow / clientsCnt)
                        {
                            Thread.Sleep(1);
                        }
                    }
                })
                {
                    IsBackground = true
                });
            }

            var sw = Stopwatch.StartNew();

            threads.ForEach(thread => thread.Start());
            doneEvent.Wait();
            sw.Stop();
            clients.ForEach(client => client.Close());

            var reqPerSec = (all + 0.0) / sw.ElapsedMilliseconds * 1000;

            context.Log.Info("{requests} requests completed in {elapsed}ms ({rate:0.00} reqs per sec).", all,
                             sw.ElapsedMilliseconds, reqPerSec);
            PerfUtils.LogData(Keyword,
                              PerfUtils.Row(PerfUtils.Col("clientsCnt", clientsCnt),
                                            PerfUtils.Col("requestsCnt", requestsCnt),
                                            PerfUtils.Col("ElapsedMilliseconds", sw.ElapsedMilliseconds)));
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-reqPerSec", Keyword, clientsCnt, requestsCnt),
                                           (int)reqPerSec);

            if (Interlocked.Read(ref all) == requestsCnt)
            {
                context.Success();
            }
            else
            {
                context.Fail();
            }
        }
Beispiel #27
0
        private void Read(Status status, int readerIdx, CommandProcessorContext context,
                          ManualResetEventSlim finishedEvent)
        {
            TcpTypedConnection <byte[]> connection;
            var iteration = new AutoResetEvent(false);

            var successes = 0;
            var fails     = 0;

            var rnd = new Random(readerIdx);

            var streamIdx = -1;
            var eventidx  = -1;

            Action <TcpTypedConnection <byte[]>, TcpPackage> packageReceived = (conn, pkg) => {
                var dto = pkg.Data.Deserialize <TcpClientMessageDto.ReadEventCompleted>();
                switch (dto.Result)
                {
                case TcpClientMessageDto.ReadEventCompleted.ReadEventResult.Success:
                    if (Equal(_streams[streamIdx], eventidx, dto.Event.Event.EventType, dto.Event.Event.Data))
                    {
                        successes++;
                        if (successes % 1000 == 0)
                        {
                            status.ReportReadsProgress(readerIdx, successes, fails);
                        }
                    }
                    else
                    {
                        fails++;
                        status.ReportReadError(readerIdx, _streams[streamIdx], eventidx);
                    }

                    break;

                case TcpClientMessageDto.ReadEventCompleted.ReadEventResult.NotFound:
                case TcpClientMessageDto.ReadEventCompleted.ReadEventResult.NoStream:
                case TcpClientMessageDto.ReadEventCompleted.ReadEventResult.StreamDeleted:
                case TcpClientMessageDto.ReadEventCompleted.ReadEventResult.Error:
                case TcpClientMessageDto.ReadEventCompleted.ReadEventResult.AccessDenied:
                    fails++;
                    status.ReportNotFoundOnRead(readerIdx, _streams[streamIdx], eventidx);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                iteration.Set();
            };
            Action <TcpTypedConnection <byte[]> >             established = _ => { };
            Action <TcpTypedConnection <byte[]>, SocketError> closed      = null;

            closed = (_, __) => {
                if (!context._tcpTestClient.Options.Reconnect)
                {
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
                connection =
                    context._tcpTestClient.CreateTcpConnection(context, packageReceived, cn => iteration.Set(), closed, false);
            };

            connection = context._tcpTestClient.CreateTcpConnection(context, packageReceived, established, closed, false);

            while (!_stopReading)
            {
                streamIdx = NextStreamForReading(rnd, readerIdx);
                int head;
                lock (_heads)
                    head = _heads[streamIdx];

                if (head > 0)
                {
                    eventidx = NextRandomEventVersion(rnd, head);
                    var stream = _streams[streamIdx];
                    var corrid = Guid.NewGuid();
                    var read   = new TcpClientMessageDto.ReadEvent(stream, eventidx, resolveLinkTos: false,
                                                                   requireLeader: false);
                    var package = new TcpPackage(TcpCommand.ReadEvent, corrid, read.Serialize());

                    connection.EnqueueSend(package.AsByteArray());
                    iteration.WaitOne();
                }
                else
                {
                    Thread.Sleep(100);
                }
            }

            status.ReportReadsProgress(readerIdx, successes, fails);
            status.FinilizeStatus(readerIdx, fails == 0);
            context._tcpTestClient.Options.Reconnect = false;
            connection.Close();
            finishedEvent.Set();
        }
        private void WriteFlood(CommandProcessorContext context, int writeCnt, int clientsCnt, long requestsCnt)
        {
            const string data = "test-data";

            context.IsAsync();

            var  clients   = new List <TcpTypedConnection <byte[]> >();
            var  threads   = new List <Thread>();
            var  doneEvent = new ManualResetEventSlim(false);
            long succ      = 0;
            long fail      = 0;
            long all       = 0;

            for (int i = 0; i < clientsCnt; i++)
            {
                var count          = requestsCnt / clientsCnt + ((i == clientsCnt - 1) ? requestsCnt % clientsCnt : 0);
                var localDoneEvent = new AutoResetEvent(false);
                var eventStreamId  = "es" + Guid.NewGuid();
                var client         = context.Client.CreateTcpConnection(
                    context,
                    (conn, pkg) =>
                {
                    if (pkg.Command != TcpCommand.WriteEventsCompleted)
                    {
                        context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                        return;
                    }

                    var dto = pkg.Data.Deserialize <TcpClientMessageDto.WriteEventsCompleted>();
                    if (dto.Result == TcpClientMessageDto.OperationResult.Success)
                    {
                        if (Interlocked.Increment(ref succ) % 1000 == 0)
                        {
                            Console.Write(".");
                        }
                    }
                    else
                    {
                        if (Interlocked.Increment(ref fail) % 1000 == 0)
                        {
                            Console.Write("#");
                        }
                    }

                    if (Interlocked.Increment(ref all) == requestsCnt)
                    {
                        context.Success();
                        doneEvent.Set();
                    }
                    localDoneEvent.Set();
                },
                    connectionClosed: (conn, err) => context.Fail(reason: "Connection was closed prematurely."));
                clients.Add(client);

                threads.Add(new Thread(() =>
                {
                    for (int j = 0; j < count; ++j)
                    {
                        var writeDto = new TcpClientMessageDto.WriteEvents(
                            eventStreamId,
                            ExpectedVersion.Any,
                            Enumerable.Range(0, writeCnt).Select(x =>
                                                                 new TcpClientMessageDto.NewEvent(Guid.NewGuid().ToByteArray(),
                                                                                                  "type",
                                                                                                  0, 0,
                                                                                                  Common.Utils.Helper.UTF8NoBom.GetBytes(data),
                                                                                                  new byte[0])).ToArray(),
                            false);
                        var package = new TcpPackage(TcpCommand.WriteEvents, Guid.NewGuid(), writeDto.Serialize());
                        client.EnqueueSend(package.AsByteArray());
                        localDoneEvent.WaitOne();
                    }
                })
                {
                    IsBackground = true
                });
            }

            var sw = Stopwatch.StartNew();

            threads.ForEach(thread => thread.Start());
            doneEvent.Wait();
            sw.Stop();
            clients.ForEach(client => client.Close());

            var reqPerSec = (all + 0.0) / sw.ElapsedMilliseconds * 1000;

            context.Log.Info("Completed. Successes: {0}, failures: {1}", succ, fail);
            context.Log.Info("{0} requests completed in {1}ms ({2:0.00} reqs per sec).", all, sw.ElapsedMilliseconds, reqPerSec);

            PerfUtils.LogData(Keyword,
                              PerfUtils.Row(PerfUtils.Col("clientsCnt", clientsCnt),
                                            PerfUtils.Col("requestsCnt", requestsCnt),
                                            PerfUtils.Col("ElapsedMilliseconds", sw.ElapsedMilliseconds)),
                              PerfUtils.Row(PerfUtils.Col("successes", succ), PerfUtils.Col("failures", fail)));
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-reqPerSec", Keyword, clientsCnt, requestsCnt), (int)reqPerSec);
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-{1}-{2}-failureSuccessRate", Keyword, clientsCnt, requestsCnt), (int)(100.0 * fail / (fail + succ)));
            PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword), (int)(sw.ElapsedMilliseconds / requestsCnt));

            if (succ != requestsCnt)
            {
                context.Fail(reason: "There were errors or not all requests completed.");
            }
            else
            {
                context.Success();
            }
        }
Beispiel #29
0
        public Connection CreateTcpConnection(Action <Connection, TcpPackage> handlePackage,
                                              Action <Connection> connectionEstablished,
                                              Action <Connection, IPEndPoint, SocketError> connectionClosed)
        {
            var        connectionCreatedEvent = new AutoResetEvent(false);
            Connection typedConnection        = null;

            var connection = _connector.ConnectTo(
                _tcpEndpoint,
                tcpConnection =>
            {
                Log.Info("Connected to [{0}].", tcpConnection.EffectiveEndPoint);
                connectionCreatedEvent.WaitOne(500);
                connectionEstablished(typedConnection);
            },
                (conn, error) =>
            {
                var message = string.Format("Connection to [{0}] failed. Error: {1}.", conn.EffectiveEndPoint, error);
                Log.Error(message);

                connectionClosed(null, conn.EffectiveEndPoint, error);
            });

            typedConnection = new Connection(connection);
            typedConnection.ConnectionClosed +=
                (conn, error) =>
            {
                Log.Info("Connection [{0}] was closed {1}",
                         conn.EffectiveEndPoint,
                         error == SocketError.Success ? "cleanly." : "with error: " + error + ".");

                connectionClosed(conn, conn.EffectiveEndPoint, error);
            };

            connectionCreatedEvent.Set();

            typedConnection.ReceiveAsync((conn, pkg) =>
            {
                var package = new TcpPackage();
                var valid   = false;
                try
                {
                    package = TcpPackage.FromArraySegment(new ArraySegment <byte>(pkg));
                    valid   = true;

                    if (package.Command == TcpCommand.HeartbeatRequestCommand)
                    {
                        var response = new TcpPackage(TcpCommand.HeartbeatResponseCommand, Guid.NewGuid(), null);
                        conn.EnqueueSend(response.AsByteArray());
                        return;
                    }

                    handlePackage(conn, package);
                }
                catch (Exception e)
                {
                    var effectiveEndPoint = conn.EffectiveEndPoint;
                    var message           = string.Format("[{0}] ERROR for {1}. Connection will be closed.",
                                                          effectiveEndPoint,
                                                          valid ? package.Command as object : "<invalid package>");

                    Log.Info(e, message);
                    conn.Close();
                }
            });

            return(typedConnection);
        }
Beispiel #30
0
        public bool Execute(CommandProcessorContext context, string[] args)
        {
            var    eventStreamId   = "test-stream";
            var    expectedVersion = ExpectedVersion.Any;
            var    data            = GenerateTestData();
            string metadata        = null;

            if (args.Length > 0)
            {
                if (args.Length < 3 || args.Length > 4)
                {
                    return(false);
                }
                eventStreamId   = args[0];
                expectedVersion = args[1].ToUpper() == "ANY" ? ExpectedVersion.Any : int.Parse(args[1]);
                data            = args[2];
                if (args.Length == 4)
                {
                    metadata = args[3];
                }
            }

            context.IsAsync();
            var writeDto = new TcpClientMessageDto.WriteEvents(
                eventStreamId,
                expectedVersion,
                new[]
            {
                new TcpClientMessageDto.NewEvent(Guid.NewGuid().ToByteArray(),
                                                 "JsonDataEvent",
                                                 1, 0,
                                                 Helper.UTF8NoBom.GetBytes(data),
                                                 Helper.UTF8NoBom.GetBytes(metadata ?? string.Empty))
            },
                false);
            var package = new TcpPackage(TcpCommand.WriteEvents, Guid.NewGuid(), writeDto.Serialize());

            var  sw           = new Stopwatch();
            bool dataReceived = false;

            context.Client.CreateTcpConnection(
                context,
                connectionEstablished: conn =>
            {
                context.Log.Info("[{remoteEndPoint}, L{localEndPoint}]: Writing...", conn.RemoteEndPoint, conn.LocalEndPoint);
                sw.Start();
                conn.EnqueueSend(package.AsByteArray());
            },
                handlePackage: (conn, pkg) =>
            {
                if (pkg.Command != TcpCommand.WriteEventsCompleted)
                {
                    context.Fail(reason: string.Format("Unexpected TCP package: {0}.", pkg.Command));
                    return;
                }

                dataReceived = true;
                sw.Stop();

                var dto = pkg.Data.Deserialize <TcpClientMessageDto.WriteEventsCompleted>();
                if (dto.Result == TcpClientMessageDto.OperationResult.Success)
                {
                    context.Log.Info("Successfully written. EventId: {correlationId}.", package.CorrelationId);
                    PerfUtils.LogTeamCityGraphData(string.Format("{0}-latency-ms", Keyword), (int)Math.Round(sw.Elapsed.TotalMilliseconds));
                }
                else
                {
                    context.Log.Info("Error while writing: {message} ({e}).", dto.Message, dto.Result);
                }

                context.Log.Info("Write request took: {elapsed}.", sw.Elapsed);
                conn.Close();
                context.Success();
            },
                connectionClosed: (connection, error) =>
            {
                if (dataReceived && error == SocketError.Success)
                {
                    context.Success();
                }
                else
                {
                    context.Fail();
                }
            });

            context.WaitForCompletion();
            return(true);
        }