protected Composable( @Nullable Environment env, @Nonnull Observable events, @Nullable Composable parent) { Assert.notNull(events, "Events Observable cannot be null."); this.env = env; this.events = events; this.parent = parent; }
/** * Close the given channel. * * @param channel The channel object. * @param <C> The type of the channel object. */ protected <C> void close(@Nonnull C channel) { Assert.notNull(channel, "Channel cannot be null"); for (Registration<? extends NetChannel<IN, OUT>> reg : netChannels.select(channel)) { NetChannel<IN, OUT> chann = reg.getObject(); reg.cancel(); notifyClose(chann); } }
/** * Find the {@link NetChannel} for the given IO channel object. * * @param ioChannel The channel object. * @param <C> The type of the channel object. * @return The {@link NetChannel} associated with the given channel. */ protected <C> NetChannel<IN, OUT> select(@Nonnull C ioChannel) { Assert.notNull(ioChannel, "Channel cannot be null."); Iterator<Registration<? extends NetChannel<IN, OUT>>> channs = netChannels.select(ioChannel).iterator(); if (channs.hasNext()) { return channs.next().getObject(); } else { NetChannel<IN, OUT> conn = createChannel(ioChannel); register(ioChannel, conn); notifyOpen(conn); return conn; } }
/** * Assign the given {@link Function} to transform the incoming value {@code T} into a {@code V} * and pass it into another {@code Composable}. * * @param fn the transformation function * @param <V> the type of the return value of the transformation function * @return a new {@code Composable} containing the transformed values */ public <V> Composable<V> map(@Nonnull final Function<T, V> fn) { Assert.notNull(fn, "Map function cannot be null."); final Deferred<V, ? extends Composable<V>> d = createDeferred(); consume( new Consumer<T>() { @Override public void accept(T value) { try { V val = fn.apply(value); d.accept(val); } catch (Throwable e) { d.accept(e); } } }); return d.compose(); }
/** * Slice this buffer at the given positions. Useful for extracting multiple segments of data from * a buffer when the exact indices of that data is already known. * * @param positions The start and end positions of the slices. * @return A list of {@link View Views} pointing to the slices. */ public List<View> slice(int... positions) { Assert.notNull(positions, "Positions cannot be null."); if (positions.length == 0) { return Collections.emptyList(); } snapshot(); List<View> views = new ArrayList<View>(); int len = positions.length; for (int i = 0; i < len; i++) { int start = positions[i]; int end = (i + 1 < len ? positions[++i] : this.limit); views.add(createView(start, end)); reset(); } return views; }
/** * Evaluate each accepted value against the given {@link Predicate}. If the predicate test * succeeds, the value is passed into the new {@code Composable}. If the predicate test fails, an * exception is propagated into the new {@code Composable}. * * @param p the {@link Predicate} to test values against * @return a new {@code Composable} containing only values that pass the predicate test */ public Composable<T> filter(@Nonnull final Predicate<T> p) { Assert.notNull(p, "Filter predicate cannot be null."); final Deferred<T, ? extends Composable<T>> d = createDeferred(); consume( new Consumer<T>() { @Override public void accept(T value) { boolean b = p.test(value); if (b) { d.accept(value); } else { d.accept( new IllegalArgumentException( String.format("%s failed a predicate test.", value))); } } }); return d.compose(); }
/** * Create a {@code TcpClient.Spec} using the given implementation class. * * @param clientImpl The concrete implementation of {@link TcpClient} to instantiate. */ @SuppressWarnings({"unchecked", "rawtypes"}) public TcpClientSpec(@Nonnull Class<? extends TcpClient> clientImpl) { Assert.notNull(clientImpl, "TcpClient implementation class cannot be null."); try { this.clientImplConstructor = (Constructor<TcpClient<IN, OUT>>) clientImpl.getDeclaredConstructor( Environment.class, Reactor.class, InetSocketAddress.class, ClientSocketOptions.class, SslOptions.class, Codec.class, Collection.class); this.clientImplConstructor.setAccessible(true); } catch (NoSuchMethodException e) { throw new IllegalArgumentException( "No public constructor found that matches the signature of the one found in the TcpClient class."); } }
protected NettyTcpServer( Environment env, Reactor reactor, InetSocketAddress listenAddress, final ServerSocketOptions opts, final SslOptions sslOpts, Codec<Buffer, IN, OUT> codec, Collection<Consumer<TcpConnection<IN, OUT>>> connectionConsumers) { super(env, reactor, listenAddress, opts, sslOpts, codec, connectionConsumers); this.eventsReactor = reactor; this.listenAddress = listenAddress; Assert.notNull(opts, "ServerSocketOptions cannot be null"); this.options = opts; int selectThreadCount = env.getProperty("reactor.tcp.selectThreadCount", Integer.class, Environment.PROCESSORS / 2); int ioThreadCount = env.getProperty("reactor.tcp.ioThreadCount", Integer.class, Environment.PROCESSORS); selectorGroup = new NioEventLoopGroup( selectThreadCount, new NamedDaemonThreadFactory("reactor-tcp-select")); ioGroup = new NioEventLoopGroup(ioThreadCount, new NamedDaemonThreadFactory("reactor-tcp-io")); this.bootstrap = new ServerBootstrap() .group(selectorGroup, ioGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, options.backlog()) .option(ChannelOption.SO_RCVBUF, options.rcvbuf()) .option(ChannelOption.SO_SNDBUF, options.sndbuf()) .option(ChannelOption.SO_REUSEADDR, options.reuseAddr()) .localAddress((null == listenAddress ? new InetSocketAddress(3000) : listenAddress)) .childHandler( new ChannelInitializer<SocketChannel>() { @Override public void initChannel(final SocketChannel ch) throws Exception { SocketChannelConfig config = ch.config(); config.setReceiveBufferSize(options.rcvbuf()); config.setSendBufferSize(options.sndbuf()); config.setKeepAlive(options.keepAlive()); config.setReuseAddress(options.reuseAddr()); config.setSoLinger(options.linger()); config.setTcpNoDelay(options.tcpNoDelay()); if (log.isDebugEnabled()) { log.debug("CONNECT {}", ch); } if (null != sslOpts) { SSLEngine ssl = new SSLEngineSupplier(sslOpts, false).get(); if (log.isDebugEnabled()) { log.debug( "SSL enabled using keystore {}", (null != sslOpts.keystoreFile() ? sslOpts.keystoreFile() : "<DEFAULT>")); } ch.pipeline().addLast(new SslHandler(ssl)); } if (options instanceof NettyServerSocketOptions && null != ((NettyServerSocketOptions) options).pipelineConfigurer()) { ((NettyServerSocketOptions) options) .pipelineConfigurer() .accept(ch.pipeline()); } ch.pipeline().addLast(createChannelHandlers(ch)); ch.closeFuture() .addListener( new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (log.isDebugEnabled()) { log.debug("CLOSE {}", ch); } close(ch); } }); } }); }
/** * Subclasses should register the given {@link reactor.net.NetChannel} for later use. * * @param ioChannel The channel object. * @param netChannel The {@link NetChannel}. * @param <C> The type of the channel object. * @return {@link reactor.event.registry.Registration} of this channel in the {@link Registry}. */ protected <C> Registration<? extends NetChannel<IN, OUT>> register( @Nonnull C ioChannel, @Nonnull NetChannel<IN, OUT> netChannel) { Assert.notNull(ioChannel, "Channel cannot be null."); Assert.notNull(netChannel, "NetChannel cannot be null."); return netChannels.register(Selectors.$(ioChannel), netChannel); }
/** * Notify this client's consumers than a global error has occurred. * * @param error The error to notify. */ protected void notifyError(@Nonnull Throwable error) { Assert.notNull(error, "Error cannot be null."); reactor.notify(error.getClass(), Event.wrap(error)); }
/** * The {@link reactor.function.Consumer Consumers} to use to ingest the incoming data. * * @param consumers the incoming data {@link reactor.function.Consumer Consumers} * @return {@literal this} */ public TcpClientSpec<IN, OUT> consume(Collection<Consumer<IN>> consumers) { Assert.notNull(consumers, "Consumers cannot be null"); this.consumers = consumers; return this; }