/*
 * dsyslog - a dumb syslog (e.g. syslog for people who have a clue)
 * Copyright (c) 2008 William Pitcock <nenolod@sacredspiral.co.uk>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "dsyslog.h"

static GQueue *event_queue_ = NULL;
static GStaticMutex event_mutex = G_STATIC_MUTEX_INIT;

static gchar *
get_node_name(void)
{
	gchar *out, *outp;

	_ENTER;

	out = g_strdup(g_get_host_name());
	outp = strchr(out, '.');
	if (outp != NULL)
		*outp = '\0';

	_LEAVE out;
}

void
dsyslog_event_dispatch(gint logcode, gchar *datestamp, gchar *source, gchar *program, gint pid, gchar *message)
{
	dsyslog_event_t *event;
	static gulong counter = 1;

	_ENTER;

	_DEBUG("logcode(%d) datestamp<%s> source<%s> program<%s> message<%s>", logcode, datestamp, source, program, message);

	event = g_slice_new(dsyslog_event_t);
	event->uid = counter++;
	event->logcode = logcode;
	event->datestamp = g_strdup(datestamp);
	event->source = source ? g_strdup(source) : get_node_name();
	event->program = g_strdup(program);
	event->pid = pid;
	event->message = g_strdup(message);

	g_static_mutex_lock(&event_mutex);
	g_queue_push_tail(event_queue_, event);
	g_static_mutex_unlock(&event_mutex);

	dsyslog_perfctr.msg_tot++;

	_LEAVE;
}

void
dsyslog_event_delete(dsyslog_event_t *event)
{
	_ENTER;

	_DEBUG("event [%p]");

	g_free(event->message);
	g_free(event->program);
	g_free(event->source);
	g_free(event->datestamp);
	g_slice_free(dsyslog_event_t, event);

	_LEAVE;
}

static gboolean
dsyslog_process_queue_cb(gpointer unused)
{
	dsyslog_event_t *event;

	_ENTER;

	/* TODO: hand off to filter code and output code once it's written. */
	while ((event = g_queue_pop_head(event_queue_)) != NULL) {
		_DEBUG("processing event [%p]", event);

		if (!dsyslog_filter_process(event)) {
			dsyslog_event_delete(event);
			dsyslog_perfctr.dropped++;
			continue;
		}

		dsyslog_output_process(event);
		dsyslog_event_delete(event);
	}

	_LEAVE TRUE;	
}

void
dsyslog_event_init(void)
{
	_ENTER;

	event_queue_ = g_queue_new();
	g_timeout_add(250, dsyslog_process_queue_cb, NULL);

	_LEAVE;
}
