I'm using the MQCB
function to add message consumer callback functions for queues that I'm reading from. I'm trying to read from two queues on the same connection, and it seems to work fine when receiving messages: my callback function gets the object handle for the queue that the message was received from.
However, when I get an MQRC_NO_MSG_AVAILABLE
event (since I set MQGMO_WAIT
on my consumer), the object handle is MQHO_NONE
, so I can't tell which queue the event refers to. I could solve that by putting the object handle in the callback context, but is that the way it's supposed to be done? Or am I missing something obvious here?
I'm connecting to a queue manager running version 8.0.0.2 on Linux, using the C client library version 8.0.0.5, likewise on Linux. Here is the output from my sample program, showing object handles being 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
And the program itself:
#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++;
}
Compile it with:
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
and set the MQSERVER
environment variable before running.