syslog: There is yet another place where the output can get split. That is in syslog_dev_write(): It will break up the stream to insert a CR before the LF. This can that can be avoid be generating the CR-LF sequence in the buffer and then detecting and ignoring valid CR-LF sequences, rather than expecting syslog_dev_write() to insert the CR in this case.

I don't like the idea that syslog_dev_write() still scans the entire output buffer to expand CR-LF sequence.  This seems really wasteful, especially in this case where we can be sure that the is no CR or LF without a matching LF or CR.  Bu, I think, the existing behavior in syslog_dev_write() must be retained because it is needed in other contexts.
This commit is contained in:
Gregory Nutt 2017-05-12 07:31:50 -06:00
parent 0fc068cc9c
commit 1c9859520f
2 changed files with 53 additions and 17 deletions

View File

@ -518,9 +518,22 @@ ssize_t syslog_dev_write(FAR const char *buffer, size_t buflen)
remaining > 0; remaining > 0;
endptr++, remaining--) endptr++, remaining--)
{ {
bool crlf = false;
/* Check for a CR-LF sequence */
if (remaining > 1 &&
((endptr[0] == '\r' && endptr[1] == '\n') ||
(endptr[0] == '\n' && endptr[1] == '\r')))
{
endptr++;
remaining--;
crlf = true;
}
/* Special case carriage return and line feed */ /* Special case carriage return and line feed */
if (*endptr == '\r' || *endptr == '\n') if (!crlf && (*endptr == '\r' || *endptr == '\n'))
{ {
/* Write everything up to this point, ignore the special /* Write everything up to this point, ignore the special
* character. * character.

View File

@ -94,6 +94,33 @@ static int syslogstream_flush(FAR struct lib_syslogstream_s *stream)
} }
#endif #endif
/****************************************************************************
* Name: syslogstream_addchar
****************************************************************************/
static void syslogstream_addchar(FAR struct lib_syslogstream_s *stream, int ch)
{
FAR struct iob_s *iob = stream->iob;
/* Add the incoming character to the buffer */
iob->io_data[iob->io_len] = ch;
iob->io_len++;
/* Increment the total number of bytes buffered. */
stream->public.nput++;
/* Is the buffer full? */
if (iob->io_len >= CONFIG_IOB_BUFSIZE)
{
/* Yes.. then flush the buffer */
syslogstream_flush(stream);
}
}
/**************************************************************************** /****************************************************************************
* Name: syslogstream_putc * Name: syslogstream_putc
****************************************************************************/ ****************************************************************************/
@ -105,31 +132,27 @@ static void syslogstream_putc(FAR struct lib_outstream_s *this, int ch)
if (ch != '\r') if (ch != '\r')
{ {
#ifdef CONFIG_SYSLOG_BUFFER #ifdef CONFIG_SYSLOG_BUFFER
FAR struct lib_syslogstream_s *stream; FAR struct lib_syslogstream_s *stream =
FAR struct iob_s *iob; (FAR struct lib_syslogstream_s *)this;
DEBUGASSERT(this != NULL); DEBUGASSERT(stream != NULL);
stream = (FAR struct lib_syslogstream_s *)this;
iob = stream->iob;
/* Do we have an IO buffer? */ /* Do we have an IO buffer? */
if (iob != NULL) if (stream->iob != NULL)
{ {
/* Yes.. Add the incoming character to the buffer */ /* Is this a linefeed? */
iob->io_data[iob->io_len] = ch; if (ch == '\n')
iob->io_len++;
this->nput++;
/* Is the buffer full? */
if (iob->io_len >= CONFIG_IOB_BUFSIZE)
{ {
/* Yes.. then flush the buffer */ /* Yes... pre-pend carriage return */
syslogstream_flush(stream); syslogstream_addchar(stream, '\r');
} }
/* Add the incoming character to the buffer */
syslogstream_addchar(stream, ch);
} }
else else
#endif #endif