きどたかのブログ

いつか誰かがこのブログからトラブルを解決しますように。

ibm.swapLFについて

ibm.swapLFなるものを調査する機会があった。

正直まだよく分かってない。。。

 

IV18977: IMPLEMENTING SWAPLF FUNCTIONALITY FOR IBM-037 CODEPAGE

このへんの話だ。

 

ちょっと表を添えておくよ。

  EBCDIC ASCII
CR 0x0D 0x0D
LF 0x25 0x0A
NL 0x15  

 

この-Dibm.swapLF=trueを渡すと、

Java on z/OSにおける0x0A(ASCII) を0x25(EBCDIC)にしてくれるようだ。

通常は0x15(EBCDIC)になっているのを0x25(EBCDIC)にかえてる。

 

0x0A(LF) -> 0x15(NL)

上のが下のに変わるってこと。

0x0A(LF) -> 0x25(LF)

 

まだその挙動を正確に把握できてない。

JOBLOGのSYSPRINTへの出力のされかたとして、

0x15(EBCDIC)を見たことはない。

レコード・オリエンティッドなせいかなって思ってる。

 

一方で、USS環境でjavaコマンドを叩きstdoutをファイルにリダイレクトさせると、

0x15(EBCDIC)を確認することが可能だった。

これは自分で書いたSystem.out.println()であって、WASのは未確認。

そうだなぁ、WASのSYSPRINTをDD変えてUSSにリダイレクトするとどうなるんだろうね。

0x15(EBCDIC)は付くのかな???(きっと付く)

 

誰かがCRもLFに変えるとか言ってたんだけど、そんなことは確認できなかった。

なぜならCRはASCIIでもEBCDICでも同じなのだから変える理由がない。

これはEBCDICにはNLがあるのに対して、

ASCIIには存在しないというマッピングの問題をどうするかの選択肢だ。

訂正:EBCDICにはNL(New Line) 0x15、ASCIIにはNEL(Next Line) 0x85がある。

WINDOWSのCR+LFの話とはきっと違う。

C/C++のライブラリではASA control characterを意識するRECFMもあるので、

CRも大切な要素だったりする。特にプリンターで使うみたいだ。

CRってWINDOWSのやつでしょ?って認識は甘いと気付かされた。

若い頃に帳票出力するプログラムに書いてたはずなのに覚えてない。

 

メインフレームと分散系の互換性って点で変更するんだろうってのが

ざっくりとした使い方なのだろうとは思う。

 

ちょっとどうでもいいことだけど、

char c = '\u000A' を書けないことに気付いた。

知らなかった。

char c = 0x0A で代用した。

たぶんワイドニング・コンバージョンでOKなんじゃないだろうか。

当然ですが、"\n"も試してますよ。

 

このプロパティを使ってSYSPRINTに出力すると面白いことになる。

WASが出力するログは何も変わらない。

アプリがSystem.outから出力するものが変わる。

System.out.println()使うじゃないですか、

結果として通常は0x15(EBCDIC)なのが0x25(EBCDIC)になるわけですよ。

しかし、0x25(EBCDIC)では折り返さないわけですよ。

0x25(EBCDIC)はデータとして扱われている。

つまり、以降のprintln()も含めて長い行になる。

そんなもん使いもんになるのかよ・・・。

 

通常の0x15(EBCDIC)がSYSPRINTに存在しないことを

レコード・オリエンティッドだからじゃないかと言う点が的を得てる可能性はある。

レコードはテキストファイルとは違うのだよ。

ざっくり言うとレコードはバイナリファイルに近い。

行という称するであろう部分のデータの終わりはあらかじめ分かってるもの。

それがレコードフォーマット。バイナリファイルもそうだ。

(項目が~とか、ブロック長が~はまた別の話としておこう)

もしくはデータの所定の位置に長さ情報が格納されているもの。

可変長レコードはこれに該当する。RDW。

レコードはその行の終端を別途把握しているため、

きっと終端データとしての0x15(EBCDIC)は不要な存在になる。

だから消えてなくなってるんじゃないだろうか。

なお自分の確認方法はSYSPRINTをxdcしてHEXで見た。

WASのSYSPRINTは134カラム。

これってFBなのVBなの???

正直それは知らん。FBでxdcすると40(スペース)がたくさん付くからヤダ。

 

話が横道に逸れすぎた。

誰が0x15(EBCDIC)を葬るものか?

それが分かれば完結する気もする。

C++か?JESか何かか?

たぶんJESって線は薄い。

JESスプールだとしてもただのI/Oだ。

JESがどうってことはないだろう。

 

もう1点気にするところは、プロパティを有効にしても

WASのSYSPRINTはきちんと改行されていたというところだ。

WASの出力方法は違うのではないか?

たとえばそう、ひょっとしてtype=recordで書きこんでたりする?

はなからWASはNLなんか使ってない疑惑。

データセットのレコードに改行コードなんて無い、

たしかにそれは納得感がある、だってそういうものだもの。

どんなに長いメッセージでも134ぴったりで折りかえすと思うんだよね。

これってLRECL使ってるんじゃなかろうかと。

折り返すといってもふつうはみ出した部分は切り捨てられるので、

134ってどこかで意識してると思うのだよ。

 

あと、ちょっと気色悪いと感じてるのが1点あった。

なぜIBM037?

IBM1047じゃないのかよ。

いずれもEBCDICだが、以下のマッピングが違う。

0x5F

0xAD

0xB0

0xBA

0xBB

0xBD

どうやらいくつものEBCDICについて同じ機能を実装しているみたいだった。

なんだそういうことか・・・。

 

こういうファイルをFTPで取得する場合、

たしか改行コードを付加するかを選ぶことができたはずだ。

アプリの出力するログは0x25があるからいいとしても、

WASの出力するログは0x25ついてないから困るよな。

どう使えばいいの?

やっぱりSYSPRINTに出力しないで使えってことかな。

ある種の業務データを別ファイルに書くのはそれで使えると思うが、

通常のログとしてのデータをSYSPRINTに出すのには少し困る。

コンバーターが介在しなければきっと大丈夫だから、

EBCDICをバイナリでつっこめばきっと0x15を入れることはできるだろうけど、

そこまでしてやる?って疑問符はつく。

どうせなら全部HFS上に出すよね。

そうなると、今度は複数SRのときに競合して面倒くさいじゃないか。

 

複数SRという面でいくと、

Log4Jとか使うならFileAppenderの拡張を作ればいけるだろう。

STC番号を拾えるから分けられる。

重複の心配をするならJOBID/STCよりもSTOKENのが安全。

STOKENはJZOSのZUtilからは無理で、

com.ibm.websphere.runtime.ServerNameからのみ。

WASのFFDCはSTOKEN混ぜてるから重複の心配はない。

 

状況証拠と仮説はだいぶそろってきたけど、まだよく分からない。

 

ちなみに、SYSPRINTやSYSOUTって、JZOS使えばDD名でも拾える。

まあ、そんなプラットフォーム依存なのはあまり書かないほうがいい。

C/C++ライブラリの仕様を意識して書かないといけなくなり、バグもでてしまう。

データセットに書かないといけないやつは仕方ない。

DD名なり完全修飾名なりで拾うしかないときに、

DD名にしておいたほうが、のちのちデータセット名の変更をJCLで吸収できる。

全ファイルの完全修飾名をプロパティに外だしするのでもいいけど、

あるデータをソートしたいときなんかは、DD名にしといたほうがよいと思う。

性能的にJavaでソートとかしたくない。

CPよりもzAAP使いたいんだ、ってのなら話は別だろう。

やっぱ、あれか、JZOSでソートか・・・。

まだJZOSでソートするの試したことなかった。

でも、よく考えると、zAAPにオフロードとか無理じゃないのかな・・・。

JZOSで書いたところでSORT FIELDSとか書くわけだし、

AP内でソートしたい理由がなければ、JCLにDD名書いてそれでやるとかもあり。

後続にまたJavaがくるなら、JVMの起動時間がもったいないから、

全部AP内でソートってのも考えられる話だろう。