/* * connect to postmaster through INET domain socket */ int connect_inet_domain_socket(int slot, bool retry) { char *host; int port; host = pool_config->backend_desc->backend_info[slot].backend_hostname; port = pool_config->backend_desc->backend_info[slot].backend_port; return connect_inet_domain_socket_by_port(host, port, retry); }
/* * 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; }
/* * 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; }
/* * 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; }