dbms: Server: queries with several replicas: fixes [#METR-14410]

This commit is contained in:
Alexey Arno 2015-02-09 00:34:43 +03:00
parent 2e5d1041a1
commit 8c0a540350
3 changed files with 28 additions and 36 deletions

View File

@ -29,9 +29,6 @@ namespace DB
/// Получить пакет от какой-нибудь реплики. /// Получить пакет от какой-нибудь реплики.
Connection::Packet receivePacket(); Connection::Packet receivePacket();
/// Разорвать соединения к репликам
void disconnect();
/// Отменить запросы к репликам /// Отменить запросы к репликам
void sendCancel(); void sendCancel();

View File

@ -82,7 +82,7 @@ public:
if (!__sync_bool_compare_and_swap(&is_cancelled, false, true)) if (!__sync_bool_compare_and_swap(&is_cancelled, false, true))
return; return;
if (sent_query && !was_cancelled && !finished && !got_exception_from_replica) if (isInProgress() && !hasThrownException() && !was_cancelled)
{ {
std::string addresses = parallel_replicas->dumpAddresses(); std::string addresses = parallel_replicas->dumpAddresses();
LOG_TRACE(log, "(" + addresses + ") Cancelling query"); LOG_TRACE(log, "(" + addresses + ") Cancelling query");
@ -96,11 +96,12 @@ public:
~RemoteBlockInputStream() override ~RemoteBlockInputStream() override
{ {
/** Если прервались в середине цикла общения с репликами, то закрываем соединения, /** Если прервались в середине цикла общения с репликами, то прервываем
* чтобы они не остались висеть в рассихронизированном состоянии. * все соединения, затем читаем и пропускаем оставшиеся пакеты чтобы
* эти соединения не остались висеть в рассихронизированном состоянии.
*/ */
if (sent_query && !finished) if (isInProgress())
parallel_replicas->disconnect(); abort();
} }
protected: protected:
@ -156,7 +157,6 @@ protected:
case Protocol::Server::Exception: case Protocol::Server::Exception:
got_exception_from_replica = true; got_exception_from_replica = true;
abort();
packet.exception->rethrow(); packet.exception->rethrow();
break; break;
@ -177,7 +177,7 @@ protected:
*/ */
progressImpl(packet.progress); progressImpl(packet.progress);
if (!was_cancelled && !finished && isCancelled()) if (!was_cancelled && isInProgress() && isCancelled())
cancel(); cancel();
break; break;
@ -196,7 +196,6 @@ protected:
default: default:
got_unknown_packet_from_replica = true; got_unknown_packet_from_replica = true;
abort();
throw Exception("Unknown packet from server", ErrorCodes::UNKNOWN_PACKET_FROM_SERVER); throw Exception("Unknown packet from server", ErrorCodes::UNKNOWN_PACKET_FROM_SERVER);
} }
} }
@ -207,10 +206,11 @@ protected:
/** Если одно из: /** Если одно из:
* - ничего не начинали делать; * - ничего не начинали делать;
* - получили все пакеты до EndOfStream; * - получили все пакеты до EndOfStream;
* - получили с сервера эксепшен; * - получили с одной реплики эксепшен;
* - получили с одной реплики неизвестный пакет;
* - то больше читать ничего не нужно. * - то больше читать ничего не нужно.
*/ */
if (!sent_query || finished || got_exception_from_replica) if (!isInProgress() || hasThrownException())
return; return;
/** Если ещё прочитали не все данные, но они больше не нужны. /** Если ещё прочитали не все данные, но они больше не нужны.
@ -256,13 +256,10 @@ protected:
parallel_replicas = ext::make_unique<ParallelReplicas>(pool, parallel_replicas_settings); parallel_replicas = ext::make_unique<ParallelReplicas>(pool, parallel_replicas_settings);
} }
/** Если с одной реплики был получен пакет Exception или неизвестный пакет, отменить запросы на всех /** Отменить запросы на всех репликах. Читать и пропускать все оставшиеся пакеты
* остальных репликах. Читать и пропускать все оставшиеся пакеты до EndOfStream или Exception, чтобы * до EndOfStream или Exception, чтоб не было рассинхронизации в соединениях с репликами.
* не было рассинхронизации в соединениях с репликами.
*/ */
void abort() void abort()
{
if (got_exception_from_replica || got_unknown_packet_from_replica)
{ {
std::string addresses = parallel_replicas->dumpAddresses(); std::string addresses = parallel_replicas->dumpAddresses();
LOG_TRACE(log, "(" + addresses + ") Aborting query"); LOG_TRACE(log, "(" + addresses + ") Aborting query");
@ -270,6 +267,17 @@ protected:
parallel_replicas->sendCancel(); parallel_replicas->sendCancel();
(void) parallel_replicas->drain(); (void) parallel_replicas->drain();
} }
/// Возвращает true, если запрос отправлен, а ещё не выполнен.
bool isInProgress() const
{
return sent_query && !finished;
}
/// Возвращает true, если исключение было выкинуто.
bool hasThrownException() const
{
return got_exception_from_replica || got_unknown_packet_from_replica;
} }
private: private:

View File

@ -133,19 +133,6 @@ namespace DB
return packet; return packet;
} }
void ParallelReplicas::disconnect()
{
for (auto it = replica_map.begin(); it != replica_map.end(); ++it)
{
Connection * connection = it->second;
if (connection != nullptr)
{
connection->disconnect();
invalidateReplica(it);
}
}
}
void ParallelReplicas::sendCancel() void ParallelReplicas::sendCancel()
{ {
if (!sent_query || cancelled) if (!sent_query || cancelled)