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; }
/* * 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; }
/* * 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); } }
/* * 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; }