diff --git a/src/Microsoft.AspNet.SignalR.DCrank.Crank/Agent.cs b/src/Microsoft.AspNet.SignalR.DCrank.Crank/Agent.cs
index 1cd07b2..9cbaa2f 100755
--- a/src/Microsoft.AspNet.SignalR.DCrank.Crank/Agent.cs
+++ b/src/Microsoft.AspNet.SignalR.DCrank.Crank/Agent.cs
@@ -173,7 +173,7 @@ public void StopWorker(int workerId)
}
}
- public void StopWorkers()
+ public async Task StopWorkers()
{
var keys = _workers.Keys.ToList();
@@ -182,12 +182,18 @@ public void StopWorkers()
AgentWorker worker;
if (_workers.TryGetValue(key, out worker))
{
- worker.Worker.Stop();
- Runner.LogAgent("Agent stopped Worker {0}.", key);
+ await worker.Worker.Stop();
+ await Runner.LogAgent("Agent stopped Worker {0}.", key);
}
}
TotalConnectionsRequested = 0;
ApplyingLoad = false;
+
+ // Wait for workers to terminate
+ while (_workers.Count > 0)
+ {
+ await Task.Delay(1000);
+ }
}
public async Task Pong(int id, int value)
diff --git a/src/Microsoft.AspNet.SignalR.DCrank.Crank/DCrankArguments.cs b/src/Microsoft.AspNet.SignalR.DCrank.Crank/DCrankArguments.cs
index ec6c640..20eab22 100644
--- a/src/Microsoft.AspNet.SignalR.DCrank.Crank/DCrankArguments.cs
+++ b/src/Microsoft.AspNet.SignalR.DCrank.Crank/DCrankArguments.cs
@@ -8,7 +8,7 @@ public class DCrankArguments
[CommandLineParameter(Command = "?", Name = "Help", Default = false, Description = "Show Help", IsHelp = true)]
public bool Help { get; set; }
- [CommandLineParameter(Command = "Mode", Required = true, Description = "DCrank operating mode (Agent or Worker).")]
+ [CommandLineParameter(Command = "Mode", Required = false, Default = "commandline",Description = "DCrank operating mode (CommandLine, Agent, or Worker).")]
public string Mode { get; set; }
[CommandLineParameter(Command = "ControllerUrl", Required = false, Default = "http://localhost:17063", Description = "URL for Test Controller (Agent mode only).")]
@@ -16,5 +16,17 @@ public class DCrankArguments
[CommandLineParameter(Command = "ParentPid", Required = false, Description = "Process ID of calling agent (Worker mode only).")]
public int ParentPid { get; set; }
+
+ [CommandLineParameter(Command = "TargetUrl", Required = false, Default = "http://localhost:24037/", Description = "The URL for the test target (CommandLine mode only).")]
+ public string TargetUrl { get; set; }
+
+ [CommandLineParameter(Command = "Workers", Required = false, Default = 1, Description = "Number of worker processes to create (CommandLine mode only).")]
+ public int Workers { get; set; }
+
+ [CommandLineParameter(Command="Connections", Required = false, Default = 100000, Description = "The number of connections to establish with the test target (CommandLine mode only).")]
+ public int Connections { get; set; }
+
+ [CommandLineParameter(Command = "SendDuration", Required = false, Default = 300, Description = "(Send phase) Duration in seconds. Default: 300 seconds")]
+ public int SendDuration { get; set; }
}
}
diff --git a/src/Microsoft.AspNet.SignalR.DCrank.Crank/Microsoft.AspNet.SignalR.DCrank.Crank.csproj b/src/Microsoft.AspNet.SignalR.DCrank.Crank/Microsoft.AspNet.SignalR.DCrank.Crank.csproj
index 169c44f..e20daa2 100644
--- a/src/Microsoft.AspNet.SignalR.DCrank.Crank/Microsoft.AspNet.SignalR.DCrank.Crank.csproj
+++ b/src/Microsoft.AspNet.SignalR.DCrank.Crank/Microsoft.AspNet.SignalR.DCrank.Crank.csproj
@@ -61,6 +61,7 @@
+
diff --git a/src/Microsoft.AspNet.SignalR.DCrank.Crank/Program.cs b/src/Microsoft.AspNet.SignalR.DCrank.Crank/Program.cs
index 3a5119d..4a89a0a 100644
--- a/src/Microsoft.AspNet.SignalR.DCrank.Crank/Program.cs
+++ b/src/Microsoft.AspNet.SignalR.DCrank.Crank/Program.cs
@@ -12,14 +12,14 @@ static void Main(string[] args)
var arguments = CommandLine.Parse();
switch (arguments.Mode.ToLowerInvariant())
{
+ case "commandline":
+ StartCommandLine(arguments);
+ break;
case "agent":
- var agent = new Agent();
- var runner = new HubRunner(agent, arguments.ControllerUrl);
- runner.Run().Wait();
+ StartAgent(arguments);
break;
case "worker":
- var worker = new Worker(arguments.ParentPid);
- worker.Run().Wait();
+ StartWorker(arguments);
break;
default:
throw new ArgumentException(string.Format("Invalid value for Mode \"{0}\"", arguments.Mode));
@@ -35,5 +35,25 @@ static void Main(string[] args)
Console.WriteLine(ex.Message);
}
}
+
+ private static void StartCommandLine(DCrankArguments arguments)
+ {
+ var agent = new Agent();
+ var runner = new Runner(agent, arguments);
+ runner.Run().Wait();
+ }
+
+ private static void StartAgent(DCrankArguments arguments)
+ {
+ var agent = new Agent();
+ var runner = new HubRunner(agent, arguments.ControllerUrl);
+ runner.Run().Wait();
+ }
+
+ private static void StartWorker(DCrankArguments arguments)
+ {
+ var worker = new Worker(arguments.ParentPid);
+ worker.Run().Wait();
+ }
}
}
diff --git a/src/Microsoft.AspNet.SignalR.DCrank.Crank/Runner.cs b/src/Microsoft.AspNet.SignalR.DCrank.Crank/Runner.cs
new file mode 100644
index 0000000..36be2f3
--- /dev/null
+++ b/src/Microsoft.AspNet.SignalR.DCrank.Crank/Runner.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace Microsoft.AspNet.SignalR.DCrank.Crank
+{
+ public class Runner : IRunner
+ {
+ private readonly Agent _agent;
+ private readonly string _targetUrl;
+ private readonly int _numberOfWorkers;
+ private readonly int _numberOfConnections;
+ private readonly int _sendDurationSeconds;
+
+ public Runner(Agent agent, DCrankArguments arguments)
+ {
+ _agent = agent;
+ _targetUrl = arguments.TargetUrl;
+ _numberOfWorkers = arguments.Workers;
+ _numberOfConnections = arguments.Connections;
+ _sendDurationSeconds = arguments.SendDuration;
+ }
+
+ public async Task Run()
+ {
+ _agent.Runner = this;
+
+ var connectionsPerWorker = _numberOfConnections / _numberOfWorkers;
+ _agent.StartWorkers(_targetUrl, _numberOfWorkers, connectionsPerWorker);
+
+ // Begin writing worker status information
+ var writeStatusCts = new CancellationTokenSource();
+ var writeStatusTask = WriteConnectionStatus(writeStatusCts.Token);
+
+ // Wait until all connections are connected
+ while (_agent.GetWorkerStatus().Aggregate(0, (state, status) => state + status.Value.ConnectedCount) <
+ _agent.TotalConnectionsRequested)
+ {
+ await Task.Delay(1000);
+ }
+
+ // Stay connected for the duration of the send phase
+ await Task.Delay(TimeSpan.FromSeconds(_sendDurationSeconds));
+
+ // Disconnect
+ await _agent.StopWorkers();
+
+ // Stop writing worker status information
+ writeStatusCts.Cancel();
+ await writeStatusTask;
+ }
+
+ private async Task WriteConnectionStatus(CancellationToken cancellationToken)
+ {
+ await Task.Run(async () =>
+ {
+ while (!cancellationToken.IsCancellationRequested)
+ {
+ var statusDictionary = _agent.GetWorkerStatus();
+ foreach (var key in statusDictionary.Keys)
+ {
+ Trace.WriteLine(string.Format("({0}) {1}", key, JsonConvert.SerializeObject(statusDictionary[key])));
+ }
+ await Task.Delay(1000);
+ }
+ });
+ }
+
+ public Task PongWorker(int workerId, int value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public async Task LogAgent(string format, params object[] arguments)
+ {
+ Trace.WriteLine(string.Format(format, arguments));
+ }
+
+ public async Task LogWorker(int workerId, string format, params object[] arguments)
+ {
+ Trace.WriteLine(string.Format("({0}) {1}", workerId, string.Format(format, arguments)));
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.SignalR.DCrank.Crank/Worker.cs b/src/Microsoft.AspNet.SignalR.DCrank.Crank/Worker.cs
index cd7b898..aeb1b1b 100755
--- a/src/Microsoft.AspNet.SignalR.DCrank.Crank/Worker.cs
+++ b/src/Microsoft.AspNet.SignalR.DCrank.Crank/Worker.cs
@@ -160,7 +160,13 @@ await _agent.Status(
);
// Sending once per 5 seconds to avoid overloading the Test Controller
- await Task.Delay(5000, cancellationToken);
+ try
+ {
+ await Task.Delay(5000, cancellationToken);
+ }
+ catch (TaskCanceledException)
+ {
+ }
}
}
}