Skip to content

Commit 67a70ac

Browse files
authored
Merge pull request #66 from ibm-messaging/qstatus
Qstatus
2 parents 6eb2358 + b429947 commit 67a70ac

File tree

11 files changed

+487
-42
lines changed

11 files changed

+487
-42
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Changelog
22

33
=======
4+
### November 2018
5+
* Added functions to mqmetric to issue DISPLAY QSTATUS for additional stats
6+
* Added z/OS capability for minimal status
7+
48
### October 2018
59
* Allow compilation against MQ v8
610

README.md

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,58 @@ This repository demonstrates how you can call IBM MQ from applications written i
44

55
> **NOTICE**: Please ensure that you use a dependency management tool such as [dep](https://github.com/golang/dep) or [Glide](http://glide.sh/), and add a specific version dependency.
66
7-
This repository previously contained sample programs that exported MQ statistics to some monitoring packages. These have now been moved to a new [GitHub repository called mq-metric-samples](https://github.com/ibm-messaging/mq-metric-samples).
7+
This repository previously contained sample programs that exported MQ statistics to
8+
some monitoring packages. These have now been moved to a
9+
new [GitHub repository called mq-metric-samples](https://github.com/ibm-messaging/mq-metric-samples).
810

9-
A minimum level of MQ V8 is required to build these packages.
10-
However, note that the monitoring data published by the queue manager is not available before MQ V9.
11+
A minimum level of MQ V8 is required to build these packages. However, note that
12+
the monitoring data published by the queue manager is not available before MQ V9.
1113

1214
## Health Warning
1315

14-
This package is provided as-is with no guarantees of support or updates. There are also no guarantees of compatibility with any future versions of the package; the API is subject to change based on any feedback.
16+
This package is provided as-is with no guarantees of support or updates. There are
17+
also no guarantees of compatibility with any future versions of the package; the API
18+
is subject to change based on any feedback. Versioned releases are made in this repository
19+
to assist with using stable APIs.
1520

1621
## MQI Description
1722

1823
The ibmmq directory contains a Go package, exposing an MQI-like interface.
1924

20-
The intention is to give an API that is more natural for Go programmers than the common procedural MQI. For example, fixed length string arrays from the C API such as MQCHAR48 are represented by the native Go string type. Conversion between these types is handled within the ibmmq package itself, removing the need for Go programmers to know about it.
25+
The intention is to give an API that is more natural for Go programmers than the
26+
common procedural MQI. For example, fixed length string arrays from the C API such
27+
as MQCHAR48 are represented by the native Go string type. Conversion between these
28+
types is handled within the ibmmq package itself, removing the need for Go programmers
29+
to know about it.
2130

22-
A short program in the samples/mqitest directory gives an example of using this interface, to put and get messages and to subscribe to a topic.
31+
A short program in the samples/mqitest directory gives an example of using this interface,
32+
to put and get messages and to subscribe to a topic.
2333

2434
The mqmetric directory contains functions to help monitoring programs access MQ status and
2535
statistics. This package is not needed for general application programs.
2636

27-
Feedback on the utility of this package, thoughts about whether it should be changed or extended are welcomed.
28-
2937
## Using the package
3038

31-
To use code in this repository, you will need to be able to build Go applications, and have a copy of MQ installed to build against. It uses cgo to access the MQI C structures and definitions. It assumes that MQ has been installed in the default location on a Linux platform (`/opt/mqm`) but you can easily change the cgo directives in the source files if necessary.
39+
To use code in this repository, you will need to be able to build Go applications, and
40+
have a copy of MQ installed to build against. It uses cgo to access the MQI C
41+
structures and definitions. It assumes that MQ has been installed in the default
42+
location (on a Linux platform this would be `/opt/mqm`) but this can be changed
43+
with environment variables if necessary.
3244

33-
Some Windows capability is also included. This has been tested with Go 1.10 compiler, which now permits standard Windows paths (eg including spaces) so the CGO directives can point at the normal MQ install path.
45+
Windows compatibility is also included. This has been tested with Go 1.10 compiler,
46+
which now permits standard Windows paths (eg including spaces) so the CGO directives
47+
can point at the normal MQ install path.
3448

3549
## Getting started
3650

37-
If you are unfamiliar with Go, the following steps can help create a working environment with source code in a suitable tree. Initial setup tends to be platform-specific, but subsequent steps are independent of the platform.
51+
If you are unfamiliar with Go, the following steps can help create a working environment
52+
with source code in a suitable tree. Initial setup tends to be platform-specific,
53+
but subsequent steps are independent of the platform.
3854

3955
### Linux
4056

41-
* Install the Go runtime and compiler. On Linux, the packaging may vary but a typical directory for the code is `/usr/lib/golang`.
57+
* Install the Go runtime and compiler. On Linux, the packaging may vary but a typical
58+
directory for the code is `/usr/lib/golang`.
4259

4360
* Create a working directory. For example, ```mkdir $HOME/gowork```
4461

@@ -81,6 +98,14 @@ set CC=x86_64-w64-mingw32-gcc.exe
8198

8299
`git clone https://github.com/ibm-messaging/mq-golang.git src/github.com/ibm-messaging/mq-golang`
83100

101+
* If you have not installed MQ libraries into the default location, then set environment variables
102+
for the C compiler to recognise those directories. For example,
103+
104+
```
105+
export CGO_CFLAGS="-I/my/mq/dir/inc"
106+
export CGO_LDFLAGS="-I/my/mq/dir/lib64"
107+
```
108+
84109
* Compile the `ibmmq` component:
85110

86111
`go install ./src/github.com/ibm-messaging/mq-golang/ibmmq`
@@ -89,9 +114,11 @@ set CC=x86_64-w64-mingw32-gcc.exe
89114

90115
`go install ./src/github.com/ibm-messaging/mq-golang/mqmetric`
91116

92-
* Follow the instructions in the [mq-metric-samples repository](https://github.com/ibm-messaging/mq-metric-samples) to compile the sample programs you are interested in.
117+
* Sample programs can be compiled in this way
118+
119+
`go build -o bin/mqitest ./src/github.com/ibm-messaging/mq-golang/samples/mqitest/*.go`
93120

94-
At this point, you should have a compiled copy of the code in `$GOPATH/bin`.
121+
At this point, you should have a compiled copy of the program in `$GOPATH/bin`.
95122

96123
## Limitations
97124

@@ -111,11 +138,16 @@ See [CHANGELOG](CHANGELOG.md) in this directory.
111138

112139
## Issues and Contributions
113140

114-
For feedback and issues relating specifically to this package, please use the [GitHub issue tracker](https://github.com/ibm-messaging/mq-golang/issues).
141+
Feedback on the utility of this package, thoughts about whether it should be changed
142+
or extended are welcomed.
143+
144+
For feedback and issues relating specifically to this package, please use
145+
the [GitHub issue tracker](https://github.com/ibm-messaging/mq-golang/issues).
115146

116-
Contributions to this package can be accepted under the terms of the IBM Contributor License Agreement,
117-
found in the [CLA file](CLA.md) of this repository. When submitting a pull request, you must include a statement stating
118-
you accept the terms in the CLA.
147+
Contributions to this package can be accepted under the terms of the IBM Contributor
148+
License Agreement, found in the [CLA file](CLA.md) of this repository. When
149+
submitting a pull request, you must include a statement stating you accept the terms
150+
in the CLA.
119151

120152
## Copyright
121153

ibmmq/mqi.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ the particular MQRC or MQCC values.
1616
1717
The build directives assume the default MQ installation path
1818
which is in /opt/mqm (Linux) and c:\Program Files\IBM\MQ (Windows).
19-
These would need to be changed in this file if you use a
20-
non-default path.
19+
If you use a non-default path for the installation, you can set
20+
environment variables CGO_CFLAGS and CGO_LDFLAGS to reference those
21+
directories.
2122
*/
2223
package ibmmq
2324

2425
/*
25-
Copyright (c) IBM Corporation 2016
26+
Copyright (c) IBM Corporation 2016, 2018
2627
2728
Licensed under the Apache License, Version 2.0 (the "License");
2829
you may not use this file except in compliance with the License.

ibmmq/mqiMQCNO.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package ibmmq
22

33
/*
4-
Copyright (c) IBM Corporation 2016
4+
Copyright (c) IBM Corporation 2016,2018
55
66
Licensed under the Apache License, Version 2.0 (the "License");
77
you may not use this file except in compliance with the License.
@@ -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: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package ibmmq
22

33
/*
4-
Copyright (c) IBM Corporation 2016
4+
Copyright (c) IBM Corporation 2016,2018
55
66
Licensed under the Apache License, Version 2.0 (the "License");
77
you may not use this file except in compliance with the License.
@@ -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: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const (
5353
)
5454

5555
var ChannelStatus StatusSet
56-
var attrsInit = false
56+
var chlAttrsInit = false
5757
var channelsSeen map[string]bool
5858

5959
/*
@@ -65,7 +65,7 @@ text. The elements can be expanded later; just trying to give a starting point
6565
for now.
6666
*/
6767
func ChannelInitAttributes() {
68-
if attrsInit {
68+
if chlAttrsInit {
6969
return
7070
}
7171
ChannelStatus.Attributes = make(map[string]*StatusAttribute)
@@ -98,7 +98,7 @@ func ChannelInitAttributes() {
9898
attr = ATTR_CHL_STATUS_SQUASH
9999
ChannelStatus.Attributes[attr] = newStatusAttribute(attr, "Channel Status - Simplified", ibmmq.MQIACH_CHANNEL_STATUS)
100100
ChannelStatus.Attributes[attr].squash = true
101-
attrsInit = true
101+
chlAttrsInit = true
102102
}
103103

104104
// If we need to list the channels that match a pattern. Not needed for
@@ -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
@@ -252,7 +254,7 @@ func collectChannelStatus(pattern string, instanceType int32) error {
252254
if cfh.Reason != ibmmq.MQRC_NONE {
253255
continue
254256
}
255-
key := parseData(instanceType, cfh, replyBuf[offset:datalen])
257+
key := parseChlData(instanceType, cfh, replyBuf[offset:datalen])
256258
if key != "" {
257259
channelsSeen[key] = true
258260
}
@@ -263,7 +265,7 @@ func collectChannelStatus(pattern string, instanceType int32) error {
263265
}
264266

265267
// Given a PCF response message, parse it to extract the desired statistics
266-
func parseData(instanceType int32, cfh *ibmmq.MQCFH, buf []byte) string {
268+
func parseChlData(instanceType int32, cfh *ibmmq.MQCFH, buf []byte) string {
267269
var elem *ibmmq.PCFParameter
268270

269271
chlName := ""

mqmetric/discover.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ var Metrics AllMetrics
9090

9191
var qList []string
9292

93+
func GetDiscoveredQueues() []string {
94+
return qList
95+
}
96+
9397
/*
9498
DiscoverAndSubscribe does all the work of finding the
9599
different resources available from a queue manager and
@@ -133,9 +137,9 @@ func discoverClasses(metaPrefix string) error {
133137

134138
// Have to know the starting point for the topic that tells about classes
135139
if metaPrefix == "" {
136-
rootTopic = "$SYS/MQ/INFO/QMGR/" + qMgr.Name + "/Monitor/METADATA/CLASSES"
140+
rootTopic = "$SYS/MQ/INFO/QMGR/" + resolvedQMgrName + "/Monitor/METADATA/CLASSES"
137141
} else {
138-
rootTopic = metaPrefix + "/INFO/QMGR/" + qMgr.Name + "/Monitor/METADATA/CLASSES"
142+
rootTopic = metaPrefix + "/INFO/QMGR/" + resolvedQMgrName + "/Monitor/METADATA/CLASSES"
139143
}
140144
sub, err = subscribe(rootTopic)
141145
if err == nil {
@@ -292,6 +296,11 @@ func discoverStats(metaPrefix string) error {
292296
// Start with an empty set of information about the available stats
293297
Metrics.Classes = make(map[int]*MonClass)
294298

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+
295304
// Then get the list of CLASSES
296305
err = discoverClasses(metaPrefix)
297306

@@ -349,7 +358,7 @@ func discoverQueues(monitoredQueues string) error {
349358
var err error
350359
qList, err = inquireObjects(monitoredQueues, ibmmq.MQOT_Q)
351360
if len(qList) > 0 {
352-
fmt.Printf("Monitoring Queues: %v\n", qList)
361+
//fmt.Printf("Monitoring Queues: %v\n", qList)
353362
if err != nil {
354363
// fmt.Printf("Queue Discovery: %v\n", err)
355364
}
@@ -414,6 +423,8 @@ func inquireObjects(objectPatternsList string, objectType int32) ([]string, erro
414423
putmqmd.Report = ibmmq.MQRO_PASS_DISCARD_AND_EXPIRY
415424

416425
cfh := ibmmq.NewMQCFH()
426+
cfh.Version = ibmmq.MQCFH_VERSION_3
427+
cfh.Type = ibmmq.MQCFT_COMMAND_XR
417428

418429
// Can allow all the other fields to default
419430
cfh.Command = command
@@ -568,6 +579,10 @@ func ProcessPublications() error {
568579
var elementidx int
569580
var value int64
570581

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

mqmetric/mqif.go

Lines changed: 33 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,31 @@ 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+
// Don't need the qMgrObject any more
104+
qMgrObject.Close(0)
105+
106+
}
107+
}
108+
81109
// MQOPEN of the COMMAND QUEUE
82110
if err == nil {
83111
mqod := ibmmq.NewMQOD()

0 commit comments

Comments
 (0)