public async Task Rollback() { while (!ReliableDictionariesInitialized) { await Task.Delay(1000); } try { await IncomingGidToPointItemMap.ClearAsync(); await IncomingAddressToGidMap.ClearAsync(); await ModelChanges.ClearAsync(); string message = $"{baseLogString} Rollback => Incoming SCADA model is rejected."; Logger.LogInformation(message); await LogAllReliableCollections(); } catch (Exception e) { string errorMessage = $"{baseLogString} Rollback => Exception: {e.Message}"; Logger.LogError(errorMessage, e); } }
private async Task <bool> CheckSuccessiveAddressCondition() { bool condition = true; var addressToGidMapDictionary = await IncomingAddressToGidMap.GetEnumerableDictionaryAsync(); foreach (var type in addressToGidMapDictionary.Keys) { var addressToGidMap = addressToGidMapDictionary[type]; for (ushort address = 1; address <= addressToGidMap.Values.Count; address++) { condition = addressToGidMap.ContainsKey(address); if (condition == false) { string errorMessage = $"{baseLogString} CheckSuccessiveAddressCondition => Addresses of {(PointType)type} measurements are not successive. Probably a problem with cim/xml."; Logger.LogError(errorMessage); break; } } if (condition == false) { break; } } return(condition); }
public async Task Commit() { while (!ReliableDictionariesInitialized) { await Task.Delay(1000); } try { await reliableDictionaryHelper.TryCopyToReliableDictionary <long, IScadaModelPointItem>(ReliableDictionaryNames.IncomingGidToPointItemMap, ReliableDictionaryNames.GidToPointItemMap, this.stateManager); await reliableDictionaryHelper.TryCopyToReliableDictionary <short, Dictionary <ushort, long> >(ReliableDictionaryNames.IncomingAddressToGidMap, ReliableDictionaryNames.AddressToGidMap, this.stateManager); await IncomingGidToPointItemMap.ClearAsync(); await IncomingAddressToGidMap.ClearAsync(); await ModelChanges.ClearAsync(); await CommandDescriptionCache.ClearAsync(); await MeasurementsCache.ClearAsync(); string message = $"{baseLogString} Commit => Incoming SCADA model is confirmed."; Logger.LogInformation(message); await SendModelUpdateCommands(); await LogAllReliableCollections(); } catch (Exception e) { string errorMessage = $"{baseLogString} Commit => Exception: {e.Message}"; Logger.LogError(errorMessage, e); } }
private async Task HandleUpdateOperation(IScadaModelPointItem incomingPointItem, long gid) { var pointItemResult = await IncomingGidToPointItemMap.TryGetValueAsync(gid); if (!pointItemResult.HasValue) { string errorMessage = $"{baseLogString} HandleUpdateOperation => Model update data in fault state. Updating entity with gid: {gid:X16}, that does not exists in IncomingGidToPointItemMap."; Logger.LogError(errorMessage); throw new ArgumentException(errorMessage); } IScadaModelPointItem oldPointItem = pointItemResult.Value; var addressToGidMapResult = await IncomingAddressToGidMap.TryGetValueAsync((short)oldPointItem.RegisterType); if (!addressToGidMapResult.HasValue) { string errorMessage = $"{baseLogString} HandleUpdateOperation => Model update data in fault state. Updating entity with gid: {gid:X16}, {oldPointItem.RegisterType} registry type does not exist in incoming IncomingAddressToGidMap."; Logger.LogError(errorMessage); throw new ArgumentException(errorMessage); } var incomingAddressToGidMapDictionary = addressToGidMapResult.Value; if (!incomingAddressToGidMapDictionary.ContainsKey(oldPointItem.Address)) { string message = $"{baseLogString} HandleUpdateOperation => Model update data in fault state. Updating point with address: {oldPointItem.Address}, that does not exists in IncomingAddressToGidMap."; Logger.LogError(message); throw new ArgumentException(message); } if (oldPointItem.Address != incomingPointItem.Address && incomingAddressToGidMapDictionary.ContainsKey(incomingPointItem.Address)) { string message = $"{baseLogString} HandleUpdateOperation => Model update data in fault state. Trying to add point with address: {incomingPointItem.Address}, that already exists in IncomingAddressToGidMap."; Logger.LogError(message); throw new ArgumentException(message); } string appendMessage = ""; string oldAddressText = ""; //LOGIC await IncomingGidToPointItemMap.SetAsync(gid, incomingPointItem); if (oldPointItem.Address != incomingPointItem.Address) { incomingAddressToGidMapDictionary.Remove(oldPointItem.Address); incomingAddressToGidMapDictionary.Add(incomingPointItem.Address, gid); await IncomingAddressToGidMap.SetAsync((short)oldPointItem.RegisterType, incomingAddressToGidMapDictionary); appendMessage = " and IncomingAddressToGidMap"; oldAddressText = $", Old address: {oldPointItem.Address}"; } string debugMessage = $"{baseLogString} HandleUpdateOperation => SUCCESSFULLY updated point from IncomingGidToPointItemMap{appendMessage}. Gid: 0x{incomingPointItem.Gid:X16}, Address: {incomingPointItem.Address}{oldAddressText}"; Logger.LogDebug(debugMessage); }
private async Task HandleDeleteOperation(long gid) { var pointItemResult = await IncomingGidToPointItemMap.TryGetValueAsync(gid); if (!pointItemResult.HasValue) { string errorMessage = $"{baseLogString} HandleDeleteOperation => Model update data in fault state. Deleting entity with gid: {gid:X16}, that does not exists in IncomingGidToPointItemMap."; Logger.LogError(errorMessage); throw new ArgumentException(errorMessage); } IScadaModelPointItem oldPointItem = pointItemResult.Value; Dictionary <ushort, long> incomingAddressToGidMapDictionary; var type = (short)oldPointItem.RegisterType; var addressToGidMapResult = await IncomingAddressToGidMap.TryGetValueAsync(type); if (!addressToGidMapResult.HasValue) { incomingAddressToGidMapDictionary = new Dictionary <ushort, long>(); } else { incomingAddressToGidMapDictionary = addressToGidMapResult.Value; } if (!incomingAddressToGidMapDictionary.ContainsKey(oldPointItem.Address)) { string message = $"{baseLogString} HandleDeleteOperation => Model update data in fault state. Deleting point with address: {oldPointItem.Address}, that does not exists in IncomingAddressToGidMap."; Logger.LogError(message); throw new ArgumentException(message); } //LOGIC await IncomingGidToPointItemMap.TryRemoveAsync(gid); incomingAddressToGidMapDictionary.Remove(oldPointItem.Address); await IncomingAddressToGidMap.SetAsync(type, incomingAddressToGidMapDictionary); string debugMessage = $"{baseLogString} HandleDeleteOperation => SUCCESSFULLY deleted point from IncomingGidToPointItemMap and IncomingAddressToGidMap. Gid: 0x{oldPointItem.Gid:X16}, Address: {oldPointItem.Address}"; Logger.LogDebug(debugMessage); }
private async Task InitializeIncomingScadaModel() { var enumerableCurrentGidToPointItemMap = await CurrentGidToPointItemMap.GetEnumerableDictionaryAsync(); foreach (long gid in enumerableCurrentGidToPointItemMap.Keys) { //NODO: to tasks, await all (performanse) IScadaModelPointItem pointItem = enumerableCurrentGidToPointItemMap[gid].Clone(); await IncomingGidToPointItemMap.SetAsync(gid, pointItem); short registerType = (short)pointItem.RegisterType; if (!(await IncomingAddressToGidMap.ContainsKeyAsync(registerType))) { await IncomingAddressToGidMap.SetAsync(registerType, new Dictionary <ushort, long>()); } var addressToGidDictionaryResult = await IncomingAddressToGidMap.TryGetValueAsync(registerType); if (!addressToGidDictionaryResult.HasValue) { string message = $"{baseLogString} InitializeIncomingScadaModel => reliable collection '{ReliableDictionaryNames.IncomingAddressToGidMap}' is not initialized properly."; Logger.LogError(message); throw new InternalSCADAServiceException(message); } var addressToGidDictionary = addressToGidDictionaryResult.Value; if (addressToGidDictionary.ContainsKey(pointItem.Address)) { string message = $"{baseLogString} InitializeIncomingScadaModel => SCADA model is invalid => Address: {pointItem.Address} (RegType: {registerType}) belongs to more than one entity."; Logger.LogError(message); throw new InternalSCADAServiceException(message); } addressToGidDictionary.Add(pointItem.Address, pointItem.Gid); await IncomingAddressToGidMap.SetAsync(registerType, addressToGidDictionary); string debugMessage = $"{baseLogString} InitializeIncomingScadaModel => measurement added to Incoming SCADA model [Gid: 0x{gid:X16}, Address: {pointItem.Address}]"; Logger.LogDebug(debugMessage); } }
private async Task HandleInsertOperation(IScadaModelPointItem incomingPointItem, long gid) { var pointItemResult = await IncomingGidToPointItemMap.TryGetValueAsync(gid); if (pointItemResult.HasValue) { string errorMessage = $"{baseLogString} HandleInsertOperation => Model update data in fault state. Inserting entity with gid: {gid:X16}, that already exists in IncomingGidToPointItemMap."; Logger.LogError(errorMessage); throw new ArgumentException(errorMessage); } Dictionary <ushort, long> incomingAddressToGidMapDictionary; var type = (short)incomingPointItem.RegisterType; var addressToGidMapResult = await IncomingAddressToGidMap.TryGetValueAsync(type); if (!addressToGidMapResult.HasValue) { incomingAddressToGidMapDictionary = new Dictionary <ushort, long>(); } else { incomingAddressToGidMapDictionary = addressToGidMapResult.Value; } if (incomingAddressToGidMapDictionary.ContainsKey(incomingPointItem.Address)) { string message = $"{baseLogString} HandleInsertOperation => Model update data in fault state. Inserting entity with address: {incomingPointItem.Address}, that already exists in IncomingAddressToGidMap."; Logger.LogError(message); throw new ArgumentException(message); } //LOGIC await IncomingGidToPointItemMap.SetAsync(gid, incomingPointItem); incomingAddressToGidMapDictionary.Add(incomingPointItem.Address, gid); await IncomingAddressToGidMap.SetAsync(type, incomingAddressToGidMapDictionary); string debugMessage = $"{baseLogString} HandleInsertOperation => SUCCESSFULLY inserted point into IncomingGidToPointItemMap and IncomingAddressToGidMap. Gid: 0x{incomingPointItem.Gid:X16}, Address: {incomingPointItem.Address}"; Logger.LogDebug(debugMessage); }
private async Task LogAllReliableCollections() { while (!ReliableDictionariesInitialized) { await Task.Delay(1000); } StringBuilder sb = new StringBuilder(); sb.AppendLine("Reliable Collections"); sb.AppendLine("CurrentGidToPointItemMap =>"); var currentGidToPointItemMap = await CurrentGidToPointItemMap.GetEnumerableDictionaryAsync(); foreach (var element in currentGidToPointItemMap) { sb.AppendLine($"Key => {element.Key}, Value => Gid: 0x{element.Value.Gid:X16}, Address: {element.Value.Address}, Name: {element.Value.Name}, RegisterType: {element.Value.RegisterType}, Alarm: {element.Value.Alarm}, Initialized: {element.Value.Initialized}"); } sb.AppendLine(); sb.AppendLine("IncomingGidToPointItemMap =>"); var incomingGidToPointItemMap = await IncomingGidToPointItemMap.GetEnumerableDictionaryAsync(); foreach (var element in incomingGidToPointItemMap) { sb.AppendLine($"Key => {element.Key}, Value => Gid: 0x{element.Value.Gid:X16}, Address: {element.Value.Address}, Name: {element.Value.Name}, RegisterType: {element.Value.RegisterType}, Alarm: {element.Value.Alarm}, Initialized: {element.Value.Initialized}"); } sb.AppendLine(); sb.AppendLine("CurrentAddressToGidMap =>"); var currentAddressToGidMap = await CurrentAddressToGidMap.GetEnumerableDictionaryAsync(); foreach (var element in currentAddressToGidMap) { sb.AppendLine($"Key => {element.Key}, Value => Dictionary Count: {element.Value.Count}"); } sb.AppendLine(); sb.AppendLine("IncomingAddressToGidMap =>"); var incomingAddressToGidMap = await IncomingAddressToGidMap.GetEnumerableDictionaryAsync(); foreach (var element in incomingAddressToGidMap) { sb.AppendLine($"Key => {element.Key}, Value => Dictionary Count: {element.Value.Count}"); } sb.AppendLine(); sb.AppendLine("InfoCache =>"); var infoCache = await InfoCache.GetEnumerableDictionaryAsync(); foreach (var element in infoCache) { sb.AppendLine($"Key => {element.Key}, Value => {element.Value}"); } sb.AppendLine(); sb.AppendLine("ModelChanges =>"); var modelChanges = await ModelChanges.GetEnumerableDictionaryAsync(); foreach (var element in modelChanges) { sb.AppendLine($"Key => {element.Key}, Value => List Count: {element.Value.Count}"); } sb.AppendLine(); sb.AppendLine("MeasurementsCache =>"); var measurementsCache = await MeasurementsCache.GetEnumerableDictionaryAsync(); foreach (var element in measurementsCache) { sb.AppendLine($"Key => {element.Key}, Value => MeasurementGid: {element.Value.MeasurementGid:X16}, Alarm: {element.Value.Alarm}, CommandOrigin: {element.Value.CommandOrigin}"); } sb.AppendLine(); sb.AppendLine("CommandDescriptionCache =>"); var commandDescriptionCache = await CommandDescriptionCache.GetEnumerableDictionaryAsync(); foreach (var element in commandDescriptionCache) { sb.AppendLine($"Key => {element.Key}, Value => Gid: {element.Value.Gid:X16}, Address: {element.Value.Address}, Value: {element.Value.Value}, CommandOrigin: {element.Value.CommandOrigin}"); } sb.AppendLine(); Logger.LogDebug($"{baseLogString} LogAllReliableCollections => {sb}"); }