Skip to content

Commit d540baf

Browse files
authored
Remove oldest channel if not used by session, when number of channels reaches MaxChannelCount - 1 (#2986)
* Remove older channel if not used by session, when number of channels reaches MaxChannelCount - 1 * Corrected channelCount and renamings * Operate on snapshot * Snapshot the entire concurentdictionary
1 parent 8e408db commit d540baf

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

Stack/Opc.Ua.Core/Stack/Tcp/TcpListenerChannel.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,21 @@ public void IdleCleanup()
161161
/// or received a keep alive.
162162
/// </summary>
163163
public int ElapsedSinceLastActiveTime => (HiResClock.TickCount - LastActiveTickCount);
164+
165+
/// <summary>
166+
/// Has the channel been used in a session
167+
/// </summary>
168+
public bool UsedBySession
169+
{
170+
get
171+
{
172+
return m_usedBySession;
173+
}
174+
protected set
175+
{
176+
m_usedBySession = value;
177+
}
178+
}
164179
#endregion
165180

166181
#region Socket Event Handlers
@@ -562,6 +577,7 @@ protected uint GetNewTokenId()
562577
private ReportAuditCloseSecureChannelEventHandler m_reportAuditCloseSecureChannelEvent;
563578
private ReportAuditCertificateEventHandler m_reportAuditCertificateEvent;
564579
private long m_lastTokenId;
580+
private bool m_usedBySession;
565581
#endregion
566582
}
567583

Stack/Opc.Ua.Core/Stack/Tcp/TcpServerChannel.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,11 @@ public void SendResponse(uint requestId, IServiceResponse response)
10901090
m_queuedResponses[requestId] = response;
10911091
return;
10921092
}
1093+
1094+
if (response is ActivateSessionResponse activateSessionResponse)
1095+
{
1096+
UsedBySession = StatusCode.IsGood(activateSessionResponse.ResponseHeader.ServiceResult);
1097+
}
10931098
}
10941099
}
10951100

Stack/Opc.Ua.Core/Stack/Tcp/TcpTransportListener.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,31 @@ private void OnAccept(object sender, SocketAsyncEventArgs e)
801801
{
802802
// TODO: .Count is flagged as hotpath, implement separate counter
803803
int channelCount = channels.Count;
804+
805+
// Remove oldest channel that does not have a session attached to it
806+
// before reaching m_maxChannelCount
807+
if (m_maxChannelCount > 0 && m_maxChannelCount == channelCount)
808+
{
809+
var snapshot = channels.ToArray();
810+
811+
// Identify channels without established sessions
812+
var nonSessionChannels = snapshot.Where(ch => !ch.Value.UsedBySession).ToArray();
813+
814+
if (nonSessionChannels.Any())
815+
{
816+
var oldestIdChannel = nonSessionChannels.Aggregate((max, current) =>
817+
current.Value.ElapsedSinceLastActiveTime > max.Value.ElapsedSinceLastActiveTime ? current : max);
818+
819+
Utils.LogInfo("TCPLISTENER: Channel Id {0} scheduled for IdleCleanup - Oldest without established session.",
820+
oldestIdChannel.Value.Id);
821+
oldestIdChannel.Value.IdleCleanup();
822+
Utils.LogInfo("TCPLISTENER: Channel Id {0} finished IdleCleanup - Oldest without established session.",
823+
oldestIdChannel.Value.Id);
824+
825+
channelCount--;
826+
}
827+
}
828+
804829
bool serveChannel = !(m_maxChannelCount > 0 && m_maxChannelCount < channelCount);
805830
if (!serveChannel)
806831
{

0 commit comments

Comments
 (0)