Added support for multiple syslog channels.

This commit is contained in:
Fotis Panagiotopoulos 2021-03-13 17:37:19 +02:00 committed by Xiang Xiao
parent dc31b4f1c1
commit f13adbe4bb
9 changed files with 216 additions and 55 deletions

View File

@ -17,6 +17,12 @@ config SYSLOG_WRITE
bool
default n
config SYSLOG_MAX_CHANNELS
int "Maximum SYSLOG channels"
default 1
---help---
Maximum number of supported SYSLOG channels.
config RAMLOG
bool "RAM log device support"
default n

View File

@ -48,7 +48,8 @@ extern "C"
*/
struct syslog_channel_s; /* Forward reference */
EXTERN FAR const struct syslog_channel_s *g_syslog_channel;
EXTERN FAR const struct syslog_channel_s *g_syslog_channel
[CONFIG_SYSLOG_MAX_CHANNELS];
/****************************************************************************
* Public Function Prototypes
@ -216,7 +217,6 @@ int syslog_add_intbuffer(int ch);
* to the SYSLOG device.
*
* Input Parameters:
* channel - The syslog channel to use in performing the flush operation.
* force - Use the force() method of the channel vs. the putc() method.
*
* Returned Value:
@ -229,8 +229,7 @@ int syslog_add_intbuffer(int ch);
****************************************************************************/
#ifdef CONFIG_SYSLOG_INTBUFFER
int syslog_flush_intbuffer(FAR const struct syslog_channel_s *channel,
bool force);
int syslog_flush_intbuffer(bool force);
#endif
/****************************************************************************

View File

@ -92,7 +92,11 @@ static const struct syslog_channel_s g_default_channel =
/* This is the current syslog channel in use */
FAR const struct syslog_channel_s *g_syslog_channel = &g_default_channel;
FAR const struct syslog_channel_s
*g_syslog_channel[CONFIG_SYSLOG_MAX_CHANNELS] =
{
&g_default_channel
};
/****************************************************************************
* Private Functions
@ -135,14 +139,82 @@ static int syslog_default_putc(int ch)
int syslog_channel(FAR const struct syslog_channel_s *channel)
{
#if (CONFIG_SYSLOG_MAX_CHANNELS != 1)
int i;
#endif
DEBUGASSERT(channel != NULL);
if (channel != NULL)
{
DEBUGASSERT(channel->sc_putc != NULL && channel->sc_force != NULL);
g_syslog_channel = channel;
#if (CONFIG_SYSLOG_MAX_CHANNELS == 1)
g_syslog_channel[0] = channel;
return OK;
#else
for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
{
if (g_syslog_channel[i] == NULL)
{
g_syslog_channel[i] = channel;
return OK;
}
else if (g_syslog_channel[i] == channel)
{
return OK;
}
}
#endif
}
return -EINVAL;
}
/****************************************************************************
* Name: syslog_channel_remove
*
* Description:
* Removes an already configured SYSLOG channel from the list of used
* channels.
*
* Input Parameters:
* channel - Provides the interface to the channel to be removed.
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on any failure.
*
****************************************************************************/
int syslog_channel_remove(FAR const struct syslog_channel_s *channel)
{
int i;
DEBUGASSERT(channel != NULL);
if (channel != NULL)
{
for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
{
if (g_syslog_channel[i] == channel)
{
/* Get the rest of the channels one position back
* to ensure that there are no holes in the list.
*/
while (i < (CONFIG_SYSLOG_MAX_CHANNELS - 1) &&
g_syslog_channel[i + 1] != NULL)
{
g_syslog_channel[i] = g_syslog_channel[i + 1];
i++;
}
g_syslog_channel[i] = NULL;
return OK;
}
}
}
return -EINVAL;

View File

@ -64,21 +64,29 @@
int syslog_flush(void)
{
DEBUGASSERT(g_syslog_channel != NULL);
int i;
#ifdef CONFIG_SYSLOG_INTBUFFER
/* Flush any characters that may have been added to the interrupt
* buffer.
*/
syslog_flush_intbuffer(g_syslog_channel, true);
syslog_flush_intbuffer(true);
#endif
for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
{
if (g_syslog_channel[i] == NULL)
{
break;
}
/* Then flush all of the buffered output to the SYSLOG device */
if (g_syslog_channel->sc_flush != NULL)
if (g_syslog_channel[i]->sc_flush != NULL)
{
return g_syslog_channel->sc_flush();
g_syslog_channel[i]->sc_flush();
}
}
return OK;

View File

@ -55,18 +55,29 @@
int syslog_force(int ch)
{
DEBUGASSERT(g_syslog_channel != NULL &&
g_syslog_channel->sc_force != NULL);
int i;
#ifdef CONFIG_SYSLOG_INTBUFFER
/* Flush any characters that may have been added to the interrupt
* buffer through the emergency channel
*/
syslog_flush_intbuffer(g_syslog_channel, true);
syslog_flush_intbuffer(true);
#endif
for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
{
if (g_syslog_channel[i] == NULL)
{
break;
}
DEBUGASSERT(g_syslog_channel[i]->sc_force != NULL);
/* Then send the character to the emergency channel */
return g_syslog_channel->sc_force(ch);
g_syslog_channel[i]->sc_force(ch);
}
return ch;
}

View File

@ -264,7 +264,6 @@ int syslog_add_intbuffer(int ch)
* to the SYSLOG device.
*
* Input Parameters:
* channel - The syslog channel to use in performing the flush operation.
* force - Use the force() method of the channel vs. the putc() method.
*
* Returned Value:
@ -276,41 +275,49 @@ int syslog_add_intbuffer(int ch)
*
****************************************************************************/
int syslog_flush_intbuffer(FAR const struct syslog_channel_s *channel,
bool force)
int syslog_flush_intbuffer(bool force)
{
syslog_putc_t putfunc;
int ch;
int ret = OK;
/* Select which putc function to use for this flush */
putfunc = force ? channel->sc_putc : channel->sc_force;
int i;
/* This logic is performed with the scheduler disabled to protect from
* concurrent modification by other tasks.
*/
sched_lock();
do
{
/* Transfer one character to time. This is inefficient, but is
* done in this way to: (1) Deal with concurrent modification of
* the interrupt buffer from interrupt activity, (2) Avoid keeper
* interrupts disabled for a long time, and (3) to handler
* wraparound of the circular buffer indices.
* wrap-around of the circular buffer indices.
*/
ch = syslog_remove_intbuffer();
if (ch != EOF)
for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
{
ret = putfunc(ch);
if ((g_syslog_channel[i] == NULL) || (ch == EOF))
{
break;
}
/* Select which putc function to use for this flush */
putfunc = force ? g_syslog_channel[i]->sc_putc :
g_syslog_channel[i]->sc_force;
putfunc(ch);
}
}
while (ch != EOF && ret >= 0);
while (ch != EOF);
sched_unlock();
return ret;
return ch;
}
#endif /* CONFIG_SYSLOG_INTBUFFER */

View File

@ -55,7 +55,7 @@
int syslog_putc(int ch)
{
DEBUGASSERT(g_syslog_channel != NULL);
int i;
/* Is this an attempt to do SYSLOG output from an interrupt handler? */
@ -65,8 +65,8 @@ int syslog_putc(int ch)
if (up_interrupt_context())
{
/* Buffer the character in the interrupt buffer.
* The interrupt buffer will be flushed before the next normal,
* non-interrupt SYSLOG output.
* The interrupt buffer will be flushed before the next
* normal,non-interrupt SYSLOG output.
*/
return syslog_add_intbuffer(ch);
@ -76,27 +76,46 @@ int syslog_putc(int ch)
{
/* Force the character to the SYSLOG device immediately
* (if possible).
* This means that the interrupt data may not be in synchronization
* with output data that may have been buffered by sc_putc().
* This means that the interrupt data may not be in
* synchronization with output data that may have been
* buffered by sc_putc().
*/
DEBUGASSERT(g_syslog_channel->sc_force != NULL);
for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
{
if (g_syslog_channel[i] == NULL)
{
break;
}
return g_syslog_channel->sc_force(ch);
DEBUGASSERT(g_syslog_channel[i]->sc_force != NULL);
g_syslog_channel[i]->sc_force(ch);
}
}
}
else
{
DEBUGASSERT(g_syslog_channel->sc_putc != NULL);
#ifdef CONFIG_SYSLOG_INTBUFFER
/* Flush any characters that may have been added to the interrupt
* buffer.
*/
syslog_flush_intbuffer(g_syslog_channel, false);
syslog_flush_intbuffer(false);
#endif
return g_syslog_channel->sc_putc(ch);
for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
{
if (g_syslog_channel[i] == NULL)
{
break;
}
DEBUGASSERT(g_syslog_channel[i]->sc_putc != NULL);
g_syslog_channel[i]->sc_putc(ch);
}
}
return ch;
}

View File

@ -56,7 +56,8 @@
static ssize_t syslog_default_write(FAR const char *buffer, size_t buflen)
{
size_t nwritten;
int i;
size_t nwritten = 0;
if (up_interrupt_context() || sched_idletask())
{
@ -70,23 +71,43 @@ static ssize_t syslog_default_write(FAR const char *buffer, size_t buflen)
else
#endif
{
DEBUGASSERT(g_syslog_channel->sc_force != NULL);
g_syslog_channel->sc_force(*buffer++);
}
}
}
#ifdef CONFIG_SYSLOG_WRITE
else if (g_syslog_channel->sc_write)
for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
{
nwritten = g_syslog_channel->sc_write(buffer, buflen);
if (g_syslog_channel[i] == NULL)
{
break;
}
DEBUGASSERT(g_syslog_channel[i]->sc_force != NULL);
g_syslog_channel[i]->sc_force(*buffer++);
}
}
}
}
#endif
else
{
for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
{
if (g_syslog_channel[i] == NULL)
{
break;
}
#ifdef CONFIG_SYSLOG_WRITE
if (g_syslog_channel[i]->sc_write)
{
nwritten = g_syslog_channel[i]->sc_write(buffer, buflen);
}
else
#endif
{
DEBUGASSERT(g_syslog_channel[i]->sc_putc != NULL);
for (nwritten = 0; nwritten < buflen; nwritten++)
{
DEBUGASSERT(g_syslog_channel->sc_putc != NULL);
g_syslog_channel->sc_putc(*buffer++);
g_syslog_channel[i]->sc_putc(*buffer++);
}
}
}
}
@ -122,7 +143,7 @@ ssize_t syslog_write(FAR const char *buffer, size_t buflen)
* buffer.
*/
syslog_flush_intbuffer(g_syslog_channel, false);
syslog_flush_intbuffer(false);
}
#endif

View File

@ -138,6 +138,24 @@ extern "C"
int syslog_channel(FAR const struct syslog_channel_s *channel);
/****************************************************************************
* Name: syslog_channel_remove
*
* Description:
* Removes an already configured SYSLOG channel from the list of used
* channels.
*
* Input Parameters:
* channel - Provides the interface to the channel to be removed.
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned
* on any failure.
*
****************************************************************************/
int syslog_channel_remove(FAR const struct syslog_channel_s *channel);
/****************************************************************************
* Name: syslog_initialize
*