技術解説とヒント
<<今月の目次>>
●比較とスワップを使用したカウンターの増分
●Vista 環境で管理者アカウントを使用可能にする
●SetLL に対する *START の使用
●PDF を戻すことができる CGI プログラム

比較とスワップを使用したカウンターの増分

ときどきある質問が、共通のストレージ・ロケーションへのアクセスを同期させて、例えば複数のジョブまたはスレッドからカウンターを同時に増分するにはどうすればよいか、そしてそれを実現する最も高速な方法は何か、というものです。ユーザー・スペースは、ジョブ間でストレージ・ロケーションを共用する高速な方法の 1 つです。ユーザー・スペースへのポインターの取得 (QUSPTRUS) API を使用してユーザー・スペースのアドレスを取得することによって、ポインターを介してユーザー・スペースにアクセスできます。ユーザー・スペース・ポインターに対して BASED データ指定キーワードを使用すると、ポインターが指しているユーザー・スペース内のロケーションに対して、その変数の読み取りまたは更新が実行されます。

2つのジョブがユーザー・スペースを同時に更新しないようにするには、いくつかのオプションがあります。次のリストは、相対的なパフォーマンスの高い順に並んでいます (最も高速なものが最初)。
  • 比較およびスワップ (CMPSWP MI 命令)
  • スペース・ロケーション・ロック (LOCKSL および UNLOCKSL MI 命令)
  • オブジェクト・ロック (LOCK および UNLOCK MI 命令)
  • オブジェクト割り振り (ALCOBJ) およびオブジェクト割り振り解除 (DLCOBJ) の両コマンド
ALCOBJ および DLCOBJ を使用して共用オブジェクトへのアクセスを同期化する方式は、既によくご存じかもしれません。LOCKSL および UNLOCKSL MI 命令の使用法について、RPG IV での例と説明をお読みになる場合は、「APIs by Example: Locking Parts of a User Space」(SystemiNetwork.com の記事 ID 54282) をご覧ください。一方、最も高速な方法は CMPSWP MI 命令なので、ここではこの命令の動作について詳しく説明します。

他のさまざまな MI 命令と同様に、CMPSWP 機能は MI ビルトインと呼ばれる機能を介して ILE プログラミング言語で使用できます。本来、MI 命令には MI コンパイラーのみが直接アクセスできますが、MI ビルトインは ILE コンパイラーへの MI 命令インターフェースを提供し、インターフェース対象の MI 命令の一部として文書化されています。

MI 命令に対応するビルトインが存在する場合は、MI ビルトイン・インターフェースを記述する「Bound program access」ボックスが、MI 命令のパラメーター記述 (MI 命令文書の先頭にある) の直後に存在します。CMPSWP ビルトイン文書はパラメーター・リストを定義し、その結果の RPG IV プロトタイプは図 1 に示すとおりです。

この例では、最初の 3 つのパラメーターを 8 バイトの符号なし整数として定義しましたが、これら 3 つのパラメーターのデータ型と長さが同じである限り、要件に応じて 1 バイト、2 バイト、または 4 バイトの整数 (符号ありまたは符号なし) として定義することもできます。4 つ目のパラメーターはオプションで、ストレージの同期化を制御します。4 つ目のパラメーターを渡さないと、CMPSWP はデフォルトで最も制限の多い動作をするようになり、ほとんどの場合はこれが最適な選択肢です。

CMPSWP ビルトインは、指定された 3 つの比較、ターゲット、およびスワップ値のパラメーターを使用して、次に示す機能を実行します。比較パラメーターは保管された共用変数の値を含み、ターゲット・パラメーターは共用変数 (このコンテキストではカウンター値) を指し、スワップ・パラメーターはターゲット・パラメーターに適用したい値を含んでいることに留意してください。
  1. 比較パラメーターとターゲット・パラメーターを比較します。
  2. 比較パラメーターとターゲット・パラメーターが等しければ、ターゲット・パラメーターの場所にスワップ・パラメーターを格納します。戻りコード 1 が呼び出し側に返されます。
  3. 比較パラメーターとターゲット・パラメーターが等しくなければ、ターゲット・パラメーターを比較パラメーターの場所に格納します。戻りコード 0 が呼び出し側に返されます。
比較結果が等しければ、ターゲット・パラメーターが比較のためにフェッチされる瞬間から、スワップ・パラメーターがターゲット・パラメーターの場所に格納される瞬間まで、他の CMPSWP 命令はターゲット・パラメーターの場所にアクセスしません。

一方、比較結果が等しくなく、ターゲット・パラメーターが比較パラメーターの場所に格納された場合は、この原子性が得られません。ただし、この場合に同期が失われることは、すぐ分かるとおりあまり重要ではありません。また、CMPSWP 命令以外の手段によってターゲット・パラメーターの場所にアクセスすると、ストレージの同期が失われる可能性があります。図 2 は、前記の処理を例示するコード・スニペットです。

最初は、カウンター値を含む共用変数が比較値パラメーターに格納され、Do Until ループに入ります (図 2 の A)。その後、B では、スワップ・パラメーターが比較値を 1 だけ増分した値に設定されます。ここで CMPSWP 機能が呼び出され (C で)、比較値とターゲット値がまだ等しければ、スワップ値がターゲット値に適用されます。正常戻りコード 1 により、Do ループが終了します。一方、比較結果が等しくない場合は、途中でターゲット値に対して更新が行われたことを示しており、CMPSWP 機能は新しいターゲット値を比較値に適用し、コールアウト B と C が繰り返されます。

CMPSWP 機能がどのように動作するか読者自身で確認できるように、2 つのテスト・プログラムと、カウンター増分機能の 2 つのバージョンを示してあります。1 つは CMPSWP ビルトインのコア機能を例示し、もう 1 つはビルトインと API の呼び出しをサービス・プログラム・プロシージャー内にラップして再利用性を高め、カウンター機能の実装を容易にする方法を示しています。

2 つのテスト・プログラム CBX6041T と CBX6042T はそれぞれ、サブシステム QSYSWRK 内のジョブ・キュー QSYSNOMAX に 2 つの同一ジョブを実行依頼します。これがご使用のシステムに適していない場合は、SBMJOB コマンドのジョブ・キュー (JOBQ) パラメーターを両プログラム内で任意のジョブ・キュー名に変更してください。ただし、このテストが動作するためには、ジョブ・キューがマルチスレッドであることが必要です。このコンテキストでは、同じジョブ優先順位を持つ複数のジョブを一度にアクティブにすることができます。

次に、基本テスト・バージョンを実行するために必要な 3 つのステップを示します。
  1. コンパイル済みオブジェクトを含むライブラリーを、ジョブのライブラリー・リストに追加します (まだリストに存在しない場合)。
    ADDLIBLE LIB(library name)
  2. コマンド行からテスト・プログラム CBX6041T を呼び出します。このプログラムは、2 つのジョブをジョブ・キュー QSYSNOMAX に実行依頼します。
    CALL PGM(CBX6041T)
  3. 実行依頼した 2 つのジョブが完了した後、RUNQRY コマンドを使用して、テスト・データ・ファイル CBX6041F の内容を検査します。
    RUNQRY QRYFILE(CBX6041F)
テスト・プログラムの 2 つ目のバージョンを実行するには、ステップ 2 でプログラム CBX6042T を呼び出し、ステップ 3 でファイル CBX6042F に対して照会を実行します。詳しくは、「Storage Synchronization Concepts」(publib.boulder.ibm.com/infocenter/iseries/v5r4/topic/rzatk/MCNSYNC.htm) と、比較およびスワップ命令 (publib.boulder.ibm.com/infocenter/iseries/v5r4
/topic/rzahw/rzahwrzahwcascasco.htm
) を参照してください。
 


↑このページのトップへ


Vista 環境で管理者アカウントを使用可能にする

Vista での大きな変更点の 1 つは、デフォルトで管理者のアカウントが使用不可になっていることです。ただし、Vista でも一部のアプリケーションは、管理者アカウントのセキュリティー権限のもとで実行しない限り正しく動作しません。Vista の管理者アカウントを使用可能にするには、「スタート」メニューを開き、「コンピュータ」を右クリックして「管理」を選択します。コンピューター管理ダイアログで、「ローカル ユーザーとグループ」ノードを開き、「ユーザー」を選択します。次に、管理者アカウントを右クリックし、「プロパティ」を選択します。「プロパティ」の下で、プロパティー「アカウントを無効にする」のチェック・マークを外します。
 


↑このページのトップへ


SetLL に対する *START の使用

Q:
ファイルの先頭で下限を設定する必要があります。何らかの方法で *START が使用できることは知っており、一度は解決したのですが、どのようにしていたのか思い出せません。このためにはどういった操作を行えばよいですか?


A:
V4R4 では、*START キーワードが ILE RPG/400 に追加されました。(RPG/400 には存在しません。)このキーワードを使用すると、文字どおりファイルの始まりに移動できます。また、ファイルの終わりに移動する、対応する *END キーワードもあります。
*START および *END が導入されるまでは、多くのユーザーが *LOVAL と *HIVAL を使用していましたが、これらは状況によっては機能しません。例えば、降順のキーが付いたファイルに対して *LOVAL を使用すると、実際にはファイルの始まりではなく終わりに移動してしまいます。複合キー (複数のフィールドで構成されるキー)、つまり一部のフィールドが昇順で一部は降順になっているキーが付いたファイルの場合は、*HIVAL と *LOVAL を使用すると完全に混乱します。一方、*START と *END は常にそれぞれファイルの始まりと終わりに移動するので、はるかに分かりやすいキーワードです。

*START (または *END) キーワードは、ファクター 1 に属します。固定フォーマットでは、ファクター 1 は次のように命令コードの前に置かれます。

C *START SETLL FILENAME

フリー・フォーマットでは、ファクター 1 は命令コードの後に置かれます。

setll *START FILENAME;

注意点が 1 つあります。ほとんどの場合、ファイル名またはレコード・フォーマット名のどちらに対しても SETLL は正常に使用できます。ただし、*START と *END はこの規則の例外です。必ずファイル名を使用する必要があり、レコード・フォーマットは使用できません。

残念ながら、この例外はインフォメーション・センターに明確に記載されていません。レコード・フォーマット名を指定して *START または *END を使用しようとすると、コンパイラーは「ファクター 2 オペランドのデータ・タイプはこの操作に対して許可されていません」という非常に不親切な RNF5319 エラーを出します。筆者がこのエラーに出くわしたときは、IBM に連絡して支援を仰がなければならず、そこで *START と *END にはファイル名が必要であることが分かりました。ファイル名を使用し始めてからは、筆者の場合はとてもうまくいくようになりました。
 


↑このページのトップへ


PDF を戻すことができる CGI プログラム

Q:
RPG での CGI プログラムの作成には精通しています。現在のところ、CGI プログラムはすべて HTML で出力を返しています。一方、会社ではスプール・ファイルを PDF に変換できるソフトウェア・パッケージを使用しています。レポートを生成し、出力を IFS の一時ファイル内で PDF に変換し、その IFS ファイルをブラウザーに返し、最後に一時ファイルを削除するプログラムを作成したいのですが、どうすればよいでしょうか?


A:
CGI プログラムの機能は HTML を返すことに限りません。どのようなタイプのデータでも返すことができます。データを返す際には、content-type HTTP ヘッダーを使用して、返されるデータのデータ・タイプを指定します。Apache はうまく設計されているので、テキストでないデータを返す際には、EBCDIC から ASCII への変換を行いません。ここでは、CGI プログラムが IFS API を使用して IFS からファイルを読み取り、ブラウザーに返す方法を例示します。

IFS API を使用して、CGI プログラムに使用される標準入出力の読み取りと書き込みを行うことができます。ほとんどの記事や資料では、QtmhRdStin() API を使用して標準入力を読み取り、QtmhRdStout() API を使用して標準出力に書き込むように指示していますが、この作業を行う方法はこれらの API だけではありません。

標準入出力ストリームに対してファイル記述子を使用することもできます。このためには、QIBM_USE_DESCRIPTOR_STDIO 環境変数を Y に設定する必要があります。この設定値は Apache では不要に思えますが、システムの他の領域では必要なので、整合性のためにこの値を設定することをお勧めします。この変数を設定すると、IFS read() および write() API を使用して、標準入力と標準出力にそれぞれアクセスできます。このためには、標準入力には記述子 0 を使用し、標準出力には記述子 1 を使用します。これらの記述子をオープンする必要はなく、Apache が CGI プログラムを呼び出す前にこれらをオープンします。IFS にストリーム・ファイルがあって、そのファイルをブラウザーに送信したい場合には、単に図 3 のコードを使用すればよいので、この方式は理想的です。

Apache によって QIBM_USE_DESCRIPTOR_STDIO 環境変数を設定するには、Apache 構成の中で、CGI プログラムがあるライブラリーの下に次のコードを挿入します。

<Directory /QSYS.LIB/MYCGILIB.LIB>
Order Allow,Deny
Allow From all
etEnv QIBM_USE_DESCRIPTOR_STDIO Y
</Directory>

コンテンツ・タイプを変更した場合でも、同じ手法を使用して、Word や Excel の文書など、他の文書タイプを返すことができます。正しいコンテンツ・タイプを返しさえすれば、どのようなタイプでも返すことができます。
 


↑このページのトップへ

TOPPAGE

BELLDATA, Inc. Copyright reserved.