protected void DisposeSubmachines(bool emergencyQuit = false) { TransportOperationMachine beginPickup = null; TransportOperationMachine endPickup = null; TransportOperationMachine beginDropoff = null; TransportOperationMachine endDropoff = null; // Get local references so that the lock isn't held while operating on each machine. lock (_subMachineLock) { beginPickup = BeginPickupMachine; BeginPickupMachine = null; endPickup = CompletePickupMachine; CompletePickupMachine = null; beginDropoff = BeginDropoffMachine; BeginDropoffMachine = null; endDropoff = CompleteDropoffMachine; CompleteDropoffMachine = null; } DisposeSubmachine(beginPickup, emergencyQuit); DisposeSubmachine(endPickup, emergencyQuit); DisposeSubmachine(beginDropoff, emergencyQuit); DisposeSubmachine(endDropoff, emergencyQuit); }
private void Retry(TransportOperationMachine startingPoint) { LogService.Log(LogType.System, LogMessageType.Debug, GetType().Name, string.Format(CultureInfo.InvariantCulture, "Retrying Tray move at '{0}'.", startingPoint.Station.Name)); NumberOfRetries--; // Dispose of the old machines. DisposeSubmachines(); // Create new first machine to execute. InitializeSubmachine(startingPoint.Operation); // Restart execution of whichever machine died, but don't raise the Started event. switch (startingPoint.Operation) { case TransportOperation.BeginPickup: BeginPickupMachine.Execute(); break; case TransportOperation.CompletePickup: CompletePickupMachine.Execute(); break; case TransportOperation.BeginDropoff: BeginDropoffMachine.Execute(); break; case TransportOperation.CompleteDropoff: CompleteDropoffMachine.Execute(); break; } }
private TransportOperationMachine CreateSubmachine(string name, IActivityMachineBuilder builder, DynamicConfiguration config) { var submachine = new TransportOperationMachine(name, _dispatcher); submachine.Builder = builder; submachine.Configuration = config; submachine.Finished += HandleSubMachineFinished; submachine.Interrupted += HandleSubMachineInterrupted; submachine.Expired += HandleSubMachineExpired; submachine.Faulted += HandleSubMachineFaulted; return(submachine); }
private void DisposeSubmachine(TransportOperationMachine submachine, bool emergencyQuit) { if (submachine != null) { submachine.Finished -= HandleSubMachineFinished; submachine.Interrupted -= HandleSubMachineInterrupted; submachine.Expired -= HandleSubMachineExpired; submachine.Faulted -= HandleSubMachineFaulted; if (emergencyQuit) { submachine.EmergencyQuit(); } else { submachine.Quit(); } } }
private TransportOperationMachine GetNextOperation(TransportOperationMachine lastMachine, out TransportOperation nextOperation) { switch (lastMachine.Operation) { case TransportOperation.BeginPickup: // Keep operating if mover was stopped for a tray abort because the tray has to be // picked up anyway. if (IsStopped && !lastMachine.Tray.IsAborted) { break; } InitializeSubmachine(TransportOperation.CompletePickup); nextOperation = TransportOperation.CompletePickup; return(CompletePickupMachine); case TransportOperation.CompletePickup: // Skip the drop-off if this mover was stopped. if (IsStopped) { break; } InitializeSubmachine(TransportOperation.BeginDropoff); nextOperation = TransportOperation.BeginDropoff; return(BeginDropoffMachine); case TransportOperation.BeginDropoff: // Keep operating if mover was stopped for a tray abort because we don't know // how much of the drop-off has run. CompleteDropoff can recover safely. if (IsStopped && !lastMachine.Tray.IsAborted) { break; } InitializeSubmachine(TransportOperation.CompleteDropoff); nextOperation = TransportOperation.CompleteDropoff; return(CompleteDropoffMachine); } nextOperation = TransportOperation.BeginPickup; return(null); }
private void HandleSubMachineFinished(object sender, TimeStampedEventArgs e) { var doneMachine = sender as TransportOperationMachine; TransportOperation nextOperation; TransportOperationMachine nextMachine = null; // lock here because the submachine references will be accessed. lock (_subMachineLock) { nextMachine = GetNextOperation(doneMachine, out nextOperation); if (doneMachine.Operation == TransportOperation.CompleteDropoff) { TeardownForFinished(); } else { if (nextMachine != null && Transport.State.IsNoneOf(StationState.Stopped, StationState.Disabled) && !(Transport as IStation).HasErred) { CurrentOperation = nextOperation; OnOperationBeginning(nextOperation); // Last step, execute the next machine. nextMachine.Execute(); } else { TeardownForInterruption(); } } } if (nextMachine == null && !_isComplete) { Quit(); LogService.Log(LogType.System, LogMessageType.Error, GetType().Name, string.Format(CultureInfo.InvariantCulture, "Machine '{0}' failed due to missing {1} sub-machine.", Name, nextOperation.ToString())); } }
/// <summary> /// Initialize one of the four transport operation machine types. Both Pick-up machines have /// CanStop turned off because there are no circumstances where a Pick-up operation can be /// stopped, even though the TrayMover as a whole can be stopped during pick-up. Both /// Drop-off machines have CanStop turned on initially so that either drop-off operation can /// be stopped. If this TrayMover has already been stopped, then this will also /// stop a newly constructed CompleteDropoff machine before returning it. /// </summary> /// <param name="startingType"></param> /// <returns>TransportOperationMachine</returns> protected TransportOperationMachine InitializeSubmachine(TransportOperation startingType) { TransportOperationMachine initialized = null; lock (_subMachineLock) { switch (startingType) { case TransportOperation.BeginPickup: BeginPickupMachine = CreateSubmachine("BeginTrayPickup", BeginPickupBuilder, _beginPickupConfig); initialized = BeginPickupMachine; break; case TransportOperation.CompletePickup: CompletePickupMachine = CreateSubmachine("CompleteTrayPickup", CompletePickupBuilder, _completePickupConfig); initialized = CompletePickupMachine; break; case TransportOperation.BeginDropoff: BeginDropoffMachine = CreateSubmachine("BeginTrayDropoff", BeginDropoffBuilder, _beginDropoffConfig); BeginDropoffMachine.CanStop = true; initialized = BeginDropoffMachine; break; case TransportOperation.CompleteDropoff: CompleteDropoffMachine = CreateSubmachine("CompleteTrayDropoff", CompleteDropoffBuilder, _completeDropoffConfig); CompleteDropoffMachine.CanStop = true; // CompleteDropoff needs to know if the mover was already stopped if (IsStopped) { CompleteDropoffMachine.Stop(); } initialized = CompleteDropoffMachine; break; } } return(initialized); }
private void RaiseTransportationException(TransportOperationMachine machineInProgress, string description, Exception innerException = null) { // If transportation already in error state, just escape. if ((Transport as IStation).HasErred) { return; } AtlasException ex; if (!(machineInProgress.Station as IStation).HasErred && machineInProgress.IsExpired) { ex = new TrayMoveExpirationException(null, Transport, machineInProgress.Station.Name, machineInProgress.Operation.ToString()); } else if (machineInProgress.HaltOnError) { // This will give transportation an error and a Busy ResourceAvailability. ex = new TrayMoveComponentException(null, innerException, Transport, machineInProgress.Station.Name, machineInProgress.Operation.ToString()); } else { ex = new TrayMoveInternalException(null, innerException, Transport, machineInProgress.Station.Name, machineInProgress.Operation.ToString(), description); } ex.Handle(); }