[转帖]Tuxedo缓冲区的封装代码,成就你打造通用的tuxedo客户端_MQ, Tuxedo及OLTP讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MQ, Tuxedo及OLTP讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 4161 | 回复: 0   主题: [转帖]Tuxedo缓冲区的封装代码,成就你打造通用的tuxedo客户端        下一篇 
ying
注册用户
等级:上尉
经验:694
发帖:59
精华:0
注册:2012-10-12
状态:离线
发送短消息息给ying 加好友    发送短消息息给ying 发消息
发表于: IP:您无权察看 2012-11-7 15:04:38 | [全部帖] [楼主帖] 楼主

大家好,我是Michael Guo,或者虫哥,这是我的笔名:邮箱:gwlii@163.com[/email],下面我讲述一下怎么去封装一个通用的 tuxedo客户端 转载本篇文章,请注明作者:Michael

Guo,并且标明:本文章来自于www.tuxdev.cn 我们知道tuxedo有4种类型的缓冲区,下面我将演示如何封装这4种类型的缓冲区

并封装好了之后,发送给tuxedo,然后获得返回数据,并进行解析,输出 整个过程,完整的封装了tuxedo。并且封装成为一个通用的tuxedo客户端。

一:,我们来分析一下输入的配置文件格式如下:

servicename@wsnaddr@typebuffer[/email]@数据成员名称:inout@数据成员类型@数据成员名称:inout@类型..(目前支持int,double,float,char,long)

对于fml类型的缓冲区需要提供FLDTBLDIR32=路径和FIELDTBLS32=值, 例如:

string类型:[url=]SWAP@//192.168.9.33:21550@string@send:in:char[1024]@recv:out:char[10[/url] 24]表示SWAP服务在那个主机上,服务端接收缓冲区类型为STRING,入参数据成员名称:send,ch

ar[1024]长度,出参数据成员的名称:recv,char[1034]

view32类型:INSERTVIEW@//192.168.9.33:21552@view32@rid:inout:int@rname:inout:lon [email=g@rsal:inout:char[8]g@rsal:inout:char[8[/email]]

表示INSERTVIEW这个服务在主机上,服务端接收VIEW32缓冲区,入参的数据成员名称分别是 :rid,rname,rsal  数据成员的类型分别是:int类型,long,和char类型,也就是struct有3个成员

fml32类型:[url=]INSERTFML@//192.168.9.33:21552@fml32:FLDTBLDIR32=/home/guowl/fml:FIELDTBLS32=regions@id:inout:long@name:inout:char[8]@sal:inout:char[8[/url]]

表示INSERTFML这个服务在主机上,服务端接收FML32缓冲区,域表头文件的目录在/home/guowl/fml,域表头文件名称regions 数据成员名称分别是:id,name,sal,类型分别是:long,char[8],char[8] 然后将这个服务定义文件,读入到一个char

*的指针里面,

char * GetServiceDef()//获取服务配置文件

{

    char sTmp[255]="";

    static char sBuffer[8192]="";

    strcpy(sTmp,"/home/guowl/service.def");//服务配置文件的路径 FILE *fp;

    fp=fopen(sTmp,"r");

    if(fp==NULL) {

    printf(" cannot open 配置文件 file%s\n",tmp);

    return -1;

    }

    memset( sBuffer,0,sizeof(sBuffer));//读取到sBuffer

    fread(sBuffer,255,100,fp); return sBuffer;//返回sBuffer;

}

二.我们来介绍一下对外的统一接口函数:

//4个入参,服务名,请求的入参数据,状态,和data,这个data指针是/home/guowl/servi ce.def里面的内容//g_OutputData,g_InputData,g_sname,tuxlog均为全局的char一维数组

char * InterFace( char *ServiceName, char *InputData,int *ServiceStatus, char *data )

{

memset(g_OutputData,0,BUFFLEN*sizeof(char));//全局一维数据初始化 memset(g_InputData,0,BUFFLEN*sizeof(char));

//由于入参是指针,极其容易发生变化,所以先把请求的入参数据和请求的服务名称复制到

    g_InputData和g_sname

 memcpy(g_InputData,InputData,strlen(InputData)); g_InputData[strlen(g_InputData)]=0;

memset(g_sname,0,sizeof(g_sname));//先初始化,再复制,因为是全局变量

memcpy(g_sname,ServiceName,strlen(ServiceName));

sname[strlen(sname)]=0;

memset(tuxlog,0,sizeof(tuxlog));//日志数组的初始化,tuxlog表示日志的一维数组

if(strlen(g_InputData)==0) {//判断请求的入参数据是否为空

    *ServiceStatus=-3;

    return (char*)NULL;

} //gx是一个全局的对象,他是TuxPost类型的一个对象,后面会介绍每个类的声明以及类的?  饔?

/* gtux.m,m是TuxPost类里面的string对象,用来存储日志信息,Buffer是TuxPost类里面?  墓潭?

长度的一纬char数组。。用来存储每一次请求,tuxedo的返回结果,这两个都需要初始化 */

gtux.m.clear();

memset(gtux.Buffer,0,sizeof(gtux.Buffer));

//*ServiceStatus= 1;//表示请求状态,默认为-1,表示失败

//g_out1也是全局的二维char数组,用来分割使用,配合splitStr函数使用。

//splitStr函数返回指针data里面,使用"\n"为分隔符,能把data分割 每一份,从前往后,可以用g_out1[1],g_out1[2]....

//下面讲公用函数的时候,会介绍的

memset(g_out1,0,sizeof(g_out1));

intiNum=splitStr(data,"\n",g_out1);

//Stype是TuxPost类型里面表示类型,也就是缓冲区类型,STRING/VIEW32/FML32,注意全 部都是大写,他也需要初始化

memset(gtux.Stype,0,sizeof(gtux.Stype));

//RedoSvc是TuxPost类型里面的一个成员函数,会查询本次请求以前有没有请求过同样的 服务

//如果请求过,则会优化一些细节,减少系统的消耗,也就是一个容器而已

gtux.RedoSvc(g_sname);

string RedoServiceName;

string Redoinput;

RedoServiceName.assign(sname); //获取redo servicename..。

Redoinput.assign(g_InputData);

//获取本次请求的redo  请求入参

if(Redoflag!=1) {//Redoflag也是全局变量,=1表示以前请求过,!=1表示以前没请求过

    for(int i=0;i<iNum;++i) {

    if(strcmp(g_out1[i],"")!=0) {

    memset(sout,0,sizeof(sout));

    memcpy(sout,g_out1[i],sizeof(g_out1[i]));

    sout[strlen(g_out1[i])]=0;

    //上面的for循环是针对配置文件service.def的每一行数据,也就是g_out[i],判断是否 为空。。

    if(gtux.VeiwInit(sout,g_sname)==0) {

    break;

    //针对每一行的数据做一些初始化和成员的识别,包括gtux.Stype和gtux.wsnaddr等等

    }

    }

    }

}

if(strcmp(gtux.Stype,"")==0) {//判断是否识别到了本次请求的缓冲区的类型信息 *ServiceStatus=-2;

    memcpy(tuxlog,gtux.m.c_str(),gtux.m.size());

    //如果没有识别到。。。那么输出日志 的错误信息,并且返回

    return (char*)NULL;

}

if(strncmp(gtux.Stype,"FML",3)==0) {//如果是FML类型,

    if(gtux.FmlDest()==-1) { //分配接收缓冲区,发送缓冲区以及初始化连接tuxedo等等。

    *ServiceStatus=gtux.m_status;

    memcpy(tuxlog,gtux.m.c_str(),gtux.m.size());//如果上述操作失败了,返回日志错误 信息

    return NULL;

    }

    if(gtux.CallAnaly(g_InputData,sname)==-1) {//分析本次的请求入参数据,根据入参数据,进行缓冲区的数据填充也就是缓冲?鳩ML成员的数据填充

    *ServiceStatus=gtux.m_status;

    memcpy(tuxlog,gtux.m.c_str(),gtux.m.size());//填充失败..

    return NULL;

    }

    if(gtux.FInvoke(sname)==-1) {//呼叫TUXEDO的服务..。

    *ServiceStatus=gtux.m_status;

    memcpy(tuxlog,gtux.m.c_str(),gtux.m.size());

    return NULL;//失败了。。

    }

    gtux.DelMem();//做一些清理工作。。。

}

if(strncmp(gtux.Stype,"VIEW",4)==0) {//VIEW32缓冲区

    if(gtux.ViewDest()==-1) {//分配VIEW32缓冲区,初始化连接tuxedo等等

    *ServiceStatus=gtux.m_status; memcpy(tuxlog,gtux.m.c_str(),gtux.m.size()); return NULL;

    }

    if(gtux.CallAnaly(g_InputData,sname)==-1) {//分析本次请求的入参数据,之后进行发送缓冲区数据的填充

    *ServiceStatus=gtux.m_status; memcpy(tuxlog,gtux.m.c_str(),gtux.m.size()); return NULL;

    }

    if(gtux.VInvoke(sname)==-1) {//呼叫view32的tuxedo服务

    *ServiceStatus=gtux.m_status;

    memcpy(tuxlog,gtux.m.c_str(),gtux.m.size()); return NULL;

    }

    gtux.DelMem();//做清理工作

}

if(strncmp(gtux.Stype,"STRING",6)==0 ) {//STRING缓冲区的处理方式.

    if(gtux.StringDest()==-1) {

    *ServiceStatus=gtux.m_status; memcpy(tuxlog,gtux.m.c_str(),gtux.m.size()); return NULL;

    }

    if(gtux.CallAnaly(g_InputData,sname)==-1) {

    *ServiceStatus=gtux.m_status; memcpy(tuxlog,gtux.m.c_str(),gtux.m.size());

    return NULL;

    }

    if(gtux.SInvoke(sname)==-1) {

    *ServiceStatus=gtux.m_status; memcpy(tuxlog,gtux.m.c_str(),gtux.m.size());

    return NULL;

    }

    gtux.DelMem();

}

//上面每种缓冲区的处理流程完成了之后,就开始把gtux.Buffer里面的数据,返回?  鋈?,环游中间产生的日志信息等等.

if(strcmp(gtux.Buffer,"")!=0) {

    memset(g_OutputData,0,BUFFLEN*sizeof(char));

    memcpy(g_OutputData,gtux.Buffer,strlen(gtux.Buffer));

}

memcpy(tuxlog,gtux.m.c_str(),gtux.m.size());

*ServiceStatus=gtux.m_status; return g_OutputData;

}

    三.介绍公用的成员函数,以及涉及到的类和函数的声明:

#define  IN 0 //入参标志

#define  OUT 1  //出参标志

#define  INOUT 2 //即是出参,又是入参标志

#define  BUFFLEN  20480

extern  char g_out1[255][255];

extern  char  g_out2[255][255];

extern  char  g_FLDTBLDIR32[255];

extern  char g_FIELDTBLS32[255];

extern char  g_WSNADDR[255];

extern char  sname[255];

extern char  sout[255];

extern  char  g_OutputData[BUFFLEN];

extern  char g_InputData[BUFFLEN];

extern int Redoflag;

extern TPINIT* tpinitbuf; 上面都是全局变量的声明.

class TuxPost

{

private:

char m_CurWSNADDR[64];

bool m_bInConnection; //是否正处在连接之中

char FIELDTBLS32[255];//类里面的FML域表头文件目录

char FLDTBLDIR32[255];

char *v_RecBuff; //view32接收缓冲区

char * v_SendBuff; //view32发送缓冲区

char * f_RecBuff; //fml32接收缓冲区\

char * f_SendBuff;//fml32发送缓冲区

char * s_RecBuff;//string接收缓冲区

char * s_SendBuff; //string发送缓冲区 Veiw gview;//辅助类对象。。。

public:

char Buffer[BUFFLEN];//统一的,用于接收tuxedo返回的处理结果

char Stype[255];//缓冲区类型

bool TuxInit();

bool TuxTerm();

int StringSrc();//分配发送缓冲区

int StringDest(); //分配接收缓冲区函数

int VeiwInit(char*a,char

*sname);//初始化service.def里面的内容,查找到和本次请求入参一样的tuxedo服务记录?⑶易龀稍钡某跏蓟?

int SetVeiwBuffer();//填充VIEW32发送缓冲区

int CallAnaly(char *p,char *sname);//分析本次请求的入参数据,以方便每个缓冲区的填充

int ViewDest();

int ViewSrc();

int BufferViewSend();//填充VIEW32的发送缓冲区

int BufferFmlSend(char *data,char *value,const char *p);//填充fml缓冲区,来源数据是

view gv

int SetSendFml(char *data,char *value,int iNum);

int BufferStringSend();//填充STRING发送缓冲区

int BufferStringRec();

int BufferFmlRec();

int FmlDest();

int FmlSrc();

void DelMem();//清理现场的函

int VInvoke(char *sname);//view32的tpcall版本

int BufferViewRec();

//处理VINVOKE后,组织数据返回结果

int OutViewBuffer();//处理返回结果

int FInvoke(char *sname); //FML版本的tpcall

int SInvoke(char *sname);

//STRING版本的tpcall

int SetServType();

//设置本次请求的缓冲区类型

int Param(const char*); //判断是入参,出参的函数

map<string,Trie> themap; //这个MAP用于保留每次请求后的结果。。以方便下次请求的成员设置

int RedoCallAnaly(string,string);//分析本次请求是否已经请求过

int makeTrie(); //产生一个Trie的对象,用于存储themap

int RedoSvc(string s); //判断是否请求过

string RedoStr;

map<string,VeiwType>RedotheView; //如果请求过,这个容器是自动保存业务成员信息的容器

    int  CheckFmlTables();//加入了检查FML请求成员的合法性.




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论