예제 #1
0
void WriteReadyHandler_Connect(AsyncCommBuffer buffer)
{
    /* Check the error from socket FD. */
    bool 	  shouldclose = false;
    int  	  error 	  = 0;
    socklen_t errlen 	  = sizeof(error);

    elog(DEBUG3, "AsyncConn FD %d is write ready for checking connection.",
         buffer->FD);

    int res = getsockopt(buffer->FD, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
    if (res < 0)
    {
        elog(WARNING, "getsocketopt() on FD %d have errors raised. errno %d",
             buffer->FD,
             errno);
        shouldclose = true;
    }
    else if ( error > 0 )
    {
        elog(WARNING, "FD %d having errors raised. errno %d",
             buffer->FD,
             error);
        shouldclose = true;
    }

    if ( setConnectionLongTermNoDelay(buffer->FD) != FUNC_RETURN_OK )
    {
        shouldclose = true;
    }

    if ( shouldclose )
    {
        ErrorHandler_Connect(buffer);
        forceCloseFileDesc(buffer);
        return;
    }

    elog(DEBUG3, "AsyncConn FD %d is a good connection.", buffer->FD);

    /* Change to normal registered FD by changing callbacks and arguments. */
    AsyncCommBufferHandlerUser userdata = (AsyncCommBufferHandlerUser)(buffer->UserData);

    buffer->ActionMask = userdata->ActionMaskForAfterConn;
    buffer->UserData   = userdata->UserDataForAfterConn;
    buffer->Methods    = userdata->MethodsForAfterConn;
    Assert(getSMBContentSize(&(buffer->ReadBuffer)) == 0);

    elog(DEBUG3, "Freed AsyncComm Conn context ( connected ).");

    rm_pfree(AsyncCommContext, userdata);
}
void WritePostHandler_Message(AsyncCommBuffer buffer)
{
	AsyncCommMessageHandlerContext context = (AsyncCommMessageHandlerContext)
											 (buffer->UserData);
	int msgsize = getSMBContentSize(&(buffer->ReadBuffer));
	if ( msgsize == 0 )
	{
		Assert( context->MessageSentHandler != NULL );
		context->MessageSentHandler(context);
	}

	elog(DEBUG3, "Write post handler for client message is called.");

	performErrorActionForWritingMessage(buffer, false);
}
예제 #3
0
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 ReadPostHandler_Message(AsyncCommBuffer buffer)
{
	AsyncCommMessageHandlerContext context = (AsyncCommMessageHandlerContext)
											 (buffer->UserData);
	int msgsize = getSMBContentSize(&(buffer->ReadBuffer));
	if ( !context->inMessage )
	{
		/* Check if having message head. */
		if ( msgsize >= DRM_MSGFRAME_HEADTAGSIZE )
		{
			char *p = buffer->ReadBuffer.Buffer;
			if ( DRM_MSGFRAME_HEADTAG_MATCHED(p) )
			{
				context->inMessage = true;
			}
			else
			{
				/*
				 * This protocol does not allow content not wrapped by message
				 * framework, therefore, here we force to close the connection.
				 * No more processing is needed.
				 */
				buffer->forcedClose = true;
				buffer->toClose     = true;
				elog(WARNING, "AsyncComm framework received invalid message head. "
							  "Close the connection FD %d.",
							  buffer->FD);
				return;
			}
		}
		else
		{
			/* Not a complete message frame head tag. Wait for new content. */
			return;
		}
	}

	/*
	 * If we are in one message, and its header was completed received, we parse
	 * the header to get the expected message content.
	 */
	if ( context->inMessage && msgsize >= DRM_MSGFRAME_HEADSIZE )
	{
		/* Check if achieve the end of message. */
		RMMessageHead header = (RMMessageHead)(buffer->ReadBuffer.Buffer);
		if ( DRM_MSGFRAME_TOTALSIZE(header) <= msgsize )
		{
			char *p = buffer->ReadBuffer.Buffer + header->MessageSize +
					  DRM_MSGFRAME_HEADSIZE;
			if ( DRM_MSGFRAME_TAILTAG_MATCHED(p) )
			{
				/* Skip heart-beat message log. */
				elog((header->MessageID == REQUEST_QD_REFRESH_RESOURCE ||
					  header->MessageID == REQUEST_RM_IMALIVE          ||
					  header->MessageID == RESPONSE_QD_REFRESH_RESOURCE ||
					  header->MessageID == RESPONSE_RM_IMALIVE) ? DEBUG3 : LOG,
					 "AsyncComm framework receives message %d from FD %d",
					 header->MessageID,
					 buffer->FD);

				/* Get complete message and call the handler. */
				if ( context->MessageRecvedHandler != NULL )
				{
					/* Check and perform error injection action. */
					performMessageForErrorAction(header->MessageID,
												 true,	/* read content.      */
												 true,	/* before processing. */
												 buffer);

					if ( CAN_PROCESS_RECEIVED(buffer->forceErrorAction) )
					{
						header = (RMMessageHead)(buffer->ReadBuffer.Buffer);
						context->MessageRecvedHandler(context,
													  header->MessageID,
													  header->Mark1,
													  header->Mark2,
													  buffer->ReadBuffer.Buffer +
														  DRM_MSGFRAME_HEADSIZE,
													  header->MessageSize);
					}

					/* Check and perform error injection action. */
					performMessageForErrorAction(header->MessageID,
												 true,	/* read content.      */
												 false,	/* after processing.  */
												 buffer);
				}
				/* Shift out this message */
				shiftLeftSelfMaintainBuffer(&(buffer->ReadBuffer),
											DRM_MSGFRAME_TOTALSIZE(header));
				/* Set out of the message */
				context->inMessage = false;
			}
			else
			{
				/* We get wrong message content. */
				elog(WARNING, "AsyncComm framework received wrong message tail "
							  "content.");
				buffer->forcedClose = true;
				buffer->toClose     = true;
			}
		}
	}
}