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();
+    }
+
+}


Reply via email to