org.elasticsearch.common.network.NetworkModule Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch - Open Source, Distributed, RESTful Search Engine
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.common.network;
import org.elasticsearch.action.support.replication.ReplicationTask;
import org.elasticsearch.cluster.routing.allocation.command.AllocateEmptyPrimaryAllocationCommand;
import org.elasticsearch.cluster.routing.allocation.command.AllocateReplicaAllocationCommand;
import org.elasticsearch.cluster.routing.allocation.command.AllocateStalePrimaryAllocationCommand;
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand;
import org.elasticsearch.cluster.routing.allocation.command.CancelAllocationCommand;
import org.elasticsearch.cluster.routing.allocation.command.MoveAllocationCommand;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.util.PageCacheRecycler;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.core.CheckedFunction;
import org.elasticsearch.http.HttpPreRequest;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.index.shard.PrimaryReplicaSyncer.ResyncTask;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.plugins.NetworkPlugin;
import org.elasticsearch.tasks.RawTaskStatus;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.tracing.Tracer;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.TransportInterceptor;
import org.elasticsearch.transport.TransportRequest;
import org.elasticsearch.transport.TransportRequestHandler;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xcontent.ParseField;
import org.elasticsearch.xcontent.XContentParser;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
/**
* A module to handle registering and binding all network related classes.
*/
public final class NetworkModule {
public static final String TRANSPORT_TYPE_KEY = "transport.type";
public static final String HTTP_TYPE_KEY = "http.type";
public static final String HTTP_TYPE_DEFAULT_KEY = "http.type.default";
public static final String TRANSPORT_TYPE_DEFAULT_KEY = "transport.type.default";
public static final Setting TRANSPORT_DEFAULT_TYPE_SETTING = Setting.simpleString(
TRANSPORT_TYPE_DEFAULT_KEY,
Property.NodeScope
);
public static final Setting HTTP_DEFAULT_TYPE_SETTING = Setting.simpleString(HTTP_TYPE_DEFAULT_KEY, Property.NodeScope);
public static final Setting HTTP_TYPE_SETTING = Setting.simpleString(HTTP_TYPE_KEY, Property.NodeScope);
public static final Setting TRANSPORT_TYPE_SETTING = Setting.simpleString(TRANSPORT_TYPE_KEY, Property.NodeScope);
private final Settings settings;
private static final List namedWriteables = new ArrayList<>();
private static final List namedXContents = new ArrayList<>();
static {
registerAllocationCommand(
CancelAllocationCommand::new,
CancelAllocationCommand::fromXContent,
CancelAllocationCommand.COMMAND_NAME_FIELD
);
registerAllocationCommand(
MoveAllocationCommand::new,
MoveAllocationCommand::fromXContent,
MoveAllocationCommand.COMMAND_NAME_FIELD
);
registerAllocationCommand(
AllocateReplicaAllocationCommand::new,
AllocateReplicaAllocationCommand::fromXContent,
AllocateReplicaAllocationCommand.COMMAND_NAME_FIELD
);
registerAllocationCommand(
AllocateEmptyPrimaryAllocationCommand::new,
AllocateEmptyPrimaryAllocationCommand::fromXContent,
AllocateEmptyPrimaryAllocationCommand.COMMAND_NAME_FIELD
);
registerAllocationCommand(
AllocateStalePrimaryAllocationCommand::new,
AllocateStalePrimaryAllocationCommand::fromXContent,
AllocateStalePrimaryAllocationCommand.COMMAND_NAME_FIELD
);
namedWriteables.add(new NamedWriteableRegistry.Entry(Task.Status.class, ReplicationTask.Status.NAME, ReplicationTask.Status::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(Task.Status.class, RawTaskStatus.NAME, RawTaskStatus::new));
namedWriteables.add(new NamedWriteableRegistry.Entry(Task.Status.class, ResyncTask.Status.NAME, ResyncTask.Status::new));
}
private final Map> transportFactories = new HashMap<>();
private final Map> transportHttpFactories = new HashMap<>();
private final List transportInterceptors = new ArrayList<>();
/**
* Creates a network module that custom networking classes can be plugged into.
* @param settings The settings for the node
*/
public NetworkModule(
Settings settings,
List plugins,
ThreadPool threadPool,
BigArrays bigArrays,
PageCacheRecycler pageCacheRecycler,
CircuitBreakerService circuitBreakerService,
NamedWriteableRegistry namedWriteableRegistry,
NamedXContentRegistry xContentRegistry,
NetworkService networkService,
HttpServerTransport.Dispatcher dispatcher,
BiConsumer perRequestThreadContext,
ClusterSettings clusterSettings,
Tracer tracer
) {
this.settings = settings;
for (NetworkPlugin plugin : plugins) {
Map> httpTransportFactory = plugin.getHttpTransports(
settings,
threadPool,
bigArrays,
pageCacheRecycler,
circuitBreakerService,
xContentRegistry,
networkService,
dispatcher,
perRequestThreadContext,
clusterSettings,
tracer
);
for (Map.Entry> entry : httpTransportFactory.entrySet()) {
registerHttpTransport(entry.getKey(), entry.getValue());
}
Map> transportFactory = plugin.getTransports(
settings,
threadPool,
pageCacheRecycler,
circuitBreakerService,
namedWriteableRegistry,
networkService
);
for (Map.Entry> entry : transportFactory.entrySet()) {
registerTransport(entry.getKey(), entry.getValue());
}
List transportInterceptors = plugin.getTransportInterceptors(
namedWriteableRegistry,
threadPool.getThreadContext()
);
for (TransportInterceptor interceptor : transportInterceptors) {
registerTransportInterceptor(interceptor);
}
}
}
/** Adds a transport implementation that can be selected by setting {@link #TRANSPORT_TYPE_KEY}. */
private void registerTransport(String key, Supplier factory) {
if (transportFactories.putIfAbsent(key, factory) != null) {
throw new IllegalArgumentException("transport for name: " + key + " is already registered");
}
}
/** Adds an http transport implementation that can be selected by setting {@link #HTTP_TYPE_KEY}. */
private void registerHttpTransport(String key, Supplier factory) {
if (transportHttpFactories.putIfAbsent(key, factory) != null) {
throw new IllegalArgumentException("transport for name: " + key + " is already registered");
}
}
// TODO: consider moving this to the ClusterModule
// this lives here instead of the more aptly named ClusterModule because it used to be used by the Transport client
/**
* Register an allocation command.
*
* @param reader the reader to read it from a stream
* @param parser the parser to read it from XContent
* @param commandName the names under which the command should be parsed. The {@link ParseField#getPreferredName()} is special because
* it is the name under which the command's reader is registered.
*/
private static void registerAllocationCommand(
Writeable.Reader reader,
CheckedFunction parser,
ParseField commandName
) {
namedXContents.add(new NamedXContentRegistry.Entry(AllocationCommand.class, commandName, parser));
namedWriteables.add(new NamedWriteableRegistry.Entry(AllocationCommand.class, commandName.getPreferredName(), reader));
}
public static List getNamedWriteables() {
return Collections.unmodifiableList(namedWriteables);
}
public static List getNamedXContents() {
return Collections.unmodifiableList(namedXContents);
}
public Supplier getHttpServerTransportSupplier() {
final String name;
if (HTTP_TYPE_SETTING.exists(settings)) {
name = HTTP_TYPE_SETTING.get(settings);
} else {
name = HTTP_DEFAULT_TYPE_SETTING.get(settings);
}
final Supplier factory = transportHttpFactories.get(name);
if (factory == null) {
throw new IllegalStateException("Unsupported http.type [" + name + "]");
}
return factory;
}
public Supplier getTransportSupplier() {
final String name;
if (TRANSPORT_TYPE_SETTING.exists(settings)) {
name = TRANSPORT_TYPE_SETTING.get(settings);
} else {
name = TRANSPORT_DEFAULT_TYPE_SETTING.get(settings);
}
final Supplier factory = transportFactories.get(name);
if (factory == null) {
throw new IllegalStateException("Unsupported transport.type [" + name + "]");
}
return factory;
}
/**
* Registers a new {@link TransportInterceptor}
*/
private void registerTransportInterceptor(TransportInterceptor interceptor) {
this.transportInterceptors.add(Objects.requireNonNull(interceptor, "interceptor must not be null"));
}
/**
* Returns a composite {@link TransportInterceptor} containing all registered interceptors
* @see #registerTransportInterceptor(TransportInterceptor)
*/
public TransportInterceptor getTransportInterceptor() {
return new CompositeTransportInterceptor(this.transportInterceptors);
}
static final class CompositeTransportInterceptor implements TransportInterceptor {
final List transportInterceptors;
private CompositeTransportInterceptor(List transportInterceptors) {
this.transportInterceptors = new ArrayList<>(transportInterceptors);
}
@Override
public TransportRequestHandler interceptHandler(
String action,
String executor,
boolean forceExecution,
TransportRequestHandler actualHandler
) {
for (TransportInterceptor interceptor : this.transportInterceptors) {
actualHandler = interceptor.interceptHandler(action, executor, forceExecution, actualHandler);
}
return actualHandler;
}
@Override
public AsyncSender interceptSender(AsyncSender sender) {
for (TransportInterceptor interceptor : this.transportInterceptors) {
sender = interceptor.interceptSender(sender);
}
return sender;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy