📄 rvmegacotermmgr.c
字号:
RvMegacoServiceChangeDescriptor * sc,RvBool keepEntity,
RvMegacoServiceChangeMethod method)
{
RvMegacoCommand command;
RvMegacoContextId contextId;
RvMegacoTransaction transaction;
RvMegacoAction action;
RvMegacoTerminationId tId;
RvBool rval = rvFalse;
rvMegacoServiceChangeDescriptorSetMethod(sc, method);
rvMegacoServiceChangeDescriptorSetVersion(sc, rvMegacoVersion);
rvMegacoTerminationIdConstruct(&tId, term->terminationId);
rvMegacoServiceChangeCommandConstruct(&command, &tId, sc);
rvMegacoContextIdConstructSpecial(&contextId, RV_MEGACOCONTEXTID_NULL);
/* Construct action */
rvMegacoActionConstruct(&action, &contextId);
/* Add command to action */
rvMegacoActionAddCommand(&action, &command);
/* Construct transaction */
rvMegacoTransactionConstruct(&transaction);
/* Add action to transaction */
rvMegacoTransactionAddAction(&transaction, &action);
if (mgr->mgcEntityValid) {
/* If is still the same address, then there is no need to
rebuild the entity */
if(!keepEntity)
rvMegacoEntityDestruct(&mgr->mgcEntity);
}
if (keepEntity || rvMegacoEntityConstructRemote(&mgr->mgcEntity,remoteAddr, rvTrue, mgr->localEntity) !=NULL)
{
mgr->mgcEntityValid = rvTrue;
rvMegacoServiceChangeDescriptorCopy(&mgr->sc, sc );
/* Send transaction */
#ifndef RV_MEGACOTERMMGR_TESTSTACKON
rvMegacoEntitySendRequest(&mgr->mgcEntity, &transaction, procServiceChangeReply, mgr);
#else
rvMegacoTestStackSendRequest(mgr,&transaction);
#endif
mgr->state = RV_MEGACOTERMMGRSTATE_REGISTERING;
rval = rvTrue;
}
/* Destroy objects */
rvMegacoTerminationIdDestruct(&tId);
rvMegacoTransactionDestruct(&transaction);
rvMegacoActionDestruct(&action);
rvMegacoContextIdDestruct(&contextId);
rvMegacoServiceChangeCommandDestruct(&command);
return(rval);
}
void rvMegacoTermMgrSendServiceChangeUp(RvMegacoTermMgr * mgr,RvMegacoTerm * term,RvMegacoServiceChangeDescriptor * sc)
{
RvBool rval = rvFalse;
RvBool keepEntity = rvFalse;
RvMegacoServiceChangeMethod method;
RvListIter(RvMegacoEntityAddress) tempIter;
/* Make sure that termination is active */
rvMegacoTermEnable(term);
while (rval == rvFalse)
{
if (mgr->state == RV_MEGACOTERMMGRSTATE_DISCONNECTED) /* If the state of the TermMgr is DISCONNECTED: */
{
tempIter = rvPtrListBegin(&mgr->mgcAddrList);/* Connect to first entry in the table (the primary MGC for this MG)*/
if (rvMegacoEntityAddressEqual(rvListIterData(tempIter), rvMegacoEntityGetAddress(&mgr->mgcEntity) ))
{ /* Unless, the last entity that we were connected to is the first entry in the table */
tempIter = rvPtrListIterNext(tempIter); /* Go to the second entry in the table. */
if (tempIter == rvPtrListEnd(&mgr->mgcAddrList)) /* if there's only one entry */
tempIter = rvPtrListBegin(&mgr->mgcAddrList); /* go back to the begining - so we don't wait around */
}
mgr->mgcAddrListIter = tempIter;
mgr->state = RV_MEGACOTERMMGRSTATE_REGISTERING;
}
/* Otherwise, attempt to connect to the first entry in the table (the primary MGC for this MG) */
/* then, set the state to REGISTERING and continue to cycle through the entries in the table */
/* If the state is REGISTERING, then just continue to cycle through the entries in the table */
/* If we're at the end of the list, sleep before trying from the begining of the list */
if (mgr->mgcAddrListIter == rvPtrListEnd(&mgr->mgcAddrList))
{
rvThreadSleep(1000);
mgr->mgcAddrListIter = rvPtrListBegin(&mgr->mgcAddrList);
}
/* We should not be at the end of the list...*/
if (mgr->mgcAddrListIter != rvPtrListEnd(&mgr->mgcAddrList))
{
if (rvMegacoEntityAddressEqual(&mgr->lastConnectedAddress,rvListIterData(mgr->mgcAddrListIter)))
{
rvMdmServiceChangeSetReason(sc, RV_MDMSERVICECHANGEREASON_MGCFAILURE);
method = RV_MEGACOSERVICECHANGEMETHOD_DISCONNECTED;
keepEntity = rvTrue;
}
else
{
/* When we're not sending the SC to the primary MGC, set the method to FAILOVER */
if (mgr->mgcAddrListIter != rvPtrListBegin(&mgr->mgcAddrList))
{
rvMdmServiceChangeSetReason(sc, RV_MDMSERVICECHANGEREASON_MGCFAILURE);
method = RV_MEGACOSERVICECHANGEMETHOD_FAILOVER;
}
else
{
rvMdmServiceChangeSetReason(sc, RV_MDMSERVICECHANGEREASON_COLDBOOT);
method = RV_MEGACOSERVICECHANGEMETHOD_RESTART;
}
}
rval = sendServiceChangeToAddress(mgr,term, rvListIterData(mgr->mgcAddrListIter), sc,keepEntity,method);
mgr->mgcAddrListIter = rvPtrListIterNext(mgr->mgcAddrListIter);
}
}
}
/* Reconnect to the current MGC */
void rvMegacoTermMgrReconnect(RvMegacoTermMgr * mgr)
{
rvMutexLock(&mgr->lock);
mgr->state = RV_MEGACOTERMMGRSTATE_REGISTERING;
sendServiceChangeToAddress(mgr,mgr->rootTermination,rvMegacoEntityGetAddress(&mgr->mgcEntity), &mgr->sc,rvTrue,RV_MEGACOSERVICECHANGEMETHOD_RESTART);
rvMutexUnlock(&mgr->lock);
}
/* Take the MG out of service */
static void sendServiceChangeDown(RvMegacoTermMgr * mgr,RvMegacoTerm * term,
RvMegacoServiceChangeDescriptor * sc,
RvMegacoReplyCb callbackFunc )
{
RvMegacoCommand command;
RvMegacoContextId contextId;
RvMegacoTransaction transaction;
RvMegacoAction action;
RvMegacoTerminationId tId;
rvMegacoServiceChangeDescriptorSetMethod(sc, RV_MEGACOSERVICECHANGEMETHOD_FORCED);
rvMegacoTerminationIdConstruct(&tId, term->terminationId);
rvMegacoServiceChangeCommandConstruct(&command, &tId, sc);
rvMegacoContextIdConstructSpecial(&contextId, RV_MEGACOCONTEXTID_NULL);
/* Construct action */
rvMegacoActionConstruct(&action, &contextId);
/* Add command to action */
rvMegacoActionAddCommand(&action, &command);
/* Construct transaction */
rvMegacoTransactionConstruct(&transaction);
/* Add action to transaction */
rvMegacoTransactionAddAction(&transaction, &action);
rvMegacoServiceChangeDescriptorCopy(&mgr->sc, sc );
/* Send transaction */
rvMegacoEntitySendRequest(&mgr->mgcEntity, &transaction, callbackFunc, mgr);
/* Destroy objects */
rvMegacoTerminationIdDestruct(&tId);
rvMegacoTransactionDestruct(&transaction);
rvMegacoActionDestruct(&action);
rvMegacoContextIdDestruct(&contextId);
rvMegacoServiceChangeCommandDestruct(&command);
}
/* Send a service change down message for other than the root termination */
static void sendTerminationServiceChangeDown(RvMegacoTermMgr * mgr,RvMegacoTerm * term,RvMegacoServiceChangeDescriptor * sc)
{
sendServiceChangeDown(mgr,term, sc,NULL ) ;
}
static void freeTerm(RvMegacoTerm * term,RvAlloc * a) {
rvMegacoTermDestruct(term);
rvAllocDeallocate(a,sizeof(RvMegacoTerm),term);
}
static RvBool MegacoUnregisterTerm(RvMdmXTermMgr * x,RvMdmXTerm * xTerm,RvMegacoServiceChangeDescriptor * sc) {
RvMegacoTermMgr * mgr = (RvMegacoTermMgr*)x;
RvMegacoTerm * term = (RvMegacoTerm*)xTerm;
RvMegacoContext * activeContext = NULL;
if(!rvMegacoTermIsInNullCtxt(term))
activeContext = rvMegacoTermGetContext(term);
/* Stop signals, delete media */
rvMegacoTermProcessCommandStart(term);
rvMegacoTermDisable(term);
rvMegacoTermProcessCommandEnd(term);
/* If termination found in active context,remove */
/* Note: at this point the application resources are released already
so rvMegacoTermLeaveContext() is not needed */
if(activeContext!=NULL) {
rvMutexLock(&activeContext->mutex);
rvMegacoTopologyRemoveTerm(&activeContext->topology,term,activeContext->alloc);
rvMutexUnlock(&activeContext->mutex);
}
/* Send the service change */
if(!rvMegacoTermIsEphemeral(term) && mgr->state == RV_MEGACOTERMMGRSTATE_REGISTERED ) {
sendTerminationServiceChangeDown(mgr,term,sc);
}
if(rvMegacoTermIsPhysical(term) ) {
rvMegacoTopologyRemoveTerm(&mgr->nullContext.topology,term,mgr->alloc);
freeTerm(term,mgr->alloc);
}
else if(rvMegacoTermIsEphemeral(term)) {
/* For ephemeral terminations,call the user callback */
/* There is some 'risk' that the user already released the asociated
resources... */
rvMdmTermMgrDeleteEphTerm_(mgr->mdmTermMgr,rvMegacoTermGetMdmTerm(term));
rvMegacoTopologyRemoveTerm(&mgr->ephContext.topology,term,mgr->ephContext.alloc);
freeTerm(term,mgr->alloc);
}
else if(term==mgr->rootTermination) {
rvMegacoTermDestruct(term);
}
else
return rvFalse;
return rvTrue;
}
/* Remove a termination from the ephemeral context */
void rvMegacoTermMgrRemoveFromEphContext(RvMegacoTermMgr * mgr,struct RvMegacoTerm_ * term) {
rvMutexLock(&mgr->ephContext.mutex);
rvMegacoTopologyRemoveTerm(&mgr->ephContext.topology,term,mgr->ephContext.alloc);
rvMutexUnlock(&mgr->ephContext.mutex);
}
typedef struct {
RvMegacoServiceChangeDescriptor * sc;
RvMegacoTermMgr * mgr;
} RvMegacoTermMgrUnregisterInfo;
static RvBool unregisterEachTerm(RvMdmTerm* term,void* data) {
RvMegacoTermMgrUnregisterInfo* info = (RvMegacoTermMgrUnregisterInfo*)data;
MegacoUnregisterTerm(info->mgr,term->xTerm,info->sc);
return rvTrue;
}
static void MegacoClearTerm(RvMdmXTermMgr * x,RvMegacoServiceChangeDescriptor * sc) {
RvMegacoTermMgr * mgr = (RvMegacoTermMgr*)x;
RvMegacoTermMgrUnregisterInfo info;
/* For each physical termination */
/*
t = &(mgr->nullContext.topology);
for(i=0;i<rvMegacoTopologyGetNumTerm(t);i++) {
MegacoUnregisterTerm(mgr,rvMegacoTopologyGetTermByIndex(t,i),sc);
}
*/
info.sc = sc;
info.mgr = mgr;
rvMegacoContextForEachTerm(&mgr->nullContext,unregisterEachTerm,&info);
/* For each ephemeral termination */
/*
t = &(mgr->ephContext.topology);
for(i=0;i<rvMegacoTopologyGetNumTerm(t);i++) {
MegacoUnregisterTerm(mgr,rvMegacoTopologyGetTermByIndex(t,i),sc);
}
MegacoUnregisterTerm(mgr,mgr->rootTermination,sc);
*/
rvMegacoContextForEachTerm(&mgr->ephContext,unregisterEachTerm,&info);
}
static RvMdmTerm* MegacoFindTerm(RvMdmXTermMgr * x,const char* id) {
RvMegacoTermMgr * mgr = (RvMegacoTermMgr*)x;
RvMegacoTerm * term = findInAllContexts(mgr,id);
return term!=NULL ? rvMegacoTermGetMdmTerm(term) : NULL;
}
typedef struct RvMegacoIdleTermInfo_ {
RvMegacoTerm* term;
const char * pattern;
} RvMegacoIdleTermInfo;
static RvBool findIdleTerm(void *node, void *data) {
RvMegacoTerm* term = (RvMegacoTerm*)node;
RvMegacoIdleTermInfo* info = (RvMegacoIdleTermInfo*)data;
if( rvMegacoTermIsInNullCtxt(term) && rvMegacoTermMatchWildcardEx(term,info->pattern,'$') ) {
info->term = term;
return rvTrue;
}
return rvFalse;
}
static RvMdmTerm* MegacoGetIdleTerm(RvMdmXTermMgr * x,const char* id_) {
RvMegacoIdleTermInfo info = { NULL,NULL };
const char * id = "$";
if(strlen(id_))
id = id_;
info.pattern = id;
rvMegacoTermMgrForEachInNullContext(x,findIdleTerm,&info);
return info.term!=NULL ? rvMegacoTermGetMdmTerm(info.term) : NULL;
}
static RvMdmTerm* MegacoRegisterPhysTerm(RvMdmXTermMgr * x,RvMdmTermClass * c,
const char* id,RvMdmTermDefaultProperties* termProperties,
RvMegacoServiceChangeDescriptor * sc) {
RvMegacoTermMgr * mgr = (RvMegacoTermMgr*)x;
RvMegacoTerm * term = rvMegacoContextAddNewTerm(&mgr->nullContext,id);
RvMdmTerm * mdmTerm = rvMegacoTermGetMdmTerm(term);
rvMegacoTermSetType(term,RV_MDMTERMTYPE_PHYSICAL);
rvMegacoTermInNullCtxt(term);
/* Set default properties */
rvMegacoTermPhysInitDefState(term);
rvMegacoTermSetDefaultState(term,termProperties);
/* Construct the mdmTerm */
rvMdmTermConstruct_(mdmTerm,c,rvMegacoPhysTermMdmXClbks,term);
/* if(mgr->state == RV_MEGACOTERMMGRSTATE_REGISTERED || mgr->state == RV_MEGACOTERMMGRSTATE_REGISTERING)*/
if(mgr->state == RV_MEGACOTERMMGRSTATE_REGISTERED )
rvMegacoTermMgrSendTermServiceChangeUp(mgr,term,sc);
return mdmTerm;
}
static RvMdmTerm* MegacoRegisterEphTerm(RvMdmXTermMgr * x,RvMdmTermClass * c,
const char* id,RvMdmTermDefaultProperties* termProperties) {
RvMegacoTermMgr * mgr = (RvMegacoTermMgr*)x;
RvMegacoTerm * term = rvMegacoContextAddNewTerm(&mgr->ephContext,id);
RvMdmTerm * mdmTerm = rvMegacoTermGetMdmTerm(term);
rvMegacoTermSetType(term,RV_MDMTERMTYPE_EPHEMERAL);
rvMegacoTermInNullCtxt(term);
/* Set default properties */
rvMegacoTermSetDefaultState(term,termProperties);
/* Construct the mdmTerm */
rvMdmTermConstruct_(mdmTerm,c,rvMegacoEphTermMdmXClbks,term);
return mdmTerm;
}
/* The root termination is already constructed, id is fixed ("root") */
static RvMdmTerm* MegacoRegisterRootTerm(RvMdmXTermMgr * x,RvMdmTermClass * c,RvMdmTermDefaultProperties* termProperties) {
RvMegacoTermMgr * mgr = (RvMegacoTermMgr*)x;
RvMdmTerm * mdmTerm = rvMegacoTermGetMdmTerm(mgr->rootTermination);
RvMegacoParameterValue value;
char num[16];
/* Reset state (maybe is not first time that is registred */
rvMegacoTermResetDynamicFields(mgr->rootTermination);
/* Construct the mdmTerm */
rvMdmTermDestruct_(mdmTerm);
rvMdmTermConstruct_(mdmTerm,c,rvMegacoRootTermMdmXClbks,mgr->rootTermination);
/* Set default properties */
rvMegacoTermSetDefaultState(mgr->rootTermination,termProperties);
/* The class must support the root package */
if(!rvMdmTermIsPkgSupported_(mdmTerm,"root"))
rvMdmTermClassAddSupportedPkg(mdmTerm->termClass,"root",1);
/* Set the root package properties */
sprintf(num,"%u",rvMegacoTermMgrGetMaxContexts(mgr));
rvMegacoParameterValueConstructA(&value,num,mgr->alloc);
rvMegacoTermUpdateDefaultProperty(mgr->rootTermination,"root","maxNumberOfContexts",&value);
rvMegacoParameterValueDestruct(&value);
sprintf(num,"%u",rvMegacoTermMgrGetMaxTermPerContext(mgr));
rvMegacoParameterValueConstructA(&value,num,mgr->alloc);
rvMegacoTermUpdateDefaultProperty(mgr->rootTermination,"root","maxTerminationsPerContext",&value);
rvMegacoParameterValueDestruct(&value);
/* Construct the mdmTerm */
rvMdmTermDestruct_(mdmTerm);
rvMdmTermConstruct_(mdmTerm,c,rvMegacoRootTermMdmXClbks,mgr->rootTermination);
return mdmTerm;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -