/*
 * Event sink management
 *
 * Copyright (C) 2000-2019 Willy Tarreau - w@1wt.eu
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation, version 2.1
 * exclusively.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h>
#include <common/compat.h>
#include <common/config.h>
#include <common/ist.h>
#include <common/mini-clist.h>
#include <proto/log.h>
#include <proto/sink.h>

struct list sink_list = LIST_HEAD_INIT(sink_list);

struct sink *sink_find(const char *name)
{
	struct sink *sink;

	list_for_each_entry(sink, &sink_list, sink_list)
		if (strcmp(sink->name, name) == 0)
			return sink;
	return NULL;
}

/* creates a new sink and adds it to the list, it's still generic and not fully
 * initialized. Returns NULL on allocation failure. If another one already
 * exists with the same name, it will be returned. The caller can detect it as
 * a newly created one has type SINK_TYPE_NEW.
 */
static struct sink *__sink_new(const char *name, const char *desc, enum sink_fmt fmt)
{
	struct sink *sink;

	sink = sink_find(name);
	if (sink)
		goto end;

	sink = malloc(sizeof(*sink));
	if (!sink)
		goto end;

	sink->name = name;
	sink->desc = desc;
	sink->fmt  = fmt;
	sink->type = SINK_TYPE_NEW;
	/* set defaults for syslog ones */
	sink->syslog_facility = 0;
	sink->syslog_minlvl   = 0;
	sink->maxlen = MAX_SYSLOG_LEN;
	/* address will be filled by the caller if needed */
	sink->ctx.fd = -1;
	sink->ctx.dropped = 0;
	HA_RWLOCK_INIT(&sink->ctx.lock);
	LIST_ADDQ(&sink_list, &sink->sink_list);
 end:
	return sink;
}

/* creates a sink called <name> of type FD associated to fd <fd>, format <fmt>,
 * and description <desc>. Returns NULL on allocation failure or conflict.
 * Perfect duplicates are merged (same type, fd, and name).
 */
struct sink *sink_new_fd(const char *name, const char *desc, enum sink_fmt fmt, int fd)
{
	struct sink *sink;

	sink = __sink_new(name, desc, fmt);
	if (!sink || (sink->type == SINK_TYPE_FD && sink->ctx.fd == fd))
		goto end;

	if (sink->type != SINK_TYPE_NEW) {
		sink = NULL;
		goto end;
	}

	/* FD not yet initialized to non-blocking mode.
	 * DON'T DO IT ON A TERMINAL!
	 */
	if (!isatty(fd))
		fcntl(fd, F_SETFL, O_NONBLOCK);
	sink->type = SINK_TYPE_FD;
	sink->ctx.fd = fd;
 end:
	return sink;
}

/* tries to send <nmsg> message parts (up to 8, ignored above) from message
 * array <msg> to sink <sink>. Formating according to the sink's preference is
 * done here. Lost messages are accounted for in the sink's counter.
 */
void sink_write(struct sink *sink, const struct ist msg[], size_t nmsg)
{
	struct iovec iovec[10];
	char short_hdr[4];
	size_t maxlen = sink->maxlen ? sink->maxlen : ~0;
	size_t sent = 0;
	int vec = 0;

	/* keep one char for a possible trailing '\n' in any case */
	maxlen--;

	if (sink->fmt == SINK_FMT_SHORT) {
		short_hdr[0] = '<';
		short_hdr[1] = '0' + sink->syslog_minlvl;
		short_hdr[2] = '>';

		iovec[vec].iov_base = short_hdr;
		iovec[vec].iov_len  = MIN(maxlen, 3);
		maxlen -= iovec[vec].iov_len;
		vec++;
	}

	/* copy the remaining entries from the original message. Skip empty fields and
	 * truncate the whole message to maxlen.
	 */
	while (nmsg && vec < (sizeof(iovec) / sizeof(iovec[0]) - 1)) {
		iovec[vec].iov_base = msg->ptr;
		iovec[vec].iov_len  = MIN(maxlen, msg->len);
		maxlen -= iovec[vec].iov_len;
		if (iovec[vec].iov_len)
			vec++;
		msg++; nmsg--;
	}

	if (sink->type == SINK_TYPE_FD) {
		/* For the FD we always emit the trailing \n. It was already provisioned above. */
		iovec[vec].iov_base = "\n";
		iovec[vec].iov_len  = 1;
		vec++;

		HA_RWLOCK_WRLOCK(LOGSRV_LOCK, &sink->ctx.lock);
		sent = writev(sink->ctx.fd, iovec, vec);
		HA_RWLOCK_WRUNLOCK(LOGSRV_LOCK, &sink->ctx.lock);
		/* sent > 0 if the message was delivered */
	}

	/* account for errors now */
	if (sent <= 0)
		HA_ATOMIC_ADD(&sink->ctx.dropped, 1);
}

static void sink_init()
{
	sink_new_fd("stdout", "standard output (fd#1)", SINK_FMT_RAW, 1);
	sink_new_fd("stderr", "standard output (fd#2)", SINK_FMT_RAW, 2);
}

INITCALL0(STG_REGISTER, sink_init);

/*
 * Local variables:
 *  c-indent-level: 8
 *  c-basic-offset: 8
 * End:
 */
