/*
 * This api would be called as and when the object is no more and the corresponding entry 
 * within the container needs to be deleted.
 */
ClRcT clAlarmPayloadCntDelete(ClCorMOIdPtrT pMoId, ClAlarmProbableCauseT probCause, ClAlarmSpecificProblemT specificProblem)
{
	ClRcT rc = CL_OK;
	ClCntNodeHandleT nodeH;
    ClAlarmPayloadCntKeyT *pCntKey = clHeapAllocate(sizeof(ClAlarmPayloadCntKeyT));
    if(NULL == pCntKey)
    {
          CL_DEBUG_PRINT (CL_DEBUG_CRITICAL,("Memory allocation failed with rc 0x%x ", rc));
          return (rc);
    }    
    pCntKey->probCause = probCause;
    pCntKey->specificProblem = specificProblem;
    pCntKey->moId = *pMoId;

    clOsalMutexLock(gClAlarmPayloadCntMutex);        
    rc = clCntNodeFind(gPayloadCntHandle,(ClCntKeyHandleT)pCntKey,&nodeH);
	if(CL_OK == rc)
	{
    	rc = clCntAllNodesForKeyDelete(gPayloadCntHandle,(ClCntKeyHandleT)pCntKey);
    	if (CL_OK != rc)
	    {
        	CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clCntAllNodesForKeyDelete failed w rc:0x%x\n", rc));
	    }        
	}
	else
	{
		CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Node does not exist with rc:0x%x\n", rc));
	}
    clHeapFree(pCntKey);
	clOsalMutexUnlock(gClAlarmPayloadCntMutex);    
	return rc;
}
/**
 * Remove a transaction definition from txn-database.
 */
extern ClRcT clTxnDbTxnDefnRemove(
        CL_IN   ClTxnDbHandleT      txnDb,
        CL_IN   ClTxnTransactionIdT txnId)
{
    ClRcT   rc  = CL_OK;

    CL_FUNC_ENTER();

    rc = clCntAllNodesForKeyDelete(txnDb, (ClCntKeyHandleT) &txnId);

    CL_FUNC_EXIT();
    return (rc);
}
/**
 * Remove an existing job from transaction.
 * FIXME: THIS IS NOT MULTITHREAD SAFE
 */
ClRcT clTxnAppJobRemove(
        CL_IN   ClTxnDefnT              *pTxnDefn, 
        CL_IN   ClTxnTransactionJobIdT  jobId)
{
    CL_FUNC_ENTER();

    if (NULL == pTxnDefn)
    {
        CL_FUNC_EXIT();
        return CL_ERR_NULL_POINTER;
    }

    clCntAllNodesForKeyDelete(pTxnDefn->jobList, 
                              (ClCntKeyHandleT) &jobId);
    /* Following has to be done atomically */
    pTxnDefn->jobCount--;


    CL_FUNC_EXIT();
    return (CL_OK);
}
ClRcT _clGmsDbDelete(
           CL_IN    const ClGmsDbT* const  gmsDb,
           CL_IN    const ClGmsDbTypeT     type,
           /* Suppressing coverity warning for pass by value with below comment */
           // coverity[pass_by_value]
           CL_IN    const ClGmsDbKeyT      key)
{
    ClRcT   rc = CL_OK;
    ClCntKeyHandleT cntKey = NULL;

    if (gmsDb == (const void *)NULL)
        return CL_ERR_NULL_POINTER;

    rc = _clGmsDbGetKey(type, key, &cntKey);

    if (rc != CL_OK) return rc;

    rc = clCntAllNodesForKeyDelete(gmsDb->htbl[type], cntKey);

    return rc;

}
ClRcT   _clGmsNameIdDbDelete(ClCntHandleT  *dbPtr,
                             ClNameT       *name)
{
    ClRcT   rc = CL_OK;
    ClGmsDbKeyT key = {{0}};
    ClCntKeyHandleT cntKey = NULL;

    if (dbPtr == NULL)
    {
        return CL_ERR_NULL_POINTER;
    }

    memcpy(&key.name, name, sizeof(ClNameT));
    rc = _clGmsDbGetKey(CL_GMS_NAME_ID_DB, key, &cntKey);

    if (rc != CL_OK)
    {
        return rc;
    }

    rc = clCntAllNodesForKeyDelete(*dbPtr, cntKey);
    return rc;
}
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;
    }
}
ClRcT clCkptMasterPeerUpdateNoLock(ClIocPortT        portId, 
                                   ClUint32T         flag, 
                                   ClIocNodeAddressT localAddr,
                                   ClUint8T          credential) 
{
    ClRcT              rc           = CL_OK;
    CkptPeerInfoT      *pPeerInfo   = NULL;
    CkptNodeListInfoT  *pPeerInfoDH = NULL;
    ClCntNodeHandleT   nodeHdl      = 0;
    ClCntNodeHandleT   tempHdl      = 0;
    ClHandleT         *pMasterHandle  = NULL;
    
    /*
     * Check whether node/component is coming up or going down.
     */
    if(flag == CL_CKPT_SERVER_UP)
    {
        /*
         * Checkpoint server up scenario.
         */
         clLogDebug(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_ANNOUNCE,
                   "Received welcome message from master, updating the peerlist for [%d]",
                    localAddr);

         /* Reset the replica list for peer being welcomed without knowing the peer is available or not */
         if(localAddr != gCkptSvr->localAddr)
         {
             clLogNotice("PEER", "UPDATE",
                         "Resetting the replica list for the peer [%#x] being welcomed", localAddr);
             clCkptMasterReplicaListUpdateNoLock(localAddr);
         }

        /* 
         * Add an entry to the peer list if not existing.
         * Mark the node as "available" i.e. available for checkpoint 
         * operations like storing replicas etc..
         */
        rc = clCntDataForKeyGet( gCkptSvr->masterInfo.peerList,
                                 (ClPtrT)(ClWordT)localAddr,
                                 (ClCntDataHandleT *)&pPeerInfo);
        if( rc == CL_OK && pPeerInfo != NULL)
        {
            CL_ASSERT(pPeerInfo->ckptList != 0);
            pPeerInfo->credential = credential;
            pPeerInfo->available  = CL_CKPT_NODE_AVAIL;

            if(localAddr != gCkptSvr->localAddr)
            {
                pPeerInfo->replicaCount = 0;
            }
        }
        else
        {
            if( CL_OK !=( rc = _ckptMasterPeerListInfoCreate(localAddr, 
                            credential,0)))
            {
                return rc;
            }
        }        
    }
    else
    {
        /*
         * Node/component down scenario.
         */
        clLogDebug(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
                   "Updating the peerAddr [%d] for down notification",
                   localAddr);
        /* 
         * Find the corresponding entry from the peer list.
         */
        if( CL_OK != (rc = clCntDataForKeyGet(gCkptSvr->masterInfo.peerList,
                                             (ClCntKeyHandleT)(ClWordT)localAddr,
                                             (ClCntDataHandleT *) &pPeerInfo)))
        {
            rc = CL_OK;
            goto exitOnError;
        }

        if( flag != CL_CKPT_COMP_DOWN)
        {
            clLogDebug(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN,
                       "Either ckpt server or node down, "
                       "changing active address");
                    
            clCntFirstNodeGet(pPeerInfo->mastHdlList,&nodeHdl);
            tempHdl = 0;
            while(nodeHdl != 0)
            {
                rc = clCntNodeUserKeyGet(pPeerInfo->mastHdlList,nodeHdl,
                                    (ClCntKeyHandleT *)&pMasterHandle);
                if( CL_OK != rc )
                {
                    clLogError(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
                            "Not able get the data for node handle rc[0x %x]",
                            rc);
                    goto exitOnError;
                }
                rc = clCntNextNodeGet(pPeerInfo->mastHdlList, nodeHdl, 
                                      &tempHdl);
                /*
                 * Update the active address and inform the clients.
                 */
                if( CL_OK != (rc = _clCkpMastertReplicaAddressUpdate(*pMasterHandle, 
                                                                 localAddr)))
                {
                    return rc;
                }
                nodeHdl = tempHdl;
                tempHdl = 0;
            }
        }
        
        if (flag != CL_CKPT_SVR_DOWN)
        {
            /* 
             * Component down/ node down case.
             * In case of component down close the associated client Hdl.
             * Incase of node down close all client Hdl.
             * Delete the ckpt Hdls from the client handle List.
             */
            clLogDebug(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
                  "Closing the opened handles from this slot id [%d]...", 
                   localAddr);
            clCntFirstNodeGet(pPeerInfo->ckptList,&nodeHdl);
            while(nodeHdl != 0)
            {
                rc = clCntNodeUserDataGet(pPeerInfo->ckptList,nodeHdl,
                        (ClCntDataHandleT *)&pPeerInfoDH);
                if( CL_OK != rc )
                {
                    clLogError(CL_CKPT_AREA_MAS_DEP, CL_CKPT_CTX_PEER_DOWN, 
                            "Not able get the data for node handle rc[0x %x]",
                            rc);
                    goto exitOnError;
                }
                clCntNextNodeGet(pPeerInfo->ckptList,nodeHdl,&tempHdl);
                if ( (flag == CL_CKPT_COMP_DOWN && 
                     pPeerInfoDH->appPortNum == portId) || 
                     (flag == CL_CKPT_NODE_DOWN) )
                {
                    /*
                     * Close the checkpoint hdl but dont delete the entry from
                     * masterHdl list.
                     */
                    if(gCkptSvr->masterInfo.masterAddr == 
                                    gCkptSvr->localAddr) 
                    {                                    
                        clLogInfo(CL_CKPT_AREA_MAS_DEP,
                                  CL_CKPT_CTX_PEER_DOWN, 
                                  "Closing the handle [%#llX]...", 
                                  pPeerInfoDH->clientHdl);
                        _clCkptMasterCloseNoLock(pPeerInfoDH->clientHdl, 
                        localAddr, !CL_CKPT_MASTER_HDL); 
                    }    
                }
                nodeHdl = tempHdl;
                tempHdl = 0; 
            }
        }
        else if (flag == CL_CKPT_SVR_DOWN)
        {
            /*
             * Mark the availability of checkpoint server as UNAVAILABLE.
             */
            if(pPeerInfo->credential == CL_CKPT_CREDENTIAL_POSITIVE)
                gCkptSvr->masterInfo.availPeerCount--;
            pPeerInfo->available = CL_CKPT_NODE_UNAVAIL;
        }   

        if(flag == CL_CKPT_NODE_DOWN
           ||
           flag == CL_CKPT_SVR_DOWN)
        {
            
            /*
             * Node down case, delete the entry from master's peer list.
             */
            rc = clCntAllNodesForKeyDelete(gCkptSvr->masterInfo.peerList,
                                (ClPtrT)(ClWordT)localAddr);
             CKPT_ERR_CHECK(CL_CKPT_SVR,CL_LOG_SEV_ERROR,
             (" MasterPeerUpdate failed rc[0x %x]\n",rc),
             rc);

        }
        
        if( flag != CL_CKPT_COMP_DOWN)
        {
            /*
             * Find other nodes to store the replicas of checkpoints for whom
             * this node was storing the replicas.
             */
             if(gCkptSvr->masterInfo.masterAddr == gCkptSvr->localAddr)
             {
                 _ckptCheckpointLoadBalancing();
             }
        }
    }
exitOnError:
    {
        return rc;
    }
}  
/**
 * API to un-register a service with transaction-agent
 */
ClRcT clTxnAgentServiceUnRegister(CL_IN ClTxnAgentServiceHandleT tHandle)
{
    ClRcT                       rc = CL_OK;
    ClUint8T                    twoPC = 0;
    ClTxnAgentCompServiceInfoT  *pCompService = NULL;


    CL_FUNC_ENTER();

    if (tHandle == 0x0)
    {
        CL_FUNC_EXIT();
        return CL_TXN_RC(CL_ERR_INVALID_HANDLE);
    }
    /*
       This is a request from service hosted in the component to unregister
       from the transaction-management.
       Remove the entry from the data-structure and invalidate the handle

       FIXME: Before actually deleting it, check to see if this service is 
              part of any active txn or not
    */

    rc = clCntDataForKeyGet(clTxnAgntCfg->compServiceMap, 
                            (ClCntKeyHandleT) &(((ClTxnAgentCompServiceInfoT *)tHandle)->serviceType),
                            (ClCntDataHandleT *)&pCompService);
    if (CL_OK == rc)
    {
        ClUint32T   srvCount;
        if (pCompService->serviceCapability == CL_TXN_AGENT_SERVICE_1PC)
        {
            twoPC = 0;
            clTxnAgntCfg->agentCapability &= ~(CL_TXN_AGENT_SERVICE_1PC);
        }
        else if(pCompService->serviceCapability == CL_TXN_AGENT_SERVICE_2PC)
        {
            twoPC = 1;
        }

        rc = clCntAllNodesForKeyDelete(clTxnAgntCfg->compServiceMap,
                                      (ClCntKeyHandleT) &(((ClTxnAgentCompServiceInfoT *)tHandle)->serviceType));
        if(CL_OK != rc)
        {
            clLogError("AGT", NULL,
                    "Failed to delete node from compServiceMap corresponding to service[%d]", 
                    ((ClTxnAgentCompServiceInfoT *)tHandle)->serviceType);
            return rc;
        }
                                        
        /* Reset agent capability, if necessary */
        rc = clCntSizeGet(clTxnAgntCfg->compServiceMap, &srvCount);
        if ( (CL_OK == rc) && (srvCount == 0x0) )
        {
            clTxnAgntCfg->agentCapability = CL_TXN_AGENT_NO_SERVICE_REGD;
        } 
        else if ( (CL_OK == rc) && (srvCount == 0x1) && 
                  ( (clTxnAgntCfg->agentCapability & CL_TXN_AGENT_SERVICE_1PC) == CL_TXN_AGENT_SERVICE_1PC) )
        {
            clTxnAgntCfg->agentCapability = CL_TXN_AGENT_SERVICE_1PC;
        }
        else if ( CL_OK != rc )
        {
            CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Error while reading number of service registered. rc:0x%x", rc));
        }
    }
    if(CL_OK == rc)
        clLogNotice("AGT", "FIN",
                "Unregistering [%s] service successfull", twoPC ? "2PC":"READ"); 
    CL_TXN_RETURN_RC(rc, ("Failed to unregister component-service rc:0x%x\n", rc));
}