BEA TUXEDO快速入门(50分)

N

netis

Unregistered / Unconfirmed
GUEST, unregistred user!
BEA TUXEDO快速入门

BEA TUXEDO Quick Start

简介 OVERVIEW AND INTRODUCTION 5
本节要点 6
TUXEDO是什么? 7
C/S系统的层次结构 8
C/S模式的演化 9
基本C/S模式 10
可管理多层C/S模式 11
TUXEDO的C/S方案 13
TUXEDO系统的特点 14
一个例子 16
开发TUXEDO C/S系统的必要步骤 23
小结 24
客户端开发 CLIENT DEVELOPMENT 25
本节要点 26
客户端在C/S模式中的作用 27
客户端开发过程 28
调试和错误处理 29
进程管理 31
数据缓冲管理 33
同步通讯 36
异步通讯I tpacall() 38
编译C语言客户端程序 40
小结 41
服务端开发 SERVER DEVELOPMENT 42
本节要点 43
服务的运行流程 44
返回控制 45
初始化和结束服务 47
创建服务 48
规划服务的考虑 49
动态发布 54
应用配置APPLICATION CONFIGURATION 56
本节要点 57
应用配置总览 58
配置文件 60
应用的信息 61
机器信息 64
组定义 65
服务定义 66
交易定义 68
生成TUXCONFIG文件 69
管理命令ADMINISTRATIVE COMMANDS 70
本节要点 71
命令tmboot 72
命令tmshutdown 73
管理工作和工具 74
缓冲数据类型 BUFFER TYPES 82
本节要点 83
简介和STRING 84
VIEW 85
FML 88
结合FML和VIEW 93
其他数据类型 94
数据依赖型路由 DATA DEPENDENT ROUTING 95
本节要点 96
简介 97
数据依赖型路由 98
使用DDR的ubbconfig的范例 99
网络 NETWORKING 100
简介 101
本节要点 102
多机配置 103
一个简单的UBBCONFIG范例 105
分布式事务处理DISTRIBUTED TRANSACTION PROCESSING 107
简介 108
本节要点 109
分布式事务处理和XA接口 110
分布式事务处理的UBBCONFIG 112
ATMI 事务API 114
管理类API ADMINAPI(MIB) 117
本节要点 118
简介 119
范例 121
其他Admin API域和错误处理 124
tpadmcall() 126
安全 SECURITY 128
简介 129
本节要点 130
概念 131
相关管理命令 132
ubbconfig 有关安全的部分 133
客户端代码范例 134
事件代理 EVENT BROKER 137
简介 138
本节要点 139
概念 140
Subscribing &
Unsubscribing ATMI 141
Ubbconfig相应改变 146
消息队列 QUEUED MESSAGE 147
本节要点 148
可靠队列 149
概念 150
基本队列 151
qmadmin范例 152
高级队列 154
事务和管道 157
ubbconfig的相应改变 159
客户端代码范例 160
会话 CONVERSATIONS 162
本节要点 163
简介 164
范例 166
广播通知UNSOLICITED NOTIFICATION 171
本节要点 172
简介 173
范例 174
工作站的客户端WORKSTATION CLIENT 177
简介 178
本节要点 179
概念 180
ubbconfig的相应变化 181
PC上的环境变量设置 183
域 do
MAINS 184
简介 185
本节要点 186
Domains 187
过程 188
小结 192

简介 Overview and Introduction

本节要点
* TUXEDO是什么?
* 客户端/服务器模式的演化
* 基本的客户端/服务器模式
* 多层结构
* TUXEDO的客户端/服务器方法
* 一个完整的例子
* 应用配置文件:ubbconfig
* 运行应用的步骤
TUXEDO是什么?
BEA TUXEDO是在企业、Internet 这样的分布式运算环境中开发和管理三层结构的客 户/服务器型关键任务应用系统的强有力工具。它具备分布式事务处理和应用通信功能,并提供完善的各种服务来建立、运行和管理关键任务应用系统。开发人员能够用它建立跨多个硬件平台、数据库和操作系统的可互操作的应用系统。BEA TUXEDO是企业、 Internet 分布式应用中的基础主干平台。它提供了一个开放的环境,支持各种各样的客 户、数据库、网络、遗留系统和通讯方式。
特点:
* 大量在线用户
* 巨量数据
* 信息访问
* 小事务
* 复杂网络

C/S系统的层次结构
以下列出了分布式系统的主要层次:
* 用户界面:被分成表示管理和表示逻辑。代表有主机框架的3270仿真终端;UNIX系统的X终端等,最新的Web浏览器界面也是。
* 商业逻辑:包含应用逻辑和应用规则。
* 数据管理:分为数据访问逻辑(SQL)和数据库管理。
区分C/S结构的类型可以根据以下特性:
客户端和服务端程序间逻辑分布,如何实现层次功能;中间件产品及技术的使用。

C/S模式的演化
上图列举了不同种类的C/S模式。其中大型主机系统仍然统治着最大的OLTP应用;基于X终端和UNIX工作站的应用在80年代后期兴起;廉价的WINTEL机器支持的Windows GUI通常用于2层模式;数据库新技术和OSF带领了3层应用模式。

基本C/S模式
C/S系统是一种分布式系统,由其程序决定其特点:
* 客户端部分执行前端功能,如:提供用户界面,向后台发出用户请求的交易,将结果返回给用户。
* 服务提供一般后端功能,按交易组织,将结果返回前端。
* 交易是分散的,按需求的操作,可以被远程客户端访问的程序。
C/S模式可能会有如下优点:
* 减小客户端程序体积,提高反应速度
* 位置无关
* 模块化
* 扩展性好

可管理多层C/S模式

在可管理多层(Managed Multi-Tier -MMT)C/S模式中,提出了中间件管理。在本书范围内,此点由交易处理(Transaction Processing -TP)管理完成,提供以下功能:
* 在客户端和服务端之间进行通讯和传输
* 提供良好的系统管理
* 提供交易、配置的分布式管理
它管理服务端从多个客户端收到的数据流,并不是在C/S间建立一对一的关系,而且客户端可以向多个服务发出请求。这种特点保证了TUXEDO可以提供强大的分布式交易处理框架。
由于不必进行通讯和交易管理,数据库引擎可以专注于其特长:管理数据!在这种情况下,数据库成了一个纯RM(Resource Manager)。

MMT C/S模式给OLTP应用增加了如下优点:
* 所有C/S模式的优点在MMT模式下都得到了增强。实际上,由于中间件的引入,处理能力得到改善。
* 由于中间件管理了数据流,带来了许多新功能,如:交易路由、服务分布、管道、数据依赖路由等成为可能。
* 统一的数据流控限制了最大交易数,总的数据库过程少了,服务器空闲时间也少了,这就增加了数据库和系统效率。
* 应用代码的设计可以不考虑物理地址和内部数据表示。
* 配置成了一件单纯的管理工作,进一步的,可以通过配置轻易的改变系统结构。服务可以动态的增加、删除和重启动。

TUXEDO的C/S方案
构成TUXEDO系统的各部分、工具和其特性组成的MMT C/S模式给应用带来的便利及TUXEDO的实现方法:
MMT C/S模式的优点
TUXEDO的实现技术
模块化
客户端,交易,服务
最大化的处理能力和流量
客户端交易流量控制,分布式配置,快速消息匹配和路由
通讯传输技术
ATMI访问,一种简单且容易定义的接口
实时应用管理
核心配置文件,MIB,管理工具和基于浏览器界面的GAI
名字服务和交易位置无关
公告牌提供目录交易便利
应用数据服务
应用服务位置可以在配置中随意配置

TUXEDO系统的特点
* TUXEDO /T
* 管理C/S数据流
* 支持3层结构
* 多平台支持
* 协同(BEA Connect, /TxRPC, /OSITP)
* 开发
* 通讯手段
* 同步
* 异步
* 会话
* 广播通知
* 管道
* 事件订阅
* 缓冲数据类型(自动编、解码)
* 事务
* 管理
* 核心配置管理
* 管理信息库(MIB)
* Web界面管理接口
* 负载平衡
* 网络配置
* 安全
* 数据依赖路由
* 数据压缩
* BEA JOLT 将TUXEDO中间件框架扩展到Internet和Java客户端
* TUXEDO /Q
* 通讯保障
* 预定处理
* TUXEDO /WS
* 多平台支持
* 把BEA TUXEDO ATMI API扩展到客户应用程序中
* TUXEDO /Domains
* TUXEDO /COBOL

一个例子
一个TUXEDO 应用可以分成3部分
* 发布交易请求的客户端
* 运行响应请求交易的服务
* 描述应用机器和服务信息的配置文件
上图是本例的示意图:
客户端请求交易“TOUPPER”,数据是“hello world”。交易“TOUPPER”将字符串转成大写,将结果成功返回客户端。

客户端范例
#include <stdio.h>
#include "atmi.h"
main()
{
char *buf;
long len;
if (tpinit((TPINIT * )NULL) == -1)
{
exit(1);
}
if ((buf=tpalloc("STRING",NULL,80))==NULL)
{
tpterm();
exit(2);
}
strcpy(buf, "hello world");
if ( tpalloc("TOUPPER",buf,0,&amp;buf,&amp;len,0)== -1)
{
fprintf(stderr,"service requst fail/n");
tpfree(buf);
tpterm();
exit(3);
}
printf("return string is :%s/n",buf);
tpfree(buf);
tpterm();
exit(0);
}
包含TUXEDO系统的头文件"atmi.h",以便引用TUXEDO的函数和变量定义。
客户端调用tpinit()连接应用
用tpalloc()分配一个STRING类型数据缓冲
将"hello world"拷贝进缓冲
用tpcall()包含数据缓冲,向交易“TOUPPER”发一个同步请求
打印出改变的数据缓冲
调用tpterm()切断与应用的连接

交易范例
#include <stdio.h>
#include <ctype.h>
#include "atmi.h"
void TOUPPER (TPSVCINFO *rqst)
{
int i;
for ( i=0;i<rqst->len-1;i++)
rqst->data = toupper(rqst->data);
tpreturn(TPSUCCESS,0,rqst->data,0L,0);
}
包含TUXEDO系统头文件"atmi.h"
象所有的TUXEDO交易函数一样,TOUPPER不用直接返回任何值,所以返回类型为void
从客户端收到的数据放在TPSVCINFO结构中,是唯一的入参
交易处理...
用tpreturn()将数据缓冲返回客户端

配置文件
有关应用的信息,如可用交易,交易位置,应用范围等,有必要集中管理于单一资源。事实上,这些信息被集中于文件UBBCONFIG。该文件分7节,主要部分内容描述如下:
*RESOURCES节包含全局信息,如:标识公告牌位置的唯一键值(IPCKEY),主控节点的名字(MASTER),应用类型(MODEL),下文例子中设为SHM表示是一个单节点应用。
*MACHINES节包含节点信息,如:机器物理名,TUXEDO系统位置(TUXDIR),服务码位置(APPDIR),以及本文件的二进制码文件名(TUXCONFIG)。
*GROUPS节包含一些管理用信息,如设定服务或交易的分布式事务处理。
*SERVERS节包含需要启动的交易和其组信息等其他信息。
*SERVICES节包含影响应用操作方式的的必要信息。本节列出的交易都是需要特别配置的,如有特别的优先级,装入参数,数据依赖路由等。
配置文件范例
#file : ubbconfig
*RESOURCES
IPCKEY 5000
MASTER SITE1
MODEL SHM
*MACHINES
gumby LMID=SITE1
TUXDIR ="/usr/tuxedo"
APPDIR ="/usr/apps/simpapp"
TUXCONFIG ="/usr/apps/simpapp/simpapp.tux"
*GROUPS
GROUP1 LMID=SITE1 GRPNO=1
*SERVERS
simpserv SRVGRP=GROUP1 SRVID=1
*SERVICES
TOUPPER

建立应用
建立一个TUXEDO应用,必须进行以下步骤:
* 设置环境变量。
TUXDIR表示TUXEDO用户目录;TUXCONFIG是二进制配置文件名;在路径中加入TUXEDO的可执行文件路径;如果用到公共库,还必须包含LD_LIBRARY_PATH,指出公共库位置。
TUXDIR=/usr/tuxedo
PATH=$PATH:$TUXDIR/bin
TUXCONFIG=/usr/apps/simpapp/simpapp.tux
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TUXDIR/lib
export LD_LIBRARY_PATH PATH TUXDIR
* 用buildclient命令从源程序编译出客户端可执行文件。
buildclient -f client.c -o client -v
* 用buildserver命令从源程序编译出服务端可执行文件。-s参数列出提供的交易。
Buildserver -f simpserv.c -o simpserv -s TOUPPER -v
* 用tmloadcf命令从文本配置文件ubbconfig生成二进制配置文件tuxconfig。
Tmloadcf -y ubbconfig

开发TUXEDO C/S系统的必要步骤
* 配置环境变量
* 编码并编译客户端和服务端的程序
* 由文本的ubbconfig生成二进制TUXCONFIG
* 启动系统和服务
* 测试应用
* 关闭系统

小结
* 客户端/服务器模式的演化
* 用TUXEDO管理多层客户端/服务器模式
* 一个简单应用:simpapp


客户端开发 Client Development
本节要点
* 客户端在客户端/服务器模式中的作用
* 开发客户端的过程
* 查找错误
tperrno,tperrordetail
tpstrerror(),tpstrerrordetail()
userlog()
* 使用ATMI
进程管理
缓冲管理
请求/响应通讯
* 建立并编译一个TUXEDO客户端应用
buildclient
客户端在C/S模式中的作用

为了更好的了解客户端的所有任务以编写客户端应用,有必要重新认识客户端在C/S模式中扮演的角色。
首先,客户端是用户界面。意思是当用户在系统上用程序进行一次操作的整个过程就是一个客户端过程。前端过程是对客户端的另一个描述。客户端的首要任务就是获得执行操作应该得到的数据。
一旦客户端得到了应有的信息,应该将数据按服务能够识别并适合传输的格式打包。
然后,向服务端发送请求并等待回应。
收到回应数据后,将其按一定格式返回给终端用户。



客户端开发过程
客户端程序的设计和实现可以被分成2部分考虑:
* 用户处理过程
* TUXEDO功能部分
下文的客户端程序只描述了TUXEDO功能部分。
利用TUXEDO的ATMI API调用可以做到:
——基本的TUXEDO调试技巧(tperrno,tpstrerror,userlog)
——TUXEDO进程管理(tpinit,tpterm)
——基本数据缓冲管理(tpalloc,tprealloc,tpfree)
——基本通讯(tpcall,tpacall,tpgetrply)

调试和错误处理
当调用ATMI出错时,返回值为-1,全程变量tperrno被设值,该变量提供系统定义的出错原因。函数tpstrerror()以此变量为参数,返回错误的字符说明信息。
完整的错误号和文本错误信息存在于文件$TUXDIR/include/atmi.h。
函数userlog()重定向输出文件为ULOG.mmddyy。使用方法同printf()。该函数每次输出都写硬盘,这样在系统失败时也能保留调试信息。
代码范例
main()
{
int ret;
ret = [a ATMI call]
if ( ret == -1 )
{
printf("Error in ATMI call/n");
usrlog("ATMI error logged %d %s",tperrno,tpstrerror(tperrno));
}else
printf("ATMI call OK/n");
......
ret = tpterm();
if ( ret == -1 )
{
printf("Error in exiting application/n");
usrlog("ATMI error logged %d %s",tperrno,tpstrerror(tperrno));
}
}

tperrno - 全程变量
(char *)tpstrerror(int)
userlog(...) - 语法同printf()
ULOG.mmddyy - 日志文件



进程管理
为了使客户端能够访问TUXEDO交易,客户端程序必须连接TUXEDO应用并进行登记。这种管理性步骤在切断连接时也要类似执行一次。API如下:
int tpinit(TPINIT *tpinfo)
客户端通过调用tpinit()与应用连接,进行交互,有以下事件发生:
调用安全接口检查客户端是否需要认证
连接BB,使进一步的ATMI函数得到信息
使BBL了解BB中已经存在请求
建立客户端消息队列使服务可以发回返回信息,系统可以送出广播通知等
错误时返回-1,可能由以下原因引起:
* TPEINVAL 参数错误
* TPENOENT BB无空间
* TPEPERM 无连接权限
* TPEPROTO 协议错误 - 被服务调用
int tpterm()
客户端调用tpterm()切断与应用的连接,结束了客户端的TUXEDO进程,该过程发生以下事件:
BB入口删除,使BBL知道客户端已经离开
客户端离开BB,客户端的信号量被移除
客户端消息队列被移除
错误时返回-1,可能由以下原因引起:
TPEPROTO 协议错误 - 被服务调用
TPESYSTEM /T系统下错误
TPEOS 操作系统错
范例
main()
{
int ret;
ret=tpinit((TPINIT *)NULL);
......
ret=tpterm();
}

数据缓冲管理
ATMI提供函数分配(tpalloc(),tprealloc())、释放(tpfree())TUXEDO数据缓冲。应用负责将应用数据填入缓冲。应用的数据类型和组织决定应该选择何种数据缓冲。函数type()可以返回正在使用的数据缓冲类型。
以下是TUXEDO基本的数据缓冲类型:
* STRING 以空值结尾的单域字符数据。
* CARRAY 有长度定义的单域二进制数据,不进行编、解码。
* VIEW 类C结构或COBOL记录的多域组织。
* FML 无固定结构的自定义缓冲。
tpalloc(),tprealloc()在出错时返回空值,可能由以下原因引起:
* TPEOS 操作系统
* TPEINVAL 非法或不正确的类型
* TPESYSTEM TUXEDO之下的错误

范例
main()
{
int ret;
char *bufptr;
ret = tpinit((TPINIT *)NULL);
if ( ret == -1)
{
printf("Error in joining application/n");
userlog("tpinit error %d %s",tperrno,tpstrerror(tperrno));
}else
printf("tpinit ok/n");
bufptr=tpalloc("STRING",NULL,1*1024);
if ( bufptr==NULL)
{
printf("Error in allocating buffers /n");
userlog("tpinit error %d %s",tperrno,tpstrerror(tperrno));
tpterm();
exit(-1);
}
......
tpfree(bufptr);
ret = tpterm();
if ( ret == -1)
{
printf("Error in exiting application/n");
userlog("tpterm error %d %s",tperrno,tpstrerror(tperrno));
}
}
函数用法
(char *)tpalloc((char *)type,(char *)subtype,long size)
(char *)tprealloc((char *)bufptr,long newsize)
void tpfree((char *)bufptr)





同步通讯

函数tpcall()有6个参数。如下:
* 交易名
* 请求数据缓冲
* 请求数据缓冲的长度(仅缓冲类型为CARRY时需要)
* 返回数据缓冲的地址。缓冲大小可以根据收到数据而改变。
* 返回数据缓冲大小的地址
* 标志量
标志量可以是以下值:
* TPNOTRAN 如有交易不调用
* TPNOBLOCK 如有阻塞不等待
* TPNOTIME 愿意等待直到超时
* TPSIGRSTRT 系统中断信号在TUXEDO完成后再发布
出错返回-1,错误原因如下:
* TPEINVAL 参数错误
* TPETRAN 交易相关错误
* TPETIME 超时
代码范例
main()
{
int ret;
long len=0,flags=0;
char *bufptr;
if (tpinit((TPINIT * )NULL) == -1)
{
exit(1);
}
if ((buf=tpalloc("STRING",NULL,801*1024==NULL)
{
tpterm();
exit(2);
}
ret = tpcall("TOUPPER",bufptr,len,&amp;bufptr,&amp;len,flags);
if (ret == -1)
{
userlog("Error requesting %d %s",tperrno,tpstrerror(tperrno));
tpfree(bufptr);
exit(-2);
}
tpfree(bufptr);
if(tpterm()== -1)
{
userlog("tpterm error %d %s",tperrno,tpstrerror(tperrno));
}
}
int tpcall((char *)servicename,(char *)bufptr,long length,(char **)bufptr,(long *)length,long flags)

异步通讯I tpacall()
ATMI提供2个异步通讯函数
* tpacall()
* tpgetrply()
tpacall()有4个参数
* 交易名
* 请求数据缓冲
* 请求数据缓冲的长度(仅缓冲类型为CARRY时需要)
* 标志量(同tpcall())
返回值是一个非负描述符(句柄),用于其后的tpgetrply()调用。如果tpacall()调用失败,句柄是-1,错误原因设置在tperrno,可能是以下值:
* TPELIMIT 过多未处理的tpacall()
* TPETIME 超时
tpacall()后总跟随一个tpgetrply(),有4个参数
* 变量地址,可以传入tpcall()所得句柄,或另设一个
* 返回数据缓冲的地址。缓冲大小可以根据收到数据而改变。
* 返回数据缓冲大小的地址
* 标志量
标志量的值可以是如下之一:
* TPGETANY 取第一个返回值,设句柄
* TPNOCHANGE 取发送请求的匹配的类型的信息
* 参见tpcall()中的值
返回值0表示成功,-1表示失败,错误原因可能如下:
* TPEINVAL 参数错误
* TPEOTYPE 返回数据缓冲类型错误
* TPETIME 超时
main()
{
if (tpinit((TPINIT *)NULL)== -1)
......
bufptr=tpalloc("STRING",NULL,100);
if (bufptr==NULL)
......
cd=tpacall("TOUPPER",bufptr,len,flags);
if (tpgetrply(&amp;cd,&amp;bufptr,&amp;len,flags)== -1)
......
tpfree(bufptr);
if (tpterm()== -1)
......
}
int tpacall((char *)service,(char *)bufptr,long len,long flags);
flag:TPNOBLOCK,TPSIGRSTRT,TPNOTIME,TPNOTRAN,TPNOCHANGE,TPGETANY
int tpgetrply((int *)handle,(char **)bufptr,(long *)len, long flags);
flag:TPNOBLOCK,TPSIGRSTRT,TPNOTIME,TPNOTRAN

编译C语言客户端程序
当C语言的客户端程序编码完后,需要连接正确的库并编译。使用buildclient可以使该过程容易一点。该命令引用了C语言编译器并按正确的次序连接TUXEDO系统的库。为使用buildclient,应确认客户端程序包含了"atmi.h",TUXDIR被设了正确的值。命令语法如下:
buildclient [-v] -o executable -f first-file [-f first-file] [-l last-file]
此处first-file表示的应该是编译器可以识别的文件。缺省的编译器是cc。一般是.c(c源程序),.C(C++源程序),.o(object)或.a(库)文件。
参数解释如下:
-o 生成的可执行文件名
-f 需要在连接TUXEDO库之前传给编译器的文件名。如有多于一个的文件名,名字应用空格分隔并用引号引起。也可以使用多个-f参数。
-l 需要在连接TUXEDO库之前传给编译器的文件名。语法同上。
-v 编译过程显示。

小结
* 不同的客户端/服务器模式
* 用TUXEDO管理多层客户端/服务器模式
* 一个简单应用:simpapp
* 开发TUXEDO客户端

服务端开发 Server Development
本节要点
* 服务的运行流程
* 返回控制
* 创建服务
* 规划服务的考虑
* 启动和关闭
* 一个服务中的交易可以调用另一个服务中的交易
* 一个服务可以提供多个交易
* 发布交易
服务的运行流程
为了更好的了解服务端的所有任务以编写服务端应用,有必要重新认识服务端在C/S模式中扮演的角色。
首先,服务是系统资源的联系点。例如,一个数据库服务联系实际数据库并对其进行查询和修改。为有效进行,应建立一个数据库连接。
其次,服务必须发布系统内可以访问的交易,保证客户端可以知道把请求发往何处。
以上两步结束后,服务进入一个循环——接收请求、处理请求并返回结果。接收请求包括进入消息队列,得到交易请求。处理请求包括检查请求数据缓冲,运行商业规则和逻辑,可能还包括访问数据库和返回结果数据缓冲。
当系统管理员需要关闭系统,可以通过系统管理工具将关闭系统的消息发给服务。服务完成所有交易,取消交易发布,关闭资源连接然后结束。

返回控制
在一般的C程序中,函数通过调用return()将控制返回,函数调用堆栈清空,控制返回调用点。
TUXEDO系统的交易函数必须结束于将回应返回给客户端或前转到另一交易。函数tpreturn()用来结束交易将回应数据缓冲发给客户端。函数tpforward()将交易前转给另一个交易,由其负责回应原来的客户端。下图是tpreturn()的示意图。
tpreturn()设计来代替常规的return(),结束绝大多数函数。它将回应数据缓冲返回请求的客户端,控制权返回给服务程序的标准main()(由TUXEDO提供)。
tpreturn()使用下列参数:
第一个值表示交易是否成功,有3种可能:
* TPSUCCESS 交易完全成功,如果是一个会话,TPEV_SVCSUCC被生成
* TPFAIL 交易失败,tperrno将被设成TPESVCFAIL。如果是事务模式,事务被标志成abort-only,如果是会话,TPEV_SVCFAIL被生成。
* TPEXIT 与TPFAIL类似,但服务会中断,如果服务设成可以重启动,则可以由TUXEDO系统将其重启动。
第二个值是应用定义返回码,此处使交易可以发送一个整形代码到客户端,给出交易处理结果的详细信息。该值与/T系统无关,通过全程变量tpurcode送到客户端程序。
第三个值是回应数据缓冲的的指针
第四个值是回应数据缓冲的长度(仅缓冲类型为CARRY时需要)
第五个值是标志位,通常不用


初始化和结束服务
tpsvrinit()和tpsvrdone()分别用来启动和关闭服务。如果应用不提供这两个函数,可以使用替代函数。tpsvrinit()用tpopen()缺省打开RM连接。tpsvrdone()用tpclose()关闭RM连接。
tpsrvinit()象标准C语言的main()一样使用参数argc,argv。服务的命令行参数可以传入该函数,被getopt()解析。该部分的用法参见应用配置部分。本函数出错时返回-1,成功返回0。
tpsvrdone()无参数,无返回值。

创建服务
当C语言的交易程序编码完后,需要连接正确的库并编译。使用buildserver可以使该过程容易一点。该命令引用了C语言编译器并按正确的次序连接TUXEDO系统的库,连接TUXEDO生成的main()等。buildserver还用-s参数产生合适的交易名/函数名映射表。要使用buildserver,必须先正确设定环境变量TUXDIR,PATH,LD_LIBRARY_PATH。命令语法如下:
buildserver [-v] [-o executable] [-s service2,service3:func] [-f source/object] [-l object/library file]
例:
buildserver -s DEPOSIT -o TLR -f TLR.o -f appinit.o
参数解释如下:
-o 生成的可执行文件名
-f 需要在连接TUXEDO库之前传给编译器的文件名。如有多于一个的文件名,名字应用空格分隔并用引号引起。也可以使用多个-f参数。
-l 需要在连接TUXEDO库之前传给编译器的文件名。语法同上。
-v 编译过程显示。
-b 指定SHM或MP模式。如无此项,两种模式都包括;使用此项可以使生成的可执行文件小一点
-r 连接此处指出的RM库。该RM的名字必须含在$TUXDIR/udataobj/RM文件中。

规划服务的考虑
在TUXEDO应用中,必要时服务可以仿客户端方式工作。例如:一个服务可能需要其他服务提供的交易,而建立一个副本并不太合理;当然,有时这样做会高效些。这种特性使程序员在多机配置应用逻辑可以改善编码和执行效率。关于这方面的例子,请参见TUXEDO提供的应用实例bankapp中的TRANSFER交易。
一般是出于以下考虑,使用此种方式:
* 最好不要使用收到的数据缓冲向其他服务请求,因为该缓冲可能被改变引起错误
* 服务中的交易不应调用本服务中的交易,因为容易产生死锁(仅当设置TPNOREPLY时可以)
* 一个MSSQ集中的服务需要返回时,应有自己的返回队列;否则会与本集中其他服务冲突。


数据缓冲管理
数据缓冲管理大部分内容与客户端相同
与请求数据缓冲不同,传给交易的数据缓冲可能已经被tpalloc(),tprealloc(),tpfree()函数处理过。
因为传给交易的请求数据缓冲已经被tpalloc()分配,所以可以tprealloc()。
所有在服务中分配的数据缓冲,在程序结束时必须全部释放;唯一例外是用在tpreturn()中的返回数据缓冲。
如有剩余数据缓冲没有释放,会在每次交易调用时都生成一些,最终耗尽服务器内存。这可以很容易通过监视进程大小发现,它会随时间增长而加大。

仿客户端的方式
下图展示的流程控制表示一个服务仿客户端方式工作。服务接收客户端请求,进一步向另一个交易进行请求。后者处理后返回前者,前者继续进行处理,准备回应数据缓冲,发回客户端。
此结构不能超过2级!

转发的方式
下图展示的流程控制表示交易请求从客户端来到一个服务,转发到另一个服务,然后返回客户端。


多个交易
一个商业应用处理可能会需要来自不同数据源的相似信息或功能。
例如下图,TUXEDO有多种方式实现:
* 各交易功能分隔在独立的可执行服务中
因为功能分布在不同的可执行服务中,编译如下:
buildserver -f read70.c -o read70 -s READ70
buildserver -f read80.c -o read80 -s READ80
buildserver -f read90.c -o read90 -s READ90
* 将不同功能组织在一个可执行服务中,分隔成不同交易
服务程序包含3个交易函数,编译如下:
buildserver -f read.c -o read -s READ70 -s READ80 -s READ90
* 合并各功能成一个交易,使用别名调用
使用TUXEDO的别名功能,使交易以不同名字发布,如:
buildserver -f read.c -o read -s READ70,READ80,READ90:READ
READ是真正的交易函数,但服务可以接受对READ70,READ80和READ90的请求

动态发布
当交易运行时,交易可以用tmadmin在启动时发布,也可以通过调用ATMI动态发布。交易例程可以通过调用服务发布或取消发布。
tpadvertise()可以被一个服务调用,发布一个交易
tpunadvertise()可以被一个服务调用,取消发布一个交易
tpadvertise()
该函数允许服务为自己动态发布一个交易,参数如下:
* 被发布的交易名
* 交易请求处理函数地址
返回值-1表示失败。
如果交易已经被同一函数发布,tpadvertise()立即返回成功。
如果tpadvertise()被一个MSSQ集中的服务调用,交易被发布到该集所有服务上。
出错原因包括:
* TPEMATCH 交易已经被其他函数发布
* TPELIMIT 可发布交易最大数已经达到,该限制在配置文件中的MAXSERVICES规定
* TPEINVAL 有参数为NULL
* TPEPROTO 协议错误(如被客户端调用)
动态发布范例1
$tmadmin
>advertise AUDIT:doaudit -g SYSGRP -i 1
AUDIT发布在组SYSGRP,服务srvid=1
动态发布范例2
void Adminservices(TPSVCINFO *transb)
{
/* 取时间time*/
if ( time>12 midnight &amp;&amp;
time < 6 a.m.)
{
if (tpadvertise("AUDIT",doaudit) == -1)
{
userlog("unable to advertise AUDIT service");
tpreturn(TPFAIL,0,transb->data,0L,0);
}
}
}
voiddo
audit(TPSVCINFO *transb)
{
......
}

应用配置Application Configuration

本节要点
* 应用配置概览
* 管理进程
* 使用IPCS资源
*RESOURCES
*MACHINES
*GROUPS
*SERVERS
*SERVICES
* 管理命令
应用配置总览
应用的描述信息配置在系统核心位置,用一个文件描述,通常称为ubbconfig文件,在主控机器上。整个TUXEDO系统的管理任务可以在一台机器上完成,在配置中被定为主控节点。
在运行时,这些信息被装入一段共享内存(一个IPC资源),称为公告牌(Bulletin Board-BB);包含有配置中不同机器的信息,在这些机器上运行的服务的信息,这些服务提供的交易的信息以及其他相关信息。
客户端在运行时连接公告牌。当客户端程序调用一个交易,将根据公告牌找到合适的服务队列。
所以,公告牌是:
——供客户端寻找适当的服务运行一个交易请求
——包含应用信息:机器,服务,交易,网络等
——创建于ubbconfig文件
TUXEDO提供一个管理进程,称为BBL(Bulletin Board Liaison),包含了一个公告牌的本地拷贝和本地服务器上应用的状态。
TUXEDO提供的另一个管理进程DBBL(Distinguished Bulletin Board Liaison),用于多服务器配置时。DBBL与BBL协同,保证所有部分的公告牌内容的一致性。

配置文件
任何TUXEDO应用系统的最基本的管理任务,是建立并维护配置文件。该文件通常称为ubbconfig文件。负责该工作的系统管理员必须很好的了解分布于各台机器上的应用服务的数据流,消息队列的构造,资源间的相互关系。ubbconfig文件可视作包含应用启动信息的容器,需编译成二进制文件tuxconfig,作为启动时的参考。
其内信息包括:
* 系统范围信息(*RESOURCES节)
* 机器信息(*MACHINES节)
* 组信息(*GROUPS节)
* 服务信息(*SERVERS节)
* 交易信息(*SERVICES节)
* 网络组信息(*NETGROUPS节)
* 网络信息(*NETWORK节)
* 路由原则信息(*ROUTING节)
当完成了ubbconfig文件后,用tmloadcf命令生成tuxconfig
另一种从ubbconfig生成tuxconfig的方法是使用图形管理界面(GAI-Graphical Administration Interface)。

应用的信息
*RESOURCES节包含整个应用范围的信息。本节必须在配置文件第一节,不可缺少。信息说明如下:
参数 意义
*RESOURCES *RESOURCES节
IPCKEY 共享内存id
UID TUXEDO管理员用户id
GID TUXEDO管理员用户id
PERM TUXEDO管理员组用户的权限
MAXACCESSERS 服务端和客户端的最大进程数
MAXSERVERS 限制可以启动服务总数
MAXSERVICES 限制可以发布交易总数
MASTER 指出主控节点的逻辑名,第二个是备份节点
MODEL 应用构架,MP表示多机
OPTIONS LAN,MIGRATE表示是一个网络应用,服务可以移植到替代处理器上
SECURITY 安全级别(5个)
AUTHSVC 客户端可以通过交易“AUTHSVC”获得认证
NOTIFY DIPIN,客户端通过dip-in收到广播通知
SYSTEM_ACCESS PROTECTED,NO_OVERRIDE,应用代码不得干扰共享内存
LDBAL 设Y则进行负载平衡
MAXBUFTYPE 数据缓冲类型及子类的最大数
SCANUNIT 内部时间间隔单位,单位是秒
SANITYSCAN 检索公告牌的内部时间间隔,单位是SCANUNIT
BLOCKTIME 交易超时时间,单位是SCANUNIT
BBLQUERY DBBL查询所有BLL的时间间隔
DBBLWAIT DBBL等待BBL回应的超时时间
MAXCONV 同时最大会话数
注意:本处未列出全部参数。这些系统范围内参数可以被后序节内参数超越。
范例
*RESOURCES
IPCKEY 80952
UID 213
GID 1
PERM 0660
MAXACCESSERS 150
MAXSERVERS 75
MAXSERVICES 200
MASTER SITE1,SITE2
MODEL MP
OPTIONS LAN,MIGRATE
SECURITY APP_PW
AUTHSVC AUTHSVC
NOTIFY DIPIN
SYSTEM_ACCESS PROTECTED,NO_OVERRIDE
LDBAL Y
MAXBUFTYPE 10
MAXBUFSTYPE 15
SCANUNIT 10
SANITYSCAN 12
BLOCKTIME 3
BBLQUERY 24
DBBLWAIT 10
MAXCONV 10



机器信息
*MACHINES节包含应用有关的每个处理器的信息。本节必须在*RESOURCES节后列出。
参数 意义
*MACHINES MACHINES节
gumby 物理处理器名,可以通过"uname -n"或节点名得到
TUXDIR TUXEDO系统软件安装位置
APPDIR 应用服务位置全路径
TUXCONFIG TUXEDO配置文件全路径
ENVFILE 环境文件全路径
ULOGPFX 应用日志文件全路径
MAXACCESSERS 本机最多处理器数,可以超越*RESOURCES节定义
MAXCONV 本机最大会话数,可以超越*RESOURCES节定义
范例
*MACHINES
gumby LMID=SITE1
TUXDIR="/usr/tuxedo"
APPDIR="/usr/apps/atmapp"
TUXCONFIG=" /usr/apps/atmapp/atmapp.tux"
ENVFILE=" /usr/apps/atmapp/ENVFILE"
ULOGPFX="/usr/apps/atmapp/logs/ULOG"
MAXACCESSERS=100
MAXCONV=15
组定义
*GROUP节包含服务组的定义。一台机器至少要定义一个服务组。如果没有定义组,管理命令tmadmin可能依然能运行。
每个组只要定义组名,映射组名的组号和逻辑机器名。组为分布式交易系统和数据依赖路由等灵活性措施提供了支持。
参数 意义
*GROUPS GROUP节
BANKB1 组的唯一标识符,可以是字母数字
GRPNO 组的唯一数字标识符
LMID 组所在的机器
范例
*GROUPS
BANKB1 GRPNO=200 LMID=SITE1
BANKB2 GRPNO=220 LMID=SITE1
SYSGRP GRPNO=110 LMID=SITE1
EVTGRP1 GRPNO=120 LMID=SITE1

服务定义
ubbconfig的*SERVERS 节包含的是服务进程的信息。本节中每一个入口代表一个应用启动时加载的服务。这些信息包含服务名,命令行参数,服务环境,重启动等等。由于每个服务功能各不相同,其配置参数也因此相同或相异。
参数 意义
*SERVERS SERVER节,列出所有服务程序
DEFAULT: 本处列出的参数为其下列出的服务的缺省值,但可以被单列条目替代相应值
RESTART 如果设成Y,则服务可以重启动
MAXGEN 在GRACE定义时间之内,服务可以重启动MAXGEN次
GRACE 周期,单位是秒
RCMD 每次服务重启动,本处定义的脚本或命令被执行
ENVFILE 列有环境变量的文件,在交易启动前设入环境
TLR 一个服务名,用buildserver建立,应在APPDIR或$TUXDIR/bin
SRVGRP 服务属于一个在*GROUPS节中定义的服务组;如果需要移植服务,也可以定义在多个组中。
SRVID 服务组中代表服务的唯一值
MIN 最少在启动时启动的服务数
MAX 运行时,最多可以起的实例数
CLOPT 跟随服务启动的其他参数
-A 服务内建交易全发布
-r 指定服务记录时间戳,用于以后计算交易处理时间
-e 定义标准错误重定向文件
-o 定义标准输出重定向文件
-- TUXEDO参数和服务特定参数的分隔符
... 传给tpsvrinit()的参数
SYSTEM_ACCESS 设定后,应用错误不干扰公告牌
RQADDR 当设定此项后,所有本服务的实例都使用相同的请求队列。这是在应用中设置MSSQ(Multiple Server Single Queue)的方便办法,可以改善处理流量。任何时候,所有MSSQ集中的实例发布相同的交易集。
XFER 另一个服务
REPLYQ 设成Y,则服务又作为一个MSSQ集配置,任何其中的交易调用其他交易,就建立一个单独的回应队列。
范例
*SERVERS
DEFAULT: RESTART=Y MAXGEN=5 GRACE=3600
RCMD="/sur/apps/atmapp/scripts/beeper"
CLOPT="-A" ENVFILE="/usr/apps/atmapp/envfile"
TLR SRVGRP=BANKB1 SRVID=10 MIN=1 MAX=2
CLOPT="-A -r
-e /usr/apps/atmapp/logs/TLR1.err
-o /usr/apps/atmapp/logs/TLR1.out
--
-T 101 -e 300 -d dbfile"
SYSTEM_ACCESS=PROTECTED
RQADDR="TLR_Q1"
XFER SRVGRP=BANKB1 SRVID=20 MIN=1 MAX=2
RQADDR="XFER_Q1" REPLYQ=Y
CLOPT="-A -r"

交易定义
*SERVICES节提供了应用的特殊交易的信息。包括负载平衡(LOAD)和数据缓冲类型检查(BUFTYPE)。如果全部都是缺省值则本节可以省略。
参数 意义
*SERVICES 交易节
# 注释行符号
大写字母 交易名,由应用服务提供
BUFTYPE 任何向该交易的请求,数据应该是此处定义类型
GROUP 交易所在服务所在的组
LOAD 负载因子,表示处理请求的时间,用于计算负载平衡
PRIO 优先级
范例
*SERVICES
#comment line
DEPOSIT BUFTYPE="FML"
SRVGRP=BANKB1
LOAD=25 PRIO=70

生成TUXCONFIG文件
UBBCONFIG文件是一个可以编辑成需要的应用配置的文本文件。但是,/T在实际应用上读取的是二进制TUXCONFIG文件用于操作。命令tmloadcf可以把UBBCONFIG文件转化成TUXCONFIG文件。
tmloadcf命令接受以下4个参数:
-c 计算运行应用需要的IPC资源,该信息将提供给管理员,用于在各机器上配置资源。
-n 进行语法检查并不生成TUXCONFIG。
-b 控制TUXCONFIG占用的物理页数。
-y 无条件覆盖TUXCONFIG
环境变量TUXCONFIG必须设定指向二进制TUXCONFIG文件。
在安全要求高的应用中,tmloadcf不能从标准输入接受,环境变量APP_PW必须包含应用密码。
tmunloadcf将TUXCONFIG转换成ASCII格式用于检查。该工具读取环境变量TUXCONFIG指向的文件。输出包含所有的参数,包括TUXEDO设定的缺省值,是UBBCONFIG文件的一个超集。
管理命令Administrative Commands

本节要点
* 命令tmboot
* 命令tmshutdown
* 命令tmadmin
* 批处理命令
* 服务移植

命令tmboot
tmboot命令启动TUXEDO系统的 /T应用,创建必要的IPC资源、启动相关机器的规定的系统和应用服务进程。大多数的tmboot的参数启动了部分系统进程。在以下说明和例子中,lmid,grpname和srvid是配置文件中指定的值。
-A 启动所有机器上的管理进程。
-M 启动主控机器上的管理进程。
-i srvid 启动服务id等于 srvid的进程。
-g grpname 启动指定的一组服务(含TMS)
-S 启动所有应用服务。
-s server-name 启动可执行文件名为server-name的服务。
-l lmid 启动TMS和指定机器上的应用服务。
-T grpname 启动指定组中所有TMS。
-B lmid 启动指定机器上的BBL。
-e command 指定启动进程失败后在主控机器上运行的命令名。
-c 打印本配置所需最少的IPC资源。

命令tmshutdown
tmshutdown命令用于关闭所有或部分应用并释放IPC资源。
本命令所用参数与tmboot类似(如:-A, -g, -i, -s, -S, -l, -M, -B),意义相同。
如果需要移动服务,关闭服务时用-R参数即可不删除BB中的入口。
在非主控节点上,可以用-P参数仅关闭该机器上的应用。
当有客户端正在连接时,tmshutdown 不能关闭管理服务。参数-c则可以超越此规则。该参数仅用于管理员需要立即关机而又无法及时通知客户端时。
参数-w delay 在delay秒后进行强制关闭。指定的服务当即被挂起,使之不能继续接受交易请求。delay的值则允许服务在一个合理的时间内完成已经接受的请求。在延迟的时间到达后,信号SIGKILL(或SIGTERM)将发给指定的服务。该参数目的是使管理员能够关闭发生死循环或死锁的服务。
管理工作和工具
主要有以下两个管理工具:
* 使用图形界面的图形管理接口(Graphical Administration Interface-GAI)
* tmadmin
通常管理工作有以下3类:
* 监视运行系统
一般监视以下信息:应用、服务、客户端、交易、队列、组、会话、网络等。
* 动态修改服务或交易参数
使用GAI 或tmadmin可以动态进行以下调整:
——交易可以挂起、恢复、发布和取消
——交易参数可以修改,如:LOAD和PRIORITY
——指定交易的超时时间
——交易口令
* 进行启动,关闭,移动服务等管理员的任务
服务信息
来自GAI的信息本处略去。
以下是tmadmin命令的printserver(简写为psr)的简单输出。
列号 描述
1. 服务的可执行文件名
2. 服务连接的队列名
3. 组名
4. 服务的数字id
5. 服务已经处理的请求数
6. 服务处理的全部请求的参数和
服务正在处理的交易,若为IDLE则服务当前是空闲
ccsmis:/home2/ccsmis>tmadmin
tmadmin - Copyright (c) 1996 BEA Systems, Inc.
Portions * Copyright 1986-1997 RSA Data Security, Inc.
All Rights Reserved.
Distributed under license by BEA Systems, Inc.
Tuxedo is a registered trademark.
> printserver
Prog Name Queue Name Grp Name ID RqDone Loaddo
ne Current Service
--------- ---------- -------- -- ------ --------- ---------------
rz_Ecsb 00004.04000 APGP2 4000 0 0 ( IDLE )
BBL 70020 simple 0 1 50 ( IDLE )
IFMTMS APGP2_TMS APGP2 30001 1 50 ( IDLE )
ftpserv32 00002.00001 FTPGP 1 60 3000 ( IDLE )
WSL 00001.00001 SYSGP 1 0 0 ( IDLE )
IFMTMS APGP2_TMS APGP2 30002 12 600 ( IDLE )
ftpserv32 00002.00002 FTPGP 2 0 0 ( IDLE )
IFMTMS APGP2_TMS APGP2 30003 11 550 ( IDLE )
CCS_QUANBIA_60 00004.06004 APGP2 6004 0 0 ( IDLE )
CCS_SCBB_4099 00004.04099 APGP2 4099 2 100 ( IDLE )
CCS_GEKEZI_300 00004.03000 APGP2 3000 0 0 ( IDLE )

交易信息
来自GAI的信息本处略去。
以下是tmadmin命令的printservice(简写为psc)的简单输出。
列号 描述
1. 交易名
2. 交易函数名
3. 服务可执行文件名
4. 服务所在组名
5. 服务的数字id
6. 提供交易的机器的LMID
7. 交易已经执行的次数
8. 交易当前状态
Service Name Routine Name Prog Name Grp Name ID Machine #do
ne Status
------------ ------------ --------- -------- -- ------- ------ ------
416701 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
416601 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
416501 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
416401 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
416201 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
416301 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
416101 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
416001 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
415901 rz_Ecsb rz_Ecsb APGP2 4000 simple 0 AVAIL
:
队列信息
以下是tmadmin命令的printqueue(简写为pq)[qaddress]的简单输出。如果不指定address,所有队列信息将被输出。
列号 描述
1. 队列连接的服务的可执行文件名
2. 字符队列名,是RQADDR参数或一个随机值
3. 连接的服务数
4. 当前队列的所有请求的参数和
5. 实际请求数
6. 平均队列长度
7. 队列所在机器的LMID
> pq 00004.05062
Prog Name Queue Name # Serve Wk Queued # Queued Ave. Len Machine
--------- ------------------- --------- -------- -------- -------
CCS_GEDAIPC_50 00004.05062 1 0 0 0.0 simple
客户端信息
来自GAI的信息本处略去。
以下是tmadmin命令的printclient(简写为pclt)的输出,来自TUXEDO系统的日志信息。主要有以下信息:
客户端id,用户名和当前状态
登录的LMID和进程号(PID)
服务组和上一访问过的服务组
交易(启动/提交/中断)和会话的统计数字
中继队列id,通知方法和提交控制
列号 描述
1. 已经登录的客户端机器的LMID
2. 用户名,由tpinit()提供的
3. 客户端名,由tpinit()提供的
4. 客户端连接后经过的时间
5. 客户端状态
6. IDLE——表示客户端目前没有任何交易在工作
7. IDLET——表示客户端启动了一个交易
8. BUSY——表示客户端在工作中
9. BUSYT——表示客户端正在交易控制下工作
10. 启动/提交/中断的交易数
> pclt
LMID User Name Client Name Time Status Bgn/Cmmt/Abrt
--------------- --------------- --------------- -------- ------- -------------
simple ccsmis WSH 17:42:47 IDLE 0/0/0
simple ccsmis tmadmin 0:44:28 IDLE 0/0/0
用tmadmin写脚本
输出所有服务/交易/队列信息
$tmadmin 2>&amp;1<<!
echo
verbose
psr
psc
pq
!
挂起bankapp内所有AUDIT交易
(tmadmin 2>&amp;1 <<!
pq
!
) |
awk 'begin
{ print "tmadmin <<! /necho"}
{if ( $1 == "AUDIT") print "susp -q" , $2, "-S $1"}
END {print "q/n!"}' |
/bin/sh
移植服务
该功能使管理员可以将服务移动到其他位置。服务可以用migrategroup(migg)[-cancel] group移植一组服务,或用migratemach(migm) [-cancel] machine移植一台机器上的服务。
以下是移植服务的步骤:
1. 服务必须用tmshutdown或-R参数关闭。该参数包含公告牌中的服务名。
2.在配置文件中的*RESOURCES段必须指明MIGRATE
*RESOURCES
...
OPTIONS MIGRATE
...
3.在*GROUP段中,被移植的服务组在LMID参数中必须有替代位置。当移植机器时,所有组的LMID参数的替代位置必须相同。
*GROUP
...
APGP2 LMID=SITE1,SITE2
...
4.服务必须可以重启动,以下是*SERVERS段有关内容
*SERVERS
...
rz_Ecsb SRVGRP=APGP2 RESTART=Y
...
移植在关闭后将被取消。migg 和migm -cancel 参数在服务关闭后从公告牌删除服务名。所以,服务需要重启动才可以使用。
$tmadmin
>stop -R -g APGP2
Shuttingdo
wn server processes ...
>psr -g APGP2
Prog Name Queue Name Grp Name ID RqDone Loaddo
ne Current Service
--------- ---------- -------- -- ------ --------- ---------------
rz_Ecsb 00004.04000 APGP2 4000 0 0 ( IDLE )
IFMTMS APGP2_TMS APGP2 30001 1 50 ( IDLE )
IFMTMS APGP2_TMS APGP2 30002 16 800 ( IDLE )
IFMTMS APGP2_TMS APGP2 30003 15 750 ( IDLE )
CCS_QUANBIA_60 00004.06004 APGP2 6004 0 0 ( IDLE )
CCS_SCBB_4099 00004.04099 APGP2 4099 2 100 ( IDLE )
>migg APGP2
migration successfully completed

缓冲数据类型 Buffer Types

本节要点
* STRING
* VIEW
定义
伪代码中VIEW的使用
代码示例
* FML
定义
伪代码中FML的使用
代码示例
* 结合FML和VIEW
* CARRAY的定义
* FML32和VIEW32
简介和STRING
TUXEDO使用固定类型的数据缓冲进行远程或本地进程间通讯。例如"STRING"就是一种包含了字符数组的一种数据缓冲。绝大多数商业应用需要不止一种数据。
TUXEDO已经预定义了一些数据缓冲类型用以传递各种数据。每种都有其独特的处理方法和相应特性。
STRING
STRING类型缓冲是一串以NULL结尾的字符。TUXEDO为STRING类型编、解码。无论缓冲分配了多大,将由NULL所在位置决定其长度。
TUXEDO的STRING缓冲的使用与C语言程序中的字符数组非常类似。
分配
buf = tpalloc ( "STRING", NULL, 4*1024);
用法
strcpy ( buf "HELLO WORLD");
调用交易
tpcall ("INQUIRY", buf , 0, &amp;buf, &amp;len, 0);


VIEW
VIEW的概念和例子
TUXEDO使用VIEW类型数据缓冲处理结构或复杂数据类型。
使用VIEW的优点:
* 结构化数据表示,可以方便地访问数据元素
* 将多个数据元素绑定在一个定义良好的数据结构上
缺点:
* 所有数据元素都通过,不检查合法性
范例:
struct MYVIEW {
float float1;
do
uble do
uble1;
long long1;
short short1;
int int1;
dec_t dec1;
char char1;
char string1[20];
unsigned short L_carray1[2];
/* length array of carray1 */
short C_carray1;
/* count of carray1 */
char carray1[2][20];
};
$ /* View data structure */
VIEW MYVIEW
#type cname fbname count flag size null
float float1 - 1 - - -
do
uble do
uble1 - 1 - - -
long long1 - 1 - - -
short short1 - 1 - - -
int int1 - 1 - - -
dec_t dec1 - 1 - 9,16 -
char char1 - 1 - - -
string string1 - 1 - 20 -
carray carray1 - 2 CL 20 -
END

使用VIEW的步骤:
* 建立一个VIEW文件
* 设置环境变量
VIEWDIR=$APPDIR
VIEWFILES= cust.V,other.V
export VIEWDIR VIEWFILES
* 编译VIEW文件
viewc -n cust.V
* 在代码中包含头文件
* 编译
* 运行
代码范例:
#include <stdio.h>
#include "atmi.h"
#include "cust.h"
main(int argc, char *argv [ ])
{
struct cust *buf;
long rcvlen;
if (tpinit ((TPINIT *) NULL) == -1)
{
ptintf("tpinit(): %s/n",tpstrerror (tperrno));
exit(1);
}
buf=(struct cust *)tpalloc("VIEW","cust",sizeof(struct cust));
if (buf == (struct cust *)NULL)
{
printf("ERROR:tpalloc(VIEW,cust),%s/n",tpstrerror(tperrno));
tpterm();
exit(1);
}
strcpy(buf->fsst_name,"Mel");
strcpy(buf->lst_name,"Gibson");
buf->acct_id = 10002;
buf->branch_id = 5;
ret = tpcall ("INQUIRY",(char *)buf,0,
(char **)&amp;buf,&amp;rcvlen,0);
if( ret == -1)
{
printf( "tpcall(INQUIRY): %s/n", tpstrerror(tperrno));
tpfree((char *) buf);
tpterm();
exit(1);
}
printf( "Returned amount is : %1.1s/n", buf->amount);
tpfree((char *)buf);
tpterm();
}

FML
概念
预定义方式的VIEW有一些缺点:
* 改变不灵活
* 结构变化时,所有程序需要重新编译
* 即使没有数据,空间也被占用
为克服以上缺点,TUXEDO提供另一种预定义数据,按照‘名字/值’组对格式组织数据。该方式称为FML(Fielded Manipulation Language)。
FML由以下部分构成:
* FML API
* FML命令行工具
FML头部,包含索引
FLOAT1
5.00
DOUBLE1
12.34
LONG1
12345
SHORT1
12
...
...
域名
域值

使用FML的步骤
* 建立一个FML文件:bank.flds
# name number type flags comments
FLOAT1 110 float - -
do
UBLE1 111 do
uble - -
LONG1 112 long - -
SHORT1 113 short - -
INT1 114 long - -
DEC1 115 string - -
CHAR1 116 char - -
STRING1 117 string - -
CARRAY1 118 carray - -

* 设置环境变量
FLDTBLDIR=$APPDIR:$TUXDIR/udataobj
FIELDTBLS=bank.flds,Usysflds
export FLDTBLDIR FIELDTBLS
* 用mkfldhdr编译
mkfldhdr bank.flds
* 编码
参见下一章节
* 编译程序
buldclient -f atmclt.c -o atmclt
FML API
#include <fml.h>
Falloc(int num_of_flds,FLDLEN space)
Finit(FBFR *f)
Fsizeof(FBFR *f,FLDLEN len)
Fadd(FBFR *f,FLDID fldid,int oc,char *value,FLDLEN len)
Fprint(FBFR *f)
Fget(FBFR *f,FLDID fldid,int oc,char *value,FLDLEN len)
Fchg(FBFR *f,FLDID fldid,int oc,char *value,FLDLEN len)
Fcpy(FBFR *f, FBFR *f2)
f = (FBFR *)tpalloc("FML",NULL,200)
Ffprint(FBFR *fbfr,FILE *iop)
* Fprint()是一个有用的调试函数,因为它可以打印出缓冲内容而不需要定义数据类型和输出格式。
* Falloc()用于内部进程通讯
* Fcpy()用来复制FML的内容,特别是在不同服务的交易之间
代码范例:
#include <stdio.h>
#include "atmi.h"
#include<fml.h>
#include "bank.flds.h"
int main (int argc,char **argv)
{
long account ;
float balance;
float amount;
FBFR *sendBuf, *recvBuf;
sendBuf = (FBFR *) tpalloc(RMLTYPE,NULL,Fneeded(20,4*1024));
recvBuf = (FBFR *) tpalloc(RMLTYPE,NULL,Fneeded(20,4*1024));
if (Fchg(sendBuf, ACCOUNT_ID,0,(char * )&amp;account,0) == -1)
{
printf("/nERROE:Fchg(ACCOUNT_ID):%s/n",Fstrerror(Ferror));
}
if(tpcall("INQUIRY",(char *)sendBuf,0,
(char **)&amp;recvBuf,&amp;len,TPSIGRSTRT)== -1
{
if(Fget(recvBuf,STATLIN,0,tmpstr,0)!= -1)
{
printf("/n%s/n",tmpstr);
}
printf("/nERROR: tpcall(INQUIRY):%s/n",tpstrerror(tperrno));
else
{
if(Fget(recvBuf,BALANCE,0,(char *)&amp;balance,0) == -1)
{
printf("/nERROR:Fget(BALANCE):%s/n",Fstrerror(Ferror));
}
else
{
printf("/nBalance:%s/n",balance);
}
}
tpfree((char *) sendbuf);
tpfree((char *) recvbuf);
tpterm();
}

结合FML和VIEW
FML的使用需要进一步的考虑,例如,访问FML数据会慢一些,因为接口要插入或取回数据。在某些场合,需要进行一些推敲。而VIEW则提供了一个通用管理数据缓冲的方案。
FML的优点是可以在机器间传递数据和灵活的存储数据。而VIEW则传递整个定义好的C结构,不管域里面是否有数据。可以使用它们的混合:FML-VIEWS。
TUXEDO提供了2个API把FML转换成VIEW
* int Fvstof(FBRF *bufptr,char *cstruct,int mode,char *view)将VIEW结构转成FML
* int Fvftos(FBFR *bufptr, char *cstruct, char *view) 将FML数据转成VIEW结构

其他数据类型
除FML,VIEW和STRING类型外,另外一个主要的数据缓冲类型是CARRY。
CARRY
CARRY数据缓冲类型是一种定长的,相对独立于机器的数据。
* 长度需要定义
* 不进行编/解码
* 可用来传递二进制数据
* 可以作为FML和VIEW的子项
* 用于文件、图形传输
FML32和VIEW32
在对FML和VIEWS初始化时,寻址是16位的。随着主要的平台都变成32位的,TEXUDO增加了FML32和VIEWS32。
* 使用32位寻址方式
* 有更大的寻址空间(2GB)
* API与16位的相似,只在名字上加了‘32’字样

数据依赖型路由 Data Dependent Routing

本节要点
* 定义
* 过程
ubbconfig


简介
当遇到非常巨大的数据需要传递时,可以将单一的数据分割成几个部分进行传递。分割的标准根据其商业应用而定。例如,可以根据省份、邮政编码或金额来分割数据。
在TUXEDO中,数据依赖型路由解决了此类大型商业应用的难点,而且不需要进行任何程序工作。仅仅改变一下ubbconfig文件就可以了。
数据依赖型路由是根据数据缓冲区中一个指定域的值,把一个交易请求映射到一个指定的服务组的机制。


数据依赖型路由
数据依赖路由(DDR-Data Dependent Routing)需要在UBBCONFIG文件中的*GROUPS节创建多个入口,并分割组中应用的资源或任务。每个组可以访问各自的数据库并且可以属于独立的机器。注意:一个组不能同时跨越一台以上的机器。
一个有多组独立服务的大型数据库可以被分成几个独立数据集。
此类数据分割的实现是通过对交易请求的缓冲数据值的路由。DDR是基于FML,FML32,VIEW和VIEW32数据缓冲。
TUXEDO使用的路由信息位于共享内存中的公告牌。在ubbconfig文件中有特别的部分对路由进行定义。路由的定义包含了数据使用的域和数据区间及其对应的服务组。
TUXEDO通过对比调用交易内码和共享内存中公告牌中数据路由的值的区间选择目标服务。
在我们的例子中,路由决定于数据域ID。交易请求映射于组G1,G2和G3。每个远程或本地机器上的组都提供相同的交易。

使用DDR的ubbconfig的范例
*GROUP
BANKB1 LMID=SITE1 GRPNO=200
BANKB2 LMID=SITE2 GRPNO=220
*SERVICES
WITHDRAWAL ROUTING=ACCOUNT_ID
*ROUTING
ACCOUNT_ID FIELD=ACCOUNT_ID
BUFTYPE="FML"
RANGES="1-10:BANKB1,
11-20:BANKB2"
BRANCH_ID FIELD=BRANCH_ID
BUFTYPE="FML"
RANGES="0-555:BANKB1,
556-888:BANKB2"
*GROUPS节说明
LMID与每个组相联系。本例中是同一台机器上的设置。当然也可以设成远程机器。
*SERVICES节说明
分割标准是为此交易设置。ROUTING是分割标准的名字
*ROUTING节说明
FILED表示请求交易的那些值用于映射组。
BUFTYPE表示其缓冲数据类型。RANGE定义路由到不同组的数据边界。
可以使用通配符'*'。

网络 Networking
简介
基于以下原因,一个商业应用需要分布于多台机器上:
* 负载均衡
* 容错
* 地理分布
使用TUXEDO,不需编程,应用就可以被分布配置在多台机器上。

本节要点
* 概念
* UBBconfig


多机配置
TUXEDO通过一些部件实现和管理一个多机应用。以下是这些部件和功能描述:

部件
功能
BBL
BBL(Bulletin Board Liaison)记录所有应用服务状态,显示于公告牌(Bulletin Board)。BBL同时修改来自DBBL的全局信息。
DBBL
DBBL(Distinguished Bulletin Board Liaison)记录所有BBL的状态。运行于主节点上,只有一份。
BRIDGE
提供TUXEDO节点间的通讯机制,仅处理ATMI数据。作为系统提供的服务,是最早启动的两个进程。
tlisten
'tlisten'在启动过程中被使用,必须先于TUXEDO应用的启动。


多机配置
tlisten用法
tlisten -d /dev/tcp -l//lcspn1:3050 -L /usr/apps/atmapp/logs/tlog
特点
* 无须编程
* 交易位置对程序员和用户透明
* 公告牌提供全局名字服务


一个简单的UBBCONFIG范例
#ubbconfig file for MP configuration
*RESOURCES
MASTER SITE1,SITE2
BBLQUERY 100
DBBLWAIT 20
MODEL MP
OPTIONS LAN,MIGRATE
*MACHINES
lcspn1 LMID =SITE1
TUXDIR ="/usr/tuxedo"
TUXCONFIG="/home/apps/atmapp/atmapp.tux"
APPDIR ="/home/apps/atmapp"
TYPE =RS6000
Lcspn2 LMID =SITE2
TUXDIR ="/usr/tuxedo"
TUXCONFIG="/home/apps/atmapp/atmapp.tux"
APPDIR ="/home/apps/atmapp"
TYPE =RS6000
*NETWORKS
SITE1 NADDR ="//lcspn1:3050"
NLSADDR ="//lcsnp1:3051"
BRIDGE ="/dev/xti/tcp"
SITE2 NADDR ="//lcspn2:3050"
NLSADDR ="//lcsnp2:3051"
BRIDGE ="/dev/xti/tcp"
*GROUPS
BANKB1 GRPNO1=1 LMID=SITE1
BANKB2 GRPNO1=2 LMID=SITE2
*SERVICES
WITHDRAWAL
*RESOURCES节说明
MASTER参数表示TUXEDO在此处初始化它的启动次序,同时表示DBBL在何处运行,出错时SITE2将作为SITE1的备份。
BBLQUERY决定应用的BBL访问主控节点上DBBL的频率,单位是秒。
当BBL在规定的BBLQUERY时间内没有响应,DBBL会发送一条信息给它,DBBLWAIT即等待响应的超时时间,单位是秒。
MODEL表示TUXEDO是否运行在多台机器上。
*MACHINES节说明
描述了TUXEDO应用或系统安装的物理方面的信息。物理机器名"lcspn1"映射到逻辑机器名"SITE1"和LMID(Logical Machine Identifier)逻辑机器标识符。
参数TYPE用来决定是否在机器间传输时需要进行编、解码。它可被设置成任何字符串。当两机此参数不同时,进行编、解码。
*NETWORKS节说明
在单机配置时,此节略去。在多机时,此节必须。
TUXEDO机器间通过主机地址和端口号传递ATMI数据,这些由NADDR按以下的规定定义:
//lcspn1 主机名
: 分隔符
端口号
NLSADDR定义的是tlisten进程的主机地址和端口号。
BRIDGE用于和其他TUXEDO机器通讯的网络设备由BRIDGE定义。
分布式事务处理Distributed Transaction Processing

简介
分布式事务处理(Distributed Transation Processing-DTP)是运行一组需要访问一定量资源的交易或工作的必须的功能。要求保证交易动作必须全部成功或者全部失败,不能存在‘部分成功’的情况。
TUXEDO系统使用XA协议在本地与远程机器间协同事务活动。

本节要点
* 定义
* XA
* 2段式提交协议
* ATMI事务API
* 过程
* ubbconfig
创建格式化事务日志
用ATMI交易API写程序
分布式事务处理和XA接口
分布式事务处理(Distributed Transation Processing-DTP)有能力处理多数据库间、全局事务而不必考虑交易各方及其资源的位置。
服务使用嵌入式SQL接口去访问数据库。在一个“全局交易”中TM和RM使用XA接口保证执行所有的资源访问动作。
全局事务通常最初被ATMI调用,包含一个以上的组;由客户端和服务端启动、提交或撤消。TUXEDO通过全局事务标识符(Global Transaction Identifier-GTRID)控制所有参与部分。
RM 资源管理者(Resource Manager),本例中是一个数据库。
XA 控制RM提交或回滚所有动作的协议。
TMS TUXEDO的事务管理服务(Transaction Management Server),能够按XA协议与RM联系。TMS负责协调系统范围内事务相关资源管理。应用程序员可以通过ATMI事务API与TMS联系。
GTRID 全局事务标识符(Global Transaction Identifier)。
TLOG 事务日志,用于跟踪交易所有部分。

二段式提交(2 Phase Commit)


分布式事务处理的UBBCONFIG
分布式事务处理的UBBCONFIG范例
#A NULL TMS Example
*RESOURCES
MAXGTT 20
CMTRET COMPLETE
*MACHINES
lcspn1 LMID =SITE1
TUXDIR ="/usr/tuxedo"
APPDIR ="/usr/apps/atmapp"
TUXCONFIG="/usr/apps/atmapp/atmapp.tux"
ENVFILE ="/usr/apps/atmapp/ENVFILE"
TLOGDEVICE ="/usr/apps/atmapp/logs/TLOG"
TLOGNAME =TLOG
TLOGSIZE =100
*GROUPS
DEFAULT:
TMSNAME =TMS
TMSCOUNT=2
OPENINFO=" "
CLOSEINFO=" "
BANKB1 LMID=SITE1 GRPNO=200
BANKB2 LMID=SITE2 GRPNO=220
*SERVICES
TRANSFER AUTOTRAN=Y TRANTIME=30
*RESOURCES节说明
MAXGTT限制了一台机器上同时可以提供的GTRID数。最大值是2048,最小是0,缺省100;
CMTRET设成LOGGED时表示tpcommit()在所有部分都成功预提交时返回;设成COMPLETE时表示tpcommit()在所有部分都成功提交才返回。
*MACHINES节说明
TLOGDEVICE指出了该机器包含事务日志(TLOG)的文件系统。
TLOGNAME指出了该机器的事务日志名字。
TLOGSIZE指出了该机器事务日志的大小,单位是物理页数。最大值是2048,最小是0,缺省100
*GROUPS节说明
TMSNAME是事务管理服务的可执行文件名
TMSCOUNT是TMS启动的数量(最小2,最大10,缺省3)
OPENINFO是一个用于打开RM的信息的字符串
CLOSEINFO是一个用于关闭RM的信息的字符串
AUTOTRAN设成N则该交易初始化成无事务方式,Y则反之。
TRANTIME事务创建的超时时间,单位为秒。
创建事务日志的脚本
tmadmin <<!
crdl -b 500 -z /usr/apps/atmapp/logs/TLOG -O 0
crlog -m STIE1
!
为支持分布式事务处理,必须创建一个格式化的设备记录事务信息。上文是用tmadmin命令的脚本生成此种设备的例子。

ATMI 事务API
事务API通过ATMI给应用提供了以下操作
* 通过tpbegin
(),tpcommit(),tpabort()控制事务的开始和结束。
int tpbegin
(int timeout, long flags)
int tpcommit(long flags)
int tpabort(long flags)
* 通过tpsuspend(),tpresume()管理多个并发的事务。
int tpsuspend(TPTRANID *tranid, long flags)
int tpresume(TPTRANID *tranid, long flags)
* 通过tpscmt()设定提交返回方式为"logged"或"complete"
int tpscmt(long flags)
TP_CMT_LOGGED-在第一段后返回
TP_CMT_COMPLETE-在第二段后返回
* 通过tpgetlev()决定当前事务模式
int tpgetlev(void)
* 通过tpopen(),tpclose()为服务组打开或关闭RM
int tpopen(void)
int tpclose(void)
使用ATMI事务API的代码范例
/* 确保交易TRANSFER没有设成AUTOTRAN */
#include <atmi.h>
FBFR *sendBuf=NULL;
FBFR *recvBuf=NULL;
Void TRANSFER(TPSVCINFO *transb)
{
sendBuf = (FBFR *)transb;
...
if (tpbegin
(30,0) == -1)
{
userlog("FAILED TO begin
TRANSACTION:%s",tpstrerror(tperrno));
tpreturn(TPFAIL, -1, (char *)recvBuf, 0, 0);
}
if ( tpcall("WITHDRAWAL", (char *)sendBuf, 0, (char **)&amp;recvBuf, &amp;len, 0)==-1)
{
userlog("tpcall (WITHDRAWAL) fail:%s", tpstrerror(tperrno));
tpreturn(TPFAIL, -1, (char *)recvBuf, 0, 0);
}
...
if ( tpcall("DEPOSIT", (char *)sendBuf, 0, (char **)&amp;recvBuf, &amp;len, 0)==-1)
{
userlog("tpcall (DEPOSIT) fail:%s", tpstrerror(tperrno));
tpreturn(TPFAIL, -1, (char *)recvBuf, 0, 0);
}
if ( tpcommit(0) == -1)
{
userlog("tpcommit() fail:%s", tpstrerror(tperrno));
tpreturn(TPFAIL, -1, (char *)recvBuf, 0 ,0);
}
userlog("Transaction committed successfully");
tpreturn(TPSUCCESS, 0 , (char *)recvBuf, 0 , 0);
}
本例中的TRANSFER交易使用了TUXEDO XA事务API;本例使用了TUXEDO的NULL TMS配置。当TRANSFER被调用,首先起一个事务,调用交易WITHDRAWAL,然后调用交易DEPOSIT。如果一切都运行成功,TRANSFER调用tpcommit()结束事务。任何错误都将导致RM回滚事务。



管理类API AdminAPI(MIB)


本节要点
* 定义
* 过程
* 代码例子
* 错误处理和管理类API域
简介
在TUXEDO下管理应用有很多手段,如下:
* tmadmin
* tmadmin的脚本
* 调用ATMI
* X-Windows GUI
* JAVA applet Web GUI
* Admin API (MIB)
每一种方法都有其优点和适用场合。Admin API提供访问TUXEDO信息的控制方法和结构。这些信息被分类成组,称为管理信息库(Management Information Base-MIB)。通过Admin API可以访问MIB。使用Admin API有以下优势:
* 可访问的TUXEDO系统信息更多
* 管理应用有更高的灵活度
* 可以集成到外部系统工具中

Admin API(MIB)
TUXEDO系统组成的各个部分都有自己的MIB,每部分的MIB是一组相关的类,每个类代表一个MIB可管理的实体或项目,有其自身的属性、许可权限和语义。TUXEDO系统的MIB有5部分,如下:
* TM_MIB
* EVENT_MIB
* APPQ_MIB
* WS_MIB
* ACL_MIB
下边的例子是访问TM_MIB并显示了/T部分的管理信息库。

范例
Admin API使用了一些预定义的FML32的域,这些数据组织存放在文件$TUXEDO/udataobj/tpadm中。环境变量必须设置如下:
FLDTBLDIR32=$TUXDIR/udataobj
FIELDTBLS32=Usysfl32,tpadm,evt_mib
Export FLDTBLDIR32 FIELDTBLS32
使用Admin API的代码范例
#include <stdio.h>
#include <fml32.h>
#include <atmi.h>
#include <tpadm.h>
main(int argc, char **argv)
{
long blen;
FBFR32 *ibuf;
/* tpinit() 连接TUXEDO */
ibuf = (FBFR32 *)tpalloc(FMLTYPE32,NULL,0);
Fchg32(ibuf,TA_OPERATION,0,"GET",0);
Fchg32(ibuf,TA_CLASS,0,"T_MACHINE",0);
printf("Query th T_MACHINE class before:/n");
Fprint32(ibuf);
printf("/n");
if (tpcall(".TMIB",(char *)ibuf,0,(char **)&amp;ibuf,&amp;blen,0)== -1){
printf("tpcall(.TMIB) failed:%s/n",tpstrerror(tperrno));
Fprint32(ibuf);
Return(-1);
}
printf("Query th T_MACHINE class after:/n");
Fprint32(ibuf);
printf("/n");
tpfree((char *)ibuf);
tpterm();
return(0);
}
因为Admin API是基于FML32类型的数据,所以要包含TUXEDO系统头文件“fml32.h"。
因为Admin API要用一些预定义的域去访问MIB信息,如TA_OPERATION和TA_CLASS,所以要包含TUXEDO系统头文件“tpadm.h"。
用tpinit()连接TUXEDO系统。
分配一个FML32数据缓冲。
在本例中,我们通过“GET(ing)”得到“MACHINE”的信息。
用tpcall()调用.TMIB服务。
显示结果。
释放FML32缓冲。
切断连接。
本例的输出(域名和域值)
TA_ERROR 0
TA_MORE 0
TA_OCCURS 1
TA_PERM 438
TA_GID 302
TA_MAXACCESSERS 20
TA_MAXCONV 1
TA_MAXGTT 20
TA_MAXWSCLIENTS 0
TA_MINOR 6000
TA_RELEASE 60
TA_SPINCOUNT 0
TA_TLOGSIZE 100
TA_TMNETLOAD 0
TA_UID 261
TA_MAXCLCACHE 100
TA_CLASS T_MACHINE
TA_STATE ACTIVE
TA_APPDIR /usr/apps/atmapp
TA_CMPLIMIT MAXLONG,MAXLONG
TA_ENVFILE /usr/apps/atmapp/ENVFILE
TA_PMID lcspn1
TA_TLOGDEVICE /usr/apps/atmapp/logs/TLOG
TA_TLOGNAME TLOG
TA_TUXCONFIG /usr/apps/tuxconfig
TA_TUXDIR /usr/tuxedo
TA_TYPE RS6000
TA_ULOGPFX /usr/apps/atmapp/logs/ULOG
TA_LMID SITE1
其他Admin API域和错误处理
除基本的域外,其他一些Admin API域在管理MIB信息时也非常有用。如:
在一个大应用中,server节会包含很多条目,以下3个域在取得这些信息时很有用。
TA_OCCURS
在请求时,表示需要得到信息的行数。
在返回结果后,表示成功得到信息的行数。
TA_CURSOR
表示上一次GET操作停止的位置。配合TA_OPERATION的GETNEXT属性,可以顺序遍历MIB。
TA_FILTER
客户端程序可以通过该域得到一个特定域信息
使用Admin API发生错误时,在回应缓冲中会带回来自MIB的错误信息
TA_ERROR
返回一个长整形操作结果值,参见诊断信息
TA_STATUS
用文本格式描述错误
TA_BADFLD
如果有一个域发生错误,用一个长整形值描述出错的FML32域
代码范例
/* 得到前3项 */
long n=3;
Fchg32(sendbuf,TA_OPERATION,0,"GET",0);
Fchg32(sendbuf,TA_CLASS,0,"T_SERVER",0);
Fchg32(sendbuf,TA_OCCURS,0,n,0);
Fchg32(sendbuf,TA_CURSOR,0,NULL,0);
/* 打印rpbuf中返回值*/
ret = tpcall(".MIB",(char *)sendbuf,0,(char **)&amp;recvbuf,&amp;len,0);
/* 如果出错打印TA_ERROR和TA_STATUS*/
if ( ret == -1 &amp;&amp;
tperrno == TPESVCFAIL){
Fget32(recvbuf,TA_ERROR,0,(char *)&amp;ta_error,NULL);
Ta_status=Ffind32(recvbuf,TA_STATUS,0,NULL);
Printf("Failure:%ld,%s/n",ta_error,ta_status);
}else
Fprint32(recvbuf);
/* 从recvbuf传递TA_CURSOR,得到下3项*/
Fget(recvbuf,TA_CURSOR,0,cursor,0);
Fchg32(sendbuf,TA_OPERATION,0,"GETNEXT",0);
Fchg32(sendbuf,TA_CURSOR,0,cursor,0);

tpadmcall()
tpadmcall(FBFR32 *inbuf, FBFR32 **outbuf, long flags)
用法:
Unbooted App
Unconfigured App
用户是管理员,用于SET一个NEW T_RESOURCE类,然后定义一个初始配置给应用
Unbooted App
Configured App
在有权限的UID/GID情况下,GET并SET任何TM_MIB(5)中任何类的任何属性。
Booted App
Unattached Process
在有权限的UID/GID情况下或用户是管理员,当返回值不是ACTIVE时,可以GET任何TM_MIB(5)中有合适权限的任何类的任何属性。
Booted App
Attached Process
权限在tpinit()时由授权key决定,可以GET任何TM_MIB(5)中有合适权限的任何类的任何属性。

代码范例:
#include <stdio.h>
#include <fml32.h>
#include <atmi.h>
#include <tpadm.h>
main(int argc , char **argv)
{
FBFR32 *ibuf;
/* tpinit() 连接TUXEDO */
ibuf = (FBFR32 *)tpalloc(FMLTYPE32,NULL,0);
Fchg32(ibuf,TA_OPERATION,0,"GET",0);
Fchg32(ibuf,TA_CLASS,0,"T_DOMAIN",0);
printf("Query th T_DOMAIN class before:/n");
Fprint32(ibuf);
printf("/n");
if (tpadmcall(ibuf,&amp;ibuf,0)== -1){
printf("tpadmcall() failed:%s/n",tpstrerror(tperrno));
Fprint32(ibuf);
Return(-1);
}
printf("Query th T_MACHINE class after:/n");
Fprint32(ibuf);
printf("/n");
tpfree((char *)ibuf);
tpterm();
return(0);
}


安全 Security
简介
TUXEDO在其系统框架中集成了进程间通讯安全功能。在商业应用中可以由用户决定安全级别。
本节中,我们将讨论TUXEDO提供的不同的安全保障能力和应用实现的必要步骤。



本节要点
* 概念
* 管理文件和命令
* ubbconfig
* API使用说明
* 代码范例
概念
TUXEDO系统在第一次ATMI调用时——tpinit()就进行安全工作。
安全级别信息先传入tpinit(),在公告牌上进行校验,然后用AUTHSVR进行二次检查。如果验证通过,tpinit()允许客户端连上TUXEDO系统。
TUXEDO API tpchkauth()用来决定应用的安全级别。下表是各安全级别认证需要的资源。
tpchkauth()的返回值
管理文件设置
UBBCONFIG的设置
TPNOAUTH

TPSYSAUTH
SECURITY APP_PW
TPAPPAUTH
tpusr
tpgrp
tpacl
SECURITY USERAUTH
ACL
MANDATORY_ACL
AUTHSVC AUTHSVC



相关管理命令
组命令
tpgrpadd -g GID groupname
tpgrpdel groupname
tpgrpmod -g GID -n new_groupname groupname
入口在$APPDIR/tpgrp
用户命令
tpusradd -u UID -g GID -c clntname usrname
tpusrdel -c clntname
tpusrmod -u UID -g GID -c clntname -l newlogin -n newclntname -p usrname
入口在$APPDIR/tpusr
ACL命令
tpacladd -g GID entity_name
tpacldel entity_name
tpaclmod -g GID entity_name
入口在$APPDIR/tpacl
简要说明
以上管理命令维护AUTHSVR的安全入口。只有安全级别要求到ACL(Access Control List)时,这些操作过程才是必须的。
AUTHSVR对每一个用户进行认证。当客户端进程调用tpinit()去连接应用时,发生以下过程:
AUTHSVR校验用户名,客户端名和密码
当成功,AUTHSVR提供一不可伪造的应用key
每次交易请求时,客户端都要提交此应用key

ubbconfig 有关安全的部分
*RESOURCES
AUTHSVC "..AUTHSVC"
SECURITY "ACL"
*SERVERS
AUTHSVR SVRGRP="AUTHGRP" SRVID=100
RESTART=Y MAXGEN=2 GRACE=0
CLOPT="-A"
AUTHSVR提供的交易名字叫“..AUTHSVC”
SECURITY设置了安全的级别

客户端代码范例
#include "atmi.h"
int ConnectToTuxedo()
{
FBFR *f;
TPINIT *tpinfo;
char *passwd2="penquin";
int do_auth = 0,no_auth = 0;
do_auth = tpchkauth();
switch(do_auth)
{
case -1:
printf("tpchkauth()err:%s",tpstrerrno(tperrno));
return(-1);
case TPNOAUTH:
no_auth = 1;
break;
case TPSYSAUTH:
tpinfo = (TPINIT *)tpalloc("TPINIT", NULL, 0);
if (tpinfo ==NULL)
{
printf("tpchkauth()err:%s",tpstrerrno(tperrno));
return(-1);
}
break;
case TPAPPAUTH:
tpinfo = (TPINIT *)tpalloc("TPINIT", NULL, TPINITNEED(15));
if (tpinfo ==NULL)
{
printf("tpchkauth()err:%s",tpstrerrno(tperrno));
return(-1);
}
tpinfo->datalen=strlen(passwd)+1;
memcpy((char *)&amp;tpinfo->data, passwd2, tpinfo->datalen);
break;
default:
printf("Invalid security setting %d/n",do_auth);
return(-1);
}
if (!no_auth)
{
strcpy(tpinfo->usrname,"tuxedo");
strcpy(tpinfo->passwd,"hello");
strcpy(tpinfo->grpname," ");
}
if ((tpinit(TPINIT *)tpinfo))==-1
{
printf("Failed to join application/n");
return(-1);
}
}
tpchkauth()返回TPNOAUTH,TPSYSAUTH,TPAPPAUTH或错误用以决定加密强度。
tpalloc()将分配一个TPINIT结构,存储与公告牌对比的密码。
Struct TPINIT {
char usrname[MAXTIDENT+2];
char cltname[MAXTIDENT+2];
char passwd[MAXTIDENT+2];
char grpname[MAXTIDENT+2];
long flags;
long datalen;
long data;
}
tpalloc()还将根据TPINITNEED()分配一段空间存储用户密码。
用tpinit()与TUXEDO连接。


事件代理 Event Broker
简介
在事件代理出现前,所有的通讯由用户发起。通过事件代理,TUXEDO系统增加了另一种进程间通讯方式——通讯可以由事件发起。事件可以独立于客户端,促使其他活动发生。
事件代理搜寻并报告一些预定义的事件,如系统错误和用户定义错误。
在本节中,我们将研究事件监视模块,练习TUXEDO的'publish'和'subscribe'事件模块的程序设计。


本节要点
* ubbconfig范例
tpsubscribe和tpunsubscribe的代码范例
tppost的范例
概念
事件代理提供了这样一种通讯方式:一些进程可以发布消息给订阅了这些消息的进程或客户端。例如:服务可以在价格发生变化时发布信息,所有连接系统的客户端都可以收到信息。
事件代理只能执行一些该事件预定动作,这些动作包括:
* 调用交易(tpacall)
* 将请求送入一个可靠队列(tpenqueue)
* 用户通知之类(tpnotify)
* 记录日志到ULOG.mmddyy
* 执行系统调用
主要有2类事件:
* 系统 TUXEDO系统内部活动引起,如网络故障等
* 用户定义 应用中与业务流程有关的
触发事件的ATMI API是tppost()。
订阅和取消订阅的ATMI API是tpsubscribe(),tpunsubscribe()。

Subscribing &amp;
Unsubscribing ATMI
long tpsubscribe(char *eventexpr, char *filter, TPEVCTL *ctl, long flags)
进行订阅。返回订阅句柄,-1失败
char *eventexpr 表示事件的字符串,可以含有通配符*
char *filter 一个布尔表达式,决定是否收到消息。
TPEVCTL ctl 一个描述事件代理将进行的动作
flags 可以是[TPNOTIME|TPSIGRSTRT|TPNOBLOCK]
int tpunsubscribe(long subscription, long flags)
取消订阅
long eventexpr tpsubscribe()返回的句柄
flags 可以是[TPNOTIME|TPSIGRSTRT|TPNOBLOCK]
struct TPEVCTL
{
long flags;
char name1[32];
char name2[32];
TPQCTL qctl;
}
调用另一个交易
ctl->flags=TPEVSERVICE;
strcpy(ctl->name1,"SERVICENAME");
进入队列
ctl->flags=TPEVQUEUE;
strcpy(ctl->name1,"QSPACENAME");
strcpy(ctl->name2,"QUEUENAME");
ctl->qctl.flags=TPQREPLYQ;
strcpy(ctl->qctl.replyqueue,"RPLYQ");
通知
ctl=(struct TPEVCTL *)NULL;
int tppost(char *eventname, char *data, long len, long flags)
tpsubscribe()和tpunsubscribe()的范例代码
#include <atmi.h>
static long sub_serv;
int tpsvrinit(int argc, char **argv)
{
TPEVCTL evctl;
/* 连接TUXEDO系统——tpinit() */
evctl.flags=TPEVSERVICE;
strcpy(evctl.name1,"BANK_MANAGER");
sub_serv=tpsubscribe("BANK_TLR_WITHDRAWAL",
"AMOUNT>300.00",&amp;evctl,TPSIGRSTRT);
if (sub_serv == -1)
return(-1);
}
int tpsvrdone()
{
if (tpunsubscribe(sub_serv,TPSIGRSTRT)== -1)
{
printf("Error unsubscribing to service event/n");
}
}
建立一个服务调用订阅事件,被调用服务是BANK_MANAGER,当交易BANK_TLR_WITHDRAWAL的AMOUNT域的值大于300.00触发。
用tpunsubscribe()取消订阅。

tppost()的范例代码
void WITHDRAWAL(TPSVCINFO *transb)
{
......
if (amt > 300.00)
{
if ( (Fchg(transf,EVENT_NAME,0,"BANK_TLR_WITHDRAWAL",0)<0) ||
(Fchg(transf,EVENT_NAME,0,gettime(),0)<0 )||
(Fchg(transf,EVENT_NAME,0,(char *)&amp;amt,0)<0) ))
{
sprintf(emsg,"Fchg(event flds) failed :%s",Fstrerror(Ferror));
}else
if( tppost("BANK_TLR_WITHDRAWAL",(char *)transf,0L,
TPNOTRAN|TPSIGRSTRT)<0)
{
if (tperrno!=TPENOENT)
{
sprintf(emsg,"tppost() failed :%s",tpstrerror(tperrno));
}
}
if ( strcmp(emsg,"")!=0)
{
userlog("WARN:Event BANK_TLR_WITHDRAWAL not posted:%s"
,emsg);
strcpy(emsg,"");
}
}
}
从传入FML中分离交易金额;增加交易过滤规则:金额>300.00,给FML域赋值;调用tppost()。




Ubbconfig相应改变
*SERVERS
TMSYSEVT SRVGRP=EVTGRP1 SRVID=100
RESTART=Y MAXGEN=5 GRACE=3600
CLOPT="-A -- -f tmsysevt.dat"
TMUSREVT SRVGRP=EVTGRP1 SRVID=150
RESTART=Y MAXGEN=5 GRACE=3600
CLOPT="-A -- -f tmusrevt.dat"
TMUSREVT SRVGRP=EVTGRP1 SRVID=200
RESTART=Y MAXGEN=5 GRACE=3600
CLOPT="-A -- -S -p 120"
TMSYSEVT 系统事件代理服务进程
TMUSREVT 用户事件代理服务进程
-f 指定了包含订阅信息的数据文件
-S 表示有第二事件代理,-p决定其轮循时间(单位:秒)

消息队列 Queued Message

本节要点
* 定义
* 基本队列
* 队列设定—qmadmin
* 高级队列
* 交易和管道
* ubbconfig
* 代码范例

可靠队列
当进程通过消息方式进行通讯时,消息在被取用前存储的地方称为消息队列。这些队列是一些存储空间,或者是内存(IPC消息队列),或在硬盘上。内存中的队列在写硬盘前可以清除;这样,在主机故障时,就有丢失信息的风险。基于硬盘的队列可以在主机或网络瘫痪时可靠地保存信息,代价是读写硬盘的开销。
商业上用队列方式使任务可以同步完成。一般地,商业系统需要保证系统总是稳定可靠,良好地完成任务。传统上是使用昂贵的容错系统达到此目标,花费主要是在冗于硬件上,使用队列,往往只要复制部分系统就能达到此效果。



概念
作为请求/应答通讯方式的一种替代,可靠队列允许商业应用通过同步或时序方式使用可靠存储队列进行通讯。BEA TUXEDO /Q提供了这种机制。
其特性提供优点如下:
* 可靠传递
* 同步的、自由处理
* 审计、恢复
/Q ATMI通过按照2段式XA事务协议操作,保证可靠的传输,并且有内建的错误处理能力处理意外情况。

基本队列
/Q 提供的API简单而功能强大,有以下两个函数:
* tpenqueue() - 将消息置入队列
* tpdequeue() - 从队列中得到消息
队列由BEA TUXEDO管理员创建,定义队列并指定大小。队列全部位于队列空间,队列空间的名字是函数参数之一。每个队列都有一个名字,函数通过名字调用队列。
tpenqueue()参数如下:
* 队列空间名
* 队列名
* 包含置入队列信息的结构
* 置入队列的数据缓冲
* 长度
* 控制标志
tpenqueue(qspace,qname,control_info,buffer,len,flags)
tpdequeue()参数如下:
* 队列空间名
* 队列名
* 包含取队列信息的结构
* 取队列的数据缓冲
* 长度
* 控制标志
tpdequeue(qspace,qname,control_info,buffer,len,flags)

qmadmin范例
qmadmin是一个命令行工具,TUXEDO /Q的一个部分,使管理员可以建立基于硬盘的的队列;qmadmin用于在设备上建立、初始化、列出和删除队列和队列空间。
$qmadmin
QMCONFIG=/usr/apps/atmapp/QUE
>crdl /usr/apps/atmapp/QUE
Starting Offset :0
Size in disk pages:400
Created decice /usr/apps/atmapp/QUE,offset 0,size 400
>qspacecreate
Queue space name:QSPACE
IPC Key for queue space:62639
Size of queue space in disk space:100
Number of queues in queue space:6
Number of concurrent transaction in queue space:4
Number of concurrent processes in queue space:9
Number of messages in queue space:3
Error queue name:errque
Initialize exter/nts(y,n[default=n]):y
Blocking factor[default=16]:16
>qopen QSPACE
>qcreate
Queue name:DEPOSIT
Queue order(priority,time,fifo,lifo):fifo
Out-of-ordering enqueuing(top,msgid):none
Retries[default=0]:2
Retry dela in seconds[default=0]:30
High limit for queue capacity warning:80%
Reset(low)limit for queue capacity warning:0%
Queue capacity command:
No default queue capacity command
Queue 'DEPOSIT' created
>qcreate
Queue name:REPLYQ
Queue order(priority,time,fifo,lifo):fifo
Out-of-ordering enqueuing(top,msgid):none
Retries[default=0]:2
Retry dela in seconds[default=0]:30
High limit for queue capacity warning:80%
Reset(low)limit for queue capacity warning:0%
Queue capacity command:
No default queue capacity command
Queue 'REPLYQ' created
说明:
用crdl命令在/usr/apps/atmapp/QUE上建立一个400页的设备
用qspacecreate命令在设备上建立一个100页的队列空间QSPACE,有6个队列。
用qopen命令打开队列空间QSPACE。
用qcreate命令在队列空间QSPACE上建立队列DEPOSIT,FIFO方式,消息可以取出2次。同样建立队列REPLYQ。

高级队列
每个队列都有与之相关的一些控制信息;其中绝大多数内容由应用设定,但是有些由BEA TUXEDO队列软件直接设定。
队列次序
缺省的,消息进出队列的次序由管理员确定,一般是先入先出(FIFO-first in first out);但有时消息不需要立即处理,这样就需要其他的队列次序。BEA TUXEDO提供了几种方案解决之,有:
* 按优先级
* 按时序
* 先进先出
* 后进先出
管理员甚至可以合并使用上述几种方式决定队列次序。
按时释放
当一个消息进队列时,程序员可以决定其在某时间前不可出队列。这个时间可以是一个定值(如:1月7号下午2点)或相对于入队列的时间。当程序试图出队列时,那些‘还没到时间’的消息是不可见的。例:
control_info->deq_time=3600;/* 3600秒后才可以出队列*/
control_info->flags=TPQTIME_REL;/* 表示相对时间值被设定*/
TPQCTL结构
TPQCTL结构用来控制一个消息如何进/出队列
struct tpqctl{
long flags;
long deq_time;
long priority;
long diagnostic;
char msgid[TMMSGIDLEN];
char corrid[TMCORRIDLEN];
char replyqueue[TMQNAMELEN+1];
char failurequeue[TMQNAMELEN+1];
CLENTID cltid;
long urcode;
long appkey;
};
tpenqueue的flags有如下可能:
TPNOFLAGS,TPQPRIORITY,TPQCORRID,[TPQTOP|TPQBEFOREMSGID],[TPQTIME_ABS|TPQTIME_REL] , TPQREPLYQ,TPQFAILUREQ
tpdequeue的flags有如下可能:
TPNOFLAGS,TPQWAIT,[TPQGETBYMSGID|TPQGETBYCORID]
本节中有定义:
typedef struct tpqctl TPQCTL;
优先级
一条消息可以被设置一个优先级;优先级决定消息相对于队列中其他消息的位置。高优先级的消息较靠近队列头,可以较早出队列。例:
control_info->priority=100; /*设入队列优先级为最高级*/
control_info->flags=TPQPRIORITY; /* 表示优先级的值已经设定*/
返回和错误队列
在将消息入队列前,程序可以定义两个队列:返回队列和错误队列。当消息出队列时,这些队列中存有原消息的处理结果:返回或错误消息。
相关标识
应用可以在消息上加一个‘标记’,当消息被从一个队列移动到另一个队列并被应用的不同部分处理时可以识别它。这些标记被称为‘相关标识’。
超次序
虽然队列被定义了一个固定的出/入次序,但有时应用需要超越这个次序。BEA TUXEDO的队列工具允许管理员配置程序入队列时可以超越次序的队列。
* 可以将一条消息置于队列头
* 可以将一条消息置于特定消息前
错误诊断
如果tperrno被设成TPEDIAGNOSTIC,则TPQCTL结构中的诊断域将被设成一个错误状态,有以下:
* QMEINVAL 调用时使用了非法标志值
* QMEDADMSGID 非法错误消息ID
* QMENOMSG 队列没有可以取出的消息
* QMEINUSE 队列中有消息,但现在不可用

事务和管道
事务
事务是一种保证一系列操作全部成功或全部失败的机制;通常用来保证对数据库的多次操作全部完成。
BEA TUXEDO可以协调本队列修改、其他队列修改和数据库系统操作。当程序调用tpdequeue()将一条消息出队列时,事实上消息仅在程序事务确认时才从队列中除去。如果事务回滚或超时,消息仍在队列中;可以再次操作。系统从而有效地保障该消息仅被处理一次。
TMQUEUE是一个BEA TUXEDO系统提供的当程序调用tpenqueue()和tpenqueue()时将消息入、出队列的服务。tpenqueue()和tpenqueue()的第一个参数是队列空间名;该名字必须由TMQUEUE的一个交易发布过。
管道
TMQFORWARD是BEA TUXEDO提供的将消息通过调用tpenqueue()将消息前转的服务。
消息将被发送到一个有与读出队列名匹配的交易的服务。消息将在一个事务中出队列并送给服务。如果交易失败,事务回滚、消息将被送回队列,可以重试的次数决定于队列配置;如果达到了限制次数,消息将送入队列空间的错误队列。
ubbconfig的相应改变
*GROUPS
QUE1 LMID=SITE1 GRPNO=2
TMSNAME=TMS_QM TMSCOUNT=2
OPENINFO="TUXEDO/QM:/apps/atmapp/QUE:QSPACE"
*SERVERS
TMQUEUE SRVGRP=QUE1 SRVID=1
CLOPT="-s QSPACE:TMQUEUE -"
TMQFORWARD SRVGRP=QUE1 SRVID=5
CLOPT="-- -I 2 -q DEPOSIT"
说明:
每个队列空间需要单独创建一个组,本例中为QUE1。TMSNAME是事务管理服务的名字。TMCOUNT决定最少启动几个TMS_QM服务。
TMQUEUE是处理tpenqueue()将请求置入队列的/Q服务。TMQFORWARD是将请求出队列并通过tpcall()将请求送相应的交易。-i决定再次读队列前应该延迟的秒数。-q决定前转请求的来源队列。
客户端代码范例
#include <stdio.h>
#include <atmi.h>
main()
{
char *reqstr;
long len;
TPQCTL qctl;
/* 用tpinit()连接TUXEDO*/
qctl.flags = TPQREPLYQ;
strcpy(qctl.rplyqueue,"RPLYQ");
if ( tpenqueue("QSPACE","TOUPPER",&amp;qctl,reqstr,0,0)== -1)
{
printf("tpenqueue(TOUPPER):%s/n",tpstrerror(tperrno));
if(tperror == TPEDIAGNOSTIC)
{
printf("Queue manager diagnostic %ld/n",qctl.diagnostic);
}
tpfree(reqstr);
tpterm();
exit (-1);
}
sleep(10);
qctl.flags = TPQWAIT;
if (tpdequeue("QSACE", "REPLYQ",&amp;qctl,&amp;reqstr,&amp;len,TPNOTIME) == -1)
{
printf("tpdequeue(REPLYQ): %s/n", tpstrerror(tperrno));
if (tperrno == TPEDIAGNOSTIC)
{
printf("Queue manager diagnotic %ld/n", qctl.diagnostic);
}
tpfree(reqstr);
tpterm();
exit(-1);
}
printf("after: %s/n",reqstr);
tpfree(reqstr);
tpterm();
return (0);
}
会话 Conversations

本节要点
* 简介
* 定义
* ATMI
* UBBconfig
简介
作为对呼叫/应答方式的补充,TUXEDO提供了一种称为会话的通讯方式。该方式用于客户端和服务端需要进行大量、多次数据传输并保持连接时。在一个会话过程中双方会有多次发送和接收。例如,一对客户端/服务端之间传诵一个大的数据库查询结果游标时,需要进行几次传输。
在呼叫/应答方式中,所有的数据必须在一次通讯中传递,不保留任何中间状态信息。在会话模式中,通讯双方使用了一种“半双工”协议。一个进程只能处于发送数据或接收数据状态之一。该通讯协议中,状态信息与数据一同传送。
会话被用来传送大量数据,如:
* 报表
* 数据/图形文件传输
* 大型数据库查询
此模式必须进行另外的ATMI编程才能实现。以下函数协助实现此种连接:
* tpconnect() 建立连接
* tpsend() 发送信息
* tprecv() 接收信息
* discon() 撤消连接(出错时)
在会话持续期间,客户端被绑定在服务上。不利之处是服务在会话期间不能响应其他请求。

ATMI
int tpconnect (char *svc, char *data, long len, long flag)
int tpsend( int cd, char *data, long len, long flag, long *revent)
int tprecev(int cd, char *data, long len, long flag, long *revent)
int tpdiscon(int cd )



范例
ubbconfig应作的改动
*RESOURCES MAXCONV 域内缺省最大会话数
MACHINES MAXCONV 本机器上最大会话数,可以超越*RESOURCES节定义的域内缺省最大会话数
*SERVERS CONV=Y 定义该服务是一个会话方式的服务。
ubbconfig的例子
*RESOURCES
MAXCONV 20
*MACHINES
lcspn1 TUXDIR="/usr/tuxedo"
MAXCONV=25
*SERVERS
audit SRVGRP=BANKB1 SRVID=1
CONV=Y
CLOPT="-A"
会话方式的客户端源程序
main(int argc, char *argv[])
{
int ret,cd; /* 循环计数器 */
char *buf; /* 数据指针 */
long len; /* 长度 */
long revent; /* tpsend 失败的事件方式 */
/* 连接TUXEDO - tpinit() */
if ( buf = (char *)tpalloc("STRING",NULL,1024)==NULL)
{
printf("tpaclloc():%s/n",tpstrerror(tperrno));
tpterm();
exit(-1);
}
if ( cd = tpconnect("AUDIT",NULL,0,TPSENDONLY)==-1)
{
printf("tpconnect():%s",tpstrerror(tperrno));
tpfree(buf);
tpterm();
exit(-1);
}
strcpy(buf, "humpty dumpty");
if (tpsend(cd , buf ,(long)strlen(buf), 0 , &amp;revent) == -1)
{
printf("tpconnect():%s",tpstrerror(tperrno));
}
strcpy(buf, "mickey mouse");
if (tpsend(cd , buf ,(long)strlen(buf), 0 , &amp;revent) == -1)
...
if (tpsend(cd , NULL , 0, TPRECVONLY , &amp;revent) == -1)
...
if ( tprecv(cd, &amp;buf , &amp;len, 0, &amp;revent) == -1 )
...
tpfree(buf);
tpterm();
}
连接TUXEDO域;
分配一个1K的ATMI缓冲;
使用tpconnect()连接名为'AUDIT'的一个会话交易;
客户端通过TPSENDONLY将通讯控制权交给服务端。此时无数据传送。返回的通讯描述符存储于cd,用来跟踪绑定在会话上的唯一服务过程;
数据首先被复制到ATMI缓冲中;
数据被发送到会话服务上;
第二部分数据被复制到ATMI缓冲中;
用tpsend()发送到会话服务上;
客户端用TPRECVONLY标志放弃控制权。此处调用tpsend()没有发送数据,客户端准备接收数据;
客户端用tprecv()接收数据。
会话方式的服务端源程序
void CONV(TPSVCINFO *rqst)
{
static state = SRECV;
long len, revent;
for ( ;
;)
{
switch(state)
{
case SRECV:
if ( tprecv(rqst->cd, &amp;buf, &amp;len, 0, &amp;revent ) == -1)
{
if ( tperrno == TPEEVENT &amp;&amp;
revent == TPEV_SENDONLY)
{
userlog("state change from receive to send");
state = SSend;
}else
{
tpreturn(TPFAIL, 0, rqst->data, 0, 0 );
}
}
break;
case SSEND:
strcpy(buf, "alldo
ne &amp;
protocol complete");
if ( tpsend(rqst->cd, buf, 0, 0, &amp;revent)==-1)
{
userlog("tpsend(%d):%s",revent,tpstrerror(tperrno));
}else
{
userlog("SEND MESSAGE");
}
state = SDONE;
break;
case SDONE:
tpfree(buf);
tpreturn(TPSUCCESS, 0, rqst->data, 0, 0);
break;


}
}
}
#define SRECV 1
#define SSEND 2
#define SDONE 3
以上宏定义在程序中用到;
当客户端刚连接交易时,状态被设为RECEIVE;
此部分代码是会话交易在RECEIVE状态中;
tprecv()用来接收客户端数据;
协议在以下情况把状态由RECEIVE转成SEND:
tprecv()返回-1
tperrno被设成TPEEVNT
revent被设成TPEV_SENDONLY
在状态变成SEND后,服务可以调用tpsend();
如果协议有“部分”失败,服务切断客户端连接去处理错误;
代码将会话交易状态转成Send;
使用tpsend()发送数据;
在一次数据传送后,服务状态被设成DONE;
注意tpreturn用来结束一个成功的会话;tpdiscon()用于出错时结束会话。
广播通知Unsolicited Notification

本节要点
* 定义
* ATMI
简介
一般情况下,客户端发起并控制通讯。TUXEDO额外提供了一种允许客户端接收消息的通讯方式。该通讯方式的发起方可以是其他客户端或服务。我们称之为广播通知。
有两种方式的广播通知:目标是一个客户端(通知);目标是多个客户端(广播)。
为接收此种非主动请求信息,客户端必须指定处理此种信息的回应函数。客户端通常使用信号传递处理信息。而不使用此种方式的客户端可以通过tpchkunsol(),或DIPIN方法处理此种信息。当任何TUXEDO ATMI API 被调用时,DIPIN被定义成此类信息的检查标志。
管理员使在系统出错时用此类信息通知客户端。此外,该类信息还有其他许多用途。
ATMI
int tpbroadcast(char *lmid, char *usrname, char *cltname, char *data, long length, long flags)
int tpnotify( CLTID *clentid, char *data, long length, long flags)
int tpchkunsol()
void *tpsetunsol( void (* disp) (char *data, long len, long flags)))()

范例
ubbconfig 中的相应信息
*RESOURCES NOTIFY DIPIN
TUXEDO 将用DIPIN方法与客户端进行广播通知方式的通讯。
客户端使用广播通知方式通讯的源代码
#include <atmi.h>
void main()
{
/*作为一个柜员客户端连接TUXEDO——tpinit()*/
if ( tpsetunsol(unsolfunc)==TPUNSOLERR)
{
printf("tpsetunsol():%s/n",tpstrerror(tperrno));
}
...
tpchkunsol();/*在一个轮循中*/
...
tpterm();
}
void unsolfunc(char *data,long len,long flag)
{
printf("Unsolicited message is %s",data);
return;
}
客户端连接TUXEDO域;
客户端登记回应函数,unsolfunc,当收到广播通知的信息时触发;
客户用tpchkunsol()端轮循处理信息;
接下来是回应函数的定义;
在本例中,广播通知的信息是一个字符串,客户端将其打印出来。
服务端广播通知消息的源代码
void UNSOL(TPSVCINFO *incoming)
{
char *data;
if (data = (char *)tpalloc("STRING",NULL,1024)==NULL)
{
userlog("Error allocating buffer");
}
strcpy(data,"This data will be sent to clents");
if (tpnotify(&amp;incoming->cltid,data,0,0) == -1)
{
userlog("tpnotify():%s",tpstrerror(tperrno));
}
if (tpbroadcast("SITE1",NULL,"TELLER",0,0)==-1)
{
userlog("tpbroadcast():%s",tpstrerror(tperrno));
}
tpreturn(TPSUCCESS,0,incoming->data, 0, 0);
}
广播通知信息必须使用ATMI缓冲,所以,先分配一个ATMI缓冲。
用tpnotify()发送消息给请求了UNSOL交易的客户端。
服务使用tpbroadcast()将同一消息发送到SITE1上所有以TELLER登录的用户。



工作站的客户端Workstation Client
简介
BEA TUXEDO 的/WS部分实际上是工作站扩展件。此前,所有的客户端平台都是运行着TUXEDO系统的UNIX,这就限制了TUXEDO的客户端只能运行于UNIX平台。在今天是不可思议的。
/WS通过以下几点突破了以上限制:
* 允许远端不需公告牌即可运行
* 不需要TUXEDO系统域资源
* 不限制客户端的平台
* 服务器上无进程对客户端的一对一的限制
突破这些限制后,服务器不再考虑客户端的表示,不必管理大量的客户端进程而专注于TUXEDO和应用服务,大大扩展了系统的可伸缩性。
本节中,我们开始研究/WS应用。

本节要点
* 定义
* 过程
* 改变ubbconfig
* 网络阻塞
* buildclient
概念
远程/WS客户端(WSC)可以是UNIX或WINDOWS客户端。所有的客户端与TUXEDO通过工作站监听进程(WSL-Workstation Listener)和工作站处理进程(WSH-Workstation Handler)进行通讯。
当客户端进行tpinit()或tpchkauth()调用时,进程读取本地环境变量WSNADDR。该变量应该与监听连接请求的WSL进程的地址相符。地址值设定在WSL可执行服务的CLOPT的参数中。
WSL进程处理请求,将WSC的网络地址通知WSH进程。WSH进程处理WSC与TUXEDO系统的进一步通讯。
WSH将请求发给合适的服务并将结果返回WSC。如果交易在远程机器上,WSH将请求发给BRIDGE,由它将请求前转到合适的节点。



ubbconfig的相应变化
*RESOURCES
NOTIFY DIPIN
*MACHINES
SITE1
...
MAXWSCLIENTS=150
...
SITE2
...
MAXWSCLIENTS=0
*SERVERS
WSL SRVGRP="BANKB1" SRVID=500 RESTART=Y
CLOPT="-A -
-n //lcspn1:3060
-d /dev/xti/tcp
-m 2 -M 7 -x 5 -I 5 -T 60"
通知客户端的方式设为“DIPIN”,使用Windows的消息仿UNIX信号,若消息为WM_TIMER则对应tpchkunsol()。
MAXWSCLIENTS表示该机最多允许连接的工作站数目。
工作站监听进程启动参数如下:
-n 指定交易请求连接TUXEDO应用环境的监听进程的主机名和端口号。格式如下:
//lcspn1 主机名
: 间隔符
3060 端口号
-d WSL和WSH用于传递ATMI数据的的设备
-m tmboot最少启动的WSH进程数
-M tmboot最多启动的WSH进程数
-x 每个WSH支持的工作站数
-I 工作站连接应用许可的最大耗时
-T 无响应连接许可时间

PC上的环境变量设置
set TUXDIR=C:/TUXEDO
set WSNADDR=//lcspn1:3060
set WSDEVICE=/dev/xti/tcp
set WSENVFILE= C:/ENV4WS
set WSTYPE=DIFF
set TMPDIR= C:/tmp
set WSRPLYMAX=64K
set APP_PW=HOMERUN
注意:WSNADDR可以是一些由逗号隔开的使用相同端口的地址,或由竖线隔开自由选择端口。例:
WSNADDR=//lcspn1:3050,//lcspn2:3050
WSNADDR=(//lcspn1:3050|//lcspn2:3050)
TUXDIR TUXEDO系统软件位置
WSNADDR WSL网络地址
WSDEVICE 网络设备
WSENVFILE 环境变量文件
WSTYPE 机器类型,控制编、解码
TMPDIR 存储返回的目录
WSRPLYMAX 应用返回缓冲内存大小
APP_PW 应用密码
编译:
buildclient -w -v -o atmclt -f atmclt.c
-w 表示是WS客户端,Windows将通过一个DLL去访问ATMI。
域 do
mains
简介
/Domain作为TUXEDO的一组件,使独立的TUXEDO应用可以进行通讯和共享资源。每个应用环境视作一个'domain'。这种结构有以下优点:
* 仍然可以访问远程其他域的数据
* 应用管理工作可以分散进行
* 资源可以根据计算的需要合适地分配
一个域可以跨越多台(个)机器或处理器。所有的客户端通过BB(Bulletin Board)了解所有的机器上提供的交易。BB间的一致性通过DBBL(Distinguished Bulletin Board Liaison)来保证。
通过/Domain,可以维护独立于主域的BB,可以设定那些交易可以响应其他机器。当一个远程域提出一个合法的交易请求时,/Domain将请求发送到被请求域并把返回送到请求进程。
以下介绍进行域间通讯时需修改的配置。

本节要点
* 概念解释
* 配置过程
——环境变量
——ubbconfig
——dmconfig
——dmloadcf

Domains
使用TUXEDO组件/DOMAINS时,需要对管理配置作一些改变。在以下例子中,会创建一个独立的测试应用环境(DOMAINID是TEST),它可以读取/请求另一个应用的交易(ProdCust)的数据。
服务GWTDOMAIN(GWT)负责响应域间通讯。GWADM和DMADM是处理管理交易和域服务的管理服务。这些服务必须配置在UBBCONFIG文件中。配置信息必须在远程和本地应用环境中定义。
服务GWTDOMAIN通过TCP/IP协议与其他域进行通讯。物理上远程的域的应用位置是透明的。
服务GWTDOMAIN是双向的:可以处理远程域发来的请求也可以向远程域发出请求。
除UBBCONFIG外,配置/DOMAINS还需要一些信息。这些信息在DMCONFIG文件中。DMCONFIG的文本文件通过BDMCONFIG编译成二进制文件。

过程
第一步:UBBCONFIG应作相应改动
为/DOMAIN建立的新组应该和其他应用组隔离开。其一用于管理,其他是网关服务。
UBBCONFIG
*RESOURCES
IPCKEY 49152
MAXACCESSERS 2
MAXSERVERS 25
MASTER SITE1
MODEL SHM
*MACHINES
class2 LMID=SITE1
TUXDIR="/usr/tuxedo"
APPDIR="/usr/apps/atmapp"
TUXCONFIG="/usr/apps/atmapp/atmapp.tux"
*GROUPS
LDMGRP LMID=SITE1 GRPNO=20
LGWGRP LMID=SITE1 GRPNO=30
#下一行用于‘prod'域
APP1 LMID=SITE1 GRPNO=10
*SERVERS
DMADM SRVGRP=LDMGRP SRVID=200
GWADM SRVGRP=LGWGRP SRVID=310
GWTDOMAIN SRVGRP=LGWGRP SRVID=320
#下一行用于‘prod'域
CUSTOMER CLOPT="-A" SRVGRP=APP1 SRVID=100
*SERVICES
#下一行用于‘prod'域
ProdCust
第二步:为域间请求创建DMCONFIG
下文的ASCII数据存在的文件一般称为DMCONFIG,由此生成的二进制格式文件称为BDMCONFIG。以下的DMCONFIG存在于“TEST“域,用来请求远程的”prod“域的”ProdCust“交易。
DMCONFIG on TESTdo
MAIN
*DM_LOCAL_DOMAINS
test GWGRP=LGWGRP
TYPE=TDOMAIN
DOMAINID="TEST"
DMTLOGDEV="/usr/apps/atmapp/logs/DLOG"
*DM_REMOTE_DOMAINS
production TYPE=TDOMAIN
DOMAINID="prod"
*DM_TDOMAIN
prod NWADDR="//lcspn1:3070"
NWDEVICE="/dev/xti/tcp"
TEST NWADDR="//lcspn2:3070"
NWDEVICE="/dev/xti/tcp"
*DM_REMOTE_SERVICES
ProdCust
*DM_LOCAL_SERVICES
第三步:创建DMCONFIG指定对域外提供的交易
下文的DMCONFIG位于域'prod',该域将向其他域提供可调用交易:ProdCust。
域‘prod’上的DMCONFIG
#本地域信息
*DM_LOCAL_DOMAINS
#LMID
production GWGRP=LGWGRP
#域描述:TDOMAIN即TUXEDOdo
MAINS
TYPE=TDOMAIN
#域的唯一标识符
DOMAINID="prod"
#交易的日志
DMTLOGDEV="/usr/apps/atmapp/logs/DLOG"
#远程域信息
*DM_REMOTE_DOMAINS
test TYPE=TDOMAIN
DOMAINID="TEST"
*DM_TDOMAIN
#地址和设备名
prod NWADDR="//lcspn1:3070"
NWDEVICE="/dev/xti/tcp"
TEST NWADDR="//lcspn2:3070"
NWDEVICE="/dev/xti/tcp"
*DM_REMOTE_SERVICES
*DM_LOCAL_SERVICES
#远程域可以使用的交易
ProdCust
第四步:设定环境变量
/DOMAIN进程需要额外的环境变量去访问/DOMAINS配置信息
export BDMCONFIG=/usr/apps/atmapp/atmapp.bdm
第五步:编译ubbconfig
本过程是从两个域中相同的UBBCONFIG生成二进制文件TUXCONFIG。在本例中,UBBCONFIG的信息位于'ubbconfig'。
tmloadcf -y ubbconfig
第六步:编译dmconfig
本过程是创建二进制DOMAINS配置文件,BDMCONFIG,在两个域中相同;而两者都有的文件‘dmconfig’内容是不同的。
dmloadcf -y dmconfig


小结
* /Domain的概念和如何使几个域间进行通讯。
- 2 -
71
11




来自:gzfrank, 时间:2002-5-16 12:59:00, ID:1104231
谢谢先!!
lsbfrank@163.com


 
真不错,谢谢.收藏.
 
顶部