package rocks.inspectit.shared.cs.storage.nio.read; import java.nio.ByteBuffer; import java.nio.channels.CompletionHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import rocks.inspectit.shared.cs.storage.nio.WriteReadAttachment; import rocks.inspectit.shared.cs.storage.nio.WriteReadCompletionRunnable; /** * Completion handler for asynchronous reading. * * @author Ivan Senic * */ public class ReadingCompletionHandler implements CompletionHandler<Integer, WriteReadAttachment> { /** * The log of this class. Can not be assigned via spring because this is not a component. */ private static final Logger LOG = LoggerFactory.getLogger(ReadingCompletionHandler.class); /** * {@inheritDoc} * <p> * On reading completion the check if the wanted reading size has been read. If not, a new read * with updated position and size is performed. If yes, the completion runnable is invoke if it * is not null and buffer is flip. */ @Override public void completed(Integer result, WriteReadAttachment attachment) { long bytesToReadMore = attachment.getSize() - result.longValue(); if (bytesToReadMore > 0) { long readSize = bytesToReadMore; long position = attachment.getPosition() + result.longValue(); attachment.setSize(readSize); attachment.setPosition(position); attachment.getFileChannel().read(attachment.getByteBuffer(), position, attachment, this); } else { ByteBuffer byteBuffer = attachment.getByteBuffer(); // there is a chance that we can read more bytes that wanted, that's just the // possibility coming from Java NIO2 // in that case, we need to assure that the byte buffer contains only the amount of // bytes we wanted to read // that will assure that the de-serialization goes without problems // keep in mind that in situation described bytesToReadMore is negative if (bytesToReadMore < 0) { byteBuffer.position(byteBuffer.position() + (int) bytesToReadMore); } byteBuffer.flip(); WriteReadCompletionRunnable.RunnableFuture completionRunnableFuture = attachment.getCompletionRunnableFuture(); if (null != completionRunnableFuture) { completionRunnableFuture.getWriteReadCompletionRunnable().markSuccess(); if (completionRunnableFuture.getWriteReadCompletionRunnable().isFinished()) { completionRunnableFuture.run(); } } } } /** * {@inheritDoc} */ @Override public void failed(Throwable exc, WriteReadAttachment attachment) { LOG.error("Write to the disk failed.", exc); WriteReadCompletionRunnable.RunnableFuture completionRunnableFuture = attachment.getCompletionRunnableFuture(); if (null != completionRunnableFuture) { completionRunnableFuture.getWriteReadCompletionRunnable().markFailed(); if (completionRunnableFuture.getWriteReadCompletionRunnable().isFinished()) { completionRunnableFuture.run(); } } } }