package edu.uw.zookeeper.net.intravm;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import java.net.SocketAddress;
import java.util.concurrent.Executor;
import com.google.common.base.Supplier;
import edu.uw.zookeeper.common.Factory;
import edu.uw.zookeeper.common.Pair;
import edu.uw.zookeeper.common.ParameterizedFactory;
import edu.uw.zookeeper.net.ClientConnectionFactory;
import edu.uw.zookeeper.net.Codec;
import edu.uw.zookeeper.net.CodecConnection;
import edu.uw.zookeeper.net.Connection;
import edu.uw.zookeeper.net.NetClientModule;
import edu.uw.zookeeper.net.NetServerModule;
import edu.uw.zookeeper.net.ServerConnectionFactory;
public class IntraVmNetModule implements NetClientModule, NetServerModule {
public static IntraVmNetModule defaults() {
return create(
IntraVmCodecEndpointFactory.unpooled(),
IntraVmCodecEndpointFactory.sameThreadExecutors(),
IntraVmFactory.<ByteBuf,ByteBuf>defaults());
}
public static IntraVmNetModule create(
Factory<? extends ByteBufAllocator> allocators,
Factory<? extends Executor> executors,
IntraVmFactory<ByteBuf,ByteBuf> factory) {
return new IntraVmNetModule(
allocators,
executors,
factory);
}
protected final Supplier<? extends ByteBufAllocator> allocators;
protected final IntraVmFactory<ByteBuf,ByteBuf> factory;
protected final Supplier<? extends Executor> executors;
public IntraVmNetModule(
Supplier<? extends ByteBufAllocator> allocators,
Factory<? extends Executor> executors,
IntraVmFactory<ByteBuf,ByteBuf> factory) {
this.factory = factory;
this.allocators = allocators;
this.executors = executors;
}
public Supplier<? extends ByteBufAllocator> allocators() {
return allocators;
}
public IntraVmFactory<ByteBuf,ByteBuf> factory() {
return factory;
}
public Supplier<? extends Executor> executors() {
return executors;
}
@Override
public <I, O, T extends Codec<I, O, ? extends I, ? extends O>, C extends Connection<?,?,?>> Factory<? extends ClientConnectionFactory<C>> getClientConnectionFactory(
Factory<? extends T> codecFactory,
ParameterizedFactory<CodecConnection<I,O,T,?>, C> connectionFactory) {
final IntraVmCodecEndpointFactory<I,O,T> endpoints = getEndpointFactory(codecFactory);
final ParameterizedFactory<Pair<? extends IntraVmCodecEndpoint<I,O,T>, ? extends AbstractIntraVmEndpoint<?,?,?,? super ByteBuf>>, ? extends C> connections = getConnectionFactory(connectionFactory);
return new Factory<ClientConnectionFactory<C>>() {
@Override
public ClientConnectionFactory<C> get() {
return factory.newClient(endpoints, connections);
}
};
}
@Override
public <I, O, T extends Codec<I, O, ? extends I, ? extends O>, C extends Connection<?,?,?>> ParameterizedFactory<SocketAddress, ? extends ServerConnectionFactory<C>> getServerConnectionFactory(
Factory<? extends T> codecFactory,
ParameterizedFactory<CodecConnection<I,O,T,?>, C> connectionFactory) {
final IntraVmCodecEndpointFactory<I,O,T> endpoints = getEndpointFactory(codecFactory);
final ParameterizedFactory<Pair<? extends IntraVmCodecEndpoint<I,O,T>, ? extends AbstractIntraVmEndpoint<?,?,?,? super ByteBuf>>, ? extends C> connections = getConnectionFactory(connectionFactory);
return new ParameterizedFactory<SocketAddress, ServerConnectionFactory<C>>() {
@Override
public ServerConnectionFactory<C> get(SocketAddress value) {
return factory.newServer(value, endpoints, connections);
}
};
}
public <I, O, T extends Codec<I, O, ? extends I, ? extends O>> IntraVmCodecEndpointFactory<I,O,T> getEndpointFactory(
Supplier<? extends T> codecFactory) {
return IntraVmCodecEndpointFactory.create(
codecFactory, allocators, factory.addresses(), executors);
}
public <I, O, T extends Codec<I, O, ? extends I, ? extends O>, C extends Connection<?,?,?>> ParameterizedFactory<Pair<? extends IntraVmCodecEndpoint<I,O,T>, ? extends AbstractIntraVmEndpoint<?,?,?,? super ByteBuf>>, ? extends C> getConnectionFactory(
final ParameterizedFactory<CodecConnection<I,O,T,?>, C> connectionFactory) {
return new ParameterizedFactory<Pair<? extends IntraVmCodecEndpoint<I,O,T>, ? extends AbstractIntraVmEndpoint<?,?,?,? super ByteBuf>>, C>() {
@Override
public C get(Pair<? extends IntraVmCodecEndpoint<I,O,T>, ? extends AbstractIntraVmEndpoint<?,?,?,? super ByteBuf>> value) {
IntraVmCodecConnection<I,O,T> endpoint = IntraVmCodecConnection.newInstance(value.first().codec(), value.first(), value.second());
return connectionFactory.get(endpoint);
}
};
}
}