/** * Copyright 2012 Akiban Technologies, Inc. * * 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. * See the License for the specific language governing permissions and * limitations under the License. */ package com.persistit; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.util.ArrayList; import java.util.List; import com.persistit.MediatedFileChannel.TestChannelInjector; /** * <p> * A {@link FileChannel} implementation that simulates IOExceptions under * control of a unit test program. This class implements only those methods used * by Persistit; many methods of FileChannel throw * {@link UnsupportedOperationException}. * </p> * * @author peter * */ class TrackingFileChannel extends FileChannel implements TestChannelInjector { volatile FileChannel _channel; final List<Long> _writePositions = new ArrayList<Long>(); final List<Long> _readPositions = new ArrayList<Long>(); @Override public void setChannel(final FileChannel channel) { _channel = channel; } @Override protected void implCloseChannel() throws IOException { _channel.close(); } @Override public void force(final boolean metaData) throws IOException { _channel.force(metaData); } @Override public int read(final ByteBuffer byteBuffer, final long position) throws IOException { _readPositions.add(position); return _channel.read(byteBuffer, position); } @Override public long size() throws IOException { return _channel.size(); } @Override public FileChannel truncate(final long size) throws IOException { return _channel.truncate(size); } @Override public synchronized FileLock tryLock(final long position, final long size, final boolean shared) throws IOException { return _channel.tryLock(position, size, shared); } @Override public int write(final ByteBuffer byteBuffer, final long position) throws IOException { _writePositions.add(position); final int written = _channel.write(byteBuffer, position); return written; } /* * -------------------------------- * * Persistit does not use these methods and so they are Unsupported. Note * that it would be difficult to support the relative read/write methods * because the channel size is unavailable after it is closed. Therefore a * client of this class must maintain its own position counter and cannot * use the relative-addressing calls. * * -------------------------------- */ @Override public FileLock lock(final long position, final long size, final boolean shared) throws IOException { throw new UnsupportedOperationException(); } @Override public MappedByteBuffer map(final MapMode arg0, final long arg1, final long arg2) throws IOException { throw new UnsupportedOperationException(); } @Override public long position() throws IOException { throw new UnsupportedOperationException(); } @Override public FileChannel position(final long arg0) throws IOException { throw new UnsupportedOperationException(); } @Override public int read(final ByteBuffer byteBuffer) throws IOException { throw new UnsupportedOperationException(); } @Override public long read(final ByteBuffer[] arg0, final int arg1, final int arg2) throws IOException { throw new UnsupportedOperationException(); } @Override public long transferFrom(final ReadableByteChannel arg0, final long arg1, final long arg2) throws IOException { throw new UnsupportedOperationException(); } @Override public long transferTo(final long arg0, final long arg1, final WritableByteChannel arg2) throws IOException { throw new UnsupportedOperationException(); } @Override public int write(final ByteBuffer byteBuffer) throws IOException { throw new UnsupportedOperationException(); } @Override public long write(final ByteBuffer[] arg0, final int arg1, final int arg2) throws IOException { throw new UnsupportedOperationException(); } public List<Long> getWritePositionList() { return _writePositions; } public List<Long> getReadPositionList() { return _readPositions; } public void assertOrdered(final boolean read, final boolean forward) { final List<Long> list = read ? _readPositions : _writePositions; final long previous = forward ? -1 : Long.MAX_VALUE; for (final Long position : list) { if (forward) { assertTrue("Position should be larger", position > previous); } else { assertTrue("Position should be smaller", position < previous); } } } }