stomp 1.3.1 → 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +15 -0
- data/README.rdoc +3 -1
- data/examples/conn11_hb1.rb +2 -2
- data/examples/examplogger.rb +306 -0
- data/examples/logexamp.rb +2 -2
- data/examples/logexamp_ssl.rb +2 -2
- data/lib/client/utils.rb +3 -1
- data/lib/connection/heartbeats.rb +20 -38
- data/lib/connection/netio.rb +22 -25
- data/lib/connection/utils.rb +22 -17
- data/lib/stomp/client.rb +29 -13
- data/lib/stomp/connection.rb +33 -14
- data/lib/stomp/constants.rb +81 -17
- data/lib/stomp/null_logger.rb +2 -0
- data/lib/stomp/version.rb +1 -1
- data/spec/connection_spec.rb +6 -1
- data/stomp.gemspec +11 -8
- data/test/test_anonymous.rb +2 -2
- data/test/test_urlogin.rb +3 -3
- metadata +61 -40
- checksums.yaml +0 -15
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
== 1.3.2 20131208
|
2
|
+
|
3
|
+
* Anon tests assigned unique class name.
|
4
|
+
* Fix TypeError on connect timeout with 1.8.x, 2.x.
|
5
|
+
* Complete revert to previous logger logic.
|
6
|
+
* start_timeout and tcp_nodelay parameters
|
7
|
+
* SSL Fix, revert not setting default ciphers.
|
8
|
+
* Copy hash params at init.
|
9
|
+
* Fix ssl => true for Ruby 1.9.x and 2.x.
|
10
|
+
* Expanded list of STOMP default SSL ciphers:
|
11
|
+
* Do not change caller's :hosts array
|
12
|
+
* Issue #78, again.
|
13
|
+
* Clean up logger interfacing.
|
14
|
+
* Fixes from RSpec testing
|
15
|
+
|
1
16
|
== 1.3.1 20131002
|
2
17
|
|
3
18
|
* Method calls to the logger object should check for that method first (#83)
|
data/README.rdoc
CHANGED
@@ -12,6 +12,7 @@ An implementation of the Stomp protocol for Ruby. See:
|
|
12
12
|
|
13
13
|
See _CHANGELOG.rdoc_ for details.
|
14
14
|
|
15
|
+
* Gem version 1.3.2. Miscellaneous fixes, see changelog for details.
|
15
16
|
* Gem version 1.3.1. Bugfix for logging.
|
16
17
|
* Gem version 1.3.0. Added ERROR frame raising as exception, added anonymous connections, miscellaneous other fixes.
|
17
18
|
* Gem version 1.2.16. Fixed Stomp::Client to expose its connection's host parameters.
|
@@ -66,7 +67,7 @@ See _CHANGELOG.rdoc_ for details.
|
|
66
67
|
# correct for your environment, expect unnecessary fail overs
|
67
68
|
:connread_timeout => 0, # Timeout during CONNECT for read of CONNECTED/ERROR, secs
|
68
69
|
:tcp_nodelay => true, # Turns on the TCP_NODELAY socket option; disables Nagle's algorithm
|
69
|
-
:start_timeout => 10, # Timeout around initialization
|
70
|
+
:start_timeout => 10, # Timeout around Stomp::Client initialization
|
70
71
|
}
|
71
72
|
|
72
73
|
# for client
|
@@ -150,4 +151,5 @@ The following people have contributed to Stomp:
|
|
150
151
|
* JP Hastings-Spital
|
151
152
|
* Glenn Roberts
|
152
153
|
* Ian Smith
|
154
|
+
* Orazio Cotroneo
|
153
155
|
|
data/examples/conn11_hb1.rb
CHANGED
@@ -6,11 +6,11 @@
|
|
6
6
|
#
|
7
7
|
if Kernel.respond_to?(:require_relative)
|
8
8
|
require_relative("./stomp11_common")
|
9
|
-
require_relative("./
|
9
|
+
require_relative("./examplogger")
|
10
10
|
else
|
11
11
|
$LOAD_PATH << File.dirname(__FILE__)
|
12
12
|
require "stomp11_common"
|
13
|
-
require "
|
13
|
+
require "examplogger"
|
14
14
|
end
|
15
15
|
include Stomp11Common
|
16
16
|
|
@@ -0,0 +1,306 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'logger' # use the standard Ruby logger .....
|
4
|
+
|
5
|
+
# == Example STOMP call back logger class.
|
6
|
+
#
|
7
|
+
# Optional callback methods:
|
8
|
+
#
|
9
|
+
# * on_connecting: connection starting
|
10
|
+
# * on_connected: successful connect
|
11
|
+
# * on_connectfail: unsuccessful connect (will usually be retried)
|
12
|
+
# * on_disconnect: successful disconnect
|
13
|
+
#
|
14
|
+
# * on_miscerr: on miscellaneous xmit/recv errors
|
15
|
+
#
|
16
|
+
# * on_publish: publish called
|
17
|
+
# * on_subscribe: subscribe called
|
18
|
+
# * on_unsubscribe: unsubscribe called
|
19
|
+
#
|
20
|
+
# * on_begin: begin called
|
21
|
+
# * on_ack: ack called
|
22
|
+
# * on_nack: nack called
|
23
|
+
# * on_commit: commit called
|
24
|
+
# * on_abort: abort called
|
25
|
+
#
|
26
|
+
# * on_receive: receive called and successful
|
27
|
+
#
|
28
|
+
# * on_ssl_connecting: SSL connection starting
|
29
|
+
# * on_ssl_connected: successful SSL connect
|
30
|
+
# * on_ssl_connectfail: unsuccessful SSL connect (will usually be retried)
|
31
|
+
#
|
32
|
+
# * on_hbread_fail: unsuccessful Heartbeat read
|
33
|
+
# * on_hbwrite_fail: unsuccessful Heartbeat write
|
34
|
+
# * on_hbfire: on any send or receive heartbeat
|
35
|
+
#
|
36
|
+
# All methods are optional, at the user's requirements.
|
37
|
+
#
|
38
|
+
# If a method is not provided, it is not called (of course.)
|
39
|
+
#
|
40
|
+
# IMPORTANT NOTE: in general, call back logging methods *SHOULD* not raise exceptions,
|
41
|
+
# otherwise the underlying STOMP connection may fail in mysterious ways.
|
42
|
+
#
|
43
|
+
# There are two useful exceptions to this rule for:
|
44
|
+
#
|
45
|
+
# * on_connectfail
|
46
|
+
# * on_ssl_connectfail
|
47
|
+
#
|
48
|
+
# These two methods can raise a Stomp::Errors::LoggerConnectionError. If this
|
49
|
+
# exception is raised, it is passed up the chain to the caller.
|
50
|
+
#
|
51
|
+
# Callback parameters: are a copy of the @parameters instance variable for
|
52
|
+
# the Stomp::Connection.
|
53
|
+
#
|
54
|
+
# A logger class may optionally inherit from the provided NullLogger
|
55
|
+
#
|
56
|
+
# # class Slogger < Stomp::NullLogger
|
57
|
+
#
|
58
|
+
class Slogger
|
59
|
+
|
60
|
+
# Initialize a new callback logger instance.
|
61
|
+
def initialize(init_parms = nil)
|
62
|
+
_init
|
63
|
+
@log.info("Logger initialization complete.")
|
64
|
+
end
|
65
|
+
|
66
|
+
def _init
|
67
|
+
@log = Logger::new(STDOUT) # User preference
|
68
|
+
@log.level = Logger::DEBUG # User preference
|
69
|
+
end
|
70
|
+
|
71
|
+
def marshal_dump
|
72
|
+
[]
|
73
|
+
end
|
74
|
+
|
75
|
+
def marshal_load(array)
|
76
|
+
_init
|
77
|
+
end
|
78
|
+
|
79
|
+
# Log connecting events
|
80
|
+
def on_connecting(parms)
|
81
|
+
begin
|
82
|
+
@log.debug "Connecting: #{info(parms)}"
|
83
|
+
rescue
|
84
|
+
@log.debug "Connecting oops"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Log connected events
|
89
|
+
def on_connected(parms)
|
90
|
+
begin
|
91
|
+
@log.debug "Connected: #{info(parms)}"
|
92
|
+
rescue
|
93
|
+
@log.debug "Connected oops"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Log connectfail events
|
98
|
+
def on_connectfail(parms)
|
99
|
+
begin
|
100
|
+
@log.debug "Connect Fail #{info(parms)}"
|
101
|
+
rescue
|
102
|
+
@log.debug "Connect Fail oops"
|
103
|
+
end
|
104
|
+
=begin
|
105
|
+
# An example LoggerConnectionError raise
|
106
|
+
@log.debug "Connect Fail, will raise"
|
107
|
+
raise Stomp::Error::LoggerConnectionError.new("quit from connect fail")
|
108
|
+
=end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Log disconnect events
|
112
|
+
def on_disconnect(parms)
|
113
|
+
begin
|
114
|
+
@log.debug "Disconnected #{info(parms)}"
|
115
|
+
rescue
|
116
|
+
@log.debug "Disconnected oops"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Log miscellaneous errors
|
121
|
+
def on_miscerr(parms, errstr)
|
122
|
+
begin
|
123
|
+
@log.debug "Miscellaneous Error #{info(parms)}"
|
124
|
+
@log.debug "Miscellaneous Error String #{errstr}"
|
125
|
+
rescue
|
126
|
+
@log.debug "Miscellaneous Error oops"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Log Subscribe
|
131
|
+
def on_subscribe(parms, headers)
|
132
|
+
begin
|
133
|
+
@log.debug "Subscribe Parms #{info(parms)}"
|
134
|
+
@log.debug "Subscribe Headers #{headers}"
|
135
|
+
rescue
|
136
|
+
@log.debug "Subscribe oops"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Log UnSubscribe
|
141
|
+
def on_unsubscribe(parms, headers)
|
142
|
+
begin
|
143
|
+
@log.debug "UnSubscribe Parms #{info(parms)}"
|
144
|
+
@log.debug "UnSubscribe Headers #{headers}"
|
145
|
+
rescue
|
146
|
+
@log.debug "UnSubscribe oops"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Log Publish
|
151
|
+
def on_publish(parms, message, headers)
|
152
|
+
begin
|
153
|
+
@log.debug "Publish Parms #{info(parms)}"
|
154
|
+
@log.debug "Publish Message #{message}"
|
155
|
+
@log.debug "Publish Headers #{headers}"
|
156
|
+
rescue
|
157
|
+
@log.debug "Publish oops"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Log Receive
|
162
|
+
def on_receive(parms, result)
|
163
|
+
begin
|
164
|
+
@log.debug "Receive Parms #{info(parms)}"
|
165
|
+
@log.debug "Receive Result #{result}"
|
166
|
+
rescue
|
167
|
+
@log.debug "Receive oops"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Log Begin
|
172
|
+
def on_begin(parms, headers)
|
173
|
+
begin
|
174
|
+
@log.debug "Begin Parms #{info(parms)}"
|
175
|
+
@log.debug "Begin Result #{headers}"
|
176
|
+
rescue
|
177
|
+
@log.debug "Begin oops"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Log Ack
|
182
|
+
def on_ack(parms, headers)
|
183
|
+
begin
|
184
|
+
@log.debug "Ack Parms #{info(parms)}"
|
185
|
+
@log.debug "Ack Result #{headers}"
|
186
|
+
rescue
|
187
|
+
@log.debug "Ack oops"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Log NAck
|
192
|
+
def on_nack(parms, headers)
|
193
|
+
begin
|
194
|
+
@log.debug "NAck Parms #{info(parms)}"
|
195
|
+
@log.debug "NAck Result #{headers}"
|
196
|
+
rescue
|
197
|
+
@log.debug "NAck oops"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Log Commit
|
202
|
+
def on_commit(parms, headers)
|
203
|
+
begin
|
204
|
+
@log.debug "Commit Parms #{info(parms)}"
|
205
|
+
@log.debug "Commit Result #{headers}"
|
206
|
+
rescue
|
207
|
+
@log.debug "Commit oops"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Log Abort
|
212
|
+
def on_abort(parms, headers)
|
213
|
+
begin
|
214
|
+
@log.debug "Abort Parms #{info(parms)}"
|
215
|
+
@log.debug "Abort Result #{headers}"
|
216
|
+
rescue
|
217
|
+
@log.debug "Abort oops"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Stomp 1.1+ - heart beat read (receive) failed.
|
222
|
+
def on_hbread_fail(parms, ticker_data = {})
|
223
|
+
begin
|
224
|
+
@log.debug "Hbreadf Parms #{info(parms)}"
|
225
|
+
@log.debug "Hbreadf Result #{ticker_data.inspect}"
|
226
|
+
rescue
|
227
|
+
@log.debug "Hbreadf oops"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# Stomp 1.1+ - heart beat send (transmit) failed.
|
232
|
+
def on_hbwrite_fail(parms, ticker_data = {})
|
233
|
+
begin
|
234
|
+
@log.debug "Hbwritef Parms #{info(parms)}"
|
235
|
+
@log.debug "Hbwritef Result #{ticker_data.inspect}"
|
236
|
+
rescue
|
237
|
+
@log.debug "Hbwritef oops"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Log SSL connection start.
|
242
|
+
def on_ssl_connecting(parms)
|
243
|
+
begin
|
244
|
+
@log.debug "SSL Connecting Parms #{info(parms)}"
|
245
|
+
rescue
|
246
|
+
@log.debug "SSL Connecting oops"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# Log a successful SSL connect.
|
251
|
+
def on_ssl_connected(parms)
|
252
|
+
begin
|
253
|
+
@log.debug "SSL Connected Parms #{info(parms)}"
|
254
|
+
rescue
|
255
|
+
@log.debug "SSL Connected oops"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# Log an unsuccessful SSL connect.
|
260
|
+
def on_ssl_connectfail(parms)
|
261
|
+
begin
|
262
|
+
@log.debug "SSL Connect Fail Parms #{info(parms)}"
|
263
|
+
@log.debug "SSL Connect Fail Exception #{parms[:ssl_exception]}, #{parms[:ssl_exception].message}"
|
264
|
+
rescue
|
265
|
+
@log.debug "SSL Connect Fail oops"
|
266
|
+
end
|
267
|
+
=begin
|
268
|
+
# An example LoggerConnectionError raise
|
269
|
+
@log.debug "SSL Connect Fail, will raise"
|
270
|
+
raise Stomp::Error::LoggerConnectionError.new("quit from SSL connect")
|
271
|
+
=end
|
272
|
+
end
|
273
|
+
|
274
|
+
# Log heart beat fires
|
275
|
+
def on_hbfire(parms, srind, firedata = {})
|
276
|
+
begin
|
277
|
+
@log.debug "HeartBeat Fire Parms #{info(parms)}"
|
278
|
+
@log.debug "HeartBeat Fire Send/Receive #{srind}"
|
279
|
+
rescue
|
280
|
+
@log.debug "HeartBeat Fire oops"
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
private
|
285
|
+
|
286
|
+
# Example information extract.
|
287
|
+
def info(parms)
|
288
|
+
#
|
289
|
+
# Available in the parms Hash:
|
290
|
+
# parms[:cur_host]
|
291
|
+
# parms[:cur_port]
|
292
|
+
# parms[:cur_login]
|
293
|
+
# parms[:cur_passcode]
|
294
|
+
# parms[:cur_ssl]
|
295
|
+
# parms[:cur_recondelay]
|
296
|
+
# parms[:cur_parseto]
|
297
|
+
# parms[:cur_conattempts]
|
298
|
+
# parms[:openstat]
|
299
|
+
#
|
300
|
+
# For the on_ssl_connectfail callback these are also available:
|
301
|
+
# parms[:ssl_exception]
|
302
|
+
#
|
303
|
+
"Host: #{parms[:cur_host]}, Port: #{parms[:cur_port]}, Login: #{parms[:cur_login]}, Passcode: #{parms[:cur_passcode]}, ssl: #{parms[:cur_ssl]}"
|
304
|
+
end
|
305
|
+
end # of class
|
306
|
+
|
data/examples/logexamp.rb
CHANGED
@@ -5,10 +5,10 @@ require 'stomp'
|
|
5
5
|
require 'logger' # for the 'local' logger
|
6
6
|
#
|
7
7
|
if Kernel.respond_to?(:require_relative)
|
8
|
-
require_relative("./
|
8
|
+
require_relative("./examplogger")
|
9
9
|
else
|
10
10
|
$LOAD_PATH << File.dirname(__FILE__)
|
11
|
-
require "
|
11
|
+
require "examplogger"
|
12
12
|
end
|
13
13
|
#
|
14
14
|
# == A STOMP::Connection program which uses the callback logging facility.
|
data/examples/logexamp_ssl.rb
CHANGED
@@ -5,10 +5,10 @@ require 'stomp'
|
|
5
5
|
require 'logger' # for the 'local' logger
|
6
6
|
#
|
7
7
|
if Kernel.respond_to?(:require_relative)
|
8
|
-
require_relative("./
|
8
|
+
require_relative("./examplogger")
|
9
9
|
else
|
10
10
|
$LOAD_PATH << File.dirname(__FILE__)
|
11
|
-
require "
|
11
|
+
require "examplogger"
|
12
12
|
end
|
13
13
|
#
|
14
14
|
# == A STOMP::Connection program which uses the callback logging facility.
|
data/lib/client/utils.rb
CHANGED
@@ -143,7 +143,9 @@ module Stomp
|
|
143
143
|
@replay_messages_by_txn = {}
|
144
144
|
|
145
145
|
@listener_map = Hash.new do |message|
|
146
|
-
@
|
146
|
+
unless @connection.slog(:on_miscerr, @connection.log_params, "Received unknown frame type: '#{message.command}'\n")
|
147
|
+
warn "Received unknown frame type: '#{message.command}'\n"
|
148
|
+
end
|
147
149
|
end
|
148
150
|
|
149
151
|
@listener_map[Stomp::CMD_MESSAGE] = lambda {|message| find_listener(message) }
|
@@ -100,22 +100,16 @@ module Stomp
|
|
100
100
|
sleep(slt)
|
101
101
|
next unless @socket # nil under some circumstances ??
|
102
102
|
curt = Time.now.to_f
|
103
|
-
|
104
|
-
if @logger && @logger.respond_to?(:on_hbfire)
|
105
|
-
@logger.on_hbfire(log_params, "send_fire", :curt => curt, :last_sleep => slt)
|
106
|
-
end
|
107
|
-
|
103
|
+
slog(:on_hbfire, log_params, "send_fire", :curt => curt, :last_sleep => slt)
|
108
104
|
delta = curt - @ls
|
109
105
|
# Be tolerant (minus), and always do this the first time through.
|
110
106
|
# Reintroduce logic removed in d922fa.
|
111
107
|
compval = (@hbsend_interval - (@hbsend_interval/5.0)) / 1000000.0
|
112
108
|
if delta > compval || first_time
|
113
109
|
first_time = false
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
:compval => compval)
|
118
|
-
end
|
110
|
+
slog(:on_hbfire, log_params, "send_heartbeat", :last_sleep => slt,
|
111
|
+
:curt => curt, :last_send => @ls, :delta => delta,
|
112
|
+
:compval => compval)
|
119
113
|
# Send a heartbeat
|
120
114
|
@transmit_semaphore.synchronize do
|
121
115
|
begin
|
@@ -126,10 +120,8 @@ module Stomp
|
|
126
120
|
@hbsend_count += 1
|
127
121
|
rescue Exception => sendex
|
128
122
|
@hb_sent = false # Set the warning flag
|
129
|
-
|
130
|
-
|
131
|
-
"exception" => sendex})
|
132
|
-
end
|
123
|
+
slog(:on_hbwrite_fail, log_params, {"ticker_interval" => sleeptime,
|
124
|
+
"exception" => sendex})
|
133
125
|
if @hbser
|
134
126
|
raise # Re-raise if user requested this, otherwise ignore
|
135
127
|
end
|
@@ -167,16 +159,12 @@ module Stomp
|
|
167
159
|
next unless @socket # nil under some circumstances ??
|
168
160
|
rdrdy = _is_ready?(@socket)
|
169
161
|
curt = Time.now.to_f
|
170
|
-
|
171
|
-
@logger.on_hbfire(log_params, "receive_fire", :curt => curt)
|
172
|
-
end
|
162
|
+
slog(:on_hbfire, log_params, "receive_fire", :curt => curt)
|
173
163
|
#
|
174
164
|
begin
|
175
165
|
delta = curt - @lr
|
176
166
|
if delta > sleeptime
|
177
|
-
|
178
|
-
@logger.on_hbfire(log_params, "receive_heartbeat", {})
|
179
|
-
end
|
167
|
+
slog(:on_hbfire, log_params, "receive_heartbeat", {})
|
180
168
|
# Client code could be off doing something else (that is, no reading of
|
181
169
|
# the socket has been requested by the caller). Try to handle that case.
|
182
170
|
lock = @read_semaphore.try_lock
|
@@ -203,24 +191,20 @@ module Stomp
|
|
203
191
|
@read_semaphore.unlock # Release read lock
|
204
192
|
@hb_received = false
|
205
193
|
read_fail_count += 1
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
"lock_fail_count" => lock_fail_count})
|
211
|
-
end
|
194
|
+
slog(:on_hbread_fail, log_params, {"ticker_interval" => sleeptime,
|
195
|
+
"read_fail_count" => read_fail_count,
|
196
|
+
"lock_fail" => false,
|
197
|
+
"lock_fail_count" => lock_fail_count})
|
212
198
|
end
|
213
199
|
else # try_lock failed
|
214
200
|
# Shrug. Could not get lock. Client must be actually be reading.
|
215
201
|
@hb_received = false
|
216
202
|
# But notify caller if possible
|
217
203
|
lock_fail_count += 1
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
"lock_fail_count" => lock_fail_count})
|
223
|
-
end
|
204
|
+
slog(:on_hbread_fail, log_params, {"ticker_interval" => sleeptime,
|
205
|
+
"read_fail_count" => read_fail_count,
|
206
|
+
"lock_fail" => true,
|
207
|
+
"lock_fail_count" => lock_fail_count})
|
224
208
|
end # of the try_lock
|
225
209
|
|
226
210
|
else # delta <= sleeptime
|
@@ -229,12 +213,10 @@ module Stomp
|
|
229
213
|
lock_fail_count = 0 # reset
|
230
214
|
end # of the if delta > sleeptime
|
231
215
|
rescue Exception => recvex
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
"lock_fail_count" => lock_fail_count})
|
237
|
-
end
|
216
|
+
slog(:on_hbread_fail, log_params, {"ticker_interval" => sleeptime,
|
217
|
+
"exception" => recvex,
|
218
|
+
"read_fail_count" => read_fail_count,
|
219
|
+
"lock_fail_count" => lock_fail_count})
|
238
220
|
fail_hard = true
|
239
221
|
end
|
240
222
|
# Do we want to attempt a retry?
|