Gate streaming exchange on OS_LINUX||OS_DARWIN, not unconditionally (keep FreeBSD/SunOS unsupported)

This commit is contained in:
Raúl Marín
2026-07-08 15:14:06 +02:00
parent ff89ccc8a9
commit 662ccad5a1
15 changed files with 77 additions and 1 deletions
+5
View File
@@ -2133,6 +2133,7 @@ try
stateless_worker_endpoint_ptr.reset();
});
#if defined(OS_LINUX) || defined(OS_DARWIN)
ExchangeConnectionsPtr exchange_connections_ptr = ExchangeConnections::instance();
std::vector<std::shared_ptr<ExchangeServer>> exchange_servers;
if (auto streaming_exchange_port = config().getUInt("distributed_query.streaming_exchange_port", 0))
@@ -2177,6 +2178,10 @@ try
exchange_server_ptr.reset();
}
});
#else
if (config().getUInt("distributed_query.streaming_exchange_port", 0))
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "ExchangeServer is not supported on this platform");
#endif
/// Set up caches.
@@ -130,6 +130,7 @@ namespace ServerSetting
namespace ErrorCodes
{
extern const int UNSUPPORTED_METHOD;
extern const int INVALID_SETTING_VALUE;
extern const int SUPPORT_IS_DISABLED;
}
@@ -235,6 +236,7 @@ QueryPlanOptimizationSettings::QueryPlanOptimizationSettings(
distributed_plan_default_shuffle_join_bucket_count = from[Setting::distributed_plan_default_shuffle_join_bucket_count];
distributed_plan_default_reader_bucket_count = from[Setting::distributed_plan_default_reader_bucket_count];
distributed_plan_optimize_exchanges = from[Setting::distributed_plan_optimize_exchanges];
#if defined(OS_LINUX) || defined(OS_DARWIN)
distributed_plan_force_exchange_kind = from[Setting::distributed_plan_force_exchange_kind].value;
if (!distributed_plan_force_exchange_kind.empty()
&& distributed_plan_force_exchange_kind != "Persisted"
@@ -242,6 +244,11 @@ QueryPlanOptimizationSettings::QueryPlanOptimizationSettings(
throw Exception(ErrorCodes::INVALID_SETTING_VALUE,
"Setting `distributed_plan_force_exchange_kind` must be empty, 'Persisted', or 'Streaming', got '{}'",
distributed_plan_force_exchange_kind);
#else
if (from[Setting::distributed_plan_force_exchange_kind].changed && from[Setting::distributed_plan_force_exchange_kind].value != "Persisted")
throw Exception(ErrorCodes::UNSUPPORTED_METHOD, "Only Persisted exchange is supported");
distributed_plan_force_exchange_kind = "Persisted";
#endif
distributed_plan_max_rows_to_broadcast = from[Setting::distributed_plan_max_rows_to_broadcast];
distributed_plan_force_shuffle_aggregation = from[Setting::distributed_plan_force_shuffle_aggregation];
distributed_aggregation_memory_efficient = from[Setting::distributed_aggregation_memory_efficient];
@@ -327,6 +334,7 @@ QueryPlanOptimizationSettings::QueryPlanOptimizationSettings(ContextPtr from)
max_parallel_replicas = std::min<size_t>(nodes, max_parallel_replicas);
}
#if defined(OS_LINUX) || defined(OS_DARWIN)
/// Auto-select the exchange kind when it is not forced: use Streaming only when its listener will
/// run (both the port and a listen host are configured), otherwise Persisted. This avoids planning
/// Streaming exchanges that would connect to a listener that was never started. A forced kind and
@@ -339,5 +347,6 @@ QueryPlanOptimizationSettings::QueryPlanOptimizationSettings(ContextPtr from)
&& !getMultipleValuesFromConfig(config, "distributed_query", "streaming_exchange_listen_host").empty();
distributed_plan_force_exchange_kind = streaming_listener_configured ? "Streaming" : "Persisted";
}
#endif
}
}
@@ -560,6 +560,7 @@ ExchangeLookupPtr createExchangeLookup(
return std::make_shared<AllKindsExchangeLookup>(exchanges_, persisted_exchanges, /*streaming_exchange_lookup=*/nullptr);
}
#if defined(OS_LINUX) || defined(OS_DARWIN)
auto streaming_exchange_port = context->getConfigRef().getUInt("distributed_query.streaming_exchange_port", 0);
if (streaming_exchange_port == 0)
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED,
@@ -588,6 +589,12 @@ ExchangeLookupPtr createExchangeLookup(
auto streaming_exchanges = createStreamingExchangeLookup(
query_id, ExchangeConnections::instance(), sources_with_ports);
return std::make_shared<AllKindsExchangeLookup>(exchanges_, persisted_exchanges, streaming_exchanges);
#else
UNUSED(exchange_stream_sources);
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED,
"Streaming exchanges are only supported on Linux and macOS; "
"use `distributed_plan_force_exchange_kind = 'Persisted'`");
#endif
}
@@ -631,10 +638,12 @@ void doExecuteTask(const DistributedQueryTaskDescription & task_description, Obj
LOG_TRACE(logger, "Task '{}' input exchange streams: [{}], output exchange streams: [{}]",
task.task_id, fmt::join(input_exchange_streams, ", "), fmt::join(output_exchange_streams, ", "));
#if defined(OS_LINUX) || defined(OS_DARWIN)
/// Release this task's pending streaming exchange connections on the worker when it ends. A
/// consumer that never connects (e.g. its query was cancelled) would otherwise leave them behind.
/// Only this task's output streams are dropped, so sibling tasks of the same query are unaffected.
SCOPE_EXIT_SAFE(ExchangeConnections::instance()->removePendingStreams(distributed_query_id, output_exchange_streams));
#endif
auto temporary_files = createTemporaryFilesLookup(
object_storage, object_storage_path, input_exchange_streams, output_exchange_streams);
@@ -1051,11 +1060,13 @@ public:
void cleanup() override
{
running_tasks.cancel();
#if defined(OS_LINUX) || defined(OS_DARWIN)
/// Drop any still-pending exchange connection slots that belong to this query
/// (the peer was cancelled or never arrived). Without this they would leak
/// FutureConnection/eventfd entries in the ExchangeConnections singleton for
/// the lifetime of the server.
ExchangeConnections::instance()->cleanupQuery(toString(unique_query_id));
#endif
}
protected:
@@ -1,3 +1,5 @@
#if defined(OS_LINUX) || defined(OS_DARWIN)
#include <mutex>
#include <Server/DistributedQuery/ExchangeConnections.h>
#include <Server/DistributedQuery/FutureConnection.h>
@@ -184,3 +186,5 @@ void ExchangeConnections::removePendingStreams(const String & query_id, const st
}
}
#endif
@@ -1,5 +1,7 @@
#pragma once
#if defined(OS_LINUX) || defined(OS_DARWIN)
#include <Client/Connection.h>
#include <base/defines.h>
#include <Poco/Net/StreamSocket.h>
@@ -88,3 +90,5 @@ private:
using ExchangeConnectionsPtr = std::shared_ptr<ExchangeConnections>;
}
#endif
@@ -1,3 +1,5 @@
#if defined(OS_LINUX) || defined(OS_DARWIN)
#include <Server/DistributedQuery/ExchangeServer.h>
#include <Server/DistributedQuery/ExchangeConnections.h>
#include <Server/DistributedQuery/StreamingExchangeProtocol.h>
@@ -260,3 +262,5 @@ void ExchangeServer::handleConnection(Poco::Net::StreamSocket socket, ExchangeCo
}
}
#endif
@@ -1,5 +1,7 @@
#pragma once
#if defined(OS_LINUX) || defined(OS_DARWIN)
#include <Server/DistributedQuery/ExchangeConnections.h>
#include <Server/TCPServerConnectionFactory.h>
#include <Poco/Net/ServerSocket.h>
@@ -41,3 +43,5 @@ private:
};
}
#endif
@@ -1,4 +1,7 @@
#include <Server/DistributedQuery/FutureConnection.h>
#if defined(OS_LINUX) || defined(OS_DARWIN)
#include <Common/Exception.h>
#include <Common/logger_useful.h>
#include <base/scope_guard.h>
@@ -125,3 +128,5 @@ void FutureConnection::notifyWaiter() const
}
}
#endif
@@ -1,5 +1,7 @@
#pragma once
#if defined(OS_LINUX) || defined(OS_DARWIN)
#include <Poco/Net/StreamSocket.h>
#include <Common/Logger.h>
#include <atomic>
@@ -58,3 +60,5 @@ private:
using FutureConnectionPtr = std::shared_ptr<FutureConnection>;
}
#endif
@@ -1,3 +1,5 @@
#if defined(OS_LINUX) || defined(OS_DARWIN)
#include <Server/DistributedQuery/StreamingExchangeLookup.h>
#include <Server/DistributedQuery/StreamingExchangeSink.h>
#include <Server/DistributedQuery/StreamingExchangeSource.h>
@@ -62,3 +64,5 @@ ExchangeLookupPtr createStreamingExchangeLookup(
}
}
#endif
@@ -1,5 +1,7 @@
#pragma once
#if defined(OS_LINUX) || defined(OS_DARWIN)
#include <Server/DistributedQuery/ExchangeConnections.h>
#include <Processors/QueryPlan/ExchangeLookup.h>
#include <QueryPipeline/DistributedPlanExecutor.h>
@@ -13,3 +15,5 @@ ExchangeLookupPtr createStreamingExchangeLookup(
const ExchangeStreamSources & exchange_stream_sources);
}
#endif
@@ -2,6 +2,8 @@
#include <memory>
#include <base/defines.h>
#if defined(OS_LINUX) || defined(OS_DARWIN)
#include <Server/DistributedQuery/StreamingExchangeSink.h>
#include <Server/DistributedQuery/StreamingExchangeProtocol.h>
#include <Processors/Transforms/AggregatingTransform.h>
@@ -444,3 +446,5 @@ void StreamingExchangeSink::markNoMoreDataNeeded()
}
}
#endif
@@ -1,5 +1,7 @@
#pragma once
#if defined(OS_LINUX) || defined(OS_DARWIN)
#include <Common/Logger.h>
#include <Core/Types.h>
#include <Processors/ISink.h>
@@ -87,3 +89,5 @@ private:
};
}
#endif
@@ -1,3 +1,5 @@
#if defined(OS_LINUX) || defined(OS_DARWIN)
#include <cstring>
#include <optional>
#include <string>
@@ -197,3 +199,5 @@ TEST(ExchangeConnectionsRendezvous, ConnectionAfterReleaseRejected)
EXPECT_TRUE(future->isReady());
EXPECT_ANY_THROW(future->getSocket());
}
#endif
+7 -1
View File
@@ -195,7 +195,13 @@ cp $SRC_PATH/config.d/storage_conf_backups.xml $DEST_SERVER_PATH/config.d/
cp $SRC_PATH/config.d/backups.xml $DEST_SERVER_PATH/config.d/
cp $SRC_PATH/config.d/filesystem_caches_path.xml $DEST_SERVER_PATH/config.d/
ln -sf $SRC_PATH/config.d/validate_tcp_client_information.xml $DEST_SERVER_PATH/config.d/
ln -sf $SRC_PATH/config.d/distributed_query.xml $DEST_SERVER_PATH/config.d/
# distributed_query.xml sets distributed_query.streaming_exchange_port, which the server rejects on
# platforms without the streaming exchange (only Linux and macOS support it); install it there only.
case "$(uname -s)" in
Linux|Darwin)
ln -sf $SRC_PATH/config.d/distributed_query.xml $DEST_SERVER_PATH/config.d/
;;
esac
ln -sf $SRC_PATH/config.d/zero_copy_destructive_operations.xml $DEST_SERVER_PATH/config.d/
ln -sf $SRC_PATH/config.d/handlers.yaml $DEST_SERVER_PATH/config.d/