925 lines
33 KiB
C#
925 lines
33 KiB
C#
using MainShell.Common;
|
||
using MainShell.ProcessResult;
|
||
using MW.WorkFlow;
|
||
using Stylet;
|
||
using System;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace MainShell.Process
|
||
{
|
||
public enum ChipPreparationAction
|
||
{
|
||
None = 0,
|
||
Load = 1,
|
||
Unload = 2,
|
||
Completed = 3,
|
||
Prepare = 4
|
||
}
|
||
|
||
public enum ChipPreparationStatus
|
||
{
|
||
Idle = 0,
|
||
Preparing = 1,
|
||
Prepared = 2,
|
||
Paused = 3,
|
||
Faulted = 4,
|
||
Loading = 5,
|
||
Loaded = 6,
|
||
Unloading = 7
|
||
}
|
||
|
||
public class ChipPreparationRequest
|
||
{
|
||
public string RequestId { get; set; }
|
||
|
||
public string RecipeName { get; set; }
|
||
|
||
public ChipPreparationAction Action { get; set; } = ChipPreparationAction.Prepare;
|
||
|
||
public string SourceStepId { get; set; }
|
||
}
|
||
|
||
public class ChipPreparationWaitResult
|
||
{
|
||
public bool Success { get; set; }
|
||
|
||
public bool IsTimeout { get; set; }
|
||
|
||
public bool IsCanceled { get; set; }
|
||
|
||
public string ErrorMessage { get; set; }
|
||
|
||
public static ChipPreparationWaitResult CreateSuccess()
|
||
{
|
||
return new ChipPreparationWaitResult
|
||
{
|
||
Success = true
|
||
};
|
||
}
|
||
|
||
public static ChipPreparationWaitResult CreateTimeout(string errorMessage)
|
||
{
|
||
return new ChipPreparationWaitResult
|
||
{
|
||
IsTimeout = true,
|
||
ErrorMessage = errorMessage
|
||
};
|
||
}
|
||
|
||
public static ChipPreparationWaitResult CreateCanceled(string errorMessage)
|
||
{
|
||
return new ChipPreparationWaitResult
|
||
{
|
||
IsCanceled = true,
|
||
ErrorMessage = errorMessage
|
||
};
|
||
}
|
||
|
||
public static ChipPreparationWaitResult CreateFailure(string errorMessage)
|
||
{
|
||
return new ChipPreparationWaitResult
|
||
{
|
||
ErrorMessage = errorMessage
|
||
};
|
||
}
|
||
}
|
||
|
||
public class ChipPreparationStateSnapshot
|
||
{
|
||
public ChipPreparationStatus Status { get; set; }
|
||
|
||
public string ActiveRequestId { get; set; }
|
||
|
||
public string RecipeName { get; set; }
|
||
|
||
public string SourceStepId { get; set; }
|
||
|
||
public string CurrentStage { get; set; }
|
||
|
||
public string ErrorMessage { get; set; }
|
||
|
||
public DateTime LastUpdatedTime { get; set; }
|
||
|
||
public ChipPreparationAction CurrentAction { get; set; }
|
||
|
||
public bool IsChipLoaded { get; set; }
|
||
}
|
||
|
||
public class ChipPreparationState : PropertyChangedBase
|
||
{
|
||
private ChipPreparationStatus _status;
|
||
private string _activeRequestId;
|
||
private string _recipeName;
|
||
private string _sourceStepId;
|
||
private string _currentStage;
|
||
private string _errorMessage;
|
||
private DateTime _lastUpdatedTime;
|
||
private ChipPreparationAction _currentAction;
|
||
private bool _isChipLoaded;
|
||
|
||
public ChipPreparationStatus Status
|
||
{
|
||
get { return _status; }
|
||
set { SetAndNotify(ref _status, value); }
|
||
}
|
||
|
||
public string ActiveRequestId
|
||
{
|
||
get { return _activeRequestId; }
|
||
set { SetAndNotify(ref _activeRequestId, value); }
|
||
}
|
||
|
||
public string RecipeName
|
||
{
|
||
get { return _recipeName; }
|
||
set { SetAndNotify(ref _recipeName, value); }
|
||
}
|
||
|
||
public string SourceStepId
|
||
{
|
||
get { return _sourceStepId; }
|
||
set { SetAndNotify(ref _sourceStepId, value); }
|
||
}
|
||
|
||
public string CurrentStage
|
||
{
|
||
get { return _currentStage; }
|
||
set { SetAndNotify(ref _currentStage, value); }
|
||
}
|
||
|
||
public string ErrorMessage
|
||
{
|
||
get { return _errorMessage; }
|
||
set { SetAndNotify(ref _errorMessage, value); }
|
||
}
|
||
|
||
public DateTime LastUpdatedTime
|
||
{
|
||
get { return _lastUpdatedTime; }
|
||
set { SetAndNotify(ref _lastUpdatedTime, value); }
|
||
}
|
||
|
||
public ChipPreparationAction CurrentAction
|
||
{
|
||
get { return _currentAction; }
|
||
set { SetAndNotify(ref _currentAction, value); }
|
||
}
|
||
|
||
public bool IsChipLoaded
|
||
{
|
||
get { return _isChipLoaded; }
|
||
set { SetAndNotify(ref _isChipLoaded, value); }
|
||
}
|
||
|
||
public bool IsBusy
|
||
{
|
||
get
|
||
{
|
||
return Status == ChipPreparationStatus.Preparing ||
|
||
Status == ChipPreparationStatus.Loading ||
|
||
Status == ChipPreparationStatus.Unloading;
|
||
}
|
||
}
|
||
|
||
public bool IsReady
|
||
{
|
||
get
|
||
{
|
||
return Status == ChipPreparationStatus.Prepared ||
|
||
Status == ChipPreparationStatus.Loaded ||
|
||
(Status == ChipPreparationStatus.Idle && CurrentAction == ChipPreparationAction.Unload);
|
||
}
|
||
}
|
||
|
||
public bool IsFaulted
|
||
{
|
||
get { return Status == ChipPreparationStatus.Faulted; }
|
||
}
|
||
|
||
public void ApplySnapshot(ChipPreparationStateSnapshot snapshot)
|
||
{
|
||
if (snapshot == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
Status = snapshot.Status;
|
||
ActiveRequestId = snapshot.ActiveRequestId;
|
||
RecipeName = snapshot.RecipeName;
|
||
SourceStepId = snapshot.SourceStepId;
|
||
CurrentStage = snapshot.CurrentStage;
|
||
ErrorMessage = snapshot.ErrorMessage;
|
||
LastUpdatedTime = snapshot.LastUpdatedTime;
|
||
CurrentAction = snapshot.CurrentAction;
|
||
IsChipLoaded = snapshot.IsChipLoaded;
|
||
NotifyOfPropertyChange(nameof(IsBusy));
|
||
NotifyOfPropertyChange(nameof(IsReady));
|
||
NotifyOfPropertyChange(nameof(IsFaulted));
|
||
}
|
||
}
|
||
|
||
public class ChipPreparationRequestedEventArgs : EventArgs
|
||
{
|
||
public ChipPreparationRequestedEventArgs(ChipPreparationRequest request)
|
||
{
|
||
Request = request;
|
||
}
|
||
|
||
public ChipPreparationRequest Request { get; private set; }
|
||
}
|
||
|
||
public class ChipPreparationStateChangedEventArgs : EventArgs
|
||
{
|
||
public ChipPreparationStateChangedEventArgs(ChipPreparationStateSnapshot snapshot)
|
||
{
|
||
Snapshot = snapshot;
|
||
}
|
||
|
||
public ChipPreparationStateSnapshot Snapshot { get; private set; }
|
||
}
|
||
|
||
public interface IChipPreparationService
|
||
{
|
||
ChipPreparationState Current { get; }
|
||
|
||
bool TryRequestPrepare(ChipPreparationRequest request, out string rejectReason);
|
||
|
||
Task<ChipPreparationWaitResult> WaitUntilReadyAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
|
||
|
||
Task<ChipPreparationWaitResult> WaitUntilLoadedAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
|
||
|
||
Task<ChipPreparationWaitResult> EnsurePreparedAsync(ChipPreparationRequest request, TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken));
|
||
|
||
bool TryMarkReady(string requestId, out string rejectReason);
|
||
|
||
bool TryMarkFault(string errorMessage, out string rejectReason);
|
||
|
||
bool TryConsumeReady(out string rejectReason);
|
||
|
||
Task CancelAsync(CancellationToken cancellationToken = default(CancellationToken));
|
||
|
||
void Pause();
|
||
|
||
void Resume();
|
||
|
||
bool TryResetFault(out string failureReason);
|
||
}
|
||
|
||
public class ChipPreparationService : IChipPreparationService
|
||
{
|
||
private readonly object _syncRoot = new object();
|
||
private readonly IEventAggregator _eventAggregator;
|
||
private readonly ProcessResultManager _processResultManager;
|
||
private ChipPreparationRequest _activeRequest;
|
||
private ChipPreparationRequest _pendingLoadRequest;
|
||
private ChipPreparationStateSnapshot _snapshot;
|
||
|
||
public ChipPreparationService(IEventAggregator eventAggregator, ProcessResultManager processResultManager)
|
||
{
|
||
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
|
||
_processResultManager = processResultManager ?? throw new ArgumentNullException(nameof(processResultManager));
|
||
_processResultManager.ReloadAll();
|
||
_snapshot = RestoreSnapshot(_processResultManager.PreparationAreaState);
|
||
Current = new ChipPreparationState();
|
||
Current.ApplySnapshot(_snapshot);
|
||
}
|
||
|
||
public ChipPreparationState Current { get; private set; }
|
||
|
||
public bool TryRequestPrepare(ChipPreparationRequest request, out string rejectReason)
|
||
{
|
||
if (request == null)
|
||
{
|
||
throw new ArgumentNullException(nameof(request));
|
||
}
|
||
|
||
if (!TryValidateActionRequest(request, out rejectReason))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(request.RequestId))
|
||
{
|
||
request.RequestId = Guid.NewGuid().ToString("N");
|
||
}
|
||
|
||
ChipPreparationRequest requestToPublish = null;
|
||
ChipPreparationStateSnapshot snapshotToPublish = null;
|
||
|
||
lock (_syncRoot)
|
||
{
|
||
if (_snapshot.Status == ChipPreparationStatus.Faulted)
|
||
{
|
||
rejectReason = string.IsNullOrWhiteSpace(_snapshot.ErrorMessage) ? "оƬ<C6AC><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD>״̬<D7B4><CCAC>" : _snapshot.ErrorMessage;
|
||
return false;
|
||
}
|
||
|
||
if (_snapshot.Status == ChipPreparationStatus.Paused)
|
||
{
|
||
rejectReason = "оƬ<C6AC><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ״̬<D7B4><CCAC>";
|
||
return false;
|
||
}
|
||
|
||
if (request.Action == ChipPreparationAction.Prepare)
|
||
{
|
||
if (_snapshot.Status == ChipPreparationStatus.Preparing ||
|
||
_snapshot.Status == ChipPreparationStatus.Prepared ||
|
||
_snapshot.Status == ChipPreparationStatus.Loading ||
|
||
_snapshot.Status == ChipPreparationStatus.Loaded)
|
||
{
|
||
rejectReason = string.Empty;
|
||
return true;
|
||
}
|
||
|
||
if (_snapshot.Status == ChipPreparationStatus.Unloading)
|
||
{
|
||
rejectReason = "оƬ<C6AC><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD>ܷ<EFBFBD><DCB7><EFBFBD><EFBFBD><D7BC><EFBFBD><EFBFBD>";
|
||
return false;
|
||
}
|
||
|
||
_activeRequest = CloneRequest(request);
|
||
_pendingLoadRequest = null;
|
||
_snapshot = CreateRunningSnapshot(_activeRequest, ChipPreparationStatus.Preparing, _snapshot.IsChipLoaded);
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
requestToPublish = CloneRequest(_activeRequest);
|
||
}
|
||
else if (request.Action == ChipPreparationAction.Load)
|
||
{
|
||
if (_snapshot.Status == ChipPreparationStatus.Loaded)
|
||
{
|
||
rejectReason = string.Empty;
|
||
return true;
|
||
}
|
||
|
||
if (_snapshot.Status == ChipPreparationStatus.Loading)
|
||
{
|
||
rejectReason = string.Empty;
|
||
return true;
|
||
}
|
||
|
||
if (_snapshot.Status == ChipPreparationStatus.Preparing)
|
||
{
|
||
_pendingLoadRequest = CloneRequest(request);
|
||
rejectReason = string.Empty;
|
||
return true;
|
||
}
|
||
|
||
if (_snapshot.Status == ChipPreparationStatus.Unloading)
|
||
{
|
||
rejectReason = "оƬ<C6AC><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD>ܷ<EFBFBD><DCB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>";
|
||
return false;
|
||
}
|
||
|
||
_activeRequest = CloneRequest(request);
|
||
_snapshot = CreateRunningSnapshot(_activeRequest, ChipPreparationStatus.Loading, _snapshot.IsChipLoaded);
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
requestToPublish = CloneRequest(_activeRequest);
|
||
}
|
||
else
|
||
{
|
||
if (_snapshot.Status == ChipPreparationStatus.Unloading)
|
||
{
|
||
rejectReason = string.Empty;
|
||
return true;
|
||
}
|
||
|
||
if (!_snapshot.IsChipLoaded && _snapshot.Status != ChipPreparationStatus.Loaded && _snapshot.Status != ChipPreparationStatus.Prepared)
|
||
{
|
||
rejectReason = "<22><>ǰû<C7B0>п<EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>оƬ<D0BE><C6AC>";
|
||
return false;
|
||
}
|
||
|
||
if (_snapshot.Status == ChipPreparationStatus.Preparing || _snapshot.Status == ChipPreparationStatus.Loading)
|
||
{
|
||
rejectReason = "оƬ<C6AC><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD>ܷ<EFBFBD><DCB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>";
|
||
return false;
|
||
}
|
||
|
||
_activeRequest = CloneRequest(request);
|
||
_pendingLoadRequest = null;
|
||
_snapshot = CreateRunningSnapshot(_activeRequest, ChipPreparationStatus.Unloading, true);
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
requestToPublish = CloneRequest(_activeRequest);
|
||
}
|
||
|
||
rejectReason = string.Empty;
|
||
}
|
||
|
||
PublishState(snapshotToPublish);
|
||
if (requestToPublish != null)
|
||
{
|
||
_eventAggregator.Publish(new ChipPreparationRequestedEventArgs(requestToPublish));
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public async Task<ChipPreparationWaitResult> WaitUntilReadyAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
|
||
{
|
||
return await WaitForStateAsync(false, timeout, cancellationToken).ConfigureAwait(false);
|
||
}
|
||
|
||
public async Task<ChipPreparationWaitResult> WaitUntilLoadedAsync(TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
|
||
{
|
||
return await WaitForStateAsync(true, timeout, cancellationToken).ConfigureAwait(false);
|
||
}
|
||
|
||
public async Task<ChipPreparationWaitResult> EnsurePreparedAsync(ChipPreparationRequest request, TimeSpan timeout, CancellationToken cancellationToken = default(CancellationToken))
|
||
{
|
||
string rejectReason;
|
||
if (!TryRequestPrepare(request, out rejectReason))
|
||
{
|
||
return ChipPreparationWaitResult.CreateFailure(rejectReason);
|
||
}
|
||
|
||
return await WaitUntilReadyAsync(timeout, cancellationToken).ConfigureAwait(false);
|
||
}
|
||
|
||
public bool TryMarkReady(string requestId, out string rejectReason)
|
||
{
|
||
ChipPreparationStateSnapshot snapshotToPublish = null;
|
||
ChipPreparationRequest requestToPublish = null;
|
||
|
||
lock (_syncRoot)
|
||
{
|
||
if (_activeRequest == null)
|
||
{
|
||
rejectReason = "<22><>ǰû<C7B0><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>е<EFBFBD>оƬ<C6AC><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||
return false;
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(requestId) &&
|
||
!string.Equals(_activeRequest.RequestId, requestId, StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
rejectReason = "оƬ<C6AC><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><CAB6>ƥ<EFBFBD>䡣";
|
||
return false;
|
||
}
|
||
|
||
if (_activeRequest.Action == ChipPreparationAction.Prepare)
|
||
{
|
||
if (_pendingLoadRequest != null)
|
||
{
|
||
_activeRequest = CloneRequest(_pendingLoadRequest);
|
||
_pendingLoadRequest = null;
|
||
_snapshot = CreateRunningSnapshot(_activeRequest, ChipPreparationStatus.Loading, true);
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
requestToPublish = CloneRequest(_activeRequest);
|
||
}
|
||
else
|
||
{
|
||
_snapshot = CreateStableSnapshot(ChipPreparationStatus.Prepared, _activeRequest, true, "Prepared");
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
_activeRequest = null;
|
||
}
|
||
}
|
||
else if (_activeRequest.Action == ChipPreparationAction.Load)
|
||
{
|
||
_snapshot = CreateStableSnapshot(ChipPreparationStatus.Loaded, _activeRequest, true, "LoadedPendingTransfer");
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
_activeRequest = null;
|
||
}
|
||
else if (_activeRequest.Action == ChipPreparationAction.Unload)
|
||
{
|
||
_snapshot = CreateIdleSnapshot(false);
|
||
_snapshot.CurrentAction = ChipPreparationAction.Unload;
|
||
_snapshot.CurrentStage = "UnloadCompleted";
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
_activeRequest = null;
|
||
}
|
||
else
|
||
{
|
||
rejectReason = "оƬ<C6AC><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7>";
|
||
return false;
|
||
}
|
||
|
||
rejectReason = string.Empty;
|
||
}
|
||
|
||
PublishState(snapshotToPublish);
|
||
if (requestToPublish != null)
|
||
{
|
||
_eventAggregator.Publish(new ChipPreparationRequestedEventArgs(requestToPublish));
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public bool TryMarkFault(string errorMessage, out string rejectReason)
|
||
{
|
||
ChipPreparationStateSnapshot snapshotToPublish;
|
||
|
||
lock (_syncRoot)
|
||
{
|
||
if (_snapshot.Status == ChipPreparationStatus.Idle)
|
||
{
|
||
rejectReason = "<22><>ǰû<C7B0><C3BB>ִ<EFBFBD><D6B4><EFBFBD>е<EFBFBD>оƬ<D0BE><C6AC><EFBFBD>̡<EFBFBD>";
|
||
return false;
|
||
}
|
||
|
||
_snapshot = CreateFaultedSnapshot(_activeRequest, errorMessage, _snapshot.IsChipLoaded);
|
||
_activeRequest = null;
|
||
_pendingLoadRequest = null;
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
rejectReason = string.Empty;
|
||
}
|
||
|
||
PublishState(snapshotToPublish);
|
||
return true;
|
||
}
|
||
|
||
public bool TryConsumeReady(out string rejectReason)
|
||
{
|
||
ChipPreparationStateSnapshot snapshotToPublish;
|
||
|
||
lock (_syncRoot)
|
||
{
|
||
if (_snapshot.Status == ChipPreparationStatus.Loaded || _snapshot.Status == ChipPreparationStatus.Prepared)
|
||
{
|
||
ResetToIdle(false);
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
rejectReason = string.Empty;
|
||
}
|
||
else if (_snapshot.Status == ChipPreparationStatus.Idle && _snapshot.CurrentAction == ChipPreparationAction.Unload)
|
||
{
|
||
_snapshot = CreateIdleSnapshot(false);
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
rejectReason = string.Empty;
|
||
}
|
||
else
|
||
{
|
||
rejectReason = "<22><>ǰû<C7B0>п<EFBFBD><D0BF><EFBFBD><EFBFBD>ѵ<EFBFBD><EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
|
||
return false;
|
||
}
|
||
}
|
||
|
||
PublishState(snapshotToPublish);
|
||
return true;
|
||
}
|
||
|
||
public Task CancelAsync(CancellationToken cancellationToken = default(CancellationToken))
|
||
{
|
||
cancellationToken.ThrowIfCancellationRequested();
|
||
|
||
ChipPreparationStateSnapshot snapshotToPublish = null;
|
||
lock (_syncRoot)
|
||
{
|
||
if (!IsTransientStatus(_snapshot.Status))
|
||
{
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
bool keepLoadedChip = _snapshot.IsChipLoaded && _snapshot.Status != ChipPreparationStatus.Unloading;
|
||
_activeRequest = null;
|
||
_pendingLoadRequest = null;
|
||
_snapshot = CreateIdleSnapshot(keepLoadedChip);
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
}
|
||
|
||
PublishState(snapshotToPublish);
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
public void Pause()
|
||
{
|
||
ChipPreparationStateSnapshot snapshotToPublish = null;
|
||
lock (_syncRoot)
|
||
{
|
||
if (!IsTransientStatus(_snapshot.Status))
|
||
{
|
||
return;
|
||
}
|
||
|
||
_snapshot = CloneSnapshot(_snapshot);
|
||
_snapshot.Status = ChipPreparationStatus.Paused;
|
||
_snapshot.CurrentStage = "Paused";
|
||
_snapshot.LastUpdatedTime = DateTime.Now;
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
}
|
||
|
||
PublishState(snapshotToPublish);
|
||
}
|
||
|
||
public void Resume()
|
||
{
|
||
ChipPreparationStateSnapshot snapshotToPublish = null;
|
||
lock (_syncRoot)
|
||
{
|
||
if (_snapshot.Status != ChipPreparationStatus.Paused || _activeRequest == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
ChipPreparationStatus resumedStatus = ResolveRunningStatus(_activeRequest.Action);
|
||
_snapshot = CloneSnapshot(_snapshot);
|
||
_snapshot.Status = resumedStatus;
|
||
_snapshot.CurrentStage = ResolveStageForStatus(resumedStatus);
|
||
_snapshot.LastUpdatedTime = DateTime.Now;
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
}
|
||
|
||
PublishState(snapshotToPublish);
|
||
}
|
||
|
||
public bool TryResetFault(out string failureReason)
|
||
{
|
||
ChipPreparationStateSnapshot snapshotToPublish;
|
||
|
||
lock (_syncRoot)
|
||
{
|
||
if (_snapshot.Status != ChipPreparationStatus.Faulted)
|
||
{
|
||
failureReason = "<22><>ǰоƬ<C6AC><D7BC><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD>״̬<D7B4><CCAC>";
|
||
return false;
|
||
}
|
||
|
||
ResetToIdle(_snapshot.IsChipLoaded);
|
||
snapshotToPublish = CloneSnapshot(_snapshot);
|
||
failureReason = string.Empty;
|
||
}
|
||
|
||
PublishState(snapshotToPublish);
|
||
return true;
|
||
}
|
||
|
||
private async Task<ChipPreparationWaitResult> WaitForStateAsync(bool requireLoaded, TimeSpan timeout, CancellationToken cancellationToken)
|
||
{
|
||
if (timeout <= TimeSpan.Zero)
|
||
{
|
||
timeout = TimeSpan.FromMilliseconds(100);
|
||
}
|
||
|
||
DateTime deadline = DateTime.Now.Add(timeout);
|
||
try
|
||
{
|
||
while (true)
|
||
{
|
||
cancellationToken.ThrowIfCancellationRequested();
|
||
|
||
ChipPreparationWaitResult immediateResult = EvaluateWaitResult(requireLoaded);
|
||
if (immediateResult != null)
|
||
{
|
||
return immediateResult;
|
||
}
|
||
|
||
if (DateTime.Now >= deadline)
|
||
{
|
||
return ChipPreparationWaitResult.CreateTimeout(requireLoaded
|
||
? "<22>ȴ<EFBFBD>оƬ<D0BE><C6AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɳ<EFBFBD>ʱ<EFBFBD><CAB1>"
|
||
: "<22>ȴ<EFBFBD>оƬ<C6AC><D7BC><EFBFBD><EFBFBD><EFBFBD>ɳ<EFBFBD>ʱ<EFBFBD><CAB1>");
|
||
}
|
||
|
||
await Task.Delay(50, cancellationToken).ConfigureAwait(false);
|
||
}
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
return ChipPreparationWaitResult.CreateCanceled(requireLoaded
|
||
? "<22>ȴ<EFBFBD>оƬ<D0BE><C6AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>"
|
||
: "<22>ȴ<EFBFBD>оƬ<C6AC><D7BC><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>");
|
||
}
|
||
}
|
||
|
||
private ChipPreparationWaitResult EvaluateWaitResult(bool requireLoaded)
|
||
{
|
||
lock (_syncRoot)
|
||
{
|
||
if (_snapshot.Status == ChipPreparationStatus.Faulted)
|
||
{
|
||
return ChipPreparationWaitResult.CreateFailure(string.IsNullOrWhiteSpace(_snapshot.ErrorMessage)
|
||
? "оƬ<C6AC><D7BC><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>ʧ<EFBFBD>ܡ<EFBFBD>"
|
||
: _snapshot.ErrorMessage);
|
||
}
|
||
|
||
if (requireLoaded)
|
||
{
|
||
if (_snapshot.Status == ChipPreparationStatus.Loaded)
|
||
{
|
||
return ChipPreparationWaitResult.CreateSuccess();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (_snapshot.Status == ChipPreparationStatus.Prepared ||
|
||
_snapshot.Status == ChipPreparationStatus.Loaded ||
|
||
(_snapshot.Status == ChipPreparationStatus.Idle && _snapshot.CurrentAction == ChipPreparationAction.Unload))
|
||
{
|
||
return ChipPreparationWaitResult.CreateSuccess();
|
||
}
|
||
}
|
||
|
||
if (_snapshot.Status == ChipPreparationStatus.Idle && _activeRequest == null)
|
||
{
|
||
return ChipPreparationWaitResult.CreateFailure("<22><>δ<EFBFBD><CEB4>ʼоƬ<C6AC><D7BC><EFBFBD><EFBFBD><EFBFBD>̡<EFBFBD>") ;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
|
||
private void ResetToIdle(bool keepLoadedChip)
|
||
{
|
||
_activeRequest = null;
|
||
_pendingLoadRequest = null;
|
||
_snapshot = CreateIdleSnapshot(keepLoadedChip);
|
||
}
|
||
|
||
private void PublishState(ChipPreparationStateSnapshot snapshot)
|
||
{
|
||
if (snapshot == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
Current.ApplySnapshot(snapshot);
|
||
_processResultManager.SavePreparationAreaState(snapshot);
|
||
_eventAggregator.Publish(new ChipPreparationStateChangedEventArgs(CloneSnapshot(snapshot)));
|
||
}
|
||
|
||
private static bool IsTransientStatus(ChipPreparationStatus status)
|
||
{
|
||
return status == ChipPreparationStatus.Preparing ||
|
||
status == ChipPreparationStatus.Loading ||
|
||
status == ChipPreparationStatus.Unloading ||
|
||
status == ChipPreparationStatus.Paused;
|
||
}
|
||
|
||
private static bool TryValidateActionRequest(ChipPreparationRequest request, out string rejectReason)
|
||
{
|
||
if (request == null)
|
||
{
|
||
rejectReason = "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ա<EFBFBD>";
|
||
return false;
|
||
}
|
||
|
||
if (request.Action != ChipPreparationAction.Prepare &&
|
||
request.Action != ChipPreparationAction.Load &&
|
||
request.Action != ChipPreparationAction.Unload)
|
||
{
|
||
rejectReason = "оƬ<C6AC><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7>";
|
||
return false;
|
||
}
|
||
|
||
rejectReason = string.Empty;
|
||
return true;
|
||
}
|
||
|
||
private static ChipPreparationStatus ResolveRunningStatus(ChipPreparationAction action)
|
||
{
|
||
if (action == ChipPreparationAction.Prepare)
|
||
{
|
||
return ChipPreparationStatus.Preparing;
|
||
}
|
||
|
||
if (action == ChipPreparationAction.Load)
|
||
{
|
||
return ChipPreparationStatus.Loading;
|
||
}
|
||
|
||
return ChipPreparationStatus.Unloading;
|
||
}
|
||
|
||
private static string ResolveStageForStatus(ChipPreparationStatus status)
|
||
{
|
||
switch (status)
|
||
{
|
||
case ChipPreparationStatus.Preparing:
|
||
return "Preparing";
|
||
case ChipPreparationStatus.Prepared:
|
||
return "Prepared";
|
||
case ChipPreparationStatus.Loading:
|
||
return "Loading";
|
||
case ChipPreparationStatus.Loaded:
|
||
return "LoadedPendingTransfer";
|
||
case ChipPreparationStatus.Unloading:
|
||
return "Unloading";
|
||
case ChipPreparationStatus.Paused:
|
||
return "Paused";
|
||
case ChipPreparationStatus.Faulted:
|
||
return "Faulted";
|
||
default:
|
||
return "Idle";
|
||
}
|
||
}
|
||
|
||
private static ChipPreparationStateSnapshot CreateIdleSnapshot(bool isChipLoaded)
|
||
{
|
||
return new ChipPreparationStateSnapshot
|
||
{
|
||
Status = ChipPreparationStatus.Idle,
|
||
CurrentStage = isChipLoaded ? "LoadedPendingTransfer" : "Idle",
|
||
LastUpdatedTime = DateTime.Now,
|
||
CurrentAction = ChipPreparationAction.None,
|
||
IsChipLoaded = isChipLoaded
|
||
};
|
||
}
|
||
|
||
private static ChipPreparationStateSnapshot CreateRunningSnapshot(ChipPreparationRequest request, ChipPreparationStatus status, bool isChipLoaded)
|
||
{
|
||
return new ChipPreparationStateSnapshot
|
||
{
|
||
Status = status,
|
||
ActiveRequestId = request != null ? request.RequestId : null,
|
||
RecipeName = request != null ? request.RecipeName : null,
|
||
SourceStepId = request != null ? request.SourceStepId : null,
|
||
CurrentStage = ResolveStageForStatus(status),
|
||
LastUpdatedTime = DateTime.Now,
|
||
CurrentAction = request != null ? request.Action : ChipPreparationAction.None,
|
||
IsChipLoaded = isChipLoaded
|
||
};
|
||
}
|
||
|
||
private static ChipPreparationStateSnapshot CreateStableSnapshot(ChipPreparationStatus status, ChipPreparationRequest request, bool isChipLoaded, string stage)
|
||
{
|
||
return new ChipPreparationStateSnapshot
|
||
{
|
||
Status = status,
|
||
ActiveRequestId = request != null ? request.RequestId : null,
|
||
RecipeName = request != null ? request.RecipeName : null,
|
||
SourceStepId = request != null ? request.SourceStepId : null,
|
||
CurrentStage = stage,
|
||
LastUpdatedTime = DateTime.Now,
|
||
CurrentAction = request != null ? request.Action : ChipPreparationAction.None,
|
||
IsChipLoaded = isChipLoaded
|
||
};
|
||
}
|
||
|
||
private static ChipPreparationStateSnapshot CreateFaultedSnapshot(ChipPreparationRequest request, string errorMessage, bool isChipLoaded)
|
||
{
|
||
return new ChipPreparationStateSnapshot
|
||
{
|
||
Status = ChipPreparationStatus.Faulted,
|
||
ActiveRequestId = request != null ? request.RequestId : null,
|
||
RecipeName = request != null ? request.RecipeName : null,
|
||
SourceStepId = request != null ? request.SourceStepId : null,
|
||
CurrentStage = "Faulted",
|
||
ErrorMessage = string.IsNullOrWhiteSpace(errorMessage) ? "оƬ<C6AC><D7BC><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>ʧ<EFBFBD>ܡ<EFBFBD>" : errorMessage,
|
||
LastUpdatedTime = DateTime.Now,
|
||
CurrentAction = request != null ? request.Action : ChipPreparationAction.None,
|
||
IsChipLoaded = isChipLoaded
|
||
};
|
||
}
|
||
|
||
private static ChipPreparationRequest CloneRequest(ChipPreparationRequest request)
|
||
{
|
||
if (request == null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
return new ChipPreparationRequest
|
||
{
|
||
RequestId = request.RequestId,
|
||
RecipeName = request.RecipeName,
|
||
Action = request.Action,
|
||
SourceStepId = request.SourceStepId
|
||
};
|
||
}
|
||
|
||
private static ChipPreparationStateSnapshot CloneSnapshot(ChipPreparationStateSnapshot snapshot)
|
||
{
|
||
if (snapshot == null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
return new ChipPreparationStateSnapshot
|
||
{
|
||
Status = snapshot.Status,
|
||
ActiveRequestId = snapshot.ActiveRequestId,
|
||
RecipeName = snapshot.RecipeName,
|
||
SourceStepId = snapshot.SourceStepId,
|
||
CurrentStage = snapshot.CurrentStage,
|
||
ErrorMessage = snapshot.ErrorMessage,
|
||
LastUpdatedTime = snapshot.LastUpdatedTime,
|
||
CurrentAction = snapshot.CurrentAction,
|
||
IsChipLoaded = snapshot.IsChipLoaded
|
||
};
|
||
}
|
||
|
||
private static ChipPreparationStateSnapshot RestoreSnapshot(PreparationAreaProcessState persistedState)
|
||
{
|
||
if (persistedState == null)
|
||
{
|
||
return CreateIdleSnapshot(false);
|
||
}
|
||
|
||
return new ChipPreparationStateSnapshot
|
||
{
|
||
Status = persistedState.Status,
|
||
ActiveRequestId = persistedState.ActiveRequestId,
|
||
RecipeName = persistedState.RecipeName,
|
||
SourceStepId = persistedState.SourceStepId,
|
||
CurrentStage = string.IsNullOrWhiteSpace(persistedState.CurrentStage)
|
||
? ResolveStageForStatus(persistedState.Status)
|
||
: persistedState.CurrentStage,
|
||
ErrorMessage = persistedState.ErrorMessage,
|
||
LastUpdatedTime = persistedState.LastUpdatedTime == default(DateTime)
|
||
? DateTime.Now
|
||
: persistedState.LastUpdatedTime,
|
||
CurrentAction = persistedState.CurrentAction,
|
||
IsChipLoaded = persistedState.HasPreparedChip
|
||
};
|
||
}
|
||
}
|
||
} |