📄 rvmegacocontext.c
字号:
if( isNullContext(x) ) {
setCommandError(x,commReply,RV_MEGACOERROR_PROTOCOL,"Cannot move termination to NULL context");
return;
}
/* Verify that more terminations can be added */
if(!canAddTerm(x,term,commReply))
return;
rvMegacoTermProcessCommandStart(term);
/* Term is still in the old context! */
rvMegacoTermProcessAuditValue(term,rvMegacoSubtractCommandGetAudit(command),commReply);
rvMegacoContextRemove(term->context,term,commReply,rvFalse,rvFalse);
/* Move to new context */
rvMegacoTopologyAddTerm(&x->topology,term,x->alloc);
rvMegacoTermEnterContext(term,x);
rvMegacoTermProcessDigitMap(term,rvMegacoMoveCommandGetDigitMap(command),commReply);
rvMegacoTermProcessMedia(term,rvMegacoMoveCommandGetMedia(command),commReply);
rvMegacoTopologyConnectNewTerm(&x->topology,term,x->chosenTerm,x->topologyDescr,commReply,x->alloc);
rvMegacoTermProcessEventBuffer(term,rvMegacoMoveCommandGetEventBuffer(command),commReply);
rvMegacoTermProcessEvents(term,rvMegacoMoveCommandGetEvents(command),commReply);
rvMegacoTermProcessSignals(term,rvMegacoMoveCommandGetSignals(command),commReply);
/* Command fail, return term to original context */
if(!rvMegacoTermMgrUtilIsCmdRspValid(commReply)) {
RvMdmError error;
/* Save old context, remove will change it */
RvMegacoContext* oldContext = term->oldContext;
rvMdmErrorConstruct_(&error);
/* Remove termination from context */
rvMegacoContextRemove(x,term,NULL,rvTrue,rvFalse);
/* Return termination to original context */
/* By now don't restore old connections */
/* State is not defined anyway */
/*rvMegacoTopologyUpdateMediaConnections(&term->oldContext->topology,&error);*/
rvMegacoTermEnterContext(term,oldContext);
}
else {
rvMegacoTopologyRemoveTerm(&term->oldContext->topology,term,term->oldContext->alloc);
if(contextIsEmpty(term->oldContext))
rvMegacoTermMgrDeleteContext(x->termMgr,term->oldContext);
}
rvMegacoTermProcessCommandEnd(term);
return;
}
void rvMegacoContextRemove(RvMegacoContext * x,RvMegacoTerm * term,
RvMegacoCommandReply * commReply,
RvBool isSubtract,RvBool getStats) {
rvMutexLock(&x->mutex);
rvMegacoTopologyDisconnectTerm(&x->topology,term,x->alloc);
/* For move, the old context topology still keeps the
termination so it can be rolled back if move failed */
if(isSubtract)
rvMegacoTopologyRemoveTerm(&x->topology,term,x->alloc);
/* Set context as old context */
/* Collect stats including time in context stat */
rvMegacoTermLeaveContext(term,commReply,isSubtract,getStats);
rvMutexUnlock(&x->mutex);
}
static void deleteEphTerm(RvMegacoContext * x,RvMegacoTerm * term) {
rvMdmTermMgrDeleteEphTerm_(x->termMgr->mdmTermMgr,rvMegacoTermGetMdmTerm(term));
rvMegacoTermDestruct(term);
rvMegacoTermMgrRemoveFromEphContext(x->termMgr,term);
rvAllocDeallocate(x->alloc,sizeof(RvMegacoTerm),term);
}
static void processSubtractCommand(RvMegacoContext * x,RvMegacoTerm * term,
const RvMegacoCommand * command,RvMegacoCommandReply * commReply) {
/* Remove from x and close all the connections */
RvBool getStats = !hasEmpyAudit(rvMegacoSubtractCommandGetAudit(command));
rvMegacoTermProcessAuditValue(term,rvMegacoSubtractCommandGetAudit(command),commReply);
rvMegacoContextRemove(x,term,commReply,rvTrue,getStats);
if(rvMegacoTermIsPhysical(term))
rvMegacoTermMgrAddToNullContext(x->termMgr,term);
else
deleteEphTerm(x,term);
return;
}
static void setCommandError(RvMegacoContext * x,RvMegacoCommandReply * commReply,unsigned int code,const char * msg) {
rvMegacoTermMgrUtilAddError(commReply,code,msg,x->alloc);
}
static RvMegacoCommandReply * addCommandReply(RvMegacoContext * x,const char* termId_,
const RvMegacoCommand * command,RvMegacoActionReply * actionReply) {
RvMegacoCommandReply reply,* newReply;
rvMegacoCommandReplyConstructA(&reply,command,x->alloc);
if(!rvMegacoCommandReplyIsTerminationList(&reply)) {
RvMegacoTerminationId termId;
rvMegacoTerminationIdConstructA(&termId,termId_,x->alloc);
rvMegacoCommandReplySetTerminationId(&reply,&termId);
rvMegacoTerminationIdDestruct(&termId);
}
rvMegacoActionReplyAddReply(actionReply,&reply);
rvMegacoCommandReplyDestruct(&reply);
newReply = (RvMegacoCommandReply*)rvMegacoActionReplyGetReply(actionReply,
rvMegacoActionReplyGetNumReplies(actionReply)-1);
return newReply;
}
/*For physical term, move from null context to new context */
/*For ephemeral term, is already in new context*/
static void processAddCommand(RvMegacoContext * x,RvMegacoTerm * term,
const RvMegacoCommand * command,RvMegacoCommandReply * commReply) {
/* Verify that more terminations can be added */
if(!canAddTerm(x,term,commReply))
return;
/* Create the command reply */
rvMegacoTermProcessCommandStart(term);
if(rvMegacoTermIsPhysical(term))
rvMegacoTermMgrRemoveFromNullContext(x->termMgr,term);
else { /* Ephemeral termination is not really in the null
context but in the eph_context, but uses the same flag */
rvMegacoTermOutNullCtxt(term);
}
/* Put termination in the new context */
rvMegacoTopologyAddTerm(&x->topology,term,x->alloc);
rvMegacoTermEnterContext(term,x);
rvMegacoTermProcessAuditValue(term,rvMegacoAddCommandGetAudit(command),commReply);
rvMegacoTermProcessDigitMap(term,rvMegacoAddCommandGetDigitMap(command),commReply);
rvMegacoTermProcessMedia(term,rvMegacoAddCommandGetMedia(command),commReply);
rvMegacoTopologyConnectNewTerm(&x->topology,term,x->chosenTerm,
x->topologyDescr,commReply,x->alloc);
rvMegacoTermProcessEventBuffer(term,rvMegacoAddCommandGetEventBuffer(command),commReply);
rvMegacoTermProcessEvents(term,rvMegacoAddCommandGetEvents(command),commReply);
rvMegacoTermProcessSignals(term,rvMegacoAddCommandGetSignals(command),commReply);
/* Command fail */
if(!rvMegacoTermMgrUtilIsCmdRspValid(commReply)) {
/* Remove termination from context */
rvMegacoContextRemove(x,term,NULL,rvTrue,rvFalse);
/* For ephemeral term, remove and delete name from reply */
if(!rvMegacoTermIsPhysical(term)) {
deleteEphTerm(x,term);
rvMegacoCommandReplySetTerminationId(commReply,x->chooseId);
return;
}
else /* Return termination to null context */
rvMegacoTermMgrAddToNullContext(x->termMgr,term);
}
rvMegacoTermProcessCommandEnd(term);
return;
}
static void processModifyCommand(RvMegacoContext * x,RvMegacoTerm * term,
const RvMegacoCommand * command,RvMegacoCommandReply * commReply) {
rvMegacoTermProcessCommandStart(term);
rvMegacoTermProcessAuditValue(term,rvMegacoModifyCommandGetAudit(command),commReply);
rvMegacoTermProcessDigitMap(term,rvMegacoModifyCommandGetDigitMap(command),commReply);
rvMegacoTermProcessMedia(term,rvMegacoModifyCommandGetMedia(command),commReply);
rvMegacoTermProcessEventBuffer(term,rvMegacoModifyCommandGetEventBuffer(command),commReply);
rvMegacoTermProcessEvents(term,rvMegacoModifyCommandGetEvents(command),commReply);
rvMegacoTermProcessSignals(term,rvMegacoModifyCommandGetSignals(command),commReply);
rvMegacoTermProcessCommandEnd(term);
return;
}
/* In the case that an empty audit descriptor is received, the reply is built as
list of terminations, so in the case that this was addressed to only one,
the termination has to be set here ! */
static void setTermInAuditReply(RvMegacoContext * x,RvMegacoTerm * term,RvMegacoCommandReply * commReply) {
if(rvMegacoCommandReplyIsTerminationList(commReply) &&
rvMegacoCommandReplyGetTerminationListSize(commReply)==0 ) {
RvMegacoTerminationId tmpId;
rvMegacoTerminationIdConstructA(&tmpId,rvMegacoTermGetId(term),x->alloc);
rvMegacoCommandReplyAddTermination(commReply,&tmpId);
rvMegacoTerminationIdDestruct(&tmpId);
}
}
static void processAuditValue(RvMegacoContext * x,RvMegacoTerm * term,const RvMegacoCommand * command,RvMegacoCommandReply * commReply) {
rvMegacoTermProcessCommandStart(term);
rvMegacoTermProcessAuditValue(term,rvMegacoAuditValCommandGetAudit(command),commReply);
rvMegacoTermProcessCommandEnd(term);
setTermInAuditReply(x,term,commReply);
}
static void processAuditCaps(RvMegacoContext * x,RvMegacoTerm * term,const RvMegacoCommand * command,RvMegacoCommandReply * commReply) {
rvMegacoTermProcessCommandStart(term);
rvMegacoTermProcessAuditCaps(term,rvMegacoAuditCapCommandGetAudit(command),commReply);
rvMegacoTermProcessCommandEnd(term);
setTermInAuditReply(x,term,commReply);
}
static void processServiceChange(RvMegacoContext * x,RvMegacoTerm * term,const RvMegacoCommand * command,RvMegacoCommandReply * commReply) {
const RvMegacoServiceChangeDescriptor* sc;
RvMegacoServiceChangeMethod method;
sc = rvMegacoServiceChangeCommandGetServiceChange(command);
method = rvMegacoServiceChangeDescriptorGetMethod(sc);
/* Check if is the root termination */
if(rvMegacoTermMatchId(term,"root")) {
rvMegacoTermMgrProcessServiceChangeCommand(x->termMgr,command,commReply);
return;
}
/* Check that the MG is active */
/* If the termination manager is disabled, accept only SVC */
if(rvMegacoTermMgrIsDisabled(x->termMgr)) {
setCommandError(x,commReply,RV_MEGACOERROR_NOTAVAIL_SRVC,"Service Unavailable");
return;
}
/* Process for another termination */
rvMegacoTermProcessCommandStart(term);
/* The MGC wants to disconnect the MG */
if (method == RV_MEGACOSERVICECHANGEMETHOD_FORCED || method == RV_MEGACOSERVICECHANGEMETHOD_GRACEFUL) {
rvMegacoTermDisable(term);
}
else if (method == RV_MEGACOSERVICECHANGEMETHOD_RESTART) {
rvMegacoTermEnable(term);
}
else {
setCommandError(x,commReply,RV_MEGACOERROR_ILLEGAL_DESCRPARAM,"Invalid SVC Method");
}
rvMegacoTermProcessCommandEnd(term);
}
/* User data */
/* Atomic operation, doesn't need a mutex */
void rvMegacoContextSetUserData(RvMegacoContext * x,void* userData) {
x->userData = userData;
}
void* rvMegacoContextGetUserData(RvMegacoContext * x) {
return x->userData;
}
/*---------------------------------------------------------------------------------*/
/* Send a notify command */
/* Is the only transaction in the message for now */
/*---------------------------------------------------------------------------------*/
void rvMegacoContextSendNotifyOrError(RvMegacoContext * x,const char * termId,
RvMegacoObservedEventsDescriptor * obsDescr,
RvMegacoErrorDescriptor* errorDescr)
{
RvMegacoTransaction tmpTrans,* transaction;
RvMegacoAction tmpAction,* action;
RvMegacoNotifyCommand notifyCommand;
RvMegacoTerminationId id;
RvMegacoContextId contextId;
transaction = rvMegacoTransactionConstructA(&tmpTrans,x->alloc);
if(rvMegacoContextGetId(x)==0)
rvMegacoContextIdConstructSpecial(&contextId,RV_MEGACOCONTEXTID_NULL);
else
rvMegacoContextIdConstruct(&contextId,rvMegacoContextGetId(x));
rvMegacoActionConstructA(&tmpAction,&contextId,x->alloc);
rvMegacoTransactionAddAction(transaction,&tmpAction);
/* Get a pointer to the newly added action */
action = (RvMegacoAction*)rvMegacoTransactionGetAction(transaction,0);
/* Construct and add a notify command */
rvMegacoTerminationIdConstructA(&id,termId,x->alloc);
rvMegacoNotifyCommandConstructA(¬ifyCommand,&id,obsDescr,x->alloc);
/* Add the error descriptor */
if(errorDescr!=NULL)
rvMegacoNotifyCommandSetError(¬ifyCommand,errorDescr);
rvMegacoActionAddCommand(action,¬ifyCommand);
/* Send the transaction */
/* If the termination manager is down, drop it */
if( rvMegacoTermMgrIsUp(x->termMgr) ) {
#ifndef RV_MEGACOTERMMGR_TESTSTACKON
rvMegacoEntitySendRequest(&x->termMgr->mgcEntity, &tmpTrans, rvMegacoTermMgrProcReply, x->termMgr);
#else
rvMegacoTestStackSendRequest(x->termMgr,&tmpTrans);
#endif
}
/* Destruct temporary objects */
rvMegacoTransactionDestruct(&tmpTrans);
rvMegacoActionDestruct(&tmpAction);
rvMegacoNotifyCommandDestruct(¬ifyCommand);
rvMegacoTerminationIdDestruct(&id);
rvMegacoContextIdDestruct(&contextId);
}
void rvMegacoContextSendNotify(RvMegacoContext * x,const char * termId,
RvMegacoObservedEventsDescriptor * obsDescr)
{
rvMegacoContextSendNotifyOrError(x,termId,obsDescr,NULL);
}
void rvMegacoContextSetWildError(RvMegacoTransactionReply* reply,RvAlloc* alloc) {
RvMegacoContextId contextId;
RvMegacoActionReply actionReply;
RvMegacoErrorDescriptor error;
rvMegacoContextIdConstructSpecial(&contextId,RV_MEGACOCONTEXTID_ALL);
rvMegacoActionReplyConstructExA(&actionReply,&contextId,alloc);
rvMegacoContextIdDestruct(&contextId);
rvMegacoErrorDescriptorConstructA(&error,RV_MEGACOERROR_NOMATCH_TERMID,
"No TerminationID matched a wildcard",alloc);
rvMegacoActionReplySetError(&actionReply,&error);
rvMegacoErrorDescriptorDestruct(&error);
rvMegacoTransactionReplyAddReply(reply,&actionReply);
rvMegacoActionReplyDestruct(&actionReply);
}
/* Process terminations in context */
RvBool rvMegacoContextForEachTerm(RvMegacoContext* x,RvMdmProcessEachTermCB func,void* data) {
RvMegacoTerm * term;
RvGraphNodeIter i,nextIter;
RvBool retval = rvFalse;
/* Loop over matching terminations, add a reply for each one unless is
a wildcarded response or termination list is required */
rvMutexLock(&x->mutex);
for(i=rvGraphBegin(&x->topology);i!=rvGraphEnd(&x->topology); i=nextIter) {
nextIter = rvGraphNodeIterNext(i);
term = (RvMegacoTerm*)rvGraphNodeIterGetNode(i);
if( (retval=func(rvMegacoTermGetMdmTerm(term),data)) == rvTrue )
break;
}
rvMutexUnlock(&x->mutex);
return retval;
}
void rvMegacoContextConstruct(RvMegacoContext * x,RvUint32 id,RvMegacoTermMgr * mgr,RvAlloc * alloc) {
/* Termination manager the context belongs to */
x->termMgr = mgr;
/* Context id */
x->id = id;
/* Context allocator */
x->alloc = alloc;
/* Holds all the terminations,media and topology in the
context */
rvGraphConstructA(&x->topology,x->alloc);
rvMutexConstruct(&x->mutex);
x->userData = NULL;
x->isEmergency = rvFalse;
x->priority = 0;
}
void rvMegacoContextDestruct(RvMegacoContext * x) {
/* Holds all the terminations,media and topology in the
context */
rvGraphDestruct(&x->topology);
rvMutexDestruct(&x->mutex);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -