/****************************************************************************** © Copyright 2006 Hewlett-Packard Development Company, L.P. Confidential computer software. Valid license from HP required for possession, use or copying. Consistent with FAR 12.211 and 12.212, Commercial Computer Software, Computer Software Documentation, and Technical Data for Commercial Items are licensed to the U.S. Government under vendor s standard commercial license. The information contained herein is subject to change without notice. The only warranties for HP products and services are set forth in the express warranty statements accompanying such products and services. Nothing herein should be construed as constituting an additional warranty. HP shall not be liable for technical or editorial errors or omissions contained herein. ******************************************************************************* FACILITY: Reliable Transaction Router Application template to manage group partition failover AUTHOR: Hewlett-Packard development company DESCRIPTION: Reads tuplets from servinfo.txt & backendinfo.txt and builds a list for rtr_request_info. Calls rtr_request_info and creates tables based on results. These tables are used by MONGROUP while making decisions related to the failover of group of partitions Note : Use RTR LIST/REQUEST info-class command to find out which items you're interested in.. On OpenVMS: build using: $ cc /include=<_directory_with_RTR.H_> MONGROUP.C $ cc /include=<_directory_with_RTR.H_> REQ_INFO.C $ link MONGROUP,REQ_INFO,sys$input/opt sys$share:librtr/share ^Z ******************************************************************************/ #define BUFFER_LIMIT 1000 #include #include #ifdef VMS #include #include #else #include #ifdef WIN32 #include #endif #endif #include #include #include "MONGROUP.h" extern void Modname_Extractor(char *); /*** * Function : Current_Partition_State_Table * * Description : This Function creates partition state table, * which contains information such as * facility name, partition name, partition state, * partition id. * This table is created based on information retrieved * from RTR using rtr_request_info call. * * Return code : Void * ***/ void Current_Partition_State_Table(char *tmp_part_name, char *tmp_fac_name, char *tmp_part_state,long tmp_partition_id) { int No_gr_Flag; CURRENT_GROUP_INFO *newnode; GROUP_INFO *tmpnode; No_gr_Flag = 0; newnode = (CURRENT_GROUP_INFO *)malloc(sizeof(CURRENT_GROUP_INFO)); memset ( newnode, 0, sizeof(CURRENT_GROUP_INFO)); strcpy (newnode->facility_name,tmp_fac_name); strcpy (newnode->partition_name,tmp_part_name); strcpy (newnode->partition_state,tmp_part_state); newnode->partition_id = tmp_partition_id; newnode->ASFlag = 0; newnode->DirtyGrFlag = 0; if (Current_Gr_Head == NULL) { /* ********* Insert Group Info From Input File ********** */ tmpnode = Head; while(tmpnode != NULL) { if( (!strcmp(tmp_fac_name,tmpnode->facility_name)) && (!strcmp(tmp_part_name,tmpnode->partition_name))) { strcpy(newnode->group_name,tmpnode->group_name); No_gr_Flag = 1; break; } tmpnode = tmpnode ->pNext; } if(No_gr_Flag == 0) memset(newnode->group_name,'\0',Max_Group_Size); Current_Gr_Head = newnode; Current_Gr_Tail = newnode; newnode->pNext = NULL; } else { /* ********* Insert Group Info From Input File ********** */ tmpnode = Head; while(tmpnode != NULL) { if( (!strcmp(tmp_fac_name,tmpnode->facility_name)) && (!strcmp(tmp_part_name,tmpnode->partition_name)) ) { strcpy(newnode->group_name,tmpnode->group_name); No_gr_Flag = 1; break; } tmpnode = tmpnode ->pNext; } if(No_gr_Flag == 0) memset(newnode->group_name,'\0',Max_Group_Size); Current_Gr_Tail->pNext = newnode; newnode->pNext = NULL; Current_Gr_Tail = newnode; } } /*** * Function : display_Current_list * * Description : This Function displays partition state table information * of all groups. * * Return code : Void * ***/ void display_Current_list(void) { CURRENT_GROUP_INFO *newnode; newnode = Current_Gr_Head; while(newnode != NULL) { if(debug) dumplog_p5("Facility = %s,Part = %s, Gr = %s State = %s Pa_Id %ld",newnode->facility_name,newnode->partition_name,newnode->group_name,newnode->partition_state,newnode->partition_id); newnode = newnode ->pNext; } } /*** * Function : Process_Id_Table_Insert * * Description : This Function creates table with facility name, * partition id and server process id information. * * Return code : Void * ***/ void Process_Id_Table_Insert(char *tmp_fac_name, long tmp_part_id, char *tmp_proc_id) { SERVER_PROC_INFO *newnode; newnode = (SERVER_PROC_INFO *)malloc(sizeof(SERVER_PROC_INFO)); memset (newnode , 0 , sizeof(SERVER_PROC_INFO)); strcpy (newnode->facility_name,tmp_fac_name); newnode->partition_id = tmp_part_id; strcpy (newnode->server_proc_id,tmp_proc_id); if (Ser_Proc_Head == NULL) { Ser_Proc_Head = newnode; Ser_Proc_Tail = newnode; newnode->pNext = NULL; } else { Ser_Proc_Tail->pNext = newnode; newnode->pNext = NULL; Ser_Proc_Tail = newnode; } } /*** * Function : display_proc_id_table * * Description : This Function displays server process ids information * of all groups. * * Return code : Void * ***/ void display_proc_id_table(void) { SERVER_PROC_INFO *newnode; newnode = Ser_Proc_Head; while(newnode != NULL) { if(debug) dumplog_p3("Facility = %s, Pa_Id = %ld, ProcId = %s",newnode->facility_name,newnode->partition_id,newnode->server_proc_id); newnode = newnode->pNext; } } /*** * Function : get_gr_table * * Description : * * Reads tuplets from servinfo.txt & * backendinfo.txt and builds a list for rtr_request_info. * Calls rtr_request_info and create tables from return values * of rtr_request_info call. Use RTR LIST/REQUEST info-class command * to find out which items you're interested in. The output of this * command can be piped as input to this program. * * Return code : Exit Status ***/ int get_gr_table(int argc, char **argv) { rtr_msgsb_t txsb; rtr_status_t rtr_status; rtr_channel_t c_chan; char pmsg[RTR_MAX_MSGLEN], itembuf[RTR_MAX_MSGLEN], infcla_buf[100], gets_buf[BUFFER_LIMIT] = "", *cp; int i, itemcnt = 0; char *input = NULL; /* DEFAULT is stdin */ rtr_infoclass_t infcla = NULL; rtr_itemcode_t selitm = "$name", /* DEFAULT */ itemlist[1000], item; rtr_selval_t selval = "*"; /* DEFAULT */ rtr_bool_t Eof = RTR_FALSE; char *table_info[4]; input = argv[1]; itemlist[0] = itembuf; if (input) { int fd; close(0); fd = open(input, O_RDONLY, 0); if (fd == -1) { perror("OPEN error"); exit(1); } /* closed on program exit */ } if (fgets(gets_buf, BUFFER_LIMIT-1,stdin)) do { infcla_buf[0] = '\0'; itemcnt = 0; do { /* * This code isn't the clearest... Maybe make into a subroutine. * Essentially reads lines from stdin in format * . As each item name is read in, it is * copied into itembuf, appended to the list of items already * in the buffer. In this way it assembles a comma-separated list * of items in itembuf. It continues doing this until either * the buffer is full, or changes, or no more lines * are read from stdin. It then calls rtr_request_info with this * buffer. */ /* */ /* INFCLA */ for (cp = gets_buf; *cp && cp < gets_buf+sizeof(gets_buf); cp++) if (*cp != ' ' && *cp != '\t') break; /* skip blanks */ if (!(*cp) || *cp == '!' || *cp == '\n' || *cp == '\r' ) continue; /* comment/blank line */ infcla = cp; while (++cp < gets_buf+sizeof(gets_buf) && *cp) if (*cp == ' ' || *cp == '\t') break; /* find EOS */ if (infcla_buf[0] == '\0') { memcpy(infcla_buf, infcla, cp-infcla); infcla_buf[cp-infcla] = '\0'; } else if (memcmp(infcla, infcla_buf, cp-infcla)) break; /* ITEM_CODE */ while (++cp < gets_buf+sizeof(gets_buf) && *cp) if (*cp != ' ' && *cp != '\t') break; /* skip blanks */ item = cp; while (++cp < gets_buf+sizeof(gets_buf) && *cp) if (*cp == ' ' || *cp == '\t' || *cp =='\r' || *cp == '\n') break; /* find EOS */ if ((itembuf - itemlist[itemcnt] + (int)sizeof(itembuf)) > (cp-item)+1 ) { /* * itemlist[] is an array pointers into itembuf. Each element * points to the next item in itembuf. This is simply a * mechanism to make printing the item plus it's returned * value easier after the call to rtr_receive_message(). */ memcpy(itemlist[itemcnt], item, cp-item); itemlist[itemcnt][cp++-item] = ','; itemlist[itemcnt+1] = itemlist[itemcnt] + (cp - item); itemcnt++; } else break; /* not enough space left in item buffer */ } while (! (Eof = (fgets(gets_buf,BUFFER_LIMIT-1, stdin) == NULL))); *(itemlist[itemcnt] - 1) = '\0'; /* overwrite trailing comma */ rtr_status = rtr_request_info ( /* *pchannel */ &c_chan, /* flags */ RTR_NO_FLAGS, /* infcla */ infcla_buf, /* selitm */ selitm, /* selval */ selval, /* getitms */ itembuf); if (rtr_status != RTR_STS_OK) { if(debug) dumplog_p3( "INFCLA %s\tITEM_CODE %s\tBad status %d, rtr_request_info()", infcla_buf, itembuf, rtr_status); break; } do { rtr_status = rtr_receive_message( /* *pchannel */ &c_chan, /* flags */ RTR_NO_FLAGS, /* *prcvchan */ RTR_ANYCHAN, /* pmsg */ pmsg, /* maxlen */ sizeof(pmsg), /* timoutms */ RTR_NO_TIMOUTMS, /* *pmsgsb */ &txsb); /* Check for bad return status from rtr_receive_message() */ if (rtr_status != RTR_STS_OK) { if(debug) dumplog_p3( "INFCLA %s\tITEM_CODE %s\tBad status %d, rtr_receive_message()", infcla_buf, itembuf, rtr_status); break; } if (txsb.msgtype == rtr_mt_closed) { rtr_status_data_t *p_data = (rtr_status_data_t*)pmsg; /* channel has been closed by RTR, no more data for this item */ break; } if (txsb.msgtype != rtr_mt_request_info) { if(debug) dumplog_p3( "INFCLA %s\tITEM_CODE %s\tUnusual msgtype %d returned from rtr_receive_message()", infcla_buf, itembuf, txsb.msgtype); break; } else { /* Receive the requested information. Print it */ /* scan through item list and print item and it's value */ for (i = 0, cp = pmsg; i < itemcnt; i++, cp += strlen(cp)+1) { *(itemlist[i+1] - 1) = '\0'; /* overwrite trailing comma */ if(debug) dumplog_p3("%-8s:%40s\t= '%s'", infcla_buf, itemlist[i], cp); table_info[i] = cp; } if(get_table_flag == 1) Current_Partition_State_Table(table_info[0],table_info[1],table_info[2],atol(table_info[3])); else if(get_table_flag == 0) Process_Id_Table_Insert(table_info[0],atol(table_info[1]),table_info[2]); if (cp - pmsg < (int)txsb.msglen) printf("ERROR: %d bytes leftover: %s\n", cp-pmsg, cp); } } while(1==1); } while (!Eof); return EXIT_SUCCESS; }