void clCkptTrackCallback(ClGmsHandleT handle, ClGmsClusterNotificationBufferT *notificationBuffer, ClUint32T  numberOfMembers, ClRcT rc)
{
    ClIocNodeAddressT deputy = 0;
    ClIocNodeAddressT newDeputy = 0;

    /* Set Master and deputy addresses */
    if(!gCkptSvr) 
    {
        clLogWarning("GMS", "TRACK", "CKPT server context is not initialized");
        return;
    }
    clOsalMutexLock(&gCkptSvr->ckptClusterSem);
    deputy = gCkptSvr->masterInfo.deputyAddr;
    newDeputy = notificationBuffer->deputy;
    _clCkptAddressesUpdate(notificationBuffer);
    clOsalMutexUnlock(&gCkptSvr->ckptClusterSem);

    CKPT_LOCK(gCkptSvr->masterInfo.ckptMasterDBSem);
    if (gCkptSvr->localAddr == newDeputy
        && 
        (deputy != gCkptSvr->localAddr
         ||
         !gCkptSvr->isSynced)
        )
    {
        /*
         * Add the deputy to our masterinfo peer list and announce the master about our arrival
         * and do the same.
         */
        _ckptSvrArrvlAnnounce();
        if (CL_OK != ckptMasterDatabaseSyncup(gCkptSvr->masterInfo.masterAddr))
        {
            clLogWarning(CL_CKPT_AREA_ACTIVE, "IOC", "ckptMasterDatabaseSyncup failed");
        } 
        else
        {
            clLogWarning(CL_CKPT_AREA_ACTIVE, "IOC", "ckptMasterDatabaseSyncup succeeded");
        }

        /*
         * If the masterdbsyncup fetched an old deputy during a IOC callback update 
         * overlapping on the master, then just patch it with the right one here.
         */
        if(gCkptSvr->masterInfo.deputyAddr != newDeputy)
            gCkptSvr->masterInfo.deputyAddr = newDeputy;

    }
    CKPT_UNLOCK(gCkptSvr->masterInfo.ckptMasterDBSem);
}
void ckptTerminate(SaInvocationT invocation, const SaNameT *compName)
{
    SaAisErrorT rc = SA_AIS_OK;
    
    clLogWarning(CL_LOG_AREA_UNSPECIFIED, CL_LOG_CONTEXT_UNSPECIFIED,"Checkpoint service is stopping.");
    /*
     * Deregister with debug server.
    */
    ckptDebugDeregister(gCkptSvr->eoHdl);
    
    /*
     * Wait for all the other threads to finalize  
    */
    clEoQueuesQuiesce();
    /*
     * Deregister with cpm.
    */
    rc = saAmfComponentUnregister(amfHandle, compName, NULL);
    /*
     * Cleanup the persistent DB information.
     */

    /*
    Feature not supported -- see bug 6017 -- don't forget to uncomment ckptDataBackupInitialize()!
    ckptDataBackupFinalize();
    */
    /*
     * Cleanup resources taken by ckpt server.
     */
    ckptShutDown();
    /* Ok tell SAFplus that we handled it properly */
    saAmfResponse(amfHandle, invocation, SA_AIS_OK);
    unblockNow = CL_TRUE;
}
/*
 * Frees up the handle database specified by databaseHandle.  If the handle
 * database is empty, it frees up the database immediately.  Otherwise,
 * it will mark the database for deletion and free it when the last entry
 * is deleted.
 */
ClRcT
clHandleDatabaseDestroy(ClHandleDatabaseHandleT databaseHandle)
{
    ClHdlDatabaseT *hdbp   = (ClHdlDatabaseT*)databaseHandle;
    ClRcT          ec      = CL_OK;
    ClHandleT      handle  = 0;
    
    hdlDbValidityChk(hdbp);
    
    ec = pthread_mutex_lock(&hdbp->mutex);
    if (ec != 0)
    {
        return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR);
    }
    clDbgResourceNotify(clDbgHandleGroupResource, clDbgRelease, 0, hdbp, ("Handle database %p released", (ClPtrT) hdbp));
    /*
     * Go thru the list of handles and delete everything, if they have not
     * been cleaned up properly, through warning message and destroy the
     * database
     */
    if (hdbp->n_handles_used > 0) /* database is not empty */
    {
       for( handle = 0; handle < hdbp->n_handles; handle++)
       {
           if( hdbp->handles[handle].state != HANDLE_STATE_EMPTY )
           {
               /* explicitly making '0' for smooth removal of handles */
               hdbp->handles[handle].ref_count = 1;
               hdbp->handles[handle].state     = HANDLE_STATE_PENDINGREMOVAL;
               ec = pthread_mutex_unlock(&hdbp->mutex);
               if( ec != 0 )
               {
                   /* Who cares about the error code, during shut down */
                   goto free_exit;          
               }
               clLogWarning(CL_HDL_AREA, CL_HDL_CTX_DBDESTROY, 
                            "Handle [%p:%#llX] has not been cleaned, destroying...",
                            (ClPtrT) hdbp, (handle + 1));
               clHandleCheckin(databaseHandle, handle + 1);
               ec = pthread_mutex_lock(&hdbp->mutex);
               if( ec != 0 )
               {
                   goto free_exit;
               }
           }
       }
    }
    /* Explicitly not checking the error code */    
    pthread_mutex_unlock(&hdbp->mutex);
free_exit:    
    if( NULL != hdbp->handles )
    {
        free(hdbp->handles); 
    }
    hdbp->pValidDb = (void *) CL_HDL_INVALID_COOKIE; 
    clHeapFree(hdbp);
    return CL_OK;
}
ClRcT clNodeCacheLeaderIocSend(ClIocNodeAddressT currentLeader, ClIocAddressT *dstAddr)
{
    ClRcT rc = CL_OK;
    ClIocSendOptionT sendOption = {CL_IOC_HIGH_PRIORITY,0,0,CL_IOC_PERSISTENT_MSG,200 };
    ClIocPhysicalAddressT compAddr = { CL_IOC_BROADCAST_ADDRESS,  CL_IOC_CPM_PORT };
    ClTimerTimeOutT delay = {  0,  200 };
    ClUint32T i = 0;
    ClBufferHandleT message = 0;
    ClEoExecutionObjT *eoObj = NULL;
    ClIocNotificationT notification;
    
    memset(&notification,0,sizeof(ClIocNotificationT));
    notification.protoVersion = htonl(CL_IOC_NOTIFICATION_VERSION);
    notification.id = (ClIocNotificationIdT) htonl(CL_IOC_NODE_ARRIVAL_NOTIFICATION);
    notification.nodeAddress.iocPhyAddress.nodeAddress = htonl(clIocLocalAddressGet());
    notification.nodeAddress.iocPhyAddress.portId = htonl(CL_IOC_GMS_PORT);

    clEoMyEoObjectGet(&eoObj);

    while(!eoObj && i++ <= 3)
    {
        clEoMyEoObjectGet(&eoObj);
        clOsalTaskDelay(delay);
    }

    if(!eoObj)
    {
        clLogWarning("CAP", "ARP", "Could not send current leader update since EO still uninitialized.");
        return CL_ERR_NOT_INITIALIZED;
    }

    clBufferCreate(&message);

    currentLeader = htonl(currentLeader);
    rc = clBufferNBytesWrite(message, (ClUint8T *)&notification, sizeof(ClIocNotificationT));
    rc |= clBufferNBytesWrite(message, (ClUint8T*)&currentLeader, sizeof(currentLeader));
    if (rc != CL_OK)
    {
        clLogError("CAP", "ARP", "clBufferNBytesWrite failed with rc = %#x", rc);
        clBufferDelete(&message);
        return rc;
    }

    rc = clIocSend(eoObj->commObj, message, CL_IOC_PORT_NOTIFICATION_PROTO, dstAddr, &sendOption);

    clBufferDelete(&message);

    return rc;

}
static void cpmPayload2StandbySC(const ClGmsClusterNotificationBufferT *notificationBuffer,
                                 ClCpmLocalInfoT *pCpmLocalInfo)
{
    ClUint32T rc = CL_OK;

    if(gpClCpm->haState == CL_AMS_HA_STATE_STANDBY)
    {
        clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
                     "Payload node already promoted to Deputy. Skipping initialization of controller functions");
        return;
    }

    clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, 
                "Payload node promoted to deputy. Initializing System controller functions on this node.");

    gpClCpm->pCpmConfig->cpmType = CL_CPM_GLOBAL;
    rc = cpmUpdateTL(CL_AMS_HA_STATE_STANDBY);
    if (rc != CL_OK)
    {
        clLogWrite(CL_LOG_HANDLE_APP, CL_LOG_SEV_DEBUG, NULL,
                   CL_CPM_LOG_1_TL_UPDATE_FAILURE, rc);
    }
    rc = clAmsStart(&gAms,
                    CL_AMS_INSTANTIATE_MODE_STANDBY);
    gpClCpm->haState = CL_AMS_HA_STATE_STANDBY;
    gpClCpm->activeMasterNodeId = notificationBuffer->leader;
    gpClCpm->deputyNodeId = notificationBuffer->deputy;
    if (CL_OK != rc)
    {
        clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
                      "Unable to initialize AMS, "
                      "error = [%#x]", rc);

        cpmSelfShutDown();
        return;
    }
    clLogInfo(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
              "initialization of AMS is successful. ");
    
    if (gpClCpm->bmTable->currentBootLevel == pCpmLocalInfo->defaultBootLevel)
    {
        cpmInitializeStandby();
    }
    
    clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
                "Payload to System Controller conversion done");

    return ;
}
ClRcT
clAmsMgmtCCBBatchCommit(CL_IN ClAmsMgmtCCBBatchHandleT batchHandle)
{
    ClRcT  rc = CL_OK;
    ClAmsMgmtCCBBatchT *batch = (ClAmsMgmtCCBBatchT*)batchHandle;
    ClUint32T saveOffset = 0;

    if(!batch)
        return CL_AMS_RC(CL_ERR_INVALID_PARAMETER);
    if(!batch->buffer)
        return CL_AMS_RC(CL_ERR_NOT_INITIALIZED);

    if(!batch->items)
    {
        clLogWarning("CCB", "COMMIT", "Batch commit tried with no items");
        return CL_OK;
    }
    rc = clBufferWriteOffsetGet(batch->buffer, &saveOffset);
    if(rc != CL_OK)
        goto out;

    rc = clBufferWriteOffsetSet(batch->buffer, batch->itemsOffset, CL_BUFFER_SEEK_SET);
    if(rc != CL_OK)
        goto out;

    /*
     * Update the item count
     */
    rc = clXdrMarshallClUint32T(&batch->items, batch->buffer, 0);
    if(rc != CL_OK)
        goto out;
    
    rc = clBufferWriteOffsetSet(batch->buffer, saveOffset, CL_BUFFER_SEEK_SET);
    if(rc != CL_OK)
        goto out;

    rc = cl_ams_ccb_batch_rmd(CL_AMS_MGMT_CCB_BATCH_COMMIT, batch->buffer, CL_VERSION_CODE(5, 1, 0));
    if(rc != CL_OK)
        goto out;

    /*
     * Clear the buffer for reuse
     */
    rc = amsMgmtCCBBatchBufferInitialize(batch);

    out:
    return rc;
}
ClBoolT clParseEnvBoolean(const ClCharT* envvar)
{
    ClCharT* val = NULL;
    ClBoolT rc = CL_FALSE;

    val = getenv(envvar);
    if (val != NULL)
    {
        /* If the env var is defined as "". */
        if (strlen(val) == 0)
        {
            rc = CL_TRUE;
        }
        else if (!strncmp(val, "1", 1) ||
                 !strncasecmp(val, "yes", 3) || 
                 !strncasecmp(val, "y", 1) ||
                 !strncasecmp(val, "true", 4) ||
                 !strncasecmp(val, "t", 1) )
        {
            rc = CL_TRUE;
        }
        else if (!strncmp(val, "0", 1) ||
                 !strncasecmp(val, "no", 2) || 
                 !strncasecmp(val, "n", 1) ||
                 !strncasecmp(val, "false", 5) ||
                 !strncasecmp(val, "f", 1) )
        {
            rc = CL_FALSE;
        }
        else 
        {
            clLogWarning("UTL", "ENV", "Environment variable [%s] value is not understood. "
                         "Please use 'YES' or 'NO'. Assuming 'NO'", envvar);
            rc = CL_FALSE;
        }
    }
    else
    {
        rc = CL_FALSE;
    }

    return rc;
}
SaAisErrorT clClovisToSafError(ClRcT clError)
{
    SaAisErrorT safError = SA_AIS_ERR_LIBRARY;

    /* First check component specific error translations */
    switch(clError)
    {
        case CL_CPM_RC(CL_CPM_ERR_OPERATION_IN_PROGRESS):
            safError = SA_AIS_ERR_BUSY;
            break;
    }

    if (safError != SA_AIS_ERR_LIBRARY) return safError;
    
    /* Next check to see if the error can be translated generically */    
    switch(CL_GET_ERROR_CODE(clError))
    {
        case CL_OK:
        {
            safError = SA_AIS_OK;
            break;
        }
        case CL_ERR_VERSION_MISMATCH:
        {
            safError = SA_AIS_ERR_VERSION;
            break;
        }
        case CL_ERR_TIMEOUT:
        {
            safError = SA_AIS_ERR_TIMEOUT;
            break;
        }
        case CL_ERR_TRY_AGAIN:
        {
            safError = SA_AIS_ERR_TRY_AGAIN;
            break;
        }
        case CL_ERR_INVALID_PARAMETER:
        {
            safError = SA_AIS_ERR_INVALID_PARAM;
            break;
        }
        case CL_ERR_NO_MEMORY:
        {
            safError = SA_AIS_ERR_NO_MEMORY;
            break;
        }
        case CL_ERR_INVALID_HANDLE:
        {
            safError = SA_AIS_ERR_BAD_HANDLE;
            break;
        }
        case CL_ERR_OP_NOT_PERMITTED:
        {
            safError = SA_AIS_ERR_ACCESS;
            break;
        }
        case CL_ERR_DOESNT_EXIST:
        {
            safError = SA_AIS_ERR_NOT_EXIST;
            break;
        }
        case CL_ERR_ALREADY_EXIST:
        {
            safError = SA_AIS_ERR_EXIST;
            break;
        }
        case CL_ERR_NO_SPACE:
        {
            safError = SA_AIS_ERR_NO_SPACE;
            break;
        }
        case CL_ERR_NO_RESOURCE:
        {
            safError = SA_AIS_ERR_NO_RESOURCES;
            break;
        }
        case CL_ERR_NOT_IMPLEMENTED:
        {
            safError = SA_AIS_ERR_NOT_SUPPORTED;
            break;
        }
        case CL_ERR_BAD_OPERATION:
        {
            safError = SA_AIS_ERR_BAD_OPERATION;
            break;
        }
        case CL_ERR_BAD_FLAG:
        {
            safError = SA_AIS_ERR_BAD_FLAGS;
            break;
        }
        case CL_ERR_NULL_POINTER:
        {
            safError = SA_AIS_ERR_INVALID_PARAM;
            break;
        }
        default:
        {
            clLogWarning("AMF", "SAF",
                         "Clovis error code [%#x] is not mapped to a valid "
                         "SAF error code, returning default [%#x]",
                         CL_GET_ERROR_CODE(clError),
                         (ClUint32T)safError);
            break;
        }
    }

    return safError;
}
ClRcT clSafToClovisError(SaAisErrorT safError)
{
    ClRcT clError = CL_ERR_UNSPECIFIED;
    
    switch (safError)
    {
        case SA_AIS_OK:
        {
            clError = CL_OK;
            break;
        }
        case SA_AIS_ERR_LIBRARY:
        {
            clError = CL_ERR_INITIALIZED;
            break;
        }
        case SA_AIS_ERR_VERSION:
        {
            clError = CL_ERR_VERSION_MISMATCH;
            break;
        }
        case SA_AIS_ERR_INIT:
        {
            clError = CL_ERR_NOT_INITIALIZED;
            break;
        }
        case SA_AIS_ERR_TIMEOUT:
        {
            clError = CL_ERR_TIMEOUT;
            break;
        }
        case SA_AIS_ERR_TRY_AGAIN:
        {
            clError = CL_ERR_TRY_AGAIN;
            break;
        }
        case SA_AIS_ERR_INVALID_PARAM:
        {
            clError = CL_ERR_INVALID_PARAMETER;
            break;
        }
        case SA_AIS_ERR_NO_MEMORY:
        {
            clError = CL_ERR_NO_MEMORY;
            break;
        }
        case SA_AIS_ERR_BAD_HANDLE:
        {
            clError = CL_ERR_INVALID_HANDLE;
            break;
        }
        case SA_AIS_ERR_BUSY:
        {
            clError = CL_ERR_TRY_AGAIN;
            break;
        }
        case SA_AIS_ERR_ACCESS:
        {
            clError = CL_ERR_OP_NOT_PERMITTED;
            break;
        }
        case SA_AIS_ERR_NOT_EXIST:
        {
            clError = CL_ERR_DOESNT_EXIST;
            break;
        }
        case SA_AIS_ERR_NAME_TOO_LONG:
        {
            clError = CL_ERR_OUT_OF_RANGE;
            break;
        }
        case SA_AIS_ERR_EXIST:
        {
            clError = CL_ERR_ALREADY_EXIST;
            break;
        }
        case SA_AIS_ERR_NO_SPACE:
        {
            clError = CL_ERR_NO_SPACE;
            break;
        }
        case SA_AIS_ERR_INTERRUPT:
        {
            clError = CL_ERR_UNSPECIFIED;
            break;
        }
        case SA_AIS_ERR_NAME_NOT_FOUND:
        {
            clError = CL_ERR_DOESNT_EXIST;
            break;
        }
        case SA_AIS_ERR_NO_RESOURCES:
        {
            clError = CL_ERR_NO_RESOURCE;
            break;
        }
        case SA_AIS_ERR_NOT_SUPPORTED:
        {
            clError = CL_ERR_NOT_IMPLEMENTED;
            break;
        }
        case SA_AIS_ERR_BAD_OPERATION:
        {
            clError = CL_ERR_BAD_OPERATION;
            break;
        }
        case SA_AIS_ERR_FAILED_OPERATION:
        {
            clError = CL_ERR_BAD_OPERATION;
            break;
        }
        case SA_AIS_ERR_BAD_FLAGS:
        {
            clError = CL_ERR_BAD_FLAG;
            break;
        }
        case SA_AIS_ERR_TOO_BIG:
        {
            clError = CL_ERR_OUT_OF_RANGE;
            break;
        }
        default:
        {
            clLogWarning("AMF", "SAF",
                         "SAF error code [%#x] is not mapped to a valid "
                         "Clovis error code, returning default [%#x]",
                         (ClUint32T)safError,
                         clError);
            break;
        }
    }

    return clError;
}
ClRcT
clLogFlusherCookieHandleDestroy(ClHandleT  hFlusher, 
                                ClBoolT    timerExpired)
{
    ClRcT     rc   = CL_OK;
    ClLogFlushCookieT  *pFlushCookie = NULL;
    ClLogSvrEoDataT    *pSvrEoEntry  = NULL;

    CL_LOG_DEBUG_TRACE(("Enter"));

    /*
     * FIXME:
     * Unable to flush this set of records but will this be true in
     * future also, DON'T know
     * Also need to reset the startAck otherwise it will not  enter
     * the cond_wait
     */
    rc = clLogSvrEoEntryGet(&pSvrEoEntry, NULL);
    if(  CL_OK != rc )
    {
        return rc;
    }

    rc = clHandleValidate(pSvrEoEntry->hFlusherDB, hFlusher);
    if( CL_OK != rc )
    {
        return rc;/*Flusher handle has already been destroyed*/
    }

    rc = clHandleCheckout(pSvrEoEntry->hFlusherDB, hFlusher, 
                          (void **) &pFlushCookie);

    if( (CL_TRUE == timerExpired) && (CL_OK != rc) )
    {
        clLogTrace("LOG", "FLS", "Timer has already destroyed the handle");
        return CL_OK;
    }    
    if( CL_OK != rc )
    {
        clLogError("LOG", "FLS", "Flusher handle checkout failed : "
                   "rc[0x %x]", rc);
        return rc;
    }

    if( CL_FALSE == timerExpired )
    {
        clLogWarning("LOG", "FLS", "Didn't get ack for %d records",
                     pFlushCookie->numRecords);
    }    
    CL_LOG_CLEANUP(clTimerDelete(&pFlushCookie->hTimer), CL_OK);

    rc = clHandleCheckin(pSvrEoEntry->hFlusherDB, hFlusher);
    if( CL_OK != rc )
    {
        clLogError("LOG", "FLS", "clHandleCheckin(): rc[0x %x]", rc);
    }    
    CL_LOG_CLEANUP(clHandleDestroy(pSvrEoEntry->hFlusherDB, hFlusher), CL_OK);

    CL_LOG_DEBUG_TRACE(("Exit"));
    return rc;
}    
ClRcT cpmGmsInitialize(void)
{
    ClRcT rc = CL_OK;
    ClTimerTimeOutT timeOut = {0, 0};

    ClGmsCallbacksT cpmGmsCallbacks = { NULL, cpmClusterTrackCallBack, NULL, NULL };
    
    gpClCpm->version.releaseCode = 'B';
    gpClCpm->version.majorVersion = 0x01;
    gpClCpm->version.minorVersion = 0x01;
    rc = clGmsInitialize(&gpClCpm->cpmGmsHdl,
                         &cpmGmsCallbacks,
                         &gpClCpm->version);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                   "Failed to do GMS initialization, error [%#x]",
                   rc);
        gpClCpm->cpmGmsHdl = CL_HANDLE_INVALID_VALUE;
        goto failure;
    }

    rc = clOsalMutexLock(&gpClCpm->cpmGmsMutex);
    CL_CPM_CHECK_1(CL_LOG_SEV_ERROR, CL_CPM_LOG_1_OSAL_MUTEX_LOCK_ERR, rc, rc,
                   CL_LOG_HANDLE_APP);

    rc = clGmsClusterTrack(gpClCpm->cpmGmsHdl, CL_GMS_TRACK_CHANGES_ONLY | CL_GMS_TRACK_CURRENT, NULL);
    if (CL_OK != rc)
    {
        clOsalMutexUnlock(&gpClCpm->cpmGmsMutex);
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                   "The GMS cluster track function failed, error [%#x]",
                   rc);
        goto failure;
    }

    /*
     * Wait for the GMS callback
     */
    retry:
#ifdef VXWORKS_BUILD
    timeOut.tsSec = gpClCpm->cpmGmsTimeout + 20;
#else
    timeOut.tsSec = gpClCpm->cpmGmsTimeout + 60;  /* There is no reason to not wait for a long time.  100% cpu could cause GMS to come up slowly */
#endif
    timeOut.tsMilliSec = 0;

    clLogInfo(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
              "Node [%s] waiting for GMS cluster track callback for [%d.%d] secs",
              gpClCpm->pCpmLocalInfo->nodeName, timeOut.tsSec, timeOut.tsMilliSec);

    rc = clOsalCondWait(&gpClCpm->cpmGmsCondVar,
                        &gpClCpm->cpmGmsMutex,
                        timeOut);
    if (CL_OK != rc)
    {
        if(gpClCpm->trackCallbackInProgress)
        {
            clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                         "GMS cluster track callback in progress. Waiting for it to complete ...");
            goto retry;
        }
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                   "Failed to receive GMS cluster track callback, "
                   "error [%#x].",
                   rc);
        clOsalMutexUnlock(&gpClCpm->cpmGmsMutex);
        goto failure;
    }

    rc = clOsalMutexUnlock(&gpClCpm->cpmGmsMutex);
    CL_CPM_CHECK_1(CL_LOG_SEV_ERROR, CL_CPM_LOG_1_OSAL_MUTEX_UNLOCK_ERR, rc,
                   rc, CL_LOG_HANDLE_APP);

    return CL_OK;

    failure:
    return rc;
}
static ClRcT cpmNodeRmv(ClCharT *nodeName)
{
    ClRcT rc = CL_OK;
    ClUint16T nodeKey = 0;
    ClCntNodeHandleT hNode = 0;
    ClUint32T numNode = 0;
    ClCpmLT *cpm = NULL;
    ClBoolT done = CL_NO;
    if (!nodeName)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "NULL pointer passed.");
        goto failure;
    }

    rc = clCksm16bitCompute((ClUint8T *)nodeName,
                            strlen(nodeName),
                            &nodeKey);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Failed to compute checksum for node, "
                   "error [%#x]",
                   rc);
        goto failure;
    }

    clOsalMutexLock(gpClCpm->cpmTableMutex);

    rc = clCntNodeFind(gpClCpm->cpmTable,
                       (ClCntKeyHandleT)(ClWordT)nodeKey,
                       &hNode);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Failed to find node [%s], error [%#x]",
                   nodeName,
                   rc);
        goto unlock;
    }

    rc = clCntKeySizeGet(gpClCpm->cpmTable,
                         (ClCntKeyHandleT)(ClWordT)nodeKey,
                         &numNode);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Unable to get key size, error [%#x]",
                   rc);
        goto unlock;
    }

    while (numNode > 0)
    {
        rc = clCntNodeUserDataGet(gpClCpm->cpmTable,
                                  hNode,
                                  (ClCntNodeHandleT *) &cpm);
        if (CL_OK != rc)
        {
            clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                       "Unable to get user data, error [%#x]",
                       rc);
            goto unlock;
        }

        if (!strncmp(nodeName, cpm->nodeName, CL_MAX_NAME_LENGTH-1))
        {
            clCntNodeDelete(gpClCpm->cpmTable, hNode);
            done = CL_YES;
            break;
        }

        if (--numNode)
        {
            rc = clCntNextNodeGet(gpClCpm->cpmTable, hNode, &hNode);
            if (CL_OK != rc)
            {
                break;
            }
        }
    }

    if (!done)
    {
        rc = CL_CPM_RC(CL_ERR_DOESNT_EXIST);
        goto unlock;
    }

    --gpClCpm->noOfCpm;

    clOsalMutexUnlock(gpClCpm->cpmTableMutex);

    /*
     * Delete from slot table
     */
    clOsalMutexLock(&gpClCpm->cpmMutex);
    if(cpmSlotClassDelete(nodeName) != CL_OK)
    {
        clLogWarning("CPM", "MGMT", "Slot class delete failed for node [%s]", nodeName);
    }
    clOsalMutexUnlock(&gpClCpm->cpmMutex);

    return CL_OK;

unlock:
    clOsalMutexUnlock(gpClCpm->cpmTableMutex);
failure:
    return rc;
}
ClRcT cpmInvocationAddKey(ClUint32T cbType,
                          void *data,
                          ClInvocationT invocationId,
                          ClUint32T flags)
{
    ClRcT rc = CL_OK;
    ClCpmInvocationT *temp = NULL;
    ClUint32T invocationKey = 0;

    if (cbType < 0x1LL || cbType >= CL_CPM_MAX_CALLBACK)
        CL_CPM_CHECK(CL_LOG_SEV_ERROR, ("Invalid parameter passed \n"),
                     CL_CPM_RC(CL_ERR_INVALID_PARAMETER));
    temp =
        (ClCpmInvocationT *) clHeapAllocate(sizeof(ClCpmInvocationT));
    if (temp == NULL)
        CL_CPM_CHECK(CL_LOG_SEV_ERROR, ("Unable to allocate memory \n"),
                     CL_CPM_RC(CL_ERR_NO_MEMORY));

    clOsalMutexLock(gpClCpm->invocationMutex);

    temp->invocation = invocationId;
    temp->data = data;
    temp->flags = flags; 

    CL_CPM_INVOCATION_KEY_GET(invocationId, invocationKey);

    rc = clCntNodeAdd(gpClCpm->invocationTable, (ClCntKeyHandleT)&temp->invocation,
                      (ClCntDataHandleT) temp, NULL);
    if (rc != CL_OK)
    {
        if(CL_GET_ERROR_CODE(rc) == CL_ERR_DUPLICATE)
        {
            clLogWarning("ADD", "INVOCATION", "Invocation entry [%#llx] already exists", invocationId);
            rc = CL_OK;
        }
        else
        {
            clLogError("ADD", "INVOCATION", "Invocation entry [%#llx] returned [%#x]",
                       invocationId, rc);
        }
        goto withLock;
    }

    /*
     * Try preventing reuse of the invocation key for new invocations.
     */
    if(gpClCpm->invocationKey <= invocationKey)
    {
        gpClCpm->invocationKey = invocationKey + 1;
    }

    clLogDebug("ADD", "INVOCATION", "Added entry for invocation [%#llx]", invocationId);
               
    clOsalMutexUnlock(gpClCpm->invocationMutex);
    return rc;

    withLock:
    clOsalMutexUnlock(gpClCpm->invocationMutex);

    failure:
    if (temp != NULL)
        clHeapFree(temp);

    return rc;
}
static void cpmMakeSCActiveOrDeputy(const ClGmsClusterNotificationBufferT *notificationBuffer,
                                    ClCpmLocalInfoT *pCpmLocalInfo)
{
    ClUint32T rc = CL_OK;
    ClGmsNodeIdT prevMasterNodeId = gpClCpm->activeMasterNodeId;
    ClBoolT leadershipChanged = notificationBuffer->leadershipChanged;
    
    /*  
     * Check for initial leadership state incase the cluster track from AMF was issued
     * after GMS leader election was done and GMS responded back with a track with a leadership changed
     * set to FALSE for a CURRENT async request from AMF.
     */
    if(leadershipChanged == CL_FALSE && 
       (ClInt32T) notificationBuffer->leader == pCpmLocalInfo->nodeId &&
       (ClInt32T) prevMasterNodeId != pCpmLocalInfo->nodeId && 
       gpClCpm->haState == CL_AMS_HA_STATE_NONE)
        leadershipChanged = CL_TRUE;
        
    if (leadershipChanged == CL_TRUE)
    {
        if ( (ClInt32T) notificationBuffer->leader == pCpmLocalInfo->nodeId)
        {
            clLogInfo(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                      "Node [%d] has become the leader of the cluster",
                      pCpmLocalInfo->nodeId);

            if(gpClCpm->haState != CL_AMS_HA_STATE_ACTIVE)
            {
                rc = cpmUpdateTL(CL_AMS_HA_STATE_ACTIVE);
                if (rc != CL_OK)
                {
                    clLogWrite(CL_LOG_HANDLE_APP, CL_LOG_SEV_DEBUG, NULL,
                               CL_CPM_LOG_1_TL_UPDATE_FAILURE, rc);
                }
            }
            gpClCpm->deputyNodeId = notificationBuffer->deputy;
        }
        else if ((ClInt32T) notificationBuffer->deputy == pCpmLocalInfo->nodeId)
        {
            clLogInfo(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                      "Node [%d] has become the deputy of the cluster",
                      pCpmLocalInfo->nodeId);
            /*
             * Deregister the active registration if going from active to standby.
             */
            if(gpClCpm->haState == CL_AMS_HA_STATE_ACTIVE)
            {
                clIocTransparencyDeregister(pCpmLocalInfo->nodeId << CL_CPM_IOC_SLOT_BITS);
            }
            rc = cpmUpdateTL(CL_AMS_HA_STATE_STANDBY);
            if (rc != CL_OK)
            {
                clLogWrite(CL_LOG_HANDLE_APP, CL_LOG_SEV_DEBUG, NULL,
                           CL_CPM_LOG_1_TL_UPDATE_FAILURE, rc);
            }
        }

        if ((gpClCpm->haState == CL_AMS_HA_STATE_ACTIVE) && 
            ( (ClInt32T) notificationBuffer->leader != pCpmLocalInfo->nodeId))
        {
            clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                       "Node [%d] is changing HA state from active to standby",
                       pCpmLocalInfo->nodeId);
              
            /*
             * Deregister the entry during a state change.
             */
            if ( (ClInt32T) notificationBuffer->deputy != pCpmLocalInfo->nodeId)
            {
                clIocTransparencyDeregister((pCpmLocalInfo->nodeId) << CL_CPM_IOC_SLOT_BITS);
            }

            /*
             * Inform AMS to become standby and read the checkpoint.
             */
            if ((gpClCpm->cpmToAmsCallback != NULL) && 
                (gpClCpm->cpmToAmsCallback->amsStateChange != NULL))
            {
                clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                           "Informing AMS on node [%d] to change state "
                           "from active to standby...",
                           pCpmLocalInfo->nodeId);

                rc = gpClCpm->cpmToAmsCallback->amsStateChange(CL_AMS_STATE_CHANGE_ACTIVE_TO_STANDBY |
                                                               CL_AMS_STATE_CHANGE_USE_CHECKPOINT);
                if (CL_OK != rc)
                {
                    clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
                                 "AMS state change from active to standby "
                                 "returned [%#x]",
                                 rc);
                }

                cpmWriteNodeStatToFile("AMS", CL_NO);

                if(!gClAmsSwitchoverInline)
                {
                    if (((notificationBuffer->numberOfItems == 0) &&
                         (notificationBuffer->notification == NULL)) &&
                        gpClCpm->polling &&
                        (gpClCpm->nodeLeaving == CL_FALSE))
                    {
                        /*
                         * This indicates that leader election API of
                         * GMS was called.  Since this involves
                         * interaction among only system controllers,
                         * we don't need to restart the worker nodes
                         * like in the case of split brain handling.
                         */
                        
                        cpmActive2Standby(CL_NO);
                    }
                    else if (( (ClInt32T) notificationBuffer->deputy == pCpmLocalInfo->nodeId) && gpClCpm->polling && (gpClCpm->nodeLeaving == CL_FALSE))
                    {
                        /*
                         * We try and handle a possible split brain
                         * since presently GMS shouldnt be reelecting.
                         * And even if it does, its pretty much
                         * invalid with respect to AMS where you could
                         * land up with 2 actives.
                         */
                     
                        /*
                         * We arent expected to return back.
                         */
                        cpmActive2Standby(CL_NO);
                    }
                }
            }

            /*
             * Bug 4168:
             * Updating the data structure gpClCpm, when the active becomes
             * standby.
             */
            gpClCpm->haState = CL_AMS_HA_STATE_STANDBY;
            gpClCpm->activeMasterNodeId = notificationBuffer->leader;
            gpClCpm->deputyNodeId = notificationBuffer->deputy;
            if(gClAmsSwitchoverInline)
            {
                /*
                 *Re-register with active.
                 */
                clOsalMutexUnlock(&gpClCpm->clusterMutex);
                cpmSwitchoverActive();
                clOsalMutexLock(&gpClCpm->clusterMutex);
            }
        }
        else if ((gpClCpm->haState == CL_AMS_HA_STATE_STANDBY) && 
                 ( (ClInt32T) notificationBuffer->leader == pCpmLocalInfo->nodeId))
        {
            rc = cpmStandby2Active(prevMasterNodeId, 
                                   notificationBuffer->deputy);
            if (CL_OK != rc)
            {
                return;
            }
        }
        else if ((gpClCpm->haState == CL_AMS_HA_STATE_NONE) && 
                 ( (ClInt32T) notificationBuffer->leader ==
                  pCpmLocalInfo->nodeId))
        {
            /*
             * Bug 4411:
             * Added the if-else block.
             * Calling the AMS initialize only if both the callback pointers
             * are not NULL.
             * FIXME: This change is sort of workaround for 2.2.
             * Neat solution is to protect gpClCpm structure and fields properly
             */
            if ((gpClCpm->amsToCpmCallback != NULL) &&
                (gpClCpm->cpmToAmsCallback != NULL))
            {
                clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Starting AMS in active mode...");

                rc = clAmsStart(&gAms,CL_AMS_INSTANTIATE_MODE_ACTIVE | CL_AMS_INSTANTIATE_USE_CHECKPOINT);
                /*
                 * Bug 4092:
                 * If the AMS intitialize fails then do the 
                 * self shut down.
                 */
                if (CL_OK != rc)
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Unable to initialize AMF, error = [%#x]", rc);

                    gpClCpm->amsToCpmCallback = NULL;
                    cpmReset(NULL,NULL);
                    return;
                }
            }
            else
            {
                rc = CL_CPM_RC(CL_ERR_NULL_POINTER);
                 
                if (!gpClCpm->polling)
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, "AMF finalize called before AMF initialize during node shutdown.");
                }
                else
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, "Unable to initialize AMF, error = [%#x]", rc);
                     
                    cpmRestart(NULL,NULL);
                }
                return;
            }
             
            gpClCpm->haState = CL_AMS_HA_STATE_ACTIVE;
            gpClCpm->activeMasterNodeId = notificationBuffer->leader;
            gpClCpm->deputyNodeId = notificationBuffer->deputy;
        }
        /*
         * There could be more than 1 standby SC. 
         * Every none HA-state SC except the master is updated to become to standby SC.        
         */
        else if (gpClCpm->haState == CL_AMS_HA_STATE_NONE)
        {
            /*
             * Bug 4411:
             * Added the if-else block.
             * Calling the clAmsStart only if both the callback pointers
             * are not NULL.
             * FIXME: This change is sort of workaround for 2.2.
             * Neat solution is to protect gpClCpm structure and fields properly
             */
            if ((gpClCpm->amsToCpmCallback != NULL) &&
                (gpClCpm->cpmToAmsCallback != NULL))
            {
                clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,
                           "Starting AMS in standby mode...");

                rc = clAmsStart(&gAms,CL_AMS_INSTANTIATE_MODE_STANDBY);
                /*
                 * Bug 4092:
                 * If the AMS initialize fails then do the 
                 * self shut down.
                 */
                if (CL_OK != rc)
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Unable to initialize AMS, error = [%#x]", rc);

                    gpClCpm->amsToCpmCallback = NULL;
                    cpmRestart(NULL,NULL);
                    return;
                }
            }
            else
            {
                rc = CL_CPM_RC(CL_ERR_NULL_POINTER);
                 
                if (!gpClCpm->polling)
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"AMS finalize called before AMS initialize during node shutdown.");
                }
                else
                {
                    clLogCritical(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS,"Unable to initialize AMS, error = [%#x]", rc);
                    cpmRestart(NULL,NULL);
                }
                return;
            }

            gpClCpm->haState = CL_AMS_HA_STATE_STANDBY;
            gpClCpm->activeMasterNodeId = notificationBuffer->leader;
            gpClCpm->deputyNodeId = notificationBuffer->deputy;
            if(gpClCpm->bmTable->currentBootLevel == pCpmLocalInfo->defaultBootLevel)
            {
                cpmInitializeStandby();
            }
        }
        else
        {
            gpClCpm->activeMasterNodeId = notificationBuffer->leader;
            gpClCpm->deputyNodeId = notificationBuffer->deputy;
        }

        clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_CPM,
                    "HA state of node [%s] with node ID [%d] is [%s], "
                    "Master node is [%d]",
                    pCpmLocalInfo->nodeName,
                    pCpmLocalInfo->nodeId,
                    gpClCpm->haState == CL_AMS_HA_STATE_ACTIVE  ? "Active":
                    gpClCpm->haState == CL_AMS_HA_STATE_STANDBY ? "Standby":
                    "None",
                    gpClCpm->activeMasterNodeId);
    }
    else
    {
        /*
         * Always update the deputy node ID.  It may be that this
         * path is reached because a deputy node failed.
         */
        gpClCpm->deputyNodeId = notificationBuffer->deputy;

        if (CL_CPM_IS_ACTIVE())
        {
            if(notificationBuffer->notification && 
               notificationBuffer->numberOfItems == 1)
            {

                if (CL_GMS_NODE_LEFT ==
                    notificationBuffer->notification->clusterChange)
                {
                    cpmFailoverNode(notificationBuffer->notification->
                                    clusterNode.nodeId, CL_FALSE);
                }
                else
                {
                    clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, 
                                "Ignoring notification of type [%d] for node [%d]",
                                notificationBuffer->notification->clusterChange,
                                notificationBuffer->notification->clusterNode.nodeId);
                }
            }
            else if(notificationBuffer->notification)
            {
                clLogNotice(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_AMS, 
                            "Ignoring notification with number of items [%d], first type [%d]",
                            notificationBuffer->numberOfItems,
                            notificationBuffer->notification->clusterChange);
            }
        }
        else if ((gpClCpm->haState == CL_AMS_HA_STATE_NONE) && ( (ClInt32T) notificationBuffer->deputy == pCpmLocalInfo->nodeId))
        {
            if(CL_GMS_NODE_JOINED ==
               notificationBuffer->notification->clusterChange)
            {
                cpmStandbyRecover(notificationBuffer);
            }
            else if(gpClCpm->bmTable->currentBootLevel == pCpmLocalInfo->defaultBootLevel)
            {
                cpmStandbyRecover(notificationBuffer);
                cpmInitializeStandby();
            }
        }
    }
    return ;
}
ClRcT clBackingStorageReadWalkFile(ClBackingStorageHandleT handle,
                                   ClBackingStorageCallbackT pCallback,
                                   ClPtrT pArg,
                                   ClUint32T readSize,
                                   ClPtrT pPrivateData)
{
    ClBackingStorageAttributesFileT *pAttr = (ClBackingStorageAttributesFileT *) pPrivateData;
    ClCharT data[0xffff+1];
    ClSizeT size = 0;
    ClOffsetT curOffset = 0;
    struct stat st = {0};
    ClRcT rc = CL_BACKING_STORAGE_RC(CL_ERR_LIBRARY);

    if(fstat(pAttr->fd, &st) < 0)
    {
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                   "stat error [%s]", strerror(errno));
        goto out;
    }
    if(!st.st_size)
    {
        rc = CL_OK;
        clLogWarning(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                     "File [%s] size is empty", pAttr->baseAttr.location);
        goto out;
    }
    curOffset = lseek(pAttr->fd, 0, SEEK_CUR);
    if(curOffset < 0)
    {
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                   "lseek error [%s]", strerror(errno));
        goto out;
    }
    if(lseek(pAttr->fd, 0, SEEK_SET) < 0)
    {
        clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                   "lseek error [%s]", strerror(errno));
        goto out;
    }

    size = st.st_size;
    while(size > 0)
    {
        ClInt32T err = 0;
        ClCharT *pData = data;
        ClInt32T chunkSize = CL_MIN((ClInt32T)sizeof(data), size);
        ClUint32T bytes = 0;

        if(readSize)
        {
            if(size < readSize)
            {
                clLogError(CL_LOG_AREA_BACKING_STORAGE,
                           CL_LOG_CONTEXT_READW_FILE,
                           "Read walk error. Chunksize doesnt match readsize [%d]",
                           chunkSize);
                goto out_restore;
            }
            chunkSize = readSize;
            pData = (ClCharT*) clHeapAllocate(chunkSize);
            if(!pData)
            {
                clLogError(CL_LOG_AREA_BACKING_STORAGE, 
                           CL_LOG_CONTEXT_READW_FILE,
                           "No memory");
                goto out_restore;
            }
        }
        while(chunkSize > 0)
        {
            err = read(pAttr->fd, pData+bytes, chunkSize);
            if(err < 0)
            {
                clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                           "read error [%s]", strerror(errno));
                if(pData != data)
                {
                    clHeapFree(pData);
                }
                goto out_restore;
            }
            bytes += err;
            chunkSize -= err;
        }

        rc = pCallback(handle, (ClPtrT)pData, bytes, pArg);
        if(rc != CL_OK)
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_READW_FILE,
                       "readwalk callback error [%#x]", rc);
            if(pData != data)
            {
                clHeapFree(pData);
            }
            goto out_restore;
        }
        size -= bytes;
    }
    rc = CL_OK;

    out_restore:
    lseek(pAttr->fd, curOffset, SEEK_SET);

    out:
    return rc;
}
ClRcT clBackingStorageWriteFile(ClBackingStorageHandleT handle, ClPtrT pData, ClUint32T size, ClOffsetT offset, ClPtrT pPrivateData)
{
    ClBackingStorageAttributesFileT *pAttr = (ClBackingStorageAttributesFileT *) pPrivateData;
    ClRcT  rc = CL_OK;
    ClInt32T err = 0;
    ClOffsetT curOffset = 0;
    ClInt32T whence = SEEK_SET;

    rc = CL_BACKING_STORAGE_RC(CL_ERR_LIBRARY);
    if( offset != (ClOffsetT)-1)
    {
        curOffset = lseek(pAttr->fd, 0, SEEK_CUR);
        if(curOffset < 0 )
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_WRITE_FILE, 
                       "File lseek save error [%s]", strerror(errno));
            goto out;
        }
        if(offset < 0)
        {
            whence = SEEK_END;
            size = -offset;
        }
        else
        {
            size -= offset;
        }
        if(lseek(pAttr->fd, offset, whence) < 0)
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_WRITE_FILE, "File lseek error [%s]", strerror(errno));
            goto out;
        }
    }

    while(size > 0 )
    {
        ClInt32T n = CL_MIN(size, 32768);
        err = write(pAttr->fd, pData, n);
        if(err < 0 )
        {
            clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_WRITE_FILE, "Write error [%s]", strerror(errno));
            if(offset != (ClOffsetT)-1)
            {
                if(lseek(pAttr->fd, curOffset, SEEK_SET) < 0)
                {
                    clLogError(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_WRITE_FILE, "lseek error [%s] restoring back offset", strerror(errno));
                }
            }
            goto out;
        }
        if(err != n)
        {
            clLogWarning(CL_LOG_AREA_BACKING_STORAGE, CL_LOG_CONTEXT_WRITE_FILE, "Write wrote [%d] bytes. Expected [%d] bytes", err, n);
        }
        size -= err;
        pData = (ClPtrT)((ClUint8T*)pData + err);
    }

    rc = CL_OK;
    out:
    return rc;
    
}
SaAisErrorT saCkptCheckpointOpen(
        SaCkptHandleT                             ckptHandle,
        const SaNameT                             *checkpointName,
        const SaCkptCheckpointCreationAttributesT *ckptAttributes,
        SaCkptCheckpointOpenFlagsT                checkpointOpenFlags,
        SaTimeT                                   timeout,
        SaCkptCheckpointHandleT                   *checkpointHandle)
{
    ClRcT                               rc         = CL_OK;
    SaAisErrorT                         safRc      = SA_AIS_OK;
    ClCkptHdlT                          tmpCkptHdl = 0;
    ClCkptCheckpointCreationAttributesT ckptAttr   = {0};

    /*
     * Validate the input parameters.
     */
    if(checkpointHandle == NULL)
        return SA_AIS_ERR_INVALID_PARAM;
        
    /*
     * Call the ckpt client open function.
     */
    if(ckptAttributes != NULL)
    {
        if( ckptAttributes->checkpointSize > 
            (ckptAttributes->maxSections * ckptAttributes->maxSectionSize) )
            {
                clLogWarning("CKP", "INI", "Possible inconsistency in SAF checkpoint open.  Your passed configuration parameters should have this relationship: checkpointSize (%d) is less than or equal to maxSections (%d) * maxSectionSize (%d).  Reducing checkpointSize to = maxSections * maxSectionSize (which is %d).",                 (int) ckptAttributes->checkpointSize, (int) ckptAttributes->maxSections, (int) ckptAttributes->maxSectionSize, (int) (ckptAttributes->maxSections * ckptAttributes->maxSectionSize));
                 ckptAttr.checkpointSize = ckptAttributes->maxSections * ckptAttributes->maxSectionSize;
            }
        else ckptAttr.checkpointSize    = ckptAttributes->checkpointSize;

        ckptAttr.creationFlags     = ckptAttributes->creationFlags;
        ckptAttr.retentionDuration = ckptAttributes->retentionDuration;
        ckptAttr.maxSectionSize    = ckptAttributes->maxSectionSize;
        ckptAttr.maxSections       = ckptAttributes->maxSections;
        ckptAttr.maxSectionIdSize  = ckptAttributes->maxSectionIdSize;
        
        rc = clCkptCheckpointOpen( (ClCkptSvcHdlT) ckptHandle,
                (SaNameT *)checkpointName, 
                &ckptAttr,
                (ClCkptOpenFlagsT) checkpointOpenFlags, 
                (ClTimeT)timeout, 
                &tmpCkptHdl);
    }
    else
    {
        rc = clCkptCheckpointOpen( (ClCkptSvcHdlT) ckptHandle,
                (SaNameT *)checkpointName, 
                NULL,
                (ClCkptOpenFlagsT) checkpointOpenFlags, 
                (ClTimeT)timeout, 
                &tmpCkptHdl);
    }
    
    /*
     * Copy the checkpoint handle to the output variable.
     */
    *checkpointHandle = tmpCkptHdl;

    /*
     * Translate the clovis error type to SAF error type.
     */
    clErrorTxlate(rc, &safRc);
    
    return safRc;
}
ClRcT _clCkpMastertReplicaAddressUpdate(ClHandleT         mastHdl,
                                        ClIocNodeAddressT actAddr)
{
    ClRcT                   rc               = CL_OK;
    ClCntNodeHandleT        nodeHdl          = 0;
    ClCntDataHandleT        dataHdl          = 0;
    CkptMasterDBEntryT      *pMasterDBEntry  = NULL;
    ClCkptClientUpdInfoT    eventInfo        = {0};
    ClEventIdT              eventId          = 0;

    clLogDebug(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
               "Changing the active address of ckpt handle [%#llX]",
               mastHdl);
    /*
     * Retrieve the information associated with the master hdl.
     */
    if( CL_OK != (rc = clHandleCheckout(gCkptSvr->masterInfo.masterDBHdl,
                                        mastHdl, (void **) &pMasterDBEntry)))
    {
        clLogError(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
                   "Master db entry doesn't have this handle [%#llX]", 
                   mastHdl);
        return rc;
    }  

    /*
     * Delete the entry of the node that went down from the checkpoint's
     * replica list.
     */
    if (pMasterDBEntry->replicaList)
        clCntAllNodesForKeyDelete(pMasterDBEntry->replicaList, (ClPtrT)(ClWordT)actAddr);
    else
    {
        clLogWarning(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN,"Replicalist for %s is empty",pMasterDBEntry->name.value);
    }


    /*
     * Store the node's address as prev active address.
     */
    pMasterDBEntry->prevActiveRepAddr = actAddr; 

    /*
     * Select the new active address. In case of COLLOCATED checkpoint,
     * the new active address to UNINIT value.
     */
    if (CL_CKPT_IS_COLLOCATED(pMasterDBEntry->attrib.creationFlags)) 
    {
        if(pMasterDBEntry->activeRepAddr == actAddr)
        {
            pMasterDBEntry->activeRepAddr = CL_CKPT_UNINIT_ADDR;
        }
        else 
        {
            if(pMasterDBEntry->activeRepAddr != CL_CKPT_UNINIT_ADDR)
            {
                /*
                 * If we have traces of the master handle in our peer list 
                 * missed by the active replica set, then remove it here.
                 */
                clLogNotice(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
                            "Active replica is [%d]."
                            "Removing master ckpt handle [%#llX] from last active [%d]",
                            pMasterDBEntry->activeRepAddr, mastHdl, actAddr);
                _ckptPeerListMasterHdlAdd(mastHdl, actAddr, CL_CKPT_UNINIT_ADDR);
            }
            goto exitOnError;
        }
    }
    else 
    {
        rc = clCntFirstNodeGet(pMasterDBEntry->replicaList, &nodeHdl);
        if(CL_ERR_INVALID_HANDLE == CL_GET_ERROR_CODE(rc) || 
           nodeHdl == 0)
        {
            rc = CL_OK;
            pMasterDBEntry->activeRepAddr = CL_CKPT_UNINIT_ADDR;
        }
        CKPT_ERR_CHECK(CL_CKPT_SVR,CL_LOG_SEV_ERROR,
                       ("clCkptActiveReplicaAddrGet failed rc[0x %x]\n",rc),
                       rc);
        if( nodeHdl != 0 ) 
        {
            rc = clCntNodeUserDataGet(pMasterDBEntry->replicaList, nodeHdl, &dataHdl);
            CKPT_ERR_CHECK(CL_CKPT_SVR,CL_LOG_SEV_ERROR,
                           ("clCkptActiveReplicaAddrGet failed rc[0x %x]\n",rc),
                           rc);
            pMasterDBEntry->activeRepAddr = (ClIocNodeAddressT)(ClWordT)dataHdl;
        }
    }

    /*
     * Inform the client about the change in active replica.
     */
    if((gCkptSvr->masterInfo.masterAddr == gCkptSvr->localAddr) ||
       (clCpmIsSCCapable() && 
        (pMasterDBEntry->prevActiveRepAddr == 
         gCkptSvr->masterInfo.masterAddr)))
    {
        eventInfo.eventType   = htonl(CL_CKPT_ACTIVE_REP_CHG_EVENT);
        eventInfo.actAddr     = htonl(pMasterDBEntry->activeRepAddr);
        saNameCopy(&eventInfo.name, &pMasterDBEntry->name);
        eventInfo.name.length = htons(pMasterDBEntry->name.length);

        clLogNotice(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
                    "Changing the address from [%d] to [%d] for checkpoint [%.*s]",
                    actAddr, pMasterDBEntry->activeRepAddr, pMasterDBEntry->name.length, pMasterDBEntry->name.value);
        rc = clEventPublish(gCkptSvr->clntUpdEvtHdl, 
                            (const void*)&eventInfo,
                            sizeof(ClCkptClientUpdInfoT), &eventId);
    }

    /*
     * Delete the masterHdl from old address's peerlist and add to 
     * new address's peerlist.
     */
    if(!CL_CKPT_IS_COLLOCATED(pMasterDBEntry->attrib.creationFlags))
    {
        _ckptPeerListMasterHdlAdd(mastHdl, actAddr,
                                  pMasterDBEntry->activeRepAddr);
    }   
     
    exitOnError:
    {
        /* 
         * Checkin the updated stuff.
         */
        clHandleCheckin(gCkptSvr->masterInfo.masterDBHdl, mastHdl);
        return rc;
    }
}
ClParserPtrT clParserOpenFileWithVer(const ClCharT *path, 
                                     const ClCharT *file, 
                                     ClVersionT *version)
{
    ClParserPtrT    top  = NULL;
    ClCharT         verStr[CL_MAX_NAME_LENGTH] = {0};
    ClParserPtrT    verTag = NULL;
    ClBoolT         found = 0;
    const ClCharT   *attrVal = NULL;
    ClUint32T       vIndex = 0;
    ClCharT         attrName[CL_MAX_NAME_LENGTH] = {0};

    if (path == NULL || file == NULL || version == NULL)
        return NULL;

    top = clParserOpenFileAllVer(path, file);
    if (top == NULL) goto done;
    
    snprintf(verStr,
             sizeof(verStr),
             "%d.%d.%d",
             version->releaseCode,
             version->majorVersion,
             version->minorVersion);
    
    /* top is pointing to <OpenClovisAsp> tag. Look for the child
     * with given version */
    verTag = clParserChild(top, "version");
    while (verTag != NULL)
    {
        vIndex = 0;
        snprintf(attrName, sizeof(attrName), "v%d",vIndex);
        attrVal = clParserAttr(verTag, attrName);
        while (attrVal != NULL)
        {
            if (!strcmp(attrVal, verStr))
            {
                found = 1;
                break;
            }
            vIndex++;
            snprintf(attrName, sizeof(attrName), "v%d",vIndex);
            attrVal = clParserAttr(verTag, attrName);
        }

        if (found == 1)
            break;

        verTag = verTag->next;
    }

    if (!found)
    {
        clLogWarning(PARSER_LOG_AREA_PARSER,PARSER_LOG_CTX_VERSION,
                     "Could not find the entry for version %s in %s",verStr,file);
        goto done;
    }

    /* Get the attributes and look for version */
    return verTag->child;
done:
    return top;
}
ClRcT
clHandleDestroy (
    ClHandleDatabaseHandleT databaseHandle,
    ClHandleT handle)
{
    ClHdlDatabaseT *hdbp = (ClHdlDatabaseT*) databaseHandle;
    ClRcT          ec    = CL_OK;

    hdlDbValidityChk(hdbp);
    handle = CL_HDL_IDX(handle); /* once we've verified it, we only care about the index */
    
    /*
     * Decrementing handle to ensure the non-zero handle interface.
     */
    if (CL_HANDLE_INVALID_VALUE == handle--)
    {
        clLogError("HDL", CL_LOG_CONTEXT_UNSPECIFIED, 
                "Passed handle [%p:%#llX] is invalid", (ClPtrT) hdbp, handle);
        return CL_HANDLE_RC(CL_ERR_INVALID_HANDLE); /* 0 no longer allowed */
    }
    /* Verify this particular handle has been already created */
    if( (NULL == hdbp->handles) || (0 == hdbp->n_handles_used) )
    {
        clLogError("HDL", CL_LOG_CONTEXT_UNSPECIFIED, 
                "Invalid attempt to delete the non exiting handle [%p:%#llX]", 
                (ClPtrT) hdbp, handle);
        return CL_HANDLE_RC(CL_ERR_INVALID_HANDLE);
    }

    ec = pthread_mutex_lock (&hdbp->mutex);
    if (ec != 0)
    {
        return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR);
    }
    if (handle >= (ClHandleT)hdbp->n_handles)
    {
        ec = pthread_mutex_unlock (&hdbp->mutex);
        if (ec != 0)
        {
            return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR); /* This can be devastating */
        }
        clLogError("HDL", CL_LOG_CONTEXT_UNSPECIFIED, 
                "Passed handle [%p:%#llX] has not been created", 
                (ClPtrT) hdbp, handle);
        return CL_HANDLE_RC(CL_ERR_INVALID_HANDLE);
    }
    clDbgResourceNotify(clDbgHandleResource, clDbgRelease, hdbp, handle+1, ("Handle [%p:%#llX] (state: %d, ref: %d) released", (ClPtrT)hdbp, handle+1,hdbp->handles[handle].state,hdbp->handles[handle].ref_count));

    if (HANDLE_STATE_USED == hdbp->handles[handle].state)
    {
        hdbp->handles[handle].state = HANDLE_STATE_PENDINGREMOVAL;

        ec = pthread_mutex_unlock (&hdbp->mutex);
        if (ec != 0)
        {
            return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR); /* This can be devastating */
        }
        /*
         * Adding 1 to handle to ensure the non-zero handle interface.
         */
        ec = clHandleCheckin (databaseHandle, handle+1);
        return ec;
    }
    else if (HANDLE_STATE_EMPTY == hdbp->handles[handle].state)
    {
        ec = CL_HANDLE_RC(CL_ERR_INVALID_HANDLE);
    }
    else if (HANDLE_STATE_PENDINGREMOVAL == hdbp->handles[handle].state)
    {
        ec = pthread_mutex_unlock( &hdbp->mutex);
        if( ec != 0 )
        {
            return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR); /* This can be devastating */
        }
        clLogWarning(CL_HDL_AREA, CL_HDL_CTX_DESTROY,  
                     "Destroy has been called for this handle [%p:%#llX]" 
                     "returning CL_OK", (ClPtrT) hdbp,
                     (handle + 1));
        return CL_OK;
    }
    else
    {
        clDbgCodeError(CL_ERR_INVALID_HANDLE, 
                       ("Passed handle [%p:%#llX] doesn't have any proper state,"
                       "corrupted code", (ClPtrT) hdbp, (handle + 1)));
        /*
         * Invalid state - this musn't happen!
         */
    }
    if(pthread_mutex_unlock (&hdbp->mutex) != 0)
    {
        return CL_HANDLE_RC(CL_ERR_MUTEX_ERROR); /* This can be devastating */
    }

#if 0
    clLogTrace(CL_HDL_AREA, CL_HDL_CTX_DESTROY, 
               "Handle [%p:%#llX] has been deleted successfully", 
               (ClPtrT) hdbp, (handle + 1));
#endif
    return ec;
}
/*Process each tag*/
static ClRcT clParseTag(ClParserPtrT node,ClParserTagT *pTag,ClParserDataT *pData,ClPtrT pCurrentBase)
{
    ClRcT rc = CL_OK;
    const ClCharT *pAttr;
    ClPtrT pValue;
    ClPtrT pDest;
    pAttr = clParserAttr(node,pTag->pTag);

    if(pAttr == NULL)
    {
        clLogWarning(PARSER_LOG_AREA_PARSER,PARSER_LOG_CTX_TAG,"XML attribute [%s] not defined, but may be optional.",pTag->pTag);
        /* clDbgCodeError(CL_LOG_SEV_WARNING,("Required attribute %s in xml configuration file is not defined\n",pTag->pTag)); */
        goto out;
    }

    /*The place to copy*/
    pDest = (ClPtrT) ((ClUint8T*)pCurrentBase+pTag->tagOffset);

    pValue = (ClPtrT)calloc(1,pTag->tagSize);

    if(pValue == NULL)
    {
        rc = CL_PARSER_RC(CL_ERR_NO_MEMORY);
        clLogError(PARSER_LOG_AREA_PARSER,PARSER_LOG_CTX_TAG,"Error allocating memory\n");
        goto out;
    }

    switch(pTag->tagType)
    {
    case CL_PARSER_STR_TAG:
        {
            strncpy((ClCharT*)pValue,pAttr,pTag->tagSize);
        }
        break;
        /*byte stream*/
    case CL_PARSER_STREAM_TAG:
        {
            memcpy(pValue,pAttr,pTag->tagSize);
        }
        break;
    case CL_PARSER_IP_TAG:
        {
            in_addr_t addr = inet_addr((char *)pAttr);
            bcopy((const char*)&addr,pValue,pTag->tagSize);
        }
        break;
    case CL_PARSER_BOOL_TAG:
        {
            ClBoolT v = CL_FALSE;
            if(!strcasecmp(pAttr,"true"))
            {
                v = CL_TRUE;
            }
            else if(!strcasecmp(pAttr,"false"))
            {
                v = CL_FALSE;
            }
            else
            {
                clLogError(PARSER_LOG_AREA_PARSER,PARSER_LOG_CTX_TAG,"Unknown bool value:%s " \
                                               "for tag:%s\n",
                                               pAttr,pData->pTag);
                rc = CL_PARSER_RC(CL_ERR_INVALID_PARAMETER);
             
                goto out_free;
            }
            memcpy(pValue,&v,pTag->tagSize);
        }
        break;
    case CL_PARSER_UINT8_TAG:
        {
            ClUint8T v = (ClUint8T)atoi(pAttr);
            *(ClUint8T*)pValue = v;
        }
        break;
    case CL_PARSER_UINT16_TAG:
        {
            ClUint16T v = (ClUint16T)atoi(pAttr);
            memcpy(pValue,&v,pTag->tagSize);
        }
        break;
    case CL_PARSER_UINT32_TAG:
        {
            ClUint32T v = (ClUint32T)strtoul(pAttr,NULL,10);
            memcpy(pValue,&v,pTag->tagSize);
        }
        break;
    case CL_PARSER_UINT64_TAG:
        {
            ClUint64T v = (ClUint64T)strtoll(pAttr,NULL,10);
            memcpy(pValue,&v,pTag->tagSize);
        }
        break;
    case CL_PARSER_CUSTOM_TAG:
        if(pTag->pTagFmt == NULL)
        {
            rc = CL_PARSER_RC(CL_ERR_UNSPECIFIED);
            clLogError(PARSER_LOG_AREA_PARSER,PARSER_LOG_CTX_TAG,"Tag:%s - Custom tag type with no fmt handler\n",pTag->pTag);
            goto out_free;
        }
        break;
    default:
        {
            rc = CL_PARSER_RC(CL_ERR_UNSPECIFIED);
            clLogError(PARSER_LOG_AREA_PARSER,PARSER_LOG_CTX_TAG,"Unknown tag type:%d\n",pTag->tagType);
            goto out_free;
        }
    }

    if(pTag->pTagFmt)
    {
        rc = pTag->pTagFmt(pTag,pData,pCurrentBase,(ClCharT*)pAttr,pValue,CL_PARSER_TAG_FMT);

        CL_PARSER_TAG_RESULT(rc,out_free);
        /*
         * Validate tag
         */
        goto validate_tag;
    }

    /*Call tag validate*/
    validate_tag:

    if(pTag->pTagValidate &&
       pTag->pTagValidate(pTag,pValue) == CL_FALSE
       )
    {
        rc = CL_PARSER_RC(CL_ERR_INVALID_PARAMETER);
        clLogError(PARSER_LOG_AREA_PARSER,PARSER_LOG_CTX_TAG,"Tag validation failed for tag:%s\n",pTag->pTag);
        goto out_free;
    }

    /*Now commit the value to the tag*/
    memcpy(pDest,pValue,pTag->tagSize);

    out_free:
    free(pValue);

    out:
    return rc;
}
/**
 * INIT: The below function initializes the checkpoint service client
 * and opens a checkpoint to store data.
 */
ClRcT clCachedCkptInitialize(ClCachedCkptSvcInfoT *serviceInfo,
                             const SaNameT *ckptName,
                             const SaCkptCheckpointCreationAttributesT *ckptAttributes,
                             SaCkptCheckpointOpenFlagsT openFlags,
                             ClUint32T cachSize)
{
    ClRcT			rc = CL_OK;
    SaCkptHandleT		ckptSvcHandle = 0;
    SaCkptCheckpointHandleT	ckptHandle = 0;
    SaVersionT			ckptVersion = {'B', 0x01, 0x01};
    ClTimerTimeOutT		delay = { 0, 500};
    ClInt32T			tries = 0;
    ClCharT cacheName[CL_MAX_NAME_LENGTH];
    ClUint32T                   shmSize = clCachedCkptShmSizeGet(cachSize);
    ClUint32T  *numberOfSections;
    ClUint32T  *sizeOfCache;

    serviceInfo->cachSize = shmSize;

    if(serviceInfo->ckptHandle != CL_HANDLE_INVALID_VALUE)
    {
        clLogWarning("CCK", "INI", "Checkpoint already initialized. Skipping initialization");
        return CL_ERR_ALREADY_EXIST;
    }

    snprintf(cacheName, sizeof(cacheName), "%s_%d", ckptName->value, gIocLocalBladeAddress);

    rc = clOsalSemCreate((ClUint8T*)cacheName, 1, &serviceInfo->cacheSem);
    if(rc != CL_OK)
    {
        ClOsalSemIdT semId = 0;

        if(clOsalSemIdGet((ClUint8T*)cacheName, &semId) != CL_OK)
        {
            clLogError("CCK", "INI", "cache semaphore creation error while fetching semaphore id");
            goto out1;
        }

        if(clOsalSemDelete(semId) != CL_OK)
        {
            clLogError("CCK", "INI", "cache semaphore creation error while deleting old semaphore id");
            goto out1;
        }

        rc = clOsalSemCreate((ClUint8T*)cacheName, 1, &serviceInfo->cacheSem);
    }

    if(ckptAttributes || openFlags)
    {
        if(serviceInfo->ckptSvcHandle == CL_HANDLE_INVALID_VALUE)
        {
            /* Initialize checkpoint service instance */
            do
            {
                rc = clCkptInitialize(&ckptSvcHandle, NULL, (ClVersionT *)&ckptVersion);
            } while(rc != CL_OK && tries++ < 100 && clOsalTaskDelay(delay) == CL_OK);

            if(rc != CL_OK)
            {
                clLogError("CCK", "INI", "Failed to initialize checkpoint service instance. error code [0x%x].", rc);
                goto out2;
            }

            serviceInfo->ckptSvcHandle = ckptSvcHandle;
        }

        /* Create the checkpoint for read and write. */
        do
        {
            rc = clCkptCheckpointOpen(serviceInfo->ckptSvcHandle,
                                      (SaNameT *)ckptName,
                                      (ClCkptCheckpointCreationAttributesT *)ckptAttributes,
                                      openFlags,
                                      0L,
                                      &ckptHandle);
        } while(rc != CL_OK && tries++ < 100 && clOsalTaskDelay(delay) == CL_OK);

        if(rc != CL_OK)
        {
            clLogError("CCK", "INI", "Failed to open checkpoint. error code [0x%x].", rc);
            goto out3;
        }

        serviceInfo->ckptHandle = ckptHandle;
    }

    /* Create shm */

    rc = clOsalShmOpen((ClCharT *)cacheName, CL_CACHED_CKPT_SHM_EXCL_CREATE_FLAGS,
                       CL_CACHED_CKPT_SHM_MODE, &serviceInfo->fd);
    if( CL_ERR_ALREADY_EXIST == CL_GET_ERROR_CODE(rc) )
    {
        rc = clOsalShmOpen((ClCharT *)cacheName, CL_CACHED_CKPT_SHM_OPEN_FLAGS,
                           CL_CACHED_CKPT_SHM_MODE, &serviceInfo->fd);
        if( CL_OK != rc )
        {
            clLogError("CCK", "INI", "Could not open shared memory.");
            goto out4;
        }
    }

    rc = clOsalFtruncate(serviceInfo->fd, shmSize);
    if( CL_OK != rc )
    {
        clLogError("CCK", "INI", "clOsalFtruncate(): error code [0x%x].", rc);
        goto out5;
    }

    rc = clOsalMmap(0, shmSize, CL_CACHED_CKPT_MMAP_PROT_FLAGS,
                    CL_CACHED_CKPT_MMAP_FLAGS, serviceInfo->fd, 0, (void **) &serviceInfo->cache);
    if( CL_OK != rc )
    {
        clLogError("CCK", "INI", "clOsalMmap(): error code [0x%x].", rc);
        goto out5;
    }

    numberOfSections = (ClUint32T *)(serviceInfo->cache);
    sizeOfCache = (ClUint32T *)(numberOfSections + 1);
    *numberOfSections = 0;
    *sizeOfCache = 0;

    clOsalMsync(serviceInfo->cache, shmSize, MS_SYNC);

    goto out1;

out5:
    clOsalShmClose(&serviceInfo->fd);
out4:
    if(serviceInfo->ckptHandle)
    {
        clCkptCheckpointClose(serviceInfo->ckptHandle);
        serviceInfo->ckptHandle =  CL_HANDLE_INVALID_VALUE;
    }
out3:
    if(serviceInfo->ckptSvcHandle)
    {
        clCkptFinalize(serviceInfo->ckptSvcHandle);
        serviceInfo->ckptSvcHandle =  CL_HANDLE_INVALID_VALUE;
    }
out2:
    clOsalSemDelete(serviceInfo->cacheSem);
out1:
    return rc;
}
ClRcT
clAmsGetFaultReport(
        CL_IN  const SaNameT  *compName,
        CL_IN  ClAmsLocalRecoveryT  recommendedRecovery,
        CL_IN  ClUint64T instantiateCookie)
{

    ClRcT  rc = CL_OK;
    ClUint32T  escalation = 0;
    ClAmsEntityRefT  entityRef = {{CL_AMS_ENTITY_TYPE_ENTITY},0,0};

    AMS_FUNC_ENTER (("\n"));

    if(!compName) 
        return CL_AMS_RC(CL_ERR_INVALID_PARAMETER);

    /*
     * First find the name reported by the fault API in the component database
     * If the name is not found in the component database it means that its a node
     * level fault escalation. In this case find the node in the node database.
     */

    memcpy (&entityRef.entity.name, compName, sizeof (SaNameT));
    entityRef.entity.type = CL_AMS_ENTITY_TYPE_COMP; 
    
    AMS_CALL ( clOsalMutexLock(gAms.mutex));

    if ( (rc = clAmsEntityDbFindEntity(&gAms.db.entityDb[CL_AMS_ENTITY_TYPE_COMP],&entityRef)) == CL_OK )
    {
        ClUint64T currentInstantiateCookie = 0;
        ClAmsCompT *comp = (ClAmsCompT*)entityRef.ptr;
        clLogInfo("COMP", "FAILURE", "Processing fault for component [%s], instantiate Cookie [%lld]", comp->config.entity.name.value, instantiateCookie);
        
        currentInstantiateCookie = comp->status.instantiateCookie;
        if(instantiateCookie && instantiateCookie < currentInstantiateCookie)
        {
            clLogInfo("COMP", "FAILURE", 
                      "Ignoring fault for component [%s], instantiation identifier [%lld] "
                      "as component has already been recovered with instantiation identifier [%lld]",
                      comp->config.entity.name.value, instantiateCookie,
                      comp->status.instantiateCookie);
            goto exitfn;
        }
        AMS_CHECK_RC_ERROR ( clAmsPeEntityFaultReport(
                    entityRef.ptr,
                    &recommendedRecovery,
                    &escalation) );

    }

    else
    {

        if ( CL_GET_ERROR_CODE (rc) != CL_ERR_NOT_EXIST )
        {
            clLogWarning("COMP", "FAILURE", "Unable to find component [%s:%d] in AMS database", 
                         compName->value, compName->length);
            goto exitfn;
        }

         /*
          * See if its node level fault escalation
          */

         entityRef.entity.type = CL_AMS_ENTITY_TYPE_NODE;

         AMS_CHECK_RC_ERROR( clAmsEntityDbFindEntity(
                     &gAms.db.entityDb[CL_AMS_ENTITY_TYPE_NODE],
                     &entityRef) ); 
         
         AMS_CHECK_RC_ERROR( clAmsPeEntityFaultReport(
                     entityRef.ptr,
                     &recommendedRecovery,
                     &escalation) );

     }

exitfn:

    AMS_CALL ( clOsalMutexUnlock(gAms.mutex));
    return CL_AMS_RC (rc);

}
static ClRcT clAmsMgmtSGRedundancyModelNoRedundancy(ClAmsSGRedundancyModelT model,
                                                    const ClCharT *sg,
                                                    const ClCharT *prefix,
                                                    ClUint32T numActiveSUs,
                                                    ClUint32T numStandbySUs,
                                                    ClAmsMgmtMigrateListT *migrateList)
{
    ClAmsSGConfigT sgConfig = {{CL_AMS_ENTITY_TYPE_ENTITY}};
    ClAmsEntityConfigT *entityConfig = NULL;
    ClRcT rc = CL_OK;
    ClAmsEntityT sgName = {CL_AMS_ENTITY_TYPE_ENTITY};
    ClUint64T bitMask = 0;

    sgName.type = CL_AMS_ENTITY_TYPE_SG;
    saNameSet(&sgName.name, sg);
    ++sgName.name.length;
    rc = clAmsMgmtEntityGetConfig(gHandle, &sgName, &entityConfig);
    if(rc != CL_OK)
    {
        clLogError("AMS", "MIGRATE", "AMS entity get config returned [%#x]", rc);
        goto out;
    }

    memcpy(&sgConfig, entityConfig, sizeof(sgConfig));
    clHeapFree(entityConfig);

    if(sgConfig.redundancyModel == CL_AMS_SG_REDUNDANCY_MODEL_NONE)
    {
        clLogWarning("AMS", "MIGRATE", "Redundancy model is already no redundancy");
        goto out;
    }

    bitMask |= SG_CONFIG_REDUNDANCY_MODEL;
    sgConfig.redundancyModel = CL_AMS_SG_REDUNDANCY_MODEL_NONE;

    bitMask |= SG_CONFIG_NUM_PREF_ACTIVE_SUS_PER_SI;
    sgConfig.numPrefActiveSUsPerSI = 1;
    
    bitMask |= SG_CONFIG_NUM_PREF_ACTIVE_SUS;
    sgConfig.numPrefActiveSUs = numActiveSUs;

    bitMask |= SG_CONFIG_NUM_PREF_STANDBY_SUS;
    sgConfig.numPrefStandbySUs = numStandbySUs;
    
    bitMask |= SG_CONFIG_NUM_PREF_INSERVICE_SUS;
    sgConfig.numPrefInserviceSUs = numActiveSUs + numStandbySUs;

    bitMask |= SG_CONFIG_NUM_PREF_ASSIGNED_SUS;
    sgConfig.numPrefAssignedSUs = numActiveSUs + numStandbySUs;

    rc = clAmsMgmtCCBEntitySetConfig(gCcbHandle, &sgConfig.entity, bitMask);

    if(rc != CL_OK)
    {
        clLogError("AMS", "MIGRATE", "AMS sg set config returned [%#x]", rc);
        goto out;
    }

    rc = clAmsMgmtCCBCommit(gCcbHandle);

    if(rc != CL_OK)
    {
        clLogError("AMS", "MIGRATE", "AMS database commit returned [%#x]", rc);
        goto out;
    }

    out:
    return rc;
}
ClRcT cpmNodeAdd(ClCharT *nodeName)
{
    ClRcT rc = CL_OK;
    ClCpmLT *cpm = NULL;
    ClUint16T nodeKey = 0;
    ClCpmSlotInfoT slotInfo = {0};

    if (!nodeName)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM, "NULL pointer passed.");
        goto failure;
    }

    clOsalMutexLock(gpClCpm->cpmTableMutex);
    rc = cpmNodeFindLocked((SaUint8T *)nodeName, &cpm);
    clOsalMutexUnlock(gpClCpm->cpmTableMutex);
    if (cpm)
    {
        clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM, "Node [%s] already exists on this node.", nodeName);
        rc = CL_CPM_RC(CL_ERR_ALREADY_EXIST);
        goto failure;
    }

    cpm = (ClCpmLT*) clHeapAllocate(sizeof(ClCpmLT));
    if (!cpm)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Unable to allocate memory");
        goto failure;
    }

    memset(cpm, 0, sizeof(ClCpmLT));
    
    strncpy(cpm->nodeName, nodeName, strlen(nodeName));
    
    rc = clCksm16bitCompute((ClUint8T *)cpm->nodeName,
                            strlen(cpm->nodeName),
                            &nodeKey);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Failed to compute checksum for node, "
                   "error [%#x]",
                   rc);
        goto failure;
    }

    /* 
     * Filling the CPML with defaults.  
     */

    saNameSet(&cpm->nodeType, nodeName);
    saNameSet(&cpm->nodeIdentifier, nodeName);
    /*
     * Set the class type to CLASS_C.
     */
    strncpy(cpm->classType, "CL_AMS_NODE_CLASS_C", sizeof(cpm->classType)-1);
    /*
     * Get the MOID of the master node. Assuming that node add is
     * only invoked on the master.
     */
    slotInfo.slotId = clIocLocalAddressGet();

    rc = clCpmSlotInfoGet(CL_CPM_SLOT_ID, &slotInfo);
    if(rc == CL_OK)
    {
        rc = cpmCorMoIdToMoIdNameGet(&slotInfo.nodeMoId, &cpm->nodeMoIdStr);
    }
    if(rc != CL_OK)
    {
        if((CL_GET_ERROR_CODE(rc) != CL_IOC_ERR_COMP_UNREACHABLE) && (CL_GET_ERROR_CODE(rc) != CL_ERR_NOT_EXIST) && (CL_GET_ERROR_CODE(rc) != CL_ERR_NOT_SUPPORTED))
        {
            goto failure;
        }
        else
        {
            rc = CL_OK;
            clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM, "COR server not running so cannot discover the Node's MoId");
        }
    }

    clOsalMutexLock(gpClCpm->cpmTableMutex);

    rc = clCntNodeAdd(gpClCpm->cpmTable,
                      (ClCntKeyHandleT)(ClWordT)nodeKey,
                      (ClCntDataHandleT) cpm,
                      NULL);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Failed to add node to the CPM node table, "
                   "error [%#x]",
                   rc);
        clOsalMutexUnlock(gpClCpm->cpmTableMutex);
        goto failure;
    }

    ++gpClCpm->noOfCpm;

    clOsalMutexUnlock(gpClCpm->cpmTableMutex);

    /*
     * Add this to the slotinfo.
     */

    clOsalMutexLock(&gpClCpm->cpmMutex);
    rc = cpmSlotClassAdd(&cpm->nodeType, &cpm->nodeIdentifier, 0);
    clOsalMutexUnlock(&gpClCpm->cpmMutex);

    if(rc != CL_OK)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Node [%s] class add returned [%#x]", cpm->nodeType.value, rc);
    }

    clLogNotice("DYN", "NODE", "Node [%s] added to the cpm table with identity [%.*s]",
                cpm->nodeName, cpm->nodeIdentifier.length, cpm->nodeIdentifier.value);
                
    return CL_OK;

    failure:
    return rc;
}
/*
 * This is the main flusher therad function. This is where the flusher action
 * starts.
 */
void*
clLogFlusherStart(void  *pData)
{
    ClRcT              rc             = CL_OK;
    ClLogSvrStreamDataT  *pStreamData = (ClLogSvrStreamDataT*) pData;
    ClLogStreamHeaderT   *pHeader     = pStreamData->pStreamHeader;
    ClTimerTimeOutT      timeout      = {0, 0};
    ClOsalTaskIdT        taskId       = CL_HANDLE_INVALID_VALUE;

    clLogDebug(CL_LOG_AREA_SVR, CL_LOG_CTX_BOOTUP,
            "Flusher started for stream [%.*s]", pStreamData->shmName.length, pStreamData->shmName.pValue);
    timeout.tsSec = pHeader->flushInterval / (1000L * 1000L * 1000L);
    timeout.tsMilliSec
        = (pHeader->flushInterval % (1000L * 1000L * 1000L)) / (1000L * 1000L);

    clLogDebug("LOG", "FLS", "timeout: %u sec %u millisec", timeout.tsSec, timeout.tsMilliSec);

    rc = clLogServerStreamMutexLockFlusher(pStreamData);
    if( CL_OK != rc )
    {
        clLogError("LOG", "FLS", "CL_LOG_LOCK(): rc[0x %x]", rc);
        pHeader->streamStatus = CL_LOG_STREAM_THREAD_EXIT;
        return NULL;
    }
    if ((CL_LOG_STREAM_HEADER_STRUCT_ID != pHeader->struct_id) || (CL_LOG_STREAM_HEADER_UPDATE_COMPLETE != pHeader->update_status))
    {/* Stream Header is corrupted so reset Header parameters */
       clLogStreamHeaderReset(pHeader); 
    }
    /*
     * Create a thread for flush interval
     */
    if( CL_LOG_SEM_MODE == clLogLockModeGet() )
    {
        rc = clLogFlushIntervalThreadCreate(pStreamData, &taskId);
        if( CL_OK != rc )
        {
            clLogWarning("SVR", "FLU", "Flusher interval thread create failed"
                    "flushFrequency function will still work..continuing...");
            rc = CL_OK;
            taskId = CL_HANDLE_INVALID_VALUE;
        }
    }

    while( gClLogSvrExiting == CL_FALSE )
    {
        CL_LOG_DEBUG_TRACE(("startIdx in server: %d  startAck  %d \n",
                    pHeader->recordIdx, pHeader->startAck));
        do
        {
            CL_LOG_DEBUG_TRACE(("recordIdx: %u startAck: %u  cnt %d",
                        pHeader->recordIdx, pHeader->startAck, 
                        pStreamData->ackersCount +
                        pStreamData->nonAckersCount));
#ifndef POSIX_BUILD
            rc = clLogServerStreamCondWait(pStreamData,
                                           &pHeader->flushCond,
                                           timeout);
#else
            rc = clLogServerStreamCondWait(pStreamData,
                                           NULL,
                                           timeout);
#endif
            if( gClLogSvrExiting == CL_TRUE 
                    || ( (CL_OK != CL_GET_ERROR_CODE(rc)) && 
                        (CL_ERR_TIMEOUT != CL_GET_ERROR_CODE(rc))) )
            { /* Log service is exiting or Stream is closed so come out of polling loop */
                pHeader->update_status = CL_LOG_STREAM_HEADER_UPDATE_INPROGRESS;
                pHeader->streamStatus = CL_LOG_STREAM_CLOSE;
            }
        }while( (CL_LOG_STREAM_CLOSE != pHeader->streamStatus) &&
                (0 == abs(pHeader->recordIdx - pHeader->startAck)));

        if( gClLogSvrExiting || CL_LOG_STREAM_CLOSE == pHeader->streamStatus )
        {
            clLogInfo("SVR", "FLU", "Stream status: CLOSE...Exiting flusher [%lu] "
                    " [%lu]", (unsigned long)pStreamData->flusherId, (long unsigned int)pthread_self());
            pHeader->streamStatus = CL_LOG_STREAM_THREAD_EXIT;
            pHeader->update_status = CL_LOG_STREAM_HEADER_UPDATE_COMPLETE;
            goto exitFlusher;
        }
        rc = clLogFlusherRecordsFlush(pStreamData);
        if( CL_OK != rc )
        {
            if(pHeader->streamStatus == CL_LOG_STREAM_CLOSE)
            {
                break;
            }
        }    

    }
    pHeader->streamStatus = CL_LOG_STREAM_THREAD_EXIT;
exitFlusher:

    if( CL_HANDLE_INVALID_VALUE != taskId )
    {
        /* Flusher interval thread has been created, so signal to that guy and
         * wait on the variable 
         */
        clLogFlushIntervalThreadJoin(pStreamData, taskId);
        taskId = CL_HANDLE_INVALID_VALUE;
    }
    clLogInfo("SVR", "FLU", "Flusher for stream [%.*s] is exiting..Id [%llu]", 
            pStreamData->shmName.length, pStreamData->shmName.pValue,
            pStreamData->flusherId);
    rc = clLogServerStreamMutexUnlock(pStreamData);
    if( CL_OK != rc )
    {
        clLogError("SVR", "FLU", "Faild to unlock the stream");
    }

    CL_LOG_DEBUG_TRACE(("Exit"));
    return NULL;
}    
static ClRcT cpmComponentAdd(ClCharT *compName)
{
    ClRcT rc = CL_CPM_RC(CL_ERR_NULL_POINTER);
    ClCpmCompConfigT compConfig = 
    {
        "",
        CL_FALSE,
        CL_AMS_COMP_PROPERTY_SA_AWARE,
        CL_CPM_COMP_SINGLE_PROCESS,
        "invalid",
        {(ClCharT*) "invalid", NULL},
        {NULL},
        "",
        "",
        0,
        0,
        0,
        0,
        0,
        {
            CL_CPM_COMPONENT_DEFAULT_HC_TIMEOUT,
            2 * CL_CPM_COMPONENT_DEFAULT_HC_TIMEOUT,
            CL_AMS_RECOVERY_NO_RECOMMENDATION
        }
    };
    ClCpmComponentT *comp = NULL;
    ClUint16T compKey = 0;
    const ClCharT *config = NULL;
    ClCharT cleanupCMD[CL_MAX_NAME_LENGTH];
        
    if (!compName)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "NULL pointer passed.");
        goto failure;
    }

    cleanupCMD[0] = 0;
    if( (config = getenv("ASP_CONFIG")) )
    {
        snprintf(cleanupCMD, sizeof(cleanupCMD), "%s/%s", config, CL_CPM_COMP_CLEANUP_SCRIPT);
        if(access(cleanupCMD, R_OK | X_OK))
            cleanupCMD[0] = 0;
    }
    rc = cpmCompFind((SaUint8T *)compName, gpClCpm->compTable, &comp);
    if (comp)
    {
        clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                     "Component [%s] already exists on this node",
                     compName);
        rc = CL_CPM_RC(CL_ERR_ALREADY_EXIST);
        goto failure;
    }

    strncpy(compConfig.compName, compName, CL_MAX_NAME_LENGTH-1);
    if(cleanupCMD[0])
        strncpy(compConfig.cleanupCMD, cleanupCMD, sizeof(compConfig.cleanupCMD)-1);

    rc = cpmCompConfigure(&compConfig, &comp);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Failed to configure component, error [%#x]",
                   rc);
        goto failure;
    }

    rc = clCksm16bitCompute((ClUint8T *) comp->compConfig->compName,
                            strlen(comp->compConfig->compName),
                            &compKey);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Failed to compute checksum for component, "
                   "error [%#x]",
                   rc);
        goto failure;
    }

    clOsalMutexLock(gpClCpm->compTableMutex);
    rc = clCntNodeAdd(gpClCpm->compTable,
                      (ClCntKeyHandleT)(ClWordT)compKey,
                      (ClCntDataHandleT) comp,
                      NULL);
    if (CL_OK != rc)
    {
        clLogError(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_MGM,
                   "Failed to add node to the CPM component table, "
                   "error [%#x]",
                   rc);
        clOsalMutexUnlock(gpClCpm->compTableMutex);
        goto failure;
    }
    ++gpClCpm->noOfComponent;
    clOsalMutexUnlock(gpClCpm->compTableMutex);

    return CL_OK;

failure:
    return rc;
}
ClRcT cpmUpdateTL(ClAmsHAStateT haState)
{
    ClIocTLInfoT tlInfo = {0};
    ClRcT rc = CL_OK;
    ClIocNodeAddressT localAddr = clIocLocalAddressGet();
    /*
     * Populate the TL structure 
     */
    cpmGetOwnLogicalAddress(&(tlInfo.logicalAddr));
    
    /*
     * CPM's component ID is slot number shifted
     * by CL_CPM_IOC_SLOT_BITS
     */
    CL_CPM_IOC_ADDRESS_SLOT_GET(clAspLocalId, tlInfo.compId);
    tlInfo.compId = tlInfo.compId << CL_CPM_IOC_SLOT_BITS;

    tlInfo.contextType = CL_IOC_TL_GLOBAL_SCOPE;
    tlInfo.physicalAddr.nodeAddress = localAddr;
    tlInfo.physicalAddr.portId = CL_IOC_CPM_PORT;
    tlInfo.haState = haState;

    if (haState == CL_AMS_HA_STATE_ACTIVE)
    {
        tlInfo.haState = CL_IOC_TL_ACTIVE;

        if( (ClInt32T) gpClCpm->activeMasterNodeId != -1)
        {
            clLogDebug(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                       "Deregistering TL entry for node [%d]",
                       gpClCpm->activeMasterNodeId);

            clIocTransparencyDeregister((gpClCpm->activeMasterNodeId) <<
                                        CL_CPM_IOC_SLOT_BITS);
        }
    }
    else if(haState == CL_AMS_HA_STATE_STANDBY)
    {
        tlInfo.haState = CL_IOC_TL_STDBY;
    }

    clLogMultiline(CL_LOG_SEV_DEBUG, CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                   "Updating transparency layer information for node [%s] -- \n"
                   "Component ID : [%#x] \n"
                   "Context type : [%s] \n"
                   "Node address : [%d] \n"
                   "Port ID : [%d] \n"
                   "HA state : [%s]",
                   gpClCpm->pCpmLocalInfo->nodeName,
                   tlInfo.compId,
                   tlInfo.contextType == CL_IOC_TL_GLOBAL_SCOPE ? "Global" :
                   "Local",
                   tlInfo.physicalAddr.nodeAddress,
                   tlInfo.physicalAddr.portId,
                   tlInfo.haState == CL_IOC_TL_ACTIVE ? "Active" : "Standby");

    /*
     * Update the TL with the CPM's logical address 
     */
    rc = clIocTransparencyRegister(&tlInfo);
    if(haState == CL_AMS_HA_STATE_ACTIVE)
    {
        /*
         * Reset the master segment cache for all components
         */
        clIocMasterCacheSet(localAddr);
    }
    else
    {
        clIocMasterCacheReset();
    }

    if (CL_IOC_ERR_TL_DUPLICATE_ENTRY == CL_GET_ERROR_CODE(rc)
        ||
        CL_ERR_ALREADY_EXIST == CL_GET_ERROR_CODE(rc))
    {
        clLogWarning(CPM_LOG_AREA_CPM, CPM_LOG_CTX_CPM_GMS,
                     "Transparency register returned "
                     "duplicate entry for node address [%d]",
                     tlInfo.physicalAddr.nodeAddress);
        return CL_OK;
    }

    return rc;
}