Search in sources :

Example 1 with ManagedSubscription

use of ratpack.stream.internal.ManagedSubscription in project ratpack by ratpack.

the class FileReadingPublisher method subscribe.

@Override
public void subscribe(Subscriber<? super ByteBuf> s) {
    file.onError(s::onError).then(channel -> s.onSubscribe(new ManagedSubscription<ByteBuf>(s, ByteBuf::release) {

        private final AtomicBoolean reading = new AtomicBoolean();

        private long position = start;

        @Override
        protected void onRequest(long n) {
            doRead();
        }

        @Override
        protected void onCancel() {
        }

        private void read() {
            if (reading.compareAndSet(false, true)) {
                doRead();
            }
        }

        private void doRead() {
            Promise.<ByteBuf>async(down -> {
                int size = (int) Math.min(stop - position, bufferSize);
                ByteBuf buffer = allocator.buffer(size, size);
                channel.read(buffer.nioBuffer(0, size), position, buffer, new CompletionHandler<Integer, ByteBuf>() {

                    @Override
                    public void completed(Integer result, ByteBuf attachment) {
                        attachment.writerIndex(Math.max(result, 0));
                        down.success(attachment);
                    }

                    @Override
                    public void failed(Throwable exc, ByteBuf attachment) {
                        attachment.release();
                        down.error(exc);
                    }
                });
            }).onError(this::complete).then(read -> {
                if (read.readableBytes() == 0) {
                    read.release();
                    complete(null);
                } else {
                    position += read.readableBytes();
                    emitNext(read);
                    if (position == stop) {
                        complete(null);
                    } else if (hasDemand()) {
                        doRead();
                    } else {
                        reading.set(false);
                        if (hasDemand()) {
                            read();
                        }
                    }
                }
            });
        }

        private void complete(Throwable error) {
            Promise<?> p = error == null ? Promise.ofNull() : Promise.error(error);
            p.close(Blocking.op(((AsynchronousFileChannel) channel)::close)).onError(this::emitError).then(v -> emitComplete());
        }
    }));
}
Also used : AsynchronousFileChannel(java.nio.channels.AsynchronousFileChannel) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ByteBuf(io.netty.buffer.ByteBuf) ManagedSubscription(ratpack.stream.internal.ManagedSubscription)

Example 2 with ManagedSubscription

use of ratpack.stream.internal.ManagedSubscription in project ratpack by ratpack.

the class ByteBufComposingPublisher method subscribe.

@Override
public void subscribe(Subscriber<? super CompositeByteBuf> subscriber) {
    subscriber.onSubscribe(new ManagedSubscription<CompositeByteBuf>(subscriber, ByteBuf::release) {

        private Subscription subscription;

        private CompositeByteBuf composite;

        private volatile State state;

        @Override
        protected void onRequest(long n) {
            if (subscription == null) {
                upstream.subscribe(new Subscriber<ByteBuf>() {

                    @Override
                    public void onSubscribe(Subscription s) {
                        subscription = s;
                        state = State.Fetching;
                        s.request(1);
                    }

                    @Override
                    public void onNext(ByteBuf t) {
                        if (state == State.Closed) {
                            t.release();
                            return;
                        }
                        if (composite == null) {
                            composite = alloc.compositeBuffer(maxNum);
                        }
                        composite.addComponent(true, t);
                        if (composite.numComponents() == maxNum || composite.readableBytes() >= watermark) {
                            state = State.Writing;
                            emitNext(composite);
                            composite = null;
                            maybeFetch();
                        } else {
                            subscription.request(1);
                        }
                    }

                    @Override
                    public void onError(Throwable t) {
                        state = State.Closed;
                        ReferenceCountUtil.release(composite);
                        emitError(t);
                    }

                    @Override
                    public void onComplete() {
                        state = State.Closed;
                        if (composite != null) {
                            emitNext(composite);
                        }
                        emitComplete();
                    }
                });
            } else {
                maybeFetch();
            }
        }

        private void maybeFetch() {
            if (getDemand() > 0 && state != State.Fetching) {
                state = State.Fetching;
                subscription.request(1);
            }
        }

        @Override
        protected void onCancel() {
            state = State.Closed;
            ReferenceCountUtil.release(composite);
            if (subscription != null) {
                subscription.cancel();
            }
        }
    });
}
Also used : CompositeByteBuf(io.netty.buffer.CompositeByteBuf) Subscriber(org.reactivestreams.Subscriber) Subscription(org.reactivestreams.Subscription) ManagedSubscription(ratpack.stream.internal.ManagedSubscription) CompositeByteBuf(io.netty.buffer.CompositeByteBuf) ByteBuf(io.netty.buffer.ByteBuf)

Aggregations

ByteBuf (io.netty.buffer.ByteBuf)2 ManagedSubscription (ratpack.stream.internal.ManagedSubscription)2 CompositeByteBuf (io.netty.buffer.CompositeByteBuf)1 AsynchronousFileChannel (java.nio.channels.AsynchronousFileChannel)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 Subscriber (org.reactivestreams.Subscriber)1 Subscription (org.reactivestreams.Subscription)1