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);
}
Esempio n. 2
0
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);
}