| 270 | } |
| 271 | |
| 272 | Block DDLQueryStatusInputStream::readImpl() |
| 273 | { |
| 274 | Block res; |
| 275 | bool all_hosts_finished = num_hosts_finished >= waiting_hosts.size(); |
| 276 | /// Seems like num_hosts_finished cannot be strictly greater than waiting_hosts.size() |
| 277 | assert(num_hosts_finished <= waiting_hosts.size()); |
| 278 | if (all_hosts_finished || timeout_exceeded) |
| 279 | { |
| 280 | bool throw_if_error_on_host = context->getSettingsRef().distributed_ddl_output_mode != DistributedDDLOutputMode::NEVER_THROW; |
| 281 | if (first_exception && throw_if_error_on_host) |
| 282 | throw Exception(*first_exception); |
| 283 | |
| 284 | return res; |
| 285 | } |
| 286 | |
| 287 | auto zookeeper = context->getZooKeeper(); |
| 288 | size_t try_number = 0; |
| 289 | |
| 290 | while (res.rows() == 0) |
| 291 | { |
| 292 | if (isCancelled()) |
| 293 | { |
| 294 | bool throw_if_error_on_host = context->getSettingsRef().distributed_ddl_output_mode != DistributedDDLOutputMode::NEVER_THROW; |
| 295 | if (first_exception && throw_if_error_on_host) |
| 296 | throw Exception(*first_exception); |
| 297 | |
| 298 | return res; |
| 299 | } |
| 300 | |
| 301 | if (timeout_seconds >= 0 && watch.elapsedSeconds() > timeout_seconds) |
| 302 | { |
| 303 | size_t num_unfinished_hosts = waiting_hosts.size() - num_hosts_finished; |
| 304 | size_t num_active_hosts = current_active_hosts.size(); |
| 305 | |
| 306 | constexpr const char * msg_format = "Watching task {} is executing longer than distributed_ddl_task_timeout (={}) seconds. " |
| 307 | "There are {} unfinished hosts ({} of them are currently active), " |
| 308 | "they are going to execute the query in background"; |
| 309 | if (throw_on_timeout) |
| 310 | throw Exception(ErrorCodes::TIMEOUT_EXCEEDED, msg_format, |
| 311 | node_path, timeout_seconds, num_unfinished_hosts, num_active_hosts); |
| 312 | |
| 313 | timeout_exceeded = true; |
| 314 | LOG_INFO(log, msg_format, node_path, timeout_seconds, num_unfinished_hosts, num_active_hosts); |
| 315 | |
| 316 | NameSet unfinished_hosts = waiting_hosts; |
| 317 | for (const auto & host_id : finished_hosts) |
| 318 | unfinished_hosts.erase(host_id); |
| 319 | |
| 320 | /// Query is not finished on the rest hosts, so fill the corresponding rows with NULLs. |
| 321 | MutableColumns columns = sample.cloneEmptyColumns(); |
| 322 | for (const String & host_id : unfinished_hosts) |
| 323 | { |
| 324 | auto [host, port] = parseHostAndPort(host_id); |
| 325 | size_t num = 0; |
| 326 | columns[num++]->insert(host); |
| 327 | if (by_hostname) |
| 328 | columns[num++]->insert(port); |
| 329 | columns[num++]->insert(Field{}); |
nothing calls this directly
no test coverage detected