#include <pthread.h>
-static pthread_mutex_t log_mutex;
-static inline void log_lock(void) { pthread_mutex_lock(&log_mutex); }
-static inline void log_unlock(void) { pthread_mutex_unlock(&log_mutex); }
+static DOMAIN(logging) log_domain;
+#define log_lock() LOCK_DOMAIN(logging, log_domain);
+#define log_unlock() UNLOCK_DOMAIN(logging, log_domain);
-static pthread_t main_thread;
-void main_thread_init(void) { main_thread = pthread_self(); }
-static int main_thread_self(void) { return pthread_equal(pthread_self(), main_thread); }
+static struct log_channel * _Atomic global_logs;
-#else
-
-static inline void log_lock(void) { }
-static inline void log_unlock(void) { }
-void main_thread_init(void) { }
-static int main_thread_self(void) { return 1; }
-
-#endif
+/* Logging flags to validly prepare logging messages */
- static _Atomic uint logging_mask;
+static _Atomic uint logging_flags;
++static _Atomic uint logging_mask = ~0U;
#ifdef HAVE_SYSLOG_H
#include <sys/syslog.h>
* in log(), so it should be written like *L_INFO.
*/
void
-log_commit(int class, buffer *buf)
+log_commit(log_buffer *buf)
{
- struct log_config *l;
+ /* Store the last pointer */
+ buf->pos[LBP__MAX] = buf->buf.pos;
- if (buf->pos == buf->end)
- strcpy(buf->end - 100, " ... <too long>");
+ /* Append the too-long message if too long */
+ if (buf->buf.pos == buf->buf.end)
+#define TOO_LONG " ... <too long>"
+ memcpy(buf->buf.end - sizeof TOO_LONG, TOO_LONG, sizeof TOO_LONG);
+#undef TOO_LONG
- log_lock();
- WALK_LIST(l, *current_log_list)
++ struct log_channel *glogs = atomic_load_explicit(&global_logs, memory_order_acquire);
++ if (!glogs)
++ {
++ static struct log_channel initial_stderr_log = {
++ .rf = &rf_stderr,
++ .mask = ~0,
++ .prepare = BIT32_ALL(LBPP_TERMINAL, LBP_CLASS, LBP_MSG),
++ };
++
++ glogs = &initial_stderr_log;
++ }
++
+ for (
- struct log_channel *l = atomic_load_explicit(&global_logs, memory_order_acquire);
- l;
++ struct log_channel *l = glogs; l;
+ l = atomic_load_explicit(&l->next, memory_order_acquire)
+ )
{
- if (!(l->mask & (1 << class)))
+ uint mask = atomic_load_explicit(&l->mask, memory_order_acquire);
+ if (!(mask & (1 << buf->class)))
continue;
- if (l->fh)
+
+ struct rfile *rf = atomic_load_explicit(&l->rf, memory_order_acquire);
+ sock *sk = atomic_load_explicit(&l->udp_sk, memory_order_acquire);
+
+ if (rf || sk)
{
- if (l->terminal_flag)
- fputs("bird: ", l->fh);
- else if (l->udp_flag)
+ /* Construct the iovec */
+ static char terminal_prefix[] = "bird: ",
+ newline[] = "\n";
+ STATIC_ASSERT(sizeof newline == 2);
+
+ struct iovec iov[LBP__MAX+2];
+ uint iov_count = 0;
+ if (BIT32_TEST(&l->prepare, LBPP_TERMINAL))
+ iov[iov_count++] = (struct iovec) {
+ .iov_base = terminal_prefix,
+ .iov_len = sizeof terminal_prefix - 1,
+ };
+
+ for (uint p = 0; p < LBP__MAX; p++)
+ if (BIT32_TEST(&l->prepare, p))
{
- int pri = LOG_DAEMON | syslog_priorities[class];
- char tbuf[TM_DATETIME_BUFFER_SIZE];
- const char *hostname = (config && config->hostname) ? config->hostname : "<none>";
- const char *fmt = "%b %d %T.%6f";
- if (!tm_format_real_time(tbuf, sizeof(tbuf), fmt, current_real_time()))
- strcpy(tbuf, "<error>");
-
- /* Legacy RFC 3164 format, but with us precision */
- fprintf(l->fh, "<%d>%s %s %s: ", pri, tbuf, hostname, bird_name);
+ off_t sz = buf->pos[p+1] - buf->pos[p];
+ if (sz > 0)
+ iov[iov_count++] = (struct iovec) {
+ .iov_base = buf->pos[p],
+ .iov_len = sz,
+ };
}
- else
- {
- byte tbuf[TM_DATETIME_BUFFER_SIZE];
- const char *fmt = config ? config->tf_log.fmt1 : "%F %T.%3f";
- if (!tm_format_real_time(tbuf, sizeof(tbuf), fmt, current_real_time()))
- strcpy(tbuf, "<error>");
-
- if (l->limit)
- {
- off_t msg_len = strlen(tbuf) + strlen(class_names[class]) +
- (buf->pos - buf->start) + 5;
- if (l->pos < 0)
- l->pos = log_size(l);
+ if (rf)
+ {
+ iov[iov_count++] = (struct iovec) {
+ .iov_base = newline,
+ .iov_len = sizeof newline - 1,
+ };
- if (l->pos + msg_len > l->limit)
- if (log_rotate(l) < 0)
- continue;
+ do {
+ if (rf_writev(rf, iov, iov_count))
+ break;
- l->pos += msg_len;
+ log_lock();
+ rf = atomic_load_explicit(&l->rf, memory_order_acquire);
+ if (rf_writev(rf, iov, iov_count))
+ {
+ log_unlock();
+ break;
}
- fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]);
- }
- fputs(buf->start, l->fh);
- fputc('\n', l->fh);
- fflush(l->fh);
+ log_rotate(l);
+ log_unlock();
+
+ rf = atomic_load_explicit(&l->rf, memory_order_relaxed);
+ } while (!rf_writev(rf, iov, iov_count));
+ }
+ else if (sk)
+ {
+ while ((writev(sk->fd, iov, iov_count) < 0) && (errno == EINTR))
+ ;
+ /* FIXME: Silently ignoring write errors */
+ }
}
#ifdef HAVE_SYSLOG_H
else