让系统来做!
您是否厌倦了从系统中手动删除不需要的日记帐接收者的麻烦?
没有时间编写程序搜索您的库并确定不再需要恢复的日记帐接收者并删除它们吗? 没有高可用性业务合作伙伴来为您管理日记帐接收者? 让系统在删除接收器之前自动保留一定天数的已保存接收器会不会很好? IBM i具有帮助您自动管理日记帐接收器的功能,从而减少了DASD的消耗并缩短了备份系统所需的时间。
在本文中,我们将研究一种方法,该方法可通过将CHGJRN或CRTJRN命令上的Delete Receivers选项与QIBM_QJO_DLT_JRNRCV注册的退出点结合使用来自动删除不需要的日记帐收件人。 提供了一个样例ILE C程序来说明使用此出口点的一种方法,该方法可以控制应保存多少天的已保存接收器,然后再删除它们。
有关帮助您确定系统管理的日记管理是否适合您的更多信息,请参阅《IBM®Redbooks® 力争在iSeries的DB2通用数据库上实现最佳日记性能》 ,特别是第87至89页。
准备日记帐接收器以自动删除
为了使系统自动更改和删除日记帐收件人,应将“更改日记帐”(CHGJRN)命令上的“ 管理收件人”和“ 删除收件人”选项分别设置为* SYSTEM和* YES,如图1所示。这允许系统管理新日记帐接收者的附件和不必要的接收者的删除。 除了在CHGJRN命令上指定这两个选项外,建议您指定日记消息队列以接收与该日记关联的任何消息。 这样会将与删除日记帐接收者有关的消息排除在QSYSOPR消息队列之外,并将它们放在方便的位置。
图1.更改日记帐(CHGJRN)选项
考虑在CHGJRN命令上进行自定义的另一个选项是“删除接收器延迟时间”。 默认值为10分钟,这意味着系统将继续尝试每10分钟删除一次日记帐接收者,并在每次无法删除时发出一条消息。 这会在日记的消息队列中产生大量不需要的消息。 例如,在清单1所示的示例退出程序中,我们编写了该程序以禁止删除日记帐接收者,直到它被保存5天。 为了避免在该时间间隔内每个日记帐接收者用数百条消息填充消息队列,表明该接收者不符合删除条件,我们将延迟时间增加到1440分钟或每天尝试一次。 您可以将此延迟时间设置为1分钟至1440分钟之间的任意值。
图2.删除接收器延迟时间选项(CHGJRN)
如果要创建需要系统来管理日记帐接收者删除的新日记帐,则可以在“创建日记帐”(CRTJRN)命令中找到这些相同的选项。 有关这些命令的信息,请参阅IBM知识中心,包括更改这些选项的可能限制。
编写退出程序
已注册的出口点(QIBM_QJO_DLT_JRNRCV)和出口点格式(DRCV0100)在IBM Knowledge Center中进行了记录。 请参阅主题“ 删除日记帐接收器退出程序”
我们提供了清单1中的程序作为示例,以说明一种使用出口点程序确定日记帐接收者是否符合删除条件的方法。 在删除日记帐接收器之前,系统会调用在此出口点上注册的所有用户出口程序,以指示是否应继续进行删除。 当用户在“删除日记帐接收器”(DLTJRNRCV)命令的DLTOPT参数上指定了* IGNEXITPGM选项时,这是一个例外。
清单1中的示例出口程序创建了QIBM_QJO_DLT_JRNRCV出口点,QjoRetrieveJournalInformation应用程序编程接口(API)以及对CEELOCT的调用的输入和输出参数所需的结构。 接下来,它将出口点输入参数复制到一个结构中,并从输入中提取日记帐接收者名称和库,并构造QJoRetrieveJournalInformation API调用中所需的合格日记帐接收者名称。 该API用于获取保存日记帐收件人的日期。 调用CEELOCT会产生本地系统日期。 我们对API返回的格里高利日期很感兴趣,我们对其进行了一些微调以使其与日记帐接收者保存日期的格式相同。 将日期转换为整数后,程序将从当前日期中减去保存的日期,然后应用标准来确定是否允许进行删除。 为此示例程序选择的两个条件是:接收者必须已经保存,保存日期和当前日期之间的差必须大于5(即,恒定的numdays的值)。否则,程序告诉系统认为接收者不符合删除条件。
清单1.删除日记帐接收器退出程序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <recio.h>
#include <qjournal.h>
#include <leawi.h>
/* Begin main function */
main(int argc, char *argv[])
{
char *temp_data;
struct Qjo_RRCV0100 *rcv_info;
long int rcv_info_length = 512;
char qual_rcv_name[20];
char format_name[8];
typedef struct{
long int exitpt_len;
char exitpt_name[20];
char exitpt_fmt[8];
char jrnrcv_name[10];
char jrnrcv_lib[10];
char jrn_name[10];
char jrn_lib[10];
char Call_Sys_Job[1];
char Call_IPL[1];
char Proc_End[1];
char jrn_type[1];
char rmtjrn_type[1];
char Save_Status[1];
char Partial_Status[1];
char detach_time[13];
} Qjo_Dlt_JrnRcv_Info_DRCV0100_t;
typedef _Packed struct Qjo_Dlt_JrnRcv_Status{
long int Statusinfo_Length;
char Dlt_Status[1];
} Qjo_Dlt_JrnRcv_Status_t;
Qjo_Dlt_JrnRcv_Info_DRCV0100_t input;
Qjo_Dlt_JrnRcv_Status_t output;
_INT4 lilian; /* Required parm not used in this program */
_FLOAT8 seconds; /* Required parm not used in this program */
_CHAR17 gregorian;
char sv_dt_tm[13];
char savdat[9];
char curdat[9];
int savdat_int;
int curdat_int;
int result;
const int numdays = 5; /*Number of days of receivers to keep*/
/* copy input parm into structure */
memcpy(&input, (Qjo_Dlt_JrnRcv_Info_DRCV0100_t *)argv[1],
sizeof(Qjo_Dlt_JrnRcv_Info_DRCV0100_t));
/* construct qualified journal receiver name from input */
memcpy(qual_rcv_name, input.jrnrcv_name,
sizeof(input.jrnrcv_name));
memcpy(&qual_rcv_name[10], input.jrnrcv_lib,
sizeof(input.jrnrcv_lib));
/* get space for output */
temp_data = (char *)calloc(1, sizeof(rcv_info_length));
/* Prepare the input parameters for the call to
Qjo_JrnReceiverInformation */
rcv_info = (struct Qjo_RRCV0100 *)temp_data;
/* Call the API */
QjoRtvJrnReceiverInformation(
rcv_info,
&rcv_info_length,
qual_rcv_name,
"RRCV0100",
NULL);
/* Get local date */
CEELOCT( &lilian, &seconds, gregorian, NULL );
/* Format the date data for the compare */
memcpy(&sv_dt_tm,rcv_info->Saved_Date_Time,sizeof(sv_dt_tm));
memcpy(savdat, &sv_dt_tm[1], sizeof(savdat));
savdat[8] = '\0';
memcpy(curdat, &gregorian[2], sizeof(curdat));
curdat[8] = '\0';
savdat_int = atoi(savdat);
curdat_int = atoi(curdat);
result = curdat_int - savdat_int;
/* Apply criteria for deletion of receiver. Receiver has to
have been saved at least numdays ago */
if (input.Save_Status[0] == '1' && result > numdays){
output.Statusinfo_Length =5;
strncpy(output.Dlt_Status,"1",1);
memcpy(argv[2], (Qjo_Dlt_JrnRcv_Status_t *)&output, 5);
}
else {
output.Statusinfo_Length =5;
strncpy(output.Dlt_Status, "0",1);
memcpy(argv[2], (Qjo_Dlt_JrnRcv_Status_t *)&output, 5);
}
free((void *)temp_data);
} /* End of main function */
注册退出程序
编写并编译出口程序之后,可以使用注册工具将其与出口点关联。 使用“使用注册信息(WRKREGINF)”命令显示系统上定义的出口点列表,并向下翻页,直到找到QBM_QJO_DLT_JRNRCV出口点,如图3所示。在该入口点上输入选项8。
图3.使用注册信息
在“使用退出程序”屏幕上,输入选项1以及退出程序的名称和库(如图4所示)。
图4.使用退出程序:添加一个退出程序
摘要
在本文中,我们研究了一种使用日记帐接收者的系统管理结合QIBM_QJO_DLT_JRNRCV出口点程序来自动删除日记帐接收者的方法。 我们看到了如何更改或创建日志以允许系统管理接收方的删除,并介绍了需要在CHGJRN或CRTJRN命令上指定的特定选项。 接下来,提出并讨论了退出程序的示例,以说明建立准则的方式,以管理允许系统删除日记帐接收者的情况。 在我们的示例中,我们只选择删除保存日期比当前日期早5天的已保存接收者。 最后,我们研究了如何将退出程序与QIBM_QJO_DLT_JRNRCV退出点相关联,以在删除接收者之前告诉系统要调用哪个退出程序。
翻译自: https://www.ibm.com/developerworks/ibmi/library/i-automate-journal-receiver-deletion/index.html