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); }
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(); }
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); }
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(); } }
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(); }
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); }
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); }
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()); }
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); }
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(); }
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); }
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(); }
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); } }
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);
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(); } }
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(); } }
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); }
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); }