ユーザー待ち行列 ( *USRQ ) はデータ待ち行列 ( *DTAQ ) と良く似たオブジェクトであるが
データ待ち行列 ( *DTAQ ) に比べてユーザー待ち行列 ( *USRQ ) の実体はメモリであるので
パフォーマンスが圧倒的に優れている。
従ってソフトウェア製品に利用するのであれば *DTAQ より *USRQ を利用すべきである。
ところが
と2つの API が用意されているのだがクリヤーする API は用意されていない。
それではクリヤーする機能は必要ないのかというと大いに必要である。
ユーザー待ち行列にメッセージ(データ)が投入された後、それを読取ると
二度とそのデータを読取ることはできない。
するといつまでもおおよそ空の状態が続くので再編成やクリヤーは
必要ないように思えるのだが、物理ファイル ( PF ) で削除レコードが
元のレコード域を削除後もいつまでも占有しているのと同じように、
ユーザー待ち行列もメッセージ(レコード)数はないのにやがては
満杯になって使用できなくなってしまうのである。
そこで適切な時期に中身をクリヤー(消去)するという作業が必要となってくる。
*DTAQ には QCLRDTAQ という名前の API が用意されていたが、
*USRQ には QCLRUSRQ という API は用意されていない。
そこで今回は、QCLRUSRQ というデータ待ち行列をクリヤーする API を
作成してみた。
0001.00 CMD PROMPT(' ユーザー待ち行列のクリヤー ') 0002.00 PARM KWD(USRQ) TYPE(USRQ) MIN(1) + 0003.00 PROMPT(' データ待ち行列 ') 0004.00 USRQ: QUAL TYPE(*NAME) LEN(10) MIN(1) 0005.00 QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) + 0006.00 SPCVAL((*LIBL) (*CURLIB)) + 0007.00 PROMPT(' ライブラリー ') 0008.00 PARM KWD(CLEAR) TYPE(*CHAR) LEN(10) RSTD(*YES) + 0009.00 DFT(*ALL) VALUES(*ALL *KEEP) + 0010.00 PROMPT(' クリヤー ')
CRTCMD CMD(MYLIB/CLRUSRQ) PGM(MYLIB/CLRUSRCL) SRCFILE(MYSRCLIB/QCMDSRC)AUT(*ALL)
コマンド: CLRUSRQ はパラメータ : CLEAR を持っているが、
これは既存のユーザー待ち行列の中身を維持して消去するのかまたは、
すべて消去してまうのかを指定するためである。
0001.00 PGM PARM(&USRQLIB &CLEAR) 0002.00 /*-------------------------------------------------------------------*/ 0003.00 /* CLRUSRQCL : ユーザー待ち行列のクリヤー */ 0004.00 /* */ 0005.00 /* 2017/05/03 作成 */ 0006.00 /*-------------------------------------------------------------------*/ 0007.00 DCL VAR(&USRQLIB) TYPE(*CHAR) LEN(20) 0008.00 DCL VAR(&USRQ) TYPE(*CHAR) LEN(10) 0009.00 DCL VAR(&USRLIB) TYPE(*CHAR) LEN(10) 0010.00 DCL VAR(&CLEAR) TYPE(*CHAR) LEN(10) 0011.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(132) 0012.00 DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) 0013.00 DCL VAR(&MSGF) TYPE(*CHAR) LEN(10) 0014.00 DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10) 0015.00 DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(132) 0016.00 DCL VAR(&TYPE) TYPE(*CHAR) LEN(1) 0017.00 DCL VAR(&TOPGMQ) TYPE(*CHAR) LEN(10) 0018.00 DCL VAR(&ERR) TYPE(*CHAR) LEN(1) 0019.00 DCL VAR(&MSGTYPE) TYPE(*CHAR) LEN(10) + 0020.00 VALUE('*ESCAPE ') 0021.00 DCL VAR(&APIERR) TYPE(*CHAR) LEN(116) + 0022.00 VALUE(X'000074') /* 2 進数 */ 0023.00 DCL VAR(&NULL4) TYPE(*CHAR) LEN(4) + 0024.00 VALUE(X'00000000') 0025.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) 0026.00 0027.00 /*( 環境の取得 )*/ 0028.00 RTVJOBA TYPE(&TYPE) 0029.00 IF COND(&TYPE *EQ '0') THEN(DO) /* バッチ */ 0030.00 CHGVAR VAR(&TOPGMQ) VALUE('*SYSOPR ') 0031.00 ENDDO /* バッチ */ 0032.00 ELSE CMD(DO) /* 対話式 */ 0033.00 CHGVAR VAR(&TOPGMQ) VALUE('*TOPGMQ ') 0034.00 ENDDO /* 対話式 */ 0035.00 0036.00 /*( パラメータの取得 )*/ 0037.00 CHGVAR VAR(&USRQ) VALUE(%SST(&USRQLIB 01 10)) 0038.00 CHGVAR VAR(&USRLIB) VALUE(%SST(&USRQLIB 11 10)) 0039.00 0040.00 /*( USRQ の確保 )*/ 0041.00 /* ALCOBJ OBJ((&USRQLIB/&USRQ *USRQ *EXCL)) WAIT(3) */ 0042.00 0043.00 /*( USRQ のクリヤー )*/ 0044.00 CALL PGM(SPOOLWTR/QCLRUSRQ) PARM(&USRQ &USRLIB + 0045.00 &CLEAR &ERR &MSG) 0046.00 /* DLCOBJ OBJ((&USRQLIB/&USRQ *USRQ *EXCL)) */ 0047.00 IF COND(&ERR *EQ 'E') THEN(DO) 0048.00 GOTO SNDMSG 0049.00 ENDDO 0050.00 0051.00 /*( 完了メッセージ )*/ 0052.00 CHGVAR VAR(&MSG) VALUE(' ユーザー待ち行列 ' *CAT + 0053.00 &USRLIB *TCAT '/' *CAT &USRQ *TCAT + 0054.00 ' をクリヤーしました。 ') 0055.00 CHGVAR VAR(&MSGTYPE) VALUE('*DIAG ') 0056.00 GOTO SNDMSG 0057.00 RETURN 0058.00 0059.00 APIERR: 0060.00 CHGVAR VAR(&MSGID) VALUE(%SST(&APIERR 9 7)) 0061.00 CHGVAR VAR(&MSGDTA) VALUE(%SST(&APIERR 17 100)) 0062.00 CHGVAR VAR(&MSGF) VALUE('QCPFMSG ') 0063.00 CHGVAR VAR(&MSGFLIB) VALUE('QSYS ') 0064.00 GOTO SNDMSG 0065.00 0066.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) + 0067.00 MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) + 0068.00 MSGFLIB(&MSGFLIB) 0069.00 SNDMSG: IF COND(&MSGID *EQ ' ') THEN(DO) 0070.00 SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) + 0071.00 TOMSGQ(&TOPGMQ) MSGTYPE(&MSGTYPE) 0072.00 ENDDO 0073.00 ELSE CMD(DO) 0074.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + 0075.00 MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) + 0076.00 MSGTYPE(&MSGTYPE) 0077.00 ENDDO 0078.00 ENDPGM
CRTCLPGM PGM(MYLIB/CLRUSRQCL) SRCFILE(MYSRCLIB/QCLSRC) AUT(*ALL)
0001.00 /********************************************************************/ 0002.00 /* */ 0003.00 /* QCLRUSRQ : ユーザー待ち行列のクリヤー */ 0004.00 /* */ 0005.00 /* Office Quattro Co,.Ltd 2018/05/03 20:34:08 created */ 0006.00 /* */ 0007.00 /* */ 0008.00 /********************************************************************/ 0009.00 #pragma comment(COPYRIGHT, "Spool Writer Ver5.0 (C) CopyRight ™ 0010.00 Office Quattro.Corp. 2018- All right reserved. Users Restricted ™ 0011.00 Rights - Use, duplication or disclosure restricted by Office Quattro ™ 0012.00 Corp. Licenced Materials-Property of Office Quattro.") 0013.00 #include0014.00 #include 0015.00 #include 0016.00 #include /* triml */ 0017.00 #include 0018.00 #include 0019.00 #include 0020.00 #include 0021.00 #include 0022.00 0023.00 #define TRUE 0 0024.00 #define FALSE -1 0025.00 int bLR = FALSE; 0026.00 typedef struct { 0027.00 int BYTESPRO; 0028.00 int BYTESAVL; 0029.00 char MSGID[7]; 0030.00 char RESRVD; 0031.00 char EXCPDATA[100]; 0032.00 } ERRSTRUCTURE; /* Define the error return structure */ 0033.00 ERRSTRUCTURE errcode;/* Error Code Structure for RCVMSG */ 0034.00 volatile _INTRPT_Hndlr_Parms_T ca; 0035.00 0036.00 /*************************************************************/ 0037.00 /* 内 部 使 用 関 数 */ 0038.00 /*************************************************************/ 0039.00 void GetParam(int argc, char *argv[]); 0040.00 void INZSR(void); 0041.00 void LRRTN(char *argv[]); 0042.00 0043.00 /*************************************************************/ 0044.00 /* IMPORT 関 数 */ 0045.00 /*************************************************************/ 0046.00 /*************************************************************/ 0047.00 /* IMPORT 変 数 */ 0048.00 /*************************************************************/ 0049.00 /*************************************************************/ 0050.00 /* 外 部 呼 出 し 関 数 */ 0051.00 /*************************************************************/ 0052.00 void MonitorMSG(_INTRPT_Hndlr_Parms_T ca, char* ref); 0053.00 #pragma linkage(MonitorMSG, OS) 0054.00 #pragma map(MonitorMSG, "ASNET.COM/MONMSG") 0055.00 /*************************************************************/ 0056.00 /* グ ロ ー バ ル 変 数 */ 0057.00 /*************************************************************/ 0058.00 /*------( 受取りパラメータ値 )----------*/ 0059.00 char USRQ[11], USRQLIB[11], CLEAR[11], ERR[2], MSG[122]; 0060.00 /*------( 受取りパラメータ値 )----------*/ 0061.00 char ref[133], usrq[11], usrqlib[11]; 0062.00 /********************************************************************/ 0063.00 /* m a i n --- main module of this pgm */ 0064.00 /* */ 0065.00 /* 1. USRQ */ 0066.00 /* 2. USRQLIB */ 0067.00 /* 3. CLEAR */ 0068.00 /* 4. ERR */ 0069.00 /* 5. MSG */ 0070.00 /* */ 0071.00 /*------------------------------------------------------------------*/ 0072.00 0073.00 int main(int argc, char *argv[]){ 0074.00 _MQAT_Template_T que_attributes; /* receiver template for matcat */ 0075.00 _SYSPTR queue; 0076.00 int Num_Msgs; /* 現在のレコード数 */ 0077.00 int Max_Msgs; /* 最大数 */ 0078.00 int Extension; /* 追加回数 */ 0079.00 int Max_Size; /* 最大サイズ */ 0080.00 int Init_Msgs; /* 初期メッセージ数 */ 0081.00 short Key_Length; /* キー長 */ 0082.00 int Q_Type; /* ユーザー待ち行列のタイプ */ 0083.00 char Type[2]; /* ユーザー待ち行列のタイプ */ 0084.00 char USRQQLIB[21], text[51], cmd[256], rcvbuf[4092]; 0085.00 _DEQ_Msg_Prefix_T d_msg_prefix; 0086.00 _ENQ_Msg_Prefix_T e_msg_prefix; 0087.00 _SYSPTR old_queue, new_queue; 0088.00 0089.00 #pragma exception_handler(MONMSG, ca, 0, _C2_MH_ESCAPE, ™ 0090.00 _CTLA_HANDLE) 0091.00 GetParam(argc, argv); /*[ パラメータの取得 ]*/ 0092.00 INZSR(); /*[ 初期設定 ]*/ 0093.00 0094.00 queue = rslvsp(_Usrq, USRQ, USRQLIB, _AUTH_ALL); 0095.00 que_attributes.Template_Size = sizeof(_MQAT_Template_T); 0096.00 matqat(&que_attributes, queue); 0097.00 0098.00 Num_Msgs = que_attributes.Num_Msgs; 0099.00 Max_Msgs = que_attributes.Max_Msgs; 0100.00 Extension = que_attributes.Extension; 0101.00 Max_Size = que_attributes.Max_Size; 0102.00 Init_Msgs = que_attributes.Init_Msgs; 0103.00 Q_Type = que_attributes.Q_Type; 0104.00 switch(Q_Type){/*switch*/ 0105.00 case 0: strcpy(Type, "K"); break; 0106.00 case 1: strcpy(Type, "L"); break; 0107.00 case 2: strcpy(Type, "F"); break; 0108.00 }/*switch*/ 0109.00 if(strncmp(Type, "K", 1) != 0) Key_Length = 0; 0110.00 0111.00 sprintf(USRQQLIB, "%10s%10s", USRQ, USRQLIB); 0112.00 if(Num_Msgs > 0 && strncmp(CLEAR, "*KEEP ", 10) == 0){/* 複製 */ 0113.00 /*( 現行 USRQ を QTEMP に移す )*/ 0114.00 sprintf(cmd, "MOVOBJ OBJ(%s/%s) OBJTYPE(*USRQ) TOLIB(QTEMP)", 0115.00 usrqlib, usrq); 0116.00 system(cmd); 0117.00 }/* 複製 */ 0118.00 else{/* 新規再作成 */ 0119.00 /*( 不要であれば削除する )*/ 0120.00 sprintf(cmd, "DLTUSRSPC USRSPC(%s/%s )", usrqlib, usrq); 0121.00 system(cmd); 0122.00 }/* 新規再作成 */ 0123.00 QUSCRTUQ(USRQQLIB, "PF ", Type, Key_Length, Max_Size, Init_Ms 0124.00 Extension, "*ALL ", text, "*NO ", &errcode); 0125.00 if(Num_Msgs > 0 && strncmp(CLEAR, "*KEEP ", 10) == 0){/* 複製 */ 0126.00 /*( OLD QUEUE から NEW QUEUE へデータを転送する )*/ 0127.00 old_queue = rslvsp(_Usrq, USRQ, "QTEMP ", _AUTH_ALL); 0128.00 new_queue = rslvsp(_Usrq, USRQ, USRQLIB, _AUTH_ALL); 0129.00 d_msg_prefix.Wait_Forever = -1;/*nowait*/ 0130.00 memset(d_msg_prefix.Wait_Time, 0, sizeof(_MI_Time)); 0131.00 while(1){/*while*/ 0132.00 if(deqi(&d_msg_prefix, rcvbuf, old_queue) == 0) break; 0133.00 e_msg_prefix.Msg_Len = strlen(rcvbuf); 0134.00 enq(new_queue, &e_msg_prefix, rcvbuf);/* SNDUSRQ*/ 0135.00 }/*while*/ 0136.00 sprintf(cmd, "DLTUSRSPC USRSPC(QTEMP/%s)", usrq); 0137.00 system(cmd); 0138.00 }/* 複製 */ 0139.00 0140.00 LRRTN(argv); 0141.00 exit(0); 0142.00 0143.00 MONMSG: 0144.00 #pragma disable_handler 0145.00 if(strncmp((char*)&ca.Msg_Id, "MCH3401", 7) == 0){/*NOT FOUND* 0146.00 sprintf(MSG, " ユーザー待ち行列 %s/%s が見つかりません。 ", 147.00 usrqlib, usrq); 148.00 ERR[0] = 'E'; 149.00 LRRTN(argv); 150.00 exit(-1); 151.00 }/*NOT FOUND*/ 152.00 MonitorMSG(ca, ref); 153.00 154.00 exit(0); 155.00 } 156.00 /*************************************/ 157.00 void GetParam(int argc, char *argv[]) 158.00 /*************************************/ 159.00 { 160.00 memcpy(USRQ, argv[1], 10); 161.00 USRQ[10] = 0x00; 162.00 memcpy(USRQLIB, argv[2], 10); 163.00 USRQLIB[10] = 0x00; 164.00 memcpy(CLEAR, argv[3], 10); 165.00 CLEAR[10] = 0x00; 166.00 } 167.00 /****************/ 0168.00 void INZSR(void) 0169.00 /****************/ 0170.00 { 0171.00 errcode.BYTESPRO = 160; 0172.00 errcode.BYTESAVL = 0; 0173.00 strcpy(usrq, USRQ); 0174.00 usrq[triml(usrq, ' ')] = 0x00; 0175.00 strcpy(usrqlib, USRQ); 0176.00 usrqlib[triml(usrqlib, ' ')] = 0x00; 0177.00 } 0178.00 /************************/ 0179.00 void LRRTN(char *argv[]) 0180.00 /************************/ 0181.00 { 0182.00 if(bLR == TRUE) return; 0183.00 bLR = TRUE; 0184.00 memcpy(argv[4], ERR, 1); 0185.00 strcpy(argv[5], MSG); 0186.00 }
CRTBNDC PGM(MYLIB/QCLRUSR) SRCFILE(MYSRCLIB/QCSRC) AUT(*ALL)
QCLRUSR は C言語として書かれているがそのままコンパイルすれば
言語は知らなくてもかまわない。
C言語を知らない人のために処理の概要を説明すると
(1)〜(6)のシナリオは難しいものではないので、どうしても C 言語は嫌だと
いう人はこのソースを見ながら RPG たまたは CLP で書くこともできるが
内容は結局、ここに書いた多くの MI 関数などを使うことになるので
C 言語のほうが圧倒的に短くて済む。
処理の内容によって言語の向き、不向きがあるので
このまま C 言語でのコンパイルが最もお勧めである。
(1)現在の *USRQ の属性 ( que_attributes ) を matqat ( MI ) によって
取得しておく matqat は知らない人も多いかも知れないが
*USRQ の属性を取得する MI ( = Machine Interface )である。
(2)既存のレコード数が存在しているか、または *KEEP が指定されている場合は
MOVOBJ で現在の *USRQ をライブラリー QTEMP に移す。
(3)それ以外であれば既存の *USRQ を削除する
(4)新しい *USRQ を元の場所(ライブラリー)に API: QUSCRTUQ を使って作成する。
(5)元の *USRQ のレコード数が存在しているか、または *KEEP が指定されている場合は
QTEMP の旧 *USRQ を読み取ってデータを新しい *USRQ に入れる。
(6)旧い QTEMP の *USRQ を削除して終了する