void buildMessageToCommBuffer(AsyncCommBuffer   buffer,
							  const char 	   *content,
							  int   	 		contentsize,
							  uint16_t 	 		messageid,
							  uint8_t    		mark1,
							  uint8_t    		mark2)
{
	static char messagehead[DRM_MSGFRAME_HEADSIZE]   = DRM_MSGFRAME_HEADTAG_STR;
	static char messagetail[DRM_MSGFRAME_TAILSIZE+1] = DRM_MSGFRAME_TAILTAG_STR;
	RMMessageHead phead = (RMMessageHead)messagehead;
	RMMessageTail ptail = (RMMessageTail)messagetail;

	/* Append message head. */
	phead->Mark1       = mark1;
	phead->Mark2       = mark2;
	phead->MessageID   = messageid;
	phead->MessageSize = contentsize;

	SelfMaintainBuffer newbuff = createSelfMaintainBuffer(AsyncCommContext);

	appendSelfMaintainBuffer(newbuff, (char *)phead, sizeof(*phead));
	/* Append actual message content. */
	appendSelfMaintainBuffer(newbuff, (char *)content, contentsize);
	/* Append message tail. */
	appendSelfMaintainBuffer(newbuff, (char *)ptail, sizeof(*ptail));

	addMessageContentToCommBuffer(buffer, newbuff);
}
void SimpleStringReplaceFirst(SimpStringPtr str, char *oldstr, char *newstr)
{
	char *pos = strstr(str->Str, oldstr);
	/* If the old string does not exist, no need to do any update. */
	if ( pos == NULL )
		return;

	SelfMaintainBufferData smb;
	initializeSelfMaintainBuffer(&smb, str->Context);
	if ( str->Str != pos ) {
		appendSelfMaintainBuffer(&smb, str->Str, pos - str->Str);
	}
	int oldstrlen = strlen(oldstr);
	appendSelfMaintainBuffer(&smb, newstr, strlen(newstr));
	if ( oldstrlen + (pos - str->Str) < str->Len ) {
		appendSMBStr(&smb, pos + oldstrlen);
	}
	setSimpleStringWithContent(str, smb.Buffer, getSMBContentSize(&smb));
	destroySelfMaintainBuffer(&smb);
}
void receivedSyncRPCResponse(AsyncCommMessageHandlerContext  context,
							 uint16_t						 messageid,
							 uint8_t						 mark1,
							 uint8_t						 mark2,
							 char 							*buffer,
							 uint32_t						 buffersize)
{
	SyncRPCContext userdata = (SyncRPCContext)(context->UserData);
	Assert(userdata != NULL);

	userdata->CommStatus = SYNC_RPC_COMM_IDLE;

	if ( userdata->ExpMessageID == messageid ) {
		resetSelfMaintainBuffer(userdata->RecvBuffer);
		appendSelfMaintainBuffer(userdata->RecvBuffer, buffer, buffersize);
		userdata->RecvMark1 = mark1;
		userdata->RecvMark2 = mark2;
		userdata->Result    = FUNC_RETURN_OK;
	}
	else {
		userdata->Result    = REQUESTHANDLER_WRONGMESSAGE;
	}
}
/******************************************************************************
 * I aM Alive.
 *
 * Request:
 *         |<----------- 64 bits (8 bytes) ----------->|
 *         +----------+--------------------------------+
 *         |  TDC     |  BDC     |     Reserved        |
 * 		   +----------+----------+---------------------+
 *         |                                           |
 *         |             Machine ID info               |
 *         |                                           |
 * 		   +-------------------------------------------+     _____ 64bit aligned
 *
 * Response:
 *         |<----------- 64 bits (8 bytes) ----------->|
 *         +---------------------+---------------------+
 *         |  heartbeat result   |    Reserved   	   |
 * 		   +---------------------+---------------------+     _____ 64bit aligned
 *
 ******************************************************************************/
int sendIMAlive(int  *errorcode,
				char *errorbuf,
				int	  errorbufsize)
{
	int 				res 					= FUNC_RETURN_OK;
	AsyncCommBuffer		newcommbuffer			= NULL;

	Assert( DRMGlobalInstance->LocalHostStat != NULL );

	/* Build request. */
	SelfMaintainBufferData tosend;
	initializeSelfMaintainBuffer(&tosend, PCONTEXT);

	RPCRequestHeadIMAliveData requesthead;
	requesthead.TmpDirCount 	  = getDQueueLength(&DRMGlobalInstance->LocalHostTempDirectories);
	requesthead.TmpDirBrokenCount = DRMGlobalInstance->LocalHostStat->FailedTmpDirNum;
	requesthead.Reserved		  = 0;

	appendSMBVar(&tosend, requesthead);
	appendSelfMaintainBuffer(&tosend,
							 (char *)(DRMGlobalInstance->LocalHostStat),
							 offsetof(SegStatData, Info) +
							 DRMGlobalInstance->LocalHostStat->Info.Size);

	/* Set content to send and add to AsyncComm framework. */
	AsyncCommMessageHandlerContext context =
			rm_palloc0(AsyncCommContext,
					   sizeof(AsyncCommMessageHandlerContextData));
	context->inMessage				 = false;
	context->UserData  				 = NULL;
	context->MessageRecvReadyHandler = NULL;
	context->MessageRecvedHandler 	 = receivedIMAliveResponse;
	context->MessageSendReadyHandler = NULL;
	context->MessageSentHandler		 = sentIMAlive;
	context->MessageErrorHandler 	 = sentIMAliveError;
	context->MessageCleanUpHandler	 = sentIMAliveCleanUp;

	/* Connect to HAWQ RM server */

	res = registerAsyncConnectionFileDesc(NULL,
										  DRMGlobalInstance->SendToStandby?
										  standby_addr_host:
										  master_addr_host,
										  rm_master_port,
										  ASYNCCOMM_READBYTES | ASYNCCOMM_WRITEBYTES,
										  &AsyncCommBufferHandlersMessage,
										  context,
										  &newcommbuffer);
	if ( res != FUNC_RETURN_OK )
	{
		rm_pfree(AsyncCommContext, context);
		elog(WARNING, "Fail to register asynchronous connection for sending "
					  "IMAlive message. %d", res);
		return res;
	}

	buildMessageToCommBuffer(newcommbuffer,
							 tosend.Buffer,
							 tosend.Cursor + 1,
							 REQUEST_RM_IMALIVE,
							 0,
							 0);

	destroySelfMaintainBuffer(&tosend);

	context->AsyncBuffer = newcommbuffer;

	InitHandler_Message(newcommbuffer);

	return FUNC_RETURN_OK;
}