Skip to content

Commit f9bbbef

Browse files
authored
Merge pull request #70 from ibm-messaging/callback
Callback
2 parents 46f64a2 + a887947 commit f9bbbef

28 files changed

+1395
-221
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## December 2018 - v3.3.0
4+
* All relevant API calls now automatically set FAIL_IF_QUIESCING
5+
* Samples updated to use "defer" instead of just suggesting it
6+
* Add support for MQCB/MQCTL callback functions
7+
* Add support for MQBEGIN transaction management
8+
* Add Dead Letter Header parser
9+
310
## November 2018 - v3.2.0
411
* Added GetPlatform to mqmetric so it can be used as a label/tag in collectors
512
* Added sample programs demonstrating specific operations such as put/get of message

README.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,7 @@ At this point, you should have a compiled copy of the program in `$GOPATH/bin`.
123123

124124
## Limitations
125125

126-
Almost all of the MQI verbs are now available through the `ibmmq` package.
127-
Currently unavailable verbs include:
128-
129-
* MQCB/MQCTL
130-
131-
There are also no structure handlers for message headers such as MQRFH2 or MQDLH.
126+
All regular MQI verbs are now available through the `ibmmq` package.
132127

133128
## History
134129

ibmmq/mqi.go

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,13 @@ package ibmmq
5151
#include <string.h>
5252
#include <cmqc.h>
5353
#include <cmqxc.h>
54+
5455
*/
5556
import "C"
5657

5758
import (
5859
"encoding/binary"
60+
"io"
5961
"strings"
6062
"unsafe"
6163
)
@@ -119,6 +121,8 @@ func (e *MQReturn) Error() string {
119121
return mqstrerror(e.verb, C.MQLONG(e.MQCC), C.MQLONG(e.MQRC))
120122
}
121123

124+
var endian binary.ByteOrder // Used by structure formatters such as MQCFH
125+
122126
/*
123127
* Copy a Go string in "strings"
124128
* to a fixed-size C char array such as MQCHAR12
@@ -138,7 +142,7 @@ func setMQIString(a *C.char, v string, l int) {
138142
/*
139143
* The C.GoStringN function can return strings that include
140144
* NUL characters (which is not really what is expected for a C string-related
141-
* function). So we have a utility function to remove any trailing nulls
145+
* function). So we have a utility function to remove any trailing nulls and spaces
142146
*/
143147
func trimStringN(c *C.char, l C.int) string {
144148
var rc string
@@ -149,7 +153,7 @@ func trimStringN(c *C.char, l C.int) string {
149153
} else {
150154
rc = s[0:i]
151155
}
152-
return rc
156+
return strings.TrimSpace(rc)
153157
}
154158

155159
/*
@@ -219,6 +223,7 @@ func (x *MQQueueManager) Disc() error {
219223
var mqrc C.MQLONG
220224
var mqcc C.MQLONG
221225

226+
savedConn := x.hConn
222227
C.MQDISC(&x.hConn, &mqcc, &mqrc)
223228

224229
mqreturn := MQReturn{MQCC: int32(mqcc),
@@ -230,6 +235,8 @@ func (x *MQQueueManager) Disc() error {
230235
return &mqreturn
231236
}
232237

238+
cbRemoveConnection(savedConn)
239+
233240
return nil
234241
}
235242

@@ -248,7 +255,7 @@ func (x *MQQueueManager) Open(good *MQOD, goOpenOptions int32) (MQObject, error)
248255
}
249256

250257
copyODtoC(&mqod, good)
251-
mqOpenOptions = C.MQLONG(goOpenOptions)
258+
mqOpenOptions = C.MQLONG(goOpenOptions) | C.MQOO_FAIL_IF_QUIESCING
252259

253260
C.MQOPEN(x.hConn,
254261
(C.PMQVOID)(unsafe.Pointer(&mqod)),
@@ -288,6 +295,9 @@ func (object *MQObject) Close(goCloseOptions int32) error {
288295

289296
mqCloseOptions = C.MQLONG(goCloseOptions)
290297

298+
savedHConn := object.qMgr.hConn
299+
savedHObj := object.hObj
300+
291301
C.MQCLOSE(object.qMgr.hConn, &object.hObj, mqCloseOptions, &mqcc, &mqrc)
292302

293303
mqreturn := MQReturn{MQCC: int32(mqcc),
@@ -299,6 +309,7 @@ func (object *MQObject) Close(goCloseOptions int32) error {
299309
return &mqreturn
300310
}
301311

312+
cbRemoveHandle(savedHConn, savedHObj)
302313
return nil
303314

304315
}
@@ -373,6 +384,33 @@ func (subObject *MQObject) Subrq(gosro *MQSRO, action int32) error {
373384
return nil
374385
}
375386

387+
/*
388+
Begin is the function to start a two-phase XA transaction coordinated by MQ
389+
*/
390+
func (x *MQQueueManager) Begin(gobo *MQBO) error {
391+
var mqrc C.MQLONG
392+
var mqcc C.MQLONG
393+
var mqbo C.MQBO
394+
395+
copyBOtoC(&mqbo, gobo)
396+
397+
C.MQBEGIN(x.hConn, (C.PMQVOID)(unsafe.Pointer(&mqbo)), &mqcc, &mqrc)
398+
399+
copyBOfromC(&mqbo, gobo)
400+
401+
mqreturn := MQReturn{MQCC: int32(mqcc),
402+
MQRC: int32(mqrc),
403+
verb: "MQBEGIN",
404+
}
405+
406+
if mqcc != C.MQCC_OK {
407+
return &mqreturn
408+
}
409+
410+
return nil
411+
412+
}
413+
376414
/*
377415
Cmit is the function to commit an in-flight transaction
378416
*/
@@ -1214,15 +1252,42 @@ func (handle *MQMessageHandle) InqMP(goimpo *MQIMPO, gopd *MQPD, name string) (s
12141252
propertyValue = true
12151253
}
12161254
case C.MQTYPE_STRING:
1217-
propertyValue = C.GoStringN((*C.char)(propertyPtr), propertyLength)
1255+
propertyValue = C.GoStringN((*C.char)(propertyPtr), (C.int)(propertyLength))
12181256
case C.MQTYPE_BYTE_STRING:
12191257
ba := make([]byte, propertyLength)
12201258
p := (*C.MQBYTE)(propertyPtr)
1221-
copy(ba[:], C.GoBytes(unsafe.Pointer(p), propertyLength))
1259+
copy(ba[:], C.GoBytes(unsafe.Pointer(p), (C.int)(propertyLength)))
12221260
propertyValue = ba
12231261
case C.MQTYPE_NULL:
12241262
propertyValue = nil
12251263
}
12261264

12271265
return goimpo.ReturnedName, propertyValue, nil
12281266
}
1267+
1268+
/*
1269+
GetHeader returns a structure containing a parsed-out version of an MQI
1270+
message header such as the MQDLH (which is currently the only structure
1271+
supported). Other structures like the RFH2 could follow.
1272+
1273+
The caller of this function needs to cast the returned structure to the
1274+
specific type in order to reference the fields.
1275+
*/
1276+
func GetHeader(md *MQMD, buf []byte) (interface{}, int, error) {
1277+
switch md.Format {
1278+
case MQFMT_DEAD_LETTER_HEADER:
1279+
return getHeaderDLH(md, buf)
1280+
}
1281+
1282+
mqreturn := &MQReturn{MQCC: int32(MQCC_FAILED),
1283+
MQRC: int32(MQRC_FORMAT_NOT_SUPPORTED),
1284+
}
1285+
1286+
return nil, 0, mqreturn
1287+
}
1288+
1289+
func readStringFromFixedBuffer(r io.Reader, l int32) string {
1290+
tmpBuf := make([]byte, l)
1291+
binary.Read(r, endian, tmpBuf)
1292+
return strings.TrimSpace(string(tmpBuf))
1293+
}

ibmmq/mqiBO.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package ibmmq
2+
3+
/*
4+
Copyright (c) IBM Corporation 2018
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
Contributors:
19+
Mark Taylor - Initial Contribution
20+
*/
21+
22+
/*
23+
24+
#include <stdlib.h>
25+
#include <string.h>
26+
#include <cmqc.h>
27+
28+
*/
29+
import "C"
30+
31+
/*
32+
This module contains the Begin Options structure
33+
*/
34+
35+
type MQBO struct {
36+
Options int32
37+
}
38+
39+
func NewMQBO() *MQBO {
40+
bo := new(MQBO)
41+
bo.Options = int32(C.MQBO_NONE)
42+
return bo
43+
}
44+
45+
func copyBOtoC(mqbo *C.MQBO, gobo *MQBO) {
46+
setMQIString((*C.char)(&mqbo.StrucId[0]), "BO ", 4)
47+
mqbo.Version = 1
48+
mqbo.Options = C.MQLONG(gobo.Options)
49+
}
50+
51+
func copyBOfromC(mqbo *C.MQBO, gobo *MQBO) {
52+
gobo.Options = int32(mqbo.Options)
53+
return
54+
}

ibmmq/mqiCBC.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package ibmmq
2+
3+
/*
4+
Copyright (c) IBM Corporation 2018
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
Contributors:
19+
Mark Taylor - Initial Contribution
20+
*/
21+
22+
/*
23+
24+
#include <stdlib.h>
25+
#include <string.h>
26+
#include <cmqc.h>
27+
28+
*/
29+
import "C"
30+
31+
/*
32+
MQCBC is a structure containing the MQ Callback Context
33+
The CompCode and Reason in the C structure are not included here. They
34+
are set in an independent MQReturn structure passed to the callback. Similarly
35+
for the hObj
36+
*/
37+
type MQCBC struct {
38+
CallType int32
39+
CallbackArea interface{} // These fields are saved/restored in parent function
40+
ConnectionArea interface{}
41+
State int32
42+
DataLength int32
43+
BufferLength int32
44+
Flags int32
45+
ReconnectDelay int32
46+
}
47+
48+
/*
49+
NewMQCBC creates a MQCBC structure. There are no default values
50+
as the structure is created within MQ.
51+
*/
52+
func NewMQCBC() *MQCBC {
53+
cbc := new(MQCBC)
54+
return cbc
55+
}
56+
57+
/*
58+
Since we do not create the structure, there's no conversion for it into
59+
a C format
60+
*/
61+
func copyCBCtoC(mqcbc *C.MQCBC, gocbc *MQCBC) {
62+
return
63+
}
64+
65+
/*
66+
But we do need a conversion process from C
67+
*/
68+
func copyCBCfromC(mqcbc *C.MQCBC, gocbc *MQCBC) {
69+
gocbc.CallType = int32(mqcbc.CallType)
70+
gocbc.State = int32(mqcbc.State)
71+
gocbc.DataLength = int32(mqcbc.DataLength)
72+
gocbc.BufferLength = int32(mqcbc.BufferLength)
73+
gocbc.Flags = int32(mqcbc.Flags)
74+
gocbc.ReconnectDelay = int32(mqcbc.ReconnectDelay)
75+
// ConnectionArea and CallbackArea are restored outside this function
76+
77+
return
78+
}

0 commit comments

Comments
 (0)