This article is going to talk about some new code shipped with the V22.214.171.124 FixPack to make it easier to see what a queue manager is doing, simplify investigation of possible problems, and to assist with writing your own MQ applications. Formatting MQ Events is now available as part of the MQ product.
To start with, we need to talk a little about MQ’s event generation.
Command and configuration events
One of the mechanisms used to monitor what is going on in MQ is to look at events that the queue manager emits. There are many different types, for example showing that a queue is full or that there has been a failure authorising some kind of access. A pair of events, the command and configuration events, can be used to get an audit trail of configuration changes. These events are written in a binary format known as PCF, and need some tool to transform them into a readable format.
The command events describe who issued a command and what kind of command it was (MQSC or PCF); configuration events show what has changed. When taken together you can use them to get a history of administrative actions.
However there were a couple of gaps in these events. In particular, changes to the security authorisations were not always recorded. Which is why, in V126.96.36.199, that has been sorted out. Now, whether you use the setmqaut command, the SET AUTHREC command in an MQSC session, or the equivalent PCF command for programmatic control, both command and configuration events get generated.
$ setmqaut -m V8004_A -t qmgr -p db2inst1 +connect The setmqaut command completed successfully.
will generate events that can be formatted as
**** Message #1 (324 Bytes) on Queue SYSTEM.ADMIN.COMMAND.EVENT **** Event Type : Command Event Reason : Command MQSC Event created : 2015/07/07 10:26:47.82 GMT Correlation Id : 414D5120563830335F41202020202CC001F03 COMMAND CONTEXT Event User Id : metaylor Event Origin : Console Event Queue Mgr : V8004_A Command : Set Auth Rec COMMAND DATA Auth Profile Name : self Object Type : Queue Mgr Principal Entity Names : db2inst1 Auth Add Auths : Connect **** Message #2 (316 Bytes) on Queue SYSTEM.ADMIN.CONFIG.EVENT **** Event Type : Config Event Reason : Config Change Object Object state : Before Change Correlation Id : 414D5120563830335F41202020202CC001F03 Event created : 2015/07/07 10:26:47.82 GMT Event User Id : metaylor Event Origin : Console Event Queue Mgr : V8004_A Object Type : Auth Rec Auth Profile Name : self Auth Rec Type : Queue Mgr Entity Name : db2inst1 Entity Type : Principal Authorization List : None **** Message #3 (316 Bytes) on Queue SYSTEM.ADMIN.CONFIG.EVENT **** Event Type : Config Event Reason : Config Change Object Object state : After Change Correlation Id : 414D5120563830335F41202020202CC001F03 Event created : 2015/07/07 10:26:47.82 GMT Event User Id : metaylor Event Origin : Console Event Queue Mgr : V8004_A Object Type : Auth Rec Auth Profile Name : self Auth Rec Type : Queue Mgr Entity Name : db2inst1 Entity Type : Principal Authorization List : Connect
From this we can see that the userid dbinst1 previously had no authorisations to the queue manager, but is now allowed to connect.
A sample event-handling program
Now that I’ve shown what the new events are, I can get to the part that I particularly wanted to write about in this blog post – the processing of these events.
In order to test that the queue manager was correctly generating these new command and configuration events, I needed a tool to format them. There have been many SupportPacs, and the KnowledgeCenter itself contains source code that you could copy and paste, but these were not able to handle some of the tasks I needed for the testing. So I started to write a program that could understand the new events, and display them in a way that proved they were being built properly inside the queue manager. Very quickly I realised that what started as a program specifically for testing could be turned into a sample program and shipped with the product. And so amqsevt was created, to sit alongside amqsmon and amqsact as a program and source code that takes MQ’s PCF messages and turns them into something useful.
Because MQ’s events can be sent to several different queues, depending on which specific event it is, this sample gets messages from multiple queues. It makes use of the MQCB verb to simplify that job; rather than looping round all of the queues in turn, we can let MQCB call back into the program whenever a message appears on any of the queues of interest.
Beyond that, I think the most interesting thing about this sample is how it makes the contents of the events readable.
Making the messages readable
The MQ API defines a lot of numbers that can be referenced in application programs, and these symbolic constants are often used to describe parameters of the API or attributes of objects. For example, MQBND_BIND_ON_GROUP is a definition whose value is 0. Programmers can refer to these constants by name, rather than worrying about the actual value. This makes program source code easy to understand. You can write
if (reasonCode == MQRC_NOT_AUTHORIZED)… instead of
if (reasonCode == 2035)….
But the opposite mapping, from a number to a meaningful name, is more problematic. With the event formatter, there needed to be a way to convert the integer that describes the default bind option for a queue into something that has a meaning. Otherwise, many events would just appear as lists of numbers which an administrator would have to decode by hand to see what was going on.
There is a method for Java programs, MQConstants.lookup(), which returns the symbolic names for a value. That could not be used from the C sample program. The solution chosen was to create lists of all of the symbolic names, and have functions that find the right string for a given value.
A new header file, cmqstrc.h, contains these functions. While an application developer still has to know which function to call to interpret a particular value (just as they have to know the correct filter in the Java lookup() method), the hard work of managing the mappings has been done in the product.
For all MQ developers
This new header file solves a problem that many application developers have, not just those working on event processing. It has been very common for developers to write their own version of a strerror-like function to handle MQ return codes in order to report failed API calls in a meaningful way. Now they can use the MQRC_STR function directly, and not need to keep their own similar tables updated. New versions of MQ will get new versions of these mapping functions; the maps are kept in step with all the other MQI definitions.
Here is an example of a few calls to the MQI mapping operations, showing how easy it is to make application output more readable.
printf("Error is %s\n",MQRC_STR(2035)); printf("Completion Code is %s\n",MQCC_STR(CompCode)); printf("%s is %s\n", MQIA_STR(MQIA_PLATFORM),MQPL_STR(MQPL_UNIX));
MQRC_NOT_AUTHORIZED MQCC_OK MQIA_PLATFORM is MQPL_UNIX
What began as a requirement primarily to help MQ administrators evolved into something that can also help application developers. I hope I’ve shown how you can use the new sample program and header file to make your own programs easier to write and to use.