様々なアプリケーション使用環境のサポート
本章では、様々なアプリケーションでProSortの機能を使用する方法について説明します。
1. ProSortコマンド
prosort コマンドは、ProSortがインストールされているマシンで実行する必要があります。また、環境変数を正しく設定した後、コマンドを実行してください。
prosort コマンドの使用方法は以下のとおりです。
prosort [-h] [-v] [-s] [-j] [script file]
| オプション | 説明 |
|---|---|
-h |
|
-v |
ProSortのバージョン情報を表示します。 |
-s |
スクリプト・ファイルを実行した後、状態情報を表示します。 このオプションを使用すると、以下の状態情報を確認することができます。
|
-j |
スクリプト・ファイルを実行した後、プロファイル情報を表示します。 プロファイルの情報は製品のバージョンによって変更されることがあるので、本書では別途説明しません。 |
script file |
スクリプト・ファイルのディレクトリ・パスとファイル名を入力します。省略すると、標準入力を通じてスクリプト・ファイルの入力を受けます。 |
2. ProSort API関数
ProSortはC関数APIを提供します。すべての関数は戻り値を持ちます。成功時は0を返し、失敗時は負数値を返します。
以下は、APIの形態で提供する関数です。
| 関数 | 説明 |
|---|---|
スクリプトの演算をすべて実行します。 |
|
ProSortの実行に必要な情報を初期化します。 |
|
すべての入出力パラメータがprosort_setup関数と同じです。 |
|
SORT演算を行う際に、データをレコードごとに入力します。 |
|
SORT演算を行う際に、データの入力が完了したことを示します。 |
|
演算の結果をレコード1件ごとに読み込みます。 |
|
すべての演算に使用したリソースを返します。 |
|
エラーが発生した際に、エラー番号を取得します。 |
|
エラーが発生した際に、エラー・メッセージを取得します。 |
2.1. prosort_run_script
スクリプトの演算をすべて実行する関数です。
-
プロトタイプ
int prosort_run_script(const char *const script); -
パラメータ
パラメータ 説明 script
演算に使用するProSortのスクリプトです。
-
例
#include <stdio.h> #include <stdlib.h> #include "prosort.h" int main(int argc, char **argv) { int rc; char *script = "DEFREC FIXED,SIZE=256 " "MEMORY 500M " "INFILE = (x1,100M, x2, 100M, x3, 100M, x4, 100M) " "SORT FIELDS=(1,13,AC,A) " "OUTFIL FNAMES = xresult "; rc = prosort_run_script (script); if (rc < 0) { fprintf(stderr,"Error[%d]:\n", rc); fprintf(stderr,"%s\n", ps_err_code_to_cause(rc)); fprintf(stderr,"%s\n", ps_err_code_to_action(rc)); exit (rc); } return 0; }
2.2. prosort_setup
ProSortの実行に必要な情報を初期化します。ただし、prosort_run_script関数を使用する場合は、prosort_setup関数を呼び出す必要がありません。
-
プロトタイプ
typedef int (*callback_func_t)(char **data_buf_addr, int *data_buf_length); int prosort_setup (const char *prosort_script, callback_func_t *data_fetch_callback_funcs, int data_fetch_callback_func_cnt, void **ptr_prosort_context); -
パラメータ
パラメータ 説明 *prosort_script
ProSort APIで使用するスクリプトです。
*data_fetch_callback_funcs
MERGEおよびCOPY演算を行う際には、別途にデータの入力を受けず、コールバック関数(callback function)を使って入力を受けます。
特に、MERGE演算を行う際には、複数のコールバック関数の入力を受けることもあるので、コールバック関数の配列のアドレスをパラメータとして受けます。
data_fetch_callback_func_cnt
コールバック関数の数です。
**ptr_prosort_context
演算の実行に必要なコンテキストの情報を取得します。作成されたコンテキストは他のAPIに適用して演算を実行できます。
-
例
#include <stdio.h> #include <stdlib.h> #include "prosort.h" static void print_err_msg(int ec) { fprintf(stderr,"Error[%d]:\n", ec); fprintf(stderr,"%s\n", ps_err_code_to_cause(ec)); fprintf(stderr,"%s\n", ps_err_code_to_action(ec)); fprintf(stderr,"%s\n", ps_err_get_last_msg()); } /* 16バイト・レコード */ #define REC_LEN 16 #define RAND (char) (rand() % 24) + 'A' int main(int argc, char **argv) { int i = 0; int j = 0; int rc = 0; void *ps_ctx; char buf[REC_LEN]; const char *script = "MEMORY 100M\n" "DATASIZE 100M\n" "DEFREC FIXED, SIZE=16\n" "SORT FIELDS = (1,8,CH,A)\n"; /* スクリプトの設定 */ rc = prosort_setup (script, NULL, 0, &ps_ctx); if (rc < 0) { print_err_msg (rc); exit (rc); } /* レコードの入力 */ for (i = 0; i < 100; i++) { for (j = 0; j < REC_LEN - 1; j++) buf[j] = RAND; buf[j] = 0; rc = prosort_release_record (ps_ctx, buf, REC_LEN); if (rc < 0) { print_err_msg (rc); exit (rc); } } /* レコード入力の完了 */ prosort_release_end (ps_ctx); do { char outbuf[REC_LEN]; char *outbufs[1]; unsigned int len = REC_LEN; outbufs[0] = outbuf; rc = prosort_return_record (ps_ctx, outbufs, &len); if (rc < 0) { print_err_msg (rc); exit (rc); } if (len == 0) break; printf ("%s\n", outbuf); } while (1); prosort_end (ps_ctx); return 0; }
2.3. prosort_setup_with_userexit
すべての入出力パラメータがprosort_setup関数と同じです。ただし、func_e15、func_e32、func_e35、 func_e61パラメータは例外です。
-
プロトタイプ
typedef int (*user_exit_func_t)(const void *rec_addr, const int rec_len, int file_no, void **ret_rec_addr, int *ret_rec_len); int prosort_setup_with_userexit(const char *prosort_script, callback_func_t *data_fetch_callback_funcs, int data_fetch_callback_func_cnt, user_exit_func_t func_e15, user_exit_func_t func_e32, user_exit_func_t func_e35, user_exit_func_t func_e61, void **ptr_prosort_context); -
パラメータ
パラメータ 説明 *prosort_script
ProSort APIで使用するスクリプトです。
*data_fetch_callback_funcs
MERGEおよびCOPY演算を行う際には、別途にデータの入力を受けず、コールバック関数を使って入力を受けます。
特に、MERGE演算を行う際には、複数のコールバック関数の入力を受けることもあるので、コールバック関数の配列のアドレスをパラメータとして受けます。
data_fetch_callback_func_cnt
コールバック関数の数です。
func_e15
ユーザー出口関数E15です。
func_e32
ユーザー出口関数E32です。
func_e35
ユーザー出口関数E35です。
func_e61
ユーザー出口関数E61です。
**ptr_prosort_context
演算の実行に必要なコンテキストの情報を取得します。作成されたコンテキストは他のAPIに適用して演算を実行することができます。
-
例
int func_e15(const void *rec_addr, const int rec_len, int file_no, void **ret_rec_addr, int *ret_rec_len) { ... } int main(int argc, char **argv) { int rc; void *ps_ctx; const char *script = "DEFREC FIXED,SIZE=150 \n" "DATASIZE 2M \n" "MEMORY 512M \n" "WORKSPACE = (./) \n" "SORT FIELDS=(1,2,A),FORMAT=BI \n" "INCLUDE COND=(1,2,CH,EQ,C'12',OR,1,2,CH,EQ,C'22',OR,1,2,CH,EQ,C'32') \n" "OUTFIL FNAMES=OUT1 \n"; rc = prosort_setup_with_userexit(script, NULL, 0, func_e15, NULL, NULL, NULL, &ps_ctx); ... }
2.4. prosort_release_record
SORT演算を行う際に、データをレコードごとに入力する関数です。
-
プロトタイプ
int prosort_release_record(void *prosort_context, const char *record, const unsigned int record_length); -
パラメータ
パラメータ 説明 *prosort_context
prosort_setup関数で作成したコンテキストを渡します。
*record
レコードのアドレスです。
record_length
レコードの長さです。
-
例
#include <stdio.h> #include <stdlib.h> #include "prosort.h" static void print_err_msg(int ec) { fprintf(stderr,"Error[%d]:\n", ec); fprintf(stderr,"%s\n", ps_err_code_to_cause(ec)); fprintf(stderr,"%s\n", ps_err_code_to_action(ec)); fprintf(stderr,"%s\n", ps_err_get_last_msg()); } /* 16バイト・レコード */ #define REC_LEN 16 #define RAND (char) (rand() % 24) + 'A' int main(int argc, char **argv) { int i = 0; int j = 0; int rc = 0; void *ps_ctx; char buf[REC_LEN]; const char *script = "MEMORY 100M\n" "DATASIZE 100M\n" "DEFREC FIXED, SIZE=16\n" "SORT FIELDS = (1,8,CH,A)\n"; /* スクリプトの設定 */ rc = prosort_setup (script, NULL, 0, &ps_ctx); if (rc < 0) { print_err_msg (rc); exit (rc); } /* レコードの入力 */ for (i = 0; i < 100; i++) { for (j = 0; j < REC_LEN - 1; j++) buf[j] = RAND; buf[j] = 0; rc = prosort_release_record (ps_ctx, buf, REC_LEN); if (rc < 0) { print_err_msg (rc); exit (rc); } } /* レコード入力の完了 */ prosort_release_end (ps_ctx); do { char outbuf[REC_LEN]; char *outbufs[1]; unsigned int len = REC_LEN; outbufs[0] = outbuf; rc = prosort_return_record (ps_ctx, outbufs, &len); if (rc < 0) { print_err_msg (rc); exit (rc); } if (len == 0) break; printf ("%s\n", outbuf); } while (1); prosort_end (ps_ctx); return 0; }
2.5. prosort_release_end
SORT演算を行う際に、データの入力が完了したことを示す関数です。
-
プロトタイプ
int prosort_release_end(void *prosort_context); -
パラメータ
パラメータ 説明 *prosort_context
prosort_setup関数で作成したコンテキストを渡します。
-
例
#include <stdio.h> #include <stdlib.h> #include "prosort.h" static void print_err_msg(int ec) { fprintf(stderr,"Error[%d]:\n", ec); fprintf(stderr,"%s\n", ps_err_code_to_cause(ec)); fprintf(stderr,"%s\n", ps_err_code_to_action(ec)); fprintf(stderr,"%s\n", ps_err_get_last_msg()); } /* 16バイト・レコード */ #define REC_LEN 16 #define RAND (char) (rand() % 24) + 'A' int main(int argc, char **argv) { int i = 0; int j = 0; int rc = 0; void *ps_ctx; char buf[REC_LEN]; const char *script = "MEMORY 100M\n" "DATASIZE 100M\n" "DEFREC FIXED, SIZE=16\n" "SORT FIELDS = (1,8,CH,A)\n"; /* スクリプトの設定 */ rc = prosort_setup (script, NULL, 0, &ps_ctx); if (rc < 0) { print_err_msg (rc); exit (rc); } /* レコードの入力 */ for (i = 0; i < 100; i++) { for (j = 0; j < REC_LEN - 1; j++) buf[j] = RAND; buf[j] = 0; rc = prosort_release_record (ps_ctx, buf, REC_LEN); if (rc < 0) { print_err_msg (rc); exit (rc); } } /* レコードの入力完了 */ prosort_release_end (ps_ctx); do { char outbuf[REC_LEN]; char *outbufs[1]; unsigned int len = REC_LEN; outbufs[0] = outbuf; rc = prosort_return_record (ps_ctx, outbufs, &len); if (rc < 0) { print_err_msg (rc); exit (rc); } if (len == 0) break; printf ("%s\n", outbuf); } while (1); prosort_end (ps_ctx); return 0; }
2.6. prosort_return_record
演算の結果をレコード1件ごとに取得する関数です。出力は、OUTFILにより複数出力されることがあるので、バッファーの配列として取得します。0番目はSORTOUT(OUTFILを実行しない出力)が出力され、スクリプトに定義されたOUTFILが順序どおり出力されます。
-
プロトタイプ
int prosort_return_record(void *prosort_context, char **output_buffer, unsigned int *output_buffer_length); -
パラメータ
パラメータ 説明 *prosort_context
prosort_setup関数で作成したコンテキストを渡します。
**output_buffer
出力レコードを取得するバッファー・アドレスの配列です。
*output_buffer_length
出力レコードのサイズを保存する配列です。
-
例
#include <stdio.h> #include <stdlib.h> #include "prosort.h" static void print_err_msg(int ec) { fprintf(stderr,"Error[%d]:\n", ec); fprintf(stderr,"%s\n", ps_err_code_to_cause(ec)); fprintf(stderr,"%s\n", ps_err_code_to_action(ec)); fprintf(stderr,"%s\n", ps_err_get_last_msg()); } /* 16バイト・レコード */ #define REC_LEN 16 #define RAND (char) (rand() % 24) + 'A' int main(int argc, char **argv) { int i = 0; int j = 0; int rc = 0; void *ps_ctx; char buf[REC_LEN]; const char *script = "MEMORY 100M\n" "DATASIZE 100M\n" "DEFREC FIXED, SIZE=16\n" "SORT FIELDS = (1,8,CH,A)\n"; /* スクリプトの設定 */ rc = prosort_setup (script, NULL, 0, &ps_ctx); if (rc < 0) { print_err_msg (rc); exit (rc); } /* レコードの入力 */ for (i = 0; i < 100; i++) { for (j = 0; j < REC_LEN - 1; j++) buf[j] = RAND; buf[j] = 0; rc = prosort_release_record (ps_ctx, buf, REC_LEN); if (rc < 0) { print_err_msg (rc); exit (rc); } } /* レコードの入力完了 */ prosort_release_end (ps_ctx); do { char outbuf[REC_LEN]; char *outbufs[1]; unsigned int len = REC_LEN; outbufs[0] = outbuf; rc = prosort_return_record (ps_ctx, outbufs, &len); if (rc < 0) { print_err_msg (rc); exit (rc); } if (len == 0) break; printf ("%s\n", outbuf); } while (1); prosort_end (ps_ctx); return 0; }
2.7. prosort_end
すべての演算に使用したリソースを返す関数です。
-
プロトタイプ
int prosort_end(void *prosort_context); -
パラメータ
パラメータ 説明 *prosort_context
prosort_setup関数で作成したコンテキストを渡します。
-
例
#include <stdio.h> #include <stdlib.h> #include "prosort.h" static void print_err_msg(int ec) { fprintf(stderr,"Error[%d]:\n", ec); fprintf(stderr,"%s\n", ps_err_code_to_cause(ec)); fprintf(stderr,"%s\n", ps_err_code_to_action(ec)); fprintf(stderr,"%s\n", ps_err_get_last_msg()); } /* 16バイト・レコード */ #define REC_LEN 16 #define RAND (char) (rand() % 24) + 'A' int main(int argc, char **argv) { int i = 0; int j = 0; int rc = 0; void *ps_ctx; char buf[REC_LEN]; const char *script = "MEMORY 100M\n" "DATASIZE 100M\n" "DEFREC FIXED, SIZE=16\n" "SORT FIELDS = (1,8,CH,A)\n"; /* スクリプトの設定 */ rc = prosort_setup (script, NULL, 0, &ps_ctx); if (rc < 0) { print_err_msg (rc); exit (rc); } /* レコードの入力 */ for (i = 0; i < 100; i++) { for (j = 0; j < REC_LEN - 1; j++) buf[j] = RAND; buf[j] = 0; rc = prosort_release_record (ps_ctx, buf, REC_LEN); if (rc < 0) { print_err_msg (rc); exit (rc); } } /* レコードの入力完了 */ prosort_release_end (ps_ctx); do { char outbuf[REC_LEN]; char *outbufs[1]; unsigned int len = REC_LEN; outbufs[0] = outbuf; rc = prosort_return_record (ps_ctx, outbufs, &len); if (rc < 0) { print_err_msg (rc); exit (rc); } if (len == 0) break; printf ("%s\n", outbuf); } while (1); prosort_end (ps_ctx); return 0; }
2.8. prosort_get_error_number
エラーが発生した際に、エラー番号を取得する関数です。
-
プロトタイプ
int prosort_get_error_number(void *prosort_context); -
パラメータ
パラメータ 説明 *prosort_context
prosort_setup関数で作成したコンテキストを渡します。
-
例
int main(int argc, char **argv) { int rc; void *ps_ctx; const char *script = "DEFREC FIXED,SIZE=150 \n" "DATASIZE 2M \n" "MEMORY 512M \n" "WORKSPACE = (./) \n" "SORT FIELDS=(1,2,A),FORMAT=BI \n" "INCLUDE COND=(1,2,CH,EQ,C'12',OR,1,2,CH,EQ,C'22',OR,1,2,CH,EQ,C'32') \n" "OUTFIL FNAMES=OUT1 \n"; rc = prosort_setup(script, NULL, 0, &ps_ctx); if(rc < 0) { fprintf(stderr, "Error number is %d\n", prosort_get_error_number(ps_ctx)); } ... }
2.9. prosort_get_error_message
エラーが発生した際に、エラー・メッセージを取得する関数です。
-
プロトタイプ
int prosort_get_error_message(void *prosort_context, char *error_message_buffer, unsigned int *error_message_length); -
パラメータ
パラメータ 説明 *prosort_context
prosort_setup関数で作成したコンテキストを渡します。
*error_message_buffer
エラー・メッセージを取得するバッファー・アドレスです。
*error_message_length
エラー・メッセージの長さです。
-
例
#define ERR_MSG_MAXLEN 1024 int main(int argc, char **argv) { int rc; void *ps_ctx; char *err_msg; unsigned int err_msg_len; const char *script = "DEFREC FIXED,SIZE=150 \n" "DATASIZE 2M \n" "MEMORY 512M \n" "WORKSPACE = (./) \n" "SORT FIELDS=(1,2,A),FORMAT=BI \n" "INCLUDE COND=(1,2,CH,EQ,C'12',OR,1,2,CH,EQ,C'22',OR,1,2,CH,EQ,C'32') \n" "OUTFIL FNAMES=OUT1 \n"; err_msg = (char *)malloc(sizeof(char) * ERR_MSG_MAXLEN); err_msg_len = ERR_MSG_MAXLEN; rc = prosort_setup(script, NULL, 0, &ps_ctx); if(rc < 0) { prosort_get_error_message(ps_ctx, err_msg, &err_msg_len); fprintf(stderr, "Error message is %s\n", err_msg); } ... }
3. OpenFrame BatchでのProSortの起動
OpenFrameではProSortを直接実行せずに、途中でDFSORTユーティリティを利用して入力データセットに対してソート、マージ、コピー、フィルタリング、再フォーマット、合計などを実行し、出力データセットを作成します。
OpenFrameでソート操作を実行するには、ジョブ制御文(JCL)を作成する必要があります。なお、作成されたジョブ制御文はバッチ・ジョブとしてOpenFrame Batchに渡す必要があります。
|
バッチ・ジョブの詳細については、OpenFrame 『Batchガイド』、またはOpenFrame 『TJESガイド』を参照してください。 |
3.1. ジョブ制御文
ジョブ制御文は、大きく、JOB文、EXEC文、DD文、/*などで構成されています。
|
JCL文法の詳細については、OpenFrame『ジョブ制御言語文法書』を参照してください。 |
-
JOB文
ジョブの先頭に位置する制御文で、ジョブの開始を知らせると同時に、そのジョブの性格を定義します。
以下は、記述例です。
//SORT00 JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1)
-
EXEC文
1つのジョブは複数のステップ(STEP)で構成されており、その中でもEXEC文はJOB STEPの先頭に位置します。プログラムの名前やプログラムに渡すパラメータなどを指定します。
ProSortを利用してソートを実行するには、PGM=DFSORTと記述する必要があります。
以下は、記述例です。
//SORT EXEC PGM=DFSORT,REGION=2M
-
DD文
ソート実行時に使われるデータセットの名前や属性などを以下の項目により指定します。
項目 説明 SYSIN
SORTの制御文を入力するためのデータセットです。一般的にDD *でシステム入力ストリームを利用します。SORT制御文はProSortの制御文ではなくDFSORT制御文に基づいて作成する必要があります。
SYSOUT
制御文のリスティングおよびメッセージを出力するためのデータセットです。一般的にシステムの出力ストリームを利用します。
SORTIN
SORT/COPY処理の入力データセットです。
SORTINnn
MERGE処理の入力データセットです。データセットの名前は必ずしもSORTIN01から順序どおり定義する必要はありませんが、同じ番号を重複して使用することはできません。
SORTINWKnn
SORT処理中に作業領域として使用するデータセットです。
SORTOUT
SORT/MERGE/COPY処理の結果を出力するデータセットです。
SORTINまたはSORTINnnが固定長(FB)であれば、SORTOUTも固定長でなければなりません。一方、SORTINまたはSORTINnnが可変長(VB)であれば、SORTOUTも可変長でなければなりません。入力がNVSMのレコードをVSAMレコードで出力したり、VSAMレコードをNVSMレコードで出力することも可能です。
SORTOFxx
OUTFILでレコードを再フォーマットする際に、複数の出力データセットに出力する際のデータセットです。xxは1文字もしくは2文字で構成された任意の英文字や数字です。
SYMNAMES
シンボルを置換する場合、参照されるデータセットです。
-
レコード形式
シンボル名、フィールドの開始位置、フィールドの長さ、フィールドのフォーマット
JNFnCNTL
JOINを実行する際、subtasknの制御文です。JOINを実行する前に実行するSORT文を指定します。nは、1 または 2です。
-
-
/*文
SYSINデータセットの終了を指定します。SORT制御文のENDを使用して終了を指定することもできます。
3.2. データセットの定義
以下は、データセットの定義に一般的に必要なオペランドです。
| データセット名 | DCB | DISP | DSN | LABEL | SPACE | UNIT | VOL | AMP |
|---|---|---|---|---|---|---|---|---|
SORTIN |
1 |
O |
O |
2 |
X |
3 |
3 |
7 |
SORTINnn |
1 |
O |
O |
2 |
5 |
3 |
3 |
7 |
SORTOUT |
1 |
O |
4 |
2 |
5 |
3 |
6 |
7 |
SORTOFxx |
1 |
O |
4 |
2 |
5 |
3 |
6 |
7 |
SORTWKnn |
X |
4 |
4 |
X |
5 |
3 |
6 |
X |
JNFnCNTL |
1 |
4 |
4 |
2 |
5 |
3 |
3 |
7 |
-
O: 必ず指定
-
X: 指定しなくてもいい
-
1: 場合によって指定
-
2: ディスク上では指定不要
-
3: 現在のジョブ・ステップ以前に作成およびカタロギングされた場合は指定する必要がないが、そうでない場合は指定
-
4: 一時データセットでない場合は指定
-
5: 直接アクセス装置上に作成する場合は指定
-
6: 一時データセットの場合、現在のジョブ・ステップ以前に作成およびカタロギングされた場合、同じジョブ内の他のジョブ・ステップから渡された場合以外は指定
-
7: VSAMデータセットは指定可能、その他の場合は不要
DCBオペランドのサブパラメータ
入出力のデータセットがVSAMデータセットではない場合には、レコード形式(RECFM)、レコード長(LRECL)、ブロック・サイズ(BLKSIZE)の情報を指定する必要があります。
| 項目 | 説明 |
|---|---|
レコード形式(RECFM) |
データセットに記録されているレコードの形式を指定します |
レコード長(LRECL) |
データセットに記録されているレコードの論理的な最大長をバイト単位で指定します |
ブロック・サイズ(BLKSIZE) |
データセットに記録されているレコードの物理的な最大長をバイト単位で指定します |
上記の情報は、以下の順序で指定します。
-
RECFM、LRECL、BLKSIZEがDD文のDCBオペランドで指定されていれば、その情報を使用します。それ以外の情報は無視します。
-
入力データセットの場合、DCBオペランドが指定されていなければエラーが発生します。ただし、すでにデータセットが存在している場合には、既存の情報を使用します。出力データセットの場合、DCBオペランドの指定がなければ、以下の順序で指定されます。
-
OUTRECで指定された情報をオーバーライドして使用します。
-
RECORDで指定された情報をオーバーライドして使用します。
-
INRECで指定された情報をオーバーライドして使用します。
-
入力データセットで指定された情報をオーバーライドして使用します。
-