Skip to content

Commit 9df5c22

Browse files
committed
By splitting observation removal lock and further adding lock, there was broken atomicity of the update.
As a result, a simultaneously running current query could not return any value for removed observation. And this observation, once restored, was not returned as sample. After all it was an update of existing observation. To mitigate the problem made update atomic.
1 parent cb51397 commit 9df5c22

1 file changed

Lines changed: 57 additions & 53 deletions

File tree

libraries/MTConnect.NET-Common/Buffers/MTConnectObservationBuffer.cs

Lines changed: 57 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -589,40 +589,40 @@ protected void AddCurrentObservation(BufferObservation observation)
589589
{
590590
_currentObservations.TryGetValue(observation._key, out existingObservation);
591591
_currentObservations.Remove(observation._key);
592-
}
593-
594-
if (existingObservation.IsValid && !isUnavailable)
595-
{
596-
if (resetTriggered == ResetTriggered.NOT_SPECIFIED)
592+
593+
if (existingObservation.IsValid && !isUnavailable)
597594
{
598-
// Update Observations based on Representation
599-
switch (observation.Representation)
595+
if (resetTriggered == ResetTriggered.NOT_SPECIFIED)
600596
{
601-
case DataItemRepresentation.DATA_SET:
597+
// Update Observations based on Representation
598+
switch (observation.Representation)
599+
{
600+
case DataItemRepresentation.DATA_SET:
602601

603-
// Update DataSet Values
604-
var existingDataSetValues = GetDataSetValues(ref existingObservation);
605-
if (!existingDataSetValues.IsNullOrEmpty())
606-
{
607-
observation.Values = CombineDataSetValues(observation.Values, ref existingDataSetValues);
608-
}
602+
// Update DataSet Values
603+
var existingDataSetValues = GetDataSetValues(ref existingObservation);
604+
if (!existingDataSetValues.IsNullOrEmpty())
605+
{
606+
observation.Values = CombineDataSetValues(observation.Values, ref existingDataSetValues);
607+
}
609608

610-
break;
609+
break;
611610

612-
case DataItemRepresentation.TABLE:
611+
case DataItemRepresentation.TABLE:
613612

614-
// Update Table Values
615-
var existingTableValues = GetTableValues(ref existingObservation);
616-
if (!existingTableValues.IsNullOrEmpty())
617-
{
618-
observation.Values = CombineTableValues(observation.Values, ref existingTableValues);
619-
}
620-
break;
613+
// Update Table Values
614+
var existingTableValues = GetTableValues(ref existingObservation);
615+
if (!existingTableValues.IsNullOrEmpty())
616+
{
617+
observation.Values = CombineTableValues(observation.Values, ref existingTableValues);
618+
}
619+
break;
620+
}
621621
}
622622
}
623-
}
624623

625-
lock (_lock) _currentObservations.Add(observation._key, observation);
624+
_currentObservations.Add(observation._key, observation);
625+
}
626626

627627
// Call Overridable Methods
628628
OnCurrentObservationAdd(ref observation);
@@ -642,49 +642,53 @@ protected void AddCurrentCondition(BufferObservation observation)
642642
var bufferObservations = new List<BufferObservation>();
643643

644644
IEnumerable<BufferObservation> existingObservations;
645+
IEnumerable<BufferObservation> iBufferObservations;
645646
lock (_lock)
646647
{
647648
_currentConditions.TryGetValue(observation._key, out existingObservations);
648649
_currentConditions.Remove(observation._key);
649-
}
650-
651-
if (!existingObservations.IsNullOrEmpty())
652-
{
653-
var conditionLevel = observation.GetValue(ValueKeys.Level);
654-
var nativeCode = observation.GetValue(ValueKeys.NativeCode);
655650

656-
if (!(conditionLevel == ConditionLevel.NORMAL.ToString() && string.IsNullOrEmpty(nativeCode)) &&
657-
conditionLevel != ConditionLevel.UNAVAILABLE.ToString())
651+
if (!existingObservations.IsNullOrEmpty())
658652
{
659-
foreach (var existingObservation in existingObservations)
660-
{
661-
var existingLevel = existingObservation.GetValue(ValueKeys.Level);
662-
var existingNativeCode = existingObservation.GetValue(ValueKeys.NativeCode);
653+
var conditionLevel = observation.GetValue(ValueKeys.Level);
654+
var nativeCode = observation.GetValue(ValueKeys.NativeCode);
663655

664-
if (existingNativeCode != nativeCode &&
665-
existingLevel != ConditionLevel.UNAVAILABLE.ToString() &&
666-
existingObservation.Sequence != observation.Sequence)
656+
if (!(conditionLevel == ConditionLevel.NORMAL.ToString() && string.IsNullOrEmpty(nativeCode)) &&
657+
conditionLevel != ConditionLevel.UNAVAILABLE.ToString())
658+
{
659+
foreach (var existingObservation in existingObservations)
667660
{
668-
bufferObservations.Add(existingObservation);
661+
var existingLevel = existingObservation.GetValue(ValueKeys.Level);
662+
var existingNativeCode = existingObservation.GetValue(ValueKeys.NativeCode);
663+
664+
if (existingNativeCode != nativeCode &&
665+
existingLevel != ConditionLevel.UNAVAILABLE.ToString() &&
666+
existingObservation.Sequence != observation.Sequence)
667+
{
668+
bufferObservations.Add(existingObservation);
669+
}
669670
}
670671
}
671672
}
672-
}
673673

674-
// Add the new Observation
675-
bufferObservations.Add(observation);
674+
// Add the new Observation
675+
bufferObservations.Add(observation);
676676

677-
// If any WARNING or FAULT states present, then remove any NORMAL states
678-
// Current should only show the active states
679-
if (bufferObservations.Any(o => o.GetValue(ValueKeys.Level) == ConditionLevel.WARNING.ToString() || o.GetValue(ValueKeys.Level) == ConditionLevel.FAULT.ToString()))
680-
{
681-
bufferObservations.RemoveAll(o => o.GetValue(ValueKeys.Level) == ConditionLevel.NORMAL.ToString());
682-
}
677+
// If any WARNING or FAULT states present, then remove any NORMAL states
678+
// Current should only show the active states
679+
if (bufferObservations.Any(o =>
680+
o.GetValue(ValueKeys.Level) == ConditionLevel.WARNING.ToString() ||
681+
o.GetValue(ValueKeys.Level) == ConditionLevel.FAULT.ToString()))
682+
{
683+
bufferObservations.RemoveAll(o =>
684+
o.GetValue(ValueKeys.Level) == ConditionLevel.NORMAL.ToString());
685+
}
683686

684-
IEnumerable<BufferObservation> iBufferObservations = bufferObservations;
687+
iBufferObservations = bufferObservations;
685688

686-
// Add to stored List
687-
lock (_lock) _currentConditions.Add(observation._key, iBufferObservations);
689+
// Add to stored List
690+
_currentConditions.Add(observation._key, iBufferObservations);
691+
}
688692

689693
// Call Overridable Method
690694
OnCurrentConditionChange(GetCurrentConditions());

0 commit comments

Comments
 (0)