final CountDownLatch completeLatch = new CountDownLatch(1);
final IOExceptionHolder exceptionHolder = new IOExceptionHolder();
final FailureHolder failureHolder = new FailureHolder();
final AtomicInteger status = new AtomicInteger(0);
OperationResult result = modelController.execute(builder.build(), new ResultHandler() {
@Override
public void handleResultFragment(String[] location, ModelNode fragment) {
try {
synchronized (outputStream) {
outputStream.write(ModelControllerClientProtocol.PARAM_HANDLE_RESULT_FRAGMENT);
outputStream.write(ModelControllerClientProtocol.PARAM_LOCATION);
StreamUtils.writeInt(outputStream, location.length);
for (String loc : location) {
StreamUtils.writeUTFZBytes(outputStream, loc);
}
outputStream.write(ModelControllerClientProtocol.PARAM_OPERATION);
fragment.writeExternal(outputStream);
outputStream.flush();
}
} catch (IOException e) {
clearAsynchronousOperation(asynchronousRequestId);
exceptionHolder.setException(e);
completeLatch.countDown();
}
}
@Override
public void handleResultComplete() {
clearAsynchronousOperation(asynchronousRequestId);
if(!status.compareAndSet(0, 1)) {
throw new RuntimeException("Result already set");
}
completeLatch.countDown();
}
@Override
public void handleFailed(final ModelNode failureDescription) {
clearAsynchronousOperation(asynchronousRequestId);
if(!status.compareAndSet(0, 2)) {
throw new RuntimeException("Result already set");
}
failureHolder.setFailure(failureDescription);
completeLatch.countDown();
}
@Override
public void handleCancellation() {
clearAsynchronousOperation(asynchronousRequestId);
if(!status.compareAndSet(0, 3)) {
throw new RuntimeException("Result already set");
}
completeLatch.countDown();
}
});
//Do this blocking operation outside the synch block or our result handler will deadlock
ModelNode compensating = result.getCompensatingOperation() != null ? result.getCompensatingOperation() : new ModelNode();
synchronized (outputStream) {
outputStream.write(ModelControllerClientProtocol.PARAM_OPERATION);
compensating.writeExternal(outputStream);
outputStream.flush();
}
if (completeLatch.getCount() == 0) {
//It was handled synchronously or has completed by now
} else {
//It was handled asynchronously
addAsynchronousOperation(asynchronousRequestId, result.getCancellable());
synchronized (outputStream) {
outputStream.write(ModelControllerClientProtocol.PARAM_REQUEST_ID);
StreamUtils.writeInt(outputStream, asynchronousRequestId);
outputStream.flush();
}