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'); }
PCPResultInfo * pcp_recovery_node(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, "O", 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=\"D\", len=%d\n", ntohl(wsize)); return process_pcp_response(pcpConn, 'O'); }
static int PCPFlush(PCPConnInfo* pcpConn) { int ret = pcp_flush(pcpConn->pcpConn); if (ret) pcp_internal_error(pcpConn, "ERROR: sending data to backend failed with error \"%s\"",strerror(errno)); return ret; }
static void process_error_response(PCPConnInfo * pcpConn, char toc, char *buf) { /* For time we only support sev, error message and details */ char *errorSev = NULL; char *errorMsg = NULL; char *errorDet = NULL; char *e = buf; if (toc != 'E' && toc != 'N') return; while (*e) { char type = *e; e++; if (*e == 0) break; if (type == 'M') errorMsg = e; else if (type == 'S') errorSev = e; else if (type == 'D') errorDet = e; else e += strlen(e) + 1; if (errorDet && errorSev && errorMsg) /* we have all what we need */ break; } if (!errorSev && !errorMsg) return; if (toc != 'E') /* This is not an error report it as debug */ { if (pcpConn->Pfdebug) fprintf(pcpConn->Pfdebug, "BACKEND %s: %s\n%s%s%s", errorSev, errorMsg, errorDet ? "DETAIL: " : "", errorDet ? errorDet : "", errorDet ? "\n" : ""); } else { pcp_internal_error(pcpConn, "%s: %s\n%s%s%s", errorSev, errorMsg, errorDet ? "DETAIL: " : "", errorDet ? errorDet : "", errorDet ? "\n" : ""); setResultStatus(pcpConn, PCP_RES_BACKEND_ERROR); } }
static void process_command_complete_response(PCPConnInfo* pcpConn, char* buf, int len) { if (strcmp(buf, "CommandComplete") == 0) { setCommandSuccessful(pcpConn); } else { pcp_internal_error(pcpConn, "command failed with reason: \"%s\"",buf); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); } }
static void process_salt_info_response(PCPConnInfo* pcpConn, char* buf, int len) { char* salt = palloc((sizeof(char) * 4)); memcpy(salt, buf, 4); if (setNextResultBinaryData(pcpConn->pcpResInfo, (void *)salt, 4, NULL) < 0 ) { pcp_internal_error(pcpConn, "command failed. invalid response"); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); } else { setCommandSuccessful(pcpConn); } }
/* -------------------------------- * 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_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_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; }
PCPConnInfo* pcp_connect(char *hostname, int port, char *username, char *password, FILE *Pfdebug) { struct sockaddr_in addr; struct sockaddr_un unix_addr; struct hostent *hp; char *password_fron_file = NULL; char os_user[256]; PCPConnInfo* pcpConn = palloc0(sizeof(PCPConnInfo)); int fd; int on = 1; int len; pcpConn->connState = PCP_CONNECTION_NOT_CONNECTED; pcpConn->Pfdebug = Pfdebug; if (hostname == NULL || *hostname == '\0' || *hostname == '/') { char *path; fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { pcp_internal_error(pcpConn, "ERROR: failed to create UNIX domain socket. socket error \"%s\"",strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } memset(&unix_addr, 0, sizeof(unix_addr)); unix_addr.sun_family = AF_UNIX; if (hostname == NULL || *hostname == '\0') { path = UNIX_DOMAIN_PATH; hostname = path; } else { path = hostname; } snprintf(unix_addr.sun_path, sizeof(unix_addr.sun_path), "%s/.s.PGSQL.%d", path, port); if (connect(fd, (struct sockaddr *) &unix_addr, sizeof(unix_addr)) < 0) { close(fd); pcp_internal_error(pcpConn, "ERROR: connection to socket \"%s\" failed with error \"%s\"",unix_addr.sun_path,strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } } else { fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { pcp_internal_error(pcpConn, "ERROR: failed to create INET domain socket with error \"%s\"",strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0) { close(fd); pcp_internal_error(pcpConn, "ERROR: set socket option failed with error \"%s\"",strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } memset((char *) &addr, 0, sizeof(addr)); addr.sin_family = AF_INET; hp = gethostbyname(hostname); if ((hp == NULL) || (hp->h_addrtype != AF_INET)) { close(fd); pcp_internal_error(pcpConn, "ERROR: could not retrieve hostname. gethostbyname failed with error \"%s\"",strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } memmove((char *) &(addr.sin_addr), (char *) hp->h_addr, hp->h_length); addr.sin_port = htons(port); len = sizeof(struct sockaddr_in); if (connect(fd, (struct sockaddr *) &addr, len) < 0) { close(fd); pcp_internal_error(pcpConn, "ERROR: connection to host \"%s\" failed with error \"%s\"",hostname,strerror(errno)); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } } pcpConn->pcpConn = pcp_open(fd); if (pcpConn->pcpConn == NULL) { close(fd); pcp_internal_error(pcpConn, "ERROR: failed to allocate memory"); pcpConn->connState = PCP_CONNECTION_BAD; return pcpConn; } pcpConn->connState = PCP_CONNECTION_CONNECTED; /* * If username is not provided. Use the os user name * and do not complain if it (getting os user name) gets failed */ if (username == NULL && get_os_username(os_user, sizeof(os_user))) username = os_user; /* * If password is not provided. lookup in pcppass file */ if (password == NULL || *password == '\0') { char port_str[100]; snprintf(port_str, sizeof(port_str), "%d",port); password_fron_file = PasswordFromFile(pcpConn, hostname, port_str, username); password = password_fron_file; } if (pcp_authorize(pcpConn,username, password) < 0) { pcp_close(pcpConn->pcpConn); pcpConn->pcpConn = NULL; pcpConn->connState = PCP_CONNECTION_AUTH_ERROR; } else pcpConn->connState = PCP_CONNECTION_OK; if(password_fron_file) pfree(password_fron_file); return pcpConn; }
static void process_process_info_response(PCPConnInfo* pcpConn, char* buf, int len) { char *index; ProcessInfo *processInfo = NULL; if (strcmp(buf, "ArraySize") == 0) { int ci_size; index = (char *) memchr(buf, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; ci_size = atoi(index); setResultStatus(pcpConn, PCP_RES_INCOMPLETE); setResultSlotCount(pcpConn, ci_size); pcpConn->pcpResInfo->nextFillSlot = 0; return; } else if (strcmp(buf, "ProcessInfo") == 0) { if(PCPResultStatus(pcpConn->pcpResInfo) != PCP_RES_INCOMPLETE) goto INVALID_RESPONSE; processInfo = palloc0(sizeof(ProcessInfo)); processInfo->connection_info = palloc0(sizeof(ConnectionInfo)); index = (char *) memchr(buf, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; processInfo->pid = atoi(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; strlcpy(processInfo->connection_info->database, index, SM_DATABASE); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; strlcpy(processInfo->connection_info->user, index, SM_USER); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; processInfo->start_time = atol(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; processInfo->connection_info->create_time = atol(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; processInfo->connection_info->major = atoi(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; processInfo->connection_info->minor = atoi(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; processInfo->connection_info->counter = atoi(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; processInfo->connection_info->backend_id = atoi(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; processInfo->connection_info->pid = atoi(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; processInfo->connection_info->connected = atoi(index); if (setNextResultBinaryData(pcpConn->pcpResInfo, (void *)processInfo, sizeof(ProcessInfo), free_processInfo) < 0) goto INVALID_RESPONSE; return; } else if (strcmp(buf, "CommandComplete") == 0) { setResultStatus(pcpConn, PCP_RES_COMMAND_OK); return; } INVALID_RESPONSE: if(processInfo) { if(processInfo->connection_info) pfree(processInfo->connection_info); pfree(processInfo); } pcp_internal_error(pcpConn, "command failed. invalid response"); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); }
static void process_node_info_response(PCPConnInfo* pcpConn, char* buf, int len) { BackendInfo* backend_info = NULL; if (strcmp(buf, "CommandComplete") == 0) { char *index = NULL; backend_info = (BackendInfo *)palloc(sizeof(BackendInfo)); index = (char *) memchr(buf, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; strlcpy(backend_info->backend_hostname, index, sizeof(backend_info->backend_hostname)); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; backend_info->backend_port = atoi(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; backend_info->backend_status = atoi(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index +=1; backend_info->backend_weight = atof(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index++; backend_info->role = atoi(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index++; backend_info->standby_delay = atol(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; index++; backend_info->status_changed_time = atol(index); index = (char *) memchr(index, '\0', len); if(index == NULL) goto INVALID_RESPONSE; if (setNextResultBinaryData(pcpConn->pcpResInfo, (void *)backend_info, sizeof(BackendInfo) , NULL) < 0) goto INVALID_RESPONSE; setCommandSuccessful(pcpConn); } else { pcp_internal_error(pcpConn, "command failed with reason: \"%s\"",buf); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); } return; INVALID_RESPONSE: if(backend_info) pfree(backend_info); pcp_internal_error(pcpConn, "command failed. invalid response"); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); }
static PCPResultInfo* process_pcp_response(PCPConnInfo* pcpConn, char sentMsg) { char toc; int rsize; char* buf; /* create empty result */ if(pcpConn->pcpResInfo == NULL) { pcpConn->pcpResInfo = palloc0(sizeof(PCPResultInfo)); pcpConn->pcpResInfo->resultSlots = 1; } while (1) { if (pcp_read(pcpConn->pcpConn, &toc, 1)) { pcp_internal_error(pcpConn, "ERROR: unable to read data from socket."); setResultStatus(pcpConn, PCP_RES_ERROR); return pcpConn->pcpResInfo; } if (pcp_read(pcpConn->pcpConn, &rsize, sizeof(int))) { pcp_internal_error(pcpConn, "ERROR: unable to read data from socket."); setResultStatus(pcpConn, PCP_RES_ERROR); return pcpConn->pcpResInfo; } rsize = ntohl(rsize); buf = (char *)palloc(rsize); if (pcp_read(pcpConn->pcpConn, buf, rsize - sizeof(int))) { pfree(buf); pcp_internal_error(pcpConn, "ERROR: unable to read data from socket."); setResultStatus(pcpConn, PCP_RES_ERROR); return pcpConn->pcpResInfo; } if(pcpConn->Pfdebug) fprintf(pcpConn->Pfdebug, "DEBUG: recv: tos=\"%c\", len=%d\n", toc, rsize); switch (toc) { case 'r': /* Authentication Response */ { if(sentMsg != 'R') { setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); } else if (strcmp(buf, "AuthenticationOK") == 0) { pcpConn->connState = PCP_CONNECTION_OK; setResultStatus(pcpConn, PCP_RES_COMMAND_OK); } else { pcp_internal_error(pcpConn, "ERROR: authentication failed. reason=\"%s\"", buf); setResultStatus(pcpConn, PCP_RES_BACKEND_ERROR); } } break; case 'm': if(sentMsg != 'M') setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); else process_salt_info_response(pcpConn,buf,rsize); break; case 'E': setResultStatus(pcpConn, PCP_RES_BACKEND_ERROR); process_error_response(pcpConn,toc,buf); break; case 'N': process_error_response(pcpConn,toc,buf); pfree(buf); continue; break; case 'i': if(sentMsg != 'I') setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); else process_node_info_response(pcpConn,buf,rsize); break; case 'l': if(sentMsg != 'L') setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); else process_pcp_node_count_response(pcpConn,buf,rsize); break; case 'c': if(sentMsg != 'C' && sentMsg != 'O') setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); else process_command_complete_response(pcpConn,buf,rsize); break; case 'd': if(sentMsg != 'D' && sentMsg != 'J') setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); else process_command_complete_response(pcpConn,buf,rsize); break; case 'a': if(sentMsg != 'A') setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); else process_command_complete_response(pcpConn,buf,rsize); break; case 'w': if(sentMsg != 'W') setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); else process_watchdog_info_response(pcpConn,buf,rsize); break; case 'p': if(sentMsg != 'P') setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); else process_process_info_response(pcpConn,buf,rsize); break; case 'n': if(sentMsg != 'N') setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); else process_process_count_response(pcpConn,buf,rsize); break; case 'b': if(sentMsg != 'B') setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); else process_pool_status_response(pcpConn,buf,rsize); break; case 't': if(sentMsg != 'T') setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); else setResultStatus(pcpConn, PCP_RES_COMMAND_OK); break; default: setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); pcp_internal_error(pcpConn, "ERROR: invalid PCP packet type =\"%c\"", toc); break; } pfree(buf); if( PCPResultStatus(pcpConn->pcpResInfo) != PCP_RES_INCOMPLETE) break; } return pcpConn->pcpResInfo; }
/* -------------------------------- * pcp_authorize - authenticate with pgpool using username and password * * return 0 on success, -1 otherwise * -------------------------------- */ static int pcp_authorize(PCPConnInfo* pcpConn, char *username, char *password) { int wsize; char salt[4]; char* salt_ptr; char encrypt_buf[(MD5_PASSWD_LEN+1)*2]; char md5[MD5_PASSWD_LEN+1]; PCPResultInfo* pcpRes; if (password == NULL) password = ""; if (username == NULL) username = ""; if (PCPConnectionStatus(pcpConn) != PCP_CONNECTION_CONNECTED) { pcp_internal_error(pcpConn, "ERROR: PCP authorization failed. invalid connection state."); return -1; } if (strlen(username) >= MAX_USER_PASSWD_LEN) { pcp_internal_error(pcpConn, "ERROR: PCP authorization failed. username too long."); return -1; } /* request salt */ pcp_write(pcpConn->pcpConn, "M", 1); wsize = htonl(sizeof(int)); pcp_write(pcpConn->pcpConn, &wsize, sizeof(int)); if (PCPFlush(pcpConn) < 0) return -1; pcpRes = process_pcp_response(pcpConn, 'M'); if(PCPResultStatus(pcpRes) != PCP_RES_COMMAND_OK) return -1; salt_ptr = pcp_get_binary_data(pcpRes, 0); if(salt_ptr == NULL) return -1; memcpy(salt, salt_ptr, 4); /* 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(pcpConn->pcpConn, "R", 1); wsize = htonl((strlen(username)+1 + strlen(encrypt_buf)+1) + sizeof(int)); pcp_write(pcpConn->pcpConn, &wsize, sizeof(int)); pcp_write(pcpConn->pcpConn, username, strlen(username)+1); pcp_write(pcpConn->pcpConn, encrypt_buf, strlen(encrypt_buf)+1); if (PCPFlush(pcpConn) < 0) return -1; pcpRes = process_pcp_response(pcpConn, 'R'); if(PCPResultStatus(pcpRes) != PCP_RES_COMMAND_OK) return -1; pcp_free_result(pcpConn); return 0; }
static void process_watchdog_info_response(PCPConnInfo* pcpConn, char* buf, int len) { char *json_data = NULL; PCPWDClusterInfo* wd_cluster_info = NULL; int clusterDataSize = 0; if (strcmp(buf, "CommandComplete") == 0) { int tempVal; char* ptr; json_data = (char *) memchr(buf, '\0', len); if(json_data == NULL) goto INVALID_RESPONSE; json_data +=1; json_value* root; json_value* value; int i,nodeCount; root = json_parse(json_data,len); /* The root node must be object */ if (root == NULL || root->type != json_object) { json_value_free(root); goto INVALID_RESPONSE; } if (json_get_int_value_for_key(root, "NodeCount", &nodeCount)) { json_value_free(root); goto INVALID_RESPONSE; } /* find the WatchdogNodes array */ value = json_get_value_for_key(root,"WatchdogNodes"); if (value == NULL) { json_value_free(root); goto INVALID_RESPONSE; } if (value->type != json_array) { json_value_free(root); goto INVALID_RESPONSE; } if (nodeCount != value->u.array.length) { json_value_free(root); goto INVALID_RESPONSE; } /* create the cluster object */ clusterDataSize = sizeof(PCPWDClusterInfo) + (sizeof(PCPWDNodeInfo) * nodeCount); wd_cluster_info = malloc(clusterDataSize); wd_cluster_info->nodeCount = nodeCount; if (json_get_int_value_for_key(root, "RemoteNodeCount", &wd_cluster_info->remoteNodeCount)) { json_value_free(root); goto INVALID_RESPONSE; } if (json_get_int_value_for_key(root, "QuorumStatus", &wd_cluster_info->quorumStatus)) { json_value_free(root); goto INVALID_RESPONSE; } if (json_get_int_value_for_key(root, "AliveNodeCount", &wd_cluster_info->aliveNodeCount)) { json_value_free(root); goto INVALID_RESPONSE; } if (json_get_int_value_for_key(root, "Escalated", &tempVal)) { json_value_free(root); goto INVALID_RESPONSE; } wd_cluster_info->escalated = tempVal==0?false:true; ptr = json_get_string_value_for_key(root, "MasterNodeName"); if (ptr == NULL) { json_value_free(root); goto INVALID_RESPONSE; } strncpy(wd_cluster_info->masterNodeName, ptr, sizeof(wd_cluster_info->masterNodeName) -1); ptr = json_get_string_value_for_key(root, "MasterHostName"); if (ptr == NULL) { json_value_free(root); goto INVALID_RESPONSE; } strncpy(wd_cluster_info->masterHostName, ptr, sizeof(wd_cluster_info->masterHostName) -1); /* Get watchdog nodes data */ for (i = 0; i < nodeCount; i++) { char* ptr; json_value* nodeInfoValue = value->u.array.values[i]; PCPWDNodeInfo* wdNodeInfo = &wd_cluster_info->nodeList[i]; if (nodeInfoValue->type != json_object) { json_value_free(root); goto INVALID_RESPONSE; } if (json_get_int_value_for_key(nodeInfoValue, "ID", &wdNodeInfo->id)) { json_value_free(root); goto INVALID_RESPONSE; } ptr = json_get_string_value_for_key(nodeInfoValue, "NodeName"); if (ptr == NULL) { json_value_free(root); goto INVALID_RESPONSE; } strncpy(wdNodeInfo->nodeName, ptr, sizeof(wdNodeInfo->nodeName) -1); ptr = json_get_string_value_for_key(nodeInfoValue, "HostName"); if (ptr == NULL) { json_value_free(root); goto INVALID_RESPONSE; } strncpy(wdNodeInfo->hostName, ptr, sizeof(wdNodeInfo->hostName) -1); ptr = json_get_string_value_for_key(nodeInfoValue, "DelegateIP"); if (ptr == NULL) { json_value_free(root); goto INVALID_RESPONSE; } strncpy(wdNodeInfo->delegate_ip, ptr, sizeof(wdNodeInfo->delegate_ip) -1); if (json_get_int_value_for_key(nodeInfoValue, "WdPort", &wdNodeInfo->wd_port)) { json_value_free(root); goto INVALID_RESPONSE; } if (json_get_int_value_for_key(nodeInfoValue, "PgpoolPort", &wdNodeInfo->pgpool_port)) { json_value_free(root); goto INVALID_RESPONSE; } if (json_get_int_value_for_key(nodeInfoValue, "State", &wdNodeInfo->state)) { json_value_free(root); goto INVALID_RESPONSE; } ptr = json_get_string_value_for_key(nodeInfoValue, "StateName"); if (ptr == NULL) { json_value_free(root); goto INVALID_RESPONSE; } strncpy(wdNodeInfo->stateName, ptr, sizeof(wdNodeInfo->stateName) -1); if (json_get_int_value_for_key(nodeInfoValue, "Priority", &wdNodeInfo->wd_priority)) { json_value_free(root); goto INVALID_RESPONSE; } } json_value_free(root); if (setNextResultBinaryData(pcpConn->pcpResInfo, (void *)wd_cluster_info,clusterDataSize , NULL) < 0) goto INVALID_RESPONSE; setCommandSuccessful(pcpConn); } else { pcp_internal_error(pcpConn, "command failed with reason: \"%s\"\n",buf); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); } return; INVALID_RESPONSE: if(wd_cluster_info) pfree(wd_cluster_info); pcp_internal_error(pcpConn, "command failed. invalid response\n"); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); }
/* -------------------------------- * pcp_pool_status - return setup parameters and status * * returns and array of POOL_REPORT_CONFIG, NULL otherwise * -------------------------------- */ static void process_pool_status_response(PCPConnInfo * pcpConn, char *buf, int len) { char *index; POOL_REPORT_CONFIG *status = NULL; if (strcmp(buf, "ArraySize") == 0) { int ci_size; index = (char *) memchr(buf, '\0', len) + 1; ci_size = ntohl(*((int *) index)); setResultStatus(pcpConn, PCP_RES_INCOMPLETE); setResultSlotCount(pcpConn, ci_size); pcpConn->pcpResInfo->nextFillSlot = 0; return; } else if (strcmp(buf, "ProcessConfig") == 0) { if (PCPResultStatus(pcpConn->pcpResInfo) != PCP_RES_INCOMPLETE) goto INVALID_RESPONSE; status = palloc(sizeof(POOL_REPORT_CONFIG)); index = (char *) memchr(buf, '\0', len); if (index == NULL) goto INVALID_RESPONSE; index += 1; strlcpy(status->name, index, POOLCONFIG_MAXNAMELEN + 1); index = (char *) memchr(index, '\0', len); if (index == NULL) goto INVALID_RESPONSE; index += 1; strlcpy(status->value, index, POOLCONFIG_MAXVALLEN + 1); index = (char *) memchr(index, '\0', len); if (index == NULL) goto INVALID_RESPONSE; index += 1; strlcpy(status->desc, index, POOLCONFIG_MAXDESCLEN + 1); if (setNextResultBinaryData(pcpConn->pcpResInfo, (void *) status, sizeof(POOL_REPORT_CONFIG), NULL) < 0) goto INVALID_RESPONSE; return; } else if (strcmp(buf, "CommandComplete") == 0) { setResultStatus(pcpConn, PCP_RES_COMMAND_OK); return; } INVALID_RESPONSE: if (status) pfree(status); pcp_internal_error(pcpConn, "command failed. invalid response"); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); }