亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問(wèn)板塊 發(fā)新帖
樓主: pacman2000
打印 上一主題 下一主題

一個(gè)程序員在AS400銀行核心系統(tǒng)開發(fā)中的技術(shù)總結(jié) [復(fù)制鏈接]

論壇徽章:
0
21 [報(bào)告]
發(fā)表于 2015-08-20 01:15 |只看該作者
本帖最后由 RAIITSMXH 于 2015-08-20 01:17 編輯

AS400就算國(guó)企不用了,外企也還用,國(guó)內(nèi)不會(huì)沒有工作,估計(jì)到時(shí)候能做400工作的都是技術(shù)過(guò)硬的忠實(shí)的400愛好者;
關(guān)于去‘IOE',阿里巴巴可以做到,銀行未必可以,拭目以待,就算最終做到了,那最起碼要5-10年吧

論壇徽章:
5
2015亞冠之阿爾艾因
日期:2015-08-10 02:23:34操作系統(tǒng)版塊每日發(fā)帖之星
日期:2015-08-13 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:1715-16賽季CBA聯(lián)賽之山西
日期:2016-04-13 02:36:59操作系統(tǒng)版塊每日發(fā)帖之星
日期:2016-04-14 06:20:00
22 [報(bào)告]
發(fā)表于 2015-08-21 01:59 |只看該作者
*多成員表

    銀行核心系統(tǒng)通常生命周期在10年左右,現(xiàn)在隨著銀行系統(tǒng)的數(shù)量和復(fù)雜度增加,系統(tǒng)的生命期也有逐漸變長(zhǎng)的趨勢(shì)。通常核心系統(tǒng)上線時(shí),很多數(shù)據(jù)表的記錄數(shù)并不太多,而當(dāng)系統(tǒng)運(yùn)行年限越來(lái)越長(zhǎng),巨型數(shù)據(jù)表就越來(lái)越多。另外,隨著城商、農(nóng)信的省級(jí)集中,用以前針對(duì)城市級(jí)商業(yè)銀行的系統(tǒng),來(lái)應(yīng)對(duì)省級(jí)的數(shù)據(jù)量,原先規(guī)模合理的表,也會(huì)變成巨型表。在實(shí)際項(xiàng)目中,已經(jīng)遇到記錄數(shù)上億,和十億級(jí)別的表了,不光嚴(yán)重影響系統(tǒng)性能,在7*24小時(shí)不間斷運(yùn)行條件下,數(shù)據(jù)清理都是個(gè)難題。以往的系統(tǒng),在這方面考慮是比較少的,大概是因?yàn)橄到y(tǒng)設(shè)計(jì)實(shí)現(xiàn)者通常只管上線,不會(huì)長(zhǎng)期維護(hù),而且原先系統(tǒng)面向銀行的規(guī)模較小。因此,要么沒考慮大數(shù)據(jù)量表的拆分,要么常處理方法也只是簡(jiǎn)單區(qū)分下當(dāng)前表和歷史表,在日終時(shí)做個(gè)當(dāng)前倒歷史的批量(歷史表巨大的話,倒歷史時(shí)間也會(huì)變得很長(zhǎng))。
分析銀行的數(shù)據(jù)表,容易產(chǎn)生很多記錄數(shù)的案例,就會(huì)發(fā)現(xiàn)通常有兩種狀況比較常見。一種是明細(xì)流水性質(zhì)的表,產(chǎn)生一筆就會(huì)新增一條記錄,日積月累就會(huì)變得很大。這里面大多數(shù)都可以用日期時(shí)間為順序和查詢依據(jù)的,例如賬戶明細(xì)表,傳票表等。這類表很明顯可以按日期進(jìn)行劃分。超過(guò)一定的期限以后,歷史的數(shù)據(jù)就可以清理了,通常歷史查詢功能由ODS之類的數(shù)據(jù)倉(cāng)庫(kù)系統(tǒng)提供。經(jīng)過(guò)清理后,數(shù)據(jù)量可以保持穩(wěn)定。另一種是賬戶主表,憑證主表,客戶信息表等,隨著系統(tǒng)多年使用逐漸增長(zhǎng),而且可清理的不多,數(shù)據(jù)量隨業(yè)務(wù)發(fā)展總體呈增長(zhǎng)趨勢(shì)。

這里我們看看在Firebird系統(tǒng)中巨型表的解決辦法。從根本上說(shuō),應(yīng)當(dāng)將大表分小,并且要適合使用的情景。在開放平臺(tái)數(shù)據(jù)庫(kù),有分區(qū)表的概念,而在400平臺(tái),對(duì)應(yīng)的就是*FILE的多MEMBER。對(duì)于可按日期劃分的表,我們可以帶日期為MEMBER名,每日一個(gè)MEMBER,預(yù)先創(chuàng)建好,無(wú)需倒歷史切換,解決了7*24小時(shí)和數(shù)據(jù)清理的問(wèn)題。對(duì)于主表,可按主鍵號(hào)碼或某些字段hash計(jì)算分MEMBER。例如,客戶表按客戶號(hào)的hash分區(qū),憑證表按憑證號(hào)的hash分區(qū)。但賬戶表要按賬戶所屬機(jī)構(gòu)號(hào)分區(qū),這是為了優(yōu)化結(jié)息批處理性能,利于每個(gè)按機(jī)構(gòu)并發(fā)的結(jié)息程序只訪問(wèn)一個(gè)MEMBER。
400系統(tǒng)對(duì)多MEMBER的限制有哪些呢?首先,同一個(gè)*FILE支持的MEMBER數(shù)量,最大為32767個(gè)。按每日分區(qū)計(jì)算,大約可以支持90年。按hash計(jì)算,10億級(jí)別的表hash到100個(gè)MEMBER,每個(gè)MEMBER僅1000萬(wàn)記錄數(shù)量。其次,單個(gè)MEMBER最多記錄數(shù)為2^32,大約42億。但實(shí)際上記錄數(shù)過(guò)多,訪問(wèn)操作性能會(huì)指數(shù)級(jí)下降。單個(gè)MEMBER內(nèi)記錄數(shù)在1000萬(wàn)級(jí)別比較合適。最后,對(duì)于LF文件的單個(gè)MEMBER,能關(guān)聯(lián)PF的MEMBER數(shù)量是有限制的,大概是32個(gè),但實(shí)際使用中LF的MEMBER命名與PF相同,完全的一對(duì)一建立。如果要搜索多個(gè)MEMBER,在應(yīng)用程序中循環(huán)讀取實(shí)現(xiàn)。

有關(guān)多MEMBER的命令有以下這些。
CRTPF或CHGPF時(shí)指定MAXMBRS為*NOMAX。
CRTLF或CHGLF時(shí)指定MAXMBRS為*NOMAX。
ADDPFM 在PF中新增一個(gè)MEMBER。
ADDLFM 在LF中新增一個(gè)MEMBER。
RMVM 刪除一個(gè)指定的MEMBER。
CLRPFM 清空一個(gè)MEMBER的所有記錄。

下面的CL程序是給PF和LF增加連續(xù)日期的MEMBER例子。MEMBER名類似M20150821。

  1.              PGM        PARM(&FLNM &STNMC &EDNMC)
  2.              INCLUDE    SRCMBR(CLHD) SRCFILE(DSCPPGM)
  3.              DCL        VAR(&FLNM) TYPE(*CHAR) LEN(10)
  4.              DCL        VAR(&STNMC) TYPE(*CHAR) LEN(8)
  5.              DCL        VAR(&EDNMC) TYPE(*CHAR) LEN(8)
  6.              DCL        VAR(&STNM) TYPE(*CHAR) LEN(10)
  7.              DCL        VAR(&EDNM) TYPE(*CHAR) LEN(10)
  8.              DCL        VAR(&MBNM) TYPE(*CHAR) LEN(10)
  9.              DCL        VAR(&DAYS) TYPE(*DEC) LEN(5 0)
  10.              DCL        VAR(&I) TYPE(*DEC) LEN(5 0)
  11.              DCL        VAR(&NM) TYPE(*CHAR) LEN(10)
  12.              DCL        VAR(&FLTP) TYPE(*CHAR) LEN(10)
  13.              DCL        VAR(&FLLB) TYPE(*CHAR) LEN(10)
  14.              DCL        VAR(&PFNM) TYPE(*CHAR) LEN(10)
  15.              RTVOBJD    OBJ(&FLNM) OBJTYPE(*FILE) OBJATR(&FLTP) RTNLIB(&FLLB)
  16.              CHGVAR     VAR(&STNM) VALUE(&STNMC)
  17.              CHGVAR     VAR(&EDNM) VALUE(&EDNMC)
  18.              CALL       PGM(DATECALC) PARM(&STNM &EDNM &DAYS)
  19.              IF         COND(&DAYS *LT 0) THEN(GOTO CMDLBL(ENDPGM))
  20.              CHGVAR     VAR(&I) VALUE(0)
  21. ADD:        IF         COND(&I *LE &DAYS) THEN(DO)
  22.              CHGVAR     VAR(&NM) VALUE('          ')
  23.              CALL       PGM(DATECALC) PARM(&STNM &NM &I)
  24.              CHGVAR     VAR(&MBNM) VALUE('M' *TCAT &NM)
  25.              IF         COND(&FLTP *EQ 'PF') THEN(DO)
  26.              ADDPFM     FILE(&FLNM) MBR(&MBNM)
  27.              ENDDO
  28.              IF         COND(&FLTP *EQ 'LF') THEN(DO)
  29.              CHGVAR     VAR(&PFNM) VALUE(%SST(&FLNM 1 7))
  30.              ADDLFM     FILE(&FLNM) MBR(&MBNM) DTAMBRS((&FLLB/&PFNM +
  31.                           (&MBNM)))
  32.              ENDDO
  33.              CHGVAR     VAR(&I) VALUE(&I + 1)
  34.              GOTO       CMDLBL(ADD)
  35.              ENDDO
  36. ENDPGM:     ENDPGM
復(fù)制代碼
下面的CL程序是給PF和LF增加連續(xù)hash的MEMBER例子。MEMBER名類似M01到M99。另外還有3位數(shù)M001到M999的程序就不貼了。

  1.              PGM        PARM(&FLNM &STNMC &EDNMC)
  2.              INCLUDE    SRCMBR(CLHD) SRCFILE(DSCPPGM)
  3.              DCL        VAR(&FLNM) TYPE(*CHAR) LEN(10)
  4.              DCL        VAR(&STNMC) TYPE(*CHAR) LEN(2)
  5.              DCL        VAR(&EDNMC) TYPE(*CHAR) LEN(2)
  6.              DCL        VAR(&STNM) TYPE(*INT)
  7.              DCL        VAR(&EDNM) TYPE(*INT)
  8.              DCL        VAR(&MBNM) TYPE(*CHAR) LEN(10)
  9.              DCL        VAR(&NM) TYPE(*CHAR) LEN(2)
  10.              DCL        VAR(&FLTP) TYPE(*CHAR) LEN(10)
  11.              DCL        VAR(&FLLB) TYPE(*CHAR) LEN(10)
  12.              DCL        VAR(&PFNM) TYPE(*CHAR) LEN(10)
  13.              RTVOBJD    OBJ(&FLNM) OBJTYPE(*FILE) OBJATR(&FLTP) RTNLIB(&FLLB)
  14.              CHGVAR     VAR(&STNM) VALUE(&STNMC)
  15.              CHGVAR     VAR(&EDNM) VALUE(&EDNMC)
  16. ADD:        IF         COND(&STNM *LE &EDNM) THEN(DO)
  17.              CHGVAR     VAR(&NM) VALUE(&STNM)
  18.              CHGVAR     VAR(&MBNM) VALUE('M' *TCAT &NM)
  19.              IF         COND(&FLTP *EQ 'PF') THEN(DO)
  20.              ADDPFM     FILE(&FLNM) MBR(&MBNM)
  21.              ENDDO
  22.              IF         COND(&FLTP *EQ 'LF') THEN(DO)
  23.              CHGVAR     VAR(&PFNM) VALUE(%SST(&FLNM 1 7))
  24.              ADDLFM     FILE(&FLNM) MBR(&MBNM) DTAMBRS((&FLLB/&PFNM +
  25.                           (&MBNM)))
  26.              ENDDO
  27.              CHGVAR     VAR(&STNM) VALUE(&STNM + 1)
  28.              GOTO       CMDLBL(ADD)
  29.              ENDDO
  30.              ENDPGM
復(fù)制代碼
建立起多MEMBER文件以后,在應(yīng)用程序中使用就有注意的地方了。
首要原則,對(duì)上層組件盡量透明,把多MEMBER的操作盡可能封裝在數(shù)據(jù)表訪問(wèn)組件內(nèi)部,對(duì)外就像操作的是一個(gè)文件一樣。這涉及到核心系統(tǒng)整體規(guī)劃上的“交易--模塊公有組件--模塊私有組件--數(shù)據(jù)訪問(wèn)封裝”體系,就是另外的話題了。
那么,在RPG程序中,多MEMBER文件的代碼怎么寫呢?主要區(qū)別在F表定義上。F表定義文件的時(shí)候,選項(xiàng)部分需要多寫兩個(gè),EXTMBR(V_MBRNAME) USROPN。EXTMBR用于根據(jù)變量V_MBRNAME的值指示要操作的MEMBER名,USROPN則是在程序執(zhí)行到OPEN語(yǔ)句時(shí)再打開文件。通過(guò)程序中先給V_MBRNAME賦值,再執(zhí)行OPEN語(yǔ)句,就可以操作指定的MEMBER啦。值得注意的是,前面介紹過(guò)激活組會(huì)保持文件的打開狀態(tài)以供下次調(diào)用使用,多MEMBER時(shí),不能簡(jiǎn)單通過(guò)%OPEN()內(nèi)置函數(shù)來(lái)判斷文件是否已打開,因?yàn)?OPEN()函數(shù)對(duì)不同MEMBER不作區(qū)分,比如已打開M003,這次雖然V_MBRNAME賦值了M998,但%OPEN()判斷時(shí)仍認(rèn)為文件已打開,必須要通過(guò)打開的MEMBER名是否相同來(lái)額外區(qū)分。

RPG對(duì)多MEMBER表的使用例子節(jié)選如下。

  1.      **********************************************************************
  2.      FAPLBTTR   O    E             DISK    INFSR(#FLEX) INFDS(S_PLBTTR)
  3.      F                                     EXTMBR(V_MBRNAME)
  4.      F                                     QUALIFIED USROPN COMMIT
  5.      **********************************************************************
  6.      D*引入數(shù)據(jù)字典枚舉常量
  7.      D/COPY DSCPPGM,ENUM
  8.      D*引入程序公共結(jié)構(gòu)
  9.      D/COPY DSCPPGM,PGDS
  10.      D*文件結(jié)構(gòu)定義
  11.      DS_PLBTTR         DS                  LIKEDS(FILESDS)
  12.      DR_PLBTTR         DS                  LIKEREC(APLBTTR.RAPLBTTR:*OUTPUT)
  13.      *************************
  14.      D*常量定義
  15.      DC_PREMBR         C                   CONST('M')
  16.      *************************
  17.      **日期結(jié)構(gòu)
  18.      DD_DATE           DS                  QUALIFIED
  19.      D YEA                            4A
  20.      D FLG1                           1A
  21.      D MON                            2A
  22.      D FLG2                           1A
  23.      D DAY                            2A
  24.      *************************
  25.      D*臨時(shí)變量結(jié)構(gòu)
  26.      DD_VARS           DS
  27.      D V_MBRNAME                           LIKE(DICT.@@FLNM)
  28.      **********************************************************************
  29.      ** @MAIN程序的主流程
  30.      **********************************************************************
  31.      C     @MAIN         BEGSR
  32.      C                   EVAL      FILEDSP = %ADDR(S_PLBTTR)
  33.      C                   EVAL      D_DATE = %CHAR(BTWTF1.BTWKDT)
  34.      C                   EVAL      V_MBRNAME = C_PREMBR + D_DATE.YEA +
  35.      C                                         D_DATE.MON + D_DATE.DAY
  36.      C*判斷已打開的成員不一致則關(guān)閉重新打開
  37.      C                   IF        FL_MEMBER <> V_MBRNAME
  38.      C                   CLOSE     APLBTTR
  39.      C                   ENDIF
  40.      C*打開指定成員
  41.      C                   IF        NOT %OPEN(APLBTTR)
  42.      C                   OPEN      APLBTTR
  43.      C                   ENDIF
  44.      C                   CLEAR                   R_PLBTTR
  45.      C                   EVAL-CORR R_PLBTTR = BTWTF1
  46.      C                   EVAL      R_PLBTTR.STTMSP  = %TIMESTAMP()
  47.      C                   EVAL      R_PLBTTR.RPSHNU  = 0
  48.      C                   EVAL      R_PLBTTR.BKEXST  = EXST_NOTEX
  49.       /FREE
  50.                          WRITE     APLBTTR.RAPLBTTR R_PLBTTR;
  51.       /END-FREE
  52.      C                   ENDSR
  53.      **********************************************************************
復(fù)制代碼

論壇徽章:
5
2015亞冠之阿爾艾因
日期:2015-08-10 02:23:34操作系統(tǒng)版塊每日發(fā)帖之星
日期:2015-08-13 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:1715-16賽季CBA聯(lián)賽之山西
日期:2016-04-13 02:36:59操作系統(tǒng)版塊每日發(fā)帖之星
日期:2016-04-14 06:20:00
23 [報(bào)告]
發(fā)表于 2015-08-24 02:31 |只看該作者
*報(bào)文格式

AS400核心系統(tǒng)的聯(lián)機(jī)交易報(bào)文,是體現(xiàn)系統(tǒng)設(shè)計(jì)優(yōu)劣的一個(gè)重要部分,并且,也決定了聯(lián)機(jī)交易主控的處理方式。

系統(tǒng)的報(bào)文規(guī)范遵循簡(jiǎn)單靈活安全高效的原則,應(yīng)做到以下幾點(diǎn)。首先,交易通過(guò)短連接單次通訊完成,不需要先分配端口,多次交互,也沒有任何前后交易的狀態(tài)耦合。其次,交易報(bào)文一次一密全文加密,并且不需要每次交易做多次密鑰交換動(dòng)作。即使將成功報(bào)文原樣重新發(fā)送,系統(tǒng)也會(huì)識(shí)別為重復(fù)提交而不會(huì)重復(fù)執(zhí)行。最后,報(bào)文組織應(yīng)充分考慮AS400應(yīng)用程序的寫法,既要滿足交易程序參數(shù)傳遞的性能,又要盡量保持報(bào)文靈活,并減少無(wú)意義的內(nèi)容傳送。在交易R(shí)PG程序中,輸入輸出接口,基本上都是以DS或DS數(shù)組的形式PARM傳遞進(jìn)來(lái)處理。因此,體現(xiàn)單個(gè)字段key-value的XML,JSON之類格式,就不太適合作為AS400報(bào)文使用。因此,F(xiàn)irebird設(shè)計(jì)了一種特定的報(bào)文格式。
整體報(bào)文結(jié)構(gòu)規(guī)則是,不論輸入報(bào)文或者輸出報(bào)文,除了少數(shù)報(bào)文頭字段,其余均以接口結(jié)構(gòu)方式組織。接口結(jié)構(gòu)由接口名稱,記錄條數(shù),單條長(zhǎng)度,接口內(nèi)容四個(gè)部分組成。一個(gè)交易的接口結(jié)構(gòu)順序,是否出現(xiàn)均不固定,不影響交易的執(zhí)行。特別的,當(dāng)接口為數(shù)組時(shí),報(bào)文只需出現(xiàn)實(shí)際條數(shù)的接口內(nèi)容,如果數(shù)組為空,則整個(gè)數(shù)組接口都不會(huì)出現(xiàn)。這樣就減少了報(bào)文的大小,提升了通訊效率。在交易輸出報(bào)文中,除了預(yù)先定義的交易輸出接口外,還可以附加的方式返回其他特殊用途接口。例如提示信息,常用于交易成功但需要傳遞的提醒或警告,需要下傳的憑證打印等。這在之前用戶空間USER SPACE時(shí)介紹過(guò)。每個(gè)交易除了公共定義的接口外,最多有9個(gè)自定義輸入接口,9個(gè)自定義輸出接口,這些接口都可以是單一結(jié)構(gòu)或數(shù)組,單條接口結(jié)構(gòu)最大64KB。接口內(nèi)部是定長(zhǎng)的,但接口數(shù)量和出現(xiàn)順序可任意組合。
目前系統(tǒng)設(shè)定的輸入輸出報(bào)文大小上限是1MB,通過(guò)修改主控的常量定義,可最大擴(kuò)充到16MB。報(bào)文在通訊中作為整體一次TCP傳遞,一筆交易一次通訊交互即可,無(wú)需應(yīng)用系統(tǒng)分片。

具體的輸入報(bào)文格式如下:
總長(zhǎng)度 INT 4
交易序號(hào) INT 8
校驗(yàn)碼 INT 4
公共接口名稱 STR 10
公共接口記錄條數(shù) INT 2
公共接口單條長(zhǎng)度 INT 2
公共接口內(nèi)容 BUF
接口一名稱 STR 10
接口一記錄條數(shù) INT 2
接口一單條長(zhǎng)度 INT 2
接口一內(nèi)容 BUF
……
接口N名稱 STR 10
接口N記錄條數(shù) INT 2
接口N單條長(zhǎng)度 INT 2
接口N內(nèi)容 BUF


輸出報(bào)文格式分兩種情況。
當(dāng)返回的是交易成功報(bào)文時(shí):
總長(zhǎng)度 INT 4
交易序號(hào) INT 8
校驗(yàn)碼 INT 4
返回碼 STR 10
公共接口名稱 STR 10
公共接口記錄條數(shù) INT 2
公共接口單條長(zhǎng)度 INT 2
公共接口內(nèi)容 BUF
接口一名稱 STR 10
接口一記錄條數(shù) INT 2
接口一單條長(zhǎng)度 INT 2
接口一內(nèi)容 BUF
……
接口N名稱 STR 10
接口N記錄條數(shù) INT 2
接口N單條長(zhǎng)度 INT 2
接口N內(nèi)容 BUF

當(dāng)返回的是出錯(cuò)報(bào)文時(shí):
總長(zhǎng)度 INT 4
交易序號(hào) INT 8
校驗(yàn)碼 INT 4
返回碼 STR 10
出錯(cuò)文件名 STR 10
錯(cuò)誤信息內(nèi)容 STR 80
接口一名稱 STR 10
接口一記錄條數(shù) INT 2
接口一單條長(zhǎng)度 INT 2
接口一內(nèi)容 BUF
……
接口N名稱 STR 10
接口N記錄條數(shù) INT 2
接口N單條長(zhǎng)度 INT 2
接口N內(nèi)容 BUF


下面詳細(xì)解釋一下報(bào)文頭各字段含義。
總長(zhǎng)度:輸入輸出報(bào)文的開頭4個(gè)字節(jié)為報(bào)文總長(zhǎng)度,即從交易序號(hào)開始,后續(xù)報(bào)文的字節(jié)數(shù)?傞L(zhǎng)度如果是負(fù)數(shù),有特殊用途,表示這筆交易會(huì)運(yùn)行于調(diào)試模式,而不影響其他交易的正常模式,適合用于生產(chǎn)環(huán)境的疑難問(wèn)題跟蹤重現(xiàn)。
交易序號(hào):用于標(biāo)識(shí)每一筆交易的唯一增長(zhǎng)值。無(wú)符號(hào)長(zhǎng)整形數(shù)值,F(xiàn)irebird使用的是全局時(shí)間戳(毫秒級(jí))加2位組合步驟序號(hào)。舉例來(lái)說(shuō),如果是柜面渠道直連核心交易,那么就是時(shí)間戳加00,如2015082401315512300,表示2015-08-24 01:31:55.123發(fā)送的交易。如果是通過(guò)綜合前置或ESB調(diào)度的組合交易,如2015082401315512302,表示2015-08-24 01:31:55.123發(fā)送的交易,在組合流程中的第2步調(diào)用。交易序號(hào)應(yīng)保證按柜員號(hào)每筆增長(zhǎng),系統(tǒng)拒絕不正常的交易序號(hào),以防止偽造或重復(fù)報(bào)文攻擊。
校驗(yàn)碼:對(duì)后續(xù)報(bào)文全文加密并計(jì)算出的校驗(yàn)碼,用于防止報(bào)文被篡改。
返回碼:輸出報(bào)文時(shí)存在,如果交易正常,返回碼為'OK',如果出錯(cuò),則為錯(cuò)誤代碼。如果為AS400系統(tǒng)級(jí)錯(cuò)誤,則為F+系統(tǒng)錯(cuò)誤代碼,如FCPF3282。如果是應(yīng)用錯(cuò)誤,則為E+應(yīng)用錯(cuò)誤代碼,如ECNBRNORL。
出錯(cuò)文件名:交易出錯(cuò)時(shí)存在此字段,表示產(chǎn)生錯(cuò)誤的源程序名。在后臺(tái)主控日志中,還可以查到產(chǎn)生系統(tǒng)錯(cuò)誤的源程序行號(hào)。
錯(cuò)誤信息內(nèi)容:錯(cuò)誤的說(shuō)明信息,通常為代入數(shù)據(jù)后的錯(cuò)誤中文描述。例如:機(jī)構(gòu)表中機(jī)構(gòu)號(hào)064001不存在。

接下來(lái)就是接口部分。
輸入的公共接口有3個(gè),INHD是輸入公共結(jié)構(gòu),INFE是交易收費(fèi)數(shù)組,INCS是券面數(shù)組。注意,后2者只有存在數(shù)據(jù)時(shí)才會(huì)出現(xiàn)。
輸出的公共接口有2個(gè),OTHD是輸出公共結(jié)構(gòu),OTVC是交易產(chǎn)生的傳票數(shù)組。同樣,OTVC只有產(chǎn)生傳票的交易才會(huì)出現(xiàn)。
輸出特有的接口有1個(gè),OTFE是輸出收費(fèi)數(shù)組,用于收費(fèi)輸入不正確或沒輸時(shí),交易報(bào)錯(cuò)并回顯正確的收費(fèi)項(xiàng)。因此這個(gè)接口只有在特定出錯(cuò)場(chǎng)景才會(huì)出現(xiàn)。
輸出額外附加的接口,包括OTWN,交易警告和提示信息數(shù)組,以及下傳的其他憑證打印接口結(jié)構(gòu)。

那么,在交易程序中,報(bào)文接口是怎么體現(xiàn)的呢?可以看一下具體的程序代碼片段。

  1.      **定義常量
  2.      DC_NBO1           C                   CONST(50)
  3.      DC_NBO2           C                   CONST(50)
  4.      DC_NBO3           C                   CONST(50)
  5.      *************************
  6.      **定義參照外部結(jié)構(gòu)的結(jié)構(gòu)、數(shù)組 
  7.      DT_INHD         E DS                  EXTNAME(INHD)  QUALIFIED  TEMPLATE
  8.      DT_INFE         E DS                  EXTNAME(INFE)  QUALIFIED  TEMPLATE
  9.      DT_INCS         E DS                  EXTNAME(INCS)  QUALIFIED  TEMPLATE
  10.      DT_OTHD         E DS                  EXTNAME(OTHD)  QUALIFIED  TEMPLATE
  11.      DT_OTVC         E DS                  EXTNAME(OTVC)  QUALIFIED  TEMPLATE
  12.      DT_I1           E DS                  EXTNAME(T020002I1) QUALIFIED TEMPLATE
  13.      DT_O1           E DS                  EXTNAME(T020002O1) QUALIFIED TEMPLATE
  14.      DT_O2           E DS                  EXTNAME(T020002O2) QUALIFIED TEMPLATE
  15.      DT_O3           E DS                  EXTNAME(T020002O3) QUALIFIED TEMPLATE
  16.      *************************
  17.      **定義參照內(nèi)部結(jié)構(gòu)、變量(LIKE)的結(jié)構(gòu)、數(shù)組
  18.      DPIN              DS                  QUALIFIED
  19.      D INHD                                LIKEDS(T_INHD)
  20.      D INFE                                DIM(C_NBINFE) LIKEDS(T_INFE)
  21.      D INCS                                DIM(C_NBINCS) LIKEDS(T_INCS)
  22.      D I1                                  LIKEDS(T_I1)
  23.      **
  24.      DPOT              DS                  QUALIFIED
  25.      D OTHD                                LIKEDS(T_OTHD)
  26.      D OTVC                                DIM(C_NBOTVC) LIKEDS(T_OTVC)
  27.      D O1                                  DIM(C_NBO1) LIKEDS(T_O1)
  28.      D O2                                  DIM(C_NBO2) LIKEDS(T_O2)
  29.      D O3                                  DIM(C_NBO3) LIKEDS(T_O3)
  30.      ***********************************************************
  31.      **定義程序入口
  32.      C     *ENTRY        PLIST
  33.      C                   PARM                    PMG
  34.      C                   PARM                    PIN
  35.      C                   PARM                    POT
復(fù)制代碼
這段是020002交易的主程序。聯(lián)機(jī)交易的PARM都是3個(gè),PMG是錯(cuò)誤信息結(jié)構(gòu),PIN是輸入接口結(jié)構(gòu),POT是輸出接口結(jié)構(gòu)。020002交易有1個(gè)自定義輸入I1,3個(gè)自定義輸出O1,O2,O3均為最大50條記錄的數(shù)組。因此加上公共接口,就體現(xiàn)為PIN,POT的完整內(nèi)容。因?yàn)閳?bào)文只會(huì)出現(xiàn)有數(shù)據(jù)的接口內(nèi)容,所以將內(nèi)容填入正確的位置,就是主控程序的工作職責(zé)了,對(duì)交易程序來(lái)說(shuō),無(wú)需關(guān)心。

論壇徽章:
10
數(shù)據(jù)庫(kù)技術(shù)版塊每日發(fā)帖之星
日期:2015-06-14 22:20:00數(shù)據(jù)庫(kù)技術(shù)版塊每日發(fā)帖之星
日期:2016-03-10 06:20:00數(shù)據(jù)庫(kù)技術(shù)版塊每日發(fā)帖之星
日期:2015-12-01 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-11-09 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-11-02 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-07-13 22:59:28IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-06-23 22:20:00程序設(shè)計(jì)版塊每日發(fā)帖之星
日期:2015-06-21 22:20:00每日論壇發(fā)貼之星
日期:2015-06-14 22:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-08-02 06:20:00
24 [報(bào)告]
發(fā)表于 2015-08-25 19:02 |只看該作者
這樣的系統(tǒng),必定會(huì)被加速淘汰。曾經(jīng)的輝煌沒落于更新太慢,創(chuàng)新不足。

論壇徽章:
10
數(shù)據(jù)庫(kù)技術(shù)版塊每日發(fā)帖之星
日期:2015-06-14 22:20:00數(shù)據(jù)庫(kù)技術(shù)版塊每日發(fā)帖之星
日期:2016-03-10 06:20:00數(shù)據(jù)庫(kù)技術(shù)版塊每日發(fā)帖之星
日期:2015-12-01 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-11-09 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-11-02 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-07-13 22:59:28IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-06-23 22:20:00程序設(shè)計(jì)版塊每日發(fā)帖之星
日期:2015-06-21 22:20:00每日論壇發(fā)貼之星
日期:2015-06-14 22:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-08-02 06:20:00
25 [報(bào)告]
發(fā)表于 2015-08-25 19:04 |只看該作者
陳舊的理論,固步自封于范式。
回復(fù) 22# pacman2000


   

論壇徽章:
0
26 [報(bào)告]
發(fā)表于 2015-09-17 13:36 |只看該作者
謝謝樓主分享,來(lái)支持呢。

論壇徽章:
5
2015亞冠之阿爾艾因
日期:2015-08-10 02:23:34操作系統(tǒng)版塊每日發(fā)帖之星
日期:2015-08-13 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:1715-16賽季CBA聯(lián)賽之山西
日期:2016-04-13 02:36:59操作系統(tǒng)版塊每日發(fā)帖之星
日期:2016-04-14 06:20:00
27 [報(bào)告]
發(fā)表于 2016-02-21 23:49 |只看該作者
*數(shù)據(jù)字典和枚舉值

    在核心系統(tǒng)應(yīng)用開發(fā)中,數(shù)據(jù)字典有舉足輕重的作用。數(shù)據(jù)字典是對(duì)系統(tǒng)中所有字段的歸納抽象,需要規(guī)范同類字段的類型長(zhǎng)度,方便定義和修改。
    但是,在過(guò)去的核心系統(tǒng)中,數(shù)據(jù)字典的理解往往也會(huì)有失誤。常見的錯(cuò)誤方法,是試圖窮舉定義所有可以出現(xiàn)的字段名字?墒菍(shí)際上核心系統(tǒng)應(yīng)用程序內(nèi)容是不斷擴(kuò)充的,功能和交易程序都在不停增加,所用到的字段也是無(wú)窮無(wú)盡。如果需要列舉的是所有字段,就像建巴比倫塔一樣困難。而且不可避免會(huì)出現(xiàn)賬號(hào)1到賬號(hào)9這樣的重復(fù)。
    在Firebird系統(tǒng)中,數(shù)據(jù)字典的使用方式回歸了本源意義,即數(shù)據(jù)字典定義的是不重復(fù)的字段基礎(chǔ)類型。舉例來(lái)說(shuō),“日期”就是一個(gè)基礎(chǔ)類型,歸數(shù)據(jù)字典管理。而“交易日期”,“開戶日期”這些字段,都只是使用基礎(chǔ)類型定義出來(lái)的具體字段變量,不歸集到數(shù)據(jù)字典管理,但命名上要求具體字段必須以數(shù)據(jù)字典基礎(chǔ)類型結(jié)尾,體現(xiàn)歸屬關(guān)系。“日期”在數(shù)據(jù)字典里定義的是WKDT,“開戶日期”起名可以叫OPWKDT,“交易日期”起名可以叫TRWKDT,不同場(chǎng)景中也可以起名不一樣。這樣的數(shù)據(jù)字典和字段命名規(guī)則,既滿足應(yīng)用系統(tǒng)字段的不斷擴(kuò)充,又保持?jǐn)?shù)據(jù)字典的精簡(jiǎn)和穩(wěn)定。

    數(shù)據(jù)字典的實(shí)現(xiàn)方式,是建立一個(gè)DICT的PF文件并編譯,里面的內(nèi)容即是所有基礎(chǔ)類型的定義。摘錄部分如下所示。

  1.      A          R RDICT
  2.      A*長(zhǎng)度 L
  3.      A            @@WKDT          L         TEXT('日期')
  4.      A
  5.      A*長(zhǎng)度 T
  6.      A            @@WKTM          T         TEXT('時(shí)間')
  7.      A
  8.      A*長(zhǎng)度 Z
  9.      A            @@TMSP          Z         TEXT('時(shí)間戳')
  10.      A
  11.      A*長(zhǎng)度 1A
  12.      A            @@CHAR         1A         TEXT('字符')
  13.      A            @@YNFG         1A         TEXT('是否標(biāo)志')
  14.      A*                            1 是 YES
  15.      A*                            0 否 NO
  16.      ......
  17.      A*長(zhǎng)度 3P
  18.      A            @@EXSQ         3P 0       TEXT('執(zhí)行序號(hào)')
  19.      A*長(zhǎng)度 4A
  20.      A            @@SMCD         4A         TEXT('摘要代碼')
  21.      A            @@ITCD         4A         TEXT('核算代碼')
  22.      A            @@CSCD         4A         TEXT('現(xiàn)金項(xiàng)目代碼')
  23.      ......
復(fù)制代碼
為了與實(shí)際應(yīng)用程序中的字段名區(qū)分,數(shù)據(jù)字典中的基礎(chǔ)類型字段名以@@開頭。

    在表結(jié)構(gòu)PF字段定義,通用結(jié)構(gòu)定義,交易、組件輸入輸出接口PF字段定義時(shí),就可以參照數(shù)據(jù)字典了。
    以尾箱憑證登記表ACNVCBB為例展示如下。

  1.      A                                      UNIQUE
  2.      A                                      REF(DICT)
  3.      A          R RACNVCBB
  4.      A            BKBRNO    R               REFFLD(@@BRNO)
  5.      A                                      TEXT('機(jī)構(gòu)號(hào)')
  6.      A                                      COLHDG('機(jī)構(gòu)號(hào)')
  7.      A            BKBXNO    R               REFFLD(@@BXNO)
  8.      A                                      TEXT('尾箱號(hào)')
  9.      A                                      COLHDG('尾箱號(hào)')
  10.      A            BKVCTP    R               REFFLD(@@VCTP)
  11.      A                                      TEXT('憑證種類')
  12.      A                                      COLHDG('憑證' '種類')
  13.      A            VBMDNU    R               REFFLD(@@MDNU)
  14.      A                                      TEXT('憑證張數(shù)')
  15.      A                                      COLHDG('憑證' '張數(shù)')
  16.      A            BKSTCD    R               REFFLD(@@STCD)
  17.      A                                      TEXT('記錄狀態(tài)')
  18.      A                                      COLHDG('記錄狀態(tài)')
  19.      A          K BKBRNO
  20.      A          K BKBXNO
  21.      A          K BKVCTP
復(fù)制代碼
以尾箱主表ACNBXBX為例展示如下。

  1.      A                                      UNIQUE
  2.      A                                      REF(DICT)
  3.      A          R RACNBXBX
  4.      A            BKBRNO    R               REFFLD(@@BRNO)
  5.      A                                      TEXT('機(jī)構(gòu)號(hào)')
  6.      A                                      COLHDG('機(jī)構(gòu)號(hào)')
  7.      A            BKBXNO    R               REFFLD(@@BXNO)
  8.      A                                      TEXT('尾箱號(hào)')
  9.      A                                      COLHDG('尾箱號(hào)')
  10.      A            VCACNO    R               REFFLD(@@ACNO)
  11.      A                                      TEXT('憑證賬號(hào)')
  12.      A                                      COLHDG('憑證' '賬號(hào)')
  13.      A            BKTLNO    R               REFFLD(@@TLNO)
  14.      A                                      TEXT('柜員號(hào)')
  15.      A                                      COLHDG('柜員號(hào)')
  16.      A            EQYNFG    R               REFFLD(@@YNFG)
  17.      A                                      TEXT('碰平標(biāo)志')
  18.      A                                      COLHDG('碰平' '標(biāo)志')
  19.      A            OPBRNO    R               REFFLD(@@BRNO)
  20.      A                                      TEXT('創(chuàng)建機(jī)構(gòu)')
  21.      A                                      COLHDG('創(chuàng)建' '機(jī)構(gòu)')
  22.      A            OPDPNO    R               REFFLD(@@DPNO)
  23.      A                                      TEXT('創(chuàng)建部門')
  24.      A                                      COLHDG('創(chuàng)建' '部門')
  25.      A            OPTLNO    R               REFFLD(@@TLNO)
  26.      A                                      TEXT('創(chuàng)建柜員')
  27.      A                                      COLHDG('創(chuàng)建' '柜員')
  28.      A            OPWKDT    R               REFFLD(@@WKDT)
  29.      A                                      TEXT('創(chuàng)建日期')
  30.      A                                      COLHDG('創(chuàng)建' '日期')
  31.      A            OPWKTM    R               REFFLD(@@WKTM)
  32.      A                                      TEXT('創(chuàng)建時(shí)間')
  33.      A                                      COLHDG('創(chuàng)建' '時(shí)間')
  34.      A            MTBRNO    R               REFFLD(@@BRNO)
  35.      A                                      TEXT('修改機(jī)構(gòu)')
  36.      A                                      COLHDG('修改' '機(jī)構(gòu)')
  37.      A            MTDPNO    R               REFFLD(@@DPNO)
  38.      A                                      TEXT('修改部門')
  39.      A                                      COLHDG('修改' '部門')
  40.      A            MTTLNO    R               REFFLD(@@TLNO)
  41.      A                                      TEXT('修改柜員')
  42.      A                                      COLHDG('修改' '柜員')
  43.      A            MTWKDT    R               REFFLD(@@WKDT)
  44.      A                                      TEXT('修改日期')
  45.      A                                      COLHDG('修改' '日期')
  46.      A            MTWKTM    R               REFFLD(@@WKTM)
  47.      A                                      TEXT('修改時(shí)間')
  48.      A                                      COLHDG('修改' '時(shí)間')
  49.      A            BKSTCD    R               REFFLD(@@STCD)
  50.      A                                      TEXT('記錄狀態(tài)')
  51.      A                                      COLHDG('記錄' '狀態(tài)')
  52.      A          K BKBRNO
  53.      A          K BKBXNO
復(fù)制代碼
從上面的例子可以看出,PF定義中首先要REF(DICT)引入數(shù)據(jù)字典,然后定義具體字段時(shí)候,REFFLD指明數(shù)據(jù)字典的基礎(chǔ)類型字段。注意的是命名規(guī)范要求,具體字段的后4位必須和數(shù)據(jù)字典基礎(chǔ)字段名字一致。這樣在程序中可以輕松認(rèn)出是哪種類型(這就是應(yīng)用型匈牙利命名法,有關(guān)匈牙利命名法的誤解和討論參見《軟件隨想錄 -- Joel on software》的第23章“讓錯(cuò)誤的代碼顯而易見”)。不同的PF字段名字可能會(huì)一樣,因此在RPG程序中需要QUALIFIED防止重疊,這在后續(xù)“命名限定”時(shí)候再介紹。

    那么如果在RPG程序中需要參照數(shù)據(jù)字典定義變量該怎么寫呢。這里就需要使用一個(gè)新的關(guān)鍵字TEMPLATE,它可以引入一個(gè)PF結(jié)構(gòu)但并不分配存儲(chǔ)空間。同樣讓例子程序說(shuō)話。

  1.      **********************************************************************
  2.      **公共結(jié)構(gòu)
  3.      **引入數(shù)據(jù)字典
  4.      DDICT           E DS                  EXTNAME(DICT) QUALIFIED TEMPLATE
  5.      *************************
  6.      **臨時(shí)變量結(jié)構(gòu)
  7.      DD_VARS           DS
  8.      **定義參照數(shù)據(jù)字典(LIKE)的變量 
  9.      D V_BKBRNO                            LIKE(DICT.@@BRNO)
  10.      D V_EQYNFG                            LIKE(DICT.@@YNFG)
  11.      **定義無(wú)法參照的臨時(shí)變量 
  12.      D V_NUM                          5P 0
  13.      **********************************************************************
復(fù)制代碼
先是D段定義了DICT,引入外部PF結(jié)構(gòu)DICT,并且是QUALIFIED限定為以點(diǎn)訪問(wèn)字段,TEMPLATE指明只聲明不分配空間,然后定義變量時(shí)就可以用LIKE了。

    數(shù)據(jù)字典除了定義了字段類型長(zhǎng)度,還對(duì)枚舉項(xiàng)列表進(jìn)行了管理。比如數(shù)據(jù)字典例子中,@@YNFG就是一個(gè)枚舉,1表示是,0表示否。在尾箱主表的EQYNFG碰平標(biāo)志就是用了這個(gè)枚舉。在程序中如果寫0,1的話,既不便于閱讀程序,也不方便枚舉值的變化。因此,F(xiàn)irebird中根據(jù)DICT自動(dòng)生成了ENUM這個(gè)枚舉列表,這樣RPG程序中就可以用YNFG_YES代表1,YNFG_NO代表0。摘錄DSCPPGM/ENUM這個(gè)RPGLE源碼部分如下。

  1.      **BEGIN***************************************************************
  2.      **程序名稱:數(shù)據(jù)字典枚舉值                                         *
  3.      **功能描述:數(shù)據(jù)字典枚舉值常量定義                                 *
  4.      **                                                                   *
  5.      **版本:2014-11-08_1                                               *
  6.      **                                                                   *
  7.      **設(shè)計(jì)人員:PACMAN          開發(fā)人員:AUTOGEN                    *
  8.      **設(shè)計(jì)日期:2011-08-30      開發(fā)日期:2011-08-30                 *
  9.      **                                                                   *
  10.      **END*****************************************************************
  11.      **
  12.       *是否標(biāo)志:是YES
  13.      D YNFG_YES        C                   CONST('1')
  14.       *是否標(biāo)志:否NO
  15.      D YNFG_NO         C                   CONST('0')
  16.       *
  17.       *借貸標(biāo)志:借方DEBIT
  18.      D DCFG_DEBIT      C                   CONST('1')
  19.       *借貸標(biāo)志:貸方CREDIT
  20.      D DCFG_CREDT      C                   CONST('2')
  21.       *
  22.       *記錄狀態(tài):正常NORMAL
  23.      D STCD_NORML      C                   CONST('1')
  24.       *記錄狀態(tài):刪除ABNORMAL
  25.      D STCD_ABNML      C                   CONST('2')
  26.       *
復(fù)制代碼
在RPG程序中,通過(guò)D/COPY DSCPPGM,ENUM 即可引入數(shù)據(jù)字典枚舉常量。之后就可以 EVAL V_EQYNFG=YNFG_YES 這么寫了。

論壇徽章:
5
2015亞冠之阿爾艾因
日期:2015-08-10 02:23:34操作系統(tǒng)版塊每日發(fā)帖之星
日期:2015-08-13 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:1715-16賽季CBA聯(lián)賽之山西
日期:2016-04-13 02:36:59操作系統(tǒng)版塊每日發(fā)帖之星
日期:2016-04-14 06:20:00
28 [報(bào)告]
發(fā)表于 2016-02-22 00:09 |只看該作者
因?yàn)閰⑴c新的核心系統(tǒng)項(xiàng)目工作緊張,并且前一陣身體抱恙,所以有一段時(shí)間沒有更新了。不過(guò)有時(shí)間還是會(huì)堅(jiān)持完成這個(gè)系列連載。

剩余還有幾篇內(nèi)容,這里先預(yù)告一下,也以免自己忘記:
13.命名限定。主要介紹RPGLE程序中文件的TEMPLATE限定寫法,QUALIFIED關(guān)鍵字,以及EVAL-CORR結(jié)構(gòu)同名字段賦值語(yǔ)句。
14.異常處理。介紹AS400編程中的異常捕捉處理,主要包括RPGLE語(yǔ)言的文件異常INFDS結(jié)構(gòu),程序異常PSDS結(jié)構(gòu),程序異常處理程序*PSSR和文件異常處理程序,(E)語(yǔ)句和%ERROR處理,以及JOB出現(xiàn)MSGW后抽取MSGW原因和上層MSGW捕獲。另外還附帶如何在程序中獲取PF文件的中文名,可用于返回錯(cuò)誤說(shuō)明報(bào)文的組織哦。
15.面向?qū)ο髮?shí)現(xiàn)。介紹Firebird核心系統(tǒng)中面向?qū)ο蟮氖褂脠?chǎng)景,以及聯(lián)機(jī)交易平臺(tái)根據(jù)交易碼進(jìn)行交易流程調(diào)度的運(yùn)行中解析,模擬多態(tài)的實(shí)現(xiàn)方法。
16.交易和組件的寫法。以實(shí)際的樣例模版程序,展示交易和組件的文件組織結(jié)構(gòu)和程序?qū)懛,之前介紹的各種技術(shù)方法,是如何組合到真正的程序中的。

論壇徽章:
5
2015亞冠之阿爾艾因
日期:2015-08-10 02:23:34操作系統(tǒng)版塊每日發(fā)帖之星
日期:2015-08-13 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:1715-16賽季CBA聯(lián)賽之山西
日期:2016-04-13 02:36:59操作系統(tǒng)版塊每日發(fā)帖之星
日期:2016-04-14 06:20:00
29 [報(bào)告]
發(fā)表于 2016-04-04 18:23 |只看該作者
*命名限定

在以往的RPG程序中,很讓人頭疼的一點(diǎn)就是字段的來(lái)源不直觀,以及同名字段的相互影響。在程序中,字段可以是通過(guò)F表定義文件而引入的記錄格式字段,也可以是EXTNAME引入的參照外部文件形成的結(jié)構(gòu)字段,還可以是DS定義的字段以及直接用D定義的變量。如果考慮到有/COPY引入DS定義的情況,通常會(huì)造成在程序中看到一個(gè)字段名,一下子不清楚到底是在哪里定義的。如果文件、DS結(jié)構(gòu)內(nèi)遇到字段名相同,程序會(huì)認(rèn)定同名字段為同一塊內(nèi)存空間,字段的值同步變動(dòng),這給程序查錯(cuò)帶來(lái)了很大的困擾。
現(xiàn)代的程序設(shè)計(jì)語(yǔ)言中,已經(jīng)注意到了全局名字空間污染的問(wèn)題,對(duì)于結(jié)構(gòu)內(nèi)的字段,通常采用“結(jié)構(gòu)名.字段名”的方式表示。RPGLE的自由格式擴(kuò)展了語(yǔ)法的長(zhǎng)度限制,消除了寫法上的障礙,因此現(xiàn)在全面采用這種寫法已經(jīng)沒有問(wèn)題了。下面詳細(xì)介紹一下QUALIFIED關(guān)鍵字的用法。

F表定義文件中使用QUALIFIED的方式。
表ACNTLMF的定義摘選如下。

  1.      A                                      UNIQUE
  2.      A                                      REF(DICT)
  3.      A          R RACNTLMF
  4.      A            BKTLNO    R               REFFLD(@@TLNO)
  5.      A                                      TEXT('柜員號(hào)')
  6.      A                                      COLHDG('柜員號(hào)')
  7.      A            BKTLTP    R               REFFLD(@@TLTP)
  8.      A                                      TEXT('柜員類型')
  9.      A                                      COLHDG('柜員' '類型')
  10.      A            TLPCNM    R               REFFLD(@@PCNM)
  11.      A                                      TEXT('柜員姓名')
  12.      A                                      COLHDG('柜員' '姓名')
  13.      A            BKBRNO    R               REFFLD(@@BRNO)
  14.      A                                      TEXT('機(jī)構(gòu)號(hào)')
  15.      A                                      COLHDG('機(jī)構(gòu)號(hào)')
  16.      A          K BKTLNO
復(fù)制代碼
RPGLE程序中寫法示意如下。

  1.      FACNTLMF   UF A E           K DISK    COMMIT QUALIFIED
  2.      **
  3.      DR_CNTLMF1        DS                  LIKEREC(ACNTLMF.RACNTLMF:*INPUT)
  4.      DR_CNTLMF2        DS                  LIKEREC(ACNTLMF.RACNTLMF:*OUTPUT)
  5.      DK_CNTLMF         DS                  LIKEREC(ACNTLMF.RACNTLMF:*KEY)
  6.      **
  7.       /FREE
  8.          CLEAR  R_CNTLMF1;
  9.          CLEAR  K_CNTLMF;
  10.          K_CNTLMF.BKTLNO = TLADF1.BKTLNO;
  11.          CHAIN  K_CNTLMF  ACNTLMF.RACNTLMF  R_CNTLMF1;
  12.          CLEAR  R_CNTLMF2;
  13.          EVAL-CORR  R_CNTLMF2 = R_CNTLMF1;
  14.          R_CNTLMF2.BKPCNM = TLADF1.BKPCNM;
  15.          UPDATE  ACNTLMF.RACNTLMF  R_CNTLMF2;
  16.        /END-FREE
復(fù)制代碼
那么,程序中由于QUALIFIED的存在,記錄格式名必須加上文件名限定,并且不能再在程序中直接使用文件中的字段,必須使用自由格式的讀寫方式,使文件操作結(jié)果關(guān)聯(lián)一個(gè)指定的DS結(jié)構(gòu),這個(gè)結(jié)構(gòu)是以LIKEREC方式給出。如上面的代碼所示,根據(jù)ACNTLMF,LIKEREC定義了3個(gè)DS結(jié)構(gòu)。*KEY定義的K_CNTLMF用于取代固定格式的KLIST,作為文件操作語(yǔ)句的鍵值定位,會(huì)選取文件定義中的所有KEY字段。*INPUT定義的R_CNTLMF1可用于READ,CHAIN等讀取語(yǔ)句存放結(jié)果。*OUTPUT定義的R_CNTLMF2可用于UPDATE,WRITE等寫入語(yǔ)句的數(shù)據(jù)來(lái)源。V6R1中,*INPUT和*OUTPUT不能通用,給寫程序帶來(lái)了一定的麻煩,READ以后的UPDATE,必須用EVAL-CORR從*INPUT往*OUTPUT賦值(EVAL-CORR前面介紹過(guò),是在兩個(gè)不同結(jié)構(gòu)間同名字段的賦值)。在V7R2中,放松了這個(gè)限制,可以用*ALL定義既可用于讀取又可用于寫入的結(jié)構(gòu),就不需要賦值了。注意使用LIKEREC定義的結(jié)構(gòu),默認(rèn)均為QUALIFIED方式DS,使用“結(jié)構(gòu)名.字段名”的寫法。

DS結(jié)構(gòu)定義中使用QUALIFIED的方式。
DS結(jié)構(gòu)使用了QUALIFIED方式,則使用“結(jié)構(gòu)名.字段名”的寫法。如果DS本身是用LIKEREC,LIKEDS定義的,那么系統(tǒng)對(duì)這種參照的DS默認(rèn)必須是QUALIFIED的。其他的DS定義或者EXTNAME的,可以寫明QUALIFIED關(guān)鍵字來(lái)達(dá)到效果。
以下面的代碼片段為例。

  1.      **引入數(shù)據(jù)字典
  2.      DDICT           E DS                  EXTNAME(DICT) QUALIFIED TEMPLATE
  3.      DC_NBTLADF2       C                   CONST(50)
  4.      DT_TLADF2       E DS                  EXTNAME(SCNTLADF2) QUALIFIED TEMPLATE
  5.      DTLADF1         E DS                  EXTNAME(SCNTLADF1) QUALIFIED
  6.      DTLADF2           DS                  QUALIFIED
  7.      D RECD                                LIKE(DICT.@@RECD)
  8.      D ARR                                 DIM(C_NBTLADF2) LIKEDS(T_TLADF2)
  9.      **程序原型定義
  10.      DSCNTLAD          PR                  EXTPGM('SCNTLAD')
  11.      D TLADF1                              LIKEDS(TLADF1)
  12.      D TLADF2                              LIKEDS(TLADF2)
復(fù)制代碼
這里定義了SCNTLAD的兩個(gè)參數(shù)DS,一個(gè)是單個(gè)結(jié)構(gòu)TLADF1,另一個(gè)是帶實(shí)際記錄條數(shù)的數(shù)組復(fù)合DS,TLADF2.RECD是實(shí)際條數(shù),TLADF2.ARR是DIM數(shù)組。這里值得注意的是TEMPLATE關(guān)鍵字的使用。在DS定義中,如果使用了TEMPLATE,那么程序不會(huì)為這個(gè)定義的DS分配實(shí)際的存儲(chǔ)空間,而只是用作編譯期定義使用。數(shù)據(jù)字典定義DICT,以及作為數(shù)組單個(gè)結(jié)構(gòu)參照的T_TLADF2,正好非常符合這個(gè)用法。

在RPGLE自由格式中,轉(zhuǎn)換成命名限定的寫法,是有必要的。這避免了以前固定格式中用的很多的PREFIX和RENAME,使得程序中的字段更可讀。
另外要提一下,在開發(fā)過(guò)程中,V6R1版本有一個(gè)PTF補(bǔ)丁問(wèn)題,導(dǎo)致TEMPLATE編譯造成編譯器軟件錯(cuò)誤。這時(shí)候可以用BASED(@)代替TEMPLATE,意為指定為空指針,即無(wú)需分配空間。

論壇徽章:
5
2015亞冠之阿爾艾因
日期:2015-08-10 02:23:34操作系統(tǒng)版塊每日發(fā)帖之星
日期:2015-08-13 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:1715-16賽季CBA聯(lián)賽之山西
日期:2016-04-13 02:36:59操作系統(tǒng)版塊每日發(fā)帖之星
日期:2016-04-14 06:20:00
30 [報(bào)告]
發(fā)表于 2016-04-05 02:25 |只看該作者
本帖最后由 pacman2000 于 2016-04-05 02:27 編輯

*異常處理

在核心系統(tǒng)開發(fā)和運(yùn)行中,異常處理是特別重要的一環(huán)。異常的規(guī)劃,對(duì)于系統(tǒng)的表現(xiàn)能力和查錯(cuò)能力有著巨大的作用,仔細(xì)的設(shè)計(jì)是十分值得的。
之前的報(bào)文格式中,提到Firebird的返回碼,是10位STRING。如果交易正常,返回碼為'OK',如果出錯(cuò),則為錯(cuò)誤代碼。如果為AS400系統(tǒng)級(jí)錯(cuò)誤,則為F+系統(tǒng)錯(cuò)誤代碼,如FCPF3282。如果是應(yīng)用錯(cuò)誤,則為E+應(yīng)用錯(cuò)誤代碼,如ECNBRNORL。另外,在返回報(bào)文中,還返回出錯(cuò)的程序源文件名,以及如果是系統(tǒng)錯(cuò)誤,要在日志中記錄出錯(cuò)的代碼行號(hào),訪問(wèn)的物理文件或者邏輯文件名等備查。

應(yīng)用部分的出錯(cuò)信息處理比較簡(jiǎn)單。Firebird沒有使用MSGF,而是普通的PF定義錯(cuò)誤代碼表,里面使用&1到&9用于文本的替換。應(yīng)用的錯(cuò)誤代碼根據(jù)模塊適用范圍,定義為E+[一級(jí)模塊]+[二級(jí)模塊]+錯(cuò)誤代碼,通用的錯(cuò)誤代碼模塊名可以省略。例如,EALEX表示“&1中&2記錄已經(jīng)存在”,ECNCMATDC表示“賬戶的余額性質(zhì)&1和余額方向&2不符”。在RPGLE程序中報(bào)應(yīng)用錯(cuò)誤的示例如下。

  1.       /FREE
  2.          CHAIN  K_CNTLMF  ACNTLMF.RACNTLMF  R_CNTLMF1;
  3.          IF  %FOUND(ACNTLMF);                //柜員已存在報(bào)錯(cuò)
  4.            PMG.BKMSID = 'EALEX';
  5.            A_MSDS(1) = C_MGTLMF;
  6.            A_MSDS(2) = C_MGTLNO + TLADF1.BKTLNO;
  7.            EXSR  #ERR;
  8.          ENDIF;
  9.        /END-FREE
  10.      **********************************************************************
  11.      ** #ERR 取錯(cuò)誤信息
  12.      **********************************************************************
  13.      C     #ERR          BEGSR
  14.      **
  15.      C                   EVAL      PMG.MSFLNM = PG_SRCMBR
  16.      C                   IF        PMG.BKMSDS = *BLANKS
  17.      C                   CALL      'SCNCMMG'
  18.      C                   PARM                    PMG
  19.      C                   PARM                    A_MSDS
  20.      C                   ENDIF
  21.      C                   EXSR      #EXIT
  22.      **
  23.      C                   ENDSR
  24.      **********************************************************************
復(fù)制代碼
其中PMG結(jié)構(gòu)保存了錯(cuò)誤代碼,報(bào)錯(cuò)文件名,錯(cuò)誤描述,在#ERR這個(gè)公用過(guò)程中,調(diào)用了SCNCMMG程序,以A_MSDS數(shù)組對(duì)&1到&9進(jìn)行了替換,結(jié)果放在PMG.BKMSDS中,層層傳遞到最外層主控程序。PMG.MSFLNM使用的是PSDS結(jié)構(gòu),這個(gè)在接下來(lái)會(huì)有介紹。還記得V7R1中的新增內(nèi)置函數(shù)%SCANRPL嗎,用于錯(cuò)誤信息替換正合適,V6R1就只能自己寫一大段處理程序了。

相對(duì)于應(yīng)用報(bào)錯(cuò)的寫法,RPGLE程序中系統(tǒng)錯(cuò)誤的捕獲和處理就有技巧得多。要做到使得應(yīng)用程序簡(jiǎn)單,又不縮減錯(cuò)誤信息,還要不遺漏所有出錯(cuò)場(chǎng)景處理,并不容易。在RPGLE程序中,處理異常通常有4種方法,有置出錯(cuò)指示器,(E)加%ERROR內(nèi)置函數(shù),設(shè)置錯(cuò)誤處理過(guò)程,MONITOR和ON-ERROR語(yǔ)句組。前兩種是以往系統(tǒng)常見的寫法,但是應(yīng)用程序就不好看,大段的系統(tǒng)錯(cuò)誤處理把正常邏輯都淹沒了。因此,F(xiàn)irebird選用了對(duì)應(yīng)用最透明的錯(cuò)誤處理過(guò)程寫法,達(dá)到絕大多數(shù)情況無(wú)需應(yīng)用關(guān)注即可捕獲異常組織錯(cuò)誤信息,如果有特殊處理,則可結(jié)合(E)加%ERROR使用,滿足特殊要求。下面分別詳細(xì)介紹程序錯(cuò)誤和文件錯(cuò)誤的錯(cuò)誤處理過(guò)程。

程序錯(cuò)誤的捕獲和報(bào)錯(cuò),在RPGLE中使用的是PSDS自動(dòng)結(jié)構(gòu),以及*PSSR異常處理過(guò)程。即在遇到錯(cuò)誤時(shí),系統(tǒng)自動(dòng)會(huì)設(shè)置PSDS結(jié)構(gòu)內(nèi)容,并調(diào)用*PSSR過(guò)程。

  1.      **程序狀態(tài)結(jié)構(gòu)
  2.      DRPGPSDS         SDS
  3.      D PG_MAINPROC             1     10A
  4.      D PG_STATUS              11     15A
  5.      D PG_PRVSTAT             16     20A
  6.      D PG_SRCLINE             21     28A
  7.      D PG_ROUTINE             29     36A
  8.      D PG_PARMNUM             37     39S 0
  9.      D PG_MSID                40     46A
  10.      D PG_PGMLIB              81     90A
  11.      D PG_EXCPDT              91    170A
  12.      D PG_LSERRFL            175    184A
  13.      D PG_JOBDATE            191    198A
  14.      D PG_FLINFO             209    243A
  15.      D PG_JOBNAME            244    253A
  16.      D PG_JOBUSER            254    263A
  17.      D PG_JOBNUM             264    269S 0
  18.      D PG_RUNDATE            276    281S 0
  19.      D PG_RUNTIME            282    287S 0
  20.      D PG_SRCFILE            304    313A
  21.      D PG_SRCLIB             314    323A
  22.      D PG_SRCMBR             324    333A
  23.      D PG_PGMNAME            334    343A
  24.      D PG_MODNAME            344    353A
  25.      D PG_SRCLNADD           354    355B 0
  26.      D PG_FLILNADD           356    357B 0
  27.      D PG_USRPRF             358    367A
  28.      D PG_EXTERR             368    371I 0
  29.      **********************************************************************
  30.      **特殊變量
  31.      **是否執(zhí)行過(guò)錯(cuò)誤處理程序
  32.      DPG_ERYNFG        S                   LIKE(DICT.@@YNFG) INZ(YNFG_NO)
  33.      **********************************************************************
  34.      ** *PSSR程序異常處理
  35.      **********************************************************************
  36.      C     *PSSR         BEGSR
  37.      **
  38.      C                   IF        PG_ERYNFG = YNFG_NO
  39.      C                   EVAL      PG_ERYNFG = YNFG_YES
  40.      C                   EVAL      PMG.MSFLNM = PG_SRCMBR
  41.      C                   EVAL      PMG.MSCDLN = PG_SRCLINE
  42.      C                   EVAL      PMG.BKMSID = 'F' + PG_MSID
  43.      C                   EVAL      PMG.BKMSDS = PG_EXCPDT
  44.      C                   EVAL      PMG.OTMSDS = PG_STATUS+' '+PG_PGMLIB+' '+
  45.      C                                          PG_PGMNAME
  46.      C                   EXSR      #EXIT
  47.      C                   ENDIF
  48.      **
  49.      C                   ENDSR
  50.      **********************************************************************
復(fù)制代碼
注意這里為了簡(jiǎn)化,PSDS沒有定義為QUALIFIED。PG_ERYNFG的作用,是為了防止錯(cuò)誤處理程序的多次重入(避免錯(cuò)誤程序中又拋出系統(tǒng)異常,導(dǎo)致無(wú)限遞歸)。
*PSSR過(guò)程中,通過(guò)結(jié)合PSDS結(jié)構(gòu),直接設(shè)置了系統(tǒng)異常錯(cuò)誤代碼(前面加了'F'),出錯(cuò)源文件名,出錯(cuò)源碼行號(hào),異常信息,以及附加信息,做到了報(bào)錯(cuò)信息組織的全自動(dòng)化。

文件錯(cuò)誤的捕獲和報(bào)錯(cuò),相對(duì)就復(fù)雜一些。在RPGLE中使用的是INFDS自動(dòng)結(jié)構(gòu),以及INFSR異常處理過(guò)程。即在遇到錯(cuò)誤時(shí),系統(tǒng)根據(jù)F表定義文件時(shí)指定的名字,自動(dòng)會(huì)設(shè)置INFDS結(jié)構(gòu)內(nèi)容,并調(diào)用INFSR過(guò)程。但是,這里有特例,如果在F表時(shí)就有錯(cuò)誤(比如自動(dòng)打開的文件不存在),那么仍然會(huì)執(zhí)行系統(tǒng)默認(rèn)異常處理而造成MSGW,這時(shí)候就需要外層主控進(jìn)行捕獲處理了。示例代碼節(jié)選如下。

  1.      FCCNTLCA   IF   E           K DISK    INFSR(#FLEX) INFDS(S_CNTLCA)
  2.      F                                     QUALIFIED
  3.      FACNTLTC   UF A E           K DISK    COMMIT QUALIFIED
  4.      F                                     INFSR(#FLEX) INFDS(S_CNTLTC)
  5.      **********************************************************************
  6.      **記錄被鎖錯(cuò)誤信息
  7.      DC_MGLOCK         C                   CONST('記錄被鎖')
  8.      **文件狀態(tài)結(jié)構(gòu)
  9.      DFILESDS          DS                  BASED(FILEDSP)
  10.      D FL_FILE                 1      8A
  11.      D FL_OPNIND               9      9A
  12.      D FL_EOFIND              10     10A
  13.      D FL_STATUS              11     15S 0
  14.      D FL_OPCODE              16     21A
  15.      D FL_ROUTINE             22     29A
  16.      D FL_SRCLINE             30     37A
  17.      D FL_RECORD              38     45A
  18.      D FL_MSID                46     52A
  19.      D FL_SRCLNADD            77     78B 0
  20.      D FL_ODPTYPE             81     82A
  21.      D FL_FILENAME            83     92A
  22.      D FL_LIBRARY             93    102A
  23.      D FL_SPLFILE            103    112A
  24.      D FL_SPLLIB             113    122A
  25.      D FL_RCDLEN             125    126I 0
  26.      D FL_KEYLEN             127    128I 0
  27.      D FL_MEMBER             129    138A
  28.      D FL_TYPE               147    148I 0
  29.      D FL_RCDNUM             156    159I 0
  30.      D FL_SPLNUM             160    163I 0
  31.      D FL_OVERFLOW           188    189I 0
  32.      D FL_BASEDMBRS          211    212I 0
  33.      D FL_OPENID             214    215B 0
  34.      D FL_RCDFMTLEN          216    217I 0
  35.      D FL_CCSID              218    219I 0
  36.      D FL_FBSIZE             367    370I 0
  37.      D FL_KEYNUM             387    388I 0
  38.      D FL_FBKEYLEN           393    394I 0
  39.      D FL_MBRNUM             395    396I 0
  40.      D FL_RRN                397    400I 0
  41.      D FL_KEY                401   2400A
  42.      **文件狀態(tài)結(jié)構(gòu)指針
  43.      DFILEDSP          S               *
  44.      **
  45.      DS_CNTLCA         DS                  LIKEDS(FILESDS)
  46.      DR_CNTLCA         DS                  LIKEREC(CCNTLCA.RCCNTLCA:*INPUT)
  47.      DK_CNTLCA         DS                  LIKEREC(CCNTLCA.RCCNTLCA:*KEY)
  48.      **
  49.      DS_CNTLTC         DS                  LIKEDS(FILESDS)
  50.      DR_CNTLTC1        DS                  LIKEREC(ACNTLTC.RACNTLTC:*INPUT)
  51.      DR_CNTLTC2        DS                  LIKEREC(ACNTLTC.RACNTLTC:*OUTPUT)
  52.      DK_CNTLTC         DS                  LIKEREC(ACNTLTC.RACNTLTC:*KEY)
  53.      **
  54.       /FREE
  55.            CLEAR  R_CNTLCA;                //取角色表信息
  56.            CLEAR  K_CNTLCA;
  57.            FILEDSP = %ADDR(S_CNTLCA);
  58.            K_CNTLCA.BKCHGN = TLADF3.ARR(V_RECD1).BKCHGN ;
  59.            CHAIN  %KDS(K_CNTLCA)  CCNTLCA.RCCNTLCA  R_CNTLCA ;
  60.            IF  NOT %FOUND(CCNTLCA);
  61.              PMG.BKMSID = 'ENTRD';
  62.              A_MSDS(1) = C_MGTLCA;
  63.              A_MSDS(2) = C_MGCHGN + TLADF3.ARR(V_RECD1).BKCHGN;
  64.              EXSR #ERR;
  65.            ENDIF;
  66.        /END-FREE
  67.      **********************************************************************
  68.      ** #FLEX文件異常處理
  69.      **********************************************************************
  70.      C     #FLEX         BEGSR
  71.      **
  72.      C                   EVAL      PMG.MSFLNM = PG_SRCMBR
  73.      C                   EVAL      PMG.MSCDLN = FL_SRCLINE
  74.      C                   EVAL      PMG.BKMSID = 'F' + FL_MSID
  75.      C                   IF        FL_STATUS = 1218
  76.      C                   CALL      'GETOBJTXT'
  77.      C                   PARM      FL_LIBRARY    V_FLEXLIB        10
  78.      C                   PARM      FL_FILENAME   V_FLEXOBJ        10
  79.      C                   PARM      '*FILE'       V_FLEXTYP         7
  80.      C                   PARM      *BLANKS       V_FLEXTEXT       50
  81.      C                   EVAL      PMG.BKMSDS = %TRIM(V_FLEXTEXT) +
  82.      C                                          %TRIM(FL_FILENAME) + '.' +
  83.      C                                          %TRIM(FL_MEMBER) + C_MGLOCK +
  84.      C                                          ',' + PG_EXCPDT
  85.      C                   ELSE
  86.      C                   EVAL      PMG.BKMSDS = PG_EXCPDT
  87.      C                   ENDIF
  88.      C                   EVAL      PMG.OTMSDS = PG_FLINFO
  89.      C                   EXSR      #EXIT
  90.      **
  91.      C                   ENDSR
  92.      **********************************************************************
復(fù)制代碼
這段就需要解釋一下了。首先,F(xiàn)表定義的多個(gè)文件,INFSR可以共用一個(gè),但I(xiàn)NFDS系統(tǒng)要求是不能共享的,必須每個(gè)文件定義一份。為了#FLEX的通用寫法,因此對(duì)FILESDS指定了一個(gè)指針FILEDSP,每次在文件操作前,程序中像這樣FILEDSP = %ADDR(S_CNTLCA)設(shè)置指針指向要操作文件對(duì)應(yīng)的FILESDS結(jié)構(gòu)。然后如果后續(xù)的文件操作出錯(cuò),F(xiàn)ILEDSP指向被自動(dòng)填充的文件結(jié)構(gòu),系統(tǒng)執(zhí)行#FLEX過(guò)程,類似程序異常一樣做到了報(bào)錯(cuò)信息組織的全自動(dòng)化。這里特別注意對(duì)于錯(cuò)誤狀態(tài)1218,即文件記錄被鎖定超時(shí),拋出的錯(cuò)誤帶經(jīng)過(guò)GETOBJTXT轉(zhuǎn)換的PF中文注釋,形如“柜員角色表CCNTLCA.CCNTLCA記錄被鎖”,對(duì)渠道端錯(cuò)誤信息展示更友好。

  1. /*BEGIN***************************************************************/
  2. /*程序名稱:GETOBJTXT                                              */
  3. /*功能描述:                                                       */
  4. /*                                                                   */
  5. /*設(shè)計(jì)人員:PACMAN          開發(fā)人員:PACMAN                     */
  6. /*設(shè)計(jì)日期:2014-11-27      開發(fā)日期:2014-11-27                 */
  7. /*-------------------------------------------------------------------*/
  8. /*維護(hù)人員:                                                       */
  9. /*維護(hù)日期:                                                       */
  10. /*維護(hù)內(nèi)容:                                                       */
  11. /*                                                                   */
  12. /*END*****************************************************************/

  13.              PGM        PARM(&LIBNM &OBJNM &OBJTP &TEXT)
  14.              INCLUDE    SRCMBR(CLHD) SRCFILE(DSCPPGM)
  15.              DCL        VAR(&LIBNM) TYPE(*CHAR) LEN(10)
  16.              DCL        VAR(&OBJNM) TYPE(*CHAR) LEN(10)
  17.              DCL        VAR(&OBJTP) TYPE(*CHAR) LEN(7)
  18.              DCL        VAR(&TEXT) TYPE(*CHAR) LEN(50)
  19.              IF         COND(&LIBNM *EQ ' ') THEN(DO)
  20.              CHGVAR     VAR(&LIBNM) VALUE('*LIBL')
  21.              ENDDO
  22.              RTVOBJD    OBJ(&LIBNM/&OBJNM) OBJTYPE(&OBJTP) TEXT(&TEXT)
  23.              MONMSG     MSGID(CPF0000)
  24. ENDPGM:     ENDPGM
復(fù)制代碼
在真正的組件和交易程序中,PSDS,F(xiàn)ILESDS結(jié)構(gòu)都封裝到/COPY的PGDS中,#ERR,*PSSR,#FLEX都封裝到/COPY的PGCM中,應(yīng)用程序篇幅就簡(jiǎn)化了很多。

通過(guò)*PSSR和#FLEX解決了大部分問(wèn)題,但最后還遺留了一點(diǎn)會(huì)造成MSGW的未能捕獲的異常。這種情況顯然也不能放過(guò),就需要更高級(jí)的主控程序處理了。聯(lián)機(jī)交易主控程序MONSVR會(huì)掃描監(jiān)視真正執(zhí)行的JOBSVR,結(jié)束掉MSGW的JOBSVR并記錄出錯(cuò)信息,然后重新啟動(dòng)一個(gè)新的代替。MONSVR代碼片段如下。

  1.   /*保存最大啟動(dòng)進(jìn)程數(shù)*/
  2.   arr[0]=num;
  3.   freenum=num;

  4.     /*監(jiān)測(cè)子進(jìn)程是否正常*/
  5.     for (i=arr[0];i>=1;i--)
  6.     {
  7.       if (arr[i]!=0)
  8.       {
  9.         char reason[3009];

  10.         memset(reason, 0, sizeof(reason));
  11.         rc=checkJob(arr[i], reason);
  12.         if (rc==1)
  13.         {
  14.           if (i<=num && new_reg_ver!=0)
  15.             writeLog("WARNING", JOBNAME, __FILE__, __LINE__,
  16.                      "任務(wù)S%05d%03d %d不存在", port, i, arr[i]);
  17.           else
  18.             debugLog(svrdebug, JOBNAME, __FILE__, __LINE__,
  19.                      "任務(wù)S%05d%03d %d已退出", port, i, arr[i]);
  20.           arr[i]=0;
  21.         }
  22.         else if (rc==2)
  23.         {
  24.           writeLog("INFO", JOBNAME, __FILE__, __LINE__,
  25.                    "任務(wù)S%05d%03d %d已出錯(cuò):%s", port, i, arr[i],
  26.                    reason);
  27.           if (!svrdebug)
  28.           {
  29.             endJob(arr[i]);
  30.             arr[i]=0;
  31.           }
  32.         }
  33.         else if (rc==3)
  34.             freenum++;
  35.       }
  36.       if (i==arr[0] && arr[i]==0)
  37.         arr[0]--;
  38.     }

  39.     /*保存最大啟動(dòng)進(jìn)程數(shù)*/
  40.     arr[0] = arr[0]>num ? arr[0] : num;
  41.     /*檢驗(yàn)進(jìn)程是否存在并啟動(dòng)*/
  42.     for (i=1;i<=num;i++)
  43.     {
  44.       if (arr[i]==0)
  45.       {
  46.         sprintf(jobname,"S%05d%03d",port,i);
  47.         sprintf(argstr, "%d %d %d %d %d %d", port, savedate,
  48.                 reg_ver, reg_num, i, bakmode);
  49.         pid=spawn(pathstr, 1, spawn_fdmap, &inherit, spawn_argv,
  50.                   spawn_envp);
  51.         if (pid<0)
  52.         {
  53.           writeLog("WARNING", JOBNAME, __FILE__, __LINE__, "重啟%s出錯(cuò)%d",
  54.                    jobname, errno);
  55.           arr[i]=0;
  56.         }
  57.         else
  58.         {
  59.           arr[i]=pid;
  60.           debugLog(svrdebug, JOBNAME, __FILE__, __LINE__,
  61.                    "重啟%s成功%d", jobname, pid);
  62.         }
  63.       }
  64.     }
復(fù)制代碼
其中重要的是這么幾點(diǎn),checkJob()用于檢查某個(gè)pid進(jìn)程的狀態(tài),如果MSGW則獲取詳細(xì)出錯(cuò)信息到reason字符串中。endJob()用于結(jié)束一個(gè)pid進(jìn)程。spawn()函數(shù)產(chǎn)生一個(gè)進(jìn)程執(zhí)行指定的程序。通過(guò)writeLog(),MONSVR將出錯(cuò)的進(jìn)程和錯(cuò)誤信息寫到主控日志備查。下面是checkJob和endJob的代碼。

  1. /*BEGIN***************************************************************/
  2. /*程序名稱:JOBCTL                                                 */
  3. /*功能描述:任務(wù)相關(guān)的調(diào)用封裝                                     */
  4. /*                                                                   */
  5. /*設(shè)計(jì)人員:PACMAN          開發(fā)人員:PACMAN                     */
  6. /*設(shè)計(jì)日期:2011-11-11      開發(fā)日期:2011-11-11                 */
  7. /*-------------------------------------------------------------------*/
  8. /*維護(hù)人員:                                                       */
  9. /*維護(hù)日期:                                                       */
  10. /*維護(hù)內(nèi)容:                                                       */
  11. /*                                                                   */
  12. /*END*****************************************************************/

  13. #include <string.h>
  14. #include <sys/types.h>
  15. #include <qp0wpid.h>

  16. #include "dscppgm/cpyrgt_h"

  17. extern void ENDJOBCL(char *jobnb, char *usrnm, char*jobnm);
  18. extern void GETJOBCL(char *jobnb, char *usrnm, char*jobnm, char *rtcd,
  19.                      char *reason);

  20. /*返回1表示未找到,返回2表示MSGW*/
  21. int checkJob(pid_t pid, char *reason)
  22. {
  23.   QP0W_Job_ID_T jobinfo;
  24.   int ret;
  25.   char rtcd[1];

  26.   ret=Qp0wGetJobID(pid, &jobinfo);
  27.   if (ret!=0)
  28.     return 1;
  29.   GETJOBCL(jobinfo.jobnumber, jobinfo.username, jobinfo.jobname, rtcd,
  30.            reason);
  31.   return rtcd[0]-'0';
  32. }

  33. int endJob(pid_t pid)
  34. {
  35.   QP0W_Job_ID_T jobinfo;
  36.   int ret;

  37.   ret=Qp0wGetJobID(pid, &jobinfo);
  38.   if (ret!=0)
  39.     return ret;
  40.   ENDJOBCL(jobinfo.jobnumber, jobinfo.username, jobinfo.jobname);
  41.   return 0;
  42. }

  43. int getJobname(pid_t pid, char *name)
  44. {
  45.   QP0W_Job_ID_T jobinfo;
  46.   int ret;

  47.   ret=Qp0wGetJobID(pid, &jobinfo);
  48.   if (ret!=0)
  49.     return ret;
  50.   strncpy(name, jobinfo.jobname, 10);
  51.   name[10]='\0';
  52.   return 0;
  53. }
復(fù)制代碼
里面使用了GETJOBCL和ENDJOBCL這兩個(gè)CL程序。代碼如下。

  1. /*BEGIN***************************************************************/
  2. /*程序名稱:GETJOBCL                                               */
  3. /*功能描述:獲取指定任務(wù)的運(yùn)行狀態(tài)                                 */
  4. /*           RTCD   返回狀態(tài)                                       */
  5. /*                  '0'    正常                                    */
  6. /*                  '1'    未找到                                  */
  7. /*                  '2'    MSGW                                      */
  8. /*                  '3'    TIMW或TIMA                              */
  9. /*           REASON MSGW原因,前7位為MSGID后3000字節(jié)為原因   */
  10. /*                                                                   */
  11. /*設(shè)計(jì)人員:PACMAN          開發(fā)人員:PACMAN                     */
  12. /*設(shè)計(jì)日期:2011-11-11      開發(fā)日期:2011-11-11                 */
  13. /*-------------------------------------------------------------------*/
  14. /*維護(hù)人員:                                                       */
  15. /*維護(hù)日期:                                                       */
  16. /*維護(hù)內(nèi)容:                                                       */
  17. /*                                                                   */
  18. /*END*****************************************************************/

  19.              PGM        PARM(&JOBNUM &USRNAM &JOBN &RTCD &REASON)
  20.              INCLUDE    SRCMBR(CLHD) SRCFILE(DSCPPGM)
  21.              DCL        VAR(&JOBNUM) TYPE(*CHAR) LEN(6)
  22.              DCL        VAR(&USRNAM) TYPE(*CHAR) LEN(10)
  23.              DCL        VAR(&JOBN) TYPE(*CHAR) LEN(10)
  24.              DCL        VAR(&RTCD) TYPE(*CHAR) LEN(1)
  25.              DCL        VAR(&JOBINF) TYPE(*CHAR) LEN(225)
  26.              DCL        VAR(&JOBST) TYPE(*CHAR) LEN(10)
  27.              DCL        VAR(&JOBACTST) TYPE(*CHAR) LEN(4)
  28.              DCL        VAR(&MSGKEY) TYPE(*CHAR) LEN(4)
  29.              DCL        VAR(&MSGQUE) TYPE(*CHAR) LEN(10)
  30.              DCL        VAR(&MSGLIB) TYPE(*CHAR) LEN(10)
  31.              DCL        VAR(&MSGASP) TYPE(*CHAR) LEN(10)
  32.              DCL        VAR(&JOBNAM) TYPE(*CHAR) LEN(26)
  33.              DCL        VAR(&SENDER) TYPE(*CHAR) LEN(80)
  34.              DCL        VAR(&REASON) TYPE(*CHAR) LEN(3008)
  35.              DCL        VAR(&MSGID)  TYPE(*CHAR) LEN(7)
  36.              DCL        VAR(&MSGHLP) TYPE(*CHAR) LEN(3000)
  37.              CHGVAR     VAR(&RTCD) VALUE('0')
  38.              CHGVAR     VAR(&JOBNAM) VALUE(&JOBN *CAT &USRNAM *CAT +
  39.                           &JOBNUM)
  40.              CHGVAR     VAR(&SENDER) VALUE(&JOBNAM)
  41.              CALL       PGM(QUSRJOBI) PARM(&JOBINF X'000000D1' +
  42.                           'JOBI0200' &JOBNAM ' ')
  43.              MONMSG     MSGID(CPF3C51 FPF3C52 CPF3C53 CPF3C54 +
  44.                           CPF3C55) EXEC(DO)
  45.              CHGVAR     VAR(&RTCD) VALUE('1')
  46.              GOTO       CMDLBL(END)
  47.              ENDDO
  48.              CHGVAR     VAR(&JOBST) VALUE(%SST(&JOBINF 51 10))
  49.              CHGVAR     VAR(&JOBACTST) VALUE(%SST(&JOBINF 108 4))
  50.              IF         COND(&JOBACTST *EQ 'MSGW') THEN(DO)
  51.              CHGVAR     VAR(&RTCD) VALUE('2')
  52.              CHGVAR     VAR(&MSGKEY) VALUE(%SST(&JOBINF 192 4))
  53.              CHGVAR     VAR(&MSGQUE) VALUE(%SST(&JOBINF 196 10))
  54.              CHGVAR     VAR(&MSGLIB) VALUE(%SST(&JOBINF 206 10))
  55.              CHGVAR     VAR(&MSGASP) VALUE(%SST(&JOBINF 216 10))
  56.              RCVMSG     MSGQ(&MSGQUE) MSGTYPE(*INQ) RMV(*NO) +
  57.                         MSGKEY(&MSGKEY) SECLVL(&MSGHLP) +
  58.                         MSGID(&MSGID) +
  59.                         SENDER(&SENDER) SENDERFMT(*SHORT)
  60.              MONMSG     MSGID(CPF0000) EXEC(DO)
  61.              GOTO       CMDLBL(END)
  62.              ENDDO
  63.              CHGVAR     VAR(&REASON) VALUE(&MSGID *CAT ':' *CAT +
  64.                           &MSGHLP)
  65.              GOTO       CMDLBL(END)
  66.              ENDDO
  67.              IF         COND((&JOBACTST *EQ 'TIMW') *OR (&JOBACTST +
  68.                           *EQ 'TIMA')) THEN(DO)
  69.              CHGVAR     VAR(&RTCD) VALUE('3')
  70.              ENDDO
  71. END:
  72.              ENDPGM
復(fù)制代碼

  1. /*BEGIN***************************************************************/
  2. /*程序名稱:ENDJOBCL                                               */
  3. /*功能描述:結(jié)束指定任務(wù)                                           */
  4. /*                                                                   */
  5. /*設(shè)計(jì)人員:PACMAN          開發(fā)人員:PACMAN                     */
  6. /*設(shè)計(jì)日期:2011-11-11      開發(fā)日期:2011-11-11                 */
  7. /*-------------------------------------------------------------------*/
  8. /*維護(hù)人員:                                                       */
  9. /*維護(hù)日期:                                                       */
  10. /*維護(hù)內(nèi)容:                                                       */
  11. /*                                                                   */
  12. /*END*****************************************************************/

  13.              PGM        PARM(&JOBNB &USRNM &JOBNM)
  14.              INCLUDE    SRCMBR(CLHD) SRCFILE(DSCPPGM)
  15.              DCL        VAR(&JOBNB) TYPE(*CHAR) LEN(6)
  16.              DCL        VAR(&USRNM) TYPE(*CHAR) LEN(10)
  17.              DCL        VAR(&JOBNM) TYPE(*CHAR) LEN(10)
  18.              ENDJOB     JOB(&JOBNB/&USRNM/&JOBNM) OPTION(*IMMED)
  19.              MONMSG     MSGID(CPF1321)
  20.              ENDPGM
復(fù)制代碼
批處理的主控也是類似,使用GETJOBCL和ENDJOBCL進(jìn)行批量任務(wù)分段JOB的監(jiān)視和錯(cuò)誤登記,這里就不再贅述了。

通過(guò)主控,RPGLE程序?qū)訉影殃P(guān),以及統(tǒng)一的錯(cuò)誤處理程序,F(xiàn)irebird減輕了應(yīng)用開發(fā)人員的錯(cuò)誤處理負(fù)擔(dān),并且讓錯(cuò)誤信息更為友好,盡可能的保存了錯(cuò)誤的豐富信息,這對(duì)于系統(tǒng)的維護(hù)可以帶來(lái)很大的幫助。而這些,正是系統(tǒng)設(shè)計(jì)時(shí)就需要重視并在整體架構(gòu)里考慮,才能做好的。
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過(guò)ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP