Дополнительные особенности программирования для WebSphere MQ
Модификация объектов
Характеристики объектов WebSphere MQ определяются в момент создания, но иногда их необходимо модифицировать, например, изменив приоритет сообщений при помещении их в очередь (Default Priority) или максимально допустимое количество сообщений в очереди (Maximum Queue Depth). Модификация объектов WebSphere MQ требуется, в частности, при восстановлении опций очередей Put Messages и Get Messages в состояние Allowed, а также параметров триггеринга, извлечении статистических данных (Message Count и т.п.). Необходимость работы с функциями MQINQ и MQSET , предназначенными для этих целей, возникает не так часто, но без этого иногда трудно обойтись.
Функция MQINQ позволяет извлечь атрибуты любой очереди, процесса, менеджера или списка кластеров namelist. MQSET дает возможность изменить эти параметры, но только для очереди. Обе функции используют массивы идентификаторов (selectors), в которых указывается, какие характеристики объектов должны быть извлечены или изменены. Имена идентификаторов имеют префиксы: MQCA_ для символьных данных (например, имя очереди) и MQIA_ для числовых данных (например, Maximum Queue Depth).
Допустим, для некоторой очереди необходимо определить характеристики: количество сообщений в очереди, максимальное количество сообщений, имя очереди и ее описание.
MQINQ (Hconn, Hobj, SelectorCount, Selectors, IntAttrCount, IntAttrs, CharAttrLength, CharAttrs, CompCode, Reason)
Очередь должна быть открыта и Hconn, Hobj известны.
Пусть общее количество идентификаторов MQLONG SelectorCount = 4 ; они должны быть перечислены в массиве MQLONG Selectors[4] ;
Selectors [0] = MQIA_CURRENT_Q_DEPTH; Selectors [1] = MQIA_MAX_Q_DEPTH; Selectors [2] = MQCA_Q_NAME; Selectors [3] = MQCA_Q_DESC;
Число цифровых атрибутов задается в MQLONG IntAttrCount = 2 ; они должны вернуться в массив MQLONG IntAttrs [2] ; Длина затребованных символьных данных MQLONG CharAttrLength = 112 ; (48 для MQCA_Q_NAME и 64 для MQCA_Q_DESC ) и они должны вернуться в массив CHAR CharAttrs[112] = "" ; Теперь можно выполнять MQINQ . Не стоит забывать одно важное правило: цифровые и символьные характеристики следуют в массивах IntAttrs и CharAttrs в том порядке, как они перечислены в массиве Selectors.
В случае, когда программа rewriter (см. лекцию 8), запускается как триггер, при поступлении сообщения в очередь INPUT.Q, использовать ini-файл неудобно и гораздо проще задать необходимые параметры в свойствах очереди. Для этого в свойствах очереди INPUT.Q в закладке Triggering указывается:
Trigger Control = On Initiation Queue Name = INPUT_INIT.Q Process Name = rewriter
а для процесса rewriter определяется
PROCESS_USER_DATA = OUTPUT.Q /* queue output */ PROCESS_APPL_ID = "C:\rewriter\rewriter.exe" PROCESS_ENV_DATA = rewriter.log /* имя лог-файла не более 24 символов */
Теперь в программе легко можно извлечь все необходимые параметры с помощью MQINQ . После завершения работы программы очередь инициализации следует очистить. Это делает следующий фрагмент кода:
MQLONG Select[1]; /* attribute selectors */ MQLONG SelectValue[1]; /* value attribute selectors */ MQLONG char_count; char queueinitname[48] = ""; int queuenamelen; Select[0] = MQCA_INITIATION_Q_NAME; /* attribute selectors */ queuenamelen = 0; char_count = 48; MQINQ(Hcon, Hobj, 1, Select, 0, NULL, char_count, queueinitname, &CompCode, &Reason); queuenamelen = strlen(queueinitname) - 1; queueinitname[queuenamelen] = ' '; strncpy(odI.ObjectName, queueinitname, 24); O_options = MQOO_INPUT_SHARED + MQOO_FAIL_IF_QUIESCING; MQOPEN(Hcon, &odI, O_options, &Hinq, &CompCode, &Reason); if (Reason != MQRC_NONE) { printf("MQOPEN (input) ended with reason code %ld\n", Reason); } if (CompCode == MQCC_FAILED) { exit(Reason); } memcpy(md.MsgId, MQMI_NONE, sizeof(md.MsgId)); memcpy(md.CorrelId, MQMI_NONE, sizeof(md.CorrelId)); while (CompCode == MQCC_OK) { gmo.Options = MQGMO_ACCEPT_TRUNCATED_MSG + MQGMO_WAIT; gmo.WaitInterval = 1; memcpy(md.MsgId, MQMI_NONE, sizeof(md.MsgId)); memcpy(md.CorrelId, MQMI_NONE, sizeof(md.CorrelId)); buflen = sizeof(buffer) - 1; MQGET(Hcon, Hinq, &md, &gmo, buflen, buffer, &messlen, &CompCode, &Reason); // printf("Inituation queue clear with // reason code %ld and CompCode %ld\n", // Reason, CompCode); } CompCode = MQCC_OK ;
В этом фрагменте MQINQ используется для извлечения только одного параметра: имени очереди инициализации. Очистка этой очереди делается командой MQGET до тех пор, пока очередь не будет пуста.
Функция MQSET по формату полностью аналогична MQINQ , разница между ними заключается только в направлении потоков данных. В качестве примера можно рассмотреть работу триггера с условиями Trigger Type = First и Trigger Depth = 1. При срабатывании триггера флажок из состояния Trigger Control = On переходит в состояние Trigger Control = Off и его надо восстанавливать. Это делает следующий фрагмент кода:
Select[0] = MQIA_TRIGGER_CONTROL; /* attribute selectors */ SelectValue[0] = 1 ; MQSET(Hcon, Hobj, 1, Select, 1, SelectValue, 0, NULL, &CompCode, &Reason);
Заключительный вывод по разделу: функция MQINQ позволяет извлечь атрибуты любой очереди, процесса, менеджера или списка кластеров namelist, а функция MQSET - изменить эти параметры, но только для очереди.