/*
 * connect to postmaster through UNIX domain socket
 */
int connect_unix_domain_socket(int slot, bool retry)
{
	int port;
	char *socket_dir;

	port = pool_config->backend_desc->backend_info[slot].backend_port;
	socket_dir = pool_config->backend_desc->backend_info[slot].backend_hostname;

	return connect_unix_domain_socket_by_port(port, socket_dir, retry);
}
Example #2
0
/*
 * create a persistent connection
 */
POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
	char *hostname, int port, char *dbname, char *user, char *password, bool retry)
{
	POOL_CONNECTION_POOL_SLOT *cp;
	int fd;

#define MAX_USER_AND_DATABASE	1024

	/* V3 startup packet */
	typedef struct {
		int protoVersion;
		char data[MAX_USER_AND_DATABASE];
	} StartupPacket_v3;

	static StartupPacket_v3 *startup_packet;
	int len, len1;
	int status;

	cp = malloc(sizeof(POOL_CONNECTION_POOL_SLOT));
	if (cp == NULL)
	{
		pool_error("make_persistent_db_connection: could not allocate memory");
		return NULL;
	}
	memset(cp, 0, sizeof(POOL_CONNECTION_POOL_SLOT));

	startup_packet = malloc(sizeof(*startup_packet));
	if (startup_packet == NULL)
	{
		pool_error("make_persistent_db_connection: could not allocate memory");
		return NULL;
	}
	memset(startup_packet, 0, sizeof(*startup_packet));
	startup_packet->protoVersion = htonl(0x00030000);	/* set V3 proto major/minor */

	/*
	 * create socket
	 */
	if (*hostname == '/')
	{
		fd = connect_unix_domain_socket_by_port(port, hostname, retry);
	}
	else
	{
		fd = connect_inet_domain_socket_by_port(hostname, port, retry);
	}

	if (fd < 0)
	{
		pool_error("make_persistent_db_connection: connection to %s(%d) failed", hostname, port);
		return NULL;
	}

	cp->con = pool_open(fd);
	cp->closetime = 0;
	cp->con->isbackend = 1;
	pool_ssl_negotiate_clientserver(cp->con);

	/*
	 * build V3 startup packet
	 */
	len = snprintf(startup_packet->data, sizeof(startup_packet->data), "user") + 1;
	len1 = snprintf(&startup_packet->data[len], sizeof(startup_packet->data)-len, "%s", user) + 1;
	if (len1 >= (sizeof(startup_packet->data)-len))
	{
		pool_error("make_persistent_db_connection: too long user name");
		return NULL;
	}

	len += len1;
	len1 = snprintf(&startup_packet->data[len], sizeof(startup_packet->data)-len, "database") + 1;
	if (len1 >= (sizeof(startup_packet->data)-len))
	{
		pool_error("make_persistent_db_connection: too long user name");
		return NULL;
	}

	len += len1;
	len1 = snprintf(&startup_packet->data[len], sizeof(startup_packet->data)-len, "%s", dbname) + 1;
	if (len1 >= (sizeof(startup_packet->data)-len))
	{
		pool_error("make_persistent_db_connection: too long database name");
		return NULL;
	}
	len += len1;
	startup_packet->data[len++] = '\0';

	cp->sp = malloc(sizeof(StartupPacket));
	if (cp->sp == NULL)
	{
		pool_error("make_persistent_db_connection: could not allocate memory");
		return NULL;
	}

	cp->sp->startup_packet = (char *)startup_packet;
	cp->sp->len = len + 4;
	cp->sp->major = 3;
	cp->sp->minor = 0;
	cp->sp->database = strdup(dbname);
	if (cp->sp->database == NULL)
	{
		pool_error("make_persistent_db_connection: could not allocate memory");
		return NULL;
	}
	cp->sp->user = strdup(user);
	if (cp->sp->user == NULL)
	{
		pool_error("make_persistent_db_connection: could not allocate memory");
		return NULL;
	}

	/*
	 * send startup packet
	 */
	status = send_startup_packet(cp);
	if (status)
	{
		pool_error("make_persistent_db_connection: send_startup_packet failed");
		return NULL;
	}

	/*
	 * do authentication
	 */
	if (s_do_auth(cp, password))
	{
		pool_error("make_persistent_db_connection: s_do_auth failed");
		return NULL;
	}

	return cp;
}
Example #3
0
/*
 * system_db_health_check()
 * check if we can connect to the SystemDB
 * returns 0 for OK. otherwise returns -1
 */
int
system_db_health_check(void)
{
    int fd;

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

    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, SYSDB_INFO->user, sizeof(mysp.sp.user) - 1);
    *mysp.sp.options = '\0';
    *mysp.sp.unused = '\0';
    *mysp.sp.tty = '\0';

    ereport(DEBUG1,
            (errmsg("health_check: SystemDB status: %d", SYSDB_STATUS)));

    /* if SystemDB is already down, ignore */
    if (SYSDB_STATUS == CON_UNUSED || SYSDB_STATUS == CON_DOWN)
        return 0;

    if (*SYSDB_INFO->hostname == '/')
        fd = connect_unix_domain_socket_by_port(SYSDB_INFO->port, SYSDB_INFO->hostname, FALSE);
    else
        fd = connect_inet_domain_socket_by_port(SYSDB_INFO->hostname, SYSDB_INFO->port, FALSE);

    if (fd < 0)
    {
        ereport(ERROR,
                (errmsg("SystemDB health check failed"),
                 errdetail("DB host \"%s\" at port %d is down",
                           SYSDB_INFO->hostname,
                           SYSDB_INFO->port)));
    }

    if (write(fd, &mysp, sizeof(mysp)) < 0)
    {
        close(fd);
        ereport(ERROR,
                (errmsg("SystemDB health check failed"),
                 errdetail("Write failed on DB host \"%s\" at port %d is down",
                           SYSDB_INFO->hostname,
                           SYSDB_INFO->port)));
    }

    if(read(fd, &kind, 1) < 0)
        ereport(WARNING,
                (errmsg("SystemDB health read on socket failed")));


    if (write(fd, "X", 1) < 0)
    {
        close(fd);
        ereport(ERROR,
                (errmsg("SystemDB health check failed"),
                 errdetail("Write failed on DB host \"%s\" at port %d is down",
                           SYSDB_INFO->hostname,
                           SYSDB_INFO->port)));
    }

    close(fd);
    return 0;
}
Example #4
0
/*
 * check if we can connect to the SystemDB
 * returns 0 for ok. otherwise returns -1
 */
int
system_db_health_check(void)
{
	int fd;

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

	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, SYSDB_INFO->user, sizeof(mysp.sp.user) - 1);
	*mysp.sp.options = '\0';
	*mysp.sp.unused = '\0';
	*mysp.sp.tty = '\0';

	pool_debug("health_check: SystemDB status: %d", SYSDB_STATUS);

	/* if SystemDB is already down, ignore */
	if (SYSDB_STATUS == CON_UNUSED || SYSDB_STATUS == CON_DOWN)
		return 0;

	if (*SYSDB_INFO->hostname == '\0')
		fd = connect_unix_domain_socket_by_port(SYSDB_INFO->port, pool_config->backend_socket_dir);
	else
		fd = connect_inet_domain_socket_by_port(SYSDB_INFO->hostname, SYSDB_INFO->port);

	if (fd < 0)
	{
		pool_error("health check failed. SystemDB host %s at port %d is down",
				   SYSDB_INFO->hostname,
				   SYSDB_INFO->port);

		return -1;
	}

	if (write(fd, &mysp, sizeof(mysp)) < 0)
	{
		pool_error("health check failed during write. SystemDB host %s at port %d is down",
				   SYSDB_INFO->hostname,
				   SYSDB_INFO->port);
		close(fd);
		return -1;
	}

	read(fd, &kind, 1);

	if (write(fd, "X", 1) < 0)
	{
		pool_error("health check failed during write. SystemDB host %s at port %d is down",
				   SYSDB_INFO->hostname,
				   SYSDB_INFO->port);
		close(fd);
		return -1;
	}

	close(fd);
	return 0;
}