@@ -28,8 +28,11 @@ import (
2828)
2929
3030// var statusDummy = fmt.Sprintf("dummy")
31- var timeTravelWarningIssued = false
32- var persistenceWarningIssued = false
31+ var (
32+ timeTravelWarningIssued = false
33+ persistenceWarningIssued = false
34+ clearQBuf = make ([]byte , 32768 )
35+ )
3336
3437/*
3538This file defines types and constructors for elements related to status
@@ -129,7 +132,7 @@ func statusTimeDiff(now time.Time, d string, t string) int64 {
129132 if diff < - (60 * 5 ) { // Cannot have status from the future but allow a tiny amount of flex
130133 if ! timeTravelWarningIssued {
131134 logError ("Status reports appear to be from the future. Difference is approximately %d seconds. Check the TZ Offset value in the program configuration." , int64 (- diff ))
132- logDebug ("statusTimeDiff d:%s t:%s diff:%f tzoffset: %f err:%v\n " , d , t , diff , ci .tzOffsetSecs , err )
135+ logDebug ("statusTimeDiff d:%s t:%s diff:%f tzoffset: %f err:%v" , d , t , diff , ci .tzOffsetSecs , err )
133136 timeTravelWarningIssued = true
134137 }
135138 }
@@ -169,21 +172,77 @@ func statusTimeEpoch(d string, t string) int64 {
169172 return epoch
170173}
171174
172- func clearQ (hObj ibmmq.MQObject ) {
175+ func clearMsgWithoutTruncation (hObj ibmmq.MQObject ) (* ibmmq.MQMD , int , error ) {
176+ var err error
177+ var md * ibmmq.MQMD
178+
179+ traceEntry ("clearMsgWithoutTruncation" )
180+
181+ msgLen := 0
182+ for trunc := true ; trunc ; {
183+ // Now get the response. Reset the MD and GMO on each iteration to ensure we don't get mixed up
184+ // with anything that gets modified (like the CCSID) even on failed/truncated GETs.
185+ md = ibmmq .NewMQMD ()
186+ gmo := ibmmq .NewMQGMO ()
187+ gmo .Options = ibmmq .MQGMO_NO_SYNCPOINT
188+ gmo .Options |= ibmmq .MQGMO_FAIL_IF_QUIESCING
189+ gmo .Options |= ibmmq .MQGMO_NO_WAIT
190+ gmo .Options |= ibmmq .MQGMO_CONVERT
191+
192+ logTrace ("clearQWithoutTruncation: Trying MQGET with clearQBuffer size %d " , len (clearQBuf ))
193+ msgLen , err = hObj .Get (md , gmo , clearQBuf )
194+ if err != nil {
195+ mqreturn := err .(* ibmmq.MQReturn )
196+ if mqreturn .MQCC != ibmmq .MQCC_OK && mqreturn .MQRC == ibmmq .MQRC_TRUNCATED_MSG_FAILED && len (clearQBuf ) < maxBufSize {
197+ // Double the size, apart from capping it at 100MB
198+ clearQBuf = append (clearQBuf , make ([]byte , len (clearQBuf ))... )
199+ if len (clearQBuf ) > maxBufSize {
200+ clearQBuf = clearQBuf [0 :maxBufSize ]
201+ }
202+ } else {
203+ traceExitF ("clearMsgWithoutTruncation" , 1 , "BufSize %d Error %v" , len (clearQBuf ), err )
204+ return md , msgLen , err
205+ }
206+ } else {
207+ trunc = false
208+ }
209+ }
210+
211+ traceExit ("clearMsgWithoutTruncation" , 0 )
212+ return md , msgLen , err
213+ }
214+
215+ func clearQ (hObj ibmmq.MQObject , usingReadAhead bool ) {
216+ var err error
217+ var getmqmd * ibmmq.MQMD
218+ // msgLen := 0
173219 p := 0
174220 buf := make ([]byte , 0 )
221+
222+ traceEntry ("clearQ" )
223+ logTrace ("clearQ: QueueName=%s readAhead=%v" , hObj .Name , usingReadAhead )
224+
175225 // Empty reply and publication destination queues in case any left over from previous runs.
176226 // Do it in batches if the messages are persistent. Which they shouldn't be, but you
177227 // never know.
178228 for ok := true ; ok ; {
179- getmqmd := ibmmq .NewMQMD ()
180- gmo := ibmmq .NewMQGMO ()
181- gmo .Options = ibmmq .MQGMO_SYNCPOINT_IF_PERSISTENT
182- gmo .Options |= ibmmq .MQGMO_FAIL_IF_QUIESCING
183- gmo .Options |= ibmmq .MQGMO_NO_WAIT
184- gmo .Options |= ibmmq .MQGMO_CONVERT
185- gmo .Options |= ibmmq .MQGMO_ACCEPT_TRUNCATED_MSG
186- _ , err := hObj .Get (getmqmd , gmo , buf )
229+ if ! usingReadAhead {
230+ getmqmd = ibmmq .NewMQMD ()
231+ gmo := ibmmq .NewMQGMO ()
232+ gmo .Options = ibmmq .MQGMO_SYNCPOINT_IF_PERSISTENT
233+ gmo .Options = ibmmq .MQGMO_NO_SYNCPOINT
234+ gmo .Options |= ibmmq .MQGMO_FAIL_IF_QUIESCING
235+ gmo .Options |= ibmmq .MQGMO_NO_WAIT
236+ gmo .Options |= ibmmq .MQGMO_CONVERT
237+ gmo .Options |= ibmmq .MQGMO_ACCEPT_TRUNCATED_MSG
238+ _ , err = hObj .Get (getmqmd , gmo , buf )
239+
240+ } else {
241+ // logDebug("Reverting to clearMsgWithoutTruncation")
242+ getmqmd , _ , err = clearMsgWithoutTruncation (hObj )
243+ }
244+
245+ // logDebug("clearQ: got message with err %v", err)
187246
188247 if err != nil && err .(* ibmmq.MQReturn ).MQCC == ibmmq .MQCC_FAILED {
189248 ok = false
@@ -196,6 +255,7 @@ func clearQ(hObj ibmmq.MQObject) {
196255 if err != nil {
197256 logError ("Problem committing removal of persistent messages: %v" , err )
198257 } else {
258+ logDebug ("Successful MQCMIT" )
199259 p = 0
200260 }
201261 }
@@ -205,15 +265,20 @@ func clearQ(hObj ibmmq.MQObject) {
205265 logWarn ("Response messages are unnecessarily persistent. Check the DEFPSIST value on the configured reply queues." )
206266 }
207267 }
268+
208269 }
209270
210271 // If we've not committed removal of a final batch of persistent messages, do it now.
211272 if p > 0 {
212273 err := hObj .GetHConn ().Cmit ()
213274 if err != nil {
214275 logError ("Problem committing removal of persistent messages: %v" , err )
276+ } else {
277+ logDebug ("Successful MQCMIT" )
278+
215279 }
216280 }
281+ traceExit ("clearQ" , 0 )
217282
218283 return
219284}
@@ -222,7 +287,7 @@ func statusClearReplyQ() {
222287 traceEntry ("statusClearReplyQ" )
223288 ci := getConnection (GetConnectionKey ())
224289
225- clearQ (ci .si .statusReplyQObj )
290+ clearQ (ci .si .statusReplyQObj , ci . si . statusReplyQReadAhead )
226291
227292 traceExit ("statusClearReplyQ" , 0 )
228293 return
@@ -316,7 +381,7 @@ func statusGetReply(correlId []byte) (*ibmmq.MQCFH, []byte, bool, error) {
316381 // command tries to use this replyQ.
317382 allDone = true
318383 if err .(* ibmmq.MQReturn ).MQRC != ibmmq .MQRC_NO_MSG_AVAILABLE {
319- logError ("StatusGetReply error : %v\n " , err )
384+ logError ("StatusGetReply error : %v" , err )
320385 }
321386 traceExitErr ("statusGetReply" , 3 , err )
322387 return nil , nil , allDone , err
0 commit comments