📄 rvmegacotrans.c
字号:
rvMutexUnlock(&tcbPtr->lock);
rvLogLeave(&rvLog, "rvMegacoTransMgrRecvRequest");
}
void rvMegacoTransMgrRecvReply( RvMegacoEntity *remote, const RvMegacoTransactionReply *reply)
{
RvMegacoTcbPtr tcbPtr;
RvHrtime roundTripTimeInNs;
RvHrtime currTime;
RvMegacoTransactionId tId = rvMegacoTransactionReplyGetId(reply);
RvMegacoEntity* localEntity;
RvBool doUnlock = rvTrue;
rvLogEnter(&rvLog, "rvMegacoTransMgrRecvReply");
localEntity = rvMegacoEntityGetLocalEntity(remote);
/* Find the TCB using the transaction Id */
tcbPtr = rvMegacoEntityFindTcb(localEntity, tId);
if (tcbPtr != NULL)
{
rvMutexLock(&tcbPtr->lock);
switch (tcbPtr->state)
{
case RV_MEGACOTCB_STATE_CMD_TO_SEND:
/* LLL If there was a way to remove the TCB from the send list */
/* we would do that here */
/* WARNING: FALLING THROUGH TO NEXT CASE !!! */
case RV_MEGACOTCB_STATE_CMDSENT:
currTime = rvTimeGetHrtime();
roundTripTimeInNs = rvTimeHrSubtract(currTime,tcbPtr->OrigSendTime);
rvMegacoEntityUpdateRoundTripTime(remote, roundTripTimeInNs);
tcbPtr->replyReceived = rvTrue;
rvMutexUnlock(&tcbPtr->lock); /* Unlock before callback */
if(tcbPtr->ReplyCallBack != NULL)
tcbPtr->ReplyCallBack(tcbPtr,reply,tcbPtr->data,RVTRANSACTIONSTATUS_RCV_REPLY);
rvMegacoEntityAddResponseAck(remote,tId);
if (tcbPtr->state == RV_MEGACOTCB_STATE_CMDSENT)
{
rvMutexLock(&tcbPtr->lock); /* Re-lock after callback and entity update*/
tcbPtr->state = RV_MEGACOTCB_STATE_INACTIVE;
rvMegacoTcbStopNStartTimer(tcbPtr, RV_MEGACOTM_SHORTINACTIVE_TO);
}
else
doUnlock = rvFalse;
break;
case RV_MEGACOTCB_STATE_IDLE:
break;
case RV_MEGACOTCB_STATE_RESPONDED:
case RV_MEGACOTCB_STATE_RESP_TO_SEND:
break;
case RV_MEGACOTCB_STATE_WAITAPPLRESPONSE:
break;
case RV_MEGACOTCB_STATE_INACTIVE:
break;
}
if (doUnlock)
rvMutexUnlock(&tcbPtr->lock);
}
rvLogLeave(&rvLog, "rvMegacoTransMgrRecvReply");
}
void rvMegacoTransMgrRecvPending(RvMegacoEntity *remote, RvMegacoTransactionId tId)
{
RvMegacoTcbPtr tcbPtr;
RvMegacoEntity* localEntity;
rvLogEnter(&rvLog, "rvMegacoTransMgrRecvPending");
localEntity = rvMegacoEntityGetLocalEntity(remote);
/* Find the TCB using the transaction Id */
tcbPtr = rvMegacoEntityFindTcb(localEntity, tId);
if (tcbPtr != NULL)
{
rvMutexLock(&tcbPtr->lock);
switch (tcbPtr->state)
{
case RV_MEGACOTCB_STATE_CMDSENT:
/* LLL update the timer based on receipt of this pending response msg */
/* According to page 127 of the spec. "The root termination has a property */
/* (ProvisionalResponseTimerValue) which can be set to the reauested maximum number of ms between receipt */
/* of a command and transmission of the TransactionPending response. */
rvMutexUnlock(&tcbPtr->lock); /* Unlock before callback */
if(tcbPtr->ReplyCallBack != NULL)
tcbPtr->ReplyCallBack(tcbPtr,NULL,tcbPtr->data,RVTRANSACTIONSTATUS_RCV_PENDING_REPLY);
rvMutexLock(&tcbPtr->lock); /* Re-lock after callback */
rvMegacoTcbStopNStartTimer(tcbPtr,(unsigned int)(rvMegacoEntityGetNextRetransTimeout(remote) / RV_TIME_NSECPERMSEC));
break;
case RV_MEGACOTCB_STATE_CMD_TO_SEND:
case RV_MEGACOTCB_STATE_RESP_TO_SEND:
case RV_MEGACOTCB_STATE_IDLE:
case RV_MEGACOTCB_STATE_RESPONDED:
case RV_MEGACOTCB_STATE_WAITAPPLRESPONSE:
case RV_MEGACOTCB_STATE_INACTIVE:
/* This message doesn't make sense in any of these states */
break;
}
rvMutexUnlock(&tcbPtr->lock);
}
rvLogLeave(&rvLog, "rvMegacoTransMgrRecvPending");
}
void rvMegacoTransMgrRecvRespAck(RvMegacoEntity *remote, RvMegacoTransactionId tId)
{
RvMegacoTcbPtr tcbPtr;
RvBool alreadyUnlocked = rvFalse;
rvLogEnter(&rvLog, "rvMegacoTransMgrRecvRespAck");
/* Find the TCB using the transaction Id */
tcbPtr = rvMegacoEntityFindTcb(remote, tId);
if (tcbPtr != NULL)
{
rvMutexLock(&tcbPtr->lock);
switch (tcbPtr->state)
{
case RV_MEGACOTCB_STATE_RESPONDED:
tcbPtr->msgFreed = rvTrue;
rvStrStreamDestruct(&tcbPtr->encodedTransaction);
tcbPtr->state = RV_MEGACOTCB_STATE_INACTIVE;
rvMegacoTcbStopNStartTimer(tcbPtr, RV_MEGACOTM_INACTIVE_TO);
rvMutexUnlock(&tcbPtr->lock); /* Unlock before callback */
alreadyUnlocked = rvTrue;
if (tcbPtr->AckCallBack != NULL)
tcbPtr->AckCallBack(tcbPtr,tcbPtr->data, RVTRANSACTIONSTATUS_RCV_REPLYACK);
break;
case RV_MEGACOTCB_STATE_IDLE:
case RV_MEGACOTCB_STATE_WAITAPPLRESPONSE:
case RV_MEGACOTCB_STATE_CMDSENT:
case RV_MEGACOTCB_STATE_INACTIVE:
case RV_MEGACOTCB_STATE_CMD_TO_SEND:
case RV_MEGACOTCB_STATE_RESP_TO_SEND:
break;
}
if (!alreadyUnlocked)
rvMutexUnlock(&tcbPtr->lock);
}
rvLogLeave(&rvLog, "rvMegacoTransMgrRecvRespAck");
}
/*$
{function:
{name: rvMegacoEntitySendRequest}
{class: RvMegacoEntity}
{include: rvmegacoentity.h}
{description:
{p: Queues a request transaction to be sent to a particular entity.}
}
{proto: void rvMegacoEntitySendRequest(RvMegacoEntity *remote, RvMegacoTransaction *t, RvMegacoReplyCb f, void *data);}
{params:
{param: {n:remote} {d:The entity to send the request to.}}
{param: {n:t} {d:The request transaction to be sent.}}
{param: {n:f} {d:The callback to be invoked for this request.}}
{param: {n:data} {d:The data to be passed to the callback.}}
}
}
$*/
void rvMegacoEntitySendRequest(RvMegacoEntity *remote, RvMegacoTransaction *t, RvMegacoReplyCb f, void *data)
{
RvMegacoStack *stack = remote->stack;
RvMegacoEntity *localEntity;
RvMegacoTcbPtr tcbPtr;
RvMegacoTransactionId tId;
rvLogEnter(&rvLog, "rvMegacoEntitySendRequest");
localEntity = rvMegacoEntityGetLocalEntity(remote);
tId = rvMegacoEntityGetNextTransactionId(localEntity);
rvMegacoTransactionSetId(t, tId);
/* allocate a tcb */
tcbPtr = (RvMegacoTcb *)rvAllocAllocate(stack->tcbAlloc, sizeof(RvMegacoTcb));
rvMegacoTcbConstruct(tcbPtr, stack, localEntity, remote, rvTrue, t);
rvMegacoEntityAddTcb(localEntity, tcbPtr);
rvMutexLock(&remote->mutex); /* Always lock entity first */
rvMutexLock(&tcbPtr->lock);
rvMegacoTransactionEncode(t, &tcbPtr->encodedTransaction, stack->encodeCompact);
tcbPtr->ReplyCallBack = f;
tcbPtr->data = data;
tcbPtr->state = RV_MEGACOTCB_STATE_CMD_TO_SEND;
/* put it in the entity's send list */
rvMegacoEntitySendListInsert(remote, tcbPtr);
rvMutexUnlock(&tcbPtr->lock);
rvMutexUnlock(&remote->mutex);
rvLogLeave(&rvLog, "rvMegacoEntitySendRequest");
}
/*$
{function:
{name: rvMegacoTcbSendReply}
{class: RvMegacoTcb}
{include: rvmegacotrans.h}
{description:
{p: Queues a reply transaction to be sent.}
}
{proto: void rvMegacoTcbSendReply(RvMegacoTcb *tcbPtr,
const RvMegacoTransactionReply *t, RvMegacoAckCB f, void *data);}
{params:
{param: {n:tcbPtr} {d:The transaction control block for this transaction.}}
{param: {n:t} {d:The reply transaction to be sent.}}
{param: {n:f} {d:The callback to be invoked for this reply.}}
{param: {n:data} {d:The data to be passed to the callback.}}
}
}
$*/
void rvMegacoTcbSendReply(RvMegacoTcb *tcbPtr, const RvMegacoTransactionReply *t, RvMegacoAckCB f, void *data)
{
RvMegacoEntity *destEntity;
rvLogEnter(&rvLog, "rvMegacoTcbSendReply");
/* Get the entity */
destEntity = rvMegacoTcbGetRemoteEntity(tcbPtr);
/* Must Lock the entity first */
rvMutexLock(&destEntity->mutex);
rvMutexLock(&tcbPtr->lock);
if (tcbPtr->state == RV_MEGACOTCB_STATE_RESP_TO_SEND)
/* Trigger the enitity to do a send */
rvMegacoEntitySendNow(tcbPtr->destEntity);
while (tcbPtr->state == RV_MEGACOTCB_STATE_RESP_TO_SEND)
rvThreadSleep(100);
if (tcbPtr->state == RV_MEGACOTCB_STATE_RESPONDED)
{
/* Need to rewind the string stream to clear out the existing transaction */
rvStrStreamSeekPos(&tcbPtr->encodedTransaction,0);
}
rvMegacoTransactionReplyEncode(t, &tcbPtr->encodedTransaction, tcbPtr->localEntity->stack->encodeCompact);
tcbPtr->AckCallBack = f;
tcbPtr->data = data;
tcbPtr->state = RV_MEGACOTCB_STATE_RESP_TO_SEND;
rvMegacoEntitySendListInsert(tcbPtr->destEntity, tcbPtr);
rvMutexUnlock(&tcbPtr->lock);
rvMutexUnlock(&destEntity->mutex);
rvLogLeave(&rvLog, "rvMegacoTcbSendReply");
}
/*$
{function:
{name: rvMegacoTcbSendPending}
{class: RvMegacoTcb}
{include: rvmegacotrans.h}
{description:
{p: Queues a pending message to be sent.}
}
{proto: void rvMegacoTcbSendPending(RvMegacoTcb *tcbPtr, RvMegacoAckCB f, void *data);}
{params:
{param: {n:tcbPtr} {d:The transaction control block for this transaction.}}
{param: {n:f} {d:The callback to be invoked for this pending reply.}}
{param: {n:data} {d:The data to be passed to the callback.}}
}
}
$*/
void rvMegacoTcbSendPending(RvMegacoTcb *tcbPtr, RvMegacoAckCB f, void *data)
{
RvMegacoEntity *destEntity;
rvLogEnter(&rvLog, "rvMegacoTcbSendPending");
/* Get the entity */
destEntity = rvMegacoTcbGetRemoteEntity(tcbPtr);
/* Must Lock the entity first */
rvMutexLock(&destEntity->mutex);
rvMutexLock(&tcbPtr->lock);
rvStrStreamSeekPos(&tcbPtr->encodedTransaction,0);
rvMegacoTransactionPendingEncode(tcbPtr->tId, &tcbPtr->encodedTransaction, tcbPtr->localEntity->stack->encodeCompact);
if (tcbPtr->SentPending == rvTrue)
{
rvMutexUnlock(&tcbPtr->lock);
rvMutexUnlock(&destEntity->mutex);
return;
}
tcbPtr->AckCallBack = f;
tcbPtr->data = data;
tcbPtr->SentPending = rvTrue;
rvMegacoEntitySendListInsert(tcbPtr->destEntity, tcbPtr);
rvMutexUnlock(&tcbPtr->lock);
rvMutexUnlock(&destEntity->mutex);
rvLogLeave(&rvLog, "rvMegacoTcbSendPending");
}
void rvMegacoTcbUpdateOnSend (RvMegacoTcbPtr tcbPtr)
{
rvMutexLock(&tcbPtr->lock);
switch(tcbPtr->state)
{
case RV_MEGACOTCB_STATE_CMD_TO_SEND:
if (tcbPtr->replyReceived)
{
tcbPtr->state = RV_MEGACOTCB_STATE_INACTIVE;
rvMegacoTcbStopNStartTimer(tcbPtr, RV_MEGACOTM_SHORTINACTIVE_TO);
}
else
{
if (tcbPtr->firstSend == rvTrue)
rvMegacoTcbStopNStartTimer(tcbPtr,(unsigned int) (rvMegacoEntityGetFirstRetransTimeout(tcbPtr->destEntity) / RV_TIME_NSECPERMSEC));
else
rvMegacoTcbStopNStartTimer(tcbPtr, (unsigned int)(rvMegacoEntityGetNextRetransTimeout(tcbPtr->destEntity) / RV_TIME_NSECPERMSEC));
tcbPtr->state = RV_MEGACOTCB_STATE_CMDSENT;
}
break;
case RV_MEGACOTCB_STATE_RESP_TO_SEND:
rvMegacoTcbStopNStartTimer(tcbPtr, RV_MEGACOTM_RESPONDED_TO);
tcbPtr->state = RV_MEGACOTCB_STATE_RESPONDED;
break;
case RV_MEGACOTCB_STATE_WAITAPPLRESPONSE:
tcbPtr->SentPending = rvFalse;
break;
case RV_MEGACOTCB_STATE_INACTIVE:
tcbPtr->firstSend = rvFalse;
break;
}
if (tcbPtr->firstSend == rvTrue)
tcbPtr->OrigSendTime = rvTimeGetHrtime();
rvMutexUnlock(&tcbPtr->lock);
}
void rvMegacoTcbUpdateFailedSend (RvMegacoTcbPtr tcbPtr)
{
rvMutexLock(&tcbPtr->lock);
switch(tcbPtr->state)
{
case RV_MEGACOTCB_STATE_CMD_TO_SEND:
tcbPtr->state = RV_MEGACOTCB_STATE_CMD_SEND_FAIL;
break;
case RV_MEGACOTCB_STATE_RESP_TO_SEND:
tcbPtr->state = RV_MEGACOTCB_STATE_RESP_SEND_FAIL;
break;
}
rvMegacoTcbStopNStartTimer(tcbPtr, 1);
rvMutexUnlock(&tcbPtr->lock);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -