/** * Copyright 2016 LinkedIn Corp. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ package com.github.ambry.utils; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.WritableByteChannel; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReentrantLock; /** * A {@link WritableByteChannel} that stores the bytes written into it in a {@link ByteBuffer}. */ public class ByteBufferChannel implements WritableByteChannel { private final AtomicBoolean channelOpen = new AtomicBoolean(true); private final ReentrantLock bufferLock = new ReentrantLock(); private final ByteBuffer buffer; /** * Gets the {@link ByteBuffer} that is being used to receive writes. * @return the {@link ByteBuffer} that is receives writes to this channel. */ public ByteBuffer getBuffer() { return buffer; } /** * This object needs to be instantiated with a {@link ByteBuffer} that is provided by the caller. The maximum * number of bytes that can be written into the {@code buffer} is determined by {@code buffer.remaining()}. * @param buffer the buffer that can be used to recieve writes. */ public ByteBufferChannel(ByteBuffer buffer) { this.buffer = buffer; } /** * {@inheritDoc} * <p/> * Copies bytes from {@code src} into the {@link ByteBuffer} ({@code buffer}) backing this channel. The number of * bytes copied is the minimum of {@code src.remaining()} and {@code buffer.remaining()}. * @param src the source {@link ByteBuffer} to copy bytes from. * @return the number of bytes copied. * @throws ClosedChannelException if the channel is closed when this function was called. */ @Override public int write(ByteBuffer src) throws ClosedChannelException { if (!isOpen()) { throw new ClosedChannelException(); } int bytesWritten = 0; bufferLock.lock(); try { int bytesToWrite = Math.min(src.remaining(), buffer.remaining()); for (; bytesWritten < bytesToWrite; bytesWritten++) { buffer.put(src.get()); } } finally { bufferLock.unlock(); } return bytesWritten; } @Override public boolean isOpen() { return channelOpen.get(); } @Override public void close() { channelOpen.set(false); } }