소스 검색

HADOOP-1619. Fix FSInputChecker to not attempt to read past EOF. Contributed by Hairong.

git-svn-id: https://svn.apache.org/repos/asf/lucene/hadoop/trunk@558831 13f79535-47bb-0310-9956-ffa450edef68
Doug Cutting 18 년 전
부모
커밋
a834d38e3e

+ 3 - 0
CHANGES.txt

@@ -404,6 +404,9 @@ Branch 0.14 (unreleased changes)
 134. HADOOP-1632.  Fix an IllegalArgumentException in fsck.
 134. HADOOP-1632.  Fix an IllegalArgumentException in fsck.
      (Hairong Kuang via cutting)
      (Hairong Kuang via cutting)
 
 
+135. HADOOP-1619.  Fix FSInputChecker to not attempt to read past EOF.
+     (Hairong Kuang via cutting)
+
 
 
 Release 0.13.0 - 2007-06-08
 Release 0.13.0 - 2007-06-08
 
 

+ 6 - 1
src/java/org/apache/hadoop/dfs/DFSClient.java

@@ -1264,7 +1264,12 @@ class DFSClient implements FSConstants {
      
      
     public long skip(long n) throws IOException {
     public long skip(long n) throws IOException {
       if ( n > 0 ) {
       if ( n > 0 ) {
-        seek(getPos()+n);
+        long curPos = getPos();
+        long fileLen = getFileLength();
+        if( n+curPos > fileLen ) {
+          n = fileLen - curPos;
+        }
+        seek(curPos+n);
         return n;
         return n;
       }
       }
       return n < 0 ? -1 : 0;
       return n < 0 ? -1 : 0;

+ 52 - 0
src/java/org/apache/hadoop/fs/ChecksumFileSystem.java

@@ -96,6 +96,7 @@ public abstract class ChecksumFileSystem extends FilterFileSystem {
     private static final int HEADER_LENGTH = 8;
     private static final int HEADER_LENGTH = 8;
     
     
     private int bytesPerSum = 1;
     private int bytesPerSum = 1;
+    private long fileLen = -1L;
     
     
     public ChecksumFSInputChecker(ChecksumFileSystem fs, Path file)
     public ChecksumFSInputChecker(ChecksumFileSystem fs, Path file)
       throws IOException {
       throws IOException {
@@ -202,6 +203,57 @@ public abstract class ChecksumFileSystem extends FilterFileSystem {
       }
       }
       return nread;
       return nread;
     }
     }
+    
+    /* Return the file length */
+    private long getFileLength() throws IOException {
+      if( fileLen==-1L ) {
+        fileLen = fs.getContentLength(file);
+      }
+      return fileLen;
+    }
+    
+    /**
+     * Skips over and discards <code>n</code> bytes of data from the
+     * input stream.
+     *
+     *The <code>skip</code> method skips over some smaller number of bytes
+     * when reaching end of file before <code>n</code> bytes have been skipped.
+     * The actual number of bytes skipped is returned.  If <code>n</code> is
+     * negative, no bytes are skipped.
+     *
+     * @param      n   the number of bytes to be skipped.
+     * @return     the actual number of bytes skipped.
+     * @exception  IOException  if an I/O error occurs.
+     *             ChecksumException if the chunk to skip to is corrupted
+     */
+    public synchronized long skip(long n) throws IOException {
+      long curPos = getPos();
+      long fileLength = getFileLength();
+      if( n+curPos > fileLength ) {
+        n = fileLength - curPos;
+      }
+      return super.skip(n);
+    }
+    
+    /**
+     * Seek to the given position in the stream.
+     * The next read() will be from that position.
+     * 
+     * <p>This method does not allow seek past the end of the file.
+     * This produces IOException.
+     *
+     * @param      pos   the postion to seek to.
+     * @exception  IOException  if an I/O error occurs or seeks after EOF
+     *             ChecksumException if the chunk to seek to is corrupted
+     */
+
+    public synchronized void seek(long pos) throws IOException {
+      if(pos>getFileLength()) {
+        throw new IOException("Cannot seek after EOF");
+      }
+      super.seek(pos);
+    }
+
   }
   }
 
 
   /**
   /**

+ 31 - 6
src/java/org/apache/hadoop/fs/FSInputChecker.java

@@ -297,7 +297,23 @@ abstract public class FSInputChecker extends FSInputStream {
     return count-pos;
     return count-pos;
   }
   }
   
   
-  @Override
+  /**
+   * Skips over and discards <code>n</code> bytes of data from the
+   * input stream.
+   *
+   * <p>This method may skip more bytes than are remaining in the backing
+   * file. This produces no exception and the number of bytes skipped
+   * may include some number of bytes that were beyond the EOF of the
+   * backing file. Attempting to read from the stream after skipping past
+   * the end will result in -1 indicating the end of the file.
+   *
+   *<p>If <code>n</code> is negative, no bytes are skipped.
+   *
+   * @param      n   the number of bytes to be skipped.
+   * @return     the actual number of bytes skipped.
+   * @exception  IOException  if an I/O error occurs.
+   *             ChecksumException if the chunk to skip to is corrupted
+   */
   public synchronized long skip(long n) throws IOException {
   public synchronized long skip(long n) throws IOException {
     if (n <= 0) {
     if (n <= 0) {
       return 0;
       return 0;
@@ -307,7 +323,19 @@ abstract public class FSInputChecker extends FSInputStream {
     return n;
     return n;
   }
   }
 
 
-  @Override
+  /**
+   * Seek to the given position in the stream.
+   * The next read() will be from that position.
+   * 
+   * <p>This method may seek past the end of the file.
+   * This produces no exception and an attempt to read from
+   * the stream will result in -1 indicating the end of the file.
+   *
+   * @param      pos   the postion to seek to.
+   * @exception  IOException  if an I/O error occurs.
+   *             ChecksumException if the chunk to seek to is corrupted
+   */
+
   public synchronized void seek(long pos) throws IOException {
   public synchronized void seek(long pos) throws IOException {
     if( pos<0 ) {
     if( pos<0 ) {
       return;
       return;
@@ -328,10 +356,7 @@ abstract public class FSInputChecker extends FSInputStream {
     // scan to the desired position
     // scan to the desired position
     int delta = (int)(pos - chunkPos);
     int delta = (int)(pos - chunkPos);
     if( delta > 0) {
     if( delta > 0) {
-      int nread = readFully(this, new byte[delta], 0, delta);
-      if (nread < delta) {
-        throw new IOException("Cannot seek after EOF");
-      }
+      readFully(this, new byte[delta], 0, delta);
     }
     }
   }
   }
 
 

+ 6 - 0
src/test/org/apache/hadoop/dfs/TestFSInputChecker.java

@@ -181,6 +181,12 @@ public class TestFSInputChecker extends TestCase {
     
     
     stm.seek(0);
     stm.seek(0);
     assertEquals(stm.skip(FILE_SIZE), FILE_SIZE);
     assertEquals(stm.skip(FILE_SIZE), FILE_SIZE);
+    assertEquals(stm.skip(10), 0);
+    
+    stm.seek(0);
+    assertEquals(stm.skip(FILE_SIZE+10), FILE_SIZE);
+    stm.seek(10);
+    assertEquals(stm.skip(FILE_SIZE), FILE_SIZE-10);
   }
   }
 
 
   private void cleanupFile(FileSystem fileSys, Path name) throws IOException {
   private void cleanupFile(FileSystem fileSys, Path name) throws IOException {