/* -------------------------------- * 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); }
static void process_process_count_response(PCPConnInfo* pcpConn, char* buf, int len) { if (strcmp(buf, "CommandComplete") == 0) { int process_count; int *process_list = NULL; char *index = NULL; int i; index = (char *) memchr(buf, '\0', len); if (index == NULL) { pcp_internal_error(pcpConn, "command failed. invalid response"); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); return; } index +=1; process_count = atoi(index); process_list = (int *)palloc(sizeof(int) * process_count); for (i = 0; i < process_count; i++) { index = (char *) memchr(index, '\0', len); if (index == NULL) { pcp_internal_error(pcpConn, "command failed. invalid response"); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); return; } index +=1; process_list[i] = atoi(index); } setResultSlotCount(pcpConn,1); if (setNextResultBinaryData(pcpConn->pcpResInfo, process_list, (sizeof(int) * process_count) , NULL) < 0) { pcp_internal_error(pcpConn, "command failed. invalid response"); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); } else { setCommandSuccessful(pcpConn); } } else { pcp_internal_error(pcpConn, "command failed with reason: \"%s\"",buf); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); } }
static void process_pcp_node_count_response(PCPConnInfo* pcpConn, char* buf, int len) { if (strcmp(buf, "CommandComplete") == 0) { char *index = NULL; index = (char *) memchr(buf, '\0', len); if (index != NULL) { int ret; index += 1; ret = atoi(index); setResultIntData(pcpConn->pcpResInfo, 0, ret); setCommandSuccessful(pcpConn); return; } else pcp_internal_error(pcpConn, "command failed. invalid response"); } else pcp_internal_error(pcpConn, "command failed with reason: \"%s\"",buf); setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE); }
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); } }
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; }
static void setCommandSuccessful(PCPConnInfo* pcpConn) { setResultStatus(pcpConn,PCP_RES_COMMAND_OK); }
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); }