Skip to content

Commit

Permalink
Finished PlcHostedService.
Browse files Browse the repository at this point in the history
  • Loading branch information
hcoona committed Dec 10, 2019
1 parent 9752f86 commit 0daf2f9
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public partial class PlcClient : IDisposable
new ConcurrentDictionary<int, PlcRequestContext>();

private int sequenceNumberGenerator = 0;
private bool closed = false;
private bool disposedValue = false;

public PlcClient(ILogger<PlcClient> logger, TcpClient tcpClient)
Expand Down Expand Up @@ -82,14 +81,18 @@ public void Dispose()
GC.SuppressFinalize(this);
}

public void Close()
public async void Close()
{
if (!this.closingCancellationTokenSource.IsCancellationRequested)
{
this.closingCancellationTokenSource.Cancel();
this.requestContextSendingBufferBlock.Complete();
this.tcpClient.Close();
this.OnClosed?.Invoke(this, EventArgs.Empty);

await this.sendingBackgroundTask.ConfigureAwait(false);
await this.receivingBackgroundTask.ConfigureAwait(false);
await this.deadlineBackgroundTask.ConfigureAwait(false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public async Task<Switch> UpdateSwitchAsync(UpdateSwitchRequest request, DateTim

private Task<PlcFrame> InvokeAsync(PlcFrame request, DateTime? deadline)
{
if (this.closed)
if (this.closingCancellationTokenSource.IsCancellationRequested)
{
return Task.FromException<PlcFrame>(new RpcException(Status.DefaultCancelled));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ private async void SendingBackgroundTaskEntryPoint()
.OutputAvailableAsync()
.ConfigureAwait(false))
{
DateTime now = DateTime.Now;
DateTime utcNow = DateTime.UtcNow;
while (this.requestContextSendingBufferBlock.TryReceive(out PlcRequestContext requestContext))
{
this.ProcessRequest(now, requestContext);
this.ProcessRequest(utcNow, requestContext);
}
}
}
Expand All @@ -36,9 +36,9 @@ private async void SendingBackgroundTaskEntryPoint()
}
}

private void ProcessRequest(DateTime now, PlcRequestContext requestContext)
private void ProcessRequest(DateTime utcNow, PlcRequestContext requestContext)
{
if (requestContext.Deadline < now)
if (requestContext.Deadline?.ToUniversalTime() < utcNow)
{
requestContext.TaskCompletionSource.SetException(new RpcException(
new Status(StatusCode.DeadlineExceeded, string.Empty)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ public void Stop()

public async Task<PlcClient> AcceptAsync()
{
TcpClient tcpClient = await this.tcpListener.AcceptTcpClientAsync().ConfigureAwait(false);
TcpClient tcpClient = await this.tcpListener
.AcceptTcpClientAsync()
.ConfigureAwait(false);
return new PlcClient(this.loggerFactory.CreateLogger<PlcClient>(), tcpClient);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,24 @@
// Licensed under the GPLv3 license. See LICENSE file in the project root for full license information.
// </copyright>

using System;
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
using GeothermalResearchInstitute.PlcV2;
using GeothermalResearchInstitute.v2;
using Google.Protobuf;
using Grpc.Core;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace GeothermalResearchInstitute.ServerConsole
{
[SuppressMessage(
"Design",
"CA1001:具有可释放字段的类型应该是可释放的",
Justification = "Disposed in StopAsync, ensured by framework.")]
public class PlcHostedService : IHostedService
{
private readonly ILogger<PlcHostedService> logger;
Expand All @@ -21,6 +29,9 @@ public class PlcHostedService : IHostedService
private readonly ConcurrentDictionary<ByteString, PlcClient> plcDictionary =
new ConcurrentDictionary<ByteString, PlcClient>();

private CancellationTokenSource cancellationTokenSource;
private Task backgroundTask;

public PlcHostedService(ILogger<PlcHostedService> logger, PlcServer plcServer)
{
this.logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
Expand All @@ -37,14 +48,86 @@ public Task StartAsync(CancellationToken cancellationToken)
this.plcServer.Start();
this.logger.LogInformation("PLC server is listening on {0}", this.plcServer.LocalEndPoint);

// TODO: Run background task
this.plcDictionary.Clear();
this.cancellationTokenSource = new CancellationTokenSource();
this.backgroundTask = Task.Factory.StartNew(
this.BackgroundTaskEntryPoint,
this.cancellationTokenSource.Token,
TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach,
TaskScheduler.Default);

return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
public async Task StopAsync(CancellationToken cancellationToken)
{
this.cancellationTokenSource.Cancel();
await this.backgroundTask.ConfigureAwait(false);

foreach (ByteString id in this.plcDictionary.Keys)
{
if (this.plcDictionary.TryRemove(id, out PlcClient client))
{
client.Close();
client.Dispose();
}
}

this.plcServer.Stop();
return Task.CompletedTask;

this.cancellationTokenSource.Dispose();
this.cancellationTokenSource = null;
this.backgroundTask.Dispose();
this.backgroundTask = null;
}

private async void BackgroundTaskEntryPoint()
{
while (!this.cancellationTokenSource.IsCancellationRequested)
{
PlcClient client = await this.plcServer.AcceptAsync().ConfigureAwait(false);

ConnectResponse response;
try
{
response = await client
.ConnectAsync(new ConnectRequest(), DateTime.UtcNow.AddSeconds(10))
.ConfigureAwait(false);
}
catch (RpcException e)
{
this.logger.LogWarning(
e,
"Failed to send ConnectRequest to newly PLC {0}",
client.RemoteEndPoint);
continue;
}

if (this.plcDictionary.TryAdd(response.Id, client))
{
this.logger.LogInformation(
"Client(MAC={0}, EndPoint={1}) connected.",
BitConverter.ToString(response.Id.ToByteArray()),
client.RemoteEndPoint);
client.OnClosed += (sender, args) =>
{
this.logger.LogInformation(
"Client(MAC={0}, EndPoint={1}) disconnected.",
BitConverter.ToString(response.Id.ToByteArray()),
client.RemoteEndPoint);
this.plcDictionary.TryRemove(response.Id, out PlcClient _);
};
}
else
{
this.logger.LogWarning(
"Failed to add the client(MAC={0}, EndPoint={1}) into dictionary.",
BitConverter.ToString(response.Id.ToByteArray()),
client.RemoteEndPoint);
client.Close();
client.Dispose();
}
}
}
}
}
1 change: 0 additions & 1 deletion codelab/ProtocolLab/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// </copyright>

using System;
using System.Buffers.Binary;
using System.Globalization;
using System.IO;
using System.Linq;
Expand Down

0 comments on commit 0daf2f9

Please sign in to comment.