private void SendBufferedMessages()
{
var sendDelegate = new Func<object, bool>(msg =>
{
if (msg is EndpointManager.Send)
{
return WriteSend(msg as EndpointManager.Send);
}
else if (msg is FlushAndStop)
{
DoFlushAndStop();
return false;
}
else if (msg is StopReading)
{
var s = msg as StopReading;
if (_reader != null) _reader.Tell(s, s.ReplyTo);
}
return true;
});
Func<int, bool> writeLoop = null;
writeLoop = new Func<int, bool>(count =>
{
if (count > 0 && _buffer.Any())
{
if (sendDelegate(_buffer.First.Value))
{
_buffer.RemoveFirst();
_writeCount += 1;
return writeLoop(count - 1);
}
return false;
}
return true;
});
Func<bool> writePrioLoop = null;
writePrioLoop = () =>
{
if (!_prioBuffer.Any()) return true;
if (WriteSend(_prioBuffer.First.Value))
{
_prioBuffer.RemoveFirst();
return writePrioLoop();
}
return false;
};
var size = _buffer.Count;
var ok = writePrioLoop() && writeLoop(SendBufferBatchSize);
if (!_buffer.Any() && !_prioBuffer.Any())
{
// FIXME remove this when testing/tuning is completed
if (_log.IsDebugEnabled)
{
_log.Debug("Drained buffer with maxWriteCount: {0}, fullBackoffCount: {1}," +
"smallBackoffCount: {2}, noBackoffCount: {3}," +
"adaptiveBackoff: {4}", _maxWriteCount, _fullBackoffCount, _smallBackoffCount, _noBackoffCount, _adaptiveBackoffNanos / 1000);
}
_fullBackoffCount = 1;
_smallBackoffCount = 0;
_noBackoffCount = 0;
_writeCount = 0;
_maxWriteCount = MaxWriteCount;
Become(Writing);
}
else if (ok)
{
_noBackoffCount += 1;
Self.Tell(BackoffTimer.Instance);
}
else
{
if (size > Settings.LogBufferSizeExceeding)
{
var now = MonotonicClock.GetNanos();
if (now - _largeBufferLogTimestamp >= LogBufferSizeInterval)
{
_log.Warning("[{0}] buffered messages in EndpointWriter for [{1}]. You should probably implement flow control to avoid flooding the remote connection.", size, RemoteAddress);
_largeBufferLogTimestamp = now;
}
}
}
AdjustAdaptiveBackup();
ScheduleBackoffTimer();
}