Отсылка файла в MQ очередь при помощи PL/I

Давайте создадим небольшую программу, в котором отправим содержимое текстового файла в MQ очередь. Текст программы (немного откомментировал, если будут вопросы - пишите в комментариях): /*********************************************************************/ /* MYMQSND: LOAD MQ QUEUE FROM FILE */ /*********************************************************************/ MYMQSND: PROC OPTIONS(MAIN) REORDER; /*********************************************************************/ /* BUILTIN функции */ /*********************************************************************/ DCL TRIM BUILTIN; DCL LENGTH BUILTIN; DCL ADDR BUILTIN; DCL ONCHAR BUILTIN; DCL ONCODE BUILTIN; DCL ONLOC BUILTIN; DCL ONSOURCE BUILTIN; /*********************************************************************/ /* Обработчик ошибок */ /*********************************************************************/ DCL ERRCHAR CHAR (01) INIT (''); DCL ERRFLD CHAR (20) INIT (''); DCL ERRPROC CHAR (20) INIT (''); DCL ERRCD FIXED BIN (5,0) INIT(0); ON ERROR BEGIN; ERRCD = ONCODE; ERRCHAR = ONCHAR; ERRFLD = ONSOURCE; ERRPROC = ONLOC; PUT SKIP DATA (ERRCD,ERRFLD,ERRCHAR,ERRPROC); CLOSE FILE (SYSPRINT); EXIT; END; /*********************************************************************/ /* Переменные */ /*********************************************************************/ DCL MQ_BUFFER CHAR (32767); DCL MSG_LENGTH BIN FIXED(31); DCL INSTR CHAR(32760); DCL INSTR_VAR CHAR(32760) VAR; DCL INSTR_BL CHAR(79) INIT(' '); /*********************************************************************/ /* MQSERIES переменные (стандартные обьявления) */ /*********************************************************************/ %INCLUDE CMQP; %INCLUDE CMQEPP; DCL L_MQMGR CHAR(48); /* Имя MQ manager */ DCL L_MQNAME CHAR(48); /* Имя очереди */ DCL 1 LMQOD LIKE MQOD; /* OBJECT DESCRIPTOR */ DCL 1 LMQMD LIKE MQMD; /* MESSAGE DESCRIPTOR */ DCL 1 LMQPMO LIKE MQPMO; /* Структура опций */ DCL OPTIONS FIXED BIN(31); /* Опции отсылки */ DCL HQM FIXED BIN(31); /* CONNECTION HANDLE */ DCL COMPCODE FIXED BIN(31); /* COMPLETION CODE */ DCL REASONE FIXED BIN(31); /* REASON CODE */ DCL HOBJ FIXED BIN(31); /* OBJECT HANDLE */ DCL RECORD_LENGTH FIXED BIN(31); /* Длина записи */ /*********************************************************************/ /* Файлы */ /*********************************************************************/ DCL SYSPRINT FILE OUTPUT; /* Файл с именем очереди */ DCL MQNAME FILE RECORD INPUT SEQL; /* Файл со входными данными */ DCL MQDATA FILE RECORD INPUT SEQL ENVIRONMENT(SCALARVARYING); DCL EOF_NAME BIT(1) INIT('0'B); /* Индикатор конца файла */ ON ENDFILE(MQNAME) EOF_NAME = '1'B; DCL EOF_DATA BIT(1) INIT('0'B); /* Индикатор конца файла */ ON ENDFILE(MQDATA) EOF_DATA = '1'B; /*********************************************************************/ /* Основной код */ /*********************************************************************/ CALL INIT_ALL; /* Инициализация */ CALL READ_MQNAME; /* Вычитываем имя очереди */ /* Открываем MQ очередь */ CALL MQ_CONNECT; CALL MQ_OPEN; /* Читаем в цикле файл */ /* Каждая вычитанная строка */ /* отсылается в MQ очередь */ OPEN FILE(MQDATA); READ FILE(MQDATA) INTO(INSTR); DO WHILE(¬EOF_DATA); CALL MQ_PUT; READ FILE(MQDATA) INTO(INSTR); END; CLOSE FILE(MQDATA); CALL MQ_CLOSE; CALL MQ_DISCONNECT; /*********************************************************************/ /* Инициализация */ /*********************************************************************/ INIT_ALL: PROC; RECORD_LENGTH = 0; OPTIONS = 0; HQM = 0; COMPCODE = 0; REASONE = 0; HOBJ = 0; L_MQNAME = ''; MSG_LENGTH = 0; INSTR = ''; /* Будет использован MQ */ L_MQMGR = ''; /* manager по-умолчанию */ END INIT_ALL; /*********************************************************************/ /* Читаем имя очереди из файла */ /*********************************************************************/ READ_MQNAME: PROC; DCL MQN_BUFFER CHAR(80); OPEN FILE(MQNAME); READ FILE(MQNAME) INTO(MQN_BUFFER); IF EOF_NAME THEN CALL GENEND('MQLM010', 'MQ QUEUE NAME MISSING'); CLOSE FILE(MQNAME); L_MQNAME = SUBSTR(MQN_BUFFER,1,48); END READ_MQNAME; /*********************************************************************/ /* Подключаемся к QUEUE MANAGER */ /*********************************************************************/ MQ_CONNECT: PROC; CALL MQCONN (L_MQMGR, HQM, COMPCODE, REASONE); IF COMPCODE ¬= MQCC_OK & REASONE ¬= MQRC_NONE THEN CALL GENEND('MQLM020', 'MQ CONNECT FAILED'); END MQ_CONNECT; /********************************************************************/ /* Отключаемся от QUEUE MANAGER */ /********************************************************************/ MQ_DISCONNECT: PROC; CALL MQDISC (HQM, COMPCODE, REASONE); IF COMPCODE ¬= MQCC_OK & REASONE ¬= MQRC_NONE THEN CALL GENEND('MQLM030', 'MQ DISCONNECT FAILED'); END MQ_DISCONNECT; /*********************************************************************/ /* Открываем очередь */ /*********************************************************************/ MQ_OPEN: PROC; LMQOD.OBJECTTYPE = MQOT_Q; LMQOD.OBJECTNAME = L_MQNAME; OPTIONS = MQOO_OUTPUT; /* Режим- отсылка данных */ CALL MQOPEN (HQM, LMQOD, OPTIONS, HOBJ, COMPCODE, REASONE); IF COMPCODE ¬= MQCC_OK & REASONE ¬= MQRC_NONE THEN CALL GENEND('MQLM030', 'MQ OPEN FAILED'); END MQ_OPEN; /********************************************************************/ /* Записываем сообщение в очередь */ /********************************************************************/ MQ_PUT: PROC; /* Посылаем только данные */ /* без пробелов в конце */ INSTR_VAR = TRIM(INSTR); MQ_BUFFER = INSTR_VAR; MSG_LENGTH = LENGTH(INSTR_VAR); /* Стандартные значения */ LMQMD.STRUCID = MQMD_STRUC_ID; LMQMD.VERSION = MQMD_VERSION_1; LMQMD.MSGTYPE = MQMT_DATAGRAM; LMQMD.EXPIRY = MQEI_UNLIMITED; LMQMD.FORMAT = MQFMT_STRING; LMQMD.PRIORITY = MQPRI_PRIORITY_AS_Q_DEF; LMQMD.PERSISTENCE = MQPER_PERSISTENCE_AS_Q_DEF; LMQMD.MSGID = MQCI_NONE; LMQMD.CORRELID = MQCI_NONE; LMQPMO.STRUCID = MQPMO_STRUC_ID; LMQPMO.VERSION = MQPMO_VERSION_1; CALL MQPUT (HQM, HOBJ, LMQMD, LMQPMO, MSG_LENGTH, MQ_BUFFER, COMPCODE, REASONE); IF COMPCODE ¬= MQCC_OK & REASONE ¬= MQRC_NONE THEN CALL GENEND('MQLM050', ' MQ PUT FAILED'); END MQ_PUT; /********************************************************************/ /* Закрываем очередь */ /********************************************************************/ MQ_CLOSE: PROC; OPTIONS = MQCO_NONE; CALL MQCLOSE (HQM, HOBJ, OPTIONS, COMPCODE, REASONE); IF COMPCODE ¬= MQCC_OK & REASONE ¬= MQRC_NONE THEN CALL GENEND('MQLM080', ' MQ CLOSE FAILED'); END MQ_CLOSE; /********************************************************************/ /* Обработчик ошибок */ /********************************************************************/ GENEND: PROC(ID,TEXT); DCL ID CHAR(7); DCL TEXT CHAR(60); PUT SKIP DATA(ID); PUT SKIP DATA(TEXT); PUT SKIP DATA(COMPCODE); PUT SKIP DATA(REASONE); SIGNAL ERROR; END GENEND; /********************************************************************/ /* Конец программы */ /********************************************************************/ END MYMQSND; Собираем программу и создаем небольшое задание, для ее запуска: //MYMQSNDJ JOB (USERID,GROUPID),'TEST JOB',NOTIFY=&SYSUID, // MSGLEVEL=(1,1),MSGCLASS=H,CLASS=2,REGION=6M //********************************************************************/ //STEP010 EXEC PGM=MYMQSND,REGION=4M //STEPLIB DD DSN=USERID.LOAD,DISP=SHR // DD DSN=SYS1.MQMXXX.SCSQAUTH,DISP=SHR // DD DSN=SYS1.MQMXXX.SCSQANLE,DISP=SHR //SYSIN DD DUMMY //SYSTSPRT DD SYSOUT=* //SYSOUT DD SYSOUT=* //SYSPRINT DD SYSOUT=* //PLIDUMP DD SYSOUT=* //********************************************************************/ //* Файл с именем очереди //********************************************************************/ //MQNAME DD DSN=USERID.MQNAME,DISP=SHR //********************************************************************/ //* Файл с данными для отсылки //********************************************************************/ //MQDATA DD DSN=USERID.MQDATA,DISP=SHR Параметры задания устанавливаем в зависимости от настроек среды. Пути к библиотекам SYS1.MQMXXX.SCSQAUTH и SYS1.MQMXXX.SCSQANLE нужно заменить на аналогичные существующие (MQMXXX - имя MQSeries environment). PS: надеюсь, лишних переменных не оставил и не удалил нужных =)Boots