出力処理

本章では、出力の概念および処理方法について説明します。

1. 概要

出力処理では、ジョブの実行中に作成されたSYSOUTをジョブの終了後に処理します。

SYSOUTは、出力という単位で処理されます。出力処理は、SYSOUTの内容をプリンターで出力、インターナル・リーダーを使用してJOBQにサブミット、そして指定のエクスターナル・ライターを使用して処理する3つのプロセスで構成されます。

SYSOUTの属性に応じて、実行される処理が決まります。

  1. OpenFrameでのプリンター出力とは、物理的なプリンターではなく、外部プリンター・ソリューションに印刷するデータと、印刷に使用されるリソース情報(FORMS、FORMDEF、PAGEDEFなど)を送信することです。外部プリンター・ソリューションにデータと情報を送信するため、OpenFrame環境設定のprintサブジェクトのPRINTnセクションのCOMMANDDRIVER_PATHキーのVALUE項目に必要なコマンドと共有ライブラリのパスを設定します。

  2. インターナル・リーダーを使用してサブミットする場合は、OpenFrame環境設定のprintサブジェクトのINTRDRセクションのDRIVER_PATHキーのVALUE項目に必要な共有ライブラリ・パスを設定します。

  3. エクスターナル・ライターを使用する場合は、OpenFrame環境設定のprintサブジェクトのWRITERセクションにエクスターナル・ライターの名前と必要な共有ライブラリ・パスを設定します。

printサブジェクトの設定方法については、OpenFrame Batch『環境設定ガイド』を参照してください。

2. 出力

出力は、出力処理の単位です。ジョブの実行が終了すると、そのジョブが作成したスプール・データセットを出力処理する必要があります。

出力は、JCLのSYSOUT文とOUTPUT文によって決まります。通常は、1つのスプール・データセットが1つの出力として処理されますが、以下の例のように1つ以上の出力として処理されることもあります。

以下ようにJCLが構成されると、1つのスプール・データセットが複数の出力処理に使用されます。

//OUT01  OUTPUT  FORMDEF=FORM1
//OUT02  OUTPUT  FROMS=LETTER01,FROMDEF=LTR1,PAGEDEF=LTR4
//PRT    DD  SYSOUT=A, OUTPUT=(*.OUT01,*.OUT02)

上記のJCLでは、PRT DDは、OUT01とOUT02の2つのOUTPUT DDを参照しています。ジョブの実行が終了すると、OUT01のOUTPUT文を参照する出力とOUT02のOUTPUT文を参照する出力が処理されます。

  • OUT01を参照する出力が処理されると、FORM1のFORMDEFフォーマットでPRT DDに定義されたスプール・データセットの内容が基本用紙に印刷されます。

  • OUT02を参照する出力が処理されると、LTR1のFORMDEFフォーマットとLTR4のPAGEDEFフォーマットで、LETTER01用紙にスプール・データセットの内容が印刷されます。

3. 出力処理

ジョブの実行が終了すると、スプール・データセットは出力単位でOUTPUTQに登録されます。登録された出力は、ofrpmsvrによってスケジューリングされ、一般プリンターまたはエクスターナル・ライターによって処理されるか、あるいはインターナル・リーダーによって再サブミットされます。ofrpmsvrは、OUTPUTQから出力の状態を確認して出力を取り出して、OpenFrame環境設定のprintサブジェクトのPRINTnセクションのCLASSキーのVALUE項目と出力クラスを比較してスケジューリングし、OUTPUT DISPOSITIONに従って処理します。

3.1. 出力の状態

OUTPUTQに登録された出力の状態を示します。出力の状態は、ofrpmsvrによって処理される際に変更されます。

以下は、出力状態の種類です。

種類 説明

Unable (U)

作成初期の状態です。スケジュールされず、OUTPUTQに待機している状態です。

Ready (R)

OUTPUTQから取り出され、スケジュールされる前の状態です。

Print (P)

スケジューリングされ、ジョブがPRINTERn、インターナル・リーダー、またはエクスターナル・ライターに送信された状態です。

Hold (H)

OUTPUT DISPOSITIONがLEAVEの場合、出力の処理後、OUTPUTQで待機中の状態です。

Cancel (C)

ユーザーによって出力処理が取り消された状態です。

Error (E)

PRINTERn、インターナル・リーダーまたはエクスターナル・ライターに送信されたジョブにエラーが発生した状態です。

ジョブの実行中に登録される出力の初期状態はUです。ofrpmsvrは、定義的にOUTPUTQをスキャンし、登録された出力からUまたはR状態の出力を取り出してR状態に更新し、ジョブをスケジューリングします。その後、ofrpmsvrは、プリンター、インターナル・リーダー、またはエクスターナル・ライターに出力処理を送信して、P(Print)状態に更新します。OUTPUT DISPOSITIONが「LEAVE」の場合は、出力が正常に処理された後、H状態に変更され、OUTPUTQで待機することになります。

出力処理中にtjesmgrを通したユーザー・コマンドによって出力が「PURGE」されると、その出力はC状態になります。また、プリンター処理中にエラーが発生した場合の出力は、E状態に更新されます。

3.2. 出力クラス

出力に付与された1バイトの文字(A-Z、0-9)です。出力クラスはJCLに記述されます。

SYSOUT文にクラスが指定された場合は、OUTPUT文に出力クラスを指定しても、SYSOUT文に指定された値によって上書きされるため、SYSOUT文にはクラスを指定しないでください。

以下は、PRINT DDの出力クラスを「Y」に指定した例です。

//OUT1     OUTPUT CLASS=Y,FORM=TEST
//PRINT    DD SYSOUT=(,),OUTPUT=*.OUT1

SYSOUT文で出力クラスを指定する場合、PRINT DDの出力クラスがAに指定されます。

//PRINT    DD SYSOUT=A

出力クラスをアスタリスク(*)に指定した場合は、JOB文のMSGCLASSに指定されたクラスが出力クラスとして指定されます。

以下の例では、PRINT DDの出力クラスが「X」に指定されます。

//COPY02   JOB CLASS=I,MSGCLASS=X,MSGLEVEL=(1,1)
...

//PRINT    DD SYSOUT=*
  • 出力クラスの優先順位

    出力クラスの設定は、以下の順で適用されます。

    1. SYSOUT=class

    2. OUTPUT CLASS=class

    3. JOB MSGCLASS=class

    SYSOUT文にクラスが指定された場合は、OUTPUT文にクラスを指定しても、SYSOUT文に指定された値が優先して適用されます。

    「SYSOUT=* 」または「SYSOUT=(,)」のようにクラスが明示されていない場合は、OUTPUT CLASSパラメータに指定された値が適用されます。SYSOUT文にクラスが指定されておらず、OUTPUT文にもCLASSパラメータを指定していない場合は、JOB文のMSGCLASSに指定された値が出力クラスとして適用されます。

    上記のいずれにもクラスを指定していない場合は、OpenFrame環境設定のtjclrunサブジェクトのJOBセクションのMSGCLASSキーのVALUE項目に設定された値が使用されます。

3.3. 出力の処理方式

OUTPUT DISPOSITIONは、ジョブの出力を処理する方式です。ジョブが正常に終了したかどうかによって、正常処理と異常処理に分けられます。

以下の図は、ジョブの出力処理方式を示しています。

figure 5 1
ジョブの出力処理方式

以下は、ジョブの出力処理方式についての説明です。

種類 説明

WRITE

出力がスケジューリングされ、印刷される必要があることを示します。正常に処理されたら、出力は削除されます。

HOLD

ユーザーが解除するまで出力はスケジューリングされずにOUTPUTQで待機します。ユーザーによって解除されると、処理方式はWRITEに変更されます。

KEEP

WRITEと同様に、出力がスケジューリングされ、印刷される必要があることを示します。正常に処理されたら、処理方式がLEAVEに変更されます。

LEAVE

ユーザーが解除するまで出力はスケジューリングされずにOUTPUTQで待機します。ユーザーによって解除されると、処理方式はKEEPに変更されます。

PURGE

出力をOUTPUTQから削除します。

以下は、ジョブの出力処理方式を設定する方法です。

  1. JCLのOUTPUT文で指定します。

    以下は、PRINT DDのOUTPUT DISPOSITIONに正常処理方式としてWRITE、異常処理方式としてPURGEを指定した例です。つまり、JCLが実行され、ジョブが正常に終了した場合は出力を処理し、ジョブが異常終了した場合は出力を処理しません。

    //OUT1     OUTPUT  OUTDISP=(WRITE,PURGE)
    //PRINT    DD SYSOUT=(A,),OUTPUT=*.OUT1
  2. 以下の例で、SUBM DDはINTRDR属性を持ちます。

    ジョブの終了後、SUBM DDに定義されたSYSOUTデータは、インターナル・リーダーによってサブミットされます。

    //SUBM    DD SYSOUT=(A,INTRDR)
  3. JCLのOUTPUT文で指定していない場合は、出力クラスに応じてOpenFrame環境設定の設定値が使用されます。

    たとえば、OpenFrame環境設定のtjesサブジェクトのOUTCLASSセクションの出力クラスに応じて出力の処理方式は以下の例のように定義されます。出力クラスがAの場合は「WRITE, WRITE」に指定され、出力クラスがBの場合は「HOLD, PURGE」に指定されます。出力クラスに対応する処理方式がOUTCLASSセクションに定義されていない場合は、デフォルト値として「PURGE, PURGE:80」が使用されます。

    $ ofconfig list -n NODE1 -s tjes -sec OUTCLASS
    
    ===================================================================================
      SUBJECT   |     SECTION      |         KEY         |            VALUE
    ===================================================================================
        tjes    |     OUTCLASS     |          A          |         WRITE,WRITE
                |                  |          B          |         HOLD,PURGE
    ===================================================================================

OUTPUTQに保存された出力には、インターナル・リーダーを通じて再びジョブとしてサブミットされるもの、外部ライターに送信されるもの、そしてレポートとして印刷されるべきものが含まれます。

インターナル・リーダーを介して処理される出力は、出力処理方式がWRITEまたはKEEPです。また、OpenFrame環境設定のprintサブジェクトのINTRDRセクションに登録されている場合は、出力クラスに関係なく、常にインターナル・リーダーによってサブミットされます。

エクスターナル・ライターに転送されるべき出力は、インターナル・リーダーと同様に、出力処理がWRITEまたはKEEPに設定されている必要があります。OpenFrame環境設定のprintサブジェクトのWRITERセクションに、SMTPP(SMTP)のようなエクスターナル・ライター名をキーとして登録し、そのエクスターナル・ライターを呼び出す共有ライブラリのパスを値として指定しておけば、OUTPUT CLASSに関係なく、そのライブラリが呼び出されて実行されます。

印刷待ちの出力は、出力処理方式がWRITEまたはKEEPの場合は、出力クラス情報を、OpenFrame環境設定のprintサブジェクトのPRINTERnセクションに登録されたクラス情報と比較して、情報が正しければ印刷されます。PRINTERnセクションに登録されたクラス情報にSYSOUT文の出力クラスが含まれている場合、ofrpmsvrはPRINTERnセクションに設定されたコマンドと共有ライブラリを使用して、データと印刷リソース情報を外部プリンター・ソリューションに送信します。

3.4. インターナル・リーダー

インターナル・リーダーは、Online CICSまたはバッチ・プログラムがジョブをTJESにサブミットできるようにするモジュールです。OpenFrame上で動作するすべてのジョブは、インターナル・リーダーを介してサブミットできます。

DD文にSYSOUT=(out_class,INTRDR)と記述して、DDに保存された内容がインターナル・リーダーを介して出力されるようにします。

以下は、インターナル・リーダーの使用方法です。

###########################################################################
## IEBEDT05 - iebedit SYSUT1 JCL and extract RMSTEP1 only.               ##
##            then submit it to intrdr                                   ##
###########################################################################
//IEBEDT05 JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1)
//IEBEDT   EXEC PGM=IEBEDIT
//SYSIN    DD *
    EDIT START=,TYPE=INCLUDE
/*
//SYSUT2   DD SYSOUT=(A,INTRDR)
//SYSUT1   DD DATA
インターナル・リーダーを介してサブミットしようとするJCLの内容
/*
//

上記のJCLは、SYSUT1 DDに与えられたJCLをSYSUT2にコピーし、SYSUT2をクラスAのインターナル・リーダーを介して出力するジョブです。

上記のように、JCLにユーザーとパスワードが指定されていない場合、インターナル・リーダーは、OpenFrame環境設定のtjesサブジェクトのINTRDRセクションのUSERNAMEPASSWORDキーのVALUE項目に設定された値を使用してJCLをサブミットします。

3.5. エクスターナル・ライター

エクスターナル・ライターは、ジョブの実行後に生成された出力を、共有ライブラリを介してSMTPなどOpenFrameが提供しない外部機能を呼び出して処理できるようにするモジュールです。

エクスターナル・ライターを使用するには、DD文にSYSOUT=(out_class,external_writer_name)の形式で記述し、OpenFrame環境設定のprintサブジェクトのWRITERセクションにexternal_writer_nameに該当するキーとその値を指定する必要があります。OpenFrameでは、エクスターナル・ライターとしてSMTPP(SMTP)のみサポートしています。

OpenFrameでSMTPP(SMTP)を使用するには、以下の2つのソフトウェアが必要です。

  • MTA(Mail transport Agent)

    メールの送受信を担当するメール転送エージェントで、通常はSMTPプロトコルのポート番号「25番」を使用します。代表的なものとしては、sendmailやpostfixなどがあります。

  • Netcat

    TCPまたはUDPプロトコルを用いてネットワーク接続を行い、データを送受信できるユーティリティです。 OpenFrameでは、Netcatコマンドを使用してSMTPポート(25番)に直接接続し、メールデータを送信します。その後、postfixなどのMTAを通じて実際のメールが送信されます。

以下は、SMTPP(SMTP)エクスターナル・ライターの使用方法です。

//EXTJOB   JOB (MDB114J),'          ',
//         CLASS=A,
//         MSGCLASS=K,
//         MSGLEVEL=(1,1),
//         NOTIFY=&SYSUID
//*
//JCLLIB   JCLLIB ORDER=(SCDC.PROD.JCLLIB)
//*
//JOBLIB   INCLUDE MEMBER=JOBLIB
//JSTEP01  EXEC PGM=IEBGENER
//SYSIN    DD DUMMY (MODE=I)
//SYSPRINT DD SYSOUT=*
//SYSUT2   DD SYSOUT=(B,SMTPP)
//SYSUT1   DD *
HELO JES2PRD1
MAIL FROM:<sender@tmax.co.kr>
RCPT TO:<recipient@tmax.co.kr>
/*
//         DD *
DATA
SUBJECT: SMTP TEST

THIS IS A TEST MAIL, From OpenFrame
PROCESSING.
/*
//*

上記のJCLは、SYSUT1 DDに与えられたJCLをSYSUT2にコピーし、SYSUT2をSYSOUTに指定されたエクスターナル・ライターのSMTPP(SMTP)を介してSMTPサーバーにメール送信するジョブです。

SMTP(SMTPP)モジュールの動作構造は以下のとおりです。

figure 5 2
SMTPの動作構造
  1. JCLのメール関連データを加工して、ファイルとして保存します。

  2. Netcatユーティリティを使用してlocalhostの25番ポートに接続し、生成されたメールデータファイルをそのポートに送信します。25番ポートは、メールサーバー間の送受信およびpostfixなどによるメール送信に使用される標準的なSMTPポートです。

  3. postfixなどのメール送信エージェントがファイル内のSMTPコマンドを実行し、メールを送信します。

3.6. その他のプリンター

インターナル・リーダーまたはエクスターナル・ライターが指定されている場合を除き、TJESではOpenFrame環境設定のprintサブジェクトのPRINTERnセクションに、最大9台までのプリンターを指定することで、SYSOUTの出力に対する処理を行うことができます。OpenFrameでは、出力処理を直接実行せず、外部プリンター・ソリューションを利用して、出力に必要な情報を渡す形式で出力処理をサポートします。

PRINTERnセクションでは、それぞれCLASSCOMMANDDRIVER_PATHをキーとして指定できます。

  • CLASSキーには、そのプリンターで処理可能な出力クラスを値として指定します。SYSOUTで指定された出力クラスと一致するクラスが設定されていない場合、出力処理は実行されません。

  • COMMANDキーには、外部プリンター・ソリューションに渡すコマンドを値として指定します。

  • DRIVER_PATHキーには、外部プリンター・ソリューションとのインターフェースのためにOpenFrameが提供する共有ライブラリのパスを値として指定します。現在、OpenFrameでは「libbspprt.so」と「liblrsprt.so」の2種類の共有ライブラリをサポートしています。

    • libbspprt.soライブラリ

      libbspprt.soでは、出力に関する情報が含まれているoutputid.ccとoutputid.ec という2つのスクリプト・ファイルが生成されます。それぞれのファイルに出力される情報は以下のとおりです。

      ファイルの種類 出力情報

      *.ec

      STORE:
      CLS={出力クラス}
      PATTERN=99
      PROGRAMN={プログラム名}
      INPUT_COUNT=1
      INPUT1:
      INPUT={出力パス}
      RID_COUNT=1
      INPUT_RID1:
      RID=

      *.cc

      CHANGE:
      RI_COUNT=1
      RI1:
      RID=
      JOB={ジョブ名}
      STEP={ステップ名}
      JOBNO={ジョブID}
      LPCI={form lpci}
      OVERLAYNAME={form overlay name}
      CODE={form code}
      NOTE={note}
      SHEETSIZE={forms form size}
      LANDSCAPE=
      PRINTMODE={PORTRAIT | LANDSCAPE | format}
      CLISTN={clist名}
      CLISTCMD={BATCH | clistコマンド}
      DDN={DD名}
      DSNAME={データセット名}
      TERMINAL={terminal}
      SIDE={forms side}
      FILE={データセット名}
      RI1_DI1:
      DIST=ALL
      SSET=01
      COPY={copies | 1}

    • liblrsprt.soライブラリ

      liblrsprt.soも、libbspprt.soと同様にoutputid.ccとoutputid.ecという2つのスクリプト・ファイルを生成します。ただし、各ファイルに出力される情報は、libbspprt.soの出力情報とは異なり、内容は以下のとおりです。

      ファイルの種類 出力情報

      *.ec

      STORE:
      CLS={出力クラス}
      PATTERN={forms}
      PROGRAMN=
      INPUT_COUNT=1
      INPUT1:
      INPUT={出力パス}
      RID_COUNT=1
      INPUT1_RID1:
      RID={ライター名 | 999999999999999999999999}
      OUTPUT:
      USERDATAn={userdata}
      ADDRESS={address}
      DEST={dest}
      ROOM='{room}'
      BUILDING='{building}'
      DEPT='{dept}'
      NAME='{name}'
      CHARS={chars}
      FCB={fcb}
      FORMDEF={formdef}
      FORMS={forms}
      JESDS={jesds}
      MAILCC={mailcc}
      MAILBCC={mailbcc}
      MAILFROM='{mailfrom}'
      MAILTO={mailto}
      OVERLAYB={overlayb}
      OVERLAYF={overlayf}
      PAGEDEF={pagedef}
      REPLYTO={replyto}
      RETAINS='{retains}'
      TITLE='{title}'
      TRC={trc}
      UCS={ucs}
      USERLIB={userlib}
      WRITER={ライター名}
      BURST={burst}
      DATACK={datack}
      DEFAULT={default}
      NOTIFY={notify}
      PIMSG={YES | NO}
      PORTNO={portno}
      PRMODE={prmode}
      PRTY={prty}

      *.cc

      CHANGE:
      RI_COUNT=1
      RI1:
      RID={ライター名 | 999999999999999999999999}
      CODE={A | M | F | 0 | 1 | 2}
      JOB='{ジョブ名}'
      STEP='{ステップ名}'
      DD='{DD名}'
      JOBNO='{ジョブID}'
      MAXLL={lecord length}
      FCB='{fcb}'
      COPIES={copies | 1}