C로 메시지 처리 또는 출력 노드 작성

시작하기 전에

LIL(Loadable Implementation Library)는 C 노드(또는 구문 분석기)용 구현 모듈입니다. LIL은 DLL(Dynamic Link Library)로 구현되며 파일 확장자 .dll이 아닌 .lil을 가집니다.

개발자가 작성해야 하는 구현 함수는 C 노드 구현 함수에 나열되어 있습니다. 이 프로세스를 돕기 위해 WebSphere Message Broker가 제공하는 유틸리티 함수는 C 노드 유틸리티 함수에 나열되어 있습니다.

WebSphere Message Broker에서는 두 개의 샘플 사용자 정의 노드, 즉 SwitchNode 및 TransformNode의 소스를 제공합니다. 현재 상태에서 이 노드를 사용하거나 수정할 수 있습니다. 사용할 User-defined Extension 샘플도 있습니다.

개념적으로, 메시지 처리 노드는 메시지를 일정 방식으로 처리하는 데 사용되고, 출력 노드는 메시지를 비트스트림으로 출력하는 데 사용됩니다. 그러나, 메시지 처리 노드와 출력 노드는 코딩할 때 근본적인 공통점이 있습니다. 출력 노드 내에서도 메시지 처리를 수행할 수 있으며, 마찬가지로 메시지 처리 노드를 사용하여 메시지를 비트스트림으로 출력할 수도 있습니다. 간단히 말해, 이 주제에서는 주로 메시지 처리 노드로서의 노드에 관해 언급하지만, 두 가지 유형의 노드의 기능성을 설명합니다.

본 주제에서는 두 가지 유형의 노드 함수에 대해 다룹니다. 다음 단계에 대한 개요가 제공됩니다.
  1. 브로커에 노드 선언
  2. 노드를 메시지 처리 노드로 정의
  3. 노드의 인스턴스 작성
  4. 속성 설정
  5. 노드 기능 구현
  6. 메시지 처리 노드 인스턴스 삭제

브로커에 노드 선언

다음 프로시저는 노드를 브로커에 선언하는 방법을 표시합니다.

  1. LIL이 운영 체제에 로드되어 초기화된 후, 브로커는 초기화 함수 bipGetMessageflowNodeFactory를 호출합니다. 이는 브로커 구성 스레드에서 호출됩니다. 브로커는 LIL이 수행할 수 있는 사항과 브로커가 LIL을 호출하는 방법을 이해하기 위해 이 함수를 호출합니다. 예를 들면, 다음 코드와 같습니다.
    CciFactory LilFactoryExportPrefix * LilFactoryExportSuffix
    bipGetMessageflowNodeFactory()
  2. 그 다음 bipGetMessageflowNodeFactory 함수는 유틸리티 함수 cniCreateNodeFactory를 호출합니다. 이 함수는 LIL이 지원하는 모든 노드의 팩토리 이름(그룹 이름)을 내보냅니다. 예를 들면, 다음 코드와 같습니다.
    {
    	CciFactory* factoryObject;
    	int rc = 0;
    	CciChar factoryName[] = L"SwitchNodeFactory";
    	CCI_EXCEPTION_ST exception_st;
    
    	/* Create the Node Factory for this node */
    	factoryObject = cniCreateNodeFactory(0, factoryName);
    	if (factoryObject == CCI_NULL_ADDR) {
    		if (rc == CCI_EXCEPTION) {
    			/* Get details of the exception */
    			cciGetLastExceptionData(&rc, &exception_st);
    
    			/* Any local error handling can go here */
    
    			/* Rethrow the exception */
    			cciRethrowLastException(&rc);
    		}
    
    		/* Any further local error handling can go here */
    	}
    	else {
    		/* Define the nodes supported by this factory */
    		defineSwitchNode(factoryObject);
    	}
    
    	/* Return address of this factory object to the broker */
    	return(factoryObject);
    }

    이 예에서 UTF-16에 추적 정보가 필요하면 CCI_EXCEPTION_ST를 CCI_EXCEPTION_WIDE_ST로 바꾸고 cciGetLastExceptionDatacciGetLastExceptionDataW로 바꿔야 합니다.

노드를 메시지 처리 노드로 정의

그 다음 LIL은 유틸리티 함수 cniDefineNodeClass를 호출하여 각 노드의 이름 및 구현 함수 주소의 가상 함수 테이블을 전달합니다. 예를 들어, SwitchNode라는 하나의 노드 및 해당 함수 테이블을 정의하는 코드는 다음과 같습니다.
void defineSwitchNode(void* factoryObject){
	static CNI_VFT vftable = {CNI_VFT_DEFAULT};

	/* Setup function table with pointers to node implementation functions */
	vftable.iFpCreateNodeContext = _createNodeContext;
	vftable.iFpDeleteNodeContext = _deleteNodeContext;
	vftable.iFpGetAttributeName2 = _getAttributeName2;
	vftable.iFpSetAttribute = _setAttribute;
	vftable.iFpGetAttribute2     = _getAttribute2;
	vftable.iFpEvaluate = _evaluate;

	cniDefineNodeClass(0, factoryObject, L"SwitchNode", &vftable);

	return;
}
이는 구성 스레드에서 호출됩니다.

사용자 정의 노드는 cniEvaluate 함수를 구현하여 메시지 처리 또는 출력 노드의 성능을 제공할 때 자체적으로 식별을 확인합니다. 사용자 정의 노드는 cniEvaluate 또는 cniRun 구현 함수 중 하나 또는 두 가지 모두를 구현해야 합니다. 아니면, 브로커는 사용자 정의 노드를 로드하지 못하고 cniDefineNodeClass 유틸리티 함수가 실패하면서 CCI_MISSING_IMPL_FUNCTION이 리턴됩니다.

사용자 정의 메시지 처리 노드가 포함된 메시지 플로우가 정상적으로 전개될 때, 메시지 플로우를 통해 전달된 각 메시지마다 노드의 cniEvaluate 함수가 호출됩니다.

메시지 플로우 데이터, 즉, 메시지, 전역 환경, 로컬 환경, 예외 목록은 노드의 입력 터미널에서 수신됩니다.

예를 들면 다음과 같습니다.
void cniEvaluate(                
    CciContext* context,                
    CciMessage* destinationList,        
    CciMessage* exceptionList,          
    CciMessage* message                 
){                                    
  ...
}

노드의 인스턴스 작성

다음 프로시저는 노드를 인스턴스화하는 방법을 보여줍니다.

  1. 브로커가 함수 포인터 테이블을 수신할 때는 사용자 정의 노드의 각 인스턴스화마다 cniCreateNodeContext 함수를 호출합니다. 사용자 정의 노드를 사용하는 세 개의 메시지 플로우가 있을 경우, 각각에 대해 cniCreateNodeContext 함수가 호출됩니다. 이 함수는 구성된 속성의 값을 보유할 사용자 정의 노드의 인스턴스화를 위한 메모리를 할당합니다. 예를 들면, 다음 코드와 같습니다.
    1. 사용자 함수 cniCreateNodeContext의 이름은 다음과 같습니다.
      CciContext* _Switch_createNodeContext(
          CciFactory* factoryObject,
          CciChar*    nodeName,
          CciNode*    nodeObject
      ){
          static char* functionName = (char *)"_Switch_createNodeContext()";
          NODE_CONTEXT_ST* p;
          CciChar          buffer[256];
      
      
    2. 로컬 컨텍스트에 포인터를 할당하고 컨텍스트 영역을 지웁니다.
            p = (NODE_CONTEXT_ST *)malloc(sizeof(NODE_CONTEXT_ST));
      
          if (p) {
                memset(p, 0, sizeof(NODE_CONTEXT_ST));
    3. 노드 오브젝트 포인터를 컨텍스트에 저장합니다.
            p->nodeObject = nodeObject;
    4. 노드 이름을 저장합니다.
        CciCharNCpy((CciChar*)&p->nodeName, nodeName, MAX_NODE_NAME_LEN);
  2. 브로커는 적절한 유틸리티 함수를 호출하여 노드의 입력 터미널 및 출력 터미널에 대한 정보를 찾습니다. 한 노드에는 여러 입력 터미널 및 출력 터미널이 연관되어 있습니다. 사용자 함수 cniCreateNodeContext에서 cniCreateInputTerminalcniCreateOutputTerminal을 호출하여 사용자 노드의 터미널을 정의해야 합니다. 이 함수는 cniCreateNodeContext 구현 함수 내에서 호출되어야 합니다. 예를 들어, 하나의 입력 터미널 및 두 개의 출력 터미널로 노드를 정의하는 코드는 다음과 같습니다.
        {
                const CciChar* ucsIn = CciString("in", BIP_DEF_COMP_CCSID) ;
                insInputTerminalListEntry(p, (CciChar*)ucsIn);
                free((void *)ucsIn) ;
        }
        {
                const CciChar* ucsOut = CciString("out", BIP_DEF_COMP_CCSID) ;
                insOutputTerminalListEntry(p, (CciChar*)ucsOut);
                free((void *)ucsOut) ;
        }
        {
                const CciChar* ucsFailure = CciString("failure", BIP_DEF_COMP_CCSID) ;
                insOutputTerminalListEntry(p, (CciChar*)ucsFailure);
                free((void *)ucsFailure) ;
        }

속성 설정

브로커를 시작할 때마다 또는 메시지 플로우를 새 값으로 재전개할 때 속성이 설정됩니다. 구성 스레드에서 사용자 코드를 호출하여 브로커가 속성을 설정합니다. 사용자 코드는 향후 메시지 처리 시 사용하기 위해 이 속성을 노드 컨텍스트 영역에 저장해야 합니다.

입력 터미널 및 출력 터미널을 작성한 다음 브로커는 cniSetAttribute 함수를 호출하여 사용자 정의 노드의 해당 인스턴스화 관련 구성 속성 값을 전달합니다. 예를 들면 다음과 같습니다.
    {
            const CciChar* ucsAttr = CciString("nodeTraceSetting", BIP_DEF_COMP_CCSID) ;
            insAttrTblEntry(p, (CciChar*)ucsAttr, CNI_TYPE_INTEGER);
            _setAttribute(p, (CciChar*)ucsAttr, (CciChar*)constZero);
            free((void *)ucsAttr) ;
    }
    {
            const CciChar* ucsAttr = CciString("nodeTraceOutfile", BIP_DEF_COMP_CCSID) ;
            insAttrTblEntry(p, (CciChar*)ucsAttr, CNI_TYPE_STRING);
            _setAttribute(p, (CciChar*)ucsAttr, (CciChar*)constSwitchTraceLocation);
            free((void *)ucsAttr) ;
    }

노드 기능 구현

브로커가 큐에서 메시지를 검색하고 해당 메시지가 사용자 정의 메시지 처리 또는 출력 노드의 입력 터미널에 도착할 때, 브로커는 구현 함수 cniEvaluate를 호출합니다. 이 함수는 메시지 처리 스레드에서 호출되고 메시지로 수행할 사항을 결정해야 합니다. 특히 추가 인스턴스가 사용될 경우 이 함수는 다중 스레드에서 호출될 수 있습니다.

메시지 처리 노드 인스턴스 삭제

노드 인스턴스를 삭제하려면 cniDeleteNodeContext 함수를 사용하십시오. 예를 들면, 다음 코드와 같습니다.

void _deleteNodeContext(
    CciContext* context
){
    static char* functionName = (char *)"_deleteNodeContext()";

    return;
}

cniDeleteNodeContext 함수는 사용자가 제공하고 메시지 플로우 삭제 시 브로커에서 호출됩니다.

주의사항 | 등록상표 | 다운로드 | 라이브러리 | 지원 | 피드백
Copyright IBM Corporation 1999, 2005 마지막 갱신 날짜: 11/08/2005
as09980_