aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src
diff options
context:
space:
mode:
authorIvan Frade <ifrade@google.com>2022-01-27 11:42:54 -0500
committerGerrit Code Review @ Eclipse.org <gerrit@eclipse.org>2022-01-27 11:42:54 -0500
commit27e554e465d043ed12914fd42554164c9333fc44 (patch)
tree12278e0a072e5b9886577fc10be73c0f54210b7f /org.eclipse.jgit/src
parent75e7d08480eb368436458504c103fe3b68bd6089 (diff)
parent1a86c1044dfb8300241728571a865971aa9f1a66 (diff)
downloadjgit-27e554e465d043ed12914fd42554164c9333fc44.tar.gz
jgit-27e554e465d043ed12914fd42554164c9333fc44.zip
Merge "PackOutputStream: Extract cancellation and digest to superclass"
Diffstat (limited to 'org.eclipse.jgit/src')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/io/CancellableDigestOutputStream.java124
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackOutputStream.java77
2 files changed, 129 insertions, 72 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/io/CancellableDigestOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/io/CancellableDigestOutputStream.java
new file mode 100644
index 0000000000..ca2095feec
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/io/CancellableDigestOutputStream.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022, Tencent.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.io;
+
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ProgressMonitor;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.security.MessageDigest;
+
+/**
+ * An OutputStream that keeps a digest and checks every N bytes for
+ * cancellation.
+ */
+public class CancellableDigestOutputStream extends OutputStream {
+
+ /** The OutputStream checks every this value for cancellation **/
+ public static final int BYTES_TO_WRITE_BEFORE_CANCEL_CHECK = 128 * 1024;
+
+ private final ProgressMonitor writeMonitor;
+
+ private final OutputStream out;
+
+ private final MessageDigest md = Constants.newMessageDigest();
+
+ private long count;
+
+ private long checkCancelAt;
+
+ /**
+ * Initialize a CancellableDigestOutputStream.
+ *
+ * @param writeMonitor
+ * monitor to update on output progress and check cancel.
+ * @param out
+ * target stream to receive all contents.
+ */
+ public CancellableDigestOutputStream(ProgressMonitor writeMonitor,
+ OutputStream out) {
+ this.writeMonitor = writeMonitor;
+ this.out = out;
+ this.checkCancelAt = BYTES_TO_WRITE_BEFORE_CANCEL_CHECK;
+ }
+
+ /**
+ * Get the monitor which is used to update on output progress and check
+ * cancel.
+ *
+ * @return the monitor
+ */
+ public final ProgressMonitor getWriteMonitor() {
+ return writeMonitor;
+ }
+
+ /**
+ * Obtain the current SHA-1 digest.
+ *
+ * @return SHA-1 digest
+ */
+ public final byte[] getDigest() {
+ return md.digest();
+ }
+
+ /**
+ * Get total number of bytes written since stream start.
+ *
+ * @return total number of bytes written since stream start.
+ */
+ public final long length() {
+ return count;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public final void write(int b) throws IOException {
+ if (checkCancelAt <= count) {
+ if (writeMonitor.isCancelled()) {
+ throw new InterruptedIOException();
+ }
+ checkCancelAt = count + BYTES_TO_WRITE_BEFORE_CANCEL_CHECK;
+ }
+
+ out.write(b);
+ md.update((byte) b);
+ count++;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public final void write(byte[] b, int off, int len) throws IOException {
+ while (0 < len) {
+ if (checkCancelAt <= count) {
+ if (writeMonitor.isCancelled()) {
+ throw new InterruptedIOException();
+ }
+ checkCancelAt = count + BYTES_TO_WRITE_BEFORE_CANCEL_CHECK;
+ }
+
+ int n = Math.min(len, BYTES_TO_WRITE_BEFORE_CANCEL_CHECK);
+ out.write(b, off, n);
+ md.update(b, off, n);
+ count += n;
+
+ off += n;
+ len -= n;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void flush() throws IOException {
+ out.flush();
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackOutputStream.java
index 7104b9453e..2d0fe28dae 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackOutputStream.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackOutputStream.java
@@ -17,10 +17,8 @@ import static org.eclipse.jgit.lib.Constants.PACK_SIGNATURE;
import java.io.IOException;
import java.io.OutputStream;
-import java.security.MessageDigest;
-import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.internal.storage.io.CancellableDigestOutputStream;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.util.NB;
@@ -28,25 +26,14 @@ import org.eclipse.jgit.util.NB;
* Custom output stream to support
* {@link org.eclipse.jgit.internal.storage.pack.PackWriter}.
*/
-public final class PackOutputStream extends OutputStream {
- private static final int BYTES_TO_WRITE_BEFORE_CANCEL_CHECK = 128 * 1024;
-
- private final ProgressMonitor writeMonitor;
-
- private final OutputStream out;
+public final class PackOutputStream extends CancellableDigestOutputStream {
private final PackWriter packWriter;
- private final MessageDigest md = Constants.newMessageDigest();
-
- private long count;
-
private final byte[] headerBuffer = new byte[32];
private final byte[] copyBuffer = new byte[64 << 10];
- private long checkCancelAt;
-
private boolean ofsDelta;
/**
@@ -66,48 +53,8 @@ public final class PackOutputStream extends OutputStream {
*/
public PackOutputStream(final ProgressMonitor writeMonitor,
final OutputStream out, final PackWriter pw) {
- this.writeMonitor = writeMonitor;
- this.out = out;
+ super(writeMonitor, out);
this.packWriter = pw;
- this.checkCancelAt = BYTES_TO_WRITE_BEFORE_CANCEL_CHECK;
- }
-
- /** {@inheritDoc} */
- @Override
- public final void write(int b) throws IOException {
- count++;
- out.write(b);
- md.update((byte) b);
- }
-
- /** {@inheritDoc} */
- @Override
- public final void write(byte[] b, int off, int len)
- throws IOException {
- while (0 < len) {
- final int n = Math.min(len, BYTES_TO_WRITE_BEFORE_CANCEL_CHECK);
- count += n;
-
- if (checkCancelAt <= count) {
- if (writeMonitor.isCancelled()) {
- throw new IOException(
- JGitText.get().packingCancelledDuringObjectsWriting);
- }
- checkCancelAt = count + BYTES_TO_WRITE_BEFORE_CANCEL_CHECK;
- }
-
- out.write(b, off, n);
- md.update(b, off, n);
-
- off += n;
- len -= n;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void flush() throws IOException {
- out.flush();
}
final void writeFileHeader(int version, long objectCount)
@@ -160,7 +107,7 @@ public final class PackOutputStream extends OutputStream {
ObjectToPack b = otp.getDeltaBase();
if (b != null && (b.isWritten() & ofsDelta)) { // Non-short-circuit logic is intentional
int n = objectHeader(rawLength, OBJ_OFS_DELTA, headerBuffer);
- n = ofsDelta(count - b.getOffset(), headerBuffer, n);
+ n = ofsDelta(length() - b.getOffset(), headerBuffer, n);
write(headerBuffer, 0, n);
} else if (otp.isDeltaRepresentation()) {
int n = objectHeader(rawLength, OBJ_REF_DELTA, headerBuffer);
@@ -209,20 +156,6 @@ public final class PackOutputStream extends OutputStream {
}
void endObject() {
- writeMonitor.update(1);
- }
-
- /**
- * Get total number of bytes written since stream start.
- *
- * @return total number of bytes written since stream start.
- */
- public final long length() {
- return count;
- }
-
- /** @return obtain the current SHA-1 digest. */
- final byte[] getDigest() {
- return md.digest();
+ getWriteMonitor().update(1);
}
}