ClRcT
clCompAppAMFCSIRemove(
    ClInvocationT       invocation,
    const SaNameT       *compName,
    const SaNameT       *csiName,
    ClAmsCSIFlagsT      csiFlags)
{
    /*
     * Print information about the CSI Remove
     */

    clprintf ("Component [%s] : PID [%d]. CSI Remove Received\n", 
              compName->value, mypid);

    clprintf ("   CSI                     : %s\n", csiName->value);
    clprintf ("   CSI Flags               : 0x%x\n", csiFlags);

    /*
     * Add application specific logic for removing the work for this CSI.
     */

    /*
     * ---BEGIN_APPLICATION_CODE---
     */

    // ...

    /*
     * ---END_APPLICATION_CODE---
     */

    clCpmResponse(cpmHandle, invocation, CL_OK);

    return CL_OK;
}
ClRcT clEventTerminate(ClInvocationT invocation, const ClNameT *compName)
{
    ClRcT rc;

    rc = clCpmClientFinalize(gClEvtTestContCpmHandle);

    clCpmResponse(gClEvtTestContCpmHandle, invocation, CL_OK);

    return CL_OK;
}
SaAisErrorT saAmfResponse(SaAmfHandleT amfHandle,
                          SaInvocationT invocation,
                          SaAisErrorT error)
{
    ClRcT rc;

    rc = clCpmResponse(amfHandle, invocation, clSafToClovisError(error));

    return clClovisToSafError(rc);
}
/*
 * The following definition should ideally be in EoApi. 
 * Duplicating here for now.
 */
typedef enum{
    CL_EO_LIB_ID_OSAL,
    CL_EO_LIB_ID_MEM,
    CL_EO_LIB_ID_HEAP,
    CL_EO_LIB_ID_BUFFER,
    CL_EO_LIB_ID_TIMER,
    CL_EO_LIB_ID_IOC,
    CL_EO_LIB_ID_RMD,
    CL_EO_LIB_ID_EO,
    CL_EO_LIB_ID_RES,
    CL_EO_LIB_ID_POOL  =  CL_EO_LIB_ID_RES,
    CL_EO_LIB_ID_CPM,
    CL_EO_LIB_ID_MAX 
}ClEoLibIdT; 

typedef struct ClPubsEventInfo
{
    ClEventInitHandleT initHandle;
    ClEventChannelHandleT channelHandle;
    ClEventHandleT eventHandle;
} ClPubsEventInfoT; 

static ClPubsEventInfoT gPubsEventInfo;

static ClEoPayloadWithReplyCallbackT gClEvtPubsTestFuncList[] =
{
    (ClEoPayloadWithReplyCallbackT) NULL,                          /* 0 */
};

static ClRcT clPubsTriggerEvent(ClEoLibIdT libId, ClWaterMarkIdT wmId, ClUint32T wmValue, ClEoWaterMarkFlagT wmFlag)
{
    ClRcT rc = CL_OK;

    ClEventIdT eventId = 0;
    SaNameT publisherName = {sizeof(CL_EVENT_PUBLISHER_NAME)-1, CL_EVENT_PUBLISHER_NAME};

    ClEventPatternT patterns[5] = {{0}};

    ClEventPatternArrayT patternArray = {
        0,
        CL_SIZEOF_ARRAY(patterns),
        patterns 
    };

    rc = clEventAllocate(gPubsEventInfo.channelHandle, &gPubsEventInfo.eventHandle);
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventAllocate() failed [%#X]\n",rc);
        goto failure;
    }

    patterns[0].patternSize = strlen(CL_EO_NAME);
    patterns[0].pPattern = (ClUint8T *)CL_EO_NAME;
    
    patterns[1].patternSize = sizeof(libId);
    patterns[1].pPattern = (ClUint8T *)&libId;
    
    patterns[2].patternSize = sizeof(wmId);
    patterns[2].pPattern = (ClUint8T *)&wmId;
    
    patterns[3].patternSize = sizeof(wmFlag);
    patterns[3].pPattern = (ClUint8T *)&wmFlag;
    
    patterns[4].patternSize = sizeof(wmValue);
    patterns[4].pPattern = (ClUint8T *)(&wmValue);
    
    rc = clEventAttributesSet(gPubsEventInfo.eventHandle, &patternArray, 
            CL_EVENT_HIGHEST_PRIORITY, 0, &publisherName);
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventAttributesSet() failed [%#X]\n",rc);
        goto event_allocated;
    }

    rc = clEventPublish(gPubsEventInfo.eventHandle, "Event Payload passed in endian neutral way", 
            sizeof("Event Payload passed in endian neutral way."), &eventId);
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventPublish() failed [%#X]\n",rc);
        goto event_allocated;
    }

event_allocated:
    rc = clEventFree(gPubsEventInfo.eventHandle);
    if(CL_OK != rc)
    {
        clOsalPrintf("clEventFree() failed [%#X]\n",rc);
    }

failure:
    return rc;
}

static ClCpmHandleT gClEvtPubsCpmHandle; /* FIXME */
ClRcT clEventPubsTerminate(ClInvocationT invocation,
			const SaNameT  *compName)
{
    ClRcT rc;

    rc = clCpmComponentUnregister(gClEvtPubsCpmHandle, compName, NULL);
    rc = clCpmClientFinalize(gClEvtPubsCpmHandle);

    clCpmResponse(gClEvtPubsCpmHandle, invocation, CL_OK);

    return CL_OK;
}
ClRcT
clCompAppTerminate(
    ClInvocationT       invocation,
    const SaNameT       *compName)
{
    ClRcT rc = CL_OK;

    clprintf ("Component [%s] : PID [%d]. Terminating\n",
              compName->value, mypid);

    /*
     * ---BEGIN_APPLICATION_CODE--- 
     */

    // ...

    /*
     * ---END_APPLICATION_CODE---
     */
    
    /*
     * Unregister with AMF and send back a response
     */

    if ( (rc = clCpmComponentUnregister(cpmHandle, compName, NULL)) )
        goto errorexit;
    if ( (rc = clCpmClientFinalize(cpmHandle)) )
        goto errorexit;

    clCpmResponse(cpmHandle, invocation, CL_OK);

    clprintf ("Component [%s] : PID [%d]. Terminated\n", compName->value, mypid);

    return rc;

errorexit:

    clprintf ("Component [%s] : PID [%d]. Termination error [0x%x]\n",
              compName->value, mypid, rc);

    return rc;
}
ClRcT
clCompAppTerminate(
    ClInvocationT       invocation,
    const ClNameT       *compName)
{
    ClRcT rc = CL_OK;

    clprintf (CL_LOG_SEV_INFO, "Component [%s] : PID [%ld]. Terminating",
              compName->value, mypid);

    /*
     * ---BEGIN_APPLICATION_CODE--- 
     */

    // ...

    /*
     * ---END_APPLICATION_CODE---
     */
    
    /*
     * Unregister with AMF and send back a response
     */

    if ( (rc = clCpmComponentUnregister(cpmHandle, compName, NULL)) )
        goto errorexit;
    if ( (rc = clCpmClientFinalize(cpmHandle)) )
        goto errorexit;

    clprintf (CL_LOG_SEV_INFO, "Component [%s] : PID [%ld]. Terminated", compName->value, mypid);
    clCpmResponse(cpmHandle, invocation, CL_OK);
    clEvalAppLogStreamClose(gEvalLogStream);

    return rc;

errorexit:

    clprintf (CL_LOG_SEV_ERROR, "Component [%s] : PID [%ld]. Termination error [0x%x]",
              compName->value, mypid, rc);

    return rc;
}
ClRcT
clCompAppAMFCSISet(
    ClInvocationT       invocation,
    const SaNameT       *compName,
    ClAmsHAStateT       haState,
    ClAmsCSIDescriptorT csiDescriptor)
{
    /*
     * Print information about the CSI Set
     */

    clprintf ("Component [%s] : PID [%d]. CSI Set Received\n", 
              compName->value, mypid);

    clCompAppAMFPrintCSI(csiDescriptor, haState);

    /*
     * Take appropriate action based on state
     */

    switch ( haState )
    {
        case CL_AMS_HA_STATE_ACTIVE:
        {
            /*
             * AMF has requested application to take the active HA state 
             * for the CSI.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            // ...

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);
            break;
        }

        case CL_AMS_HA_STATE_STANDBY:
        {
            /*
             * AMF has requested application to take the standby HA state 
             * for this CSI.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            // ...

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);
            break;
        }

        case CL_AMS_HA_STATE_QUIESCED:
        {
            /*
             * AMF has requested application to quiesce the CSI currently
             * assigned the active or quiescing HA state. The application 
             * must stop work associated with the CSI immediately.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            // ...

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);
            break;
        }

        case CL_AMS_HA_STATE_QUIESCING:
        {
            /*
             * AMF has requested application to quiesce the CSI currently
             * assigned the active HA state. The application must stop work
             * associated with the CSI gracefully and not accept any new
             * workloads while the work is being terminated.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            // ...

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmCSIQuiescingComplete(cpmHandle, invocation, CL_OK);
            break;
        }

        default:
        {
            /*
             * Should never happen. Ignore.
             */
        }
    }

    return CL_OK;
}
ClRcT
clCompAppAMFCSISet(
    ClInvocationT       invocation,
    const ClNameT       *compName,
    ClAmsHAStateT       haState,
    ClAmsCSIDescriptorT csiDescriptor)
{
    /*
     * ---BEGIN_APPLICATION_CODE--- 
     */

    ClRcT       rc = CL_OK;

    /*
     * ---END_APPLICATION_CODE---
     */

    /*
     * Print information about the CSI Set
     */

    clprintf (CL_LOG_SEV_INFO, "Component [%s] : PID [%ld]. CSI Set Received", 
              compName->value, mypid);

    clCompAppAMFPrintCSI(csiDescriptor, haState);

    /*
     * Take appropriate action based on state
     */

    switch ( haState )
    {
        case CL_AMS_HA_STATE_ACTIVE:
        {
            /*
             * AMF has requested application to take the active HA state 
             * for the CSI.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            // ...

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);
            
            rc = clAlarmEventSubscribe(&alarm_event_subscribe_callback);
            if (CL_OK != rc)
            {
                clprintf(CL_LOG_SEV_ERROR,"%s: Failed while subscribing for the alarm events. rc[0x%x]", appname, rc);
                return rc;
            }
            break;
        }

        case CL_AMS_HA_STATE_STANDBY:
        {
            /*
             * AMF has requested application to take the standby HA state 
             * for this CSI.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            // ...

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);
            break;
        }

        case CL_AMS_HA_STATE_QUIESCED:
        {
            /*
             * AMF has requested application to quiesce the CSI currently
             * assigned the active or quiescing HA state. The application 
             * must stop work associated with the CSI immediately.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            // ...

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);

            rc = clAlarmEventUnsubscribe();
            if (CL_OK != rc)
            {
                clprintf(CL_LOG_SEV_ERROR,"%s: Failed while un-subscribing for the alarm evnets. rc[0x%x] ", appname, rc);
                return rc;
            }
            break;
        }

        case CL_AMS_HA_STATE_QUIESCING:
        {
            /*
             * AMF has requested application to quiesce the CSI currently
             * assigned the active HA state. The application must stop work
             * associated with the CSI gracefully and not accept any new
             * workloads while the work is being terminated.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            // ...

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmCSIQuiescingComplete(cpmHandle, invocation, CL_OK);
            break;
        }

        default:
        {
            /*
             * Should never happen. Ignore.
             */
        }
    }

    return CL_OK;
}
ClRcT
clCompAppAMFCSISet(
    ClInvocationT       invocation,
    const ClNameT       *compName,
    ClAmsHAStateT       haState,
    ClAmsCSIDescriptorT csiDescriptor)
{
    /*
     * ---BEGIN_APPLICATION_CODE--- 
     */

    // ...

    /*
     * ---END_APPLICATION_CODE---
     */

    /*
     * Print information about the CSI Set
     */

    clprintf (CL_LOG_SEV_INFO, "Component [%s] : PID [%ld]. CSI Set Received", 
              compName->value, mypid);

    clCompAppAMFPrintCSI(csiDescriptor, haState);

    /*
     * Take appropriate action based on state
     */

    switch ( haState )
    {
        case CL_AMS_HA_STATE_ACTIVE:
        {
            /*
             * AMF has requested application to take the active HA state 
             * for the CSI.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            clprintf(CL_LOG_SEV_INFO,"csa102: ACTIVE state requested; activating service");
            running = 1;

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);
            break;
        }

        case CL_AMS_HA_STATE_STANDBY:
        {
            /*
             * AMF has requested application to take the standby HA state 
             * for this CSI.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            clprintf(CL_LOG_SEV_INFO,"csa102: New state is not the ACTIVE; deactivating service");
            running = 0;

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);
            break;
        }

        case CL_AMS_HA_STATE_QUIESCED:
        {
            /*
             * AMF has requested application to quiesce the CSI currently
             * assigned the active or quiescing HA state. The application 
             * must stop work associated with the CSI immediately.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            clprintf(CL_LOG_SEV_INFO,"csa102: Acknowledging new state");
            running = 0;

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);
            break;
        }

        case CL_AMS_HA_STATE_QUIESCING:
        {
            /*
             * AMF has requested application to quiesce the CSI currently
             * assigned the active HA state. The application must stop work
             * associated with the CSI gracefully and not accept any new
             * workloads while the work is being terminated.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            clprintf(CL_LOG_SEV_INFO,"csa102: Signaling completion of QUIESCING");
            running = 0;

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmCSIQuiescingComplete(cpmHandle, invocation, CL_OK);
            break;
        }

        default:
        {
            break;
        }
    }

    return CL_OK;
}
ClRcT
clCompAppAMFCSISet(
    ClInvocationT       invocation,
    const ClNameT       *compName,
    ClAmsHAStateT       haState,
    ClAmsCSIDescriptorT csiDescriptor)
{
    /*
     * ---BEGIN_APPLICATION_CODE--- 
     */

    // ...

    /*
     * ---END_APPLICATION_CODE---
     */

    /*
     * Print information about the CSI Set
     */

    clprintf (CL_LOG_SEV_INFO, "Component [%s] : PID [%d]. CSI Set Received\n", 
              compName->value, mypid);

    clCompAppAMFPrintCSI(csiDescriptor, haState);

    /*
     * Take appropriate action based on state
     */

    switch ( haState )
    {
        case CL_AMS_HA_STATE_ACTIVE:
        {
            /*
             * AMF has requested application to take the active HA state 
             * for the CSI.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */
            if ((csiDescriptor.csiFlags == CL_AMS_CSI_FLAG_TARGET_ALL)||(csiDescriptor.csiFlags == CL_AMS_CSI_FLAG_TARGET_ONE))
              {
                /* Do not reload the virtual address info for the "TARGET" flag -- the CSI is not filled in.
                   We will use the values that were cached when the "standby" assignment occurred.
                 */
              }
            else /* CL_AMS_CSI_FLAG_ADD_ONE */
              {
                GetVirtualAddressInfo(csiDescriptor, &gVirtualIp);
              }

            AddRemVirtualAddress("up",&gVirtualIp);
            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);
            break;
        }

        case CL_AMS_HA_STATE_STANDBY:
        {
            /*
             * AMF has requested application to take the standby HA state 
             * for this CSI.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */
            GetVirtualAddressInfo(csiDescriptor, &gVirtualIp);
            AddRemVirtualAddress("down",&gVirtualIp);  /* Bring it down just in case it is up from a prior run */
            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);
            break;
        }

        case CL_AMS_HA_STATE_QUIESCED:
        {
            /*
             * AMF has requested application to quiesce the CSI currently
             * assigned the active or quiescing HA state. The application 
             * must stop work associated with the CSI immediately.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */
            
            if ((csiDescriptor.csiFlags == CL_AMS_CSI_FLAG_TARGET_ALL)||(csiDescriptor.csiFlags == CL_AMS_CSI_FLAG_TARGET_ONE))
              {
                AddRemVirtualAddress("down",&gVirtualIp);           
              }
            else /* CL_AMS_CSI_FLAG_ADD_ONE */
              {
                VirtualIpAddress temp;
                GetVirtualAddressInfo(csiDescriptor, &temp);
                AddRemVirtualAddress("down",&temp);
              }

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmResponse(cpmHandle, invocation, CL_OK);
            break;
        }

        case CL_AMS_HA_STATE_QUIESCING:
        {
            /*
             * AMF has requested application to quiesce the CSI currently
             * assigned the active HA state. The application must stop work
             * associated with the CSI gracefully and not accept any new
             * workloads while the work is being terminated.
             */

            /*
             * ---BEGIN_APPLICATION_CODE---
             */

            // ...

            /*
             * ---END_APPLICATION_CODE---
             */

            clCpmCSIQuiescingComplete(cpmHandle, invocation, CL_OK);
            break;
        }

        default:
        {
            break;
        }
    }

    return CL_OK;
}