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_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_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"))); } }
/* -------------------------------- * pcp_node_info - get information of node pointed by given argument * * return structure of node information on success, -1 otherwise * -------------------------------- */ PCPResultInfo * pcp_node_info(PCPConnInfo* pcpConn, int nid) { int wsize; char node_id[16]; if(PCPConnectionStatus(pcpConn) != PCP_CONNECTION_OK) { pcp_internal_error(pcpConn, "invalid PCP connection"); return NULL; } snprintf(node_id, sizeof(node_id), "%d", nid); pcp_write(pcpConn->pcpConn, "I", 1); wsize = htonl(strlen(node_id)+1 + sizeof(int)); pcp_write(pcpConn->pcpConn, &wsize, sizeof(int)); pcp_write(pcpConn->pcpConn, node_id, strlen(node_id)+1); if (PCPFlush(pcpConn) < 0) return NULL; if(pcpConn->Pfdebug) fprintf(pcpConn->Pfdebug,"DEBUG: send: tos=\"I\", len=%d\n", ntohl(wsize)); return process_pcp_response(pcpConn,'I'); }
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 PCPResultInfo * _pcp_promote_node(PCPConnInfo* pcpConn,int nid, bool gracefully) { int wsize; char node_id[16]; char *sendchar; if(PCPConnectionStatus(pcpConn) != PCP_CONNECTION_OK) { pcp_internal_error(pcpConn,"invalid PCP connection"); return NULL; } snprintf(node_id, sizeof(node_id), "%d", nid); if (gracefully) sendchar = "j"; else sendchar = "J"; pcp_write(pcpConn->pcpConn, sendchar, 1); wsize = htonl(strlen(node_id)+1 + sizeof(int)); pcp_write(pcpConn->pcpConn, &wsize, sizeof(int)); pcp_write(pcpConn->pcpConn, node_id, strlen(node_id)+1); if (PCPFlush(pcpConn) < 0) return NULL; if(pcpConn->Pfdebug) fprintf(pcpConn->Pfdebug,"DEBUG: send: tos=\"E\", len=%d\n", ntohl(wsize)); return process_pcp_response(pcpConn, 'J'); }
/* -------------------------------- * pcp_terminate_pgpool - send terminate packet * * return 0 on success, -1 otherwise * -------------------------------- */ int pcp_terminate_pgpool(char mode) { int wsize; if (pc == NULL) { if (debug) fprintf(stderr, "DEBUG: connection does not exist\n"); errorcode = NOCONNERR; return -1; } pcp_write(pc, "T", 1); wsize = htonl(sizeof(int) + sizeof(char)); pcp_write(pc, &wsize, sizeof(int)); pcp_write(pc, &mode, sizeof(char)); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return -1; } if (debug) fprintf(stderr, "DEBUG: send: tos=\"T\", len=%d\n", ntohl(wsize)); return 0; }
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 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_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 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))); }
int send_to_pcp_frontend(char* data, int len, bool flush) { int ret; if (processType != PT_PCP_WORKER || pcp_frontend == NULL) return -1; ret = pcp_write(pcp_frontend, data, len); if (flush && !ret) ret = pcp_flush(pcp_frontend); return ret; }
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); }
PCPResultInfo* pcp_pool_status(PCPConnInfo *pcpConn) { int wsize; if(PCPConnectionStatus(pcpConn) != PCP_CONNECTION_OK) { pcp_internal_error(pcpConn,"invalid PCP connection"); return NULL; } pcp_write(pcpConn->pcpConn, "B", 1); wsize = htonl(sizeof(int)); pcp_write(pcpConn->pcpConn, &wsize, sizeof(int)); if (PCPFlush(pcpConn) < 0) return NULL; if (pcpConn->Pfdebug) fprintf(pcpConn->Pfdebug, "DEBUG pcp_pool_status: send: tos=\"B\", len=%d\n", ntohl(wsize)); return process_pcp_response(pcpConn, 'B'); }
/* -------------------------------- * pcp_terminate_pgpool - send terminate packet * * return 0 on success, -1 otherwise * -------------------------------- */ PCPResultInfo *pcp_terminate_pgpool(PCPConnInfo* pcpConn, char mode) { int wsize; if(PCPConnectionStatus(pcpConn) != PCP_CONNECTION_OK) { pcp_internal_error(pcpConn,"invalid PCP connection"); return NULL; } pcp_write(pcpConn->pcpConn, "T", 1); wsize = htonl(sizeof(int) + sizeof(char)); pcp_write(pcpConn->pcpConn, &wsize, sizeof(int)); pcp_write(pcpConn->pcpConn, &mode, sizeof(char)); if (PCPFlush(pcpConn) < 0) return NULL; if(pcpConn->Pfdebug) fprintf(pcpConn->Pfdebug,"DEBUG: send: tos=\"T\", len=%d\n", ntohl(wsize)); return process_pcp_response(pcpConn, 'T'); }
PCPResultInfo * pcp_set_backend_parameter(PCPConnInfo* pcpConn,char* parameter_name, char* value) { int wsize; char null_chr = 0; if(PCPConnectionStatus(pcpConn) != PCP_CONNECTION_OK) { pcp_internal_error(pcpConn,"invalid PCP connection"); return NULL; } if(pcpConn->Pfdebug) fprintf(pcpConn->Pfdebug,"DEBUG: seting: \"%s = %s\"\n", parameter_name,value); pcp_write(pcpConn->pcpConn, "A", 1); wsize = htonl(strlen(parameter_name) + 1 + strlen(value) + 1 + sizeof(int)); pcp_write(pcpConn->pcpConn, &wsize, sizeof(int)); pcp_write(pcpConn->pcpConn, parameter_name, strlen(parameter_name)); pcp_write(pcpConn->pcpConn, &null_chr, 1); pcp_write(pcpConn->pcpConn, value, strlen(value)); pcp_write(pcpConn->pcpConn, &null_chr, 1); if (PCPFlush(pcpConn) < 0) return NULL; if(pcpConn->Pfdebug) fprintf(pcpConn->Pfdebug,"DEBUG: send: tos=\"A\", len=%d\n", ntohl(wsize)); return process_pcp_response(pcpConn,'A'); }
/* -------------------------------- * pcp_disconnect - close connection to pgpool * -------------------------------- */ void pcp_disconnect(PCPConnInfo* pcpConn) { int wsize; if(PCPConnectionStatus(pcpConn) != PCP_CONNECTION_OK) { pcp_internal_error(pcpConn,"invalid PCP connection"); return; } pcp_write(pcpConn->pcpConn, "X", 1); wsize = htonl(sizeof(int)); pcp_write(pcpConn->pcpConn, &wsize, sizeof(int)); if (PCPFlush(pcpConn) < 0) return; if(pcpConn->Pfdebug) fprintf(pcpConn->Pfdebug, "DEBUG: send: tos=\"X\", len=%d\n", (int) sizeof(int)); pcp_close(pcpConn->pcpConn); pcpConn->connState = PCP_CONNECTION_NOT_CONNECTED; pcpConn->pcpConn = NULL; }
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))); }
/* -------------------------------- * pcp_disconnect - close connection to pgpool * -------------------------------- */ void pcp_disconnect(void) { int wsize; if (pc == NULL) { if (debug) fprintf(stderr, "DEBUG: connection does not exist\n"); return; } pcp_write(pc, "X", 1); wsize = htonl(sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); if (pcp_flush(pc) < 0) { /* backend had closed connection already */ } if (debug) fprintf(stderr, "DEBUG: send: tos=\"X\", len=%d\n", (int) sizeof(int)); pcp_close(pc); pc = NULL; }
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 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); }
/* -------------------------------- * pcp_systemdb_info - get information of system DB * * return structure of system DB information on success, -1 otherwise * -------------------------------- */ SystemDBInfo * pcp_systemdb_info(void) { char tos; char *buf = NULL; int wsize; int rsize; SystemDBInfo *systemdb_info = NULL; int offset = 0; if (pc == NULL) { if (debug) fprintf(stderr, "DEBUG: connection does not exist\n"); errorcode = NOCONNERR; return NULL; } pcp_write(pc, "S", 1); wsize = htonl(sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return NULL; } if (debug) fprintf(stderr, "DEBUG: send: tos=\"S\", len=%d\n", ntohl(wsize)); while (1) { if (pcp_read(pc, &tos, 1)) return NULL; if (pcp_read(pc, &rsize, sizeof(int))) return NULL; rsize = ntohl(rsize); buf = (char *)malloc(rsize); if (buf == NULL) { errorcode = NOMEMERR; return NULL; } if (pcp_read(pc, buf, rsize - sizeof(int))) { free(buf); return NULL; } if (debug) fprintf(stderr, "DEBUG: recv: tos=\"%c\", len=%d, data=%s\n", tos, rsize, buf); if (tos == 'e') { if (debug) fprintf(stderr, "DEBUG: command failed. reason=%s\n", buf); free(buf); errorcode = BACKENDERR; return NULL; } else if (tos == 's') { char *index; if (strcmp(buf, "SystemDBInfo") == 0) { systemdb_info = (SystemDBInfo *)malloc(sizeof(SystemDBInfo)); if (systemdb_info == NULL) { free(buf); errorcode = NOMEMERR; return NULL; } index = (char *) memchr(buf, '\0', rsize) + 1; if (index != NULL) systemdb_info->hostname = strdup(index); if (systemdb_info->hostname == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) systemdb_info->port = atoi(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) systemdb_info->user = strdup(index); if (systemdb_info->user == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) systemdb_info->password = strdup(index); if (systemdb_info->password == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) systemdb_info->schema_name = strdup(index); if (systemdb_info->schema_name == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) systemdb_info->database_name = strdup(index); if (systemdb_info->database_name == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) systemdb_info->dist_def_num = atoi(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) systemdb_info->system_db_status = atoi(index); if (systemdb_info->dist_def_num > 0) { systemdb_info->dist_def_slot = NULL; systemdb_info->dist_def_slot = (DistDefInfo *)malloc(sizeof(DistDefInfo) * systemdb_info->dist_def_num); if (systemdb_info->dist_def_slot == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } } } else if (strcmp(buf, "DistDefInfo") == 0) { DistDefInfo *dist_def_info = NULL; int i; dist_def_info = (DistDefInfo *)malloc(sizeof(DistDefInfo)); if (dist_def_info == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } index = (char *) memchr(buf, '\0', rsize) + 1; if (index != NULL) dist_def_info->dbname = strdup(index); if (dist_def_info->dbname == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) dist_def_info->schema_name = strdup(index); if (dist_def_info->schema_name == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) dist_def_info->table_name = strdup(index); if (dist_def_info->table_name == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) dist_def_info->dist_key_col_name = strdup(index); if (dist_def_info->dist_key_col_name == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) dist_def_info->col_num = atoi(index); dist_def_info->col_list = NULL; dist_def_info->col_list = (char **)malloc(sizeof(char *) * dist_def_info->col_num); if (dist_def_info->col_list == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } for (i = 0; i < dist_def_info->col_num; i++) { index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) dist_def_info->col_list[i] = strdup(index); if (dist_def_info->col_list[i] == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } } dist_def_info->type_list = NULL; dist_def_info->type_list = (char **)malloc(sizeof(char *) * dist_def_info->col_num); if (dist_def_info->type_list == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } for (i = 0; i < dist_def_info->col_num; i++) { index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) dist_def_info->type_list[i] = strdup(index); if (dist_def_info->type_list[i] == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } } index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) dist_def_info->dist_def_func = strdup(index); if (dist_def_info->dist_def_func == NULL) { free(buf); free_systemdb_info(systemdb_info); errorcode = NOMEMERR; return NULL; } memcpy(&systemdb_info->dist_def_slot[offset++], dist_def_info, sizeof(DistDefInfo)); } else if (strcmp(buf, "CommandComplete") == 0) { free(buf); return systemdb_info; } else { /* never reached */ } } } free(buf); return NULL; }
/* -------------------------------- * pcp_node_count - get number of nodes currently connected to pgpool * * return array of pids on success, NULL otherwise * -------------------------------- */ int * pcp_process_count(int *pnum) { char tos; char *buf = NULL; int wsize; int rsize; if (pc == NULL) { if (debug) fprintf(stderr, "DEBUG: connection does not exist\n"); errorcode = NOCONNERR; return NULL; } pcp_write(pc, "N", 1); wsize = htonl(sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return NULL; } if (debug) fprintf(stderr, "DEBUG: send: tos=\"N\", len=%d\n", ntohl(wsize)); if (pcp_read(pc, &tos, 1)) return NULL; if (pcp_read(pc, &rsize, sizeof(int))) return NULL; rsize = ntohl(rsize); buf = (char *)malloc(rsize); if (buf == NULL) { errorcode = NOMEMERR; return NULL; } if (pcp_read(pc, buf, rsize - sizeof(int))) { free(buf); return NULL; } if (debug) fprintf(stderr, "DEBUG: recv: tos=\"%c\", len=%d, data=%s\n", tos, rsize, buf); if (tos == 'e') { if (debug) fprintf(stderr, "DEBUG: command failed. reason=%s\n", buf); free(buf); errorcode = BACKENDERR; return NULL; } else if (tos == 'n') { if (strcmp(buf, "CommandComplete") == 0) { int process_count; int *process_list = NULL; char *index = NULL; int i; index = (char *) memchr(buf, '\0', rsize) + 1; process_count = atoi(index); process_list = (int *)malloc(sizeof(int) * process_count); if (process_list == NULL) { free(buf); errorcode = NOMEMERR; return NULL; } for (i = 0; i < process_count; i++) { index = (char *) memchr(index, '\0', rsize) + 1; process_list[i] = atoi(index); } *pnum = process_count; free(buf); return process_list; } } free(buf); return NULL; }
/* -------------------------------- * pcp_process_info - get information of node pointed by given argument * * return structure of process information on success, -1 otherwise * -------------------------------- */ ProcessInfo * pcp_process_info(int pid, int *array_size) { int wsize; char process_id[16]; char tos; char *buf = NULL; int rsize; ProcessInfo *process_info = NULL; ConnectionInfo *conn_info = NULL; int ci_size = 0; int offset = 0; if (pc == NULL) { if (debug) fprintf(stderr, "DEBUG: connection does not exist\n"); errorcode = NOCONNERR; return NULL; } snprintf(process_id, sizeof(process_id), "%d", pid); pcp_write(pc, "P", 1); wsize = htonl(strlen(process_id)+1 + sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); pcp_write(pc, process_id, strlen(process_id)+1); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return NULL; } if (debug) fprintf(stderr, "DEBUG: send: tos=\"P\", len=%d\n", ntohl(wsize)); while (1) { if (pcp_read(pc, &tos, 1)) return NULL; if (pcp_read(pc, &rsize, sizeof(int))) return NULL; rsize = ntohl(rsize); buf = (char *)malloc(rsize); if (buf == NULL) { errorcode = NOMEMERR; return NULL; } if (pcp_read(pc, buf, rsize - sizeof(int))) { free(buf); return NULL; } if (debug) fprintf(stderr, "DEBUG: recv: tos=\"%c\", len=%d, data=%s\n", tos, rsize, buf); if (tos == 'e') { if (debug) fprintf(stderr, "DEBUG: command failed. reason=%s\n", buf); free(buf); errorcode = BACKENDERR; return NULL; } else if (tos == 'p') { char *index; if (strcmp(buf, "ArraySize") == 0) { index = (char *) memchr(buf, '\0', rsize) + 1; if (index != NULL) ci_size = atoi(index); *array_size = ci_size; process_info = (ProcessInfo *)malloc(sizeof(ProcessInfo) * ci_size); if (process_info == NULL) { free(buf); errorcode = NOMEMERR; return NULL; } conn_info = (ConnectionInfo *)malloc(sizeof(ConnectionInfo) * ci_size); if (conn_info == NULL) { free(buf); free(process_info); errorcode = NOMEMERR; return NULL; } continue; } else if (strcmp(buf, "ProcessInfo") == 0) { process_info[offset].connection_info = &conn_info[offset]; index = (char *) memchr(buf, '\0', rsize) + 1; if (index != NULL) process_info[offset].pid = atoi(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) strcpy(process_info[offset].connection_info->database, index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) strcpy(process_info[offset].connection_info->user, index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) process_info[offset].start_time = atol(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) process_info[offset].connection_info->create_time = atol(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) process_info[offset].connection_info->major = atoi(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) process_info[offset].connection_info->minor = atoi(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) process_info[offset].connection_info->counter = atoi(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) process_info[offset].connection_info->backend_id = atoi(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) process_info[offset].connection_info->pid = atoi(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) process_info[offset].connection_info->connected = atoi(index); offset++; } else if (strcmp(buf, "CommandComplete") == 0) { free(buf); return process_info; } else { /* never reached */ } } } free(buf); return NULL; }
/* -------------------------------- * pcp_node_info - get information of node pointed by given argument * * return structure of node information on success, -1 otherwise * -------------------------------- */ BackendInfo * pcp_node_info(int nid) { int wsize; char node_id[16]; char tos; char *buf = NULL; int rsize; if (pc == NULL) { if (debug) fprintf(stderr, "DEBUG: connection does not exist\n"); errorcode = NOCONNERR; return NULL; } snprintf(node_id, sizeof(node_id), "%d", nid); pcp_write(pc, "I", 1); wsize = htonl(strlen(node_id)+1 + sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); pcp_write(pc, node_id, strlen(node_id)+1); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return NULL; } if (debug) fprintf(stderr, "DEBUG: send: tos=\"I\", len=%d\n", ntohl(wsize)); if (pcp_read(pc, &tos, 1)) return NULL; if (pcp_read(pc, &rsize, sizeof(int))) return NULL; rsize = ntohl(rsize); buf = (char *)malloc(rsize); if (buf == NULL) { errorcode = NOMEMERR; return NULL; } if (pcp_read(pc, buf, rsize - sizeof(int))) { free(buf); return NULL; } if (debug) fprintf(stderr, "DEBUG: recv: tos=\"%c\", len=%d, data=%s\n", tos, rsize, buf); if (tos == 'e') { if (debug) fprintf(stderr, "DEBUG: command failed. reason=%s\n", buf); errorcode = BACKENDERR; free(buf); return NULL; } else if (tos == 'i') { if (strcmp(buf, "CommandComplete") == 0) { char *index = NULL; BackendInfo* backend_info = NULL; backend_info = (BackendInfo *)malloc(sizeof(BackendInfo)); if (backend_info == NULL) { errorcode = NOMEMERR; free(buf); return NULL; } index = (char *) memchr(buf, '\0', rsize) + 1; if (index != NULL) strcpy(backend_info->backend_hostname, index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) backend_info->backend_port = atoi(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) backend_info->backend_status = atoi(index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) backend_info->backend_weight = atof(index); free(buf); return backend_info; } } free(buf); return NULL; }
/* -------------------------------- * pcp_node_count - get number of nodes currently connected to pgpool * * return array of node IDs on success, -1 otherwise * -------------------------------- */ int pcp_node_count(void) { char tos; char *buf = NULL; int wsize; int rsize; char *index = NULL; if (pc == NULL) { if (debug) fprintf(stderr, "DEBUG: connection does not exist\n"); errorcode = NOCONNERR; return -1; } pcp_write(pc, "L", 1); wsize = htonl(sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return -1; } if (debug) fprintf(stderr, "DEBUG: send: tos=\"L\", len=%d\n", ntohl(wsize)); if (pcp_read(pc, &tos, 1)) return -1; if (pcp_read(pc, &rsize, sizeof(int))) return -1; rsize = ntohl(rsize); buf = (char *)malloc(rsize); if (buf == NULL) { errorcode = NOMEMERR; return -1; } if (pcp_read(pc, buf, rsize - sizeof(int))) { free(buf); return -1; } if (debug) fprintf(stderr, "DEBUG: recv: tos=\"%c\", len=%d, data=%s\n", tos, rsize, buf); if (tos == 'e') { if (debug) fprintf(stderr, "DEBUG: command failed. reason=%s\n", buf); errorcode = BACKENDERR; } else if (tos == 'l') { if (strcmp(buf, "CommandComplete") == 0) { index = (char *) memchr(buf, '\0', rsize) + 1; if (index != NULL) { int ret = atoi(index); free(buf); return ret; } } } free(buf); return -1; }
/* -------------------------------- * pcp_pool_status - return setup parameters and status * * returns and array of POOL_REPORT_CONFIG, NULL otherwise * -------------------------------- */ POOL_REPORT_CONFIG* pcp_pool_status(int *array_size) { char tos; char *buf = NULL; int wsize; int rsize; POOL_REPORT_CONFIG *status = NULL; int ci_size = 0; int offset = 0; if (pc == NULL) { if (debug) fprintf(stderr, "DEBUG: connection does not exist\n"); errorcode = NOCONNERR; return NULL; } pcp_write(pc, "B", 1); wsize = htonl(sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return NULL; } if (debug) fprintf(stderr, "DEBUG pcp_pool_status: send: tos=\"B\", len=%d\n", ntohl(wsize)); while (1) { if (pcp_read(pc, &tos, 1)) return NULL; if (pcp_read(pc, &rsize, sizeof(int))) return NULL; rsize = ntohl(rsize); buf = (char *)malloc(rsize); if (buf == NULL) { errorcode = NOMEMERR; return NULL; } if (pcp_read(pc, buf, rsize - sizeof(int))) { free(buf); return NULL; } if (debug) fprintf(stderr, "DEBUG: recv: tos=\"%c\", len=%d, data=%s\n", tos, rsize, buf); if (tos == 'e') { if (debug) fprintf(stderr, "DEBUG: command failed. reason=%s\n", buf); free(buf); errorcode = BACKENDERR; return NULL; } else if (tos == 'b') { char *index; if (strcmp(buf, "ArraySize") == 0) { index = (char *) memchr(buf, '\0', rsize) + 1; ci_size = ntohl(*((int *)index)); *array_size = ci_size; status = (POOL_REPORT_CONFIG *) malloc(ci_size * sizeof(POOL_REPORT_CONFIG)); continue; } else if (strcmp(buf, "ProcessConfig") == 0) { index = (char *) memchr(buf, '\0', rsize) + 1; if (index != NULL) strcpy(status[offset].name, index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) strcpy(status[offset].value, index); index = (char *) memchr(index, '\0', rsize) + 1; if (index != NULL) strcpy(status[offset].desc, index); offset++; } else if (strcmp(buf, "CommandComplete") == 0) { free(buf); return status; } else { /* never reached */ } } } free(buf); return NULL; }
static int _pcp_promote_node(int nid, bool gracefully) { int wsize; char node_id[16]; char tos; char *buf = NULL; int rsize; char *sendchar; if (pc == NULL) { if (debug) fprintf(stderr, "DEBUG: connection does not exist\n"); errorcode = NOCONNERR; return -1; } snprintf(node_id, sizeof(node_id), "%d", nid); if (gracefully) sendchar = "j"; else sendchar = "J"; pcp_write(pc, sendchar, 1); wsize = htonl(strlen(node_id)+1 + sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); pcp_write(pc, node_id, strlen(node_id)+1); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return -1; } if (debug) fprintf(stderr, "DEBUG: send: tos=\"E\", len=%d\n", ntohl(wsize)); if (pcp_read(pc, &tos, 1)) return -1; if (pcp_read(pc, &rsize, sizeof(int))) return -1; rsize = ntohl(rsize); buf = (char *)malloc(rsize); if (buf == NULL) { errorcode = NOMEMERR; return -1; } if (pcp_read(pc, buf, rsize - sizeof(int))) { free(buf); return -1; } if (debug) fprintf(stderr, "DEBUG: recv: tos=\"%c\", len=%d, data=%s\n", tos, rsize, buf); if (tos == 'e') { if (debug) fprintf(stderr, "DEBUG: command failed. reason=%s\n", buf); errorcode = BACKENDERR; } else if (tos == 'd') { /* strcmp() for success message, or fail */ if(strcmp(buf, "CommandComplete") == 0) { free(buf); return 0; } } free(buf); return -1; }
/* -------------------------------- * pcp_authorize - authenticate with pgpool using username and password * * return 0 on success, -1 otherwise * -------------------------------- */ static int pcp_authorize(char *username, char *password) { char tos; char *buf = NULL; int wsize; int rsize; char salt[4]; char encrypt_buf[(MD5_PASSWD_LEN+1)*2]; char md5[MD5_PASSWD_LEN+1]; /* request salt */ pcp_write(pc, "M", 1); wsize = htonl(sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return -1; } if (pcp_read(pc, &tos, 1)) return -1; if (pcp_read(pc, &rsize, sizeof(int))) return -1; rsize = ntohl(rsize); buf = (char *)malloc(rsize); if (buf == NULL) { errorcode = NOMEMERR; return -1; } if (pcp_read(pc, buf, rsize - sizeof(int))) return -1; memcpy(salt, buf, 4); free(buf); /* encrypt password */ pool_md5_hash(password, strlen(password), md5); md5[MD5_PASSWD_LEN] = '\0'; pool_md5_encrypt(md5, username, strlen(username), encrypt_buf + MD5_PASSWD_LEN + 1); encrypt_buf[(MD5_PASSWD_LEN+1)*2-1] = '\0'; pool_md5_encrypt(encrypt_buf+MD5_PASSWD_LEN+1, salt, 4, encrypt_buf); encrypt_buf[MD5_PASSWD_LEN] = '\0'; pcp_write(pc, "R", 1); wsize = htonl((strlen(username)+1 + strlen(encrypt_buf)+1) + sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); pcp_write(pc, username, strlen(username)+1); pcp_write(pc, encrypt_buf, strlen(encrypt_buf)+1); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return -1; } if (debug) fprintf(stderr, "DEBUG: send: tos=\"R\", len=%d\n", ntohl(wsize)); if (pcp_read(pc, &tos, 1)) return -1; if (pcp_read(pc, &rsize, sizeof(int))) return -1; rsize = ntohl(rsize); buf = (char *)malloc(rsize); if (buf == NULL) { errorcode = NOMEMERR; return -1; } if (pcp_read(pc, buf, rsize - sizeof(int))) return -1; if (debug) fprintf(stderr, "DEBUG: recv: tos=\"%c\", len=%d, data=%s\n", tos, rsize, buf); if (tos == 'e') { if (debug) fprintf(stderr, "DEBUG: command failed. reason=%s\n", buf); errorcode = BACKENDERR; } else if (tos == 'r') { if (strcmp(buf, "AuthenticationOK") == 0) { free(buf); return 0; } if (debug) fprintf(stderr, "DEBUG: authentication failed. reason=%s\n", buf); errorcode = AUTHERR; } free(buf); return -1; }