ユーザー待ち行列( *USRQ ) はプロセス間でデータを共有するのに最も高速で
処理することができる有効な手段であるが、データを送信するためには
「enq」という MI (マシン・インターフェース) を使用しなければならない。
enq を使用するには一般的には C 言語からしか呼び出すことはできないが
使用方法に精通しているユーザーも多くはないと思われるので
弊社で製品 EnterpriseServer で実際に使用されている SNDUSRQ という
名前の ANS-C によるプログラム・ソースを公開しよう。
------------------------------------------------------------------------
0001.00 #include <stdio.h>
0002.00 #include <stdlib.h>
0003.00 #include <string.h>
0004.00 #include <miqueue.h>
0005.00 #include <qusec.h>
0006.00 #include <miptrnam.h>
0007.00 #include <signal.h>
0008.00
0009.00 #define TRUE 0
0010.00 #define FALSE -1
0011.00
0012.00 void SNDUSR(char* usrq, char* usrqlib, char* snddta);
0013.00 int main(int argc, char *argv[]){
0014.00 SNDUSR(argv[1], argv[2], argv[3]);
0015.00 }
0016.00 void SNDUSR(char* usrq, char* usrqlib, char* snddta)
0017.00 {
0018.00 _ENQ_Msg_Prefix_T e_msg_prefix;
0019.00 _SYSPTR queue;
0020.00 volatile _INTRPT_Hndlr_Parms_T ca;
0021.00 int err;
0022.00
0023.00 err=1;
0024.00 #pragma exception_handler(MONMSG, ca, 0, _C2_MH_ESCAPE, \
0025.00 _CTLA_HANDLE)
0026.00 queue = rslvsp(_Usrq, usrq, usrqlib, _AUTH_ALL);
0027.00 e_msg_prefix.Msg_Len = strlen(snddta);
0028.00 enq(queue,&e_msg_prefix, snddta);/* SNDUSRQ*/
0029.00 return;
0030.00 MONMSG:
0031.00 memset(snddta, 0, sizeof(snddta));
0032.00 memcpy(snddta, "*ERROR", 6);
0033.00 return;
0034.00 }
------------------------------------------------------------------------
CRTCMOD MODULE(QTEMP/SNDUSRQ) SRCFILE(MYSRCLIB/QCSRC) AUT(*ALL)
CRTSRVPGM SRVPGM(MYLIB/SNDUSRQ) MODULE(QTEMP/SNDUSRQ) EXPORT(*ALL) ACTGRP(*CALLER) AUT(*ALL)
または
CRTPGM PGM(MYLIB/SNDUSRQ) MODULE(QTEMP/SNDUSRQ) ACTGRP(*NEW) AUT(*ALL)
としてサービス・プログラムとしてもプログラムとしても利用することができる。
プログラムとして作成した場合は実行は簡単であり、
CALL MYLIB/SNDUSRQ('USRQ名', 'ライブラリー名', '投入するデータ')
である。ただし「投入するデータ」は char* として定義されているので、長さは任意である。
次は この SNDUSRQ を呼び出しているサンプルCLP ソースである。
------------------------------------------------------------------------------------
0001.00 PGM PARM(&IPADR)
0002.00 /*---------------------------------------------------------*/
0003.00 /* STRMYLOGCL : アクセス・ログの個別出力 */
0004.00 /*---------------------------------------------------------*/
0005.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(80)
0006.00 DCL VAR(&IPADR) TYPE(*CHAR) LEN(15)
0007.00 DCL VAR(&TYPE) TYPE(*CHAR) LEN(1)
0008.00 DCL VAR(&INSTANSE) TYPE(*CHAR) LEN(10)
0009.00 DCL VAR(&QNAME) TYPE(*CHAR) LEN(11)
0010.00 DCL VAR(&QLIB) TYPE(*CHAR) LEN(11)
0011.00 DCL VAR(&SNDDTA) TYPE(*CHAR) LEN(256)
0012.00 DCL VAR(&NULL) TYPE(*CHAR) LEN(1) VALUE(X'00')
0013.00 DCL VAR(&STRPOS) TYPE(*DEC) LEN(3 0) VALUE(1)
0014.00 DCL VAR(&STRLEN) TYPE(*DEC) LEN(3 0) VALUE(10)
0015.00 DCL VAR(&PATLEN) TYPE(*DEC) LEN(3 0) VALUE(1)
0016.00 DCL VAR(&RESULT) TYPE(*DEC) LEN(3 0)
0017.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
0018.00
0019.00 RTVJOBA TYPE(&TYPE)
0020.00 IF COND(%SST(&IPADR 1 5) *EQ '*CALC') THEN(DO)
0021.00 ASNET.COM/RTVDEVIP DEV(*CURRENT) IPADDR(&IPADR)
0022.00 ENDDO
0023.00 RTVDTAARA DTAARA(ASNET.USR/HTTPSVR (20 10)) +
0024.00 RTNVAR(&INSTANSE)
0025.00 CALL PGM(QCLSCAN) PARM(&INSTANSE &STRLEN &STRPOS +
0026.00 &NULL &PATLEN ' ' ' ' ' ' &RESULT)
0027.00 IF COND(&RESULT *NE 0) THEN(DO) /* +
0028.00 NULL を除去する */
0029.00 CHGVAR VAR(%SST(&INSTANSE &RESULT 1)) VALUE(' ')
0030.00 ENDDO /* NULL を除去する */
0031.00 CHGVAR VAR(&QNAME) VALUE(&INSTANSE *TCAT '_SIG' +
0032.00 *CAT &NULL)
0033.00 CHGVAR VAR(&QLIB) VALUE('QUSRTEMP ' *CAT &NULL)
0034.00 CHGVAR VAR(&SNDDTA) VALUE('STRMYLOG=' *CAT +
0035.00 &IPADR *TCAT &NULL)
0036.00 CALL PGM(ASNET.COM/SNDUSRQ) PARM(&QNAME &QLIB +
0037.00 &SNDDTA)
0038.00 CHGVAR VAR(&MSG) VALUE(&IPADR *TCAT +
0039.00 ' のアクセス・ログ出力を開始しました。 ')
0040.00 GOTO SNDMSG
0041.00
0042.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG)
0043.00 SNDMSG:
0044.00 IF COND(&TYPE *EQ '0') THEN(DO)
0045.00 SNDPGMMSG MSG(&MSG) TOMSGQ(*SYSOPR) MSGTYPE(*COMP)
0046.00 ENDDO
0047.00 ELSE CMD(DO)
0048.00 SNDPGMMSG MSG(&MSG) TOMSGQ(*TOPGMQ) MSGTYPE(*DIAG)
0049.00 ENDDO
0050.00 ENDPGM
------------------------------------------------------------------------------------