ここは、印刷物の出力先がどうして決まるかを説明します。
スプールとは
SPOOLはSimultaneous Peripheral Operations On Lineのacronymです。(ほんとにアメリカ人はアクロニムが好きですよね。おかげでコンピュータ用語はアクロニムの巣くつです。)
無理矢理、和訳すると、「同時のオンラインの周辺機器操作」となります。
「同時」とは、外部周辺機器(例えばプリンター)とCPU演算を「同時に」ということです。元々は、入力も出力もあったのですが、現在カードリーダーなんか無いので、もっぱらスプールといえば、印刷データを意味します。
- このスプーリングの概念は、NASAヒューストン計算センタでHASP(Houston
Automatic Spooling Program)として知られたものが、1960年代のIBM360に取り入れられたそうで、結構歴史は古いのです。つまり、AS/400固有の機能ではありません。
スプーリングの本質
スプーリングの本質は
「入力装置上では出来るだけ前もって読むために、出力装置では出力を受け入れるまで出力ファイルを累積しておくために、非常に大きなバッファとしてディスクを使用する」ことです。
SPOOLしない場合。(直接印刷)
印刷装置ファイルの定義で、SPOOL(*NO)とすると、その印刷装置ファイルに書き込まれるデータはスプールされません。よって、OUTQにも累積されません。プリントライターにより、印刷装置ファイルは、DEVパラメータに定義された印刷装置と関連付けられ、印刷装置ファイルのオープンと同時に、プリンターを占有します。
大昔のDOSの印刷のように、プログラムとプリンターが結びつきます。これは、滅多にしません。以前見かけたのは、プリンターが伝票印刷専用にセットされているものに、「即伝」形式(入力したら即、伝票印刷。出力バッファーが満たされると、その時、遅滞なく印刷する。)していました。しかし、この場合でも、SPOOL(*NO)にするメリットは、さほど大きなものではないと思います。SPOOL(*NO)は、あまり使われていないと思います。 |
SPOOLする場合。
これが原則だと思います。SPOOL(*YES)は、印刷装置ファイルの作成時の省略値です。
さて、印刷装置ファイル(以下PRTF)がSPOOL(*YES)となると初めて、OUTQが関係してきます。
OUTQ
AS/400に、出力待ち行列(OUTQ ; Output Queue)と呼ばれるオブジェクトがあります。そして、
- スプールされた出力データは、この出力待ち行列に必ず入ります。
逆にいうと、OUTQに入らない印刷データは、スプールファイルではありません。
OUTQに入れられた(正確には、OUTQエントリに関連付けられた)スプールファイルを、実際に印刷するプログラムは「プリントライター」と呼ばれます。始動コマンドはSTRPRTWTRです。
- プリントライターは、SPOOL完了のスケジュールが、
- *FILEENDなら、RPGがLRしてから印刷し、
- *JOBENDならば、PRTFに書き出すジョブが終了すると印刷、
- *IMMEDはPRTFに書き出すとバッファー満了後すぐに印刷となります。
- 図式化すると、(スケジュール*FILEENDの場合)
処理 |
SPOOLの状況 |
RPGが印刷装置ファイルをオープンする。
(スプールファイルがOUTQと結びつく。) |
OPN |
↓ |
|
RPGが印刷装置ファイルに書き出す。 (OUTQの中でスプールファイルが作成される。) |
OPN |
↓ |
|
RPGが印刷装置ファイルをクローズする。 |
RDY |
↓ |
|
OUTQに関連付けられた「プリントライター」が印刷装置へデータを渡す。 |
WTR |
↓ |
|
印刷装置が印刷する。 |
WTR |
となります。
スプールがOUTQに結びつく部分の仕組みを説明します。
問題は、PRTFに書き出されたデータが入るそのOUTQの決定経路が分からない人が多いのです。
- これは、はっきりいうとIBMのマニュアルに問題があります。また、SYSTEM38のころに無かったパラメータが急に増えたりしているのも原因です。
OUTQを決定するオブジェクトとパラメータ(コマンドキーワード)
オブジェクト |
印刷装置ファイル |
ジョブ記述 |
ジョブ環境の決定 |
ユーザープロファイル |
画面装置記述 |
さて、あるゆるパターンを説明しようかと思ったのですが、これではただのマニュアルになってしまいますね。そこで、よくありそうなパターンを説明します。
端末に依存する対話型ジョブのOUTQ決定
サブシステムの実行項目は、JOBD(*USRPRF)になっていると仮定します。
自分の会社では、例外無く、全員にユーザープロファイルを与えているのですが、ジョブ記述は、ある程度のグループ性を持たせています。つまり、セクション別にいくつかのユーザープロファイルに共通のJOBDを与えています。これは、OUTQのためではなく、ひとえにSBMJOBのJOBQの決定のためです。
プリンターファイルのOUTQは少数を除き、原則的に*JOBとします。
- つまり、RPGをCALLする「ジョブ環境」がOUTQを決めます。単純ですよね。
- また、SBMJOBのOUTQ(*CURRENT)もSBMJOBを実行する「ジョブ環境」から取り出されます。
他のパラメータと比較すると、オブジェクトとしての「ジョブ記述」を参照する場合は、*JOBDになっていますので、
*JOBは、「ジョブ記述」というより「ジョブ環境」をさしていると考えた方がいいでしょう。 |
さて、ここで、よくある要求があります。 それは、
「誰が実行しようと、ある端末の側で実行したら、その側のプリンターから印刷したい」
というものです。
- 例えば、
- あるユーザーが、東京で仕事している時は、その東京のプリンターで印刷して、
- その人が大阪に出張して印刷したら、その大阪のプリンターから印刷したいわけです。
- これでいくと、予め、画面端末とOUTQが結びつかねばなりません。
-
自分の会社では、最初System38だったので、今のようにDEVパラメータが無く、仕方なく端末名とOUTQのテーブルファイルを作成して、経路指定項目でそのテーブルを参照して、CHGJOB
OUTQ(...)してからQCLをTFRCTLしていました。(ジョブ記述をOUTQ分つくって、WSEに登録する方法もありますが、忙しいのにこんなことしてられませんでした。) |
現在、AS/400では*WRKSTNパラメータが出来ています。
これは、画面端末の記述内にあるOUTQやDEVにより、ジョブ環境のOUTQが決定します。
上記の環境を前提に、システムのオブジェクトだけで、最も単純に要求を満たす方法は、
印刷装置ファイルの、OUTQは*JOBにします。 |
ジョブ記述のOUTQを*USRPRFにする。 |
各ユーザープロファイルのOUTQを、*WRKSTNにする。 |
画面装置記述のOUTQに、関連する印刷装置(OUTQ名)を設定します。 |
[解説]
ユーザーがサインオンをした時点で、
サブシステムの実行項目(ワークステーションエントリ)にはジョブ記述は、ユーザープロファイルに定義されていると出ています。(*USRPRF) |
そこで、ユーザープロファイルのジョブ記述を参照します。
そして、そのジョブ記述には、ユーザープロファイルのOUTQを参照しろと出ています。(*USRPRF) |
そして、ユーザープロファイルのOUTQを見ると、端末の記述のOUTQを参照しろと出ています。(*WRKSTN) |
やっと、端末のOUTQにたどり着きました。 |
これで、初期の「ジョブ環境」の中のOUTQ名が決定されます。 |
印刷装置ファイルは、OUTQ(*JOB)なので、「ジョブ環境」の中のOUTQ名が使われます。 |
- これで、ある端末からの印刷物は、その端末に関連付けられた印刷装置から印刷されます。
- なお、PRTDEVにセットしてもいいのですが、あくまで印刷装置記述を参照しますので、実在するDEVDを入力しないとエラーになります。
- もし、プログラマー用ならば、USRPRFのOUTQに自分専用のOUTQ名をセットします。
- 通常このプログラマー固有のOUTQは、印刷装置とは接続しません。でないと、コンパイルリストがじゃんじゃん出てきます。
端末に依存しないバッチジョブのOUTQ決定
端末に依存しないバッチジョブは、OUTQの決定を端末に依存せず、SBMJOBのパラメータOUTQで、そのジョブの省略値のOUTQを独立して決めて、そのジョブの中での、細かなOUTQは、そのCLPのなかで、OVRPRTF
OUTQ(....) , CALL , DLTOVRをしています。
- 例えば、
- 日締め処理などで、一つのバッチジョブから様々なスプールを、様々なOUTQ(=プリンター)に出したい時には、OVRPRTF
OUTQ(...)です。CHGJOB OUTQ(...)をしてしまうと、また、元に戻さないと、後続のジョブで、予定外のOUTQへ、スプールが出たりします。
|