1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

VSAM on z/OS のレプリケーション - (4) VSAMファイルの追加(Kafka連携) / レプリケーションのテスト

Last updated at Posted at 2021-11-10

はじめに

ここまでで、z/OS上のVSAMファイルをDb2, Kafkaにレプリケーションするための構成の流れを見てきました。インフラ設定とVSAMファイルごとのレプリケーション設定を合わせて実施しているので、操作の位置づけが分かりにくいかもしれません。
ここでは、一旦一通りの構成が出来た後に、レプリケーションするVSAMファイルが増えた場合の追加分の手順を追ってみます。TargetとしてはKafkaを使用します。
また、CICSアプリからVSAMファイルを更新し、その更新情報がKafka Topic上ににどのようなメッセージとして伝播されるのかを確認してみます。

関連記事

VSAM on z/OS のレプリケーション - (1) 環境構築(to Db2)
VSAM on z/OS のレプリケーション - (2) レプリケーション構成(to Db2)
VSAM on z/OS のレプリケーション - (3) Kafka連携
VSAM on z/OS のレプリケーション - (4) VSAMファイルの追加(Kafka連携) / レプリケーションのテスト

全体像

image.png

ソース側設定

VSAM, LOGSTREAMの準備

参考: VSAM on z/OSのカスタマイズ

レプリケーション対象のVSAM(SMS対象のVOLに保持している必要あり) を選定します。既存のものがあれば、LOGREPLICATE, LOGSTREAMIDが指定されているかどうか確認します。指定されていなければ先の例に従ってログを取得するようパラメータを設定します。
今回は、新規にVSAMファイルを作成する想定で、以下のようなJCLでVSAMファイルを新規に作成することにします。

//DEFFILET JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=&SYSUID
//*********************************************************************
/*
//DELETE    EXEC PGM=IDCAMS,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 /* DELETE A FILET DATASET           */
 DELETE DB2P.CT56B4A1.FILET
/*
//DEFINE    EXEC PGM=IDCAMS,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 /* DEFINE A FILET DATASET           */
 DEFINE CLUSTER(NAME(DB2P.CT56B4A1.FILET)-
          REC(200)-
          LOG(ALL) -
          LOGREPLICATE -
          LOGSTREAMID(CEC.RMTLRS.CECREPL) -
          STORAGECLASS(SCDB2K) INDEXED) -
         DATA(NAME(DB2P.CT56B4A1.FILET.DATA)-
         RECSZ(200 200)-
         UNIQUE -
         KEYS(6 0)) -
        INDEX(NAME(DB2P.CT56B4A1.FILET.INDEX)-
          UNIQUE -
          SHR(2 3))
//*

1レコード200bytes、キーは先頭6bytesの想定です。また、LOGSTREAMは先に作成したものを使う想定です。別のLOGSTREAMを使用する場合は適宜LOGSTREAMも作成してください。

VSAM定義登録

参考: 1.1 VSAM定義登録

Linux上のコンテナとして稼働しているVSAM Remote Source上に、レプリケーション対象のVSAMファイルの情報を登録します。
コンテナに接続してClassicInstallAndMaintenanceMenu.shスクリプトを実行します。

[root@test12 ~]# podman exec -it --workdir /classic/usr/scripts ClassicCDCVSAM2 bash
[cecuser@ff6dc51e9523 scripts]$ ./ClassicInstallAndMaintenanceMenu.sh
*---------------------------------------------------------------------*
*
* IBM Data Replication VSAM for z/OS Remote Source, V11.4
* PID: 5737-C30
*
* Menu options:
*    1.  Set the job card
*    2.  Set the z/OS High Level Qualifier (HLQ)
*    3.  Set the z/OS Unix System Services (USS) path
*    4.  Install or replace z/OS libraries with this container's maintenance level
*    5.  Start a new z/OS log reader
*    6.  Stop the existing z/OS log reader
*    7.  Get diagnostic log for the existing z/OS log reader
*    8.  Configure a z/OS VSAM cluster for the container environment
*    9.  Configure VSAM IVP file
*   10.  Update container scripts from the current image
*   11.  Generate diagnostics tar
*   99.  Exit this script
*
*---------------------------------------------------------------------*
Select an option: 8
*---------------------------------------------------------------------*
*
* Classic CDC for VSAM
* Define a VSAM cluster to Linux components for refresh/replication
*
*---------------------------------------------------------------------*
Enter a VSAM base cluster data set name:DB2P.CT56B4A1.FILET
Enter the replication log to use for this VSAM DSN: CEC.RMTLRS.CECREPL
You provided DSN: <DB2P.CT56B4A1.FILET> with replication log: <CEC.RMTLRS.CECREPL>
Is this correct? (Y or N)y
DSN: <DB2P.CT56B4A1.FILET> added to <../../shell/vsamcat/vsamcat.txt>

Do you want to generate JCL to ALTER DSN: <DB2P.CT56B4A1.FILET> for change capture? (Y or N)n
Is CICS VR installed for VSAM batch logging? (Y or N)n
Do you want to generate JCL to DEFINE LOGSTREAM for replication log: <CEC.RMTLRS.CECREPL>? (Y or N)n
Should the IDCAMS ALTER JCL be submitted to your z/OS system? (Y or N)n
...

登録したいVSAMファイル(DB2P.CT56B4A1.FILET)、および、使用するLOGSTREAM(CEC.RMTLRS.CECREPL)の情報を登録します。各種JCLの生成はしません。ここで指定した情報はvsamcat.txtファイルに保持されます。

/classic/shell/vsamcat/vsamcat.txt
...
VSAMDD,DB2P.CT56B4A1.FILET,32760,0,20,C,K,Y,0,32764,Y,CEC.RMTLRS.CECREPL

VSAM表作成

参考: 1.5 VSAM表の作成

Classic Data ArchitectからVSAM Remote Sourceに接続してVSAM表を作成します。

COPYBOOKのインポート

ファイルに保持するレコードのレイアウトは以下のCOPYBOOKを使用する想定ですので、これをインポートします。インポートするプロジェクトは前回作成したものをそのまま使用します。(別プロジェクトとして作成したい場合はプロジェクトから作成してください。)

FILET.cpy
        01 RT-SEG.
            02 RT-KEY       PIC  X(06) VALUE '000001'.
            02 RT-ALPHA     PIC  X(10) VALUE 'ThisIsROOT'.
            02 RT-ALPHAKANA PIC  X(10) VALUE 'アイウエオカキクケコ'.
            02 RT-MIXDBCS   PIC  X(32)
                     VALUE 'あいうえおアイウエオ全角漢文'.
            02 RT-MIXALL    PIC  X(40)
                    VALUE 'ABCDEFGHあいうabcdefgh全角漢アイウエオカキク'.
            02 RT-GRAPHIC   PIC  G(15) USAGE DISPLAY-1
                   VALUE G'全角漢文字あいうえおアイウエオ'.
            02 RT-DECIMAL   PIC  9(10) VALUE 1234567890.
            02 RT-PACKED    PIC S9(05) COMP-3 VALUE 12345.
            02 RT-BINHALF   PIC S9(04) COMP  VALUE 1234.
            02 RT-BINFULL   PIC S9(08) COMP  VALUE 12345678.
            02 RT-BINDBLE   PIC S9(12) COMP  VALUE 123456789012.
            02 RT-GROUP.
             03 RT-GRP01    PIC  X(10) VALUE 'ThisIs1st!'.
             03 RT-GRP02    PIC  X(10) VALUE 'ThisIs2nd!'.
             03 RT-GRP03    PIC  X(10) VALUE 'ThisIs3rd!'.
            02  FILLER      PIC  X(15) VALUE SPACE.

プロジェクト右クリック - インポートを選択
image.png

Classic Data Architect - クラシック参照ファイル を選択して次へ
image.png

ローカルホストを選択し、ファイル・タイプ: COBOLコピーブック、ファイル: 上のFILET.cpy を選択して次へ
image.png

内容を確認して終了
image.png

VSAM表作成

物理データ・モデルも既存のものを使う想定です。物理データ・モデル以下のデータベースを右クリック - クラシック・オブジェクトの追加 - VSAM表を選択
image.png

データ定義横の参照ボタンをクリック
image.png

先ほどインポートしたCOPYBOOKを選択してOK
image.png

適当なスキーマ名を指定し、照会、変更キャプチャーを選択して次へ
image.png

表名:FILET、データセットの名前: DB2P.CT56B4A1.FILET を指定して次へ
image.png

以下のようにチェックして次へ
image.png

内容を確認して終了
image.png

VSAM表が作成されました。
image.png

DDLの生成/適用

上で作成したVSAM表は、WindowsのCDA上のプロジェクトとして作成しただけなので、これをVSAM Remote Source上に反映させる必要があります。VSAM Remote Source上に反映させるためにはDDL(SQL)を生成してそれを実行する必要があります。

上で生成したVSAM表(FILET)を右クリック - DDLの生成を選択
image.png

そのまま次へ
image.png

そのまま次へ
image.png

ファイル名に適当な値を指定し、サーバー上でDDLを実行にチェックを入れて次へ
image.png

参考:上で作成されたDDL
--<ScriptOptions statementTerminator=";"/>

CREATE TABLE "TEST01"."FILET" DBTYPE VSAM
	DS "DB2P.CT56B4A1.FILET"
	(

	"RT_KEY" SOURCE DEFINITION
		DATAMAP OFFSET 0 LENGTH 6
		DATATYPE C
		USE AS CHAR(6),
	"RT_ALPHA" SOURCE DEFINITION
		DATAMAP OFFSET 6 LENGTH 10
		DATATYPE C
		USE AS CHAR(10),
	"RT_ALPHAKANA" SOURCE DEFINITION
		DATAMAP OFFSET 16 LENGTH 10
		DATATYPE C
		USE AS CHAR(10),
	"RT_MIXDBCS" SOURCE DEFINITION
		DATAMAP OFFSET 26 LENGTH 32
		DATATYPE C
		USE AS CHAR(32),
	"RT_MIXALL" SOURCE DEFINITION
		DATAMAP OFFSET 58 LENGTH 40
		DATATYPE C
		USE AS CHAR(40),
	"RT_GRAPHIC" SOURCE DEFINITION
		DATAMAP OFFSET 98 LENGTH 15
		DATATYPE C
		USE AS GRAPHIC(15),
	"RT_DECIMAL" SOURCE DEFINITION
		DATAMAP OFFSET 128 LENGTH 10
		DATATYPE UC
		USE AS CHAR(10),
	"RT_PACKED" SOURCE DEFINITION
		DATAMAP OFFSET 138 LENGTH 3
		DATATYPE P
		USE AS DECIMAL(5 , 0),
	"RT_BINHALF" SOURCE DEFINITION
		DATAMAP OFFSET 141 LENGTH 2
		DATATYPE H
		USE AS SMALLINT,
	"RT_BINFULL" SOURCE DEFINITION
		DATAMAP OFFSET 143 LENGTH 4
		DATATYPE F
		USE AS INTEGER,
	"RT_BINDBLE" SOURCE DEFINITION
		DATAMAP OFFSET 147 LENGTH 8
		DATATYPE D
		USE AS DECIMAL(12 , 0),
	"RT_GRP01" SOURCE DEFINITION
		DATAMAP OFFSET 155 LENGTH 10
		DATATYPE C
		USE AS CHAR(10),
	"RT_GRP02" SOURCE DEFINITION
		DATAMAP OFFSET 165 LENGTH 10
		DATATYPE C
		USE AS CHAR(10),
	"RT_GRP03" SOURCE DEFINITION
		DATAMAP OFFSET 175 LENGTH 10
		DATATYPE C
		USE AS CHAR(10));

ALTER TABLE "TEST01"."FILET" DATA CAPTURE CHANGES;

適用先のVSAM Remote Sourceを選択して次へ
image.png

確認して終了
image.png

DDL適用結果の確認
image.png

データ・ソース・エクスプローラー・ビューから、VSAM Remote Source上に反映されたVSAM表が確認できます。
image.png

ターゲット側設定

参考: ターゲット環境(Kafka)構築
ターゲット側は、先に作成したKafka Brokerを使用する想定なので特に追加指定する必要はありません。

レプリケーション構成

参考: レプリケーション構成

レプリケーション設定(サブスクリプション)

Management ConsoleからAccess Serverに接続してレプリケーションの構成を行います。ソース用データストア、ターゲット用データストアは作成済みの想定なので、サブスクリプションの設定から追加していきます。

構成タブに切り替えて、サブスクリプションビューの"新規サブスクリプションの作成"アイコンをクリックします。
image.png

適当な名前を指定し、データストアにはソースとしてVsamRemoteSource01、ターゲットとしてKafka_test01を指定し、拡張設定をクリック
image.png

確認のみ。(ソースIDとして前画面の名前の先頭8文字がとられるようなので、全画面の名前も8文字にしておくとよい)
image.png

OK
image.png

はい
image.png

カスタムKafkaマッピングを選択して次へ
image.png

FILETを選択して次へ
image.png

キー列としてRT_KEYを選択して右矢印をクリック (キー列にRT_KEYが表示された状態にする)
次へ
image.png

現在のビューに戻るを選択して終了
image.png

Kafkaプロパティーの設定

上に表示された警告に従って、今作成したサブスクリプションを右クリック-Kafkaプロパティーを選択
image.png

ZooKeeper Serverを指定して、ZooKeeperのアドレス、ポートを指定します。また、Schema Registryのアドレス、ポートも指定します。
image.png

レプリケーション実行

リフレッシュ

まず最初に、現時点でのVSAMデータをKafkaに反映させておきます。
この時、CICSからはVSAMをClose状態にしておきます。

サブスクリプションを右クリック - リフレッシュの開始を選択
image.png

OK
image.png

Kafka上のTopicのリストを参照してみます。

[root@test12 ~/Kafka]# /opt/confluent-6.2.0/bin/kafka-topics --list --bootstrap-server localhost:9092 | grep -i filet
cdc_kafka_test01-FILET01-commitstream
cdc_kafka_test01.filet01.sourcedb.vsam.test01.filet

kafka-avro-console-consumerコマンドを使って Topic cdc_kafka_test01.filet01.sourcedb.vsam.test01.filetのメッセージを参照してみます。

[root@test12 ~/Kafka]# /opt/confluent-6.2.0/bin/kafka-avro-console-consumer --from-beginning --topic cdc_kafka_test01.filet01.sourcedb.vsam.test01.filet --bootstrap-server localhost:9092 --property print.key=true --property print.schema.ids=true
{"RT_KEY":{"string":"000001"}}  3       {"RT_KEY":{"string":"000001"},"RT_ALPHA":{"string":"ThisIsROOT"},"RT_ALPHAKANA":{"string":"アイウエオカキクケコ"},"RT_MIXDBCS":{"string":"あいうえおアイウエオ全角漢文  "},"RT_MIXALL":{"string":"ABCDEFGHあいうabcdefgh全角漢アイウエオカキク"},"RT_GRAPHIC":{"string":"全角漢文字あいうえおアイウエオ"},"RT_DECIMAL":{"string":"1234567890"},"RT_PACKED":{"int":12345},"RT_BINHALF":{"int":1234},"RT_BINFULL":{"int":12345678},"RT_BINDBLE":{"long":123456789012},"RT_GRP01":{"string":"ThisIs1st!"},"RT_GRP02":{"string":"ThisIs2nd!"},"RT_GRP03":{"string":"ThisIs3rd!"}}       4
{"RT_KEY":{"string":"000002"}}  3       {"RT_KEY":{"string":"000002"},"RT_ALPHA":{"string":"11:11:54.3"},"RT_ALPHAKANA":{"string":"アイウエオカキクケコ"},"RT_MIXDBCS":{"string":"あいうえおアイウエオ全角漢文  "},"RT_MIXALL":{"string":"ABCDEFGHあいうabcdefgh全角漢アイウエオカキク"},"RT_GRAPHIC":{"string":"全角漢文字あいうえおアイウエオ"},"RT_DECIMAL":{"string":"1234567890"},"RT_PACKED":{"int":12345},"RT_BINHALF":{"int":1234},"RT_BINFULL":{"int":12345678},"RT_BINDBLE":{"long":123456789012},"RT_GRP01":{"string":"ThisIs1st!"},"RT_GRP02":{"string":"ThisIs2nd!"},"RT_GRP03":{"string":"ThisIs3rd!"}}       4
{"RT_KEY":{"string":"000003"}}  3       {"RT_KEY":{"string":"000003"},"RT_ALPHA":{"string":"ThisIsROOT"},"RT_ALPHAKANA":{"string":"アイウエオカキクケコ"},"RT_MIXDBCS":{"string":"あいうえおアイウエオ全角漢文  "},"RT_MIXALL":{"string":"ABCDEFGHあいうabcdefgh全角漢アイウエオカキク"},"RT_GRAPHIC":{"string":"全角漢文字あいうえおアイウエオ"},"RT_DECIMAL":{"string":"1234567890"},"RT_PACKED":{"int":12345},"RT_BINHALF":{"int":1234},"RT_BINFULL":{"int":12345678},"RT_BINDBLE":{"long":123456789012},"RT_GRP01":{"string":"ThisIs1st!"},"RT_GRP02":{"string":"ThisIs2nd!"},"RT_GRP03":{"string":"ThisIs3rd!"}}       4
{"RT_KEY":{"string":"000004"}}  3       {"RT_KEY":{"string":"000004"},"RT_ALPHA":{"string":"ThisIsROOT"},"RT_ALPHAKANA":{"string":"アイウエオカキクケコ"},"RT_MIXDBCS":{"string":"あいうえおアイウエオ全角漢文  "},"RT_MIXALL":{"string":"ABCDEFGHあいうabcdefgh全角漢アイウエオカキク"},"RT_GRAPHIC":{"string":"全角漢文字あいうえおアイウエオ"},"RT_DECIMAL":{"string":"1234567890"},"RT_PACKED":{"int":12345},"RT_BINHALF":{"int":1234},"RT_BINFULL":{"int":12345678},"RT_BINDBLE":{"long":123456789012},"RT_GRP01":{"string":"ThisIs1st!"},"RT_GRP02":{"string":"ThisIs2nd!"},"RT_GRP03":{"string":"ThisIs3rd!"}}       4
スキーマ確認
[root@test12 ~]# curl -s  http://localhost:8081/schemas/ids/4 | jq .schema | sed -e 's/^"//' -e 's/"$//' -e 's/\\//g' | jq .
{
  "type": "record",
  "name": "FILET",
  "namespace": "value.SOURCEDB.VSAM.TEST01",
  "fields": [
    {
      "name": "RT_KEY",
      "type": [
        {
          "type": "string",
          "logicalType": "CHARACTER",
          "dbColumnName": "RT_KEY",
          "length": 6
        },
        "null"
      ],
      "doc": "",
      "default": ""
    },
    {
      "name": "RT_ALPHA",
      "type": [
        {
          "type": "string",
          "logicalType": "CHARACTER",
          "dbColumnName": "RT_ALPHA",
          "length": 10
        },
        "null"
      ],
      "doc": "",
      "default": ""
    },
    {
      "name": "RT_ALPHAKANA",
      "type": [
        {
          "type": "string",
          "logicalType": "CHARACTER",
          "dbColumnName": "RT_ALPHAKANA",
          "length": 10
        },
        "null"
      ],
      "doc": "",
      "default": ""
    },
    {
      "name": "RT_MIXDBCS",
      "type": [
        {
          "type": "string",
          "logicalType": "CHARACTER",
          "dbColumnName": "RT_MIXDBCS",
          "length": 32
        },
        "null"
      ],
      "doc": "",
      "default": ""
    },
    {
      "name": "RT_MIXALL",
      "type": [
        {
          "type": "string",
          "logicalType": "CHARACTER",
          "dbColumnName": "RT_MIXALL",
          "length": 40
        },
        "null"
      ],
      "doc": "",
      "default": ""
    },
    {
      "name": "RT_GRAPHIC",
      "type": [
        {
          "type": "string",
          "logicalType": "VARCHAR",
          "dbColumnName": "RT_GRAPHIC",
          "length": 15
        },
        "null"
      ],
      "doc": "",
      "default": ""
    },
    {
      "name": "RT_DECIMAL",
      "type": [
        {
          "type": "string",
          "logicalType": "CHARACTER",
          "dbColumnName": "RT_DECIMAL",
          "length": 10
        },
        "null"
      ],
      "doc": "",
      "default": ""
    },
    {
      "name": "RT_PACKED",
      "type": [
        {
          "type": "int",
          "logicalType": "DECIMAL",
          "dbColumnName": "RT_PACKED",
          "precision": 5,
          "scale": 0
        },
        "null"
      ],
      "doc": "",
      "default": 0
    },
    {
      "name": "RT_BINHALF",
      "type": [
        {
          "type": "int",
          "logicalType": "SMALLINT",
          "dbColumnName": "RT_BINHALF"
        },
        "null"
      ],
      "doc": "",
      "default": 0
    },
    {
      "name": "RT_BINFULL",
      "type": [
        {
          "type": "int",
          "logicalType": "INTEGER",
          "dbColumnName": "RT_BINFULL"
        },
        "null"
      ],
      "doc": "",
      "default": 0
    },
    {
      "name": "RT_BINDBLE",
      "type": [
        {
          "type": "long",
          "logicalType": "DECIMAL",
          "dbColumnName": "RT_BINDBLE",
          "precision": 12,
          "scale": 0
        },
        "null"
      ],
      "doc": "",
      "default": 0
    },
    {
      "name": "RT_GRP01",
      "type": [
        {
          "type": "string",
          "logicalType": "CHARACTER",
          "dbColumnName": "RT_GRP01",
          "length": 10
        },
        "null"
      ],
      "doc": "",
      "default": ""
    },
    {
      "name": "RT_GRP02",
      "type": [
        {
          "type": "string",
          "logicalType": "CHARACTER",
          "dbColumnName": "RT_GRP02",
          "length": 10
        },
        "null"
      ],
      "doc": "",
      "default": ""
    },
    {
      "name": "RT_GRP03",
      "type": [
        {
          "type": "string",
          "logicalType": "CHARACTER",
          "dbColumnName": "RT_GRP03",
          "length": 10
        },
        "null"
      ],
      "doc": "",
      "default": ""
    }
  ]
}

ミラーリングの開始

サブスクリプションを右クリック - ミラーリングの開始を選択
image.png

継続を選択してOK
image.png

モニタータブを開いて、指定したサブスクリプションの状態が"継続ミラーリング"になっていることを確認。
image.png

レプリケーションのテスト1

上の設定で、一通りVSAMファイルのレプリケーションの設定は済んだので、CICSアプリケーションからVSAMファイルを更新してその時の状況を確認してみます。
ここでは主に、DBCSや数値などいくつかの型を含むレコードのレプリケーション状況、および、Insert, Update, Delete処理がどのようにKafkaに伝播されるか、という辺りを見ていきます。

CICSアプリケーションの準備

単純なVSAMファイルアクセス用のプログラムをいくつか用意します。基本的にはCOMMAREAベースのアプリケーションで、キー値のみ指定して単発でVSAMファイルをアクセスするものです。テスト用なのでかなり単純化しています。
※更新系の操作のみKafkaへ反映されるので参照系のものはあまり意味が無いですが、一応作成しています。

レコード追加用

COMMAREAにキー値(6バイト)を指定して呼び出すと、キー値以外は固定の文字列(ソース中に埋め込まれた文字列)がセットされたレコードがVSAM(KSDS)に追加される。
実行例: CECI LINK PROGRAM(TGFADD) COMMAREA(000005)

ソース: TGFADD
TGFADD
       IDENTIFICATION   DIVISION.
        PROGRAM-ID.     TGFADD.
       DATA             DIVISION.
       WORKING-STORAGE  SECTION.
        01  RESP1               PIC S9(08)  COMP VALUE 0.

        01 Z-EIBFN              PIC X(15) VALUE ' '.
        01 Z-EIBRESP            PIC 9(4) VALUE ZERO.
        01 Z-EIBRESP2           PIC 9(4) VALUE ZERO.

        01  CURRENT-DATE.
            03  CURRENT-YEAR            PIC 9(2).
            03  CURRENT-MONTH           PIC 9(2).
            03  CURRENT-DAY             PIC 9(2).
        01  CURRENT-TIME.
            03  CURRENT-HOUR            PIC 9(2).
            03  CURRENT-MINUTE          PIC 9(2).
            03  CURRENT-SECOND          PIC 9(2).
            03  CURRENT-HNDSEC          PIC 9(2).

        01  WS-RAWTIME             PIC S9(15) COMP-3.
        01  CURRENT-DATE-CICS      PIC X(8).
        01  CURRENT-TIME-CICS      PIC X(8).

        01 TSQ-NAME                PIC X(8) VALUE 'TSQTESTQ'.
        01 FILE-NAME               PIC X(8) VALUE 'FILET'.

        01 RT-SEG.
            02 RT-KEY       PIC  X(06) VALUE '000001'.
            02 RT-ALPHA     PIC  X(10) VALUE 'ThisIsROOT'.
            02 RT-ALPHAKANA PIC  X(10) VALUE 'アイウエオカキクケコ'.
            02 RT-MIXDBCS   PIC  X(32)
                     VALUE 'あいうえおアイウエオ全角漢文'.
            02 RT-MIXALL    PIC  X(40)
                    VALUE 'ABCDEFGHあいうabcdefgh全角漢アイウエオカキク'.
           02 RT-GRAPHIC   PIC  G(15) USAGE DISPLAY-1
                   VALUE G'全角漢文字あいうえおアイウエオ'.
            02 RT-DECIMAL   PIC  9(10) VALUE 1234567890.
            02 RT-PACKED    PIC S9(05) COMP-3 VALUE 12345.
            02 RT-BINHALF   PIC S9(04) COMP  VALUE 1234.
            02 RT-BINFULL   PIC S9(08) COMP  VALUE 12345678.
            02 RT-BINDBLE   PIC S9(12) COMP  VALUE 123456789012.
            02 RT-GROUP.
             03 RT-GRP01    PIC  X(10) VALUE 'ThisIs1st!'.
             03 RT-GRP02    PIC  X(10) VALUE 'ThisIs2nd!'.
             03 RT-GRP03    PIC  X(10) VALUE 'ThisIs3rd!'.
            02  FILLER      PIC  X(15) VALUE SPACE.

        01 TEMP-RECORD PIC X(200).
      *---------------------------------------------------------------
       LINKAGE SECTION.
        01 DFHCOMMAREA.
           03 COMMAREA-DATA    PIC X(6).
      *---------------------------------------------------------------
       PROCEDURE        DIVISION.
           DISPLAY 'TGFADD Start-------------'
      * Get Timestamp from ACCEPT
           ACCEPT CURRENT-DATE FROM DATE.
           ACCEPT CURRENT-TIME FROM TIME.
           DISPLAY 'ACCEPT DATE = ' CURRENT-MONTH '/'
              CURRENT-DAY '/' CURRENT-YEAR  '  (mm/dd/yy)'.
           DISPLAY '       TIME = ' CURRENT-HOUR ':'
              CURRENT-MINUTE ':' CURRENT-SECOND '.' CURRENT-HNDSEC

      * Display COMMAREA
           DISPLAY '    Received COMMAREA: ' COMMAREA-DATA.

      * Move COMMAREA-DATA to Key
           IF EIBCALEN > 0 AND EIBCALEN < 7 THEN
             MOVE COMMAREA-DATA TO RT-KEY
           END-IF.

      * WRITEQ TS
           EXEC CICS WRITEQ TS QUEUE(TSQ-NAME)
                     FROM(RT-SEG)
                     LENGTH(LENGTH OF RT-SEG)
                     RESP(Z-EIBRESP)
                     RESP2(Z-EIBRESP2)
           END-EXEC.

           IF Z-EIBRESP NOT = DFHRESP(NORMAL) THEN
              DISPLAY '***** WRITEQ TS ERROR!'
              DISPLAY 'RESP: ' Z-EIBRESP
              DISPLAY 'RESP2: ' Z-EIBRESP2
              EXEC CICS ABEND ABCODE('TTTT') END-EXEC
              EXEC CICS RETURN END-EXEC
           ELSE
              DISPLAY 'WRITEQ TS OK'
           END-IF.


      * WRITE FILE (Add Record)
           EXEC CICS WRITE FILE(FILE-NAME)
                     FROM(RT-SEG)
                     RIDFLD(RT-KEY)
                     LENGTH(LENGTH OF RT-SEG)
                     RESP(Z-EIBRESP)
                     RESP2(Z-EIBRESP2)
           END-EXEC.


           IF Z-EIBRESP NOT = DFHRESP(NORMAL) THEN
              DISPLAY '***** WRITE FILE ERROR!'
              DISPLAY 'RESP: ' Z-EIBRESP
              DISPLAY 'RESP2: ' Z-EIBRESP2
              IF Z-EIBRESP = DFHRESP(DUPREC) THEN
                  DISPLAY 'DUPLICATTE KEY!'
              END-IF
              EXEC CICS ABEND ABCODE('TTTT') END-EXEC
              EXEC CICS RETURN END-EXEC
           ELSE
              DISPLAY 'WRITE FILE OK'
           END-IF.

      *  Display Data
           DISPLAY '*****'.
      *    DISPLAY 'LENGTH Total: ' LENGTH OF RT-SEG.
      *    DISPLAY 'LENGTH RT-PACKED: ' LENGTH OF RT-PACKED.
      *    DISPLAY 'LENGTH RT-BINHALF: ' LENGTH OF RT-BINHALF.
      *    DISPLAY 'LENGTH RT-BINFULL: ' LENGTH OF RT-BINFULL.
      *    DISPLAY 'LENGTH RT-BINDBLE: ' LENGTH OF RT-BINDBLE.
           DISPLAY RT-SEG.
           DISPLAY '*****'.

      * Delay
           EXEC CICS DELAY FOR SECONDS(1) END-EXEC.
      * End
           DISPLAY 'TGFADD End---------------'.
           EXEC CICS RETURN END-EXEC.

レコード更新用

COMMAREAにキー値(6バイト)を指定して呼び出すと、指定したキー値を持つレコードの情報を上書きする。
基本的にはキー値以外は固定の文字列(ソース中に埋め込まれた文字列)がセットされたレコードがVSAM(KSDS)に追加される。
ただし、RT-ALPHAフィールドには実行時のタイムスタンプをセットし、また、RT-MIXDBCSフィールドには環境依存文字を含む文字列をセットする。
実行例: CECI LINK PROGRAM(TGFUPDT) COMMAREA(000005)

ソース: TGFUPDT
TGFUPDT
       IDENTIFICATION   DIVISION.
        PROGRAM-ID.     TGFUPDT.
       DATA             DIVISION.
       WORKING-STORAGE  SECTION.
        01  RESP1               PIC S9(08)  COMP VALUE 0.

        01 Z-EIBFN              PIC X(15) VALUE ' '.
        01 Z-EIBRESP            PIC 9(4) VALUE ZERO.
        01 Z-EIBRESP2           PIC 9(4) VALUE ZERO.

        01  CURRENT-DATE.
            03  CURRENT-YEAR            PIC 9(2).
            03  CURRENT-MONTH           PIC 9(2).
            03  CURRENT-DAY             PIC 9(2).
        01  CURRENT-TIME.
            03  CURRENT-HOUR            PIC 9(2).
            03  CURRENT-MINUTE          PIC 9(2).
            03  CURRENT-SECOND          PIC 9(2).
            03  CURRENT-HNDSEC          PIC 9(2).

        01  WS-RAWTIME             PIC S9(15) COMP-3.
        01  CURRENT-DATE-CICS      PIC X(8).
        01  CURRENT-TIME-CICS      PIC X(8).

        01 TSQ-NAME                PIC X(8) VALUE 'TSQTESTQ'.
        01 FILE-NAME               PIC X(8) VALUE 'FILET'.

        01 RT-SEG.
            02 RT-KEY       PIC  X(06) VALUE '000001'.
            02 RT-ALPHA     PIC  X(10) VALUE '00:00:00.0'.
            02 RT-ALPHAKANA PIC  X(10) VALUE 'アイウエオカキクケコ'.
            02 RT-MIXDBCS   PIC  X(32)
                     VALUE 'あいうえおアイウエオ㈱①Ⅰ鯵鰺'.
            02 RT-MIXALL    PIC  X(40)
                    VALUE 'ABCDEFGHあいうabcdefgh全角漢アイウエオカキク'.
            02 RT-GRAPHIC   PIC  G(15) USAGE DISPLAY-1
                   VALUE G'全角漢文字あいうえおアイウエオ'.
            02 RT-DECIMAL   PIC  9(10) VALUE 1234567890.
            02 RT-PACKED    PIC S9(05) COMP-3 VALUE 12345.
            02 RT-BINHALF   PIC S9(04) COMP  VALUE 1234.
            02 RT-BINFULL   PIC S9(08) COMP  VALUE 12345678.
            02 RT-BINDBLE   PIC S9(12) COMP  VALUE 123456789012.
            02 RT-GROUP.
             03 RT-GRP01    PIC  X(10) VALUE 'ThisIs1st!'.
             03 RT-GRP02    PIC  X(10) VALUE 'ThisIs2nd!'.
             03 RT-GRP03    PIC  X(10) VALUE 'ThisIs3rd!'.
            02  FILLER      PIC  X(15) VALUE SPACE.

        01 TEMP-SEG.
            02 TEMP-KEY       PIC  X(06).
            02 TEMP-ALPHA     PIC  X(10).
            02 TEMP-ALPHAKANA PIC  X(10).
            02 TEMP-MIXDBCS   PIC  X(32).
            02 TEMP-MIXALL    PIC  X(40).
            02 TEMP-GRAPHIC   PIC  G(15) USAGE DISPLAY-1.
            02 TEMP-DECIMAL   PIC  9(10) .
            02 TEMP-PACKED    PIC S9(05) COMP-3.
            02 TEMP-BINHALF   PIC S9(04) COMP.
            02 TEMP-BINFULL   PIC S9(08) COMP.
            02 TEMP-BINDBLE   PIC S9(12) COMP.
            02 TEMP-GROUP.
             03 TEMP-GRP01    PIC  X(10).
             03 TEMP-GRP02    PIC  X(10).
             03 TEMP-GRP03    PIC  X(10).
            02  FILLER      PIC  X(15).

         01 CURRENT-TIME-STR PIC X(10) VALUE '00:00:00.0'.

      *---------------------------------------------------------------
       LINKAGE SECTION.
        01 DFHCOMMAREA.
           03 COMMAREA-DATA    PIC X(6).
      *---------------------------------------------------------------
       PROCEDURE        DIVISION.
           DISPLAY 'TGFUPDT Start-------------'
      * Get Timestamp from ACCEPT
           ACCEPT CURRENT-DATE FROM DATE.
           ACCEPT CURRENT-TIME FROM TIME.
           DISPLAY 'ACCEPT DATE = ' CURRENT-MONTH '/'
              CURRENT-DAY '/' CURRENT-YEAR  '  (mm/dd/yy)'.
           DISPLAY '       TIME = ' CURRENT-HOUR ':'
              CURRENT-MINUTE ':' CURRENT-SECOND '.' CURRENT-HNDSEC

      * Display COMMAREA
           DISPLAY '    Received COMMAREA: ' COMMAREA-DATA.

      * Move COMMAREA-DATA to Key
           IF EIBCALEN > 0 AND EIBCALEN < 7 THEN
             MOVE COMMAREA-DATA TO RT-KEY
             MOVE COMMAREA-DATA TO TEMP-KEY
           END-IF.

      * READ FILE with UPDATE (Read Record)
           EXEC CICS READ FILE(FILE-NAME)
                     INTO(TEMP-SEG)
                     RIDFLD(TEMP-KEY)
                     LENGTH(LENGTH OF TEMP-SEG)
                     UPDATE
                     RESP(Z-EIBRESP)
                     RESP2(Z-EIBRESP2)
           END-EXEC.

           IF Z-EIBRESP NOT = DFHRESP(NORMAL) THEN
              DISPLAY '***** READ FILE ERROR!'
              DISPLAY 'RESP: ' Z-EIBRESP
              DISPLAY 'RESP2: ' Z-EIBRESP2
              IF Z-EIBRESP = DFHRESP(NOTFND) THEN
                  DISPLAY 'NOT FOUND!'
              END-IF
              EXEC CICS ABEND ABCODE('TTTT') END-EXEC
              EXEC CICS RETURN END-EXEC
           ELSE
              DISPLAY 'READ FILE OK'
           END-IF.

      * Display Data
           DISPLAY 'Before Data*****'.
      *    DISPLAY 'LENGTH Total: ' LENGTH OF RT-SEG.
      *    DISPLAY 'LENGTH RT-PACKED: ' LENGTH OF RT-PACKED.
      *    DISPLAY 'LENGTH RT-BINHALF: ' LENGTH OF RT-BINHALF.
      *    DISPLAY 'LENGTH RT-BINFULL: ' LENGTH OF RT-BINFULL.
      *    DISPLAY 'LENGTH RT-BINDBLE: ' LENGTH OF RT-BINDBLE.
           DISPLAY TEMP-SEG.
           DISPLAY '*****'.

      * Set Current Time to New Record
           STRING CURRENT-HOUR, ':'
                  CURRENT-MINUTE, ':',
                  CURRENT-SECOND, '.'
                  CURRENT-HNDSEC(1:1)
                  DELIMITED BY SIZE INTO CURRENT-TIME-STR.
           MOVE CURRENT-TIME-STR TO RT-ALPHA.

      * REWRITE FILE (Update Record)
           EXEC CICS REWRITE FILE(FILE-NAME)
                     FROM(RT-SEG)
                     LENGTH(LENGTH OF RT-SEG)
                     RESP(Z-EIBRESP)
                     RESP2(Z-EIBRESP2)
           END-EXEC.


           IF Z-EIBRESP NOT = DFHRESP(NORMAL) THEN
              DISPLAY '***** REWRITE FILE ERROR!'
              DISPLAY 'RESP: ' Z-EIBRESP
              DISPLAY 'RESP2: ' Z-EIBRESP2
              EXEC CICS ABEND ABCODE('TTTT') END-EXEC
              EXEC CICS RETURN END-EXEC
           ELSE
              DISPLAY 'REWRITE FILE OK'
           END-IF.

      * Display Data
           DISPLAY 'After Data*****'.
      *    DISPLAY 'LENGTH Total: ' LENGTH OF RT-SEG.
      *    DISPLAY 'LENGTH RT-PACKED: ' LENGTH OF RT-PACKED.
      *    DISPLAY 'LENGTH RT-BINHALF: ' LENGTH OF RT-BINHALF.
      *    DISPLAY 'LENGTH RT-BINFULL: ' LENGTH OF RT-BINFULL.
      *    DISPLAY 'LENGTH RT-BINDBLE: ' LENGTH OF RT-BINDBLE.
           DISPLAY RT-SEG.
           DISPLAY '*****'.

      * Delay
           EXEC CICS DELAY FOR SECONDS(1) END-EXEC.
      * End
           DISPLAY 'TGFUPDT End---------------'.
           EXEC CICS RETURN END-EXEC.

レコード削除用

COMMAREAにキー値(6バイト)を指定して呼び出すと、指定したキー値を持つレコードが削除される。
実行例: CECI LINK PROGRAM(TGFDEL) COMMAREA(000005)

ソース: TGFDEL
TGFDEL
       IDENTIFICATION   DIVISION.
        PROGRAM-ID.     TGFDEL.
       DATA             DIVISION.
       WORKING-STORAGE  SECTION.
        01  RESP1               PIC S9(08)  COMP VALUE 0.

        01 Z-EIBFN              PIC X(15) VALUE ' '.
        01 Z-EIBRESP            PIC 9(4) VALUE ZERO.
        01 Z-EIBRESP2           PIC 9(4) VALUE ZERO.

        01  CURRENT-DATE.
            03  CURRENT-YEAR            PIC 9(2).
            03  CURRENT-MONTH           PIC 9(2).
            03  CURRENT-DAY             PIC 9(2).
        01  CURRENT-TIME.
            03  CURRENT-HOUR            PIC 9(2).
            03  CURRENT-MINUTE          PIC 9(2).
            03  CURRENT-SECOND          PIC 9(2).
            03  CURRENT-HNDSEC          PIC 9(2).

        01  WS-RAWTIME             PIC S9(15) COMP-3.
        01  CURRENT-DATE-CICS      PIC X(8).
        01  CURRENT-TIME-CICS      PIC X(8).

        01 TSQ-NAME                PIC X(8) VALUE 'TSQTESTQ'.
        01 FILE-NAME               PIC X(8) VALUE 'FILET'.

        01 RT-SEG.
            02 RT-KEY       PIC  X(06) VALUE '000001'.
            02 RT-ALPHA     PIC  X(10) VALUE 'ThisIsROOT'.
            02 RT-ALPHAKANA PIC  X(10) VALUE 'アイウエオカキクケコ'.
            02 RT-MIXDBCS   PIC  X(32)
                     VALUE 'あいうえおアイウエオ全角漢文'.
            02 RT-MIXALL    PIC  X(40)
                    VALUE 'ABCDEFGHあいうabcdefgh全角漢アイウエオカキク'.
            02 RT-GRAPHIC   PIC  G(15) USAGE DISPLAY-1
                   VALUE G'全角漢文字あいうえおアイウエオ'.
            02 RT-DECIMAL   PIC  9(10) VALUE 1234567890.
            02 RT-PACKED    PIC S9(05) COMP-3 VALUE 12345.
            02 RT-BINHALF   PIC S9(04) COMP  VALUE 1234.
            02 RT-BINFULL   PIC S9(08) COMP  VALUE 12345678.
            02 RT-BINDBLE   PIC S9(12) COMP  VALUE 123456789012.
            02 RT-GROUP.
             03 RT-GRP01    PIC  X(10) VALUE 'ThisIs1st!'.
             03 RT-GRP02    PIC  X(10) VALUE 'ThisIs2nd!'.
             03 RT-GRP03    PIC  X(10) VALUE 'ThisIs3rd!'.
            02  FILLER      PIC  X(15) VALUE SPACE.

      *---------------------------------------------------------------
       LINKAGE SECTION.
        01 DFHCOMMAREA.
           03 COMMAREA-DATA    PIC X(6).
      *---------------------------------------------------------------
       PROCEDURE        DIVISION.
           DISPLAY 'TGFDEL Start-------------'
      * Get Timestamp from ACCEPT
           ACCEPT CURRENT-DATE FROM DATE.
           ACCEPT CURRENT-TIME FROM TIME.
           DISPLAY 'ACCEPT DATE = ' CURRENT-MONTH '/'
              CURRENT-DAY '/' CURRENT-YEAR  '  (mm/dd/yy)'.
           DISPLAY '       TIME = ' CURRENT-HOUR ':'
              CURRENT-MINUTE ':' CURRENT-SECOND '.' CURRENT-HNDSEC

      * Display COMMAREA
           DISPLAY '    Received COMMAREA: ' COMMAREA-DATA.

      * Move COMMAREA-DATA to Key
           IF EIBCALEN > 0 AND EIBCALEN < 7 THEN
             MOVE COMMAREA-DATA TO RT-KEY
           END-IF.

      * DELETE FILE
           EXEC CICS DELETE FILE(FILE-NAME)
                     RIDFLD(RT-KEY)
                     RESP(Z-EIBRESP)
                     RESP2(Z-EIBRESP2)
           END-EXEC.


           IF Z-EIBRESP NOT = DFHRESP(NORMAL) THEN
              DISPLAY '***** DELETE FILE ERROR!'
              DISPLAY 'RESP: ' Z-EIBRESP
              DISPLAY 'RESP2: ' Z-EIBRESP2
              IF Z-EIBRESP = DFHRESP(NOTFND) THEN
                  DISPLAY 'NOT FOUND!'
              END-IF
              EXEC CICS ABEND ABCODE('TTTT') END-EXEC
              EXEC CICS RETURN END-EXEC
           ELSE
              DISPLAY 'DELETE FILE OK'
           END-IF.

      * Display Data
      *    DISPLAY '*****'.
      *    DISPLAY 'LENGTH Total: ' LENGTH OF RT-SEG.
      *    DISPLAY 'LENGTH RT-PACKED: ' LENGTH OF RT-PACKED.
      *    DISPLAY 'LENGTH RT-BINHALF: ' LENGTH OF RT-BINHALF.
      *    DISPLAY 'LENGTH RT-BINFULL: ' LENGTH OF RT-BINFULL.
      *    DISPLAY 'LENGTH RT-BINDBLE: ' LENGTH OF RT-BINDBLE.
      *     DISPLAY RT-SEG.
      *     DISPLAY '*****'.

      * Delay
           EXEC CICS DELAY FOR SECONDS(1) END-EXEC.
      * End
           DISPLAY 'TGFDEL End---------------'.
           EXEC CICS RETURN END-EXEC.

レコード参照用(1レコード)

COMMAREAにキー値(6バイト)を指定して呼び出すと、指定したキー値をもつレコード(1件)を読み、内容をDISPLAY文で出力(JOBLOGのCEEMSGで確認)。
実行例: CECI LINK PROGRAM(TGFREAD) COMMAREA(000001)

ソース: TGFREAD
TGFREAD
       IDENTIFICATION   DIVISION.
        PROGRAM-ID.     TGFREAD.
       DATA             DIVISION.
       WORKING-STORAGE  SECTION.
        01  RESP1               PIC S9(08)  COMP VALUE 0.

        01 Z-EIBFN              PIC X(15) VALUE ' '.
        01 Z-EIBRESP            PIC 9(4) VALUE ZERO.
        01 Z-EIBRESP2           PIC 9(4) VALUE ZERO.

        01  CURRENT-DATE.
            03  CURRENT-YEAR            PIC 9(2).
            03  CURRENT-MONTH           PIC 9(2).
            03  CURRENT-DAY             PIC 9(2).
        01  CURRENT-TIME.
            03  CURRENT-HOUR            PIC 9(2).
            03  CURRENT-MINUTE          PIC 9(2).
            03  CURRENT-SECOND          PIC 9(2).
            03  CURRENT-HNDSEC          PIC 9(2).

        01  WS-RAWTIME             PIC S9(15) COMP-3.
        01  CURRENT-DATE-CICS      PIC X(8).
        01  CURRENT-TIME-CICS      PIC X(8).

        01 TSQ-NAME                PIC X(8) VALUE 'TSQTESTQ'.
        01 FILE-NAME               PIC X(8) VALUE 'FILET'.

        01 RT-SEG.
            02 RT-KEY       PIC  X(06) VALUE '000001'.
            02 RT-ALPHA     PIC  X(10) VALUE 'ThisIsROOT'.
            02 RT-ALPHAKANA PIC  X(10) VALUE 'アイウエオカキクケコ'.
            02 RT-MIXDBCS   PIC  X(32)
                     VALUE 'あいうえおアイウエオ全角漢文'.
            02 RT-MIXALL    PIC  X(40)
                    VALUE 'ABCDEFGHあいうabcdefgh全角漢アイウエオカキク'.
            02 RT-GRAPHIC   PIC  G(15) USAGE DISPLAY-1
                   VALUE G'全角漢文字あいうえおアイウエオ'.
            02 RT-DECIMAL   PIC  9(10) VALUE 1234567890.
            02 RT-PACKED    PIC S9(05) COMP-3 VALUE 12345.
            02 RT-BINHALF   PIC S9(04) COMP  VALUE 1234.
            02 RT-BINFULL   PIC S9(08) COMP  VALUE 12345678.
            02 RT-BINDBLE   PIC S9(12) COMP  VALUE 123456789012.
            02 RT-GROUP.
             03 RT-GRP01    PIC  X(10) VALUE 'ThisIs1st!'.
             03 RT-GRP02    PIC  X(10) VALUE 'ThisIs2nd!'.
             03 RT-GRP03    PIC  X(10) VALUE 'ThisIs3rd!'.
            02  FILLER      PIC  X(15) VALUE SPACE.

        01 TEMP-SEG.
            02 TEMP-KEY       PIC  X(06).
            02 TEMP-ALPHA     PIC  X(10).
            02 TEMP-ALPHAKANA PIC  X(10).
            02 TEMP-MIXDBCS   PIC  X(32).
            02 TEMP-MIXALL    PIC  X(40).
            02 TEMP-GRAPHIC   PIC  G(15) USAGE DISPLAY-1.
            02 TEMP-DECIMAL   PIC  9(10) .
            02 TEMP-PACKED    PIC S9(05) COMP-3.
            02 TEMP-BINHALF   PIC S9(04) COMP.
            02 TEMP-BINFULL   PIC S9(08) COMP.
            02 TEMP-BINDBLE   PIC S9(12) COMP.
            02 TEMP-GROUP.
             03 TEMP-GRP01    PIC  X(10).
             03 TEMP-GRP02    PIC  X(10).
             03 TEMP-GRP03    PIC  X(10).
            02  FILLER      PIC  X(15).
      *---------------------------------------------------------------
       LINKAGE SECTION.
        01 DFHCOMMAREA.
           03 COMMAREA-DATA    PIC X(6).
      *---------------------------------------------------------------
       PROCEDURE        DIVISION.
           DISPLAY 'TGFREAD Start-------------'
      * Get Timestamp from ACCEPT
           ACCEPT CURRENT-DATE FROM DATE.
           ACCEPT CURRENT-TIME FROM TIME.
           DISPLAY 'ACCEPT DATE = ' CURRENT-MONTH '/'
              CURRENT-DAY '/' CURRENT-YEAR  '  (mm/dd/yy)'.
           DISPLAY '       TIME = ' CURRENT-HOUR ':'
              CURRENT-MINUTE ':' CURRENT-SECOND '.' CURRENT-HNDSEC

      * Display COMMAREA
           DISPLAY '    Received COMMAREA: ' COMMAREA-DATA.

      * Move COMMAREA-DATA to Key
           IF EIBCALEN > 0 AND EIBCALEN < 7 THEN
             MOVE COMMAREA-DATA TO TEMP-KEY
           END-IF.

      * READ FILE (Read Record)
           EXEC CICS READ FILE(FILE-NAME)
                     INTO(TEMP-SEG)
                     RIDFLD(TEMP-KEY)
                     LENGTH(LENGTH OF TEMP-SEG)
                     RESP(Z-EIBRESP)
                     RESP2(Z-EIBRESP2)
           END-EXEC.


           IF Z-EIBRESP NOT = DFHRESP(NORMAL) THEN
              DISPLAY '***** READ FILE ERROR!'
              DISPLAY 'RESP: ' Z-EIBRESP
              DISPLAY 'RESP2: ' Z-EIBRESP2
              IF Z-EIBRESP = DFHRESP(NOTFND) THEN
                  DISPLAY 'NOT FOUND!'
              END-IF
              EXEC CICS ABEND ABCODE('TTTT') END-EXEC
              EXEC CICS RETURN END-EXEC
           ELSE
              DISPLAY 'READ FILE OK'
           END-IF.

      * Display Data
           DISPLAY '*****'.
      *    DISPLAY 'LENGTH Total: ' LENGTH OF RT-SEG.
      *    DISPLAY 'LENGTH RT-PACKED: ' LENGTH OF RT-PACKED.
      *    DISPLAY 'LENGTH RT-BINHALF: ' LENGTH OF RT-BINHALF.
      *    DISPLAY 'LENGTH RT-BINFULL: ' LENGTH OF RT-BINFULL.
      *    DISPLAY 'LENGTH RT-BINDBLE: ' LENGTH OF RT-BINDBLE.
           DISPLAY TEMP-SEG.
           DISPLAY '*****'.

      * Delay
           EXEC CICS DELAY FOR SECONDS(1) END-EXEC.
      * End
           DISPLAY 'TGFREAD End---------------'.
           EXEC CICS RETURN END-EXEC.

レコード参照用(複数レコード)

COMMAREAにキー値(6バイト)を指定して呼び出すと、指定したキー値以降のレコードを読み、内容をDISPLAY文で出力(JOBLOGのCEEMSGで確認)。
実行例: CECI LINK PROGRAM(TGFREAD) COMMAREA(000001)

ソース: TGFLIST
TGFLIST
       IDENTIFICATION   DIVISION.
        PROGRAM-ID.     TGFLIST.
       DATA             DIVISION.
       WORKING-STORAGE  SECTION.
        01  RESP1               PIC S9(08)  COMP VALUE 0.

        01 Z-EIBFN              PIC X(15) VALUE ' '.
        01 Z-EIBRESP            PIC 9(4) VALUE ZERO.
        01 Z-EIBRESP2           PIC 9(4) VALUE ZERO.

        01  CURRENT-DATE.
            03  CURRENT-YEAR            PIC 9(2).
            03  CURRENT-MONTH           PIC 9(2).
            03  CURRENT-DAY             PIC 9(2).
        01  CURRENT-TIME.
            03  CURRENT-HOUR            PIC 9(2).
            03  CURRENT-MINUTE          PIC 9(2).
            03  CURRENT-SECOND          PIC 9(2).
            03  CURRENT-HNDSEC          PIC 9(2).

        01  WS-RAWTIME             PIC S9(15) COMP-3.
        01  CURRENT-DATE-CICS      PIC X(8).
        01  CURRENT-TIME-CICS      PIC X(8).

        01 TSQ-NAME                PIC X(8) VALUE 'TSQTESTQ'.
        01 FILE-NAME               PIC X(8) VALUE 'FILET'.

        01 RT-SEG.
            02 RT-KEY       PIC  X(06) VALUE '000001'.
            02 RT-ALPHA     PIC  X(10) VALUE 'ThisIsROOT'.
            02 RT-ALPHAKANA PIC  X(10) VALUE 'アイウエオカキクケコ'.
            02 RT-MIXDBCS   PIC  X(32)
                     VALUE 'あいうえおアイウエオ全角漢文'.
            02 RT-MIXALL    PIC  X(40)
                    VALUE 'ABCDEFGHあいうabcdefgh全角漢アイウエオカキク'.
            02 RT-GRAPHIC   PIC  G(15) USAGE DISPLAY-1
                   VALUE G'全角漢文字あいうえおアイウエオ'.
            02 RT-DECIMAL   PIC  9(10) VALUE 1234567890.
            02 RT-PACKED    PIC S9(05) COMP-3 VALUE 12345.
            02 RT-BINHALF   PIC S9(04) COMP  VALUE 1234.
            02 RT-BINFULL   PIC S9(08) COMP  VALUE 12345678.
            02 RT-BINDBLE   PIC S9(12) COMP  VALUE 123456789012.
            02 RT-GROUP.
             03 RT-GRP01    PIC  X(10) VALUE 'ThisIs1st!'.
             03 RT-GRP02    PIC  X(10) VALUE 'ThisIs2nd!'.
             03 RT-GRP03    PIC  X(10) VALUE 'ThisIs3rd!'.
            02  FILLER      PIC  X(15) VALUE SPACE.

        01 TEMP-SEG.
            02 TEMP-KEY       PIC  X(06).
            02 TEMP-ALPHA     PIC  X(10).
            02 TEMP-ALPHAKANA PIC  X(10).
            02 TEMP-MIXDBCS   PIC  X(32).
            02 TEMP-MIXALL    PIC  X(40).
            02 TEMP-GRAPHIC   PIC  G(15) USAGE DISPLAY-1.
            02 TEMP-DECIMAL   PIC  9(10) .
            02 TEMP-PACKED    PIC S9(05) COMP-3.
            02 TEMP-BINHALF   PIC S9(04) COMP.
            02 TEMP-BINFULL   PIC S9(08) COMP.
            02 TEMP-BINDBLE   PIC S9(12) COMP.
            02 TEMP-GROUP.
             03 TEMP-GRP01    PIC  X(10).
             03 TEMP-GRP02    PIC  X(10).
             03 TEMP-GRP03    PIC  X(10).
            02  FILLER      PIC  X(15).

         01 SRCH-KEY PIC X(10).
         01 LINE-CNT PIC S9(4) COMP VALUE +0.
      *---------------------------------------------------------------
       LINKAGE SECTION.
        01 DFHCOMMAREA.
           03 COMMAREA-DATA    PIC X(6).
      *---------------------------------------------------------------
       PROCEDURE        DIVISION.
           DISPLAY 'TGFLIST Start-------------'
      * Get Timestamp from ACCEPT
           ACCEPT CURRENT-DATE FROM DATE.
           ACCEPT CURRENT-TIME FROM TIME.
           DISPLAY 'ACCEPT DATE = ' CURRENT-MONTH '/'
              CURRENT-DAY '/' CURRENT-YEAR  '  (mm/dd/yy)'.
           DISPLAY '       TIME = ' CURRENT-HOUR ':'
              CURRENT-MINUTE ':' CURRENT-SECOND '.' CURRENT-HNDSEC

      * Display COMMAREA
           DISPLAY '    Received COMMAREA: ' COMMAREA-DATA.

      * Move COMMAREA-DATA to Key
           IF EIBCALEN > 0 AND EIBCALEN < 7 THEN
             MOVE COMMAREA-DATA TO SRCH-KEY
           END-IF.

      * READ All Record
       SRCH-RESUME.
           EXEC CICS STARTBR FILE(FILE-NAME)
                     RIDFLD(SRCH-KEY) GTEQ
                     RESP(Z-EIBRESP)
                     RESP2(Z-EIBRESP2)
           END-EXEC.

           IF Z-EIBRESP NOT = DFHRESP(NORMAL) THEN
              DISPLAY '***** STARTBR FILE ERROR!'
              DISPLAY 'RESP: ' Z-EIBRESP
              DISPLAY 'RESP2: ' Z-EIBRESP2
              IF Z-EIBRESP = DFHRESP(NOTFND) THEN
                  DISPLAY 'NOT FOUND!'
              END-IF
              EXEC CICS ABEND ABCODE('TTTT') END-EXEC
              EXEC CICS RETURN END-EXEC
           ELSE
              DISPLAY 'STARTBR FILE OK'
           END-IF.

       SRCH-LOOP.
           EXEC CICS READNEXT FILE(FILE-NAME)
                     INTO(TEMP-SEG)
                     RIDFLD(SRCH-KEY)
                     LENGTH(LENGTH OF TEMP-SEG)
                     RESP(Z-EIBRESP)
                     RESP2(Z-EIBRESP2)
           END-EXEC.

           IF Z-EIBRESP = DFHRESP(ENDFILE) THEN
              DISPLAY '*****'
              GO TO SRCH-DONE
           END-IF.

           IF Z-EIBRESP NOT = DFHRESP(NORMAL) THEN
              DISPLAY '***** READNEXT FILE ERROR!'
              DISPLAY 'RESP: ' Z-EIBRESP
              DISPLAY 'RESP2: ' Z-EIBRESP2
              IF Z-EIBRESP = DFHRESP(NOTFND) THEN
                  DISPLAY 'NOT FOUND!'
              END-IF
              EXEC CICS ABEND ABCODE('TTTT') END-EXEC
              EXEC CICS RETURN END-EXEC
           ELSE
              ADD 1 TO LINE-CNT
              DISPLAY LINE-CNT ' : *****'
              DISPLAY TEMP-SEG
              GO TO SRCH-LOOP
           END-IF.

       SRCH-DONE.
           EXEC CICS ENDBR FILE(FILE-NAME) END-EXEC.


      * Delay
           EXEC CICS DELAY FOR SECONDS(1) END-EXEC.
      * End
           DISPLAY 'TGFLIST End---------------'.
           EXEC CICS RETURN END-EXEC.

参考: コンパイル用JCLサンプル

コンパイル用JCLサンプル

コンパイル用JCLのテンプレートです(@ProgName@はソースのメンバー名に置き換え)。
CICS TS V5.6を使用している想定です。
データセット名等は適宜環境に合わせて変更する必要があります。

//TRANCBL  JOB MSGLEVEL=(1,1),CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//DFHYITVL PROC SUFFIX=1$,           Suffix for translator module
//       INDEX='CICSTS56.CICS',      Qualifier(s) for CICS libraries
//       PROGLIB='CICSTS56.CICS.SDFHLOAD', Name of o/p library
//       DSCTLIB='CICSTS56.CICS.SDFHCOB', Private macro/dsect
//       AD370HLQ='LANG.IGY.V6R1M0',   Qualifier(s) for AD/Cycle compiler
//       LE370HLQ='CEE',             Qualifier(s) for LE/370 libraries
//       OUTC=*,                     Class for print output
//       REG=0M,                     Region size for all steps
//       TRNPARM='COBOL3,SP,DBCS',
//       COBPARM='NODYNAM,OBJECT,RENT,APOST,MAP,XREF,TRUNC(BIN)',
//       LNKPARM='LIST,XREF,REUS=RENT',        Link edit parameters
//       STUB='DFHEILID',            Lked INC. for DFHELII
//       LIB='SDFHSAMP',             Library
//       WORK=SYSDA                  Unit for work datasets
//*
//*     This procedure generates a COBOL module.
//*
//*      This procedure contains 4 steps
//*      1.   Exec the COBOL translator
//*           (using the supplied suffix 1$)
//*      2.   Exec the COBOL compiler
//*      3.   Reblock &LIB(&STUB) for use by the linkedit step
//*      4.   Linkedit the output into dataset &PROGLIB
//*
//*      The following JCL should be used
//*      to execute this procedure
//*
//*      //APPLPROG EXEC DFHYITVL
//*      //TRN.SYSIN  DD *
//*         .
//*         . Application program
//*         .
//*      /*
//*      //LKED.SYSIN DD *
//*         NAME anyname(R)
//*      /*
//*
//*      Where   anyname   is the name of your application program.
//*      (Refer to the system definition guide for full details,
//*      including what to do if your program contains calls to
//*      the common programming interface.)
//*
//TRN    EXEC PGM=DFHECP&SUFFIX,
//            PARM='&TRNPARM',                                     @01C
//            REGION=&REG
//STEPLIB  DD DSN=&INDEX..SDFHLOAD,DISP=SHR
//SYSPRINT DD SYSOUT=&OUTC
//SYSPUNCH DD DSN=&&SYSCIN,
//            DISP=(,PASS),UNIT=&WORK,
//            DCB=BLKSIZE=400,
//            SPACE=(400,(400,100))
//*
//COB    EXEC PGM=IGYCRCTL,REGION=&REG,PARM='&COBPARM'
//STEPLIB  DD DSN=&AD370HLQ..SIGYCOMP,DISP=SHR
//SYSLIB   DD DSN=&DSCTLIB,DISP=SHR
//         DD DSN=&INDEX..SDFHCOB,DISP=SHR
//         DD DSN=&INDEX..SDFHMAC,DISP=SHR
//         DD DSN=&INDEX..SDFHSAMP,DISP=SHR
//*        DD DSN=CICSTS56.@DBDC.DSCTLIB,DISP=SHR
//SYSPRINT DD SYSOUT=&OUTC
//SYSIN    DD DSN=&&SYSCIN,DISP=(OLD,DELETE)
//SYSLIN   DD DSN=&&LOADSET,DISP=(MOD,PASS),
//            UNIT=&WORK,SPACE=(80,(250,100))
//SYSMDECK DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT1   DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT2   DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT3   DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT4   DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT5   DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT6   DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT7   DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT8   DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT9   DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT10  DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT11  DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT12  DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT13  DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT14  DD UNIT=&WORK,SPACE=(460,(350,100))
//SYSUT15  DD UNIT=&WORK,SPACE=(460,(350,100))
//*
//COPYLINK EXEC PGM=IEBGENER,COND=(7,LT,COB)
//SYSUT1   DD DSN=&INDEX..&LIB(&STUB),DISP=SHR
//SYSUT2   DD DSN=&&COPYLINK,DISP=(NEW,PASS),
//            DCB=(LRECL=80,BLKSIZE=400,RECFM=FB),
//            UNIT=&WORK,SPACE=(400,(20,20))
//SYSPRINT DD SYSOUT=&OUTC
//SYSIN    DD DUMMY
//*
//LKED   EXEC PGM=IEWL,REGION=&REG,
//            PARM='&LNKPARM',COND=(5,LT,COB)
//SYSLIB   DD DSN=&INDEX..SDFHLOAD,DISP=SHR
//         DD DSN=&LE370HLQ..SCEELKED,DISP=SHR
//SYSLMOD  DD DSN=&PROGLIB,DISP=SHR
//SYSUT1   DD UNIT=&WORK,DCB=BLKSIZE=1024,
//            SPACE=(1024,(200,20))
//SYSPRINT DD SYSOUT=&OUTC
//SYSLIN   DD DSN=&&COPYLINK,DISP=(OLD,DELETE)
//         DD DSN=&&LOADSET,DISP=(OLD,DELETE)
//         DD DDNAME=SYSIN
//*
//         PEND
//*********************************************************************
//* RUN INSTREAM-PROCEDURE                                            *
//*********************************************************************
//@COBOL   EXEC DFHYITVL
//TRN.SYSIN     DD DISP=SHR,DSN=CICSTS56.@DBDC.PGMSOR(@ProgName@)
//LKED.SYSLMOD  DD DISP=SHR,DSN=CICSTS56.@DBDC.USERLIB.PDSE
//LKED.SYSIN    DD *
   MODE AMODE(31),RMODE(ANY)
   NAME   @ProgName@(R)
/*

CICS資源定義

FILE定義

CEDA  View File( FILET    )                                               
 File           : FILET                                                   
 Group          : TAGGRP                                                  
 DEScription    :                                                         
VSAM PARAMETERS                                                           
 DSNAme         : DB2P.CT56B4A1.FILET                                     
 Password       :                    PASSWORD NOT SPECIFIED               
 RLsaccess      : No                 Yes | No                             
 LSRPOOLId      : 1                  1-8 | None                           
 LSRPOOLNum     : 001                1-255 | None                         
 READInteg      : Uncommitted        Uncommitted | Consistent | Repeatable
 DSNSharing     : Allreqs            Allreqs | Modifyreqs                 
 STRings        : 003                1-255                                
 Nsrgroup       :                                                         
REMOTE ATTRIBUTES                                                         
 REMOTESystem   :                                                         
 REMOTEName     :                                                         
REMOTE AND CFDATATABLE PARAMETERS           
...                              

PROGRAM定義

CEDA  View PROGram( TGFADD   )                                            
 PROGram        : TGFADD                                                  
 Group          : TAGGRP                                                  
 DEScription    :                                                         
 Language       :                    CObol | Assembler | Le370 | C | Pli  
 RELoad         : No                 No | Yes                             
 RESident       : No                 No | Yes                             
 USAge          : Normal             Normal | Transient                   
 USElpacopy     : No                 No | Yes                             
 Status         : Enabled            Enabled | Disabled                   
 RSl            : 00                 0-24 | Public                        
 CEdf           : Yes                Yes | No                             
 DAtalocation   : Any                Below | Any                          
 EXECKey        : User               User | Cics                          
 COncurrency    : Quasirent          Quasirent | Threadsafe | Required    
 Api            : Cicsapi            Cicsapi | Openapi                    
REMOTE ATTRIBUTES                                                         
 DYnamic        : No                 No | Yes                             

同様に、TAGFUPDT、TAGFDEL、TAGFREAD、TAGFLIST についてもプログラム定義を追加。

テスト実行

リフレッシュ直後のTopicの状態確認

[root@test12 ~/Kafka]# /opt/confluent-6.2.0/bin/kafka-avro-console-consumer --from-beginning --topic cdc_kafka_test01.filet01.sourcedb.vsam.test01.filet --bootstrap-server localhost:9092 --property print.key=true
{"RT_KEY":{"string":"000001"}}  {"RT_KEY":{"string":"000001"},"RT_ALPHA":{"string":"ThisIsROOT"},"RT_ALPHAKANA":{"string":"アイウエオカキクケコ"},"RT_MIXDBCS":{"string":"あいうえおアイウエオ全角漢文  "},"RT_MIXALL":{"string":"ABCDEFGHあいうabcdefgh全角漢アイウエオカキク"},"RT_GRAPHIC":{"string":"全角漢文字あいうえおアイウエオ"},"RT_DECIMAL":{"string":"1234567890"},"RT_PACKED":{"int":12345},"RT_BINHALF":{"int":1234},"RT_BINFULL":{"int":12345678},"RT_BINDBLE":{"long":123456789012},"RT_GRP01":{"string":"ThisIs1st!"},"RT_GRP02":{"string":"ThisIs2nd!"},"RT_GRP03":{"string":"ThisIs3rd!"}}
{"RT_KEY":{"string":"000002"}}  {"RT_KEY":{"string":"000002"},"RT_ALPHA":{"string":"11:11:54.3"},"RT_ALPHAKANA":{"string":"アイウエオカキクケコ"},"RT_MIXDBCS":{"string":"あいうえおアイウエオ全角漢文  "},"RT_MIXALL":{"string":"ABCDEFGHあいうabcdefgh全角漢アイウエオカキク"},"RT_GRAPHIC":{"string":"全角漢文字あいうえおアイウエオ"},"RT_DECIMAL":{"string":"1234567890"},"RT_PACKED":{"int":12345},"RT_BINHALF":{"int":1234},"RT_BINFULL":{"int":12345678},"RT_BINDBLE":{"long":123456789012},"RT_GRP01":{"string":"ThisIs1st!"},"RT_GRP02":{"string":"ThisIs2nd!"},"RT_GRP03":{"string":"ThisIs3rd!"}}
{"RT_KEY":{"string":"000003"}}  {"RT_KEY":{"string":"000003"},"RT_ALPHA":{"string":"ThisIsROOT"},"RT_ALPHAKANA":{"string":"アイウエオカキクケコ"},"RT_MIXDBCS":{"string":"あいうえおアイウエオ全角漢文  "},"RT_MIXALL":{"string":"ABCDEFGHあいうabcdefgh全角漢アイウエオカキク"},"RT_GRAPHIC":{"string":"全角漢文字あいうえおアイウエオ"},"RT_DECIMAL":{"string":"1234567890"},"RT_PACKED":{"int":12345},"RT_BINHALF":{"int":1234},"RT_BINFULL":{"int":12345678},"RT_BINDBLE":{"long":123456789012},"RT_GRP01":{"string":"ThisIs1st!"},"RT_GRP02":{"string":"ThisIs2nd!"},"RT_GRP03":{"string":"ThisIs3rd!"}}
{"RT_KEY":{"string":"000004"}}  {"RT_KEY":{"string":"000004"},"RT_ALPHA":{"string":"ThisIsROOT"},"RT_ALPHAKANA":{"string":"アイウエオカキクケコ"},"RT_MIXDBCS":{"string":"あいうえおアイウエオ全角漢文  "},"RT_MIXALL":{"string":"ABCDEFGHあいうabcdefgh全角漢アイウエオカキク"},"RT_GRAPHIC":{"string":"全角漢文字あいうえおアイウエオ"},"RT_DECIMAL":{"string":"1234567890"},"RT_PACKED":{"int":12345},"RT_BINHALF":{"int":1234},"RT_BINFULL":{"int":12345678},"RT_BINDBLE":{"long":123456789012},"RT_GRP01":{"string":"ThisIs1st!"},"RT_GRP02":{"string":"ThisIs2nd!"},"RT_GRP03":{"string":"ThisIs3rd!"}}

VSAM上に4つのレコードがある状態。ここからミラーリングを開始します。

レコード追加

TGFADDプログラムを動かしてKey:000005のレコードを追加してみます。

Topicに以下のメッセージが追加されました。

{"RT_KEY":{"string":"000005"}}  {"RT_KEY":{"string":"000005"},"RT_ALPHA":{"string":"ThisIsROOT"},"RT_ALPHAKANA":{"string":"アイウエオカキクケコ"},"RT_MIXDBCS":{"string":"あいうえおアイウエオ全角漢文  "},"RT_MIXALL":{"string":"ABCDEFGHあいうabcdefgh全角漢アイウエオカキク"},"RT_GRAPHIC":{"string":"全角漢文字あいうえおアイウエオ"},"RT_DECIMAL":{"string":"1234567890"},"RT_PACKED":{"int":12345},"RT_BINHALF":{"int":1234},"RT_BINFULL":{"int":12345678},"RT_BINDBLE":{"long":123456789012},"RT_GRP01":{"string":"ThisIs1st!"},"RT_GRP02":{"string":"ThisIs2nd!"},"RT_GRP03":{"string":"ThisIs3rd!"}}

レコード更新

TGFUPDTプログラムを動かしてKey:000005のレコードを更新してみます。

Topicに以下のメッセージが追加されました。

{"RT_KEY":{"string":"000005"}}  {"RT_KEY":{"string":"000005"},"RT_ALPHA":{"string":"16:15:20.9"},"RT_ALPHAKANA":{"string":"アイウエオカキクケコ"},"RT_MIXDBCS":{"string":"あいうえおアイウエオ㈱①Ⅰ鯵鰺"},"RT_MIXALL":{"string":"ABCDEFGHあいうabcdefgh全角漢アイウエオカキク"},"RT_GRAPHIC":{"string":"全角漢文字あいうえおアイウエオ"},"RT_DECIMAL":{"string":"1234567890"},"RT_PACKED":{"int":12345},"RT_BINHALF":{"int":1234},"RT_BINFULL":{"int":12345678},"RT_BINDBLE":{"long":123456789012},"RT_GRP01":{"string":"ThisIs1st!"},"RT_GRP02":{"string":"ThisIs2nd!"},"RT_GRP03":{"string":"ThisIs3rd!"}}

レコード削除

TGFDELプログラムを動かしてKey:000005のレコードを削除してみます。

Topicに以下のメッセージが追加されました。

{"RT_KEY":{"string":"000005"}}  null

補足

Kafka Consumerで結果を確認していますが、kafka-avro-console-consumerを実行しているロケールはja_JP.UTF-8を使用しています。すなわち、元々のデータはEBCDIC(1399)ですが、UTF-8に文字コード変換されていることが確認できています。
Graphicタイプ(DBCSのみ)のフィールドもきちんとコード変換できていますし、環境依存文字(㈱、①など)も変換できているようです。
その他、デフォルトでは、COBOL COPYBOOKの型と、Kafka上の型は以下の様にマッピングされていました。

COBOL COPYBOOK Avro
01 RT-SEG. -
02 RT-KEY PIC X(06). string
02 RT-ALPHA PIC X(10). string
02 RT-ALPHAKANA PIC X(10). string
02 RT-MIXDBCS PIC X(32). string
02 RT-MIXALL PIC X(40). string
02 RT-GRAPHIC PIC G(15) USAGE DISPLAY-1. string
02 RT-DECIMAL PIC 9(10). string
02 RT-PACKED PIC S9(05) COMP-3. int
02 RT-BINHALF PIC S9(04) COMP. int
02 RT-BINFULL PIC S9(08) COMP. int
02 RT-BINDBLE PIC S9(12) COMP. long
02 RT-GROUP. -
03 RT-GRP01 PIC X(10). string
03 RT-GRP02 PIC X(10). string
03 RT-GRP03 PIC X(10). string
02 FILLER PIC X(15). なし

レプリケーションのテスト2

テスト1で実行したシナリオを少し改修して試してみます。ここでは、CopyBookを元に生成されるVSAM表を一部カスタマイズしてみます。

使用するCopyBook

FILET2.cpy
        01 RT-SEG.
            02 RT-KEY       PIC  X(06) VALUE '000001'.
            02 RT-ALPHA     PIC  X(10) VALUE 'ThisIsROOT'.
            02 RT-ALPHAKANA PIC  X(10) VALUE 'アイウエオカキクケコ'.
            02 RT-MIXDBCS   PIC  X(32)
                     VALUE 'あいうえおアイウエオ全角漢文'.
            02 RT-MIXALL    PIC  X(40)
                    VALUE 'ABCDEFGHあいうabcdefgh全角漢アイウエオカキク'.
            02 RT-GRAPHIC   PIC  G(15) USAGE DISPLAY-1
                   VALUE G'全角漢文字あいうえおアイウエオ'.
            02 RT-DECIMAL   PIC  9(10) VALUE 1234567890.
            02 RT-PACKED    PIC S9(05) COMP-3 VALUE 12345.
            02 RT-BINHALF   PIC S9(04) COMP  VALUE 1234.
            02 RT-BINFULL   PIC S9(08) COMP  VALUE 12345678.
            02 RT-BINDBLE   PIC S9(12) COMP  VALUE 123456789012.
            02 RT-GROUP.
             03 RT-GRP01    PIC  X(10) VALUE 'ThisIs1st!'.
             03 RT-GRP02    PIC  X(10) VALUE 'ThisIs2nd!'.
             03 RT-GRP03    PIC  X(10) VALUE 'ThisIs3rd!'.
            02 RT-BIT8      PIC  X(01) VALUE X'F0'.       
            02 RT-BIT16     PIC  X(02) VALUE X'FFF0'.     
            02 RT-BIT32     PIC  X(04) VALUE X'FFFFFFF0'. 
            02 FILLER       PIC  X(08) VALUE SPACE. 

最後にバイナリのデータを保持する想定のフィールドを追加しました。型としてはPIC Xを使用していますが、ここにバイナリのデータ(コード変換対象外)のデータが含まれる想定です。
(上のCopyBookに指定してある固定の値をそのままファイルに書き込むイメージです。)

先の例だと、デフォルトでPIC Xは文字列(string)として扱われることになります。通常はこれで問題ありませんが、PIC Xのフィールドにバイナリ情報を格納して扱っているケースもあり得ますので、特定のフィールドを明示的にバイナリとして扱うよう変更してみます。
また、先の例では、PIC 9 (ゾーン10進)のフィールドも文字列として変換されていました。こちらも明示的に数値として扱うよう変更してみます。

※ここではテスト1と同じ手順でレプリケーションの設定を追加していきますが、テスト1と違うところだけ記載します。他の手順は同等です。

VSAM表のカスタマイズ

COBOLのCopyBookを取りこみ => VSAM表を作成 => DDL生成 => DDL適用 という流れでVSAM Remote Source上にVSAM表を反映させますが、生成されたDDLを用途に合わせてカスタマイズしてから適用します。

DDLのカスタマイズはマニュアルの以下の辺りを参考にします。
参考:Columns for VSAM

先にあげたCopyBookを元にClassic Data Architect上で生成させたDDLはこちらです。

create_FILET2.sql
--<ScriptOptions statementTerminator=";"/>

CREATE TABLE "TEST01"."FILET2" DBTYPE VSAM
	DS "DB2P.CT56B4A1.FILET2"
	(

	"RT_KEY" SOURCE DEFINITION
		DATAMAP OFFSET 0 LENGTH 6
		DATATYPE C
		USE AS CHAR(6),
	"RT_ALPHA" SOURCE DEFINITION
		DATAMAP OFFSET 6 LENGTH 10
		DATATYPE C
		USE AS CHAR(10),
	"RT_ALPHAKANA" SOURCE DEFINITION
		DATAMAP OFFSET 16 LENGTH 10
		DATATYPE C
		USE AS CHAR(10),
	"RT_MIXDBCS" SOURCE DEFINITION
		DATAMAP OFFSET 26 LENGTH 32
		DATATYPE C
		USE AS CHAR(32),
	"RT_MIXALL" SOURCE DEFINITION
		DATAMAP OFFSET 58 LENGTH 40
		DATATYPE C
		USE AS CHAR(40),
	"RT_GRAPHIC" SOURCE DEFINITION
		DATAMAP OFFSET 98 LENGTH 15
		DATATYPE C
		USE AS GRAPHIC(15),
	"RT_DECIMAL" SOURCE DEFINITION
		DATAMAP OFFSET 128 LENGTH 10
		DATATYPE UC
		USE AS CHAR(10),
	"RT_PACKED" SOURCE DEFINITION
		DATAMAP OFFSET 138 LENGTH 3
		DATATYPE P
		USE AS DECIMAL(5 , 0),
	"RT_BINHALF" SOURCE DEFINITION
		DATAMAP OFFSET 141 LENGTH 2
		DATATYPE H
		USE AS SMALLINT,
	"RT_BINFULL" SOURCE DEFINITION
		DATAMAP OFFSET 143 LENGTH 4
		DATATYPE F
		USE AS INTEGER,
	"RT_BINDBLE" SOURCE DEFINITION
		DATAMAP OFFSET 147 LENGTH 8
		DATATYPE D
		USE AS DECIMAL(12 , 0),
	"RT_GRP01" SOURCE DEFINITION
		DATAMAP OFFSET 155 LENGTH 10
		DATATYPE C
		USE AS CHAR(10),
	"RT_GRP02" SOURCE DEFINITION
		DATAMAP OFFSET 165 LENGTH 10
		DATATYPE C
		USE AS CHAR(10),
	"RT_GRP03" SOURCE DEFINITION
		DATAMAP OFFSET 175 LENGTH 10
		DATATYPE C
		USE AS CHAR(10),
	"RT_BIT8" SOURCE DEFINITION
		DATAMAP OFFSET 185 LENGTH 1
		DATATYPE C
		USE AS CHAR(1),
	"RT_BIT16" SOURCE DEFINITION
		DATAMAP OFFSET 186 LENGTH 2
		DATATYPE C
		USE AS CHAR(2),
	"RT_BIT32" SOURCE DEFINITION
		DATAMAP OFFSET 188 LENGTH 4
		DATATYPE C
		USE AS CHAR(4));

ALTER TABLE "TEST01"."FILET2" DATA CAPTURE CHANGES;

これを以下のように変更します。(変更箇所のみ抜粋)

create_FILET2.sql
...
	"RT_DECIMAL" SOURCE DEFINITION
		DATAMAP OFFSET 128 LENGTH 10
		DATATYPE UC
		USE AS DECIMAL(10 , 0),
...
	"RT_BIT8" SOURCE DEFINITION
		DATAMAP OFFSET 185 LENGTH 1
		DATATYPE B
		USE AS BINARY(1),
	"RT_BIT16" SOURCE DEFINITION
		DATAMAP OFFSET 186 LENGTH 2
		DATATYPE B
		USE AS BINARY(2),
	"RT_BIT32" SOURCE DEFINITION
		DATAMAP OFFSET 188 LENGTH 4
		DATATYPE B
		USE AS BINARY(4));
...

上のDDLを適用すると変更した箇所とは関係ない所で以下のWarningが出ました。とりあえず無視してよさそうなので放置。

SQLState=S1000 列 RT_BINDBLE について LENGTH 8 は、DECIMAL の USE AS SQL データ・タイプに基づいて無視されます。 .

こんな感じでVSAM表が作成されました。
image.png

テスト実行

Avro Consumerを使用してVSAMにデータを投入してKafkaのTopicを確認してみます。

{"RT_KEY":{"string":"000001"}}  {"RT_KEY":{"string":"000001"},"RT_ALPHA":{"string":"ThisIsROOT"},"RT_ALPHAKANA":{"string":"アイウエオカキクケコ"},"RT_MIXDBCS":{"string":"あいうえおアイウエオ全角漢文  "},"RT_MIXALL":{"string":"ABCDEFGHあいうabcdefgh全角漢アイウエオカキク"},"RT_GRAPHIC":{"string":"全角漢文字あいうえおアイウエオ"},"RT_DECIMAL":{"long":1234567890},"RT_PACKED":{"int":12345},"RT_BINHALF":{"int":1234},"RT_BINFULL":{"int":12345678},"RT_BINDBLE":{"long":123456789012},"RT_GRP01":{"string":"ThisIs1st!"},"RT_GRP02":{"string":"ThisIs2nd!"},"RT_GRP03":{"string":"ThisIs3rd!"},"RT_BIT8":{"bytes":"d"},"RT_BIT16":{"bytes":"yd"},"RT_BIT32":{"bytes":"yyyd"}}

RT_DECIMALは意図した通り数値型(long)になっています。
一方RT_BIT8, RT_BIT16, RT_BIT32は文字列として表示されてしまっています。

スキーマを確認してみます。

{
  "type": "record",
  "name": "FILET2",
  "namespace": "value.SOURCEDB.VSAM.TEST01",
  "fields": [
...
    {
      "name": "RT_DECIMAL",
      "type": [
        {
          "type": "long",
          "logicalType": "DECIMAL",
          "dbColumnName": "RT_DECIMAL",
          "precision": 10,
          "scale": 0
        },
        "null"
      ],
      "doc": "",
      "default": 0
    },
...
    {
      "name": "RT_BIT8",
      "type": [
        {
          "type": "bytes",
          "logicalType": "BINARY",
          "dbColumnName": "RT_BIT8",
          "length": 1
        },
        "null"
      ],
      "doc": "",
      "default": ""
    },
    {
      "name": "RT_BIT16",
      "type": [
        {
          "type": "bytes",
          "logicalType": "BINARY",
          "dbColumnName": "RT_BIT16",
          "length": 2
        },
        "null"
      ],
      "doc": "",
      "default": ""
    },
    {
      "name": "RT_BIT32",
      "type": [
        {
          "type": "bytes",
          "logicalType": "BINARY",
          "dbColumnName": "RT_BIT32",
          "length": 4
        },
        "null"
      ],
      "doc": "",
      "default": ""
    }
  ]
}

スキーマ上、RT_BITxxのフィールドは"type":"bytes"になっているので、恐らく確認に使っているAvroComsumerの仕様で文字列として表示されているのではないかと思われます。

kafka-console-consumerを使用して先頭のメッセージだけ抜き出してHexダンプを出力してみます。

[root@test12 ~/Kafka]# /opt/confluent-6.2.0/bin/kafka-console-consumer --from-beginning --topic cdc_kafka_test01.filet02.sourcedb.vsam.test01.filet2 --max-messages 1 --bootstrap-server localhost:9092 | xxd > temp.txt
Processed a total of 1 messages

[root@test12 ~/Kafka]# cat temp.txt
00000000: 0000 0000 0200 0c30 3030 3030 3100 1454  .......000001..T
00000010: 6869 7349 7352 4f4f 5400 3cef bdb1 efbd  hisIsROOT.<.....
00000020: b2ef bdb3 efbd b4ef bdb5 efbd b6ef bdb7  ................
00000030: efbd b8ef bdb9 efbd ba00 58e3 8182 e381  ..........X.....
00000040: 84e3 8186 e381 88e3 818a e382 a2e3 82a4  ................
00000050: e382 a6e3 82a8 e382 aae5 85a8 e8a7 92e6  ................
00000060: bca2 e696 8720 2000 7441 4243 4445 4647  .....  .tABCDEFG
00000070: 48e3 8182 e381 84e3 8186 6162 6364 6566  H.........abcdef
00000080: 6768 e585 a8e8 a792 e6bc a2ef bdb1 efbd  gh..............
00000090: b2ef bdb3 efbd b4ef bdb5 efbd b6ef bdb7  ................
000000a0: efbd b800 5ae5 85a8 e8a7 92e6 bca2 e696  ....Z...........
000000b0: 87e5 ad97 e381 82e3 8184 e381 86e3 8188  ................
000000c0: e381 8ae3 82a2 e382 a4e3 82a6 e382 a8e3  ................
000000d0: 82aa 00a4 8bb0 9909 00f2 c001 00a4 1300  ................
000000e0: 9c85 e30b 00a8 e8c8 e997 0700 1454 6869  .............Thi
000000f0: 7349 7331 7374 2100 1454 6869 7349 7332  sIs1st!..ThisIs2
00000100: 6e64 2100 1454 6869 7349 7333 7264 2100  nd!..ThisIs3rd!.
00000110: 02f0 0004 fff0 0008 ffff fff0 0a         .............

末尾にf0 fff0 fffffff0 というデータがあるのでバイナリデータとしてコード変換されずにデータが送信されていることが確認できました。

まとめ

  • Kafkaをターゲットとして連携する場合、更新情報が1メッセージとしてTopic上に送付されます。
  • Kafka Topic上のメッセージはKey + Valueで構成されますが、Key部分には更新レコードのキーとなるフィールド、Value部分には更新レコード全体が含まれます。
  • メッセージ単体からはInsert, Updateの区別はつきません。Updateの場合、更新後のレコード情報がValueに含まれるだけなのでどのフィールドに変更が入ったかの判別もできません。
  • Deleteの場合、DeleteされたレコードのKey情報のみが転送され、Value部分はnullとなっています。
  • MixedField, DBCSのみのフィールド、数値フィールドなど上のテストで挙げた型は意図した通りに変換できているようです(Mixed FieldとDBCS Fieldそれぞれに対してCCSIDを指定するパラメータがあるので注意!)。
    バイナリや一部の数値フィールドはCopyBookから生成されるDDLを手動でカスタマイズしてVSAM表を作成する必要があるので注意が必要です。
  • 更新情報は、更新された各レコード単位で独立したメッセージとしてKafkaに送られます。ソース側で複数レコードの更新を1UOWで更新した場合などでも、Kafka側では別々のイベントとして捉えられてしまいます。そのため、Kafkaから先のターゲットへの反映タイミングによっては整合性の取れていない状態となり得ます(Partitionを1つにしても、同一表の異なるレコードを1UOWで更新した場合は反映タイミングによっては不整合状態が生じうる)。トランザクション性を保証する必要がある場合は、"Kafka transactionally consistent consumer"の機能を使用して、1UOWとして扱われるメッセージの塊をKafka Consumer側でハンドリングする必要があります。

参考:
Kafka transactionally consistent consumer
A Solution for Leveraging Kafka to Provide End-to-End ACID Transactions

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?