blogliou 发表于 2004-01-09 17:13

AS/400开发经验点滴(五)-- 通用日志管理工具

AS/400开发经验点滴(五)
---- 通用日志管理工具

BLOG LIOU



八.通用日志管理工具

1.        引言

AS/400系统上有日志(JRN)和日志接收器(JRNRCV)目标对象,用来存放对数据库文件进行增删改等操作的日志记录。日志接收器是存放日志记录的具体地方,它可以是由一个无限增大的文件组成,也可以是由多个固定大小的文件组成。多个日志接收器文件形成日志接收器链,当当前ATTACHED的有限大小的日志接收器满了以后,系统会自动产生或由用户产生一个新的同样属性的接收器文件。

用CHGJRN命令可以改变产生新的日志方式,当Manage receivers( MNGRCV)选项选择*SYSTEM时,系统会自动产生新的日志接收器,当Manage receivers( MNGRCV)选项选择*USER时,则当日志接收器满了以后,需要由用户产生新的日志接收器。当Manage receivers( MNGRCV)选项选择*SYSTEM时,可以在Delete receivers(DLTRCV)选项里选择*YES来让系统自动删除已经被DETACH的日志接收器文件。

但如果我们希望定制保留固定个数的日志记录,或者保存若干天的日志记录,或者其他一些原因不能让系统自动删除日志接收器,那么我们就必须手工删除日志接收器,如果系统业务比较频繁,产生日志接收器量比较大,可能会很快使系统硬盘空间涨满,那么我们手工维护日志接收器的工作量很大。在一般的双机热备系统中比如MIMIX、OMS等都提供了日志管理功能,本文提供一个与这些软件日志管理功能类似的独立的一个通用日志管理工具,可以使你不需要依靠其他软件就可以独立地由程序来完成日志管理工作。

保留日志接收器,通常有两种方式,一种是按时间即天来保留,一种是按日志记录个数来保留。本文的例子是按日志记录个数来保留日志接收器的。但按照该例的方法也可以很容易实现按天来保留日志接收器。

2.日志管理原理

(1)        要由程序来实现日志管理,必须先用CHGJRN命令把日志属性中Manage receivers( MNGRCV)选项改为*USER。

(2)        如果Manage receivers( MNGRCV)属性已经设置为*USER,那么当前日志接收器超过其阀值大小后,系统会发送CPF7099的消息。程序根据这个消息知道当前日志接收器已经满了,需要产生一个新的日志接收器。这个消息是由系统发送到日志属性中Journal message queue(MSGQ)中所定义的消息队列里。通常日志该消息队列缺省为QSYSOPR。用CRTMSGQ命令创建一个叫TTJRNMSGQ的消息队列。并用该队列名用CHGJRN命令修改Journal message queue(MSGQ)的值。

(3)        把保留的日志个数设置成参数,保存在一个数据区域里,下例创建了一个保留1000万日志记录参数的数据区域:
CRTDTAARA   DTAARA(QGPL/TTDTA)
               TYPE(*CHAR)
LEN(10)
VALUE('0010000000')
这个参数可以由用户根据硬盘大小来调节,用CHGDTAARA命令可以改变这个参数。

(4)        在程序运行过程中,当产生新的日志接收器文件后,程序会计算最新日志接收器件的开始日志序号与最前一个日志接收器的开始日志序号差,并用这个差与数据区域中定义的保留最大日志记录个数相比较,当日志序号差超过最大日志记录个数,程序就会自动删除过量的日志接收器文件,并把最后一个删除日志接收器文件保存在叫LASTRCV的SAVF文件里,以维护硬盘空间不会增长。 下面是日志管理原理示意图:


jrn2.jpg

图日志管理示意

3.源程序

(1)        主调程序JRNMGR

用RCVMSG命令读TTJRNMSGQ消息队列,当有CPF7099消息时,先调用CHKJRNCL程序来产生新的日志接收器,然后再调用删除日志接收器程序,如果删除接收器不成功,主调程序等待一段时间后会继续调用删除日志接收器程序:

/*===================================================================*/
/*                                                                           */
/*   PROGRAM NAME    : JRNMGR                                       */
/*   CREATED BY      : BLOG LIOU                                        */
/*   DESCRIPTION   :                                                    */
/*===================================================================*/
             PGM
             DCL      VAR(&MSGID) TYPE(*CHAR) LEN(7)
             DCL      VAR(&RTCDCHK) TYPE(*CHAR) LEN(1)
             DCL      VAR(&JRNNAM) TYPE(*CHAR) LEN(10) +
                        VALUE('TTJRN’')      /* 测试日志TTJRN */
             DCL      VAR(&JRNLIB) TYPE(*CHAR) LEN(10) +
                        VALUE(‘QGPL’)
             DCL      VAR(&DJRNFLG) TYPE(*CHAR) LEN(1) VALUE('0')
             DCL      VAR(&DJRNRTN) TYPE(*CHAR) LEN(1)

             CHGVAR   VAR(&RTCDCHK) VALUE('0')

LOOP:
/* 条件满足时调用删除日志接收器程序 */
             IF         COND(&DJRNFLG *EQ + '1')) THEN(DO)
             CALL       PGM(DELJRNCL) PARM(&JRNNAM &JRNLIB +
                        &DJRNRTN)
             IF         COND(&DJRNRTN *EQ '0') THEN(CHGVAR +
                        VAR(&DJRNFLG) VALUE('0'))
             ENDDO

/* 读TTJRNMSGQ消息队列,调用产生新日志接收器程序*/
             RCVMSG   MSGQ(TTJRNMSGQ) RMV(*YES) MSGID(&MSGID)

             IF         COND((&MSGID *EQ 'CPF7099') *OR (&RTCDCHK +
                        *EQ '1')) THEN(DO)
             CALL       PGM(CHKJRNCL) PARM( &JRNNAM &JRNLIB +
                        &RTCDCHK)
             CHGVAR   VAR(&MSGID) VALUE(' ')
             IF         COND(&RTCDCHK *EQ '0') THEN(DO)
             CHGVAR   VAR(&DJRNFLG) VALUE('1') /* 设置执行删除接收器程序标志 */
             CLRMSGQ    MSGQ(TTJRNMSGQ)
             MONMSG   MSGID(CPF2357)
             ENDDO
             ENDDO

             DLYJOB      DLY(60)
             GOTO       CMDLBL(LOOP)
             ENDPGM

(2)        产生新的日志接收器程序CHKJRNCL

当主调程序从消息队列读到CPF7099的消息后,开始调用CHKJRNCL程序,来产生新的日志接收器。

/*===================================================================*/
/*   PROGRAM NAME    : CHKJRNCL                                       */
/*   CREATED BY      : BLOG LIOU                                        */
/*   CREATED DATE    :                                                   */
/*   DESCRIPTION   :                                                    */
/*===================================================================*/
             PGM      PARM( &JRNNAM &JRNLIB &RTCD)
             DCL      VAR(&JRNNAM) TYPE(*CHAR) LEN(10)
             DCL      VAR(&JRNLIB) TYPE(*CHAR) LEN(10)
             DCL      VAR(&RTCD) TYPE(*CHAR) LEN(1)

             CHGVAR   VAR(&RTCD) VALUE('0')
/*-------------------------------------------------------------------*/
/*产生新的日志接收器                        */
/*-------------------------------------------------------------------*/
             SNDMSG   MSG(&JRNNAM *TCAT '*GEN') TOUSR(MYUSR)
             CHGJRN   JRN(&JRNLIB/&JRNNAM) JRNRCV(*GEN)
             MONMSG   MSGID(CPF7013) EXEC(CHGVAR VAR(&RTCD) +
                        VALUE('1'))

END:      ENDPGM

(3)        删除日志接收器程序DELJRNCL

当产生新的日志接收器调用成功后,主调程序会调用删除过量日志接收器程序。

/*===================================================================*/
/*   PROGRAM NAME    : DELJRNCL                                       */
/*   CREATED BY      : BLOG LIOU                                        */
/*   CREATED DATE    :                                                   */
/*   DESCRIPTION   :                                                    */
/*===================================================================*/
             PGM      PARM( &JRNNAM &JRNLIB &RTNCDE)
             DCL      VAR(&RTNCDE) TYPE(*CHAR) LEN(1)
             DCL      VAR(&CURRCV) TYPE(*CHAR) LEN(10)
             DCL      VAR(&JRNRCV) TYPE(*CHAR) LEN(10)
             DCL      VAR(&RCVLIB) TYPE(*CHAR) LEN(10)
             DCL      VAR(&JRNNAM) TYPE(*CHAR) LEN(10)
             DCL      VAR(&JRNLIB) TYPE(*CHAR) LEN(10)
             DCL      VAR(&STRSEQ) TYPE(*DEC) LEN(10 0)
             DCL      VAR(&STRSEQ1) TYPE(*DEC) LEN(10 0)
             DCL      VAR(&STRSEQ2) TYPE(*DEC) LEN(10 0)
             DCL      VAR(&SNDMSG) TYPE(*CHAR) LEN(50)
             DCL      VAR(&JRNNAMPR) TYPE(*CHAR) LEN(5)
             DCL      VAR(&DELJRNSC) TYPE(*CHAR) LEN(10)
             DCL      VAR(&DELJRNS) TYPE(*DEC) LEN(10 0)
             DCL      VAR(&SNDMSG1) TYPE(*CHAR) LEN(10)

/*-------------------------------------------------------------------*/
/* Init,从TTDTA数据区域读保留日志个数      */
/*-------------------------------------------------------------------*/
             CHGVAR   VAR(&RTNCDE) VALUE('0')
             CHGVAR   VAR(&JRNNAMPR) VALUE(%SST(&JRNNAM 1 5))
             RTVDTAARADTAARA(TTDTA (1 10)) RTNVAR(&DELJRNSC)
             CHGVAR   VAR(&DELJRNS) VALUE(&DELJRNSC)

/*------------------------------------------------------------------------*/
/* 提取当前日志接收器第一个日志记录序号和接收器名 */
/*------------------------------------------------------------------------*/
             RTVJRNE    JRN(&JRNLIB/&JRNNAM) RCVRNG(*CURRENT) +
                        TOENT(*FIRST) RTNSEQNBR(&STRSEQ) +
                        RTNRCV(&CURRCV) RTNRCVLIB(&RCVLIB)

/*-------------------------------------------------------------------*/
/* 删除过量日志接收器                         */
/*-------------------------------------------------------------------*/
LOOP:       RTVJRNE    JRN(&JRNLIB/&JRNNAM) RCVRNG(*CURCHAIN) +
                        TOENT(*FIRST) RTNSEQNBR(&STRSEQ1) +
                        RTNRCV(&JRNRCV) RTNRCVLIB(&RCVLIB)

             IF         COND(&JRNRCV *EQ &CURRCV) THEN(GOTO +
                        CMDLBL(END))

             CHGVAR   VAR(&STRSEQ2) VALUE(&STRSEQ1 - &STRSEQ)

/* 日志序号差在定义参数范围内,不执行删除动作 */
             IF         COND(&STRSEQ2 *LT &DELJRNS) THEN(GOTO +
                        CMDLBL(END))

/*删除前先备份,LASTRCV重复使用*/
             DLTF       FILE(&RCVLIB/LASTRCV)
             MONMSG   MSGID(CPF2105)
             CRTSAVF    FILE(&RCVLIB/LASTRCV)
             SAVOBJ   OBJ(&JRNRCV) LIB(&RCVLIB) DEV(*SAVF) +
                        OBJTYPE(*JRNRCV) SAVF(&RCVLIB/LASTRCV) +
                        SAVFDTA(*YES)
             MONMSG   MSGID(CPF3770) /* No object saved */

/*删除日志接收器*/
             DLTJRNRCVJRNRCV(&RCVLIB/&JRNRCV)
             MONMSG   MSGID(CPF2105 CPF7023)

             CHGVAR   VAR(&SNDMSG) VALUE(&JRNRCV *BCAT 'Journal +
                        Receiver Deleted !')
             SNDMSG   MSG(&SNDMSG) TOUSR(MYUSR)
             GOTO       CMDLBL(LOOP)

END:      ENDPGM

最后把JRNMGR程序提交在QBATCH子系统下运行,就可以实现对日志的自动维护。

xuguopeng 发表于 2004-01-09 17:33

AS/400开发经验点滴(五)-- 通用日志管理工具

楼主,爱死你了。。这真是新年大礼啊

qingzhou 发表于 2004-01-09 17:55

AS/400开发经验点滴(五)-- 通用日志管理工具

楼主真牛!!!
多谢了!

nhxingliang 发表于 2005-12-26 18:06

下载回去好好研究一下.......................



:em02::em02::em02::em02:

afeng2000 发表于 2005-12-27 22:52

还真没用过,收藏.

qingzhou 发表于 2005-12-28 13:58

发表于: 2004-1-9 17:13   

以前没权限设精华,现在补设吧。

很好的工具。。。

wanghl 发表于 2005-12-31 08:42

多谢了,收藏先!

[ 本帖最后由 wanghl 于 2005-12-31 08:46 编辑 ]

狱中苍 发表于 2009-07-16 10:33

好贴留名

好贴留名

oldv 发表于 2009-07-20 10:15

lz id都注销了?

感慨。

blogliou 发表于 2011-12-15 17:39

找日志管理,翻到这个帖子。 回复楼上的同志, 我的ID仍然在。
页: [1] 2
查看完整版本: AS/400开发经验点滴(五)-- 通用日志管理工具