Author: jbellis
Date: Thu Mar 3 16:06:16 2011
New Revision: 1076662
URL: http://svn.apache.org/viewvc?rev=1076662&view=rev
Log:
throw EOFException when seeking past EOF in read-only mode
patch by Pavel Yaskevich; reviewed by tjake and jbellis for CASSANDRA-2256
Modified:
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/io/util/BufferedRandomAccessFile.java
cassandra/branches/cassandra-0.7/test/unit/org/apache/cassandra/io/util/BufferedRandomAccessFileTest.java
Modified:
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/io/util/BufferedRandomAccessFile.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/io/util/BufferedRandomAccessFile.java?rev=1076662&r1=1076661&r2=1076662&view=diff
==============================================================================
---
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/io/util/BufferedRandomAccessFile.java
(original)
+++
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/io/util/BufferedRandomAccessFile.java
Thu Mar 3 16:06:16 2011
@@ -17,6 +17,7 @@
*/
package org.apache.cassandra.io.util;
+import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
@@ -291,6 +292,9 @@ public class BufferedRandomAccessFile ex
if (buffer == null)
throw new ClosedChannelException();
+ if (isReadOnly())
+ throw new IOException("Unable to write: file is in the read-only
mode.");
+
while (length > 0)
{
int n = writeAtMost(buff, offset, length);
@@ -301,6 +305,11 @@ public class BufferedRandomAccessFile ex
}
}
+ private boolean isReadOnly()
+ {
+ return fileLength != -1;
+ }
+
/*
* Write at most "length" bytes from "b" starting at position "offset", and
* return the number of bytes written. caller is responsible for setting
@@ -328,6 +337,9 @@ public class BufferedRandomAccessFile ex
if (newPosition < 0)
throw new IllegalArgumentException("new position should not be
negative");
+ if (isReadOnly() && newPosition > fileLength)
+ throw new EOFException("unable to seek past the end of the file in
read-only mode.");
+
current = newPosition;
if (newPosition >= bufferOffset + validBufferBytes || newPosition <
bufferOffset)
Modified:
cassandra/branches/cassandra-0.7/test/unit/org/apache/cassandra/io/util/BufferedRandomAccessFileTest.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/test/unit/org/apache/cassandra/io/util/BufferedRandomAccessFileTest.java?rev=1076662&r1=1076661&r2=1076662&view=diff
==============================================================================
---
cassandra/branches/cassandra-0.7/test/unit/org/apache/cassandra/io/util/BufferedRandomAccessFileTest.java
(original)
+++
cassandra/branches/cassandra-0.7/test/unit/org/apache/cassandra/io/util/BufferedRandomAccessFileTest.java
Thu Mar 3 16:06:16 2011
@@ -521,6 +521,107 @@ public class BufferedRandomAccessFileTes
file.bytesPastMark();
}
+ @Test
+ public void testReadOnly() throws IOException
+ {
+ BufferedRandomAccessFile file = createTempFile("brafReadOnlyTest");
+
+ byte[] data = new byte[20];
+ for (int i = 0; i < data.length; i++)
+ data[i] = 'c';
+
+ file.write(data);
+ file.sync(); // flushing file to the disk
+
+ // read-only copy of the file, with fixed file length
+ final BufferedRandomAccessFile copy = new
BufferedRandomAccessFile(file.getPath(), "r");
+
+ copy.seek(copy.length());
+ assertTrue(copy.bytesRemaining() == 0 && copy.isEOF());
+
+ // can't seek past the end of the file for read-only files
+ expectEOF(new Callable<Object>()
+ {
+ public Object call() throws IOException
+ {
+ copy.seek(copy.length() + 1);
+ return null;
+ }
+ });
+
+ /* Any write() call should fail */
+ expectException(new Callable<Object>()
+ {
+ public Object call() throws IOException
+ {
+ copy.write(1);
+ return null;
+ }
+ }, IOException.class);
+
+ expectException(new Callable<Object>()
+ {
+ public Object call() throws IOException
+ {
+ copy.write(new byte[1]);
+ return null;
+ }
+ }, IOException.class);
+
+ expectException(new Callable<Object>()
+ {
+ public Object call() throws IOException
+ {
+ copy.write(new byte[3], 0, 2);
+ return null;
+ }
+ }, IOException.class);
+
+ copy.seek(0);
+ copy.skipBytes(5);
+
+ assertEquals(copy.bytesRemaining(), 15);
+ assertEquals(copy.getFilePointer(), 5);
+ assertTrue(!copy.isEOF());
+
+ copy.seek(0);
+ ByteBuffer contents = copy.readBytes((int) copy.length());
+
+ assertEquals(contents.limit(), copy.length());
+ assertTrue(ByteBufferUtil.compare(contents, data) == 0);
+
+ copy.seek(0);
+
+ int count = 0;
+ while (!copy.isEOF())
+ {
+ assertEquals((byte) copy.read(), 'c');
+ count++;
+ }
+
+ assertEquals(count, copy.length());
+
+ copy.seek(0);
+ byte[] content = new byte[10];
+ copy.read(content);
+
+ assertEquals(new String(content), "cccccccccc");
+
+ file.close();
+ copy.close();
+ }
+
+ @Test
+ public void testSeekPastEOF() throws IOException
+ {
+ BufferedRandomAccessFile file = createTempFile("brafTestSeekPastEOF");
+ file.seek(1);
+ file.write(1);
+ file.seek(0);
+ assertEquals(0, file.read());
+ assertEquals(1, file.read());
+ }
+
private void expectException(Callable<?> callable, Class<?> exception)
{
boolean thrown = false;