大量のスペースをスキャンする
Question
サード・パーティーのクエリー・ツールで作成されたクエリーの保存に使用している多数の (約 1,200) ユーザー・スペースがあります。その一部は QDLS パスを使用しており、それらのクエリーを識別し、代わりに IFS ディレクトリーを使用するよう変更するのにかなりの負担が掛かりました。これらのユーザー・スペース中の文字列「QDLS」をどのように探せばいいのでしょうか。QShell で grep ツールを試してみましたが、行当たり 2,048 文字しか検索できないため、これらのユーザー・スペースの文字列は検索できません。助けてください。
Answer
ユーザー・スペースまたは IFS ストリーム・ファイル中の文字列を検索できる、RPG で作成された QShell ユーティリティーのコードを提供しましょう。また、QShell でそれをどのように呼び出し、検索するユーザー・スペースの名前を提供するのかお見せしましょう。
間に合わせのソリューションとしては、自分の QShell ユーティリティーを作成することです。QShell を利用する主な理由は、ファイル名を見つけるのに役立つからです。これが単発のプログラムでない場合は、パフォーマンス上の理由で他の方法を選択したかもしれませんが。
ディスプレイ・ファイルを使用していないという前提で、QShell から任意の *PGM オブジェクトを呼び出すことができるという考えがベースです。私の例では、FINDQDLS というプログラムを作成しています。したがって、そのプログラムが MYLIB ライブラリーにあるという前提で、次のように QShell から呼び出すことができます。
> /QSYS.LIB/MYLIB.LIB/FINDQDLS.PGM
これは、QShell 内から私の FINDQDLS プログラムを実行しており、パラメーターは渡しません。
ある IFS ディレクトリー内のパターン *.txt に一致するファイルごとに 1 回ずつ、これを何回も実行したいとしましょう。そのためには、QShell から次を実行できます。
> for f in *.txt; do /QSYS.LIB/MYLIB.LIB/FINDQDLS.PGM "$f"; done
この例では、パターン「*.txt」に一致するファイルごとに MYLIB/FINDQDLS を実行させて、ファイル名をパラメーターとして渡すよう QShell に指示しています。私の IFS ディレクトリーに *.txt で終わるファイルが 200 件ある場合、FINDQDLS プログラムを 200 回呼び出します。それぞれ、異なるファイル名がパラメーターとして渡されます。
IFS では、*USRSPC オブジェクトを、ストリーム・ファイルの場合とまったく同じに使用できます。そのため、自分のプログラムを呼び出したいが QShell に IFS パス名を USRSPCLIB ライブラリーのすべてのユーザー・スペースに渡させる場合、次のようにできます。
> for f in /QSYS.LIB/USRSPCLIB.LIB/*.USRSPC; do /QSYS.LIB/MYLIB.LIB/FINDQDLS.PGM "$f"; done
注: /QSYS.LIB パス名を使用して名前ライブラリー/オブジェクト・ファイル・システムにアクセスする場合、パス名をすべて大文字で入力しないと QShell の結果がおかしくなることがわかりました。そのため、ネイティブ・オブジェクトを使用している場合、パス名はすべて大文字にします。
前述の例では、USRSPCLIB ライブラリーのユーザー・スペースごとに 1 回 MYLIB/FINDQDLS を呼び出しています。毎回 IFS パス名がユーザー・スペースに渡されています。
FINDQDLS は、ストリーム・ファイルまたはユーザー・スペース・オブジェクト中の「QDLS」文字列を検索するために作成したプログラムです。この記事の終わりに、ソース・コードをダウンロードできるリンクを用意しました。プログラムの理解に役立つよう、処理内容を説明する擬似コードをいくつかご紹介します。
- 第 1 パラメーターからパス名を取得します。
- IFS open() API でパス名を開きます-- 必要に応じて EBCDIC へテキスト変換を行います。
- fstat() API を使用して、開いたファイルのサイズを取得します。
- ファイルのデータすべてを格納できるよう十分なメモリーをバッファーに割り当てます。
- ファイル全体をバッファーに読み込みます。
- IFS ファイルを閉じると、データのコピーが準備されます。
- 検索で大文字小文字を区別するよう、バッファーを大文字に変換します。
- ScanMem() プロシージャーを呼び出してバッファーを検索します。(このプロシージャーは既に持っていたもので、C API を使用して、メモリーの大部分中のある文字列を検索します。)
- 文字列が見つかったら、ファイル名を印刷します。
- 割り当てられていたメモリーを解放します。
- プログラムを終了します。
上記のように、約 16MB 以下のファイルのみ処理します。いずれにしても、このサイズがユーザー・スペースの最大サイズです。しかし、多少変更すれば、大規模ファイル向けにテラスペースを処理できるようになります。そのため、一部の STMF オブジェクトのサイズが 16MB より大きな IFS ディレクトリーで実行する場合、「Not enough memory for this object (このオブジェクトにはメモリーが足りません)」というエラーを受信する場合があります。
このプログラムを MYLIB に入れると、上記のように実行でき、文字列「QDLS」を含むオブジェクトのリストが印刷されます。
> for f in /QSYS.LIB/USRSPCLIB.LIB/*.USRSPC; do /QSYS.LIB/MYLIB.LIB/FINDQDLS.PGM "$f"; done
/QSYS.LIB/USRSPCLIB.LIB/TESTUSRSPC.USRSPC
/QSYS.LIB/USRSPCLIB.LIB/ANOTHER.USRSPC
$
FINDQDLS プログラムのソースは systeminetwork.com/article/scanning-slew-spaces からダウンロードできます。ページの下部にスクロールしてください。