* 新增差异化流程节点:在程序内部执行流程进行可配置化, 提供一套公用的类,满足相关的流程配置化实现的需求。
电信计费模型中 流程配置化节点驱动,按照system_type为基本元素进行流程配置驱动。
#需要配置流程组的业务话单类型,0 在线话单 1 离线FEDX 2 离线FIX,按照 , 分隔
[system]
task_type_comp=0;1;2 # 0 在线话单 1 离线FEDX 2 离线FIX,按照 , 分隔
#流程组节点
[proc]
v_offline =cAcomp;B;C;D
g_offline =A;B;C;D
s_offline =A;B;C;D
v_obtain = cAcomp;B;C;D
g_offline =cAcomp;B;C;D
v_online = cAcomp;B;C;D
#离线文件的流程配置化的组,按照 system_type 进行配置驱动耦合度低一些
[task_type_1]
vc = v_offline
vf = v_offline
gg = g_offline
ss = s_offline
si = s_offline
#在线文件的流程配置化的组
[task_type_0]
vc = v_online
#离线FIX文件的流程配置化的组
[task_type_2]
vc = v_online
具体的相关实现方案:
procAuto.h
/*<! Application own data define begin 2013.07.19 */
#define PROC_Y_FLAG 'Y'
#define PROC_SPLIT_CHAR ';'
#define MAX_PROCGROUP_NUM 20 /*<! 组的最大个数*/
#define MAX_PROCGROUP_NAME_LNE 64 /*<! 流程名的最大长度*/
#define MAX_PROCTASKTYPE_MAX 5 /*<! 根据task_type定义的一个阀值,task_type 从0 开始不能大于此值*/
#define PROC_NODE_TYPE_C 0 /*<! 可选的配置节点*/
#define PROC_NODE_TYPE_M 1 /*<! 必选的配置节点*/
/*<! 流程节点分组的定义 ,最大值不能超过 MAX_PROCGROUP_NUM,同时不能有重复的定义 */
#define PROCGROUP_CDRDEAL_NORMAL 0 /*<! cdr处理的相关的流程调用*/
#define PROCGROUP_TASKDEAL_NORMAL 1 /*<! ctask处理的相关的流程调用*/
#define PROCGROUP_ONHANDLEEND_NORMAL 2 /*<! 在onHandle结尾部分需要做的工作流程节点*/
/*
** 流程节点的入参类,对于融合计费子系统中最重要的两个入参,贯穿整个系统流程处理始终的类
*/
class cProcParam
{
public:
cProcParam();
~cProcParam();
cProcParam & operator=(cProcParam &);
void print();
void init();
//检查这个参数的信息
int checkParamTask();
int checkParamCdr();
public:
CDR * pCDR;
cTask * pTask;
char flag;
};
/*
** 流程节点类节点,基类,其中其他的个性的流程类节点需要继承此类节点
*/
class cProcedure
{
public:
cProcedure();
~cProcedure();
cProcedure & operator=(cProcedure &);
void print();
//检查这个流程节点的分组以及类定义是否合法
int check();
public:
int groupNo; //分组组号,构造函数中就需要指定其群组编号
int type; //节点类型,必须的流程节点 和 可选流程节点
char desc[128+1];//描述
public:
//初始化,对其分组、类型、描述进行分别的初始化,纯虚函数,子类必须继承实现
virtual void init()=0;
//具体执行调用
virtual int exec(cProcParam * pParam)=0;
};
/*
** 流程节点类封装
*/
class cProcedureNode
{
public:
cProcedureNode();
~cProcedureNode();
cProcedureNode & operator=(cProcedureNode &);
void print();
public:
cProcedure * pProc;
char flag;
};
/*
** 流程节点类组合容器,使用vector3 数据信息
*/
class cProcedureGroup
{
public:
cProcedureGroup();
~cProcedureGroup();
cProcedureGroup & operator=(cProcedureGroup &);
void print();
void clear();
public:
//存储流程节点的容器
vector3<cProcedureNode> pProcVec;
char flag;
};
/*
** 流程节点类组合与组合之间的一个形成一套流程节点
*/
class cProcGroupComp
{
public:
cProcGroupComp();
~cProcGroupComp();
cProcGroupComp & operator=(cProcGroupComp &);
void print();
void clear();
public:
//流程组
cProcedureGroup groupProc[MAX_PROCGROUP_NUM+1];
//流程组别名
char procGroupName[MAX_PROCGROUP_NAME_LNE+1];
//是否有效的标志
char flag;
public:
//流程组驱动器,进行获取其中的流程组,过程调度实现中的一个核心函数,需要支持多线程对vector3 遍历访问
int ProcDrive(cProcParam * pParam,int groupNo);
};
/*
** 一套流程节点,不同task_type 组合的 新的封装节点
*/
class cProcVector
{
public:
cProcVector();
~cProcVector();
cProcVector & operator=(cProcVector &);
void print();
void clear();
public:
cProcGroupComp procComp[MAX_PROCTASKTYPE_MAX+1];
};
/*
** 流程节点类管理的一个总体的封装其中的函数和类都作为static,作为类的全局变量
*/
class cProcManager
{
public:
static void print();
static void printProcGroupComp();
public:
/*<! 存储注册的流程的节点信息的二叉树*/
static avlTree<string,cProcedure *> procRegister;
/*<! 全局的cProcGroupComp 容器中 */
static vector3<cProcGroupComp> procGroupVec;
/*<! 存储临时一组的节点的容器*/
static vector3<cProcedureNode> tmpProc;
public:
/*<! 初始化*/
void init();
/*<! 流程名称和类名,进行注册的动作,如果没有在这里面注册则认为是无效的,流程节点*/
static int ProcedureRegister(string name,cProcedure * pProc);
/*<! 流程名称和类名,是否被注册*/
static cProcedure ** FindProc(string name);
/*<! 流程组名称是否在 procGroupVec 找得到*/
static cProcGroupComp * FindProcGroupComp(char * name);
/*<! 将流程节点按照分隔符来生成其中的流程节点容器*/
static int SetProc(string procflow,string compname);
/*<! 把流程节点中的某一个明细的节点*/
static int SetProcDetail(char * name);
};
/*<! 注册类的宏定义,需要将其中的函数都注册到全局对象中去*/
#define PROCEDURE_REGISTER(procname) int procname##Temp = cProcManager::ProcedureRegister(#procname,new procname());
/*<! 公共函数 begin*/
int iRegister_All_Procudures();
int initSysProcedure(cProcVector (*)[75][75],struct connectDSC *);//初始导航流程节点内存的数据:
int clearSysProcedure(cProcVector (*gOperSysProc_tmp)[75][75],struct connectDSC *pp);//清空导航流程节点内存的数据:
void printSysProcedure(cProcVector (*gOperSysProc_tmp)[75][75]);//打印导航流程节点内存的数据:
cProcGroupComp * getSysProcHandle(char* strSysType,int taskType);
/*<! 公共函数 end*/
procAuto.cpp
//cProcParam begin
//构造函数
cProcParam::cProcParam()
{
pCDR=NULL;
pTask=NULL;
flag='0';
}
void cProcParam::init()
{
pCDR=NULL;
pTask=NULL;
flag='0';
}
int cProcParam::checkParamCdr()
{
if(pCDR == NULL || flag != PROC_Y_FLAG)
return -1;
else
return 0;
}
int cProcParam::checkParamTask()
{
if(pTask == NULL || flag != PROC_Y_FLAG)
return -1;
else
return 0;
}
void cProcParam::print()
{
}
// 析构函数
cProcParam::~cProcParam()
{
}
//等号操作符重载
cProcParam & cProcParam::operator=(cProcParam & other)
{
if(this == &other) return *this;
pCDR = other.pCDR;
pTask = other.pTask;
flag = other.flag;
return * this;
}
// cProcParam end
//cProcedure begin
//构造函数
cProcedure::cProcedure()
{
groupNo=-1;
type=-1;
memset(desc,0,sizeof(desc));
}
int cProcedure::check()
{
if(groupNo <0 || groupNo > MAX_PROCGROUP_NUM)
{
printf("[%s][%d] proc groupNo[%d] out of range [%d,%d]\n",__FILE__,__LINE__,groupNo,0,MAX_PROCGROUP_NUM);
return -1;
}
if(type != PROC_NODE_TYPE_C && type != PROC_NODE_TYPE_M)
{
printf("[%s][%d] proc type invalid ...\n",__FILE__,__LINE__);
return -1;
}
return 0;
}
void cProcedure::print()
{
printf("cProcedure Info:--|groupNo:[%d],type:[%d],desc[:%s]\n",groupNo,type,desc);
}
// 析构函数
cProcedure::~cProcedure()
{
}
//等号操作符重载
cProcedure & cProcedure::operator=(cProcedure & other)
{
if(this == &other) return *this;
groupNo = other.groupNo;
type = other.type;
strcpy(desc, other.desc);
return * this;
}
// cProcedure end
//cProcedureNode begin
//构造函数
cProcedureNode::cProcedureNode()
{
pProc=NULL;
flag='0';
}
void cProcedureNode::print()
{
if(pProc!=NULL)
{
pProc->print();
}
else
{
printf("Cur cProcedureNode is null, error...\n");
}
}
// 析构函数
cProcedureNode::~cProcedureNode()
{
}
//等号操作符重载
cProcedureNode & cProcedureNode::operator=(cProcedureNode & other)
{
if(this == &other) return *this;
pProc = other.pProc;
flag = other.flag;
return * this;
}
// cProcedureNode end
//cProcedureGroup begin
//构造函数
cProcedureGroup::cProcedureGroup()
{
pProcVec.clear();
flag='0';
}
void cProcedureGroup::clear()
{
pProcVec.clear();
}
void cProcedureGroup::print()
{
cProcedureNode * node=NULL;
for(node=pProcVec.begin();node!=NULL;node=pProcVec.next())//遍历数据
{
node->print();
}
}
// 析构函数
cProcedureGroup::~cProcedureGroup()
{
}
//等号操作符重载
cProcedureGroup & cProcedureGroup::operator=(cProcedureGroup & other)
{
if(this == &other) return *this;
pProcVec = other.pProcVec;
flag = other.flag;
return * this;
}
// cProcedureGroup end
//cProcGroupComp begin
//构造函数
cProcGroupComp::cProcGroupComp()
{
memset(procGroupName,0,sizeof(procGroupName));
flag='0';
for(int i = 0;i<MAX_PROCGROUP_NUM+1;i++)
{
groupProc[i].clear();
}
}
void cProcGroupComp::clear()
{
memset(procGroupName,0,sizeof(procGroupName));
flag='0';
for(int i = 0;i<MAX_PROCGROUP_NUM+1;i++)
{
groupProc[i].clear();
}
}
void cProcGroupComp::print()
{
printf("cProcedure Info:--|groupProcCompName [%s] flag[%c] ...\n",procGroupName,flag);
for(int i = 0;i<MAX_PROCGROUP_NUM+1;i++)
{
groupProc[i].print();
}
}
//流程组驱动器,进行获取其中的流程组,过程调度实现中的一个核心函数
int cProcGroupComp::ProcDrive(cProcParam * pParam,int groupNo)
{
if(groupNo <0 || groupNo > MAX_PROCGROUP_NUM)
return -1;
int iRet= 0;
cProcedureGroup * pGroup=&(groupProc[groupNo]);
cProcedureNode * pTmp = NULL;
struct vector3<cProcedureNode>::typeLinkNode *tmpTLinKNode;
//使用如下模式,此函数支持多线程模式的容器访问
for(pTmp=pGroup->pProcVec.begin(&tmpTLinKNode);pTmp!=NULL;pTmp=pGroup->pProcVec.next(&tmpTLinKNode))
{
#ifdef DEBUG
pTmp->pProc->print();
#endif
//其中某一个流程节点执行错误,则整体错误
if(iRet = pTmp->pProc->exec(pParam))
{
return iRet;
}
}
return 0;
}
// 析构函数
cProcGroupComp::~cProcGroupComp()
{
}
//等号操作符重载
cProcGroupComp & cProcGroupComp::operator=(cProcGroupComp & other)
{
if(this == &other) return *this;
strcpy(procGroupName,other.procGroupName);
flag=other.flag;
for(int i = 0;i<MAX_PROCGROUP_NUM+1;i++)
{
groupProc[i]=other.groupProc[i];
}
return * this;
}
// cProcGroupComp end
//cProcVector begin
//构造函数
cProcVector::cProcVector()
{
for(int i = 0;i<MAX_PROCTASKTYPE_MAX+1;i++)
{
procComp[i].clear();
}
}
void cProcVector::clear()
{
for(int i = 0;i<MAX_PROCTASKTYPE_MAX+1;i++)
{
procComp[i].clear();
}
}
void cProcVector::print()
{
for(int i = 0;i<MAX_PROCTASKTYPE_MAX+1;i++)
{
procComp[i].print();
}
}
// 析构函数
cProcVector::~cProcVector()
{
}
//等号操作符重载
cProcVector & cProcVector::operator=(cProcVector & other)
{
if(this == &other) return *this;
for(int i = 0;i<MAX_PROCTASKTYPE_MAX+1;i++)
{
procComp[i]=other.procComp[i];
}
return * this;
}
// cProcVector end
//cProcManager begin
/*<! 存储注册的流程的节点信息的二叉树,static 成员变量的实际定义*/
avlTree<string,cProcedure *> cProcManager::procRegister;
vector3<cProcGroupComp> cProcManager::procGroupVec;
/*<! 存储临时一组的节点的容器*/
vector3<cProcedureNode> cProcManager::tmpProc;
void cProcManager::print()
{
/*<! 存储注册的流程的节点信息的二叉树*/
printf("***************cProcManager print begin [%s][%d]*********\n",__FILE__,__LINE__);
printf("***************cProcManager procRegister info below: *********\n",__FILE__,__LINE__);
binTreeNode<string,cProcedure*> * prcod;
for(prcod=procRegister.begin();prcod != NULL;prcod=procRegister.next())
{
(prcod->_t)->print();
}
printf("***************cProcManager print end [%s][%d]*********\n",__FILE__,__LINE__);
}
void cProcManager::printProcGroupComp()
{
printf("***************cProcManager print begin [%s][%d]*********\n",__FILE__,__LINE__);
/*<! 全局的cProcGroupComp 容器中 */
printf("***************cProcManager procGroupVec info below: *********\n",__FILE__,__LINE__);
cProcGroupComp * node=NULL;
for(node=procGroupVec.begin();node!=NULL;node=procGroupVec.next())//遍历数据
{
node->print();
}
printf("***************cProcManager print end [%s][%d]*********\n",__FILE__,__LINE__);
}
void cProcManager::init()
{
procGroupVec.clear();
procGroupVec.clear();
tmpProc.clear();
}
/*<! 流程名称和类名,进行注册的动作,如果没有在这里面注册则认为是无效的,流程节点*/
int cProcManager::ProcedureRegister(string name,cProcedure * pProc)
{
if(pProc==NULL)
{
gProcRegisterFlag = 1; //流程节点注册出现错误
return -1;
}
else
{
//先执行初始化函数
pProc->init();
//检查初始化的函数是否正确
if(pProc->check())
{
gProcRegisterFlag = 2; //流程节点注册出现错误
return -1;
}
else
procRegister.insert(name,pProc);
}
return 0;
}
/*<! 流程名称和类名,是否被注册,返回0 已经被注册,非0 没有被注册*/
cProcedure ** cProcManager::FindProc(string name)
{
cProcedure ** pd = NULL;
if((pd = procRegister.search(name)) == NULL)
{
return NULL;
}
return pd;
}
/*<! 流程组名称是否在 procGroupVec 找得到*/
cProcGroupComp * cProcManager::FindProcGroupComp(char * name)
{
if(name == NULL)
return NULL;
cProcGroupComp * pTmp = NULL;
cProcGroupComp * pTar = NULL;
struct vector3<cProcGroupComp>::typeLinkNode *tmpTLinKNode;
for(pTmp=procGroupVec.begin(&tmpTLinKNode);pTmp!=NULL;pTmp=procGroupVec.next(&tmpTLinKNode))
{
//如果找到其中的节点为初始化完成,同时其中的流程组名称 能匹配上,则找到退出。
if(pTmp->flag == PROC_Y_FLAG && strcmp(pTmp->procGroupName,name) == 0)
{
pTar = pTmp;
break;
}
}
return pTar;
}
/*<! 将流程节点按照分隔符来生成其中的流程节点容器
procflow APROC;BPROC;CPROC 按照分隔符 PROC_SPLIT_CHAR 进行填充
*/
int cProcManager::SetProc(string procflow,string compname)
{
/*<! 存储临时一组的节点的容器*/
tmpProc.clear();
/*<! 按照分隔符来处理流程串组*/
int ProcNum = 0;
char strProcFlow[1024+1];
memset(strProcFlow,0,sizeof(strProcFlow));
strcpy(strProcFlow,procflow.c_str());
ProcNum = charpos_num(strProcFlow,PROC_SPLIT_CHAR);
if (ProcNum < 0)
{
printf("[%s][%d] ProcNum not allow <=0 ...\n",__FILE__,__LINE__);
return -1;
}
int i =0;
char tmpProcName[50+1];
int iDetailflag=0;
for (i=0;i<ProcNum+1;i++)
{
memset(tmpProcName,0,sizeof(tmpProcName));
getTextField(tmpProcName,strProcFlow,PROC_SPLIT_CHAR,i+1);
iDetailflag = SetProcDetail(tmpProcName);
if(iDetailflag)
{
printf("[%s][%d] PROCEDURE_SET_DETAIL [%s] fail ...\n",__FILE__,__LINE__,tmpProcName);
return -1;
}
}
cProcGroupComp tmpGroupComp;
tmpGroupComp.clear();
strcpy(tmpGroupComp.procGroupName,compname.c_str());
cProcedureNode * node;
int groupNo=0;
//流程配置组节点中至少要有一个 PROCGROUP_ONHANDLEEND_NORMAL 的节点
int checkOHBdealFlag=0;
for(node=tmpProc.begin();node!=NULL;node=tmpProc.next())//遍历数据
{
groupNo=node->pProc->groupNo;
if(groupNo <0 || groupNo > MAX_PROCGROUP_NUM)
return -1;
//检查配置组的内容
if(PROCGROUP_ONHANDLEEND_NORMAL ==groupNo)
{
checkOHBdealFlag=1;
}
tmpGroupComp.groupProc[groupNo].pProcVec.insert(*node);
}
if(checkOHBdealFlag == 0)
{
printf("[%s][%d] at least contain one PROCGROUP_ONHANDLEEND_NORMAL procedure comp [%s] ...\n",__FILE__,__LINE__,tmpGroupComp.procGroupName);
return -1;
}
//把数据插入到 全局的cProcGroupComp 容器 procGroupVec 中
tmpGroupComp.flag = PROC_Y_FLAG;
procGroupVec.insert(tmpGroupComp);
return 0;
}
/*<! 把流程节点中的某一个明细的节点*/
int cProcManager::SetProcDetail(char * name)
{
if(name == NULL)
{
printf("[%s][%d] name not allow null ...\n",__FILE__,__LINE__);
return -1;
}
cProcedure ** pd = NULL;
if((pd = FindProc(string(name))) == NULL)
{
printf("[%s][%d] pProc [%s] not been Registered ...\n",__FILE__,__LINE__,name);
return -1;
}
cProcedureNode node;
node.flag = PROC_Y_FLAG;
if((*pd) != NULL)
node.pProc = (*pd);
else
{
printf("[%s][%d] pProc not allow null ...\n",__FILE__,__LINE__);
return -1;
}
tmpProc.insert(node);
return 0;
}
//初始导航流程节点内存的数据:
int initSysProcedure(cProcVector (*gOperSysProc_tmp)[75][75],struct connectDSC *pp)
{
stOperationProcConfig tmpProcConfig;
memset(&tmpProcConfig,0,sizeof(stOperationProcConfig));
//内存sys_proc=2 重新初始化需要清空原有的内存区内容
cProcManager::procGroupVec.clear();
cProcManager::tmpProc.clear();
if(busi_cfgfile_read_proc(&tmpProcConfig))
{
writeRunlog( 1, "FILE=[%s]LINE=[%d]:busi_cfgfile_read_proc wrong!\n",__FILE__,__LINE__);
return -1;
}
int id1=0, id2=0;
DSC_ROW v_row ;
int i = 0;
char tmpCompName[INIFILE_NAME_MAX_LEN+1];
memset(tmpCompName,0,sizeof(tmpCompName));
cProcVector tmpProcVec;
cProcGroupComp * tmpProcComp=NULL;
tmpProcVec.clear();
//把导航中的信息信息进行初始化
for(id1=0;id1<75;id1++)
{
for(id2=0;id2<75;id2++)
{
(*gOperSysProc_tmp)[id1][id2].clear();
}
}
if(DSC_query_p(pp->v_client, &((pp->dciTable).getOptNavigation)))
{
writeRunlog( 4, "FILE=[%s]LINE=[%d]:DSC_query wrong!\n",__FILE__,__LINE__);
return -1;
}
while(v_row = DSC_fetch_row(pp->v_client))
{
id1 = v_row[0][0] - '0';
id2 = v_row[0][1] - '0';
if(id1<0 || id2 < 0)
continue;
if(id1>74 || id2 >74)
continue;
tmpProcVec.clear();
for(i=0;i<MAX_PROCTASKTYPE_CONFIG+1;i++)
{
if(tmpProcConfig.taskTypeProc[i].flag == PROCTASKTYPE_YFLAG)
{
if(tmpProcConfig.AllSysProc[id1][id2].ProcConfig[i].flag == PROCTASKTYPE_YFLAG)
{
strcpy(tmpCompName,tmpProcConfig.AllSysProc[id1][id2].ProcConfig[i].procCompName);
if((tmpProcComp = cProcManager::FindProcGroupComp(tmpCompName)) != NULL)
{
//拷贝内容
tmpProcVec.procComp[i] = (*tmpProcComp);
}
else
{
writeRunlog( 4, "FILE=[%s]LINE=[%d]:FindProcGroupComp [%s] systemType[%s] failed!\n",__FILE__,__LINE__,tmpCompName,v_row[0]);
return -1;
}
}
}
}
//赋值拷贝内容
(*gOperSysProc_tmp)[id1][id2]=tmpProcVec;
}
return 0;
}
//清空导航流程节点内存的数据:
int clearSysProcedure(cProcVector (*gOperSysProc_tmp)[75][75],struct connectDSC *pp)
{
int id1=0, id2=0;
//把导航中的信息信息进行初始化
for(id1=0;id1<75;id1++)
{
for(id2=0;id2<75;id2++)
{
(*gOperSysProc_tmp)[id1][id2].clear();
}
}
return 0;
}
//打印导航流程节点内存的数据:
void printSysProcedure(cProcVector (*gOperSysProc_tmp)[75][75])
{
int id1=0, id2=0;
//把导航中的信息信息进行初始化
for(id1=0;id1<75;id1++)
{
for(id2=0;id2<75;id2++)
{
(*gOperSysProc_tmp)[id1][id2].clear();
}
}
}
//根据systemType和taskType 获取其对应的流程节点组的指针信息
cProcGroupComp * getSysProcHandle(char* strSysType,int taskType)
{
int iIdx1 = strSysType[0] - '0';
int iIdx2 = strSysType[1] - '0';
if(iIdx1<0 || iIdx2 < 0)
return NULL;
if(iIdx1>74 || iIdx2 >74)
return NULL;
if(taskType<0 || taskType > MAX_PROCTASKTYPE_MAX)
return NULL;
if((*gOperSysProc)[iIdx1][iIdx2].procComp[taskType].flag == PROC_Y_FLAG)
return (&((*gOperSysProc)[iIdx1][iIdx2].procComp[taskType]));
else
return NULL;
}
// cProcManager end