#include <iostream>
#include <string>
struct GwListNode
{
int gwid;
InterConnectionGatewayContext gw;
GwListNode *next;
};
class GwCircleList
{
private:
GwListNode *head, *end;
GwListNode *flag_pos;//used to record polling position
public:
GwCircleList();
int length()const;
bool IsEmpty()const;
GwListNode *findByGwid(int)const;
GwListNode *findInsertPos(int)const;
void insertByGwid(InterConnectionGatewayContext gw);
void deleteByGwid(int id);
GwListNode* getFlagPos();
void setFlagPos(GwListNode* newpos);
void printList();
static int GwCircleListIndex;
};
class GwAlgorithm
{
public:
GwAlgorithm(void){}
~GwAlgorithm(void){}
void insertGw(InterConnectionGatewayContext gw);
void deleteGw(int id);
void ChangeGwWithBoolValue(int id, RELATE_PARE_CHANGE_T para_cat, bool& value);
void ChangeGwWithIntValue(int id, RELATE_PARE_CHANGE_T para_cat, int& value);
bool GwPollAlgorithm(int callervpn, InterConnectionGatewayContext& gw);
};
#endif
#include "gw_choose.hpp"
#include <iomanip>
GwCircleList GwCircleListForChoose;
int GwCircleList::GwCircleListIndex = 0;
GwCircleList::GwCircleList()
{
head = new GwListNode;
head->gwid = -1;
end = new GwListNode;
end->gwid = -1;
head->next = end;
end->next = head;
flag_pos = NULL;
}
int GwCircleList::length()const
{
return GwCircleListIndex;
}
bool GwCircleList::IsEmpty()const
{
if(GwCircleListIndex == 0)
{
return true;
}
return false;
}
GwListNode* GwCircleList::getFlagPos()
{
return flag_pos;
}
void GwCircleList::setFlagPos(GwListNode* newpos)
{
flag_pos = newpos;
return;
}
void GwCircleList::printList()
{
if(IsEmpty())
{
return;
}
GwListNode *node = head->next;
while (node->next != head)
{
node = node->next;
}
return;
}
GwListNode* GwCircleList::findByGwid( int gwid)const
{
GwListNode *node;
if(IsEmpty())
{
return NULL;
}
node = head->next;
while(gwid != node->gwid && node->next!=head)
{
node = node->next;
}
if(gwid == node->gwid)
{
return node;
}
return NULL;
}
GwListNode* GwCircleList::findInsertPos( int gwid)const
{
if(IsEmpty())
{
return NULL;
}
GwListNode *node,*prenode;
if(gwid< head->next->gwid)
{
return head;
}
node = head->next;
while(gwid > node->gwid && node->next != head)
{
prenode = node;
node = node->next;
}
return prenode;
}
void GwCircleList::deleteByGwid(int id)
{
GwListNode *node,*prenode;
node = head->next;
prenode = head;
if(GwCircleListIndex == 0)
{
return;
}
while(id != node->gwid && node->next != head)
{
prenode = node;
node = node->next;
}
if(id == node->gwid)
{
if(node->gwid == getFlagPos()->gwid && node->next != end)//its not the last one
{
setFlagPos(node->next);
}
prenode->next = node->next;
delete node;
GwCircleListIndex--;
}
printList();
return;
}
void GwCircleList::insertByGwid(InterConnectionGatewayContext gwinsert)
{
int gwid = gwinsert.gwid_;
GwListNode* newnode = new GwListNode;
newnode->gwid = gwid;
newnode->gw = gwinsert;
if(IsEmpty())
{
newnode->next = head->next;
head->next = newnode;
setFlagPos(newnode);
GwCircleListIndex++;
printList();
return;
}
if(findByGwid(gwid) != NULL) //delete old
{
deleteByGwid(gwid);
}
//insert new
GwListNode* frontnode = NULL;
frontnode = findInsertPos(gwid);
if(NULL != frontnode)
{
newnode->next = frontnode->next;
frontnode->next = newnode;
}
GwCircleListIndex++;
printList();
return;
}
void GwAlgorithm::insertGw(InterConnectionGatewayContext gw)
{
GwCircleListForChoose.insertByGwid(gw);
return;
}
void GwAlgorithm::deleteGw(int id)
{
GwCircleListForChoose.deleteByGwid(id);
return;
}
void GwAlgorithm::ChangeGwWithBoolValue(int id, RELATE_PARE_CHANGE_T para_cat, bool& value)
{
GwListNode* node = NULL;
node = GwCircleListForChoose.findByGwid(id);
if(node != NULL)
{
switch(para_cat)
{
case RELATE_PARE_MARK://bool
node->gw.setMark(value, false);
break;
case RELATE_PARE_CALL_IS_OUT://bool
node->gw.setOut(value, false);
break;
case RELATE_PARE_CALL_BPUNISH://bool
node->gw.setPunish(value, false);
break;
default:
break;
}
}
return;
}
void GwAlgorithm::ChangeGwWithIntValue(int id, RELATE_PARE_CHANGE_T para_cat, int& value)
{
GwListNode* node = NULL;
node = GwCircleListForChoose.findByGwid(id);
if(node != NULL)
{
switch(para_cat)
{
case RELATE_PARE_CALL_COUNT://int
node->gw.setCallCount(value, false);
break;
case RELATE_PARE_MAX_CAPABILITY://int
node->gw.setMaxCapability(value, false);
break;
case RELATE_PARE_STATUS://int
node->gw.setStatus(value, false);
break;
case RELATE_PARE_GW_STATUS://int
node->gw.setGwStatus(value, false);
break;
case RELATE_PARA_GW_ISDN:
node->gw.setIsdn(value, false);
break;
default:
break;
}
}
return;
}
bool GwAlgorithm::GwPollAlgorithm(int callervpn, InterConnectionGatewayContext& gwinfo)
{
int minRate = 10000;
InterConnectionGatewayContext* minRateGwinfo = NULL;
InterConnectionGatewayContext* unpunishedPollGwinfo = NULL;
InterConnectionGatewayContext* punishedPollGwinfo = NULL;
if(GwCircleListForChoose.IsEmpty())
{
return false;
}
GwListNode * startpos = GwCircleListForChoose.getFlagPos();
bool bPollStop = false;
bool bStart = true;
GwListNode * node = startpos;
InterConnectionGatewayContext* currentgw = NULL;
if(startpos == NULL)
{
return NULL;
}
for(;bStart || node != startpos; node = node->next)//start from the
{
bStart = false;
if(node->gwid == -1)//head or end node
{
continue;
}
currentgw = &(node->gw);
if(DeviceManager_T::instance()->scc_check_gw_state(currentgw, callervpn) != BCC_SUCCESS)
{
continue;
}
//method 1: mini-rate prior, used for 2 types of gws
int rate = (10000*currentgw->getCallCount())/(currentgw->getMaxCapability());
if(rate < minRate)
{
minRate = rate;
minRateGwinfo = currentgw;
}
if(!bPollStop && (minRate < 10000 && minRate >= 0))
{
bPollStop = true;
}
//method 2:polling, used only for type capability unknown gw,
if(!bPollStop && !currentgw->isMark())//if found minrate usable, no need to polling
{
if(currentgw->isPunished() && (NULL == punishedPollGwinfo))
{
punishedPollGwinfo = currentgw; //find the first unnull punished gw
}
else if((!currentgw->isPunished()))
{
unpunishedPollGwinfo = currentgw;//find the first unnull unpushied gw
bPollStop = true;
}
}
if(bPollStop) //start from the next pos
{
GwCircleListForChoose.setFlagPos(node->next);
}
}
//1st priority
if(minRate < 10000 && minRate >= 0)
{
gwinfo = *minRateGwinfo;
return true;
}
//2nd priority
else if(NULL != unpunishedPollGwinfo)
{
gwinfo = *unpunishedPollGwinfo;
return true;
}
//3rd priority
else if(NULL != punishedPollGwinfo)
{
gwinfo = *punishedPollGwinfo;
return true;
}
return false;
}