static void process_recovery_request(PCP_CONNECTION *frontend,char *buf) { int wsize; char code[] = "CommandComplete"; int node_id = atoi(buf); if ( (node_id < 0) || (node_id >= pool_config->backend_desc->num_backends) ) ereport(ERROR, (errmsg("process recovery request failed"), errdetail("node id %d is not valid", node_id))); if ((!REPLICATION && !(MASTER_SLAVE && !strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP))) || (MASTER_SLAVE && !strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP) && node_id == PRIMARY_NODE_ID)) { if (MASTER_SLAVE && !strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP)) ereport(ERROR, (errmsg("process recovery request failed"), errdetail("primary server cannot be recovered by online recovery."))); else ereport(ERROR, (errmsg("process recovery request failed"), errdetail("recovery request is accepted only in replication mode or stereaming replication mode."))); } else { if (pcp_mark_recovery_in_progress() == false) ereport(FATAL, (errmsg("process recovery request failed"), errdetail("pgpool-II is already processing another recovery request."))); ereport(DEBUG1, (errmsg("PCP: processing recovery request"), errdetail("start online recovery"))); PG_TRY(); { start_recovery(node_id); finish_recovery(); pcp_write(frontend, "c", 1); wsize = htonl(sizeof(code) + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); do_pcp_flush(frontend); pcp_mark_recovery_finished(); } PG_CATCH(); { finish_recovery(); pcp_mark_recovery_finished(); PG_RE_THROW(); }PG_END_TRY(); } do_pcp_flush(frontend); }
static void process_status_request(PCP_CONNECTION *frontend) { int nrows = 0; int i; POOL_REPORT_CONFIG *status = get_config(&nrows); int len = 0; /* First, send array size of connection_info */ char arr_code[] = "ArraySize"; char code[] = "ProcessConfig"; /* Finally, indicate that all data is sent */ char fin_code[] = "CommandComplete"; pcp_write(frontend, "b", 1); len = htonl(sizeof(arr_code) + sizeof(int) + sizeof(int)); pcp_write(frontend, &len, sizeof(int)); pcp_write(frontend, arr_code, sizeof(arr_code)); len = htonl(nrows); pcp_write(frontend, &len, sizeof(int)); do_pcp_flush(frontend); for (i = 0; i < nrows; i++) { pcp_write(frontend, "b", 1); len = htonl(sizeof(int) + sizeof(code) + strlen(status[i].name) + 1 + strlen(status[i].value) + 1 + strlen(status[i].desc) + 1 ); pcp_write(frontend, &len, sizeof(int)); pcp_write(frontend, code, sizeof(code)); pcp_write(frontend, status[i].name, strlen(status[i].name)+1); pcp_write(frontend, status[i].value, strlen(status[i].value)+1); pcp_write(frontend, status[i].desc, strlen(status[i].desc)+1); } pcp_write(frontend, "b", 1); len = htonl(sizeof(fin_code) + sizeof(int)); pcp_write(frontend, &len, sizeof(int)); pcp_write(frontend, fin_code, sizeof(fin_code)); do_pcp_flush(frontend); pfree(status); ereport(DEBUG1, (errmsg("PCP: processing status request"), errdetail("retrieved status information"))); }
static void process_detach_node(PCP_CONNECTION *frontend,char *buf, char tos) { int node_id; int wsize; char code[] = "CommandComplete"; bool gracefully; if (tos == 'D') gracefully = false; else gracefully = true; node_id = atoi(buf); ereport(DEBUG1, (errmsg("PCP: processing detach node"), errdetail("detaching Node ID %d", node_id))); pool_detach_node(node_id, gracefully); pcp_write(frontend, "d", 1); wsize = htonl(sizeof(code) + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); do_pcp_flush(frontend); }
static void process_set_configration_parameter(PCP_CONNECTION *frontend,char *buf, int len) { char* param_name; char* param_value; int wsize; char code[] = "CommandComplete"; param_name = buf; if(param_name == NULL) ereport(ERROR, (errmsg("PCP: set configuration parameter failed"), errdetail("invalid pcp packet received from client"))); param_value = (char *) memchr(buf, '\0', len); if(param_value == NULL) ereport(ERROR, (errmsg("set configuration parameter failed"), errdetail("invalid pcp packet received from client"))); param_value +=1; ereport(LOG, (errmsg("set configuration parameter, \"%s TO %s\"",param_name,param_value))); if(strcasecmp(param_name, "client_min_messages") == 0) { const char *ordered_valid_values[] = {"debug5","debug4","debug3","debug2","debug1","log","commerror","info","notice","warning","error",NULL}; bool found = false; int i; for(i=0; ; i++) { char* valid_val = (char*)ordered_valid_values[i]; if(!valid_val) break; if (!strcasecmp(param_value, valid_val)) { found = true; pool_config->client_min_messages = i + 10; ereport(DEBUG1, (errmsg("PCP setting parameter \"%s\" to \"%s\"",param_name,param_value))); break; } } if (!found) ereport(ERROR, (errmsg("PCP: set configuration parameter failed"), errdetail("invalid value \"%s\" for parameter \"%s\"",param_value,param_name))); } else ereport(ERROR, (errmsg("PCP: set configuration parameter failed"), errdetail("invalid parameter \"%s\"",param_name))); pcp_write(frontend, "a", 1); wsize = htonl(sizeof(code) + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); do_pcp_flush(frontend); }
static void process_authentication(PCP_CONNECTION *frontend, char *buf, char* salt, int *random_salt) { int wsize; int authenticated; if (*random_salt) { authenticated = user_authenticate(buf, pcp_conf_file, salt, 4); } if (!*random_salt || !authenticated) { ereport(FATAL, (errmsg("authentication failed"), errdetail("username and/or password does not match"))); *random_salt = 0; } else { char code[] = "AuthenticationOK"; pcp_write(frontend, "r", 1); wsize = htonl(sizeof(code) + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); do_pcp_flush(frontend); *random_salt = 0; ereport(DEBUG1, (errmsg("PCP: processing authentication request"), errdetail("authentication OK"))); } }
static void inform_watchdog_info(PCP_CONNECTION *frontend,char *buf) { int wd_index; int wsize; char code[] = "CommandComplete"; char pgpool_port_str[6]; char wd_port_str[6]; char status[2]; WdInfo *wi = NULL; if (!pool_config->use_watchdog) ereport(ERROR, (errmsg("PCP: informing watchdog info failed"), errdetail("watcdhog is not enabled"))); wd_index = atoi(buf); wi = wd_get_watchdog_info(wd_index); if (wi == NULL) ereport(ERROR, (errmsg("PCP: informing watchdog info failed"), errdetail("invalid watchdog index"))); ereport(DEBUG2, (errmsg("PCP: informing watchdog info"), errdetail("retrieved node information from shared memory"))); snprintf(pgpool_port_str, sizeof(pgpool_port_str), "%d", wi->pgpool_port); snprintf(wd_port_str, sizeof(wd_port_str), "%d", wi->wd_port); snprintf(status, sizeof(status), "%d", wi->status); pcp_write(frontend, "w", 1); wsize = htonl(sizeof(code) + strlen(wi->hostname)+1 + strlen(pgpool_port_str)+1 + strlen(wd_port_str)+1 + strlen(status)+1 + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); pcp_write(frontend, wi->hostname, strlen(wi->hostname)+1); pcp_write(frontend, pgpool_port_str, strlen(pgpool_port_str)+1); pcp_write(frontend, wd_port_str, strlen(wd_port_str)+1); pcp_write(frontend, status, strlen(status)+1); do_pcp_flush(frontend); }
static void send_md5salt(PCP_CONNECTION *frontend, char* salt) { int wsize; ereport(DEBUG1, (errmsg("PCP: sending md5 salt to client"))); pool_random_salt(salt); pcp_write(frontend, "m", 1); wsize = htonl(sizeof(int) + 4); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, salt, 4); do_pcp_flush(frontend); }
static void inform_watchdog_info(PCP_CONNECTION *frontend,char *buf) { int wd_index; int json_data_len; int wsize; char code[] = "CommandComplete"; char* json_data; if (!pool_config->use_watchdog) ereport(ERROR, (errmsg("PCP: informing watchdog info failed"), errdetail("watcdhog is not enabled"))); wd_index = atoi(buf); json_data = wd_get_watchdog_nodes(wd_index); if (json_data == NULL) ereport(ERROR, (errmsg("PCP: informing watchdog info failed"), errdetail("invalid watchdog index"))); ereport(DEBUG2, (errmsg("PCP: informing watchdog info"), errdetail("retrieved node information from IPC socket"))); /* * This is the voilation of PCP protocol but I think * in future we should shift to more adaptable protocol for * data transmition. */ json_data_len = strlen(json_data); wsize = htonl(sizeof(code) + json_data_len+ 1 + sizeof(int)); pcp_write(frontend, "w", 1); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); pcp_write(frontend, json_data, json_data_len +1); do_pcp_flush(frontend); pfree(json_data); }
static void process_promote_node(PCP_CONNECTION *frontend, char *buf, char tos) { int node_id; int wsize; char code[] = "CommandComplete"; bool gracefully; if (tos == 'J') gracefully = false; else gracefully = true; node_id = atoi(buf); if ( (node_id < 0) || (node_id >= pool_config->backend_desc->num_backends) ) ereport(ERROR, (errmsg("could not process recovery request"), errdetail("node id %d is not valid", node_id))); /* promoting node is reserved to Streaming Replication */ if (!MASTER_SLAVE || (strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP) != 0)) { ereport(FATAL, (errmsg("invalid pgpool mode for process recovery request"), errdetail("not in streaming replication mode, can't promote node id %d", node_id))); } if (node_id == PRIMARY_NODE_ID) { ereport(FATAL, (errmsg("invalid pgpool mode for process recovery request"), errdetail("specified node is already primary node, can't promote node id %d", node_id))); } ereport(DEBUG1, (errmsg("PCP: processing promote node"), errdetail("promoting Node ID %d", node_id))); pool_promote_node(node_id, gracefully); pcp_write(frontend, "d", 1); wsize = htonl(sizeof(code) + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); do_pcp_flush(frontend); }
static void inform_process_count(PCP_CONNECTION *frontend) { int wsize; int process_count; char process_count_str[16]; int *process_list = NULL; char code[] = "CommandComplete"; char *mesg = NULL; int i; int total_port_len = 0; process_list = pool_get_process_list(&process_count); mesg = (char *)palloc(6*process_count); /* port# is at most 5 characters long (MAX:65535) */ snprintf(process_count_str, sizeof(process_count_str), "%d", process_count); for (i = 0; i < process_count; i++) { char port[6]; snprintf(port, sizeof(port), "%d", process_list[i]); snprintf(mesg+total_port_len, strlen(port)+1, "%s", port); total_port_len += strlen(port)+1; } pcp_write(frontend, "n", 1); wsize = htonl(sizeof(code) + strlen(process_count_str)+1 + total_port_len + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); pcp_write(frontend, process_count_str, strlen(process_count_str)+1); pcp_write(frontend, mesg, total_port_len); do_pcp_flush(frontend); pfree(process_list); pfree(mesg); ereport(DEBUG1, (errmsg("PCP: informing process count"), errdetail("%d process(es) found", process_count))); }
static void inform_node_info(PCP_CONNECTION *frontend,char *buf) { int node_id; int wsize; char port_str[6]; char status[2]; char weight_str[20]; char code[] = "CommandComplete"; BackendInfo *bi = NULL; node_id = atoi(buf); bi = pool_get_node_info(node_id); if (bi == NULL) ereport(ERROR, (errmsg("informing node info failed"), errdetail("invalid node ID"))); ereport(DEBUG2, (errmsg("PCP: informing node info"), errdetail("retrieved node information from shared memory"))); snprintf(port_str, sizeof(port_str), "%d", bi->backend_port); snprintf(status, sizeof(status), "%d", bi->backend_status); snprintf(weight_str, sizeof(weight_str), "%f", bi->backend_weight); pcp_write(frontend, "i", 1); wsize = htonl(sizeof(code) + strlen(bi->backend_hostname)+1 + strlen(port_str)+1 + strlen(status)+1 + strlen(weight_str)+1 + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); pcp_write(frontend, bi->backend_hostname, strlen(bi->backend_hostname)+1); pcp_write(frontend, port_str, strlen(port_str)+1); pcp_write(frontend, status, strlen(status)+1); pcp_write(frontend, weight_str, strlen(weight_str)+1); do_pcp_flush(frontend); }
static void process_shutown_request(PCP_CONNECTION *frontend, char mode) { char code[] = "CommandComplete"; pid_t ppid = getppid(); int sig,len; if (mode == 's') { ereport(DEBUG1, (errmsg("PCP: processing shutdown request"), errdetail("sending SIGTERM to the parent process with PID:%d", ppid))); sig = SIGTERM; } else if (mode == 'f') { ereport(DEBUG1, (errmsg("PCP: processing shutdown request"), errdetail("sending SIGINT to the parent process with PID:%d", ppid))); sig = SIGINT; } else if (mode == 'i') { ereport(DEBUG1, (errmsg("PCP: processing shutdown request"), errdetail("sending SIGQUIT to the parent process with PID:%d", ppid))); sig = SIGQUIT; } else { ereport(ERROR, (errmsg("PCP: error while processing shutdown request"), errdetail("invalid shutdown mode \"%c\"", mode))); } pcp_write(frontend, "t", 1); len = htonl(sizeof(code) + sizeof(int)); pcp_write(frontend, &len, sizeof(int)); pcp_write(frontend, code, sizeof(code)); do_pcp_flush(frontend); pool_signal_parent(sig); }
static void process_attach_node(PCP_CONNECTION *frontend,char *buf) { int node_id; int wsize; char code[] = "CommandComplete"; node_id = atoi(buf); ereport(DEBUG1, (errmsg("PCP: processing attach node"), errdetail("attaching Node ID %d", node_id))); send_failback_request(node_id,true); pcp_write(frontend, "c", 1); wsize = htonl(sizeof(code) + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); do_pcp_flush(frontend); }
static void inform_node_count(PCP_CONNECTION *frontend) { int wsize; char mesg[16]; char code[] = "CommandComplete"; int node_count = pool_get_node_count(); snprintf(mesg, sizeof(mesg), "%d", node_count); pcp_write(frontend, "l", 1); wsize = htonl(sizeof(code) + strlen(mesg)+1 + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); pcp_write(frontend, mesg, strlen(mesg)+1); do_pcp_flush(frontend); ereport(DEBUG1, (errmsg("PCP: informing node count"), errdetail("%d node(s) found", node_count))); }
static void inform_process_info(PCP_CONNECTION *frontend,char *buf) { int proc_id; int wsize; int num_proc = pool_config->num_init_children; int i; proc_id = atoi(buf); if ((proc_id != 0) && (pool_get_process_info(proc_id) == NULL)) { ereport(ERROR, (errmsg("informing process info failed"), errdetail("invalid process ID : %s",buf))); } else { /* First, send array size of connection_info */ char arr_code[] = "ArraySize"; char con_info_size[16]; /* Finally, indicate that all data is sent */ char fin_code[] = "CommandComplete"; POOL_REPORT_POOLS *pools = get_pools(&num_proc); if (proc_id == 0) { snprintf(con_info_size, sizeof(con_info_size), "%d", num_proc); } else { snprintf(con_info_size, sizeof(con_info_size), "%d", pool_config->max_pool * NUM_BACKENDS); } pcp_write(frontend, "p", 1); wsize = htonl(sizeof(arr_code) + strlen(con_info_size)+1 + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, arr_code, sizeof(arr_code)); pcp_write(frontend, con_info_size, strlen(con_info_size)+1); do_pcp_flush(frontend); /* Second, send process information for all connection_info */ for (i=0; i<num_proc; i++) { char code[] = "ProcessInfo"; char proc_pid[16]; char proc_start_time[20]; char proc_create_time[20]; char majorversion[5]; char minorversion[5]; char pool_counter[16]; char backend_id[16]; char backend_pid[16]; char connected[2]; if (proc_id != 0 && proc_id != pools[i].pool_pid) continue; snprintf(proc_pid, sizeof(proc_pid), "%d", pools[i].pool_pid); snprintf(proc_start_time, sizeof(proc_start_time), "%ld", pools[i].start_time); snprintf(proc_create_time, sizeof(proc_create_time), "%ld", pools[i].create_time); snprintf(majorversion, sizeof(majorversion), "%d", pools[i].pool_majorversion); snprintf(minorversion, sizeof(minorversion), "%d", pools[i].pool_minorversion); snprintf(pool_counter, sizeof(pool_counter), "%d", pools[i].pool_counter); snprintf(backend_id, sizeof(backend_pid), "%d", pools[i].backend_id); snprintf(backend_pid, sizeof(backend_pid), "%d", pools[i].pool_backendpid); snprintf(connected, sizeof(connected), "%d", pools[i].pool_connected); pcp_write(frontend, "p", 1); wsize = htonl( sizeof(code) + strlen(proc_pid)+1 + strlen(pools[i].database)+1 + strlen(pools[i].username)+1 + strlen(proc_start_time)+1 + strlen(proc_create_time)+1 + strlen(majorversion)+1 + strlen(minorversion)+1 + strlen(pool_counter)+1 + strlen(backend_id)+1 + strlen(backend_pid)+1 + strlen(connected)+1 + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, code, sizeof(code)); pcp_write(frontend, proc_pid, strlen(proc_pid)+1); pcp_write(frontend, pools[i].database, strlen(pools[i].database)+1); pcp_write(frontend, pools[i].username, strlen(pools[i].username)+1); pcp_write(frontend, proc_start_time, strlen(proc_start_time)+1); pcp_write(frontend, proc_create_time, strlen(proc_create_time)+1); pcp_write(frontend, majorversion, strlen(majorversion)+1); pcp_write(frontend, minorversion, strlen(minorversion)+1); pcp_write(frontend, pool_counter, strlen(pool_counter)+1); pcp_write(frontend, backend_id, strlen(backend_id)+1); pcp_write(frontend, backend_pid, strlen(backend_pid)+1); pcp_write(frontend, connected, strlen(connected)+1); do_pcp_flush(frontend); } pcp_write(frontend, "p", 1); wsize = htonl(sizeof(fin_code) + sizeof(int)); pcp_write(frontend, &wsize, sizeof(int)); pcp_write(frontend, fin_code, sizeof(fin_code)); do_pcp_flush(frontend); ereport(DEBUG1, (errmsg("PCP informing process info"), errdetail("retrieved process information from shared memory"))); pfree(pools); } }