COMPSCI 711 1 radu/2020
Assignment 2
Assignment 1 required the design and develop a faithful sequential emulation of the
Echo algorithm, extended to determine the size of the network.
Assignment 2 requires two non-sequential versions of Assignment 1’s solution:
1. A multi-threaded implementation using channels, as available in System.Threading.Channels.
2. A multi-process implementation based on HTTP services, as available via ASP.NET Core – additional layers such as WebAPI (REST), Carter, gRPC are acceptable (but please ask).
As before, there is a central message dispatcher called Arcs, which can also act as virtual node 0. Arcs read the input config from stdin and traces messages on standout, using the same conventions, constraints, specs. You can your own sequential solution for A#1, or the model solution, or a combination of both (your choice).
To minimize the changes, use the following blueprint, where thin lines represent procedure calls, thick line channels or HTTP request/responses, and dotted lines an optional initialisation component:
A good implementation will localise most of the communication specifics in the proxy classes, and then the main Arcs and Node classes will be virtually the same.
In the Channels version, all components are included in the same source file.
In the HTTP version, the arcs process is described in one file, and the node process in another. Each node will start its own HTTP service, listening at port 8080+node number.
COMPSCI 711 2 radu/2020
Development language and platform
C#, for .NET Core 3.1.X (which is free, open source, cross-platform, and LTS).
Marks: 7 course marks
Part I: 3 marks
Part II: 4 marks, plus 1 bonus mark for each of the other two alternatives
Submission
For part 1 (Channels), submit to automarker:
https://www.automarker.cs.auckland.ac.nz/student.php
Submit just one single C# source file, named as UPI.cs. For part 2 (HTTP), submit to ADB:
https://adb.auckland.ac.nz/
Submit two C# source files, named as UPI-arcs.cs and UPI-node.cs.
For both parts, replace UPI by your actual university ID, e.g. jbon007.
Ensure that all programs terminate properly, otherwise you may get timeout errors.
Readings
An Introduction to System.Threading.Channels
System.Threading.Channels Namespace
https://docs.microsoft.com/en- us/dotnet/api/system.threading.channels?view=netcore-3.1
Create web APIs with ASP.NET Core
https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-3.1
Carter
https://github.com/CarterCommunity/Carter
gRPC
https://docs.microsoft.com/en-us/aspnet/core/grpc/?view=aspnetcore-3.1
COMPSCI 711 3 radu/2020
A#2.2 FAQ – Problems and solutions
gRPC Appendix
Problems
o Multiple servers starting on the same code base — concurrent updates o Process API ok for console and UI apps, but less for server apps
o ProcessAPIredirectioncomplicated
o Servers have unpredictable startup delays — ensure they are listening o Servers may accidentally hang — self stop, outside (Arcs) stop
Solutions
o Projects structure: Arcs contains a Node subfolder, for the node services
o Arcs write out starting batch script — .bat, .sh
o Serversstartwithdelays–1sec?
o Arcs calls this batch via Process.Start — does not directly start individual node servers
o Beforestarting,ArcspingseachurlwithanewAYT(AreYouThere)message
o Afterendingitsmessagedispatchingloop(normallyoronexceptions),Arcssend
out STOP messages
o EachnodestopsitselfaftersendingouttheReturnmessage
Demo
o Atthelecture/tutorial
COMPSCI 711 4 radu/2020
Protobuf file node.proto – MANDATORY!
syntax = “proto3”;
option csharp_namespace = “Echo”; package echosize;
// The service definition. service Node {
rpc Process (MsgArray) returns (MsgArray); }
// The request/response message. message MsgArray {
message Msg { int32 time = 1; int32 code = 2; int32 from = 3; int32 to = 4; int32 tok = 5; int32 pay = 6;
}
repeated Msg Msgs = 1; }
COMPSCI 711 5 radu/2020
Project layout
Arcs folder
Bin folder
Node folder – for Node project Bin folder
Obj folder
Protos folder – with mandatory node.proto files
Obj folder
Protos folder – with mandatory node.proto files
Sample startup .bat script generated by Arcs, on Windows
Assuming test case #1, with four nodes, 1, 2, 3, 4:
start “node_1” cmd /k .\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.exe 1 2 3 4
timeout 1
start “node_2” cmd /k
.\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.exe 2 1 3 timeout 1
start “node_4” cmd /k .\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.exe 4 3 1
timeout 1
start “node_3” cmd /k
.\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.exe 3 1 2 4 timeout 1
Sorry for the four wrapped lines.
COMPSCI 711 6 radu/2020
Testing .bat script for Windows
@set PROMPT=$G
dotnet build a2-model-arcs-grpc.csproj @pause
@set EchoNodePath=dotnet run -p .\Node\a2-model-node-grpc.csproj — @set EchoNodePath=
.\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.exe @set EchoNodePath=
dotnet .\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.dll
@echo EchoNodePath=%EchoNodePath%
@for /l %%X in (1, 1, 10) do @(
rem dotnet run -p a2-model-arcs-grpc.csproj — %EchoNodePath%
< a2-inp%%X.txt > a2-outp%%X-test.txt
rem .\bin\Debug\netcoreapp3.1\a2-model-arcs-grpc.exe %EchoNodePath%
< a2-inp%%X.txt > a2-outp%%X-test.txt
dotnet .\bin\Debug\netcoreapp3.1\a2-model-arcs-grpc.dll %EchoNodePath%
< a2-inp%%X.txt > a2-outp%%X-test.txt rem type a2-outp%%X.txt
fc a2-outp%%X.txt a2-outp%%X-test.txt pause
) pause
Sorry for the four wrapped lines.
To minimise delays and reduce the conflicts likelihood, prefer the path that points to
the exe or dotnet dll (not dotnet run-ning the project, which implies a build). .
Please note that Arcs takes one command line argument = the path to run the Node
project (no spaces assumed)
COMPSCI 711 7 radu/2020
Testing .sh script for *nix and *nix enabled Windows – tested on Windows only!
#!/bin/bash
set +v
function pause () {
read -n1 -p “Press any key to continue . . .”
echo }
set -v
dotnet build a2-model-arcs-grpc.csproj
set +v
pause
EchoNodePath=”dotnet run -p .\Node\a2-model-node-grpc.csproj –” EchoNodePath=
“dotnet .\Node\bin\Debug\netcoreapp3.1\a2-model-node-grpc.dll”
echo EchoNodePath=$EchoNodePath #for ((X=1; X<=10; X++))
for X in {1..10}
do
#dotnet run -p a2-model-arcs-grpc.csproj -- $EchoNodePath
< a2-inp$X.txt > a2-outp$X-test.txt
dotnet ./bin/Debug/netcoreapp3.1/a2-model-arcs-grpc.dll $EchoNodePath
< a2-inp$X.txt > a2-outp$X-test.txt #cat a2-outp$X.txt
diff –strip-trailing-cr a2-outp$X.txt a2-outp$X-test.txt echo a2 case $X : $?
pause
done
pause
Sorry for the three wrapped lines.
COMPSCI 711 8 radu/2020
Singletons in ASP.NET
New message tokens:
Arcs stops all nodes by broadcasting STOP messages
In proxy:
public void ConfigureServices (IServiceCollection services) { …
services.AddSingleton
public readonly static int TokAYT = 0; // ayt public readonly static int TokSTOP = 3; // stop
public async Task STOP () { try {
Console.Error.WriteLine ($”… STOP NODE={Self}”);
await Process (new[] {new Message (0, 1, 0, Self, Message.TokSTOP, 0)}); } catch (Exception ex) {
_ = ex;
Console.Error.WriteLine ($”*** STOP NODE={Self} UNREACHABLE”); }
}
After the dispatching loop (assuming that nn.Value is a proxy):
foreach (var nn in nodes) { await nn.Value.STOP ();
}
COMPSCI 711 9 radu/2020
Node stops itself, if completed or required
Call Stop when you want to stop, e.g. just before sending the return, or after receiving a stop message — but w/o awaiting its completion!
public async Task Stop () {
await Task.Delay (100);
_logger.Log (LogLevel.Information, $”… STOP”); Environment.Exit (0);
}
Arcs tests that a node service has really started
In proxy, call AYT 3 times, at 1 sec intervals:
public async Task AYT () { var count = 0;
while (true) {
try {
count += 1;
Console.Error.WriteLine ($”… AYT NODE={Self} ({count})”);
await Process (new[] {new Message (0, 1, 0, Self, Message.TokAYT, 0)}); break;
} catch (Exception ex) { _ = ex;
Console.Error.WriteLine ($”*** AYT NODE={Self} ({count})”);
await Task.Delay (1000); }
if (count == 3) {
throw new Exception ($”AYT {Self}”);
} }
}