排序实用工具 - AWS 大型机现代化

AWS 大型机现代化服务(托管运行时环境体验)不再向新客户开放。有关类似于 AWS 大型机现代化服务(托管运行时环境体验)的功能,请浏览 AWS 大型机现代化服务(自我管理体验)。现有客户可以继续正常使用该服务。有关更多信息,请参阅AWS 大型机现代化可用性变更

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

排序实用工具

排序实用程序依赖于其引用对实用程序具有特殊含义的数据集。因此,现代化方面的所有排序实用程序在groovy脚本中都具有相同的调用模式:

mpr.withFileConfigurations(<FILE CONFIGURATIONS DETAILS>...) .withParameters(params) .runProgram("<SORT UTILITY ALIAS>")

其中mprMainProgramRunner实例(请参阅本页中的 “调用程序的脚本” 部分)。以下各节给出了排序实用程序的别名。

JCL 脚本中的DD(数据集定义)条目被现代化为文件配置详细信息中的条目,这些条目充当该方法的mpr.withFileConfigurations()参数。有关该概念的插图,请参阅下面的示例。

SORT/SYNCSORT/ICEMAN

用途

该程序根据提供的标准模拟各种大型机排序实用程序,这些实用程序用于数据集中的sort/merge/copy数据。可以使用以下程序别名(并与相应的旧版排序实用程序名称相匹配):

  • SORT

  • SYNCSORT

  • ICEMAN

此处未提供有关控制卡中的 SORT/MERGE 指令和传统排序实用程序功能的详细信息,但应从现有的相关遗留平台文档中获取。

签名

该程序不接受任何参数,而是依赖特定的数据集引用:

  • SYSIN数据集(又名 “控制卡”)保存控制语句 sort/merge

  • 可选SYMNAMES数据集在 SYSIN 内容中保存变量替换指令

  • 可选的SORTXDUPSORTXSUM数据集可用于存储重复的记录

  • 以要处理的记录为前缀SORTINSORTDBIN保存要处理的数据集(输入)

  • SORTOUT数据集保存程序的结果(输出)

  • 在某些旧版作业脚本中找到的 SORT WORK 数据集的SORTWK定义会被忽略(并且不在现代化调用中表示);在现代环境中,排序工作数据集将始终动态分配

  • DD 以SORTJN(前缀)开头的两个数据集包含连接键指令(用于在排序过程中连接数据集)所涉及的记录

例如,考虑以下联接键指令:

JOINKEYS FILE=F1,FIELDS=(13,5,A) JOINKEYS FILE=F2,FIELDS=(24,5,A)

在这里,连接键的长度为 5,起始于:

  • 数据集中记录的位置 13SORTJNF1SORTJN前缀和文件的串联)F1

  • 数据集中记录的位置 24SORTJNF2SORTJN前缀和文件的串联)F2

检查/错误处理

  • 如果输入文件 (SORTIN) 有SHR处置但无法找到,则会记录一条错误消息,程序返回码设置为 1,程序运行暂停(不会进行排序,也不会生成任何输出)

对于以下情况,将抛出RuntimeException保留专用消息:

  • 如果程序调用需要连接到数据库(使用SORTDBIN数据集时,不是SORTIN)但找不到有效的数据源

  • 如果输出文件 (SORTOUT) 定义不正确

  • 如果在控制卡中找到的命令无法理解或不受支持

  • 如果不完全是,则为一个SORT JOINKEYS案例提供了两个输入文件

示例用法

合并示例

以下是来自作业脚本ICEMAN片段的调用示例:

控制卡是内联的,命令用于合并输入文件中的字段(参见SYSIN条目)

//* //PASOSO03 EXEC PGM=ICEMAN,REGION=0M //SORTIN01 DD DSN=input(input809a.data),DISP=SHR,LRECL=10 //SORTIN02 DD DSN=input(input809b.data),DISP=SHR,LRECL=10 //SORTOUT DD DSN=output(out809.txt),DISP=(,PASS),LRECL=10 //SORTWK01 DD SPACE=(281,(156300,156300),RLSE),AVGREC=U //SORTWK02 DD SPACE=(281,(156300,156300),RLSE),AVGREC=U //SYSIN DD * MERGE FIELDS=(1,6,PD,A,7,2,CH,A) END /*

还有匹配的现代化 groovy 脚本片段——请注意,如前所述,在现代化过程中不会考虑这些SORTWK条目,而且内联控制卡与旧版控制卡内容完全匹配。

// STEP PASOSO03 - PGM - ICEMAN*************************************************** def stepPASOSO03(Object shell, Map params, Map programResults){ shell.with { if (checkValidProgramResults(programResults)) { return execStep("PASOSO03", "ICEMAN", programResults, { mpr .withFileConfigurations(new FileConfigurationUtils() .withJobContext(jobContext) .fileSystem("SORTIN01") .path("input(input809a.data)").recordSize(10) .disposition("SHR") .build() .fileSystem("SORTIN02") .path("input(input809b.data)").recordSize(10) .disposition("SHR") .build() .fileSystem("SORTOUT") .path("output(out809.txt)").recordSize(10) .normalTermination("PASS") .build() .fileSystem("SYSIN") .stream( """ MERGE FIELDS=(1,6,PD,A,7,2,CH,A) END """, getEncoding()) .build() .getFileConfigurations()) .withParameters(params) .runProgram("ICEMAN") }) } } }

简单排序示例

一个带有内联控制卡的简单传统排序步骤(作业脚本片段),从 carddemo 示例应用程序中获取:

//********************************************************************* //* CREATE COPY OF TRANSACT FILE WITH CARD NUMBER AND TRAN ID AS KEY //********************************************************************* //STEP010 EXEC PGM=SORT //SORTIN DD DISP=SHR,DSN=AWS.M2.CARDDEMO.TRANSACT.VSAM.KSDS //SYSPRINT DD SYSOUT=* //SYSOUT DD SYSOUT=* //SORTOUT DD DSN=AWS.M2.CARDDEMO.TRXFL.SEQ, // DISP=(NEW,CATLG,DELETE),UNIT=SYSDA, // DCB=(LRECL=350,BLKSIZE=3500,RECFM=FB), // SPACE=(CYL,(1,1),RLSE) //SYSIN DD * SORT FIELDS=(263,16,CH,A,1,16,CH,A) OUTREC FIELDS=(1:263,16,17:1,262,279:279,50) /*

以及匹配的现代化 groovy 脚本片段:

// STEP STEP010 - PGM - SORT****************************************************** def stepSTEP010(Object shell, Map params, Map programResults){ shell.with { if (checkValidProgramResults(programResults)) { return execStep("STEP010", "SORT", programResults, { mpr .withFileConfigurations(new FileConfigurationUtils() .withJobContext(jobContext) .bluesam("SORTIN") .dataset("AWS.M2.CARDDEMO.TRANSACT.VSAM.KSDS") .disposition("SHR") .build() .systemOut("SYSPRINT") .output("*") .build() .systemOut("SYSOUT") .output("*") .build() .fileSystem("SORTOUT") .path("AWS.M2.CARDDEMO.TRXFL.SEQ").recordSize(350) .disposition("NEW") .normalTermination("CATLG") .abnormalTermination("DELETE") .build() .fileSystem("SYSIN") .stream( """ SORT FIELDS=(263,16,CH,A,1,16,CH,A) OUTREC FIELDS=(1:263,16,17:1,262,279:279,50)""", getEncoding()) .build() .getFileConfigurations()) .withParameters(params) .runProgram("SORT") }) } } }

请注意,内联控制卡按 “原样” 使用,未对旧版控制卡内容进行任何修改。

ICETOOL

用途

ICETOOL 实用程序用于在单个作业步骤中对数据集执行多项操作(数据操作、排序和分析)。

支持以下核心运算符:

  • COPY-将数据从输入文件复制到输出文件

  • SORT-使用指定的排序卡/标准对数据进行排序

  • SELECT-根据条件筛选和选择特定记录

  • SPLICE-来自多个来源 Merges/joins 的数据

  • COUNT-计算符合指定标准的记录

  • OCCUR-分析数据中的出现模式

对于SPLICE操作员,该实用程序将使用基于数据分块策略的多线程方法来确保优化的性能。

有关运算符的详细信息应从相应的旧平台文档中获取。

签名

ICETOOL实用程序不采用任何参数,但依赖于特定的数据集:

  • TOOLIN数据集包含要由实用程序处理的控制语句

  • TOOLMSG而且现代化ICETOOL实用程序暂时不使用DFSMSG数据集(已忽略)

  • IN是输入数据集(要处理的记录)的前缀

  • OUT是输出数据集(处理产生的记录)的前缀

  • 控制卡中的控制语句可能会引用其他数据集

检查/错误处理

对于以下情况,RuntimeException将抛出带有相关消息的 a:

  • 如果不支持其中一个控制语句中使用的运算符

  • 对于任何运算符,如果提供了不支持的指令

示例用法

ICETOOL 排序示例

以下是使用 ICETOOL 进行排序的传统 jcl 示例:

  • 每个 SORT 运算符控制语句都使用专用的控制卡,其引用通过 USING 关键字指定

  • 所有控制卡都是在定义之后定义的,并且是内联的(参见SEL1CNTL下面的*CNTL条目)TOOLIN

//SAMPLO52 EXEC PGM=ICETOOL,REGION=1024K //TOOLMSG DD SYSOUT=* //DFSMSG DD SYSOUT=* //IN1 DD DSN=input(input846a.data),DISP=SHR // DCB=(RECFM=F,LRECL=8) //IN2 DD DSN=input(input846b.data),DISP=SHR // DCB=(RECFM=F,LRECL=8) //OUT1 DD DSN=output(out846a.txt),DISP=(,CATLG) // DCB=(RECFM=F,LRECL=8) //OUT2 DD DSN=output(out846b.txt),DISP=(,CATLG) // DCB=(RECFM=V) //OUT3 DD DSN=output(out846c.txt),DISP=(,CATLG) // DCB=(RECFM=V) //TOOLIN DD * SORT FROM(IN1) TO(OUT1) USING(SEL1) SORT FROM(IN2) TO(OUT1) USING(SEL2) SORT FROM(IN1) TO(OUT2) USING(SEL3) SORT FROM(IN2) TO(OUT2) USING(SEL4) SORT FROM(IN1) TO(OUT3) USING(SEL5) SORT FROM(IN2) TO(OUT3) USING(SEL6) /* //SEL1CNTL DD * OPTION COPY OUTFIL BUILD=(1,8,JFY=(SHIFT=LEFT,TRAIL=C'*')) //* //SEL2CNTL DD * OPTION COPY,SKIPREC=1 OUTFIL BUILD=(1,8,JFY=(SHIFT=LEFT,TRAIL=C'*')) //* //SEL3CNTL DD * OPTION COPY OUTFIL BUILD=(1,8,JFY=(SHIFT=LEFT,TRAIL=C'*')), FTOV,VLTRIM=C' ' //* //SEL4CNTL DD * OPTION COPY,SKIPREC=1 OUTFIL BUILD=(1,8,JFY=(SHIFT=LEFT,TRAIL=C'*')), FTOV,VLTRIM=C' ' //* //SEL5CNTL DD * OPTION COPY OUTFIL BUILD=(1,8,JFY=(SHIFT=LEFT,TRAIL=C'*')), FTOV,VLTRIM=C' ' //* //SEL6CNTL DD * OPTION COPY,SKIPREC=1 OUTFIL BUILD=(1,7,JFY=(SHIFT=LEFT,TRAIL=C'*')), FTOV,VLTRIM=C' ' //*

现代化后,匹配的 groovy 脚本片段如下所示:

// STEP SAMPLO52 - PGM - ICETOOL************************************************** def stepSAMPLO52(Object shell, Map params, Map programResults){ shell.with { if (checkValidProgramResults(programResults)) { return execStep("SAMPLO52", "ICETOOL", programResults, { mpr .withFileConfigurations(new FileConfigurationUtils() .withJobContext(jobContext) .systemOut("TOOLMSG") .output("*") .build() .systemOut("DFSMSG") .output("*") .build() .fileSystem("IN1") .path("input(input846a.data)").recordSize(8) .disposition("SHR") .build() .fileSystem("IN2") .path("input(input846b.data)").recordSize(8) .disposition("SHR") .build() .fileSystem("OUT1") .path("output(out846a.txt)").recordSize(8) .normalTermination("CATLG") .build() .fileSystem("OUT2") .path("output(out846b.txt)").rdw(true) .normalTermination("CATLG") .build() .fileSystem("OUT3") .path("output(out846c.txt)").rdw(true) .normalTermination("CATLG") .build() .fileSystem("TOOLIN") .stream( """ SORT FROM(IN1) TO(OUT1) USING(SEL1) SORT FROM(IN2) TO(OUT1) USING(SEL2) SORT FROM(IN1) TO(OUT2) USING(SEL3) SORT FROM(IN2) TO(OUT2) USING(SEL4) SORT FROM(IN1) TO(OUT3) USING(SEL5) SORT FROM(IN2) TO(OUT3) USING(SEL6) """, getEncoding()) .build() .fileSystem("SEL1CNTL") .stream( """ OPTION COPY OUTFIL BUILD=(1,8,JFY=(SHIFT=LEFT,TRAIL=C'*')) """, getEncoding()) .build() .fileSystem("SEL2CNTL") .stream( """ OPTION COPY,SKIPREC=1 OUTFIL BUILD=(1,8,JFY=(SHIFT=LEFT,TRAIL=C'*'))""", getEncoding()) .build() .fileSystem("SEL3CNTL") .stream( """ OPTION COPY OUTFIL BUILD=(1,8,JFY=(SHIFT=LEFT,TRAIL=C'*')), FTOV,VLTRIM=C' '""", getEncoding()) .build() .fileSystem("SEL4CNTL") .stream( """ OPTION COPY,SKIPREC=1 OUTFIL BUILD=(1,8,JFY=(SHIFT=LEFT,TRAIL=C'*')), FTOV,VLTRIM=C' '""", getEncoding()) .build() .fileSystem("SEL5CNTL") .stream( """ OPTION COPY OUTFIL BUILD=(1,8,JFY=(SHIFT=LEFT,TRAIL=C'*')), FTOV,VLTRIM=C' '""", getEncoding()) .build() .fileSystem("SEL6CNTL") .stream( """ OPTION COPY,SKIPREC=1 OUTFIL BUILD=(1,7,JFY=(SHIFT=LEFT,TRAIL=C'*')), FTOV,VLTRIM=C' '""", getEncoding()) .build() .getFileConfigurations()) .withParameters(params) .runProgram("ICETOOL") }) } } }

备注:

  • 内联控制卡 “按原样” 使用;从旧控制卡中没有任何转换

  • TOOLMSGDFSMSG在现代化版本中定义,但在运行时将被忽略

  • 在旧版本和现代版本中,控制卡都使用CNTL后缀定义,但在数据集的指令中引用时不带后缀:例如SORT FROM(IN1) TO(OUT1) USING(SEL1),在中,USING(SEL1)是指TOOLIN数据集定义 SEL1CNTL

ICETOOL 复制样本

这是另一个使用 COPY 运算符的 ICETOOL 示例。在 TOOLIN jcl 脚本片段中已内联:

//SAMPLO51 EXEC PGM=ICETOOL,REGION=1024K //TOOLMSG DD SYSOUT=* //DFSMSG DD SYSOUT=* //IN1 DD DSN=input(input831.data),DISP=SHR // DCB=(RECFM=F,LRECL=12) //OUT1 DD DSN=output(out831a.txt),DISP=OLD // DCB=(RECFM=F,LRECL=12) //OUT2 DD DSN=output(out831b.txt),DISP=OLD // DCB=(RECFM=F,LRECL=12) //TOOLIN DD * COPY FROM(IN1) TO(OUT1,OUT2) USING(SEL1) /* //SEL1CNTL DD * OPTION COPY OUTFIL INCLUDE=(7,2,CH,EQ,C'10') //*

以下是匹配的现代化 groovy 脚本片段:

// STEP SAMPLO51 - PGM - ICETOOL************************************************** def stepSAMPLO51(Object shell, Map params, Map programResults){ shell.with { if (checkValidProgramResults(programResults)) { return execStep("SAMPLO51", "ICETOOL", programResults, { mpr .withFileConfigurations(new FileConfigurationUtils() .withJobContext(jobContext) .systemOut("TOOLMSG") .output("*") .build() .systemOut("DFSMSG") .output("*") .build() .fileSystem("IN1") .path("input(input831.data)").recordSize(12) .disposition("SHR") .build() .fileSystem("OUT1") .path("output(out831a.txt)").recordSize(12) .disposition("OLD") .build() .fileSystem("OUT2") .path("output(out831b.txt)").recordSize(12) .disposition("OLD") .build() .fileSystem("TOOLIN") .stream( """ COPY FROM(IN1) TO(OUT1,OUT2) USING(SEL1) COPY FROM(IN1) TO(OUT3,OUT4) COPY FROM(IN1) TO(OUT4) COPY FROM(IN1) TO(OUT5,OUT6) """, getEncoding()) .build() .fileSystem("SEL1CNTL") .stream( """ OPTION COPY OUTFIL INCLUDE=(7,2,CH,EQ,C'10')""", getEncoding()) .build() .getFileConfigurations()) .withParameters(params) .runProgram("ICETOOL") }) } } }

MFSORT

用途

该实用程序旨在模仿 Micro Focus 环境中名为 MFSORT 的排序实用程序的行为(它通常从命令行或旧版环境中的脚本中调用)。

在内部,该程序将实际的排序操作委托给SORT/SYNCSORT/ICEMAN实用程序。

签名

仅支持以下传统语法:mfsort take <control card>

不支持直接指令调用。mfsort <instructions>

它不接受任何参数;take 指令使用引用为的数据集进行模拟TAKE,该数据集包含 MFSORT 要操作的命令。

检查/错误处理

  • 如果TAKE数据集缺失或无效,则RuntimeException会抛出

  • 考虑到从 MFSORT 到 SORT 的授权,这里也检查/错误处理适用

示例用法

以下命令调用显示了 MFSORT 的用法示例:

mfsort take TESTSRT1.CTL

以下是匹配的现代化改编版 groovy 脚本片段:

mpr.withFileConfigurations(new FileConfigurationUtils() .fileSystem("TAKE") .path("input(TESTSRT1.CTL)") .build() .getFileConfigurations()) .withArguments("input") // relative path for use and give files .runProgram("MFSORT");