@@ -12,6 +12,7 @@ package mqjms
12
12
import (
13
13
"fmt"
14
14
"strconv"
15
+ "sync"
15
16
16
17
"github.com/ibm-messaging/mq-golang-jms20/jms20subset"
17
18
ibmmq "github.com/ibm-messaging/mq-golang/v5/ibmmq"
@@ -21,6 +22,7 @@ import (
21
22
// connection to an IBM MQ queue manager.
22
23
type ContextImpl struct {
23
24
qMgr ibmmq.MQQueueManager
25
+ ctxLock * sync.Mutex // Mutex to synchronize MQRC calls to the queue manager
24
26
sessionMode int
25
27
receiveBufferSize int
26
28
sendCheckCount int
@@ -65,6 +67,11 @@ func (ctx ContextImpl) CreateConsumer(dest jms20subset.Destination) (jms20subset
65
67
// receive messages that match the specified selector from the given Destination.
66
68
func (ctx ContextImpl ) CreateConsumerWithSelector (dest jms20subset.Destination , selector string ) (jms20subset.JMSConsumer , jms20subset.JMSException ) {
67
69
70
+ // Lock the context while we are making calls to the queue manager so that it
71
+ // doesn't conflict with the finalizer we use (below) to delete unused MessageHandles.
72
+ ctx .ctxLock .Lock ()
73
+ defer ctx .ctxLock .Unlock ()
74
+
68
75
// First validate the selector string format (we don't make use of it at
69
76
// runtime until the receive is called)
70
77
if selector != "" {
@@ -118,6 +125,11 @@ func (ctx ContextImpl) CreateConsumerWithSelector(dest jms20subset.Destination,
118
125
// an application can look at messages without removing them.
119
126
func (ctx ContextImpl ) CreateBrowser (dest jms20subset.Destination ) (jms20subset.QueueBrowser , jms20subset.JMSException ) {
120
127
128
+ // Lock the context while we are making calls to the queue manager so that it
129
+ // doesn't conflict with the finalizer we use (below) to delete unused MessageHandles.
130
+ ctx .ctxLock .Lock ()
131
+ defer ctx .ctxLock .Unlock ()
132
+
121
133
// Set up the necessary objects to open the queue
122
134
mqod := ibmmq .NewMQOD ()
123
135
var openOptions int32
@@ -165,6 +177,11 @@ func (ctx ContextImpl) CreateBrowser(dest jms20subset.Destination) (jms20subset.
165
177
// CreateTextMessage is a JMS standard mechanism for creating a TextMessage.
166
178
func (ctx ContextImpl ) CreateTextMessage () jms20subset.TextMessage {
167
179
180
+ // Lock the context while we are making calls to the queue manager so that it
181
+ // doesn't conflict with the finalizer we use (below) to delete unused MessageHandles.
182
+ ctx .ctxLock .Lock ()
183
+ defer ctx .ctxLock .Unlock ()
184
+
168
185
var bodyStr * string
169
186
thisMsgHandle := createMsgHandle (ctx .qMgr )
170
187
@@ -198,6 +215,11 @@ func createMsgHandle(qMgr ibmmq.MQQueueManager) ibmmq.MQMessageHandle {
198
215
// and initialise it with the chosen text string.
199
216
func (ctx ContextImpl ) CreateTextMessageWithString (txt string ) jms20subset.TextMessage {
200
217
218
+ // Lock the context while we are making calls to the queue manager so that it
219
+ // doesn't conflict with the finalizer we use (below) to delete unused MessageHandles.
220
+ ctx .ctxLock .Lock ()
221
+ defer ctx .ctxLock .Unlock ()
222
+
201
223
thisMsgHandle := createMsgHandle (ctx .qMgr )
202
224
203
225
msg := & TextMessageImpl {
@@ -213,6 +235,11 @@ func (ctx ContextImpl) CreateTextMessageWithString(txt string) jms20subset.TextM
213
235
// CreateBytesMessage is a JMS standard mechanism for creating a BytesMessage.
214
236
func (ctx ContextImpl ) CreateBytesMessage () jms20subset.BytesMessage {
215
237
238
+ // Lock the context while we are making calls to the queue manager so that it
239
+ // doesn't conflict with the finalizer we use (below) to delete unused MessageHandles.
240
+ ctx .ctxLock .Lock ()
241
+ defer ctx .ctxLock .Unlock ()
242
+
216
243
var thisBodyBytes * []byte
217
244
thisMsgHandle := createMsgHandle (ctx .qMgr )
218
245
@@ -227,6 +254,11 @@ func (ctx ContextImpl) CreateBytesMessage() jms20subset.BytesMessage {
227
254
// CreateBytesMessageWithBytes is a JMS standard mechanism for creating a BytesMessage.
228
255
func (ctx ContextImpl ) CreateBytesMessageWithBytes (bytes []byte ) jms20subset.BytesMessage {
229
256
257
+ // Lock the context while we are making calls to the queue manager so that it
258
+ // doesn't conflict with the finalizer we use (below) to delete unused MessageHandles.
259
+ ctx .ctxLock .Lock ()
260
+ defer ctx .ctxLock .Unlock ()
261
+
230
262
thisMsgHandle := createMsgHandle (ctx .qMgr )
231
263
232
264
return & BytesMessageImpl {
@@ -240,6 +272,11 @@ func (ctx ContextImpl) CreateBytesMessageWithBytes(bytes []byte) jms20subset.Byt
240
272
// Commit confirms all messages that were sent under this transaction.
241
273
func (ctx ContextImpl ) Commit () jms20subset.JMSException {
242
274
275
+ // Lock the context while we are making calls to the queue manager so that it
276
+ // doesn't conflict with the finalizer we use (below) to delete unused MessageHandles.
277
+ ctx .ctxLock .Lock ()
278
+ defer ctx .ctxLock .Unlock ()
279
+
243
280
var retErr jms20subset.JMSException
244
281
245
282
if (ibmmq.MQQueueManager {}) != ctx .qMgr {
@@ -294,6 +331,11 @@ func (ctx ContextImpl) Commit() jms20subset.JMSException {
294
331
// Rollback releases all messages that were sent under this transaction.
295
332
func (ctx ContextImpl ) Rollback () jms20subset.JMSException {
296
333
334
+ // Lock the context while we are making calls to the queue manager so that it
335
+ // doesn't conflict with the finalizer we use (below) to delete unused MessageHandles.
336
+ ctx .ctxLock .Lock ()
337
+ defer ctx .ctxLock .Unlock ()
338
+
297
339
var retErr jms20subset.JMSException
298
340
299
341
if (ibmmq.MQQueueManager {}) != ctx .qMgr {
@@ -321,6 +363,12 @@ func (ctx ContextImpl) Close() {
321
363
ctx .Rollback ()
322
364
323
365
if (ibmmq.MQQueueManager {}) != ctx .qMgr {
366
+
367
+ // Lock the context while we are making calls to the queue manager so that it
368
+ // doesn't conflict with the finalizer we use (below) to delete unused MessageHandles.
369
+ ctx .ctxLock .Lock ()
370
+ defer ctx .ctxLock .Unlock ()
371
+
324
372
ctx .qMgr .Disc ()
325
373
}
326
374
0 commit comments