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 bool
default n default n
config SYSLOG_MAX_CHANNELS
int "Maximum SYSLOG channels"
default 1
---help---
Maximum number of supported SYSLOG channels.
config RAMLOG config RAMLOG
bool "RAM log device support" bool "RAM log device support"
default n default n

View File

@ -48,7 +48,8 @@ extern "C"
*/ */
struct syslog_channel_s; /* Forward reference */ 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 * Public Function Prototypes
@ -216,7 +217,6 @@ int syslog_add_intbuffer(int ch);
* to the SYSLOG device. * to the SYSLOG device.
* *
* Input Parameters: * 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. * force - Use the force() method of the channel vs. the putc() method.
* *
* Returned Value: * Returned Value:
@ -229,8 +229,7 @@ int syslog_add_intbuffer(int ch);
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_SYSLOG_INTBUFFER #ifdef CONFIG_SYSLOG_INTBUFFER
int syslog_flush_intbuffer(FAR const struct syslog_channel_s *channel, int syslog_flush_intbuffer(bool force);
bool force);
#endif #endif
/**************************************************************************** /****************************************************************************

View File

@ -92,7 +92,11 @@ static const struct syslog_channel_s g_default_channel =
/* This is the current syslog channel in use */ /* 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 * Private Functions
@ -135,14 +139,82 @@ static int syslog_default_putc(int ch)
int syslog_channel(FAR const struct syslog_channel_s *channel) int syslog_channel(FAR const struct syslog_channel_s *channel)
{ {
#if (CONFIG_SYSLOG_MAX_CHANNELS != 1)
int i;
#endif
DEBUGASSERT(channel != NULL); DEBUGASSERT(channel != NULL);
if (channel != NULL) if (channel != NULL)
{ {
DEBUGASSERT(channel->sc_putc != NULL && channel->sc_force != 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; 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; return -EINVAL;

View File

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

View File

@ -55,18 +55,29 @@
int syslog_force(int ch) int syslog_force(int ch)
{ {
DEBUGASSERT(g_syslog_channel != NULL && int i;
g_syslog_channel->sc_force != NULL);
#ifdef CONFIG_SYSLOG_INTBUFFER #ifdef CONFIG_SYSLOG_INTBUFFER
/* Flush any characters that may have been added to the interrupt /* Flush any characters that may have been added to the interrupt
* buffer through the emergency channel * buffer through the emergency channel
*/ */
syslog_flush_intbuffer(g_syslog_channel, true); syslog_flush_intbuffer(true);
#endif #endif
/* Then send the character to the emergency channel */ 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);
/* Then send the character to the emergency channel */
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. * to the SYSLOG device.
* *
* Input Parameters: * 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. * force - Use the force() method of the channel vs. the putc() method.
* *
* Returned Value: * Returned Value:
@ -276,41 +275,49 @@ int syslog_add_intbuffer(int ch)
* *
****************************************************************************/ ****************************************************************************/
int syslog_flush_intbuffer(FAR const struct syslog_channel_s *channel, int syslog_flush_intbuffer(bool force)
bool force)
{ {
syslog_putc_t putfunc; syslog_putc_t putfunc;
int ch; int ch;
int ret = OK; int i;
/* Select which putc function to use for this flush */
putfunc = force ? channel->sc_putc : channel->sc_force;
/* This logic is performed with the scheduler disabled to protect from /* This logic is performed with the scheduler disabled to protect from
* concurrent modification by other tasks. * concurrent modification by other tasks.
*/ */
sched_lock(); sched_lock();
do do
{ {
/* Transfer one character to time. This is inefficient, but is /* Transfer one character to time. This is inefficient, but is
* done in this way to: (1) Deal with concurrent modification of * done in this way to: (1) Deal with concurrent modification of
* the interrupt buffer from interrupt activity, (2) Avoid keeper * the interrupt buffer from interrupt activity, (2) Avoid keeper
* interrupts disabled for a long time, and (3) to handler * 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(); 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(); sched_unlock();
return ret;
return ch;
} }
#endif /* CONFIG_SYSLOG_INTBUFFER */ #endif /* CONFIG_SYSLOG_INTBUFFER */

View File

@ -55,7 +55,7 @@
int syslog_putc(int ch) int syslog_putc(int ch)
{ {
DEBUGASSERT(g_syslog_channel != NULL); int i;
/* Is this an attempt to do SYSLOG output from an interrupt handler? */ /* 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()) if (up_interrupt_context())
{ {
/* Buffer the character in the interrupt buffer. /* Buffer the character in the interrupt buffer.
* The interrupt buffer will be flushed before the next normal, * The interrupt buffer will be flushed before the next
* non-interrupt SYSLOG output. * normal,non-interrupt SYSLOG output.
*/ */
return syslog_add_intbuffer(ch); return syslog_add_intbuffer(ch);
@ -76,27 +76,46 @@ int syslog_putc(int ch)
{ {
/* Force the character to the SYSLOG device immediately /* Force the character to the SYSLOG device immediately
* (if possible). * (if possible).
* This means that the interrupt data may not be in synchronization * This means that the interrupt data may not be in
* with output data that may have been buffered by sc_putc(). * 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 else
{ {
DEBUGASSERT(g_syslog_channel->sc_putc != NULL);
#ifdef CONFIG_SYSLOG_INTBUFFER #ifdef CONFIG_SYSLOG_INTBUFFER
/* Flush any characters that may have been added to the interrupt /* Flush any characters that may have been added to the interrupt
* buffer. * buffer.
*/ */
syslog_flush_intbuffer(g_syslog_channel, false); syslog_flush_intbuffer(false);
#endif #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) 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()) if (up_interrupt_context() || sched_idletask())
{ {
@ -70,23 +71,43 @@ static ssize_t syslog_default_write(FAR const char *buffer, size_t buflen)
else else
#endif #endif
{ {
DEBUGASSERT(g_syslog_channel->sc_force != NULL); for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
g_syslog_channel->sc_force(*buffer++); {
if (g_syslog_channel[i] == NULL)
{
break;
}
DEBUGASSERT(g_syslog_channel[i]->sc_force != NULL);
g_syslog_channel[i]->sc_force(*buffer++);
}
} }
} }
} }
#ifdef CONFIG_SYSLOG_WRITE
else if (g_syslog_channel->sc_write)
{
nwritten = g_syslog_channel->sc_write(buffer, buflen);
}
#endif
else else
{ {
for (nwritten = 0; nwritten < buflen; nwritten++) for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
{ {
DEBUGASSERT(g_syslog_channel->sc_putc != NULL); if (g_syslog_channel[i] == NULL)
g_syslog_channel->sc_putc(*buffer++); {
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++)
{
g_syslog_channel[i]->sc_putc(*buffer++);
}
}
} }
} }
@ -122,7 +143,7 @@ ssize_t syslog_write(FAR const char *buffer, size_t buflen)
* buffer. * buffer.
*/ */
syslog_flush_intbuffer(g_syslog_channel, false); syslog_flush_intbuffer(false);
} }
#endif #endif

View File

@ -131,13 +131,31 @@ extern "C"
* channel - Provides the interface to the channel to be used. * channel - Provides the interface to the channel to be used.
* *
* Returned Value: * Returned Value:
* Zero (OK)is returned on success. A negated errno value is returned * Zero (OK) is returned on success. A negated errno value is returned
* on any failure. * on any failure.
* *
****************************************************************************/ ****************************************************************************/
int syslog_channel(FAR const struct syslog_channel_s *channel); 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 * Name: syslog_initialize
* *