I was using my Python programs for processing MQ PCF data, and was testing them out with different sorts of MQ data. I found the documentation for change events in the IBM knowledge centre is a bit sparse, so here is some information on it.
I did
- define QL(DELETEME)
- alter ql(DELETEME) descr(‘change comment’)
- delete QL(DELETEME)
For define and delete there is one event message created. For alter there are two messages created, one contains before data the other has the after data.
The MD looks like
"MQMD":{
"StrucId":"MD ",
"Version":1,
"Report":"NONE",
"MsgType":"DATAGRAM",
"Expiry":-1,
"Feedback":"NONE",
"Encoding":546,
"CodedCharSetId":1208,
"Format":"MQEVENT ",
"Priority":0,
"Persistence":"NOT_PERSISTENT",
"MsgId":"0x414d5120514d4120202020202020202020…",
"CorrelId":"0x414d5120514d4120202020202020202020…",
"BackoutCount":0,
"ReplyToQ":" ",
"ReplyToQMgr":"QMA",
"UserIdentifier":" ",
"AccountingToken":"0x0000…",
"ApplIdentityData":" ",
"PutApplType":"QMGR",
"PutApplName":"QMA ",
"PutDate":"20190217",
"PutTime":"11141373",
"ApplOriginData":" ",
"GroupId":"0x000000...",
"MsgSeqNumber":1,
"Offset":0,
"MsgFlags":0,
"OriginalLength":-1
},
When a change event occurs the MD for the “after” message is effectively the same but note the MsgID is different, and the CorrelId is the same, so you will need to clear the MsgId and keep the CorrelID when getting the second message.
For the create command the PCF header was
"Header":{
"Type":"EVENT",
"StrucLength":36,
"Version":2,
"Command":"CONFIG_EVENT",
"MsgSeqNumber":1,
"Control":"LAST",
"CompCode":0,
"Reason":2367, "CONFIG_CREATE_OBJECT"
"ParameterCount":58,
},
For the delete command the PCF header was
"Header":{
"Type":"EVENT",
"StrucLength":36,
"Version":2,
"Command":"CONFIG_EVENT",
"MsgSeqNumber":1,
"Control":"LAST",
"CompCode":0,
"Reason":2369, "CONFIG_DELETE_OBJECT
"ParameterCount":58
}
For the alter/change command the PCF headers were
"Header":{
"Type":"EVENT",
"StrucLength":36,
"Version":2,
"Command":"CONFIG_EVENT",
"MsgSeqNumber":1,
"Control":"NOT_LAST",
"CompCode":0,
"Reason":2368,
"ParameterCount":58
},
and
"Header":{
"Type":"EVENT",
"StrucLength":36,
"Version":2,
"Command":"CONFIG_EVENT",
"MsgSeqNumber":2,
"Control":"LAST",
"CompCode":0,
"Reason":2368, "CONFIG_CHANGE_OBJECT"
"ParameterCount":58
},
The differences are the MsgSeqNumber value and Control being NOT_LAST or LAST.
The data is common to all requests. You need to compare the fields in both the records for the change event, to see which are different. With the data in Python dict – this was a trivial exercise.
"Data":{
"EVENT_USER_ID":"colinpaice",
"EVENT_ORIGIN":"CONSOLE",
"EVENT_Q_MGR":"QMA",
"OBJECT_TYPE":"Q",
"Q_NAME":"DELETEME",
"Q_DESC":"",
…
"Q_TYPE":"LOCAL"
}
after the change
"Data":{
"EVENT_USER_ID":"colinpaice",
"EVENT_ORIGIN":"CONSOLE",
"EVENT_Q_MGR":"QMA",
"OBJECT_TYPE":"Q",
"Q_NAME":"DELETEME",
"Q_DESC":"change comment",
…
"ALTERATION_DATE":"2019-02-17",
"ALTERATION_TIME":"11.14.33",
…
"Q_TYPE":"LOCAL"
}
When I printed out the changed data, the first time ALTERATION_DATA and ALTERATION_TIME were both displayed. The second time, only ALTERATION_TIME was displayed. I thought this was a bug in my program. After checking my program, it was obvious… If I change the queue 10 minutes later – the ALTERATION_DATE does not change – so remember to report both of these, and not just the change values.
Great post, but do you know where can I find the format of the data part of a config event message? It looks like the data part varies depending on its type, 93F (create), 940 (change) or 941 (delete).
I have found the parameters of the changed object that are in clear text, eg. description, storage class, cf structure etc, but it’s a bit more triggy to find fx put enabled, get enabled, usage etc. which are really just a bit setting where x’0000′ means Yes and x’0001′ means No.
I can see from the data part, that the fields are prefixed with a length field so that it is possible to figure out how long the field is.
LikeLike
Hi,
One of the reasons why I wrote this code was because there is no easy way of processing the PCF data.
For example the data “OBJECT_TYPE”:”Q”.
There will be a structure ( integer) with a type of 1016. From grep 1016 /opt/mqm/inc/*.h I got
cmqcfc.h: #define MQIACF_OBJECT_TYPE 1016
but /opt/mqm/inc/cmqstrc.h has a function MQIACF_STR(value). You pass in the 1016 and it returns “MQIACF_OBJECT_TYPE”. Great!
Now you know it is an Object Type. You can use MQOT_STR() in cmqstrc.h to covert from the value (1) to “MQOT_Q”.
In practice you need a big select statement to pick the correct type, then the specific value.
In my python coded, I built a dictionary of (1016,1) ->MQOT_Q, (1016,2)-> MQOT_NAMELIST.
Perhaps I should create this mapping for people to make it easier.
regards
Colin
LikeLike