final int port = (secure ? SECURE_PORT : NON_SECURE_PORT);
final String scheme = (secure ? "https" : "http");
final ExecutorService service = Executors.newCachedThreadPool();
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().setMaxConnectionsPerHost(60).setMaxConnections(60).setAcceptAnyCertificate(true).build();
final AsyncHttpClient client = new DefaultAsyncHttpClient(new GrizzlyAsyncHttpProvider(config), config);
try {
final int[] statusCodes = new int[threadCount];
final int[] totalsReceived = new int[threadCount];
final Throwable[] errors = new Throwable[threadCount];
for (int i = 0; i < threadCount; i++) {
final int idx = i;
service.execute(new Runnable() {
@Override
public void run() {
FeedableBodyGenerator generator = new FeedableBodyGenerator();
FeedableBodyGenerator.NonBlockingFeeder nonBlockingFeeder = new FeedableBodyGenerator.NonBlockingFeeder(generator) {
private final Random r = new Random();
private final InputStream in;
private final byte[] bytesIn = new byte[2048];
private boolean isDone;
{
try {
in = new FileInputStream(tempFile);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
@Override
public void canFeed() throws IOException {
final int read = in.read(bytesIn);
if (read == -1) {
isDone = true;
feed(Buffers.EMPTY_BUFFER, true);
return;
}
final Buffer b = Buffers.wrap(DEFAULT_MEMORY_MANAGER, bytesIn, 0, read);
feed(b, false);
}
@Override
public boolean isDone() {
return isDone;
}
@Override
public boolean isReady() {
// simulate real-life usecase, where data could
// not be ready
return r.nextInt(100) < 80;
}
@Override
public void notifyReadyToFeed(final NonBlockingFeeder.ReadyToFeedListener listener) {
service.execute(new Runnable() {
public void run() {
try {
Thread.sleep(2);
} catch (InterruptedException e) {
}
listener.ready();
}
});
}
};
generator.setFeeder(nonBlockingFeeder);
generator.setMaxPendingBytes(10000);
RequestBuilder builder = new RequestBuilder("POST");
builder.setUrl(scheme + "://localhost:" + port + "/test");
builder.setBody(generator);
client.executeRequest(builder.build(), new AsyncCompletionHandler<org.asynchttpclient.Response>() {
@Override
public org.asynchttpclient.Response onCompleted(org.asynchttpclient.Response response) throws Exception {
try {
totalsReceived[idx] = Integer.parseInt(response.getHeader("x-total"));
} catch (Exception e) {
errors[idx] = e;
}
statusCodes[idx] = response.getStatusCode();
latch.countDown();
return response;
}
@Override
public void onThrowable(Throwable t) {
errors[idx] = t;
t.printStackTrace();
latch.countDown();
}
});
}
});
}
try {
latch.await(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
fail("Latch interrupted");
} finally {
service.shutdownNow();
}
for (int i = 0; i < threadCount; i++) {
assertEquals(statusCodes[i], 200);
assertNull(errors[i]);
assertEquals(totalsReceived[i], tempFile.length());
}
} finally {
client.close();
}
}