< Summary

Information
Class: Ice.Internal.IdleTimeoutTransceiverDecorator
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/Internal/IdleTimeoutTransceiverDecorator.cs
Tag: 71_18251537082
Line coverage
93%
Covered lines: 56
Uncovered lines: 4
Coverable lines: 60
Total lines: 152
Line coverage: 93.3%
Branch coverage
95%
Covered branches: 19
Total branches: 20
Branch coverage: 95%
Method coverage
85%
Covered methods: 24
Total methods: 28
Method coverage: 85.7%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_idleCheckEnabled()100%11100%
set_idleCheckEnabled(...)100%11100%
ToString()100%11100%
bind()100%210%
checkSendSize(...)100%11100%
close()100%11100%
closing(...)100%11100%
destroy()100%22100%
fd()100%210%
finishRead(...)100%22100%
finishWrite(...)100%11100%
getInfo(...)100%11100%
initialize(...)100%11100%
protocol()100%210%
read(...)100%22100%
setBufferSize(...)100%11100%
startRead(...)100%11100%
startWrite(...)100%11100%
toDetailedString()100%210%
write(...)100%22100%
.ctor(...)100%22100%
enableIdleCheck()100%44100%
disableIdleCheck()100%44100%
scheduleHeartbeat()100%11100%
cancelReadTimer()100%11100%
cancelWriteTimer()100%11100%
rescheduleReadTimer()50%22100%
rescheduleWriteTimer()100%11100%

File(s)

/home/runner/work/ice/ice/csharp/src/Ice/Internal/IdleTimeoutTransceiverDecorator.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5using System.Diagnostics;
 6using System.Net.Sockets;
 7
 8namespace Ice.Internal;
 9
 10#pragma warning disable CA1001 // _readTimer and _writeTimer are disposed by destroy.
 11internal sealed class IdleTimeoutTransceiverDecorator : Transceiver
 12#pragma warning restore CA1001
 13{
 14    private readonly Transceiver _decoratee;
 15    private readonly TimeSpan _idleTimeout;
 16    private readonly System.Threading.Timer? _readTimer;
 17    private readonly System.Threading.Timer _writeTimer;
 18
 19    // Called by ConnectionI with its mutex locked.
 120    internal bool idleCheckEnabled { get; private set; }
 21
 122    public override string ToString() => _decoratee.ToString()!;
 23
 024    public EndpointI? bind() => _decoratee.bind();
 25
 126    public void checkSendSize(Buffer buf) => _decoratee.checkSendSize(buf);
 27
 28    public void close()
 29    {
 130        disableIdleCheck();
 131        cancelWriteTimer();
 132        _decoratee.close();
 133    }
 34
 135    public int closing(bool initiator, LocalException ex) => _decoratee.closing(initiator, ex);
 36
 37    public void destroy()
 38    {
 139        disableIdleCheck();
 140        cancelWriteTimer();
 141        _decoratee.destroy();
 142        _readTimer?.Dispose();
 143        _writeTimer.Dispose();
 144    }
 45
 046    public Socket fd() => _decoratee.fd();
 47
 48    public void finishRead(Buffer buf)
 49    {
 150        if (idleCheckEnabled)
 51        {
 52            // We don't want the idle check to run while we're reading, so we reschedule it before reading.
 153            rescheduleReadTimer();
 54        }
 155        _decoratee.finishRead(buf);
 156    }
 57
 58    // We call write after finishWrite, so no need to do anything here.
 159    public void finishWrite(Buffer buf) => _decoratee.finishWrite(buf);
 60
 61    public ConnectionInfo getInfo(bool incoming, string adapterName, string connectionId) =>
 162        _decoratee.getInfo(incoming, adapterName, connectionId);
 63
 64    public int initialize(Buffer readBuffer, Buffer writeBuffer, ref bool hasMoreData) =>
 165        _decoratee.initialize(readBuffer, writeBuffer, ref hasMoreData);
 66
 067    public string protocol() => _decoratee.protocol();
 68
 69    public int read(Buffer buf, ref bool hasMoreData)
 70    {
 71        // We don't want the idle check to run while we're reading, so we reschedule it before reading.
 172        if (idleCheckEnabled)
 73        {
 174            rescheduleReadTimer();
 75        }
 176        return _decoratee.read(buf, ref hasMoreData);
 77    }
 78
 179    public void setBufferSize(int rcvSize, int sndSize) => _decoratee.setBufferSize(rcvSize, sndSize);
 80
 81    // We always call finishRead or read to actually read the data.
 82    public bool startRead(Buffer buf, AsyncCallback callback, object state) =>
 183        _decoratee.startRead(buf, callback, state);
 84
 85    // startWrite is called right after write returns SocketOperationWrite. The logic in write is sufficient.
 86    public bool startWrite(Buffer buf, AsyncCallback callback, object state, out bool messageWritten) =>
 187        _decoratee.startWrite(buf, callback, state, out messageWritten);
 88
 089    public string toDetailedString() => _decoratee.toDetailedString();
 90
 91    public int write(Buffer buf)
 92    {
 193        cancelWriteTimer();
 194        int op = _decoratee.write(buf);
 195        if (op == SocketOperation.None) // write completed
 96        {
 197            rescheduleWriteTimer();
 98        }
 199        return op;
 100    }
 101
 1102    internal IdleTimeoutTransceiverDecorator(
 1103        Transceiver decoratee,
 1104        ConnectionI connection,
 1105        TimeSpan idleTimeout,
 1106        bool enableIdleCheck)
 107    {
 108        Debug.Assert(idleTimeout > TimeSpan.Zero);
 109
 1110        _decoratee = decoratee;
 1111        _idleTimeout = idleTimeout;
 112
 1113        if (enableIdleCheck)
 114        {
 1115            _readTimer = new System.Threading.Timer(_ => connection.idleCheck(_idleTimeout));
 116
 117            // idleCheckEnabled remains false for now. ConnectionI calls enableIdleCheck() when it becomes Active to
 118            // schedule the first idle check and set idleCheckEnabled to true.
 119            // We don't want the idle check to start when a client connection is waiting for the initial
 120            // ValidateConnection message or when a server connection is in its initial StateHolding state.
 121        }
 1122        _writeTimer = new System.Threading.Timer(_ => connection.sendHeartbeat());
 1123    }
 124
 125    internal void enableIdleCheck()
 126    {
 1127        if (!idleCheckEnabled && _readTimer is not null)
 128        {
 1129            rescheduleReadTimer();
 1130            idleCheckEnabled = true;
 131        }
 1132    }
 133
 134    internal void disableIdleCheck()
 135    {
 1136        if (idleCheckEnabled && _readTimer is not null)
 137        {
 1138            cancelReadTimer();
 1139            idleCheckEnabled = false;
 140        }
 1141    }
 142
 1143    internal void scheduleHeartbeat() => rescheduleWriteTimer();
 144
 1145    private void cancelReadTimer() => _readTimer!.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
 146
 1147    private void cancelWriteTimer() => _writeTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
 148
 1149    private void rescheduleReadTimer() => _readTimer?.Change(_idleTimeout, Timeout.InfiniteTimeSpan);
 150
 1151    private void rescheduleWriteTimer() => _writeTimer.Change(_idleTimeout / 2, Timeout.InfiniteTimeSpan);
 152}