Author: johan Date: Tue Apr 6 13:37:38 2010 New Revision: 931148 URL: http://svn.apache.org/viewvc?rev=931148&view=rev Log: Cache BufferedRandomAccessFile.length result to avoid native call. Patch by johan, review by jbellis. CASSANDRA-950
Added: cassandra/trunk/test/unit/org/apache/cassandra/io/util/ cassandra/trunk/test/unit/org/apache/cassandra/io/util/BufferedRandomAccessFileTest.java Modified: cassandra/trunk/src/java/org/apache/cassandra/io/util/BufferedRandomAccessFile.java Modified: cassandra/trunk/src/java/org/apache/cassandra/io/util/BufferedRandomAccessFile.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/io/util/BufferedRandomAccessFile.java?rev=931148&r1=931147&r2=931148&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/io/util/BufferedRandomAccessFile.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/io/util/BufferedRandomAccessFile.java Tue Apr 6 13:37:38 2010 @@ -57,6 +57,7 @@ public class BufferedRandomAccessFile ex private boolean hitEOF_; // buffer contains last file block? private long diskPos_; // disk position private long markedPointer; + private long fileLength = -1; // cache for file size /* * To describe the above fields, we introduce the following abstractions for @@ -125,7 +126,7 @@ public class BufferedRandomAccessFile ex { super(file, mode); path_ = file.getAbsolutePath(); - this.init(size); + this.init(size, mode); } /** @@ -138,14 +139,14 @@ public class BufferedRandomAccessFile ex this(name, mode, 0); } - public BufferedRandomAccessFile(String name, String mode, int size) throws FileNotFoundException + public BufferedRandomAccessFile(String name, String mode, int size) throws IOException { super(name, mode); path_ = name; - this.init(size); + this.init(size, mode); } - private void init(int size) + private void init(int size, String mode) throws IOException { this.dirty_ = false; this.lo_ = this.curr_ = this.hi_ = 0; @@ -153,6 +154,11 @@ public class BufferedRandomAccessFile ex this.maxHi_ = (long) BuffSz_; this.hitEOF_ = false; this.diskPos_ = 0L; + if ("r".equals(mode)) + { + // read only file, we can cache file length + this.fileLength = super.length(); + } } public String getPath() @@ -266,8 +272,16 @@ public class BufferedRandomAccessFile ex public long length() throws IOException { - // max accounts for the case where we have written past the old file length, but not yet flushed our buffer - return Math.max(this.curr_, super.length()); + if (fileLength == -1) + { + // max accounts for the case where we have written past the old file length, but not yet flushed our buffer + return Math.max(this.curr_, super.length()); + } + else + { + // opened as read only, file length is cached + return fileLength; + } } public int read() throws IOException Added: cassandra/trunk/test/unit/org/apache/cassandra/io/util/BufferedRandomAccessFileTest.java URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/io/util/BufferedRandomAccessFileTest.java?rev=931148&view=auto ============================================================================== --- cassandra/trunk/test/unit/org/apache/cassandra/io/util/BufferedRandomAccessFileTest.java (added) +++ cassandra/trunk/test/unit/org/apache/cassandra/io/util/BufferedRandomAccessFileTest.java Tue Apr 6 13:37:38 2010 @@ -0,0 +1,48 @@ +package org.apache.cassandra.io.util; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import org.junit.Test; + +public class BufferedRandomAccessFileTest +{ + + @Test + public void testLength() throws IOException + { + File tmpFile = File.createTempFile("lengthtest", "bin"); + BufferedRandomAccessFile rw = new BufferedRandomAccessFile(tmpFile, "rw"); + assertEquals(0, rw.length()); + + // write a chunk smaller then our buffer, so will not be flushed + // to disk + byte[] lessThenBuffer = new byte[BufferedRandomAccessFile.BuffSz_ / 2]; + rw.write(lessThenBuffer); + assertEquals(lessThenBuffer.length, rw.length()); + + // sync the data and check length + rw.sync(); + assertEquals(lessThenBuffer.length, rw.length()); + + // write more then the buffer can hold and check length + byte[] biggerThenBuffer = new byte[BufferedRandomAccessFile.BuffSz_ * 2]; + rw.write(biggerThenBuffer); + assertEquals(biggerThenBuffer.length + lessThenBuffer.length, rw.length()); + + // checking that reading doesn't interfere + rw.seek(0); + rw.read(); + assertEquals(biggerThenBuffer.length + lessThenBuffer.length, rw.length()); + + rw.close(); + + // will use cachedlength + BufferedRandomAccessFile r = new BufferedRandomAccessFile(tmpFile, "r"); + assertEquals(lessThenBuffer.length + biggerThenBuffer.length, r.length()); + r.close(); + } + +}