Я использую функцию MQCB
для добавления функций обратного вызова потребителя сообщений для очередей, из которых я читаю. Я пытаюсь прочитать из двух очередей в одном и том же соединении, и, кажется, он работает нормально при получении сообщений: моя функция обратного вызова получает дескриптор объекта для очереди, из которой было получено сообщение.
Однако, когда я получаю событие MQRC_NO_MSG_AVAILABLE
(поскольку я установил MQGMO_WAIT
для моего потребителя), дескриптор объекта равен MQHO_NONE
, поэтому я не могу сказать, к какой очереди относится событие. Я мог бы решить это, поместив дескриптор объекта в контекст обратного вызова, но так ли это должно быть? Или я что-то упускаю здесь очевидное?
Я подключаюсь к администратору очередей под управлением версии 8.0.0.2 в Linux, используя клиентскую библиотеку C версии 8.0.0.5, также в Linux. Вот вывод из моей программы-примера, показывающий, что дескрипторы объекта равны 0:
Opened queue 'AMQ.5A55ED982D616602 ' with handle 101
Opened queue 'AMQ.5A55ED982D616603 ' with handle 102
Completion code MQCC_FAILED, reason MQRC_NO_MSG_AVAILABLE, object handle 0
Completion code MQCC_FAILED, reason MQRC_NO_MSG_AVAILABLE, object handle 0
И сама программа:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <cmqc.h>
#include <cmqxc.h>
#include <cmqstrc.h>
void my_message_consumer(MQHCONN, PMQMD, PMQGMO, PMQVOID, PMQCBC);
volatile unsigned events_received = 0;
void
check_fail(const char *action, MQLONG comp_code, MQLONG reason)
{
if (comp_code != MQCC_OK) {
fprintf(stderr, "%s failed with %s %s\n",
action, MQCC_STR(comp_code), MQRC_STR(reason));
exit(1);
}
}
int
main()
{
MQHCONN hconn;
MQHOBJ hobj1, hobj2;
MQOD od = {MQOD_DEFAULT};
char queue_name[MQ_Q_NAME_LENGTH + 1];
MQLONG c, r;
MQCONN("", &hconn, &c, &r);
check_fail("MQCONN", c, r);
/* Open two dynamic queues */
strcpy(od.ObjectName, "SYSTEM.DEFAULT.MODEL.QUEUE");
MQOPEN(hconn, &od, MQOO_INPUT_EXCLUSIVE, &hobj1, &c, &r);
check_fail("MQOPEN", c, r);
strncpy(queue_name, od.ObjectName, MQ_Q_NAME_LENGTH);
queue_name[MQ_Q_NAME_LENGTH] = '\0';
printf("Opened queue '%48s' with handle %d\n", queue_name, hobj1);
strcpy(od.ObjectName, "SYSTEM.DEFAULT.MODEL.QUEUE");
MQOPEN(hconn, &od, MQOO_INPUT_EXCLUSIVE, &hobj2, &c, &r);
check_fail("MQOPEN", c, r);
strncpy(queue_name, od.ObjectName, MQ_Q_NAME_LENGTH);
queue_name[MQ_Q_NAME_LENGTH] = '\0';
printf("Opened queue '%48s' with handle %d\n", queue_name, hobj2);
/* Add a callback with zero WaitInterval for both queues */
MQMD md = {MQMD_DEFAULT};
MQGMO gmo = {MQGMO_DEFAULT};
MQCBD cbd = {MQCBD_DEFAULT};
gmo.Options = MQGMO_NO_SYNCPOINT | MQGMO_WAIT;
gmo.WaitInterval = 0;
cbd.CallbackType = MQCBT_MESSAGE_CONSUMER;
cbd.CallbackFunction = &my_message_consumer;
MQCB(hconn, MQOP_REGISTER, &cbd, hobj1, &md, &gmo, &c, &r);
check_fail("MQCB", c, r);
MQCB(hconn, MQOP_REGISTER, &cbd, hobj2, &md, &gmo, &c, &r);
check_fail("MQCB", c, r);
/* Start consuming */
MQCTLO ctlo = {MQCTLO_DEFAULT};
MQCTL(hconn, MQOP_START, &ctlo, &c, &r);
check_fail("MQCTL start", c, r);
/* Wait until events received */
while (events_received < 2)
sleep(1);
return 0;
}
void
my_message_consumer(MQHCONN hconn, PMQMD md, PMQGMO gmo,
PMQVOID buffer, PMQCBC context)
{
printf("Completion code %s, reason %s, object handle %d\n",
MQCC_STR(context->CompCode), MQRC_STR(context->Reason),
context->Hobj);
events_received++;
}
Скомпилируйте его с помощью:
gcc -o mq-no-msg mq-no-msg.c -g -Wall -I/opt/mqm/inc -L/opt/mqm/lib64 -lmqic_r -Wl,-rpath=/opt/mqm/lib64
и установите переменную окружения MQSERVER
перед запуском.