Beispiel #1
0
int 
FileRepConnServer_StartListener(
		char	*hostAddress,
		int		portLocal)
{

	int	status = STATUS_OK;
	int i;
	
	for (i=0; i < FILEREP_MAX_LISTEN; i++) {
		listenSocket[i] = -1;
	}
	
	/* NOTE check if family AF_UNIX has to be considered as well */
	status = StreamServerPort(
					AF_UNSPEC, 
					hostAddress,
					(unsigned short) portLocal,
					NULL,
					listenSocket,
					FILEREP_MAX_LISTEN);

	if (status != STATUS_OK) {
		ereport(WARNING, 
				(errcode_for_socket_access(),
				 errmsg("could not start listener, host:'%s' port:'%d': %m",
						hostAddress,
						portLocal),
				 errSendAlert(true),
				 FileRep_errcontext()));
	}
	
	return status;
}
Beispiel #2
0
/*
 * lookup ack entry
 */
static FileRepAckHashEntry_s*
FileRepAckPrimary_LookupHashEntry(FileName fileName)
{
	FileRepAckHashEntry_s	*entry;
	char					key[MAXPGPATH+1];
	
	snprintf(key, sizeof(key), "%s", fileName);
	
	Assert(fileRepAckHashShmem->hash != NULL);
		
	entry = (FileRepAckHashEntry_s *) hash_search(
										  fileRepAckHashShmem->hash, 
										  (void *) &key, 
										  HASH_FIND, 
										  NULL);
	
	if (entry == NULL) {
		
		ereport(WARNING,
				(errmsg("mirror failure, "
						"could not lookup ack entry '%s' into ack table, no entry "
						"failover requested",
						(fileName == NULL) ? "<null>" : fileName), 
				 errhint("run gprecoverseg to re-establish mirror connectivity"),
				 FileRep_errcontext()));			
	} 

	return entry;
}
int
FileRepConnServer_CreateConnection()
{
	int			status = STATUS_OK;

	port = (Port *) calloc(1, sizeof(Port));
	if (port == NULL)
	{
		ereport(ERROR,
				(errcode(ERRCODE_OUT_OF_MEMORY),
				 (errmsg("not enough memory to create connection"))));
		return status;
	}

	status = StreamConnection(listenSocket[0], port);
	if (status != STATUS_OK)
	{
		ereport(WARNING,
				(errcode_for_socket_access(),
				 errmsg("could not accept connection: %m"),
				 FileRep_errcontext()));

		if (port->sock >= 0)
		{
			StreamClose(port->sock);
		}
		ConnFree();
	}
	else
	{
		/*
		 * MPP-14225: On NIC failure, filerep receiver process's recv() system
		 * call will take hours to timeout, depending on the TCP timeout. Add
		 * SO_RCVTIMEO timeout to filerep receiver process's socket to avoid
		 * this.
		 */
		struct timeval tv;

		tv.tv_sec = file_rep_socket_timeout;
		tv.tv_usec = 0;			/* Not initializing this can cause strange
								 * errors */

		if (setsockopt(port->sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(struct timeval)) == -1)
			ereport(WARNING,
					(errcode_for_socket_access(),
					 errmsg("could not set receive timeout on socket")));

		/* set TCP keep-alive parameters for FileRep connection */
		(void) pq_setkeepalivesidle(gp_filerep_tcp_keepalives_idle, port);
		(void) pq_setkeepalivesinterval(gp_filerep_tcp_keepalives_interval, port);
		(void) pq_setkeepalivescount(gp_filerep_tcp_keepalives_count, port);

		MyProcPort = port;
	}

	return status;
}
int
FileRepConnClient_EstablishConnection(
									  char *hostAddress,
									  int port,
									  bool reportError)
{
	int			status = STATUS_OK;
	char		portbuf[11];
	char		timeoutbuf[11];
	const char *keys[5];
	const char *vals[5];

/*	FileRepConnClient_CloseConnection();*/

	snprintf(portbuf, sizeof(portbuf), "%d", port);
	snprintf(timeoutbuf, sizeof(timeoutbuf), "%d", gp_segment_connect_timeout);

	keys[0] = "host";
	vals[0] = hostAddress;
	keys[1] = "port";
	vals[1] = portbuf;
	keys[2] = "dbname";
	vals[2] = "postgres";
	keys[3] = "connect_timeout";
	vals[3] = timeoutbuf;
	keys[4] = NULL;
	vals[4] = NULL;

	filerep_conn = PQconnectdbParams(keys, vals, false);

	if (PQstatus(filerep_conn) != CONNECTION_OK)
	{
		if (reportError || Debug_filerep_print)
			ereport(WARNING,
					(errcode_for_socket_access(),
					 errmsg("could not establish connection with server, host:'%s' port:'%d' err:'%s' : %m",
							hostAddress,
							port,
							PQerrorMessage(filerep_conn)),
					 errSendAlert(true),
					 FileRep_errcontext()));

		status = STATUS_ERROR;

		if (filerep_conn)
		{
			PQfinish(filerep_conn);
			filerep_conn = NULL;
		}
	}

	/* NOTE Handle error message see ftsprobe.c */

	return status;
}
int
FileRepConnServer_Select(void)
{
	struct timeval timeout;
	fd_set		rfds;
	int			retval;

	timeout.tv_sec = 0;
	timeout.tv_usec = 100 * 1000L;

	FD_ZERO(&rfds);

	FD_SET(listenSocket[0], &rfds);

	retval = select(listenSocket[0] + 1, &rfds, NULL, NULL, &timeout);

	/*
	 * check and process any signals received The routine returns TRUE if the
	 * received signal requests process shutdown.
	 */

	if (retval)
	{
		if (!FD_ISSET(listenSocket[0], &rfds))
		{
			retval = -1;
		}
	}

	if (retval == -1)
	{
		ereport(WARNING,
				(errcode_for_socket_access(),
				 errmsg("receive failure on connection: %m"),
				 FileRep_errcontext()));
	}

	return retval;
}
Beispiel #6
0
static int
FileRepPrimary_ResyncBufferPoolIncrementalWrite(ChangeTrackingRequest *request)
{
	int				status = STATUS_OK;
	Page			page;
	Buffer			buf; 
	BlockNumber		numBlocks = 0;
	SMgrRelation	smgr_relation = NULL;
	char			relidstr[OIDCHARS + 1 + OIDCHARS + 1 + OIDCHARS + 1];
	int				ii;
	XLogRecPtr		loc;
	XLogRecPtr		loc1;
	int				count = 0;
	int				thresholdCount = 0;
	bool			mirrorDataLossOccurred = FALSE;
	int				NumberOfRelations = request->count;
	
	FileRepResyncHashEntry_s	entry;
	ChangeTrackingResult		*result = NULL;	

	while (1)
	{
		/* allow flushing buffers from buffer pool during scan */
		FileRepResync_SetReadBufferRequest();
		if ((result = ChangeTracking_GetChanges(request)) != NULL) 
		{
			FileRepResync_ResetReadBufferRequest();
					
			for (ii = 0; ii < result->count; ii++)
			{
				
				if (smgr_relation == NULL)
				{
					NumberOfRelations--;
					
					smgr_relation = smgropen(result->entries[ii].relFileNode);
					
					snprintf(relidstr, sizeof(relidstr), "%u/%u/%u",
							 smgr_relation->smgr_rnode.spcNode,
							 smgr_relation->smgr_rnode.dbNode,
							 smgr_relation->smgr_rnode.relNode);

					numBlocks = smgrnblocks(smgr_relation);
					
					if (Debug_filerep_print)
						elog(LOG, "resynchronize buffer pool relation '%u/%u/%u' "
							 "number of blocks:'%u' ",
							 smgr_relation->smgr_rnode.spcNode,
							 smgr_relation->smgr_rnode.dbNode,
							 smgr_relation->smgr_rnode.relNode,
							 numBlocks);
					
					thresholdCount = Min(numBlocks, 1024);
				}
				
				loc1 =  result->entries[ii].lsn_end;
				
				/*
				 * if relation was truncated then block_num from change tracking can be beyond numBlocks 
				 */
				if (result->entries[ii].block_num >=  numBlocks)
				{
					ereport(LOG,	
							(errmsg("could not resynchonize buffer pool relation '%s' block '%d' (maybe due to truncate), "
									"lsn change tracking '%s(%u/%u)' "
									"number of blocks '%d' ",
									relidstr,
									result->entries[ii].block_num,
									XLogLocationToString(&loc1),
									loc1.xlogid,
									loc1.xrecoff,
									numBlocks),						
							 FileRep_errcontext()));						
					
					goto flush_check;
				}
				
				/* allow flushing buffers from buffer pool during scan */
				FileRepResync_SetReadBufferRequest();
				buf = ReadBuffer_Resync(smgr_relation,
										result->entries[ii].block_num,
										relidstr);
				FileRepResync_ResetReadBufferRequest();
				
				Assert(result->entries[ii].block_num < numBlocks);
				
				LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
				page = BufferGetPage(buf);
				
				loc = PageGetLSN(page); 
				
				if(Debug_filerep_print)
				{
					elog(LOG,	
							"incremental resync buffer pool identifier '%s' num blocks '%d' blkno '%d' lsn page '%s(%u/%u)' "
							"lsn end change tracking '%s(%u/%u)' ",
							relidstr,
							numBlocks,
							result->entries[ii].block_num,
							XLogLocationToString(&loc),
							loc.xlogid,
							loc.xrecoff,
							XLogLocationToString(&loc1),
							result->entries[ii].lsn_end.xlogid,
							result->entries[ii].lsn_end.xrecoff);					
				}
				else
				{
					char	tmpBuf[FILEREP_MAX_LOG_DESCRIPTION_LEN];
					
					snprintf(tmpBuf, sizeof(tmpBuf), 
							 "incremental resync buffer pool identifier '%s' num blocks '%d' blkno '%d' lsn page '%s(%u/%u)' ",
							 relidstr,
							 numBlocks,
							 result->entries[ii].block_num,
							 XLogLocationToString(&loc),
							 loc.xlogid,
							 loc.xrecoff);
					
					FileRep_InsertConfigLogEntry(tmpBuf);
					
					snprintf(tmpBuf, sizeof(tmpBuf), 
							 "incremental resync buffer pool identifier '%s' lsn end change tracking '%s(%u/%u)' ",
							 relidstr,
							 XLogLocationToString(&loc1),
							 result->entries[ii].lsn_end.xlogid,
							 result->entries[ii].lsn_end.xrecoff);
					
					FileRep_InsertConfigLogEntry(tmpBuf);
					
				}
								
				if (XLByteLE(result->entries[ii].lsn_end, PageGetLSN(page)))
				{
					if (! XLByteEQ(PageGetLSN(page), result->entries[ii].lsn_end))
					{
						ereport(LOG,
							(errmsg("Resynchonize buffer pool relation '%s' block '%d' has page lsn less than CT lsn, "
								"lsn end change tracking '%s(%u/%u)' lsn page '%s(%u/%u)' "
								"number of blocks '%d'",
								relidstr,
								result->entries[ii].block_num,
								XLogLocationToString(&loc),
								loc.xlogid,
								loc.xrecoff,
								XLogLocationToString(&loc1),
								loc1.xlogid,
								loc1.xrecoff,
								numBlocks),
							 FileRep_errcontext()));

					}

					/*
					 * It's safe and better to perform write of the page to mirror,
					 * for this case, as primary and mirror data pages should always
					 * be same. So, we might do some extra work but definitely won't
					 * loose out blocks, or error out and need to perform full recovery.
					 * Need to cover for this case as there are some known scenarios where
					 * CT file can have extra records which should have been discarded,
					 * but as we loose out information of xlog LSN cannot be discarded.
					 * One such case is when CT_TRANSIENT being compacted to CT_COMPACT
					 * with specific xlog LSN (to discard extra records) in CT mode gets
					 * interrupted by resync. Compaction during Resync collects all the
					 * CT records and doesn't have xlog LSN information to discard any
					 * extra records from CT_TRANSIENT.
					 */

					smgrwrite(smgr_relation,
							  result->entries[ii].block_num,
							  (char *)BufferGetBlock(buf),
							  FALSE);
				}

#ifdef FAULT_INJECTOR	
				FaultInjector_InjectFaultIfSet(
											   FileRepResyncWorker, 
											   DDLNotSpecified,
											   "",	// databaseName
											   ""); // tableName
#endif				
				
				UnlockReleaseBuffer(buf);
				
#ifdef FAULT_INJECTOR	
				FaultInjector_InjectFaultIfSet(
											   FileRepResyncWorker, 
											   DDLNotSpecified,
											   "",	// databaseName
											   ""); // tableName
#endif				
		
	flush_check:			
				if (((ii + 1) == result->count) ||
					! (result->entries[ii].relFileNode.spcNode == result->entries[ii+1].relFileNode.spcNode &&
					   result->entries[ii].relFileNode.dbNode == result->entries[ii+1].relFileNode.dbNode &&
					   result->entries[ii].relFileNode.relNode == result->entries[ii+1].relFileNode.relNode))
				{
					if (result->ask_for_more == false)
					{
								
						smgrimmedsync(smgr_relation);
						
						smgrclose(smgr_relation);
								 
						smgr_relation = NULL;
							
						FileRep_GetRelationPath(
												 entry.fileName, 
												 result->entries[ii].relFileNode, 
												 0 /* segment file number is always 0 for Buffer Pool */);							 
								 
						status = FileRepResync_UpdateEntry(&entry);
						if (status != STATUS_OK)
						{
							 break;
						}
					}
								 
				}			
							
				if (count > thresholdCount)
				{
					count = 0;
					FileRepSubProcess_ProcessSignals();
					
					if (! (FileRepSubProcess_GetState() == FileRepStateReady && 
						   dataState == DataStateInResync))
					{
						mirrorDataLossOccurred = TRUE;
						break;
					}
				}
				else
					count++;
			}  // for (ii = 0; ii < result->count; ii++)
			
		} // if ((result = ChangeTracking_GetChanges(request)) != NULL) 
		
		FileRepResync_ResetReadBufferRequest();
			
		if (result != NULL && result->ask_for_more == true)
		{
			Assert(request->count == 1);
			request->entries[0].lsn_start = result->next_start_lsn;
		}
		else
		{
			break;
		}

	} // while(1) 
		
	ChangeTracking_FreeRequest(request);
	ChangeTracking_FreeResult(result);
	
	Insist(NumberOfRelations == 0);
	
	if (mirrorDataLossOccurred)
		status = STATUS_ERROR;
	
	return status;	
}
Beispiel #7
0
/*
 * Receive Startup packet
 * Response Client Authentication
 */
int
FileRepConnServer_ReceiveStartupPacket(void)
{
	uint32	length;
	int		status = STATUS_OK;
	char	*buf = NULL;
	
	pq_init(); 

	status = FileRepConnServer_ReceiveMessageLength(&length);
	if (status != STATUS_OK) {
		goto exit;
	}
	
	if (length < (uint32) sizeof(ProtocolVersion) ||
		length > MAX_STARTUP_PACKET_LENGTH) {
		
		status = STATUS_ERROR;
		ereport(WARNING,
				(errcode(ERRCODE_PROTOCOL_VIOLATION), 
				 errmsg("invalid length of startup packet"),
				FileRep_errcontext()));
		goto exit;
	}
	
	buf = (char *)malloc(length +1);
	if (buf == NULL) {
		ereport(ERROR,
				(errcode(ERRCODE_OUT_OF_MEMORY),
				 errmsg("not enough memory to allocate buffer for startup packet"),
				FileRep_errcontext()));		
	}
	memset(buf, 0, length + 1);
	
	if (pq_getbytes(buf, length) == EOF) {
		
		status = STATUS_ERROR;
		ereport(WARNING,
				(errcode_for_socket_access(),
				 errmsg("receive EOF on connection: %m"),
				FileRep_errcontext()));
		goto exit;
	}
	
	port->proto = ntohl(*((ProtocolVersion *) buf));
	
	if (PG_PROTOCOL_MAJOR(port->proto) >= 3) {
	/*	uint32	offset = sizeof(ProtocolVersion);*/
	/* 
	 * tell the client that it is authorized (no pg_hba.conf and 
	 * password are required).
	 */
		StringInfoData	buf;
		
		/* sends AUTH_REQ_OK back to client */
		FakeClientAuthentication(port);
		
		/* send to client that we are ready to receive data */
		/* similar to ReadyForQuery(DestRemoteExecute); */
		pq_beginmessage(&buf, 'Z');
		pq_sendbyte(&buf, 'I');
		pq_endmessage(&buf);
		
		pq_flush();
	} else {	
		ereport(WARNING,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("not supported version"),
				FileRep_errcontext()));		
	}

exit:
	if (buf) {
		free(buf);
		buf = NULL;
	}
	
	return status;
}
/*
 * FileRepAckMirror_ConstructAndInsertMessage
 *			a) reserve ack shared memory
 *			b) construct message header 
 *			c) calculate message body crc
 *			d) calculate message header crc
 *			e) insert message header, message header crc and message body into ack shared memory
 *			f) set filerep message state to 'ready' so that message can be consumed
 *			g) signal send ack process so message will be sent to primary immediately
 */
static int 
FileRepAckMirror_ConstructAndInsertMessage(
										   FileRepIdentifier_u		fileRepIdentifier,
										   FileRepRelationType_e	fileRepRelationType,
										   FileRepOperation_e		fileRepOperation,
										   FileRepOperationDescription_u fileRepOperationDescription,
										   FileRepAckState_e		fileRepAckState,
										   uint32					messageBodyLength,
										   char						*messageBody)
{
	
	FileRepShmemMessageDescr_s	*fileRepShmemMessageDescr = NULL;
	FileRepMessageHeader_s		*fileRepMessageHeader = NULL;
	pg_crc32					*fileRepMessageHeaderCrc = 0;
	pg_crc32					fileRepMessageHeaderCrcLocal = 0;
	char						*msgPositionInsert = NULL;
	char						*fileRepMessageBody = NULL;
	uint32						msgLength = 0;
	uint32						spareField = 0;
	
	Assert(messageBodyLength == 0);
	
	msgLength = sizeof(FileRepMessageHeader_s) + sizeof(pg_crc32) + messageBodyLength;
	/*
	 * Shared memory is reserved in advance in order to avoid 
	 * holding lock during memcpy() and Crc calculation...
	 *
	 * Construct FileRepShmemMessageDescr_s 
	 */
	msgPositionInsert = FileRep_ReserveShmem(
											 fileRepAckShmemArray[FILEREP_OUTGOING_MESSAGE_QUEUE], 
											 msgLength, 
											 &spareField, 
											 fileRepOperation, 
											 FileRepAckShmemLock);
	
	if (msgPositionInsert == NULL) {
		
		ereport(WARNING,	
				(errmsg("mirror failure, "
						"could not queue ack message to be sent to primary, "
						"failover requested"),  	
				 errhint("run gprecoverseg to re-establish mirror connectivity"),
				 FileRep_errdetail(fileRepIdentifier,
								   fileRepRelationType,
								   fileRepOperation,
								   FILEREP_UNDEFINED),
				 FileRep_errdetail_ShmemAck(),
				 FileRep_errcontext()));	
		
		return STATUS_ERROR;
	}
	
	fileRepMessageHeader = 
	(FileRepMessageHeader_s *) (msgPositionInsert + 
								sizeof(FileRepShmemMessageDescr_s));
	
	fileRepMessageHeader->fileRepMessageHeaderVersion = FileRepMessageHeaderVersionOne;
	
	fileRepMessageHeader->fileRepRelationType = fileRepRelationType;
	
	fileRepMessageHeader->fileRepOperation = fileRepOperation;
	
	fileRepMessageHeader->fileRepIdentifier = fileRepIdentifier;
	
	fileRepMessageHeader->fileRepAckState = fileRepAckState;
	
	fileRepMessageHeader->messageCount = spareField;
	
	fileRepMessageHeader->messageBodyLength = messageBodyLength;
	
	if (messageBodyLength)
	{
		FileRep_CalculateCrc((char *) messageBody,
							 messageBodyLength,
							 &fileRepMessageHeader->fileRepMessageBodyCrc);
	}
	else
	{
		fileRepMessageHeader->fileRepMessageBodyCrc = 0;
	}
	
	switch (fileRepOperation) {
		case FileRepOperationReconcileXLogEof:
		case FileRepOperationValidation:
		case FileRepOperationCreate:
			fileRepMessageHeader->fileRepOperationDescription = fileRepOperationDescription;
			break;
			
		default:
			break;
	}
	
	/* 
	 * The following fields are not in use during fsync(). 
	 * They were zeroed during reserving message buffer.  
	 *		a) fileRepOperationDescription
	 *		b) fileRepMessageBodyCrc
	 *		c) messageCount
	 */
	
	fileRepMessageHeaderCrc =
	(pg_crc32 *) (msgPositionInsert + 
				  sizeof(FileRepMessageHeader_s) + 
				  sizeof(FileRepShmemMessageDescr_s));

	FileRep_CalculateCrc((char *) fileRepMessageHeader,
						 sizeof(FileRepMessageHeader_s),
						 &fileRepMessageHeaderCrcLocal);
	
	*fileRepMessageHeaderCrc = fileRepMessageHeaderCrcLocal;
	
	FileRep_InsertLogEntry(
						   "M_ConstructAndInsertMessageAck",
						   fileRepIdentifier,
						   fileRepRelationType,
						   fileRepOperation,
						   fileRepMessageHeaderCrcLocal,
						   FILEREP_UNDEFINED,
						   fileRepAckState,
						   FILEREP_UNDEFINED,
						   fileRepMessageHeader->messageCount);	

	if (Debug_filerep_print)
		ereport(LOG,
				(errmsg("M_ConstructAndInsertMessageAck construct and insert ack message "
						"msg header crc '%u' message body length '%d' position insert '%p' ack state '%s' ",
						fileRepMessageHeaderCrcLocal,
						messageBodyLength,
						msgPositionInsert,
						FileRepAckStateToString[fileRepAckState]),
				 FileRep_errdetail(fileRepIdentifier,
								   fileRepRelationType,
								   fileRepOperation,
								   fileRepMessageHeader->messageCount),
				 FileRep_errdetail_ShmemAck(),
				 FileRep_errcontext()));			
	
	if (messageBodyLength)
	{
		fileRepMessageBody = (char *) (msgPositionInsert + 
									   sizeof(FileRepMessageHeader_s) + 
									   sizeof(FileRepShmemMessageDescr_s) +
									   sizeof(pg_crc32));
		
		memcpy(fileRepMessageBody, messageBody, messageBodyLength);	
	}

	fileRepShmemMessageDescr = 
	(FileRepShmemMessageDescr_s*) msgPositionInsert;	
	
	fileRepShmemMessageDescr->messageSync = 
				FileRep_IsOperationSynchronous(fileRepOperation);		
	
	fileRepShmemMessageDescr->messageState = FileRepShmemMessageStateReady; 
	
	LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE);

	FileRep_IpcSignal(fileRepIpcArray[fileRepAckShmemArray[FILEREP_OUTGOING_MESSAGE_QUEUE]->ipcArrayIndex]->semC, 
					  &fileRepIpcArray[fileRepAckShmemArray[FILEREP_OUTGOING_MESSAGE_QUEUE]->ipcArrayIndex]->refCountSemC);
	LWLockRelease(FileRepAckShmemLock);
	
	return STATUS_OK;
}	
/*
 * SenderLoop
 *
 */
static int
FileRepAckMirror_RunSender(void)
{
	FileRepShmemMessageDescr_s	*fileRepShmemMessageDescr=NULL;
	char						*fileRepMessage;
	int							status = STATUS_OK;
	bool						movePositionConsume = FALSE;
	FileRepConsumerProcIndex_e  messageType;
	FileRepMessageHeader_s		*fileRepMessageHeader;
	FileRepShmem_s              *fileRepAckShmem = NULL;
	
	FileRep_InsertConfigLogEntry("run sender ack");
	
	fileRepAckShmem = fileRepAckShmemArray[FILEREP_OUTGOING_MESSAGE_QUEUE];

	while (1) {

		LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE);
		
		if (movePositionConsume) {
			
			fileRepAckShmem->positionConsume = 
					fileRepAckShmem->positionConsume +
					fileRepShmemMessageDescr->messageLength + 
					sizeof(FileRepShmemMessageDescr_s);
			
			if (fileRepAckShmem->positionConsume == fileRepAckShmem->positionWraparound &&
				fileRepAckShmem->positionInsert != fileRepAckShmem->positionWraparound) {
				
				fileRepAckShmem->positionConsume = fileRepAckShmem->positionBegin;
				fileRepAckShmem->positionWraparound = fileRepAckShmem->positionEnd;
			}
			
			FileRep_IpcSignal(fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->semP, 
							  &fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->refCountSemP);
		}
		
		fileRepShmemMessageDescr = 
		(FileRepShmemMessageDescr_s*) fileRepAckShmem->positionConsume;	
		
		while ((fileRepAckShmem->positionConsume == fileRepAckShmem->positionInsert) ||
			   ((fileRepAckShmem->positionConsume != fileRepAckShmem->positionInsert) &&
				(fileRepShmemMessageDescr->messageState != FileRepShmemMessageStateReady))) {
			
			fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->refCountSemC++;
			
			LWLockRelease(FileRepAckShmemLock);
			
			FileRepSubProcess_ProcessSignals();
			if (FileRepSubProcess_GetState() != FileRepStateReady) {

				LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE);
				break;
			}
			
			FileRep_IpcWait(fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->semC, &fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->refCountSemC, FileRepAckShmemLock);
						
			LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE); 
			
			if (fileRepAckShmem->positionConsume == fileRepAckShmem->positionWraparound &&
				fileRepAckShmem->positionInsert != fileRepAckShmem->positionWraparound) {
				
				fileRepAckShmem->positionConsume = fileRepAckShmem->positionBegin;
				fileRepAckShmem->positionWraparound = fileRepAckShmem->positionEnd;
			}			
			
			/* Re-assign to find if messageState is changed */
			fileRepShmemMessageDescr = 
			(FileRepShmemMessageDescr_s*) fileRepAckShmem->positionConsume;				
		} // while internal
		fileRepAckShmem->consumeCount++;
		
		LWLockRelease(FileRepAckShmemLock); 

		FileRepSubProcess_ProcessSignals();
		if (FileRepSubProcess_GetState() != FileRepStateReady) {
			break;
		}
	
		FileRep_InsertLogEntry(
							   "M_RunSenderAck",
							   FileRep_GetFlatFileIdentifier("", ""),
							   FileRepRelationTypeNotSpecified,
							   FileRepOperationNotSpecified,
							   FILEREP_UNDEFINED,
							   FILEREP_UNDEFINED,
							   FileRepAckStateNotInitialized,
							   FILEREP_UNDEFINED,
							   FILEREP_UNDEFINED);		
				
#ifdef FAULT_INJECTOR
		FaultInjector_InjectFaultIfSet(
									   FileRepSender,
									   DDLNotSpecified,
									   "",	//databaseName
									   ""); // tableName
#endif						
		
		fileRepMessage = (char*) (fileRepAckShmem->positionConsume + 
								  sizeof(FileRepShmemMessageDescr_s));
		
		fileRepMessageHeader = (FileRepMessageHeader_s*) (fileRepAckShmem->positionConsume + 
														  sizeof(FileRepShmemMessageDescr_s));

		messageType = FileRepMessageTypeXLog;
		
		if (! FileRepConnClient_SendMessage(
						messageType,
						fileRepShmemMessageDescr->messageSync,
						fileRepMessage,
						fileRepShmemMessageDescr->messageLength)) 
		{

			ereport(WARNING, 
					(errcode_for_socket_access(),
					 errmsg("mirror failure, "
							"could not sent ack message to primary : %m, "
							"failover requested"),
					 errhint("run gprecoverseg to re-establish mirror connectivity"),
					 FileRep_errdetail_ShmemAck(),
					 FileRep_errcontext()));		
			
			status = STATUS_ERROR;
			break;
		}

		movePositionConsume = TRUE;
	} // while(1)
	
	FileRepConnClient_CloseConnection();

	return status;
}
Beispiel #10
0
/*
 * FileRepAckPrimary_RunConsumer()
 */
static int
FileRepAckPrimary_RunConsumer(void)
{
	FileRepShmemMessageDescr_s	*fileRepShmemMessageDescr = NULL;
	FileRepMessageHeader_s		*fileRepMessageHeader = NULL;
	pg_crc32					*fileRepMessageHeaderCrc;
	pg_crc32					messageHeaderCrcLocal = 0;
	int							status = STATUS_OK;
	bool						movePositionConsume = FALSE;
	FileRepShmem_s              *fileRepAckShmem = NULL;
		
	FileRep_InsertConfigLogEntry("run consumer");
	
	fileRepAckShmem = fileRepAckShmemArray[FILEREP_ACKSHMEM_MESSAGE_SLOT_PRIMARY_ACK];
	
	while (1) {	
		
		LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE);
		
		if (movePositionConsume) {
			
			fileRepAckShmem->positionConsume = 
				fileRepAckShmem->positionConsume +
				fileRepShmemMessageDescr->messageLength + 
				sizeof(FileRepShmemMessageDescr_s);
			
			if (fileRepAckShmem->positionConsume == fileRepAckShmem->positionWraparound &&
				fileRepAckShmem->positionInsert != fileRepAckShmem->positionWraparound) {
				
				fileRepAckShmem->positionConsume = fileRepAckShmem->positionBegin;
				fileRepAckShmem->positionWraparound = fileRepAckShmem->positionEnd;
			}
			FileRep_IpcSignal(fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->semP, 
							  &fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->refCountSemP);
		}
				
		fileRepShmemMessageDescr = 
			(FileRepShmemMessageDescr_s*) fileRepAckShmem->positionConsume;	

		while ((fileRepAckShmem->positionConsume == fileRepAckShmem->positionInsert) ||
			   ((fileRepAckShmem->positionConsume != fileRepAckShmem->positionInsert) &&
				(fileRepShmemMessageDescr->messageState != FileRepShmemMessageStateReady))) {
			
			fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->refCountSemC++;

			LWLockRelease(FileRepAckShmemLock);
						
			FileRepSubProcess_ProcessSignals();
			if (FileRepSubProcess_GetState() != FileRepStateReady &&
				FileRepSubProcess_GetState() != FileRepStateInitialization) {
				LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE);
				break;
			}
			
			FileRep_IpcWait(fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->semC, &fileRepIpcArray[fileRepAckShmem->ipcArrayIndex]->refCountSemC, FileRepAckShmemLock);
			
			LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE);
			
			if (fileRepAckShmem->positionConsume == fileRepAckShmem->positionWraparound &&
				fileRepAckShmem->positionInsert != fileRepAckShmem->positionWraparound) {
				
				fileRepAckShmem->positionConsume = fileRepAckShmem->positionBegin;
				fileRepAckShmem->positionWraparound = fileRepAckShmem->positionEnd;
			}
			
			/* Re-assign to find if messageState is changed */
			fileRepShmemMessageDescr = 
				(FileRepShmemMessageDescr_s*) fileRepAckShmem->positionConsume;	
				
		} // internal while
		fileRepAckShmem->consumeCount++;
		LWLockRelease(FileRepAckShmemLock);
		
		FileRepSubProcess_ProcessSignals();
		if (FileRepSubProcess_GetState() != FileRepStateReady && 
			FileRepSubProcess_GetState() != FileRepStateInitialization) {
			break;
		}
		
		SIMPLE_FAULT_INJECTOR(FileRepConsumer);
		
		/* Calculate and compare FileRepMessageHeader_s Crc */
		fileRepMessageHeader = (FileRepMessageHeader_s*) (fileRepAckShmem->positionConsume + 
														  sizeof(FileRepShmemMessageDescr_s));
		
		FileRep_CalculateCrc((char *) fileRepMessageHeader,
							 sizeof(FileRepMessageHeader_s),
							 &messageHeaderCrcLocal);	
		
		fileRepMessageHeaderCrc =
			(pg_crc32 *) (fileRepAckShmem->positionConsume + 
						  sizeof(FileRepMessageHeader_s) + 
						  sizeof(FileRepShmemMessageDescr_s));
		
		if (*fileRepMessageHeaderCrc != messageHeaderCrcLocal) 
		{
			status = STATUS_ERROR;
			ereport(WARNING,
					(errmsg("mirror failure, "
							"could not match ack message header checksum between primary '%u' and mirror '%u', "
							"failover requested", 
							*fileRepMessageHeaderCrc, 
							messageHeaderCrcLocal),
					 errhint("run gprecoverseg to re-establish mirror connectivity"),
					 FileRep_errdetail(fileRepMessageHeader->fileRepIdentifier,
									   fileRepMessageHeader->fileRepRelationType,
									   fileRepMessageHeader->fileRepOperation,
									   fileRepMessageHeader->messageCount),
					 FileRep_errdetail_ShmemAck(),
					 FileRep_errcontext()));		
						
			break;
		}
				
	    /* Write operation is never acknowledged. 
		 * That means message should never have body. 
		 * CRC of body should be always 0.
		 */
		Assert(fileRepMessageHeader->fileRepOperation != FileRepOperationWrite);
		Assert(fileRepMessageHeader->fileRepMessageBodyCrc == 0);
		
		switch (fileRepMessageHeader->fileRepOperation)
		{
			case FileRepOperationReconcileXLogEof:			
				xLogEof = fileRepMessageHeader->fileRepOperationDescription.reconcile.xLogEof;

				if (Debug_filerep_print)
					ereport(LOG,
						(errmsg("ack reconcile xlogid '%d' xrecoff '%d' ",
							xLogEof.xlogid, 
							xLogEof.xrecoff)));	

				break;
		
			case FileRepOperationValidation:
				mirrorStatus = fileRepMessageHeader->fileRepOperationDescription.validation.mirrorStatus;

				if (Debug_filerep_print)
					ereport(LOG,
						(errmsg("ack validation status '%s' ",
							FileRepStatusToString[mirrorStatus])));	

				break;
				
			case FileRepOperationCreate:
				mirrorStatus = fileRepMessageHeader->fileRepOperationDescription.create.mirrorStatus;

				if (Debug_filerep_print)
					ereport(LOG,
						(errmsg("ack create status '%s' ",
								FileRepStatusToString[mirrorStatus])));	

				break;

			case FileRepOperationStartSlruChecksum:
				mirrorStatus =
					fileRepMessageHeader->fileRepOperationDescription.startChecksum.mirrorStatus;

				if (Debug_filerep_print)
				{
					ereport(LOG,
						(errmsg("ack start SLRU checksum: status = '%s', directory = '%s' ",
								FileRepStatusToString[mirrorStatus],
								fileRepMessageHeader->fileRepIdentifier.fileRepFlatFileIdentifier.directorySimpleName)));
				}

				break;

			case FileRepOperationVerifySlruDirectoryChecksum:
				mirrorStatus =
					fileRepMessageHeader->fileRepOperationDescription.verifyDirectoryChecksum.mirrorStatus;

				if (Debug_filerep_print)
				{
					ereport(LOG,
						(errmsg("ack verify SLRU directory checksum: status = '%s', directory = '%s' ",
								FileRepStatusToString[mirrorStatus],
								fileRepMessageHeader->fileRepIdentifier.fileRepFlatFileIdentifier.directorySimpleName)));
				}

				break;
				
			default:
				break;
		}
		
		if (fileRepMessageHeader->fileRepAckState != FileRepAckStateCompleted) {

			status = STATUS_ERROR;
			
			ereport(WARNING,
					(errmsg("mirror failure, "
							"could not complete operation on mirror ack state '%s', "
							"failover requested", 
							FileRepAckStateToString[fileRepMessageHeader->fileRepAckState]),
					 errhint("run gprecoverseg to re-establish mirror connectivity"),
					 errSendAlert(true),
					 FileRep_errdetail(fileRepMessageHeader->fileRepIdentifier,
									   fileRepMessageHeader->fileRepRelationType,
									   fileRepMessageHeader->fileRepOperation,
									   fileRepMessageHeader->messageCount),
					 FileRep_errdetail_Shmem(),
					 FileRep_errdetail_ShmemAck(),
					 FileRep_errcontext()));	
			
			/* 
			 * FAULT has to be set before entry is updated in ack hash table
			 * in order to suspend backend process.
			 */	
			FileRep_SetSegmentState(SegmentStateFault, FaultTypeMirror);
			FileRepSubProcess_ProcessSignals();
		}
				
		if (FileRepAckPrimary_UpdateHashEntry(
				fileRepMessageHeader->fileRepIdentifier,
				fileRepMessageHeader->fileRepRelationType,
				fileRepMessageHeader->fileRepAckState) != STATUS_OK) {
			
			status = STATUS_ERROR;
			ereport(WARNING,
					(errmsg("mirror failure, "
							"could not update ack state '%s' in ack hash table, "
							"failover requested", 
							FileRepAckStateToString[fileRepMessageHeader->fileRepAckState]),
					 errhint("run gprecoverseg to re-establish mirror connectivity"),
					 errSendAlert(true),
					 FileRep_errdetail(fileRepMessageHeader->fileRepIdentifier,
									   fileRepMessageHeader->fileRepRelationType,
									   fileRepMessageHeader->fileRepOperation,
									   fileRepMessageHeader->messageCount),
					 FileRep_errdetail_Shmem(),
					 FileRep_errdetail_ShmemAck(),
					 FileRep_errcontext()));					
		}
	
		FileRep_InsertLogEntry(
							   "P_RunConsumer",
							   fileRepMessageHeader->fileRepIdentifier,
							   fileRepMessageHeader->fileRepRelationType,
							   fileRepMessageHeader->fileRepOperation,
							   messageHeaderCrcLocal,
							   fileRepMessageHeader->fileRepMessageBodyCrc,
							   fileRepMessageHeader->fileRepAckState,
							   FILEREP_UNDEFINED,
							   fileRepMessageHeader->messageCount);				
		
		if (status != STATUS_OK) {
			break;
		}
				
		movePositionConsume = TRUE;		
	} // while(1)	
	
	return status;
}
Beispiel #11
0
/*
 * Backend checks if acknowledgement that its operation is completed
 * is received from mirror. 
 * If acknowledgement is received (state == FileRepAckStateCompleted) then
 *			a) entry is removed from hash
 *			b) TRUE is returned 
 */
bool 
FileRepAckPrimary_IsOperationCompleted(
					   FileRepIdentifier_u	 fileRepIdentifier,
					   FileRepRelationType_e fileRepRelationType)
{

	FileRepAckHashEntry_s	*entry = NULL;
	bool					isCompleted = FALSE;
	bool					isRemoved;
	FileName				fileName = NULL;
	int						retry = 0;
	bool					retval = FALSE;
	bool					wait = FALSE;

	fileName = FileRep_GetFileName(fileRepIdentifier, fileRepRelationType);
	
	while ((isCompleted == FALSE) && FileRep_IsRetry(retry)) 
	{
		
		LWLockAcquire(FileRepAckHashShmemLock, LW_EXCLUSIVE);
		
		entry = FileRepAckPrimary_LookupHashEntry(fileName);
		
		if (entry == NULL)
		{
			LWLockRelease(FileRepAckHashShmemLock);
			break;
		}
			
		if (! FileRep_IsIpcSleep(entry->fileRepOperation))
		{					
			if (wait == TRUE)
			{	
				wait = FALSE;
			}
		}
							
		switch (entry->fileRepAckState) 
		{
			case FileRepAckStateWaiting:
				/* No Operation */
				break;
			case FileRepAckStateCompleted:
				
				retval = TRUE;
				xLogEof = entry->xLogEof;
				mirrorStatus = entry->mirrorStatus;
				/* no BREAK */
			case FileRepAckStateMirrorInFault:
				
				isCompleted = TRUE;
				
				isRemoved = FileRepAckPrimary_RemoveHashEntry(fileName);
				
				Assert(isRemoved == TRUE);
				
				break;
			default:
				break;
		}
		
		if (isCompleted == false) 
		{
			if (! FileRep_IsIpcSleep(entry->fileRepOperation))
			{					
					fileRepIpcArray[fileRepAckHashShmem->ipcArrayIndex]->refCountSemP++;
					wait = TRUE;
			}
		}
		
		LWLockRelease(FileRepAckHashShmemLock);
		
		if (isCompleted == false) 
		{
			if (FileRepSubProcess_IsStateTransitionRequested())
			{
				break;
			}
			
			if (FileRep_IsIpcSleep(entry->fileRepOperation))
			{					
				FileRep_Sleep1ms(retry);
				
				if (retry == (3 * file_rep_retry / 4))
					ereport(WARNING,
						(errmsg("threshold '75' percent of 'gp_segment_connect_timeout=%d' is reached, "
								"mirror may not be able to keep up with primary, "
								"primary may transition to change tracking",
								gp_segment_connect_timeout),
						errhint("increase guc 'gp_segment_connect_timeout' by 'gpconfig' and 'gpstop -u' "),
						errSendAlert(true)));	

				FileRep_IncrementRetry(retry);
			}
			else
			{
				FileRep_IpcWait(fileRepIpcArray[fileRepAckHashShmem->ipcArrayIndex]->semP, &fileRepIpcArray[fileRepAckHashShmem->ipcArrayIndex]->refCountSemP, FileRepAckHashShmemLock);
			}			
			
			/*
			 * if the message was from the main filerep process then it is a
			 *   graceful shutdown message to the mirror.  We don't want to stall
			 *   shutdown if the mirror is unavailable so we wait a smaller amount
			 *   of time
			 */
			if ( entry->fileRepOperation == FileRepOperationShutdown &&
			     retry == 50)
            {
				FileRepAckPrimary_RemoveHashEntry(fileName);
                break;
            }
		}
	}
	
	if (retval == FALSE) 
	{
		mirrorStatus = FileRepStatusMirrorLossOccurred;
		
		if (! primaryMirrorIsIOSuspended())
		{
			ereport(WARNING,
					(errmsg("mirror failure, "
							"could not complete mirrored request identifier '%s' ack state '%s', "
							"failover requested",
							(fileName == NULL) ? "<null>" : fileName,
							(entry == NULL) ? "<entry not found>" : FileRepAckStateToString[entry->fileRepAckState]),
					 errhint("run gprecoverseg to re-establish mirror connectivity"),
					 FileRep_errdetail_ShmemAck(),
					 FileRep_errcontext()));	
		}
	}
	
	if (fileName) 
	{
		pfree(fileName);
		fileName = NULL;
	}		
	
	return retval;
}
Beispiel #12
0
/*
 * Consumer process on Primary update the state in the hash entry 
 */		
static int 
FileRepAckPrimary_UpdateHashEntry(
					FileRepIdentifier_u		fileRepIdentifier,
					FileRepRelationType_e	fileRepRelationType,
					FileRepAckState_e		fileRepAckState)
{

	FileRepAckHashEntry_s	*entry;
	bool					exists;
	int						status = STATUS_OK;
	FileName				fileName = NULL;
	
	fileName = FileRep_GetFileName(fileRepIdentifier, fileRepRelationType);
	
	LWLockAcquire(FileRepAckHashShmemLock, LW_EXCLUSIVE);
	
	entry = FileRepAckPrimary_InsertHashEntry(fileName, &exists);
				
	/* entry should be found since ack has not been processed yet */			
	Assert(entry != NULL);
				
	if (!exists) 
	{
		LWLockRelease(FileRepAckHashShmemLock);
		
		if (fileRepRelationType == FileRepRelationTypeUnknown)
		{
			goto exit;
		}
		
		status = STATUS_ERROR;
		ereport(WARNING,
				(errmsg("mirror failure, "
						"could not update ack entry with ack status, no entry found "
						"identifier '%s' relation type '%s' "
						"failover requested", 
						(fileName == NULL) ? "<null>" : fileName,
						FileRepRelationTypeToString[fileRepRelationType]),
				 errhint("run gprecoverseg to re-establish mirror connectivity"),
				 FileRep_errcontext()));	
		
		goto exit;
	}

	entry->fileRepAckState = fileRepAckState;
	
	entry->xLogEof = xLogEof;
	entry->mirrorStatus = mirrorStatus;
	
	FileRep_IpcSignal(fileRepIpcArray[fileRepAckHashShmem->ipcArrayIndex]->semP, 
					  &fileRepIpcArray[fileRepAckHashShmem->ipcArrayIndex]->refCountSemP);

	LWLockRelease(FileRepAckHashShmemLock);
		
	if (Debug_filerep_print)	
		ereport(LOG,
			(errmsg("update hash entry identifier '%s' ack state '%s' ",
					(entry->fileName == NULL) ? "<null>" : entry->fileName, 
					FileRepAckStateToString[entry->fileRepAckState])));

exit:	
	if (fileName) 
	{
		pfree(fileName);
		fileName = NULL;
	}		
	
	return status;			
}
Beispiel #13
0
/*
 * It is called by backend process to insert new ack entry into hash table. 
 */		
int 
FileRepAckPrimary_NewHashEntry(
					FileRepIdentifier_u		fileRepIdentifier, 
					FileRepOperation_e		fileRepOperation,
					FileRepRelationType_e	fileRepRelationType)
{

	FileRepAckHashEntry_s	*entry=NULL;
	bool					exists = FALSE;
	FileName				fileName = NULL;
	int						status = STATUS_OK;
	int						retry = 0;
	bool					wait = FALSE;
		
	fileName = FileRep_GetFileName(fileRepIdentifier, fileRepRelationType);
		
	while (FileRep_IsRetry(retry)) {
		LWLockAcquire(FileRepAckHashShmemLock, LW_EXCLUSIVE);
		

		if (! FileRep_IsIpcSleep(fileRepOperation))
		{
			if (wait == TRUE)
			{	
				wait = FALSE;
			}
		}
		
		entry = FileRepAckPrimary_InsertHashEntry(fileName, &exists);
					
		if (entry == NULL) 
		{
			LWLockRelease(FileRepAckHashShmemLock);
			status = STATUS_ERROR;
			
			ereport(WARNING,
					(errmsg("mirror failure, "
							"could not insert ack entry into ack table, no memory "
							"failover requested"), 
					 errhint("run gprecoverseg to re-establish mirror connectivity"),
					 FileRep_errdetail(fileRepIdentifier,
									   fileRepRelationType,
									   fileRepOperation,
									   FILEREP_UNDEFINED),				 
					 FileRep_errcontext()));	
			
			goto exit;
		}
					
		if (exists) 
		{
			if (! FileRep_IsIpcSleep(fileRepOperation))
			{					
					fileRepIpcArray[fileRepAckHashShmem->ipcArrayIndex]->refCountSemC++;
					wait = TRUE;
			}
			
			LWLockRelease(FileRepAckHashShmemLock);
			if (FileRepSubProcess_IsStateTransitionRequested())
			{
				status = STATUS_ERROR;
				break;
			}	
			
			if (FileRep_IsIpcSleep(fileRepOperation))
			{					
				FileRep_Sleep1ms(retry);
				FileRep_IncrementRetry(retry);
			}
			else
			{
				FileRep_IpcWait(fileRepIpcArray[fileRepAckHashShmem->ipcArrayIndex]->semC, &fileRepIpcArray[fileRepAckHashShmem->ipcArrayIndex]->refCountSemC, FileRepAckHashShmemLock);
			}	
			
			continue;
		}

		entry->fileRepOperation = fileRepOperation;
		entry->fileRepRelationType = fileRepRelationType;
		entry->fileRepAckState = FileRepAckStateWaiting;
		entry->xLogEof = xLogEof;
		entry->mirrorStatus = FileRepStatusSuccess;
		
		LWLockRelease(FileRepAckHashShmemLock);
		break;
	}

	if (exists) {
		status = STATUS_ERROR;
		
		ereport(WARNING,
				(errmsg("mirror failure, "
						"could not insert ack entry into ack table, entry exists "
						"failover requested"), 
				 errhint("run gprecoverseg to re-establish mirror connectivity"),
				 FileRep_errdetail(fileRepIdentifier,
								   fileRepRelationType,
								   fileRepOperation,
								   FILEREP_UNDEFINED),				 
				 FileRep_errcontext()));	
	} 
	
exit:
	
	if (fileName) 
	{
		pfree(fileName);
		fileName = NULL;
	}		
	
	return status;			
}
Beispiel #14
0
static int
FileRepAckPrimary_RunReceiver(void)
{
	uint32_t				msgLength = 0;
	FileRepConsumerProcIndex_e	msgType;
	int						status = STATUS_OK;
	char					*msgPositionInsert;
	FileRepShmemMessageDescr_s  *fileRepShmemMessageDescr;
	uint32					spareField;
	
	FileRep_InsertConfigLogEntry("run receiver");
	
	while (1) {
		
		FileRepSubProcess_ProcessSignals();
		if (FileRepSubProcess_GetState() != FileRepStateReady &&
			FileRepSubProcess_GetState() != FileRepStateInitialization) {
			break;
		}
		
		if ( ! FileRepConnServer_AwaitMessageBegin()) {
			/* call was interrupted ... go back to beginning to process signals */
			continue;
		}

		status = FileRepConnServer_ReceiveMessageType(&msgType);
		
		if (status != STATUS_OK) {
			break;
		}
				
		/* DATA MESSAGE TYPE */
		status = FileRepConnServer_ReceiveMessageLength(&msgLength);
		
		if (status != STATUS_OK) {
			break;
		}

		msgPositionInsert = FileRep_ReserveShmem(fileRepAckShmemArray[msgType], 
												 msgLength, 
												 /* not used */ &spareField, 
												 FileRepOperationNotSpecified, 
												 FileRepAckShmemLock);
		
		if (msgPositionInsert == NULL) {
			
			status = STATUS_ERROR;
			ereport(WARNING,
					(errmsg("mirror failure, "
							"could not queue received ack message to be processed, "
							"failover requested"), 
					 errhint("run gprecoverseg to re-establish mirror connectivity"),
					 FileRep_errdetail_Shmem(),
					 FileRep_errdetail_ShmemAck(),
					 FileRep_errcontext()));													
			break;
		}
		
		status = FileRepConnServer_ReceiveMessageData(
						msgPositionInsert + sizeof(FileRepShmemMessageDescr_s),
						msgLength);
		
		if (status != STATUS_OK) {
			break;
		}		
		
		SIMPLE_FAULT_INJECTOR(FileRepReceiver);
		
		fileRepShmemMessageDescr = 
		(FileRepShmemMessageDescr_s*) msgPositionInsert;	
		
		/* it is not in use */
		fileRepShmemMessageDescr->messageSync = FALSE;
		
		fileRepShmemMessageDescr->messageState = FileRepShmemMessageStateReady; 
		
		LWLockAcquire(FileRepAckShmemLock, LW_EXCLUSIVE);
		
		FileRep_IpcSignal(fileRepIpcArray[fileRepAckShmemArray[msgType]->ipcArrayIndex]->semC, 
						  &fileRepIpcArray[fileRepAckShmemArray[msgType]->ipcArrayIndex]->refCountSemC);
		
		LWLockRelease(FileRepAckShmemLock);
		
		FileRep_InsertLogEntry(
							   "P_RunReceiver",
							   FileRep_GetFlatFileIdentifier("", ""),
							   FileRepRelationTypeNotSpecified,
							   FileRepOperationNotSpecified,
							   FILEREP_UNDEFINED,
							   FILEREP_UNDEFINED,
							   FileRepAckStateNotInitialized,
							   spareField,
							   FILEREP_UNDEFINED);			
		
	} // while(1)
	
	FileRepConnServer_CloseConnection();
	
	return status;
}
Beispiel #15
0
/*
 * 
 * FileRepAckPrimary_StartReceiver
 */
void 
FileRepAckPrimary_StartReceiver(void)
{	
	int				status = STATUS_OK;
	struct timeval	currentTime;
	pg_time_t		beginTime = 0;
	pg_time_t		endTime = 0;	
	int				retval = 0;
	
	FileRep_InsertConfigLogEntry("start receiver ack");

	{
		char	tmpBuf[FILEREP_MAX_LOG_DESCRIPTION_LEN];
		
		snprintf(tmpBuf, sizeof(tmpBuf), "primary address(port) '%s(%d)' mirror address(port) '%s(%d)' ",
				 fileRepPrimaryHostAddress, 
				 fileRepPrimaryPort,
				 fileRepMirrorHostAddress, 
				 fileRepMirrorPort);
		
		FileRep_InsertConfigLogEntry(tmpBuf);
	}
		
	FileRepAckPrimary_ShmemReInit();
	
	Insist(fileRepRole == FileRepPrimaryRole);
	
	if (filerep_inject_listener_fault)
	{
		status = STATUS_ERROR;
		ereport(WARNING,
				(errmsg("mirror failure, "
						"injected fault by guc filerep_inject_listener_fault, "
						"failover requested"), 
				 FileRep_errcontext()));												
		
		FileRep_SetSegmentState(SegmentStateFault, FaultTypeMirror);
		FileRepSubProcess_SetState(FileRepStateFault);
		FileRepSubProcess_ProcessSignals();
		return;
	}
	
	status = FileRepConnServer_StartListener(
								 fileRepPrimaryHostAddress,
								 fileRepPrimaryPort);
	
	gettimeofday(&currentTime, NULL);
	beginTime = (pg_time_t) currentTime.tv_sec;
	
	while (1) {
		
		if (status != STATUS_OK) 
		{
			FileRep_SetSegmentState(SegmentStateFault, FaultTypeMirror);
			FileRepSubProcess_SetState(FileRepStateFault);
		}
		
		while (FileRepSubProcess_GetState() == FileRepStateFault) {
			
			FileRepSubProcess_ProcessSignals();
			pg_usleep(50000L); /* 50 ms */	
		}
		
		if (FileRepSubProcess_GetState() == FileRepStateShutdown) {
			
			break;
		}

		PG_SETMASK(&BlockSig);
		retval = FileRepConnServer_Select();	
		PG_SETMASK(&UnBlockSig);
		
		gettimeofday(&currentTime, NULL);
		endTime = (pg_time_t) currentTime.tv_sec;

		if ((endTime - beginTime) > gp_segment_connect_timeout) 
		{
			ereport(WARNING, 
					(errmsg("mirror failure, "
							"no connection was established from client from mirror, "
							"primary address(port) '%s(%d)' mirror address(port) '%s(%d)' timeout reached '%d' "
							"failover requested",
							fileRepPrimaryHostAddress, 
							fileRepPrimaryPort,
							fileRepMirrorHostAddress, 
							fileRepMirrorPort,
							gp_segment_connect_timeout),
					 errSendAlert(true),
					 FileRep_errcontext()));
			
			status = STATUS_ERROR;
			continue;
		}

		/* 
		 * check and process any signals received 
		 * The routine returns TRUE if the received signal requests
		 * process shutdown.
		 */
		if (FileRepSubProcess_ProcessSignals()) {
			continue;
		}
		
		if (retval < 0) {
			status = STATUS_ERROR;
			continue;
		}
		
		if (retval == 0) {
			continue;
		}
		
		Assert(retval > 0);
		
		status = FileRepConnServer_CreateConnection();
		
		if (status != STATUS_OK) {
			continue;
		}				
		
		status = FileRepConnServer_ReceiveStartupPacket();
		if (status != STATUS_OK) {
			continue;
		} 
		
		fileRepShmemArray[0]->state = FileRepStateInitialization;
		
		status = FileRepAckPrimary_RunReceiver();
		
	} // while(1)
			
	FileRepConnServer_CloseConnection();
	
	return;
}