*用户空间USER SPACE的使用
用户空间USER SPACE,是AS400所提供进程间通讯的另一个机制,可以保存一块较大的持久化数据。常用的三大机制,DATA AREA在核心系统中用于控制参数的设置,例如批处理平台并发数控制,联机平台各种标志,以及全局内容在*LDA的跨PGM保存传递。DATA QUEUE可用于进程间传递消息数据,因核心系统设计上处理进程的隔离性而没有用到。USER SPACE则用于实现输出报文的灵活性,保存核心系统交易处理过程中,可能产生返回的凭证打印报文接口段。
USER SPACE最大长度可达16M,必须命名以持久化。由于在系统中用于暂存一笔联机交易需要返回的附加报文数据,因此对持久化其实没有要求,但性能要求很高,又不能互相影响。于是将USER SPACE建立在QTEMP中。这样不同JOB各自有一份使用,而且QTEMP数据系统应该是在内存中建立的,恰好符合要求。
那么程序中如何访问呢,可以看实际使用的例子。
创建USER SPACE,名称为QTEMP/JOBADDUS。
-
PGM PARM(&SPCLEN)
-
INCLUDE SRCMBR(CLHD) SRCFILE(DSCPPGM)
-
DCL VAR(&PASSPCNM) TYPE(*CHAR) LEN(20)
-
DCL VAR(&SPCATTR) TYPE(*CHAR) LEN(10)
-
DCL VAR(&SPCLEN) TYPE(*UINT) LEN(4)
-
DCL VAR(&SPCVALUE) TYPE(*CHAR) LEN(1)
-
DCL VAR(&SPCAUTH) TYPE(*CHAR) LEN(10)
-
DCL VAR(&SPCTEXT) TYPE(*CHAR) LEN(50)
-
CHGVAR VAR(&PASSPCNM) VALUE('JOBADDUS QTEMP ')
-
CHGVAR VAR(&SPCAUTH) VALUE('*CHANGE')
-
CHGVAR VAR(&SPCTEXT) VALUE('附加报文用户空间')
-
CHGVAR VAR(&SPCVALUE) VALUE(X'00')
-
CALL PGM(QUSCRTUS) PARM(&PASSPCNM &SPCATTR +
-
&SPCLEN &SPCVALUE &SPCAUTH &SPCTEXT)
-
MONMSG MSGID(CPF9870)
-
ENDPGM
因为JOB结束时QTEMP自动释放,而JOB不结束的话USER SPACE可以重复使用,因此不需要人为去删除这个USER SPACE。
使用这个USER SPACE,会有两种情况。
一是交易运行过程中,产生需要附加的打印接口数据,这时候调用下面的程序记录进USER SPACE,注意,同时将已附加长度写进*LDA记录。另一种情况是组返回报文时,读取数据打包进报文,这个用的是后续的USER SPACE指针操作。
-
#include <stdio.h>
-
#include <string.h>
-
#include <arpa/inet.h>
-
-
#include "dscppgm/cpyrgt_h"
-
#include "config_h"
-
#include "msginfo_h"
-
#include "opdtaac_h"
-
-
extern void JOBUSPTR(char **usptr);
-
extern void fill_str(char *buf, const char *str, int len);
-
extern int get_output_arrays_count(oa_otct*);
-
extern int set_otlen(int len);
-
-
/* parm1 MESG
-
parm2 ITNAME 10A
-
parm3 ITCNT 2B hostorder
-
parm4 ITPLEN 2B hostorder
-
parm5 ITBUF ITCNT*ITPLEN
-
*/
-
int main(int argc, char **argv)
-
{
-
oa_otct oa;
-
rpg_msg_info *rpginfo;
-
int olen, tlen;
-
unsigned short pcnt, plen, tmp;
-
char *obuf, *itbuf;
-
char *itnm;
-
char linebuf[LINENO_LEN+1];
-
-
if (argc<2)
-
return -1;
-
rpginfo=(rpg_msg_info *)argv[1];
-
if (argc!=6)
-
{
-
fill_str(rpginfo->msgflnm, __FILE__, FILENM_LEN);
-
sprintf(linebuf, "%6d", __LINE__);
-
fill_str(rpginfo->msgline, linebuf, LINENO_LEN);
-
fill_str(rpginfo->msgid, "EPLMNOPCK ", MSG_ID_LEN);
-
fill_str(rpginfo->msgtext, "组附加报文接口不正确", MSG_TEXT_LEN);
-
fill_str(rpginfo->msgotds, "", MSG_TEXT_LEN);
-
return -1;
-
}
-
itnm=argv[2];
-
pcnt=*(unsigned short *)argv[3];
-
plen=*(unsigned short *)argv[4];
-
itbuf=argv[5];
-
-
JOBUSPTR(&obuf);
-
get_output_arrays_count(&oa);
-
olen=oa.ot_len;
-
obuf += olen;
-
-
tlen = olen + ITNAME_SIZE + ITCNT_SIZE + ITPLEN_SIZE
-
+ (pcnt==0 ? plen : pcnt*plen);
-
if (tlen > DAT_MAX_LEN)
-
{
-
char errbuf[MSG_TEXT_LEN];
-
-
fill_str(rpginfo->msgflnm, __FILE__, FILENM_LEN);
-
sprintf(linebuf, "%6d", __LINE__);
-
fill_str(rpginfo->msgline, linebuf, LINENO_LEN);
-
fill_str(rpginfo->msgid, "EPLMNOLEN ", MSG_ID_LEN);
-
sprintf(errbuf, "组附加报文时长度%d + %d超过最大长度%d",
-
olen, tlen-olen, DAT_MAX_LEN);
-
fill_str(rpginfo->msgtext, errbuf, MSG_TEXT_LEN);
-
fill_str(rpginfo->msgotds, "", MSG_TEXT_LEN);
-
return -1;
-
}
-
-
fill_str(obuf, itnm, ITNAME_SIZE);
-
obuf += ITNAME_SIZE;
-
tmp = htons(pcnt);
-
memcpy(obuf, &tmp, ITCNT_SIZE);
-
obuf += ITCNT_SIZE;
-
tmp = htons(plen);
-
memcpy(obuf, &tmp, ITPLEN_SIZE);
-
obuf += ITPLEN_SIZE;
-
memcpy(obuf, itbuf, pcnt==0 ? plen : pcnt*plen);
-
-
set_otlen(olen);
-
return tlen;
-
}
这个程序将一个报文接口,以ITNAME接口名,ITCNT接口数组条数,ITLEN接口单条长度,ITBUF接口数据的方式,打包记录进USER SPACE。其中,JOBUSPTR用于获取USER SPACE的指针,然后就像普通内存一样操作。下面就是JOBUSPTR的程序。
-
PGM PARM(&USPTR)
-
INCLUDE SRCMBR(CLHD) SRCFILE(DSCPPGM)
-
DCL VAR(&PASSPCNM) TYPE(*CHAR) LEN(20)
-
DCL VAR(&USPTR) TYPE(*PTR)
-
CHGVAR VAR(&PASSPCNM) VALUE('JOBADDUS QTEMP ')
-
CALL PGM(QUSPTRUS) PARM(&PASSPCNM &USPTR)
-
ENDPGM
核心系统中的用法到此为止。实际上,USER SPACE相关的命令和调用有不少,修改内容的方式除了获取指针,还可以用QUSRTVUS获取USER SPACE内容,QUSCHGUS修改USER SPACE内容。这两个调用以字符串的形式操作。遗憾的是,CL对USER SPACE的支持较少,需要用到的话自己写程序扩充吧。
阅读(2255) | 评论(0) | 转发(1) |