This is an automated email from the ASF dual-hosted git repository.

peterlee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git


The following commit(s) were added to refs/heads/master by this push:
     new 101137b  COMPRESS-539 : Update the IOUtils.skip to the latest 
implementation of Commons IO, and reuse the record buffer in 
TarArchiveInputStream.
101137b is described below

commit 101137bfa0f3ae709c2a2771368b190ceb899ea0
Author: PeterAlfredLee <peteralfred...@gmail.com>
AuthorDate: Sat Jul 4 19:11:41 2020 +0800

    COMPRESS-539 : Update the IOUtils.skip to the latest implementation of 
Commons IO, and reuse the record buffer in TarArchiveInputStream.
---
 src/changes/changes.xml                            |  4 +++
 .../archivers/tar/TarArchiveInputStream.java       | 11 +++---
 .../org/apache/commons/compress/utils/IOUtils.java | 42 +++++++++++-----------
 3 files changed, 32 insertions(+), 25 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3a1c189..6247111 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -127,6 +127,10 @@ The <action> type attribute can be add,update,fix,remove.
         and methods are also modified/added.
         Github Pull Request #97.
       </action>
+      <action issue="COMPRESS-539" type="update" date="2020-07-04" 
due-to="Robin Schimpf">
+        Update the IOUtils.skip to the latest implementation of Commons
+        IO, and reuse the record buffer in TarArchiveInputStream.
+      </action>
     </release>
     <release version="1.20" date="2020-02-08"
              description="Release 1.20">
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java
 
b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java
index 57bb601..bac1ee4 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java
@@ -59,6 +59,9 @@ public class TarArchiveInputStream extends ArchiveInputStream 
{
     /** The size the TAR header */
     private final int recordSize;
 
+    /** The buffer to store the TAR header **/
+    private final byte[] recordBuffer;
+
     /** The size of a block */
     private final int blockSize;
 
@@ -190,6 +193,7 @@ public class TarArchiveInputStream extends 
ArchiveInputStream {
         this.encoding = encoding;
         this.zipEncoding = ZipEncodingHelper.getZipEncoding(encoding);
         this.recordSize = recordSize;
+        this.recordBuffer = new byte[recordSize];
         this.blockSize = blockSize;
         this.lenient = lenient;
     }
@@ -519,16 +523,13 @@ public class TarArchiveInputStream extends 
ArchiveInputStream {
      * @throws IOException on error
      */
     protected byte[] readRecord() throws IOException {
-
-        final byte[] record = new byte[recordSize];
-
-        final int readNow = IOUtils.readFully(inputStream, record);
+        final int readNow = IOUtils.readFully(inputStream, recordBuffer);
         count(readNow);
         if (readNow != recordSize) {
             return null;
         }
 
-        return record;
+        return recordBuffer;
     }
 
     private void readGlobalPaxHeaders() throws IOException {
diff --git a/src/main/java/org/apache/commons/compress/utils/IOUtils.java 
b/src/main/java/org/apache/commons/compress/utils/IOUtils.java
index 7fa502a..f36070d 100644
--- a/src/main/java/org/apache/commons/compress/utils/IOUtils.java
+++ b/src/main/java/org/apache/commons/compress/utils/IOUtils.java
@@ -40,7 +40,7 @@ public final class IOUtils {
 
     // This buffer does not need to be synchronised because it is write only; 
the contents are ignored
     // Does not affect Immutability
-    private static final byte[] SKIP_BUF = new byte[SKIP_BUF_SIZE];
+    private static byte[] SKIP_BUF;
 
     /** Private constructor to prevent instantiation of this utility class. */
     private IOUtils(){
@@ -95,37 +95,39 @@ public final class IOUtils {
      * Skips the given number of bytes by repeatedly invoking skip on
      * the given input stream if necessary.
      *
-     * <p>In a case where the stream's skip() method returns 0 before
-     * the requested number of bytes has been skip this implementation
-     * will fall back to using the read() method.</p>
-     *
      * <p>This method will only skip less than the requested number of
      * bytes if the end of the input stream has been reached.</p>
+     * <p>
+     * This method is copied from Apache Commons IO with commit ID
+     * of 401d17349e7ec52d8fa866c35efd24103f332c29
      *
-     * @param input stream to skip bytes in
+     * @param input     stream to skip bytes in
      * @param numToSkip the number of bytes to skip
      * @return the number of bytes actually skipped
      * @throws IOException on error
      */
     public static long skip(final InputStream input, long numToSkip) throws 
IOException {
-        final long available = numToSkip;
-        while (numToSkip > 0) {
-            final long skipped = input.skip(numToSkip);
-            if (skipped == 0) {
-                break;
-            }
-            numToSkip -= skipped;
+        if (numToSkip < 0) {
+            throw new IllegalArgumentException("Skip count must be 
non-negative, actual: " + numToSkip);
         }
-
-        while (numToSkip > 0) {
-            final int read = readFully(input, SKIP_BUF, 0,
-                                 (int) Math.min(numToSkip, SKIP_BUF_SIZE));
-            if (read < 1) {
+        /*
+         * N.B. no need to synchronize this because: - we don't care if the 
buffer is created multiple times (the data
+         * is ignored) - we always use the same size buffer, so if it it is 
recreated it will still be OK (if the buffer
+         * size were variable, we would need to synch. to ensure some other 
thread did not create a smaller one)
+         */
+        if (SKIP_BUF == null) {
+            SKIP_BUF = new byte[SKIP_BUF_SIZE];
+        }
+        long remain = numToSkip;
+        while (remain > 0) {
+            // See https://issues.apache.org/jira/browse/IO-203 for why we use 
read() rather than delegating to skip()
+            final long n = input.read(SKIP_BUF, 0, (int) Math.min(remain, 
SKIP_BUF_SIZE));
+            if (n < 0) { // EOF
                 break;
             }
-            numToSkip -= read;
+            remain -= n;
         }
-        return available - numToSkip;
+        return numToSkip - remain;
     }
 
     /**

Reply via email to