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());
}
}));
}
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();
}
}
});
}
Aggregations