commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bode...@apache.org
Subject [1/6] commons-compress git commit: Working version of deferred block decompression for skipped entries.
Date Wed, 24 Feb 2016 14:54:02 GMT
Repository: commons-compress
Updated Branches:
  refs/heads/master 3baf454c2 -> 1d66f1208


Working version of deferred block decompression for skipped entries.


Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/a53ab172
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/a53ab172
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/a53ab172

Branch: refs/heads/master
Commit: a53ab172b2a9b7c1a57be9f8d6dc82977af02bff
Parents: deb891f
Author: Dawid Weiss <dawid.weiss@carrotsearch.com>
Authored: Tue Feb 23 16:19:25 2016 +0100
Committer: Stefan Bodewig <bodewig@apache.org>
Committed: Wed Feb 24 15:42:19 2016 +0100

----------------------------------------------------------------------
 .../compress/archivers/sevenz/SevenZFile.java   | 72 +++++++++++---------
 1 file changed, 41 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-compress/blob/a53ab172/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
index 90bda16..60ffea8 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
@@ -26,6 +26,7 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.RandomAccessFile;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.LinkedList;
@@ -74,9 +75,10 @@ public class SevenZFile implements Closeable {
     private int currentEntryIndex = -1;
     private int currentFolderIndex = -1;
     private InputStream currentFolderInputStream = null;
-    private InputStream currentEntryInputStream = null;
     private byte[] password;
-        
+
+    private ArrayList<InputStream> deferredBlockStreams = new ArrayList<InputStream>();
+
     static final byte[] sevenZSignature = {
         (byte)'7', (byte)'z', (byte)0xBC, (byte)0xAF, (byte)0x27, (byte)0x1C
     };
@@ -809,17 +811,25 @@ public class SevenZFile implements Closeable {
     private void buildDecodingStream() throws IOException {
         final int folderIndex = archive.streamMap.fileFolderIndex[currentEntryIndex];
         if (folderIndex < 0) {
-            currentEntryInputStream = new BoundedInputStream(
-                    new ByteArrayInputStream(new byte[0]), 0);
+        	deferredBlockStreams.clear();
+            // TODO: previously it'd return an empty stream?
+        	// new BoundedInputStream(new ByteArrayInputStream(new byte[0]), 0);
             return;
         }
         final SevenZArchiveEntry file = archive.files[currentEntryIndex];
         if (currentFolderIndex == folderIndex) {
+        	// (COMPRESS-320).
+        	// The current entry is within the same (potentially opened) folder. The
+        	// previous stream has to be fully decoded before we can start reading
+        	// but don't do it eagerly -- if the user skips over the entire folder nothing
+        	// is effectively decompressed.
+
             // need to advance the folder input stream past the current file
-            drainPreviousEntry();
             file.setContentMethods(archive.files[currentEntryIndex - 1].getContentMethods());
         } else {
+        	// We're opening a new folder. Discard any queued streams/ folder stream.
             currentFolderIndex = folderIndex;
+        	deferredBlockStreams.clear();
             if (currentFolderInputStream != null) {
                 currentFolderInputStream.close();
                 currentFolderInputStream = null;
@@ -831,26 +841,15 @@ public class SevenZFile implements Closeable {
                     archive.streamMap.packStreamOffsets[firstPackStreamIndex];
             currentFolderInputStream = buildDecoderStack(folder, folderOffset, firstPackStreamIndex,
file);
         }
-        final InputStream fileStream = new BoundedInputStream(
-                currentFolderInputStream, file.getSize());
+
+        InputStream fileStream = new BoundedInputStream(currentFolderInputStream, file.getSize());
         if (file.getHasCrc()) {
-            currentEntryInputStream = new CRC32VerifyingInputStream(
-                    fileStream, file.getSize(), file.getCrcValue());
-        } else {
-            currentEntryInputStream = fileStream;
+            fileStream = new CRC32VerifyingInputStream(fileStream, file.getSize(), file.getCrcValue());
         }
         
+        deferredBlockStreams.add(fileStream);
     }
-    
-    private void drainPreviousEntry() throws IOException {
-        if (currentEntryInputStream != null) {
-            // return value ignored as IOUtils.skip ensures the stream is drained completely
-            IOUtils.skip(currentEntryInputStream, Long.MAX_VALUE);
-            currentEntryInputStream.close();
-            currentEntryInputStream = null;
-        }
-    }
-    
+
     private InputStream buildDecoderStack(final Folder folder, final long folderOffset,
                 final int firstPackStreamIndex, SevenZArchiveEntry entry) throws IOException
{
         file.seek(folderOffset);
@@ -886,13 +885,27 @@ public class SevenZFile implements Closeable {
      *             if an I/O error has occurred
      */
     public int read() throws IOException {
-        if (currentEntryInputStream == null) {
-            throw new IllegalStateException("No current 7z entry");
-        }
-        return currentEntryInputStream.read();
+    	return getCurrentStream().read();
     }
     
-    /**
+    private InputStream getCurrentStream() throws IOException {
+        if (deferredBlockStreams.isEmpty()) {
+            throw new IllegalStateException("No current 7z entry (call getNextEntry() first).");
+        }
+        
+        while (deferredBlockStreams.size() > 1) {
+        	// In solid compression mode we need to decompress all leading folder' 
+        	// streams to get access to an entry. We defer this until really needed
+        	// so that entire blocks can be skipped without wasting time for decompression.
+        	InputStream stream = deferredBlockStreams.remove(0);
+        	IOUtils.skip(stream, Long.MAX_VALUE);
+        	stream.close();
+        }
+
+		return deferredBlockStreams.get(0);
+	}
+
+	/**
      * Reads data into an array of bytes.
      * 
      * @param b the array to write data to
@@ -901,7 +914,7 @@ public class SevenZFile implements Closeable {
      *             if an I/O error has occurred
      */
     public int read(byte[] b) throws IOException {
-        return read(b, 0, b.length);
+    	return read(b, 0, b.length);
     }
     
     /**
@@ -915,10 +928,7 @@ public class SevenZFile implements Closeable {
      *             if an I/O error has occurred
      */
     public int read(byte[] b, int off, int len) throws IOException {
-        if (currentEntryInputStream == null) {
-            throw new IllegalStateException("No current 7z entry");
-        }
-        return currentEntryInputStream.read(b, off, len);
+        return getCurrentStream().read(b, off, len);
     }
     
     private static long readUint64(final DataInput in) throws IOException {


Mime
View raw message