yugabyte-ycql-driver 3.2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +13 -0
  3. data/README.md +242 -0
  4. data/ext/cassandra_murmur3/cassandra_murmur3.c +178 -0
  5. data/ext/cassandra_murmur3/extconf.rb +2 -0
  6. data/lib/cassandra/address_resolution.rb +36 -0
  7. data/lib/cassandra/address_resolution/policies.rb +2 -0
  8. data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +56 -0
  9. data/lib/cassandra/address_resolution/policies/none.rb +35 -0
  10. data/lib/cassandra/aggregate.rb +123 -0
  11. data/lib/cassandra/argument.rb +51 -0
  12. data/lib/cassandra/attr_boolean.rb +33 -0
  13. data/lib/cassandra/auth.rb +100 -0
  14. data/lib/cassandra/auth/providers.rb +17 -0
  15. data/lib/cassandra/auth/providers/password.rb +65 -0
  16. data/lib/cassandra/cassandra_logger.rb +80 -0
  17. data/lib/cassandra/cluster.rb +331 -0
  18. data/lib/cassandra/cluster/client.rb +1612 -0
  19. data/lib/cassandra/cluster/connection_pool.rb +78 -0
  20. data/lib/cassandra/cluster/connector.rb +372 -0
  21. data/lib/cassandra/cluster/control_connection.rb +962 -0
  22. data/lib/cassandra/cluster/failed_connection.rb +35 -0
  23. data/lib/cassandra/cluster/metadata.rb +142 -0
  24. data/lib/cassandra/cluster/options.rb +145 -0
  25. data/lib/cassandra/cluster/registry.rb +284 -0
  26. data/lib/cassandra/cluster/schema.rb +405 -0
  27. data/lib/cassandra/cluster/schema/cql_type_parser.rb +112 -0
  28. data/lib/cassandra/cluster/schema/fetchers.rb +1627 -0
  29. data/lib/cassandra/cluster/schema/fqcn_type_parser.rb +175 -0
  30. data/lib/cassandra/cluster/schema/partitioners.rb +21 -0
  31. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +45 -0
  32. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +37 -0
  33. data/lib/cassandra/cluster/schema/partitioners/random.rb +37 -0
  34. data/lib/cassandra/cluster/schema/replication_strategies.rb +21 -0
  35. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +102 -0
  36. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +39 -0
  37. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +44 -0
  38. data/lib/cassandra/column.rb +66 -0
  39. data/lib/cassandra/column_container.rb +326 -0
  40. data/lib/cassandra/compression.rb +69 -0
  41. data/lib/cassandra/compression/compressors/lz4.rb +73 -0
  42. data/lib/cassandra/compression/compressors/snappy.rb +69 -0
  43. data/lib/cassandra/custom_data.rb +53 -0
  44. data/lib/cassandra/driver.rb +260 -0
  45. data/lib/cassandra/errors.rb +784 -0
  46. data/lib/cassandra/execution/info.rb +69 -0
  47. data/lib/cassandra/execution/options.rb +267 -0
  48. data/lib/cassandra/execution/profile.rb +153 -0
  49. data/lib/cassandra/execution/profile_manager.rb +71 -0
  50. data/lib/cassandra/execution/trace.rb +192 -0
  51. data/lib/cassandra/executors.rb +113 -0
  52. data/lib/cassandra/function.rb +156 -0
  53. data/lib/cassandra/function_collection.rb +85 -0
  54. data/lib/cassandra/future.rb +794 -0
  55. data/lib/cassandra/host.rb +102 -0
  56. data/lib/cassandra/index.rb +118 -0
  57. data/lib/cassandra/keyspace.rb +473 -0
  58. data/lib/cassandra/listener.rb +87 -0
  59. data/lib/cassandra/load_balancing.rb +121 -0
  60. data/lib/cassandra/load_balancing/policies.rb +20 -0
  61. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +172 -0
  62. data/lib/cassandra/load_balancing/policies/round_robin.rb +141 -0
  63. data/lib/cassandra/load_balancing/policies/token_aware.rb +149 -0
  64. data/lib/cassandra/load_balancing/policies/white_list.rb +100 -0
  65. data/lib/cassandra/materialized_view.rb +92 -0
  66. data/lib/cassandra/null_logger.rb +56 -0
  67. data/lib/cassandra/protocol.rb +102 -0
  68. data/lib/cassandra/protocol/coder.rb +1085 -0
  69. data/lib/cassandra/protocol/cql_byte_buffer.rb +418 -0
  70. data/lib/cassandra/protocol/cql_protocol_handler.rb +448 -0
  71. data/lib/cassandra/protocol/request.rb +41 -0
  72. data/lib/cassandra/protocol/requests/auth_response_request.rb +51 -0
  73. data/lib/cassandra/protocol/requests/batch_request.rb +117 -0
  74. data/lib/cassandra/protocol/requests/credentials_request.rb +51 -0
  75. data/lib/cassandra/protocol/requests/execute_request.rb +122 -0
  76. data/lib/cassandra/protocol/requests/options_request.rb +39 -0
  77. data/lib/cassandra/protocol/requests/prepare_request.rb +59 -0
  78. data/lib/cassandra/protocol/requests/query_request.rb +112 -0
  79. data/lib/cassandra/protocol/requests/register_request.rb +38 -0
  80. data/lib/cassandra/protocol/requests/startup_request.rb +49 -0
  81. data/lib/cassandra/protocol/requests/void_query_request.rb +24 -0
  82. data/lib/cassandra/protocol/response.rb +28 -0
  83. data/lib/cassandra/protocol/responses/already_exists_error_response.rb +50 -0
  84. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +36 -0
  85. data/lib/cassandra/protocol/responses/auth_success_response.rb +36 -0
  86. data/lib/cassandra/protocol/responses/authenticate_response.rb +36 -0
  87. data/lib/cassandra/protocol/responses/error_response.rb +142 -0
  88. data/lib/cassandra/protocol/responses/event_response.rb +30 -0
  89. data/lib/cassandra/protocol/responses/function_failure_error_response.rb +52 -0
  90. data/lib/cassandra/protocol/responses/prepared_result_response.rb +62 -0
  91. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +59 -0
  92. data/lib/cassandra/protocol/responses/read_failure_error_response.rb +71 -0
  93. data/lib/cassandra/protocol/responses/read_timeout_error_response.rb +61 -0
  94. data/lib/cassandra/protocol/responses/ready_response.rb +43 -0
  95. data/lib/cassandra/protocol/responses/result_response.rb +42 -0
  96. data/lib/cassandra/protocol/responses/rows_result_response.rb +39 -0
  97. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +73 -0
  98. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +70 -0
  99. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +37 -0
  100. data/lib/cassandra/protocol/responses/status_change_event_response.rb +39 -0
  101. data/lib/cassandra/protocol/responses/supported_response.rb +36 -0
  102. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +33 -0
  103. data/lib/cassandra/protocol/responses/unavailable_error_response.rb +58 -0
  104. data/lib/cassandra/protocol/responses/unprepared_error_response.rb +48 -0
  105. data/lib/cassandra/protocol/responses/void_result_response.rb +34 -0
  106. data/lib/cassandra/protocol/responses/write_failure_error_response.rb +73 -0
  107. data/lib/cassandra/protocol/responses/write_timeout_error_response.rb +63 -0
  108. data/lib/cassandra/protocol/v1.rb +326 -0
  109. data/lib/cassandra/protocol/v3.rb +358 -0
  110. data/lib/cassandra/protocol/v4.rb +478 -0
  111. data/lib/cassandra/reconnection.rb +49 -0
  112. data/lib/cassandra/reconnection/policies.rb +20 -0
  113. data/lib/cassandra/reconnection/policies/constant.rb +46 -0
  114. data/lib/cassandra/reconnection/policies/exponential.rb +79 -0
  115. data/lib/cassandra/result.rb +276 -0
  116. data/lib/cassandra/retry.rb +154 -0
  117. data/lib/cassandra/retry/policies.rb +21 -0
  118. data/lib/cassandra/retry/policies/default.rb +53 -0
  119. data/lib/cassandra/retry/policies/downgrading_consistency.rb +73 -0
  120. data/lib/cassandra/retry/policies/fallthrough.rb +39 -0
  121. data/lib/cassandra/session.rb +270 -0
  122. data/lib/cassandra/statement.rb +32 -0
  123. data/lib/cassandra/statements.rb +23 -0
  124. data/lib/cassandra/statements/batch.rb +146 -0
  125. data/lib/cassandra/statements/bound.rb +65 -0
  126. data/lib/cassandra/statements/prepared.rb +235 -0
  127. data/lib/cassandra/statements/simple.rb +118 -0
  128. data/lib/cassandra/statements/void.rb +38 -0
  129. data/lib/cassandra/table.rb +240 -0
  130. data/lib/cassandra/time.rb +103 -0
  131. data/lib/cassandra/time_uuid.rb +78 -0
  132. data/lib/cassandra/timestamp_generator.rb +37 -0
  133. data/lib/cassandra/timestamp_generator/simple.rb +38 -0
  134. data/lib/cassandra/timestamp_generator/ticking_on_duplicate.rb +58 -0
  135. data/lib/cassandra/trigger.rb +67 -0
  136. data/lib/cassandra/tuple.rb +131 -0
  137. data/lib/cassandra/types.rb +1704 -0
  138. data/lib/cassandra/udt.rb +443 -0
  139. data/lib/cassandra/util.rb +464 -0
  140. data/lib/cassandra/uuid.rb +110 -0
  141. data/lib/cassandra/uuid/generator.rb +212 -0
  142. data/lib/cassandra/version.rb +21 -0
  143. data/lib/datastax/cassandra.rb +47 -0
  144. data/lib/ycql.rb +842 -0
  145. metadata +243 -0
@@ -0,0 +1,78 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright DataStax, Inc.
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
+
19
+ module Cassandra
20
+ class Cluster
21
+ # @private
22
+ class ConnectionPool
23
+ include Enumerable
24
+
25
+ def initialize
26
+ @connections = []
27
+ @lock = ::Mutex.new
28
+ end
29
+
30
+ def add_connections(connections)
31
+ @lock.synchronize do
32
+ @connections.concat(connections)
33
+ connections.each do |connection|
34
+ connection.on_closed do
35
+ @lock.synchronize do
36
+ @connections.delete(connection)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def connected?
44
+ @lock.synchronize do
45
+ @connections.any?
46
+ end
47
+ end
48
+
49
+ def snapshot
50
+ @lock.synchronize do
51
+ @connections.dup
52
+ end
53
+ end
54
+
55
+ def random_connection
56
+ raise Errors::IOError, 'Not connected' unless connected?
57
+ @lock.synchronize do
58
+ @connections.sample
59
+ end
60
+ end
61
+
62
+ def size
63
+ @lock.synchronize do
64
+ @connections.size
65
+ end
66
+ end
67
+
68
+ def each_connection(&callback)
69
+ return self unless block_given?
70
+ raise Errors::IOError, 'Not connected' unless connected?
71
+ @lock.synchronize do
72
+ @connections.each(&callback)
73
+ end
74
+ end
75
+ alias each each_connection
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,372 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright DataStax, Inc.
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
+
19
+ module Cassandra
20
+ class Cluster
21
+ # @private
22
+ class Connector
23
+ include MonitorMixin
24
+
25
+ def initialize(logger,
26
+ io_reactor,
27
+ cluster_registry,
28
+ connection_options,
29
+ execution_options)
30
+ @logger = logger
31
+ @reactor = io_reactor
32
+ @registry = cluster_registry
33
+ @connection_options = connection_options
34
+ @execution_options = execution_options
35
+ @connections = ::Hash.new
36
+ @open_connections = ::Hash.new
37
+
38
+ mon_initialize
39
+ end
40
+
41
+ def connect(host)
42
+ synchronize do
43
+ open_connections = @open_connections[host]
44
+ if open_connections
45
+ connection = open_connections.shift
46
+ @open_connections.delete(host) if open_connections.empty?
47
+ return Ione::Future.resolved(connection)
48
+ end
49
+ end
50
+
51
+ f = do_connect(host)
52
+
53
+ f.on_failure do |error|
54
+ connection_error(host, error)
55
+ end
56
+
57
+ f.on_value do |connection|
58
+ connection.on_closed do |cause|
59
+ disconnected(host, cause)
60
+ end
61
+
62
+ connected(host)
63
+ end
64
+
65
+ f
66
+ end
67
+
68
+ def refresh_status(host)
69
+ if synchronize { @connections[host] }
70
+ @registry.host_up(host.ip)
71
+
72
+ return Future.resolved
73
+ end
74
+
75
+ @logger.debug("Checking if host #{host.ip} is up")
76
+ f = do_connect(host)
77
+
78
+ f.on_failure do |error|
79
+ connection_error(host, error)
80
+ end
81
+
82
+ f.on_value do |connection|
83
+ connection.on_closed do |cause|
84
+ disconnected(host, cause)
85
+ end
86
+
87
+ synchronize do
88
+ @open_connections[host] ||= []
89
+ @open_connections[host] << connection
90
+ end
91
+
92
+ timer = @reactor.schedule_timer(UNCLAIMED_TIMEOUT)
93
+ timer.on_value do
94
+ close = false
95
+
96
+ synchronize do
97
+ open_connections = @open_connections[host]
98
+ if open_connections
99
+ close = !open_connections.delete(connection).nil?
100
+ @open_connections.delete(host) if open_connections.empty?
101
+ end
102
+ end
103
+
104
+ connection.close if close
105
+ end
106
+
107
+ connected(host)
108
+ end
109
+
110
+ f
111
+ end
112
+
113
+ private
114
+
115
+ NO_CONNECTIONS = Ione::Future.resolved([])
116
+ UNCLAIMED_TIMEOUT = 5 # close unclaimed connections in five seconds
117
+
118
+ def do_connect(host)
119
+ @reactor.connect(host.ip.to_s,
120
+ @connection_options.port,
121
+ timeout: @connection_options.connect_timeout,
122
+ ssl: @connection_options.ssl) do |connection|
123
+ raise Errors::ClientError, 'Not connected, reactor stopped' unless connection
124
+
125
+ connection.to_io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY,
126
+ @connection_options.nodelay? ? 1 : 0)
127
+
128
+ Protocol::CqlProtocolHandler.new(connection,
129
+ @reactor,
130
+ @connection_options.protocol_version,
131
+ @connection_options.compressor,
132
+ @connection_options.heartbeat_interval,
133
+ @connection_options.idle_timeout,
134
+ @connection_options.requests_per_connection,
135
+ @connection_options.custom_type_handlers)
136
+ end.flat_map do |connection|
137
+ # connection is a CqlProtocolHandler
138
+ f = request_options(connection)
139
+ f = f.flat_map do |options|
140
+ compression = @connection_options.compression
141
+ supported_algorithms = options['COMPRESSION']
142
+
143
+ if compression && !supported_algorithms.include?(compression)
144
+ @logger.warn("Compression with #{compression.inspect} is not supported " \
145
+ "by host at #{host.ip}, supported algorithms are " \
146
+ "#{supported_algorithms.inspect}")
147
+ compression = nil
148
+ end
149
+
150
+ supported_cql_versions = options['CQL_VERSION']
151
+ cql_version = (supported_cql_versions && !supported_cql_versions.empty?) ?
152
+ supported_cql_versions.first :
153
+ '3.1.0'
154
+
155
+ startup_connection(host, connection, cql_version, compression)
156
+ end
157
+ f.fallback do |error|
158
+ case error
159
+ when Errors::ProtocolError
160
+ synchronize do
161
+ current_version = connection.protocol_version
162
+ if current_version > 1 && @connection_options.protocol_negotiable?
163
+ @logger.info("Host #{host.ip} doesn't support protocol version " \
164
+ "#{current_version}, downgrading")
165
+
166
+ # This is tricky. We want to try with the next lower protocol version.
167
+ # However, the connection_options used for all connections may have
168
+ # already been updated due to other node connection failures. So,
169
+ # it may already have a lower protocol-version than our current-1. We
170
+ # don't want to accidentally raise it, so we update it to the min
171
+ # of itself and current-1.
172
+ @connection_options.protocol_version =
173
+ [@connection_options.protocol_version, current_version - 1].min
174
+ do_connect(host)
175
+ else
176
+ Ione::Future.failed(error)
177
+ end
178
+ end
179
+ when Errors::TimeoutError
180
+ future = Ione::CompletableFuture.new
181
+ connection.close(error).on_complete do |_|
182
+ future.fail(error)
183
+ end
184
+ future
185
+ else
186
+ Ione::Future.failed(error)
187
+ end
188
+ end
189
+ end.fallback do |error|
190
+ case error
191
+ when Error
192
+ Ione::Future.failed(error)
193
+ else
194
+ e = Errors::IOError.new(error.message)
195
+ e.set_backtrace(error.backtrace)
196
+ Ione::Future.failed(e)
197
+ end
198
+ end
199
+ end
200
+
201
+ def startup_connection(host, connection, cql_version, compression)
202
+ connection.send_request(Protocol::StartupRequest.new(cql_version, compression),
203
+ @execution_options.timeout).flat_map do |r|
204
+ case r
205
+ when Protocol::AuthenticateResponse
206
+ if @connection_options.protocol_version == 1
207
+ credentials = @connection_options.credentials
208
+ if credentials
209
+ send_credentials(connection, credentials)
210
+ else
211
+ Ione::Future.failed(cannot_authenticate_error)
212
+ end
213
+ else
214
+ authenticator = @connection_options.create_authenticator(r.authentication_class, host)
215
+ if authenticator
216
+ challenge_response_cycle(connection, authenticator, authenticator.initial_response)
217
+ else
218
+ Ione::Future.failed(cannot_authenticate_error)
219
+ end
220
+ end
221
+ when Protocol::ReadyResponse
222
+ ::Ione::Future.resolved(connection)
223
+ when Protocol::ErrorResponse
224
+ ::Ione::Future.failed(
225
+ r.to_error(nil, VOID_STATEMENT, VOID_OPTIONS, EMPTY_LIST, :quorum, 0)
226
+ )
227
+ else
228
+ ::Ione::Future.failed(
229
+ Errors::InternalError.new("Unexpected response #{r.inspect}")
230
+ )
231
+ end
232
+ end
233
+ end
234
+
235
+ def cannot_authenticate_error
236
+ Errors::AuthenticationError.new(
237
+ 'Server requested authentication, but client was not configured to ' \
238
+ 'authenticate',
239
+ nil,
240
+ nil,
241
+ nil,
242
+ VOID_STATEMENT,
243
+ VOID_OPTIONS,
244
+ EMPTY_LIST,
245
+ :quorum,
246
+ 0
247
+ )
248
+ end
249
+
250
+ def request_options(connection)
251
+ connection.send_request(Protocol::OptionsRequest.new,
252
+ @execution_options.timeout).map do |r|
253
+ case r
254
+ when Protocol::SupportedResponse
255
+ r.options
256
+ when Protocol::ErrorResponse
257
+ raise r.to_error(nil, VOID_STATEMENT, VOID_OPTIONS, EMPTY_LIST, :quorum, 0)
258
+ else
259
+ raise Errors::InternalError, "Unexpected response #{r.inspect}"
260
+ end
261
+ end
262
+ end
263
+
264
+ def send_credentials(connection, credentials)
265
+ connection.send_request(Protocol::CredentialsRequest.new(credentials),
266
+ @execution_options.timeout).map do |r|
267
+ case r
268
+ when Protocol::ReadyResponse
269
+ connection
270
+ when Protocol::ErrorResponse
271
+ raise r.to_error(nil, VOID_STATEMENT, VOID_OPTIONS, EMPTY_LIST, :quorum, 0)
272
+ else
273
+ raise Errors::InternalError, "Unexpected response #{r.inspect}"
274
+ end
275
+ end
276
+ end
277
+
278
+ def challenge_response_cycle(connection, authenticator, token)
279
+ connection.send_request(Protocol::AuthResponseRequest.new(token),
280
+ @execution_options.timeout).flat_map do |r|
281
+ case r
282
+ when Protocol::AuthChallengeResponse
283
+ token = authenticator.challenge_response(r.token)
284
+ challenge_response_cycle(connection, authenticator, token)
285
+ when Protocol::AuthSuccessResponse
286
+ begin
287
+ authenticator.authentication_successful(r.token)
288
+ rescue
289
+ nil
290
+ end
291
+ ::Ione::Future.resolved(connection)
292
+ when Protocol::ErrorResponse
293
+ ::Ione::Future.failed(
294
+ r.to_error(nil, VOID_STATEMENT, VOID_OPTIONS, EMPTY_LIST, :quorum, 0)
295
+ )
296
+ else
297
+ ::Ione::Future.failed(
298
+ Errors::InternalError.new("Unexpected response #{r.inspect}")
299
+ )
300
+ end
301
+ end
302
+ end
303
+
304
+ def connected(host)
305
+ notify = false
306
+
307
+ synchronize do
308
+ connections = @connections[host]
309
+
310
+ if connections
311
+ @connections[host] = connections + 1
312
+ else
313
+ notify = true
314
+
315
+ @connections[host] = 1
316
+ end
317
+ end
318
+
319
+ @registry.host_up(host.ip) if notify
320
+
321
+ self
322
+ end
323
+
324
+ def disconnected(host, error)
325
+ notify = false
326
+
327
+ synchronize do
328
+ connections = @connections[host]
329
+
330
+ return self unless connections
331
+
332
+ connections -= 1
333
+
334
+ if connections == 0
335
+ notify = !error.nil?
336
+ @connections.delete(host)
337
+ else
338
+ @connections[host] = connections
339
+ end
340
+ end
341
+
342
+ @logger.debug("Host #{host.ip} closed connection (#{error.class.name}: " \
343
+ "#{error.message})") if error
344
+
345
+ if notify
346
+ @logger.warn("Host #{host.ip} closed all connections")
347
+ @registry.host_down(host.ip)
348
+ end
349
+
350
+ self
351
+ end
352
+
353
+ def connection_error(host, error)
354
+ notify = false
355
+
356
+ synchronize do
357
+ notify = !error.nil? && !@connections.key?(host)
358
+ end
359
+
360
+ @logger.debug("Host #{host.ip} refused connection (#{error.class.name}: " \
361
+ "#{error.message})")
362
+
363
+ if notify
364
+ @logger.warn("Host #{host.ip} refused all connections")
365
+ @registry.host_down(host.ip)
366
+ end
367
+
368
+ self
369
+ end
370
+ end
371
+ end
372
+ end