void FileRepResetPeer_Main(void) { /* BASIC PROCESS SETUP */ FileRepReset_ConfigureSignals(); /* * If an exception is encountered, processing resumes here. * * See notes in postgres.c about the design of this coding and comments about how the error * handling works. */ sigjmp_buf local_sigjmp_buf; if (sigsetjmp(local_sigjmp_buf, 1) != 0) { HOLD_INTERRUPTS(); EmitErrorReport(); proc_exit(EXIT_CODE_SHOULD_ENTER_FAULT); } /* We can now handle ereport(ERROR) */ PG_exception_stack = &local_sigjmp_buf; PG_SETMASK(&UnBlockSig); /** NOW DO THE ACTUAL WORK */ char messageFromPeer[MESSAGE_FROM_PEER_BUF_SIZE]; char resetNumberFromPeer[MESSAGE_FROM_PEER_BUF_SIZE]; char resetNumberThatIndicatesResetComplete[MESSAGE_FROM_PEER_BUF_SIZE]; struct addrinfo *addrList = NULL; char portStr[100]; PrimaryMirrorModeTransitionArguments args = primaryMirrorGetArgumentsFromLocalMemory(); Assert(args.mode == PMModePrimarySegment || args.mode == PMModeMirrorSegment); snprintf(portStr, sizeof(portStr), "%d", args.peerPostmasterPort); if (! determineTargetHost(&addrList, args.peerAddress, portStr)) { elog(WARNING, "during reset, unable to look up address for peer host to coordinate reset; " "will transition to fault state."); proc_exit(EXIT_CODE_SHOULD_ENTER_FAULT); } sendMessageToPeerAndExitIfProblem(addrList, "beginPostmasterReset", messageFromPeer, resetNumberThatIndicatesResetComplete); for ( ;; ) { pg_usleep(10 * 1000L); /* 10 ms */ sendMessageToPeerAndExitIfProblem(addrList, "getPostmasterResetStatus", messageFromPeer, resetNumberFromPeer ); if (strequals(messageFromPeer, RESET_STATUS_IS_IN_RESET_PIVOT_POINT)) { if (args.mode == PMModeMirrorSegment) { /** * peer is in the reset pivot point, we can break out of our checking loop and * thus exit with a code telling the postmaster to begin the startup sequence again * * this is only done on the mirror as currently the mirror must execute the startup sequence * before the primary */ elog(DEBUG1, "peer reset: primary peer has reached reset point"); break; } } else if (strequals(messageFromPeer, RESET_STATUS_IS_RUNNING)) { /** it's running -- is it >= than the reset number that indicates reset complete one */ if (strcmp( resetNumberFromPeer, resetNumberThatIndicatesResetComplete) >= 0) { /** yes, the reset is complete and so we can quit and do a restart */ elog(DEBUG1, "peer reset: mirror peer reset is complete"); break; } } } proc_exit(EXIT_CODE_SHOULD_RESTART_SHMEM_CLEANLY); }
int main(int argc, char **argv) { struct addrinfo *addrList = NULL; char *host = NULL, *port = NULL, *inputFile = NULL; char *mode = NULL; char *status = NULL; char *seg_addr = NULL; char *seg_pm_port = NULL; char *seg_rep_port = NULL; char *peer_addr = NULL; char *peer_pm_port = NULL; char *peer_rep_port = NULL; char *num_retries_str = NULL; char *transition_timeout_str = NULL; int num_retries = 20; int transition_timeout = 3600; /* 1 hour */ char opt; char msgBuffer[SEGMENT_MSG_BUF_SIZE]; char *msg = NULL; int msgLen = 0; while ((opt = getopt(argc, argv, "m:s:H:P:R:h:p:r:i:n:t:")) != -1) { switch (opt) { case 'i': inputFile = optarg; break; case 'm': mode = optarg; break; case 's': status = optarg; break; case 'H': seg_addr = optarg; break; case 'P': seg_pm_port = optarg; break; case 'R': seg_rep_port = optarg; break; case 'h': host = peer_addr = optarg; break; case 'p': port = peer_pm_port = optarg; break; case 'r': peer_rep_port = optarg; break; case 'n': num_retries_str = optarg; break; case 't': transition_timeout_str = optarg; break; case '?': fprintf(stderr, "Unrecognized option: -%c\n", optopt); } } if (num_retries_str != NULL) { num_retries = (int) strtol(num_retries_str, NULL, 10); if (num_retries == 0 || errno == ERANGE) { fprintf(stderr, "Invalid num_retries (-n) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } } if (transition_timeout_str != NULL) { transition_timeout = (int) strtol (transition_timeout_str, NULL, 10); if (transition_timeout == 0 || errno == ERANGE) { fprintf(stderr, "Invalid transition_timeout (-t) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } } /* check if input file parameter is passed */ if (seg_addr == NULL) { if ( host == NULL) { fprintf(stderr, "Missing host (-h) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } if ( port == NULL ) { fprintf(stderr, "Missing port (-p) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } /* find the target machine */ if ( ! determineTargetHost(&addrList, host, port)) { return TRANS_ERRCODE_ERROR_HOST_LOOKUP_FAILED; } /* load the input message into memory */ if ( inputFile == NULL) { msg = readFully(stdin, &msgLen); } else { FILE *f = fopen(inputFile, "r"); if ( f == NULL) { fprintf(stderr, "Unable to open file %s\n", inputFile); return TRANS_ERRCODE_ERROR_READING_INPUT; } msg = readFully(f, &msgLen); fclose(f); } } else { /* build message from passed parameters */ if (mode == NULL) { fprintf(stderr, "Missing mode (-m) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } if (status == NULL) { fprintf(stderr, "Missing status (-s) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } if (seg_addr == NULL) { fprintf(stderr, "Missing segment host (-H) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } if (seg_pm_port == NULL) { fprintf(stderr, "Missing segment postmaster port (-P) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } if (seg_rep_port == NULL) { fprintf(stderr, "Missing segment replication port (-R) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } if (peer_addr == NULL) { fprintf(stderr, "Missing peer host (-h) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } if (peer_pm_port == NULL) { fprintf(stderr, "Missing peer postmaster port (-p) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } if (peer_rep_port == NULL) { fprintf(stderr, "Missing peer replication port (-r) argument\n"); return TRANS_ERRCODE_ERROR_INVALID_ARGUMENT; } /* build message */ msgLen = snprintf( msgBuffer, sizeof(msgBuffer), "%s\n%s\n%s\n%s\n%s\n%s\n%s\n", mode, status, seg_addr, seg_rep_port, peer_addr, peer_rep_port, peer_pm_port ); msg = msgBuffer; /* find the target machine */ if (!determineTargetHost(&addrList, seg_addr, seg_pm_port)) { return TRANS_ERRCODE_ERROR_HOST_LOOKUP_FAILED; } } /* check for errors while building the message */ if ( msg == NULL ) { return TRANS_ERRCODE_ERROR_READING_INPUT; } /* send the message */ PrimaryMirrorTransitionClientInfo client; client.receivedDataCallbackFn = gpMirrorReceivedDataCallbackFunction; client.errorLogFn = gpMirrorErrorLogFunction; client.checkForNeedToExitFn = gpCheckForNeedToExitFn; return sendTransitionMessage(&client, addrList, msg, msgLen, num_retries, transition_timeout); }