Skip to content

Commit dd9fe35

Browse files
committed
Add qstatus and ability to access z/OS status
1 parent 86966e4 commit dd9fe35

File tree

7 files changed

+68
-9
lines changed

7 files changed

+68
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
=======
44
### November 2018
55
* Added functions to mqmetric to issue DISPLAY QSTATUS for additional stats
6+
* Added z/OS capability for minimal status
67

78
### October 2018
89
* Allow compilation against MQ v8

ibmmq/mqiMQCNO.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void setCCDTUrl(MQCNO *mqcno, PMQCHAR url, MQLONG length) {
4242
mqcno->CCDTUrlOffset = 0;
4343
mqcno->CCDTUrlPtr = NULL;
4444
mqcno->CCDTUrlLength = length;
45-
if (url != NULL) {
45+
if (url != NULL && length > 0) {
4646
mqcno->CCDTUrlPtr = url;
4747
}
4848
#else
@@ -181,7 +181,9 @@ func copyCNOtoC(mqcno *C.MQCNO, gocno *MQCNO) {
181181
// The CCDT URL option was introduced in MQ V9. To compile against older
182182
// versions of MQ, setting of it has been moved to a C function that can use
183183
// the pre-processor to decide whether it's needed.
184-
C.setCCDTUrl(mqcno, C.PMQCHAR(C.CString(gocno.CCDTUrl)), C.MQLONG(len(gocno.CCDTUrl)))
184+
if gocno.CCDTUrl != "" {
185+
C.setCCDTUrl(mqcno, C.PMQCHAR(C.CString(gocno.CCDTUrl)), C.MQLONG(len(gocno.CCDTUrl)))
186+
}
185187
return
186188
}
187189

ibmmq/mqiPCF.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,15 @@ func ReadPCFParameter(buf []byte) (*PCFParameter, int) {
252252
case C.MQCFT_GROUP:
253253
binary.Read(p, endian, &pcfParm.Parameter)
254254
binary.Read(p, endian, &pcfParm.ParameterCount)
255+
256+
case C.MQCFT_BYTE_STRING:
257+
// For now, the data is not actually stored anywhere as we don't need it
258+
// But we do need to know how to step over the field
259+
offset := int32(C.MQCFBS_STRUC_LENGTH_FIXED)
260+
binary.Read(p, endian, &pcfParm.Parameter)
261+
binary.Read(p, endian, &pcfParm.stringLength)
262+
p.Next(int(pcfParm.strucLength - offset))
263+
255264
default:
256265
fmt.Println("mqiPCF.go: Unknown PCF type ", pcfParm.Type)
257266
// Skip the remains of this structure, assuming it really is

mqmetric/channel.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ func collectChannelStatus(pattern string, instanceType int32) error {
199199
buf = make([]byte, 0)
200200

201201
cfh := ibmmq.NewMQCFH()
202+
cfh.Version = ibmmq.MQCFH_VERSION_3
203+
cfh.Type = ibmmq.MQCFT_COMMAND_XR
202204

203205
// Can allow all the other fields to default
204206
cfh.Command = ibmmq.MQCMD_INQUIRE_CHANNEL_STATUS

mqmetric/discover.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,9 @@ func discoverClasses(metaPrefix string) error {
137137

138138
// Have to know the starting point for the topic that tells about classes
139139
if metaPrefix == "" {
140-
rootTopic = "$SYS/MQ/INFO/QMGR/" + qMgr.Name + "/Monitor/METADATA/CLASSES"
140+
rootTopic = "$SYS/MQ/INFO/QMGR/" + resolvedQMgrName + "/Monitor/METADATA/CLASSES"
141141
} else {
142-
rootTopic = metaPrefix + "/INFO/QMGR/" + qMgr.Name + "/Monitor/METADATA/CLASSES"
142+
rootTopic = metaPrefix + "/INFO/QMGR/" + resolvedQMgrName + "/Monitor/METADATA/CLASSES"
143143
}
144144
sub, err = subscribe(rootTopic)
145145
if err == nil {
@@ -296,6 +296,11 @@ func discoverStats(metaPrefix string) error {
296296
// Start with an empty set of information about the available stats
297297
Metrics.Classes = make(map[int]*MonClass)
298298

299+
// Allow us to proceed on z/OS even though it does not support pub/sub resources
300+
if metaPrefix == "" && platform == ibmmq.MQPL_ZOS {
301+
return nil
302+
}
303+
299304
// Then get the list of CLASSES
300305
err = discoverClasses(metaPrefix)
301306

@@ -418,6 +423,8 @@ func inquireObjects(objectPatternsList string, objectType int32) ([]string, erro
418423
putmqmd.Report = ibmmq.MQRO_PASS_DISCARD_AND_EXPIRY
419424

420425
cfh := ibmmq.NewMQCFH()
426+
cfh.Version = ibmmq.MQCFH_VERSION_3
427+
cfh.Type = ibmmq.MQCFT_COMMAND_XR
421428

422429
// Can allow all the other fields to default
423430
cfh.Command = command
@@ -572,6 +579,10 @@ func ProcessPublications() error {
572579
var elementidx int
573580
var value int64
574581

582+
if platform == ibmmq.MQPL_ZOS {
583+
return nil
584+
}
585+
575586
// Keep reading all available messages until queue is empty. Don't
576587
// do a GET-WAIT; just immediate removals.
577588
cnt := 0

mqmetric/mqif.go

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,17 @@ import (
2828
"fmt"
2929

3030
"github.com/ibm-messaging/mq-golang/ibmmq"
31+
"strings"
3132
)
3233

3334
var (
34-
qMgr ibmmq.MQQueueManager
35-
cmdQObj ibmmq.MQObject
36-
replyQObj ibmmq.MQObject
37-
statusReplyQObj ibmmq.MQObject
38-
getBuffer = make([]byte, 32768)
35+
qMgr ibmmq.MQQueueManager
36+
cmdQObj ibmmq.MQObject
37+
replyQObj ibmmq.MQObject
38+
statusReplyQObj ibmmq.MQObject
39+
getBuffer = make([]byte, 32768)
40+
platform int32
41+
resolvedQMgrName string
3942

4043
qmgrConnected = false
4144
queuesOpened = false
@@ -78,6 +81,29 @@ func InitConnection(qMgrName string, replyQ string, cc *ConnectionConfig) error
7881
qmgrConnected = true
7982
}
8083

84+
if err == nil {
85+
mqod := ibmmq.NewMQOD()
86+
openOptions := ibmmq.MQOO_INQUIRE + ibmmq.MQOO_FAIL_IF_QUIESCING
87+
88+
mqod.ObjectType = ibmmq.MQOT_Q_MGR
89+
mqod.ObjectName = ""
90+
91+
qMgrObject, err := qMgr.Open(mqod, openOptions)
92+
93+
if err == nil {
94+
selectors := []int32{ibmmq.MQCA_Q_MGR_NAME,
95+
ibmmq.MQIA_PLATFORM}
96+
97+
intAttrs, charAttrs, err := qMgrObject.Inq(selectors, 1, 48)
98+
99+
if err == nil {
100+
resolvedQMgrName = strings.TrimSpace(string(charAttrs[0:48]))
101+
platform = intAttrs[0]
102+
}
103+
104+
}
105+
}
106+
81107
// MQOPEN of the COMMAND QUEUE
82108
if err == nil {
83109
mqod := ibmmq.NewMQOD()

mqmetric/queue.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const (
4141
ATTR_Q_OPPROCS = "output_handles"
4242
ATTR_Q_QTIME_SHORT = "qtime_short"
4343
ATTR_Q_QTIME_LONG = "qtime_long"
44+
ATTR_Q_DEPTH = "depth"
4445
)
4546

4647
var QueueStatus StatusSet
@@ -70,6 +71,11 @@ func QueueInitAttributes() {
7071
QueueStatus.Attributes[attr] = newStatusAttribute(attr, "Input Handles", ibmmq.MQIA_OPEN_INPUT_COUNT)
7172
attr = ATTR_Q_OPPROCS
7273
QueueStatus.Attributes[attr] = newStatusAttribute(attr, "Input Handles", ibmmq.MQIA_OPEN_OUTPUT_COUNT)
74+
// Usually we get the QDepth from published resources, But on z/OS we can get it from the QSTATUS response
75+
if platform == ibmmq.MQPL_ZOS {
76+
attr = ATTR_Q_DEPTH
77+
QueueStatus.Attributes[attr] = newStatusAttribute(attr, "Queue Depth", ibmmq.MQIA_CURRENT_Q_DEPTH)
78+
}
7379

7480
attr = ATTR_Q_QTIME_SHORT
7581
QueueStatus.Attributes[attr] = newStatusAttribute(attr, "Queue Time Short", ibmmq.MQIACF_Q_TIME_INDICATOR)
@@ -156,6 +162,8 @@ func collectQueueStatus(pattern string, instanceType int32) error {
156162
buf = make([]byte, 0)
157163

158164
cfh := ibmmq.NewMQCFH()
165+
cfh.Version = ibmmq.MQCFH_VERSION_3
166+
cfh.Type = ibmmq.MQCFT_COMMAND_XR
159167

160168
// Can allow all the other fields to default
161169
cfh.Command = ibmmq.MQCMD_INQUIRE_Q_STATUS

0 commit comments

Comments
 (0)