/*
 * Pipe management
 *
 * Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 */

#include <unistd.h>
#include <fcntl.h>

#include <common/config.h>
#include <common/hathreads.h>
#include <common/memory.h>

#include <types/global.h>
#include <types/pipe.h>

DECLARE_STATIC_POOL(pool_head_pipe, "pipe", sizeof(struct pipe));

struct pipe *pipes_live = NULL; /* pipes which are still ready to use */

__decl_spinlock(pipes_lock); /* lock used to protect pipes list */

static THREAD_LOCAL int local_pipes_free = 0;  /* #cache objects   */
static THREAD_LOCAL struct pipe *local_pipes = NULL;

int pipes_used = 0;             /* # of pipes in use (2 fds each) */
int pipes_free = 0;             /* # of pipes unused */

/* return a pre-allocated empty pipe. Try to allocate one if there isn't any
 * left. NULL is returned if a pipe could not be allocated.
 */
struct pipe *get_pipe()
{
	struct pipe *ret = NULL;
	int pipefd[2];

	ret = local_pipes;
	if (likely(ret)) {
		local_pipes = ret->next;
		local_pipes_free--;
		HA_ATOMIC_SUB(&pipes_free, 1);
		HA_ATOMIC_ADD(&pipes_used, 1);
		goto out;
	}

	if (likely(pipes_live)) {
		HA_SPIN_LOCK(PIPES_LOCK, &pipes_lock);
		ret = pipes_live;
		if (likely(ret))
			pipes_live = ret->next;
		HA_SPIN_UNLOCK(PIPES_LOCK, &pipes_lock);
		if (ret) {
			HA_ATOMIC_SUB(&pipes_free, 1);
			HA_ATOMIC_ADD(&pipes_used, 1);
			goto out;
		}
	}

	HA_ATOMIC_ADD(&pipes_used, 1);
	if (pipes_used + pipes_free >= global.maxpipes)
		goto fail;

	ret = pool_alloc(pool_head_pipe);
	if (!ret)
		goto fail;

	if (pipe(pipefd) < 0)
		goto fail;

#ifdef F_SETPIPE_SZ
	if (global.tune.pipesize)
		fcntl(pipefd[0], F_SETPIPE_SZ, global.tune.pipesize);
#endif
	ret->data = 0;
	ret->prod = pipefd[1];
	ret->cons = pipefd[0];
	ret->next = NULL;
 out:
	return ret;
 fail:
	pool_free(pool_head_pipe, ret);
	HA_ATOMIC_SUB(&pipes_used, 1);
	return NULL;

}

/* destroy a pipe, possibly because an error was encountered on it. Its FDs
 * will be closed and it will not be reinjected into the live pool.
 */
void kill_pipe(struct pipe *p)
{
	close(p->prod);
	close(p->cons);
	pool_free(pool_head_pipe, p);
	HA_ATOMIC_SUB(&pipes_used, 1);
}

/* put back a unused pipe into the live pool. If it still has data in it, it is
 * closed and not reinjected into the live pool. The caller is not allowed to
 * use it once released.
 */
void put_pipe(struct pipe *p)
{
	if (unlikely(p->data)) {
		kill_pipe(p);
		return;
	}

	if (likely(local_pipes_free * global.nbthread < global.maxpipes - pipes_used)) {
		p->next = local_pipes;
		local_pipes = p;
		local_pipes_free++;
		goto out;
	}

	HA_SPIN_LOCK(PIPES_LOCK, &pipes_lock);
	p->next = pipes_live;
	pipes_live = p;
	HA_SPIN_UNLOCK(PIPES_LOCK, &pipes_lock);
 out:
	HA_ATOMIC_ADD(&pipes_free, 1);
	HA_ATOMIC_SUB(&pipes_used, 1);
}

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