Skip to content

Commit

Permalink
DiagnosticsNodeManager: prevent recursion of DoScan (#2060)
Browse files Browse the repository at this point in the history
* prevent recursion of DoScan

Co-authored-by: Martin Regen <mregen@microsoft.com>
  • Loading branch information
jnsjll and mregen committed Apr 11, 2023
1 parent 620e7c4 commit 8da702d
Showing 1 changed file with 93 additions and 82 deletions.
175 changes: 93 additions & 82 deletions Libraries/Opc.Ua.Server/Diagnostics/DiagnosticsNodeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public class DiagnosticsNodeManager : CustomNodeManager2
m_sessions = new List<SessionDiagnosticsData>();
m_subscriptions = new List<SubscriptionDiagnosticsData>();
m_diagnosticsEnabled = true;
m_doScanBusy = false;
m_sampledItems = new List<MonitoredItem>();
m_minimumSamplingInterval = 100;
}
Expand Down Expand Up @@ -1547,124 +1548,133 @@ private void DoScan(object alwaysUpdateArrays)
{
lock (Lock)
{
if (!m_diagnosticsEnabled)
if (!m_diagnosticsEnabled || m_doScanBusy)
{
return;
}

m_lastDiagnosticsScanTime = DateTime.UtcNow;
try
{
m_doScanBusy = true;

// update server diagnostics.
UpdateServerDiagnosticsSummary();
m_lastDiagnosticsScanTime = DateTime.UtcNow;

// update session diagnostics.
bool sessionsChanged = alwaysUpdateArrays != null;
SessionDiagnosticsDataType[] sessionArray = new SessionDiagnosticsDataType[m_sessions.Count];
// update server diagnostics.
UpdateServerDiagnosticsSummary();

for (int ii = 0; ii < m_sessions.Count; ii++)
{
SessionDiagnosticsData diagnostics = m_sessions[ii];
// update session diagnostics.
bool sessionsChanged = alwaysUpdateArrays != null;
SessionDiagnosticsDataType[] sessionArray = new SessionDiagnosticsDataType[m_sessions.Count];

if (UpdateSessionDiagnostics(null, diagnostics, sessionArray, ii))
for (int ii = 0; ii < m_sessions.Count; ii++)
{
sessionsChanged = true;
SessionDiagnosticsData diagnostics = m_sessions[ii];

if (UpdateSessionDiagnostics(null, diagnostics, sessionArray, ii))
{
sessionsChanged = true;
}
}
}

// check of the session diagnostics array node needs to be updated.
SessionDiagnosticsArrayState sessionsNode = (SessionDiagnosticsArrayState)FindPredefinedNode(
VariableIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary_SessionDiagnosticsArray,
typeof(SessionDiagnosticsArrayState));
// check of the session diagnostics array node needs to be updated.
SessionDiagnosticsArrayState sessionsNode = (SessionDiagnosticsArrayState)FindPredefinedNode(
VariableIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary_SessionDiagnosticsArray,
typeof(SessionDiagnosticsArrayState));

if (sessionsNode != null && (sessionsNode.Value == null || StatusCode.IsBad(sessionsNode.StatusCode) || sessionsChanged))
{
sessionsNode.Value = sessionArray;
sessionsNode.ClearChangeMasks(SystemContext, false);
}
if (sessionsNode != null && (sessionsNode.Value == null || StatusCode.IsBad(sessionsNode.StatusCode) || sessionsChanged))
{
sessionsNode.Value = sessionArray;
sessionsNode.ClearChangeMasks(SystemContext, false);
}

bool sessionsSecurityChanged = alwaysUpdateArrays != null;
SessionSecurityDiagnosticsDataType[] sessionSecurityArray = new SessionSecurityDiagnosticsDataType[m_sessions.Count];
bool sessionsSecurityChanged = alwaysUpdateArrays != null;
SessionSecurityDiagnosticsDataType[] sessionSecurityArray = new SessionSecurityDiagnosticsDataType[m_sessions.Count];

for (int ii = 0; ii < m_sessions.Count; ii++)
{
SessionDiagnosticsData diagnostics = m_sessions[ii];
for (int ii = 0; ii < m_sessions.Count; ii++)
{
SessionDiagnosticsData diagnostics = m_sessions[ii];

if (UpdateSessionSecurityDiagnostics(null, diagnostics, sessionSecurityArray, ii))
if (UpdateSessionSecurityDiagnostics(null, diagnostics, sessionSecurityArray, ii))
{
sessionsSecurityChanged = true;
}
}

// check of the array node needs to be updated.
SessionSecurityDiagnosticsArrayState sessionsSecurityNode = (SessionSecurityDiagnosticsArrayState)FindPredefinedNode(
VariableIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary_SessionSecurityDiagnosticsArray,
typeof(SessionSecurityDiagnosticsArrayState));

if (sessionsSecurityNode != null && (sessionsSecurityNode.Value == null || StatusCode.IsBad(sessionsSecurityNode.StatusCode) || sessionsSecurityChanged))
{
sessionsSecurityChanged = true;
sessionsSecurityNode.Value = sessionSecurityArray;
sessionsSecurityNode.ClearChangeMasks(SystemContext, false);
}
}

// check of the array node needs to be updated.
SessionSecurityDiagnosticsArrayState sessionsSecurityNode = (SessionSecurityDiagnosticsArrayState)FindPredefinedNode(
VariableIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary_SessionSecurityDiagnosticsArray,
typeof(SessionSecurityDiagnosticsArrayState));
bool subscriptionsChanged = alwaysUpdateArrays != null;
SubscriptionDiagnosticsDataType[] subscriptionArray = new SubscriptionDiagnosticsDataType[m_subscriptions.Count];

if (sessionsSecurityNode != null && (sessionsSecurityNode.Value == null || StatusCode.IsBad(sessionsSecurityNode.StatusCode) || sessionsSecurityChanged))
{
sessionsSecurityNode.Value = sessionSecurityArray;
sessionsSecurityNode.ClearChangeMasks(SystemContext, false);
}
for (int ii = 0; ii < m_subscriptions.Count; ii++)
{
SubscriptionDiagnosticsData diagnostics = m_subscriptions[ii];

bool subscriptionsChanged = alwaysUpdateArrays != null;
SubscriptionDiagnosticsDataType[] subscriptionArray = new SubscriptionDiagnosticsDataType[m_subscriptions.Count];
if (UpdateSubscriptionDiagnostics(null, diagnostics, subscriptionArray, ii))
{
subscriptionsChanged = true;
}
}

for (int ii = 0; ii < m_subscriptions.Count; ii++)
{
SubscriptionDiagnosticsData diagnostics = m_subscriptions[ii];
// check of the subscription node needs to be updated.
SubscriptionDiagnosticsArrayState subscriptionsNode = (SubscriptionDiagnosticsArrayState)FindPredefinedNode(
VariableIds.Server_ServerDiagnostics_SubscriptionDiagnosticsArray,
typeof(SubscriptionDiagnosticsArrayState));

if (UpdateSubscriptionDiagnostics(null, diagnostics, subscriptionArray, ii))
if (subscriptionsNode != null && (subscriptionsNode.Value == null || StatusCode.IsBad(subscriptionsNode.StatusCode) || subscriptionsChanged))
{
subscriptionsChanged = true;
subscriptionsNode.Value = subscriptionArray;
subscriptionsNode.ClearChangeMasks(SystemContext, false);
}
}

// check of the subscription node needs to be updated.
SubscriptionDiagnosticsArrayState subscriptionsNode = (SubscriptionDiagnosticsArrayState)FindPredefinedNode(
VariableIds.Server_ServerDiagnostics_SubscriptionDiagnosticsArray,
typeof(SubscriptionDiagnosticsArrayState));
for (int ii = 0; ii < m_sessions.Count; ii++)
{
SessionDiagnosticsData diagnostics = m_sessions[ii];
List<SubscriptionDiagnosticsDataType> subscriptionDiagnosticsArray = new List<SubscriptionDiagnosticsDataType>();

if (subscriptionsNode != null && (subscriptionsNode.Value == null || StatusCode.IsBad(subscriptionsNode.StatusCode) || subscriptionsChanged))
{
subscriptionsNode.Value = subscriptionArray;
subscriptionsNode.ClearChangeMasks(SystemContext, false);
}
NodeId sessionId = diagnostics.Summary.NodeId;

for (int ii = 0; ii < m_sessions.Count; ii++)
{
SessionDiagnosticsData diagnostics = m_sessions[ii];
List<SubscriptionDiagnosticsDataType> subscriptionDiagnosticsArray = new List<SubscriptionDiagnosticsDataType>();
for (int jj = 0; jj < m_subscriptions.Count; jj++)
{
SubscriptionDiagnosticsData subscriptionDiagnostics = m_subscriptions[jj];

NodeId sessionId = diagnostics.Summary.NodeId;
if (subscriptionDiagnostics.Value.Value == null)
{
continue;
}

for (int jj = 0; jj < m_subscriptions.Count; jj++)
{
SubscriptionDiagnosticsData subscriptionDiagnostics = m_subscriptions[jj];
if (subscriptionDiagnostics.Value.Value.SessionId != sessionId)
{
continue;
}

if (subscriptionDiagnostics.Value.Value == null)
{
continue;
subscriptionDiagnosticsArray.Add(subscriptionDiagnostics.Value.Value);
}

if (subscriptionDiagnostics.Value.Value.SessionId != sessionId)
// update session subscription array.
subscriptionsNode = (SubscriptionDiagnosticsArrayState)diagnostics.Summary.CreateChild(
SystemContext,
BrowseNames.SubscriptionDiagnosticsArray);

if (subscriptionsNode != null && (subscriptionsNode.Value == null || StatusCode.IsBad(subscriptionsNode.StatusCode) || subscriptionsChanged))
{
continue;
subscriptionsNode.Value = subscriptionDiagnosticsArray.ToArray();
subscriptionsNode.ClearChangeMasks(SystemContext, false);
}

subscriptionDiagnosticsArray.Add(subscriptionDiagnostics.Value.Value);
}

// update session subscription array.
subscriptionsNode = (SubscriptionDiagnosticsArrayState)diagnostics.Summary.CreateChild(
SystemContext,
BrowseNames.SubscriptionDiagnosticsArray);

if (subscriptionsNode != null && (subscriptionsNode.Value == null || StatusCode.IsBad(subscriptionsNode.StatusCode) || subscriptionsChanged))
{
subscriptionsNode.Value = subscriptionDiagnosticsArray.ToArray();
subscriptionsNode.ClearChangeMasks(SystemContext, false);
}
}
finally
{
m_doScanBusy = false;
}
}
}
catch (Exception e)
Expand Down Expand Up @@ -2097,6 +2107,7 @@ private void DoSample(object state)
private Timer m_diagnosticsScanTimer;
private int m_diagnosticsMonitoringCount;
private bool m_diagnosticsEnabled;
private bool m_doScanBusy;
private DateTime m_lastDiagnosticsScanTime;
private ServerDiagnosticsSummaryValue m_serverDiagnostics;
private NodeValueSimpleEventHandler m_serverDiagnosticsCallback;
Expand Down

0 comments on commit 8da702d

Please sign in to comment.