io.opentelemetry.exporter.sender.jdk.internal.BodyPublisher Maven / Gradle / Ivy
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.sender.jdk.internal;
import java.net.http.HttpRequest;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Flow;
import java.util.function.Supplier;
final class BodyPublisher implements HttpRequest.BodyPublisher {
private final int length;
private final byte[] content;
private final Supplier bufSupplier;
BodyPublisher(byte[] content, int length, Supplier bufSupplier) {
this.content = content;
this.length = length;
this.bufSupplier = bufSupplier;
}
private List copyToBuffers() {
int offset = 0;
int length = this.length;
List buffers = new ArrayList<>();
while (length > 0) {
ByteBuffer b = bufSupplier.get();
b.clear();
int lengthToCopy = Math.min(b.capacity(), length);
b.put(content, offset, lengthToCopy);
offset += lengthToCopy;
length -= lengthToCopy;
b.flip();
buffers.add(b);
}
return buffers;
}
@Override
public long contentLength() {
return length;
}
@Override
public void subscribe(Flow.Subscriber super ByteBuffer> subscriber) {
Subscription subscription = new Subscription(copyToBuffers(), subscriber);
subscriber.onSubscribe(subscription);
}
private static class Subscription implements Flow.Subscription {
private volatile boolean isCompleted;
private final List buffers;
private final Flow.Subscriber super ByteBuffer> subscriber;
private int offset = 0;
private Subscription(List buffers, Flow.Subscriber super ByteBuffer> subscriber) {
this.buffers = buffers;
this.subscriber = subscriber;
}
@Override
public void request(long n) {
if (isCompleted) {
return;
}
if (n <= 0) {
subscriber.onError(new IllegalArgumentException("Subscription request must be >= 0"));
isCompleted = true;
} else {
run(n);
}
}
@Override
public void cancel() {
isCompleted = true;
}
private synchronized void run(long requestedItems) {
if (isCompleted) {
return;
}
long count = 0;
ByteBuffer next;
while (count < requestedItems) {
int nextIndex = offset++;
if (nextIndex >= buffers.size()) {
break;
}
next = buffers.get(nextIndex);
subscriber.onNext(next);
count++;
}
if (offset >= buffers.size()) {
isCompleted = true;
subscriber.onComplete();
}
}
}
}