예제 #1
0
static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp, int secondary_backend)
{
	int fd;

	if (secondary_backend)
	{
		if (*pool_config.secondary_backend_host_name == '\0')
			fd = connect_unix_domain_socket(1);
		else
			fd = connect_inet_domain_socket(1);
	}
	else
	{
		if (*pool_config.current_backend_host_name == '\0')
			fd = connect_unix_domain_socket(0);
		else
			fd = connect_inet_domain_socket(0);
	}

	if (fd < 0)
	{
		/* fatal error, notice to parent and exit */
		notice_backend_error(!secondary_backend);
		exit(1);
	}

	cp->con = pool_open(fd);
	cp->closetime = 0;
	return cp;
}
예제 #2
0
/*
 * create connection pool
 */
static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp, int slot)
{
	BackendInfo *b = &pool_config->backend_desc->backend_info[slot];
	int fd;

	if (*b->backend_hostname == '/')
	{
		fd = connect_unix_domain_socket(slot, TRUE);
	}
	else
	{
		fd = connect_inet_domain_socket(slot, TRUE);
	}

	if (fd < 0)
	{
		pool_error("connection to %s(%d) failed", b->backend_hostname, b->backend_port);
		return NULL;
	}

	cp->sp = NULL;
	cp->con = pool_open(fd);
	cp->closetime = 0;
	return cp;
}
예제 #3
0
/*
 * process cancel request
 */
void cancel_request(CancelPacket *sp)
{
	int	len;
	int fd;
	POOL_CONNECTION *con;
	int i,j,k;
	ConnectionInfo *c = NULL;
	CancelPacket cp;
	bool found = false;

	pool_debug("Cancel request received");

	/* look for cancel key from shmem info */
	for (i=0;i<pool_config->num_init_children;i++)
	{
		for (j=0;j<pool_config->max_pool;j++)
		{
			for (k=0;k<NUM_BACKENDS;k++)
			{
				c = pool_coninfo(i, j, k);
				pool_debug("con_info: address:%p database:%s user:%s pid:%d key:%d i:%d",
						   c, c->database, c->user, ntohl(c->pid), ntohl(c->key),i);

				if (c->pid == sp->pid && c->key == sp->key)
				{
					pool_debug("found pid:%d key:%d i:%d",ntohl(c->pid), ntohl(c->key),i);
					c = pool_coninfo(i, j, 0);
					found = true;
					goto found;
				}
			}
		}
	}

 found:
	if (!found)
	{
		pool_error("cancel_request: invalid cancel key: pid:%d key:%d",ntohl(sp->pid), ntohl(sp->key));
		return;	/* invalid key */
	}

	for (i=0;i<NUM_BACKENDS;i++,c++)
	{
		if (!VALID_BACKEND(i))
			continue;

		if (*(BACKEND_INFO(i).backend_hostname) == '/')
			fd = connect_unix_domain_socket(i, TRUE);
		else
			fd = connect_inet_domain_socket(i, TRUE);

		if (fd < 0)
		{
			pool_error("Could not create socket for sending cancel request for backend %d", i);
			return;
		}

		con = pool_open(fd);
		if (con == NULL)
			return;

		len = htonl(sizeof(len) + sizeof(CancelPacket));
		pool_write(con, &len, sizeof(len));

		cp.protoVersion = sp->protoVersion;
		cp.pid = c->pid;
		cp.key = c->key;

		pool_log("cancel_request: canceling backend pid:%d key: %d", ntohl(cp.pid),ntohl(cp.key));

		if (pool_write_and_flush(con, &cp, sizeof(CancelPacket)) < 0)
			pool_error("Could not send cancel request packet for backend %d", i);

		pool_close(con);

		/*
		 * this is needed to ensure that the next DB node executes the
		 * query supposed to be canceled.
		 */
		sleep(1);
	}
}
예제 #4
0
파일: main.c 프로젝트: machack666/pgpool-II
/*
 * check if we can connect to the backend
 * returns 0 for ok. otherwise returns backend id + 1
 */
int health_check(void)
{
	int fd;
	int sts;

	/* V2 startup packet */
	typedef struct {
		int len;		/* startup packet length */
		StartupPacket_v2 sp;
	} MySp;
	MySp mysp;
	char kind;
	int i;

	if (*InRecovery)
		return 0;

	memset(&mysp, 0, sizeof(mysp));
	mysp.len = htonl(296);
	mysp.sp.protoVersion = htonl(PROTO_MAJOR_V2 << 16);
	strcpy(mysp.sp.database, "template1");
	strncpy(mysp.sp.user, pool_config->health_check_user, sizeof(mysp.sp.user) - 1);
	*mysp.sp.options = '\0';
	*mysp.sp.unused = '\0';
	*mysp.sp.tty = '\0';

	for (i=0;i<pool_config->backend_desc->num_backends;i++)
	{
		pool_debug("health_check: %d th DB node status: %d", i, BACKEND_INFO(i).backend_status);

		if (BACKEND_INFO(i).backend_status == CON_UNUSED ||
			BACKEND_INFO(i).backend_status == CON_DOWN)
			continue;

		if (*(BACKEND_INFO(i).backend_hostname) == '\0')
			fd = connect_unix_domain_socket(i);
		else
			fd = connect_inet_domain_socket(i);

		if (fd < 0)
		{
			pool_error("health check failed. %d th host %s at port %d is down",
					   i,
					   BACKEND_INFO(i).backend_hostname,
					   BACKEND_INFO(i).backend_port);

			return i+1;
		}

		if (write(fd, &mysp, sizeof(mysp)) < 0)
		{
			pool_error("health check failed during write. host %s at port %d is down. reason: %s",
					   BACKEND_INFO(i).backend_hostname,
					   BACKEND_INFO(i).backend_port,
					   strerror(errno));
			close(fd);
			return i+1;
		}

		/*
		 * Don't bother to be blocked by read(2). It will be
		 * interrupted by ALRAM anyway.
		 */
		sts = read(fd, &kind, 1);
		if (sts == -1)
		{
			pool_error("health check failed during read. host %s at port %d is down. reason: %s",
					   BACKEND_INFO(i).backend_hostname,
					   BACKEND_INFO(i).backend_port,
					   strerror(errno));
			close(fd);
			return i+1;
		}
		else if (sts == 0)
		{
			pool_error("health check failed. EOF encountered. host %s at port %d is down",
					   BACKEND_INFO(i).backend_hostname,
					   BACKEND_INFO(i).backend_port);
			close(fd);
			return i+1;
		}

		/*
		 * If a backend raised a FATAL error(max connections error or
		 * starting up error?), do not send a Terminate message.
		 */
		if ((kind != 'E') && (write(fd, "X", 1) < 0))
		{
			pool_error("health check failed during write. host %s at port %d is down. reason: %s. Perhaps wrong health check user?",
					   BACKEND_INFO(i).backend_hostname,
					   BACKEND_INFO(i).backend_port,
					   strerror(errno));
			close(fd);
			return i+1;
		}

		close(fd);
	}

	return 0;
}