using DTS.Common.Events; using DTS.Common.SharedResource.Strings; using DTS.Common.Utilities.Logging; using Prism.Events; using Prism.Events; using Prism.Ioc; using System; using System.Collections.Generic; using System.Drawing.Text; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows.Interop; namespace DTS.Common.Classes.Locking { public class SensorsLocking { private LockRecord[] _existingLocks = null; private static readonly object MyLock = new object(); private CancellationTokenSource _cancellationTokenSource = null; private readonly Task _updateTask = null; private const int MAX_WAIT_TIME_MS = 10000; /// /// returns false if stop was not needed or failed /// returns true if stop was completed /// /// private bool StopUpdating() { if (null == _cancellationTokenSource || null == _existingLocks) { return false; } lock (MyLock) { _cancellationTokenSource.Cancel(); if (!_updateTask.Wait(MAX_WAIT_TIME_MS)) { APILogger.Log("Failed to stop updating locks"); return false; } } return true; } public void Unlock(bool bCheckLock, string userName, int userId) { if (!StopUpdating()) { return; } lock (MyLock) { if (null == _existingLocks || 0 == _existingLocks.Length) { return; } } try { FreeLocks(); } catch (Exception ex) { APILogger.Log(ex); } } private void FreeLocks() { LockRecord[] locks; lock (MyLock) { if (null == _existingLocks || 0 == _existingLocks.Length) { return; } locks = _existingLocks.ToArray(); } foreach( var record in locks) { try { LockManager.FreeLoc } catch(Exception ex) { APILogger.Log(ex); } } } private bool CheckLock(bool publishErrors, string userName, int userId, LockRecord lockRecord, out LockError lockError) { throw new NotImplementedException(); } /// /// performs an immediate update of locks, publishes an error if the lock could not be updated /// /// whether to publish when there's an error or not /// private bool CheckLocks(bool publishErrors, string userName, int userId) { try { LockRecord[] records; lock (MyLock) { //FB 18006 Prevent null reference exception if (_existingLocks == null || 0 == _existingLocks.Length) { APILogger.Log("_existingLock is null"); return false; } //create a local copy of the locks so we can update them without the lock records = _existingLocks.ToArray(); } var failed = new List(); var errors = new List(); foreach (var record in records) { LockError lockError; if (!CheckLock(publishErrors, userName, userId, record, out lockError)) { failed.Add(record); errors.Add(lockError); } } if (failed.Any() && errors.Any()) { if (publishErrors) { var msg = GetErrorMessage(errors.ToArray(), records.ToArray()); var eventAggregator = ContainerLocator.Container.Resolve(); eventAggregator.GetEvent().Publish(new PageErrorArg(new[] { msg }, null)); } //if we failed to update ANY of them we need to wipe out our selection lock (MyLock) { _existingLocks = new LockRecord[0]; } WipeOutChanges(); return false; } return true; } catch (Exception ex) { APILogger.Log(ex); if (publishErrors) { var eventAggregator = ContainerLocator.Container.Resolve(); eventAggregator.GetEvent().Publish(new PageErrorArg( new[] { $"{StringResources.FailedToUpdateLock}, {ex.Message}" }, null)); } _cancellationTokenSource?.Cancel(); lock (MyLock) { _existingLocks = new LockRecord[0]; } return false; } } private void WipeOutChanges() { throw new NotImplementedException(); } private static string GetErrorMessage(LockError[] errors, LockRecord[] lockRecords ) { StringBuilder sb = new StringBuilder(0); for( var i = 0; i < errors.Length && i < lockRecords.Length; i ++) { var error = errors[i]; var record = lockRecords[i]; if (error.LockStolen) { sb.AppendLine(string.Format(StringResources.LockStolen_Sensors, record.ItemKey, error.LockingUser, error.LockingMachine)); } else if(error.LockLost) { sb.AppendLine(string.Format(StringResources.LockLost_Sensors, record.ItemKey)); } else { sb.AppendLine($"{StringResources.FailedToUpdateLock} - {record.ItemKey}"); } } return sb.ToString(); } /// /// returns true if the lockrecord matches the sensor currently locked in this control /// 14340 sensor lost/locked - unlocked on sensor import /// /// /// public bool IsCurrentlyLocked(LockRecord lockRecord) { lock (MyLock) { if (null == _existingLocks) { return false; } return Array.Exists(_existingLocks, x => x.ItemId == lockRecord.ItemId && x.ItemCategory == lockRecord.ItemCategory); } } } }