Merge "Refactor IndexPack to use InputStream for inflation"
This commit is contained in:
commit
bc1130c6aa
|
@ -74,13 +74,14 @@
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.eclipse.jgit.lib.ObjectIdSubclassMap;
|
import org.eclipse.jgit.lib.ObjectIdSubclassMap;
|
||||||
import org.eclipse.jgit.lib.ObjectLoader;
|
import org.eclipse.jgit.lib.ObjectLoader;
|
||||||
|
import org.eclipse.jgit.lib.ObjectReader;
|
||||||
import org.eclipse.jgit.lib.ProgressMonitor;
|
import org.eclipse.jgit.lib.ProgressMonitor;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.lib.ObjectReader;
|
|
||||||
import org.eclipse.jgit.storage.file.PackIndexWriter;
|
import org.eclipse.jgit.storage.file.PackIndexWriter;
|
||||||
import org.eclipse.jgit.storage.file.PackLock;
|
import org.eclipse.jgit.storage.file.PackLock;
|
||||||
import org.eclipse.jgit.storage.pack.BinaryDelta;
|
import org.eclipse.jgit.storage.pack.BinaryDelta;
|
||||||
import org.eclipse.jgit.util.FileUtils;
|
import org.eclipse.jgit.util.FileUtils;
|
||||||
|
import org.eclipse.jgit.util.IO;
|
||||||
import org.eclipse.jgit.util.NB;
|
import org.eclipse.jgit.util.NB;
|
||||||
|
|
||||||
/** Indexes Git pack files for local use. */
|
/** Indexes Git pack files for local use. */
|
||||||
|
@ -148,7 +149,7 @@ private static enum Source {
|
||||||
*/
|
*/
|
||||||
private final ObjectDatabase objectDatabase;
|
private final ObjectDatabase objectDatabase;
|
||||||
|
|
||||||
private Inflater inflater;
|
private InflaterStream inflater;
|
||||||
|
|
||||||
private final MessageDigest objectDigest;
|
private final MessageDigest objectDigest;
|
||||||
|
|
||||||
|
@ -210,8 +211,6 @@ private static enum Source {
|
||||||
|
|
||||||
private LongMap<UnresolvedDelta> baseByPos;
|
private LongMap<UnresolvedDelta> baseByPos;
|
||||||
|
|
||||||
private byte[] skipBuffer;
|
|
||||||
|
|
||||||
private MessageDigest packDigest;
|
private MessageDigest packDigest;
|
||||||
|
|
||||||
private RandomAccessFile packOut;
|
private RandomAccessFile packOut;
|
||||||
|
@ -239,10 +238,9 @@ public IndexPack(final Repository db, final InputStream src,
|
||||||
repo = db;
|
repo = db;
|
||||||
objectDatabase = db.getObjectDatabase().newCachedDatabase();
|
objectDatabase = db.getObjectDatabase().newCachedDatabase();
|
||||||
in = src;
|
in = src;
|
||||||
inflater = InflaterCache.get();
|
inflater = new InflaterStream();
|
||||||
readCurs = objectDatabase.newReader();
|
readCurs = objectDatabase.newReader();
|
||||||
buf = new byte[BUFFER_SIZE];
|
buf = new byte[BUFFER_SIZE];
|
||||||
skipBuffer = new byte[512];
|
|
||||||
objectDigest = Constants.newMessageDigest();
|
objectDigest = Constants.newMessageDigest();
|
||||||
tempObjectId = new MutableObjectId();
|
tempObjectId = new MutableObjectId();
|
||||||
packDigest = Constants.newMessageDigest();
|
packDigest = Constants.newMessageDigest();
|
||||||
|
@ -441,7 +439,7 @@ public void index(final ProgressMonitor progress) throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
InflaterCache.release(inflater);
|
inflater.release();
|
||||||
} finally {
|
} finally {
|
||||||
inflater = null;
|
inflater = null;
|
||||||
objectDatabase.close();
|
objectDatabase.close();
|
||||||
|
@ -776,7 +774,6 @@ private void readPackFooter() throws IOException {
|
||||||
// Cleanup all resources associated with our input parsing.
|
// Cleanup all resources associated with our input parsing.
|
||||||
private void endInput() {
|
private void endInput() {
|
||||||
in = null;
|
in = null;
|
||||||
skipBuffer = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read one entire object or delta from the input.
|
// Read one entire object or delta from the input.
|
||||||
|
@ -952,65 +949,24 @@ private void sync() throws IOException {
|
||||||
|
|
||||||
private void inflateAndSkip(final Source src, final long inflatedSize)
|
private void inflateAndSkip(final Source src, final long inflatedSize)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
inflate(src, inflatedSize, skipBuffer, false /* do not keep result */);
|
final InputStream inf = inflate(src, inflatedSize);
|
||||||
|
IO.skipFully(inf, inflatedSize);
|
||||||
|
inf.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] inflateAndReturn(final Source src, final long inflatedSize)
|
private byte[] inflateAndReturn(final Source src, final long inflatedSize)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final byte[] dst = new byte[(int) inflatedSize];
|
final byte[] dst = new byte[(int) inflatedSize];
|
||||||
inflate(src, inflatedSize, dst, true /* keep result in dst */);
|
final InputStream inf = inflate(src, inflatedSize);
|
||||||
|
IO.readFully(inf, dst, 0, dst.length);
|
||||||
|
inf.close();
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void inflate(final Source src, final long inflatedSize,
|
private InputStream inflate(final Source src, final long inflatedSize)
|
||||||
final byte[] dst, final boolean keep) throws IOException {
|
throws IOException {
|
||||||
final Inflater inf = inflater;
|
inflater.open(src, inflatedSize);
|
||||||
try {
|
return inflater;
|
||||||
int off = 0;
|
|
||||||
long cnt = 0;
|
|
||||||
int p = fill(src, 24);
|
|
||||||
inf.setInput(buf, p, bAvail);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
int r = inf.inflate(dst, off, dst.length - off);
|
|
||||||
if (r == 0) {
|
|
||||||
if (inf.finished())
|
|
||||||
break;
|
|
||||||
if (inf.needsInput()) {
|
|
||||||
if (p >= 0) {
|
|
||||||
crc.update(buf, p, bAvail);
|
|
||||||
use(bAvail);
|
|
||||||
}
|
|
||||||
p = fill(src, 24);
|
|
||||||
inf.setInput(buf, p, bAvail);
|
|
||||||
} else {
|
|
||||||
throw new CorruptObjectException(MessageFormat.format(
|
|
||||||
JGitText.get().packfileCorruptionDetected,
|
|
||||||
JGitText.get().unknownZlibError));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cnt += r;
|
|
||||||
if (keep)
|
|
||||||
off += r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cnt != inflatedSize) {
|
|
||||||
throw new CorruptObjectException(MessageFormat.format(JGitText
|
|
||||||
.get().packfileCorruptionDetected,
|
|
||||||
JGitText.get().wrongDecompressedLength));
|
|
||||||
}
|
|
||||||
|
|
||||||
int left = bAvail - inf.getRemaining();
|
|
||||||
if (left > 0) {
|
|
||||||
crc.update(buf, p, left);
|
|
||||||
use(left);
|
|
||||||
}
|
|
||||||
} catch (DataFormatException dfe) {
|
|
||||||
throw new CorruptObjectException(MessageFormat.format(JGitText
|
|
||||||
.get().packfileCorruptionDetected, dfe.getMessage()));
|
|
||||||
} finally {
|
|
||||||
inf.reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DeltaChain extends ObjectId {
|
private static class DeltaChain extends ObjectId {
|
||||||
|
@ -1165,4 +1121,111 @@ private void addObjectAndTrack(PackedObjectInfo oe) {
|
||||||
if (needNewObjectIds())
|
if (needNewObjectIds())
|
||||||
newObjectIds.add(oe);
|
newObjectIds.add(oe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class InflaterStream extends InputStream {
|
||||||
|
private final Inflater inf;
|
||||||
|
|
||||||
|
private final byte[] skipBuffer;
|
||||||
|
|
||||||
|
private Source src;
|
||||||
|
|
||||||
|
private long expectedSize;
|
||||||
|
|
||||||
|
private long actualSize;
|
||||||
|
|
||||||
|
private int p;
|
||||||
|
|
||||||
|
InflaterStream() {
|
||||||
|
inf = InflaterCache.get();
|
||||||
|
skipBuffer = new byte[512];
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() {
|
||||||
|
inf.reset();
|
||||||
|
InflaterCache.release(inf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void open(Source source, long inflatedSize) throws IOException {
|
||||||
|
src = source;
|
||||||
|
expectedSize = inflatedSize;
|
||||||
|
actualSize = 0;
|
||||||
|
|
||||||
|
p = fill(src, 24);
|
||||||
|
inf.setInput(buf, p, bAvail);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long skip(long toSkip) throws IOException {
|
||||||
|
long n = 0;
|
||||||
|
while (n < toSkip) {
|
||||||
|
final int cnt = (int) Math.min(skipBuffer.length, toSkip - n);
|
||||||
|
final int r = read(skipBuffer, 0, cnt);
|
||||||
|
if (r <= 0)
|
||||||
|
break;
|
||||||
|
n += r;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
int n = read(skipBuffer, 0, 1);
|
||||||
|
return n == 1 ? skipBuffer[0] & 0xff : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] dst, int pos, int cnt) throws IOException {
|
||||||
|
try {
|
||||||
|
int n = 0;
|
||||||
|
while (n < cnt) {
|
||||||
|
int r = inf.inflate(dst, pos + n, cnt - n);
|
||||||
|
if (r == 0) {
|
||||||
|
if (inf.finished())
|
||||||
|
break;
|
||||||
|
if (inf.needsInput()) {
|
||||||
|
crc.update(buf, p, bAvail);
|
||||||
|
use(bAvail);
|
||||||
|
|
||||||
|
p = fill(src, 24);
|
||||||
|
inf.setInput(buf, p, bAvail);
|
||||||
|
} else {
|
||||||
|
throw new CorruptObjectException(
|
||||||
|
MessageFormat
|
||||||
|
.format(
|
||||||
|
JGitText.get().packfileCorruptionDetected,
|
||||||
|
JGitText.get().unknownZlibError));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
n += r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actualSize += n;
|
||||||
|
return 0 < n ? n : -1;
|
||||||
|
} catch (DataFormatException dfe) {
|
||||||
|
throw new CorruptObjectException(MessageFormat.format(JGitText
|
||||||
|
.get().packfileCorruptionDetected, dfe.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
// We need to read here to enter the loop above and pump the
|
||||||
|
// trailing checksum into the Inflater. It should return -1 as the
|
||||||
|
// caller was supposed to consume all content.
|
||||||
|
//
|
||||||
|
if (read(skipBuffer) != -1 || actualSize != expectedSize) {
|
||||||
|
throw new CorruptObjectException(MessageFormat.format(JGitText
|
||||||
|
.get().packfileCorruptionDetected,
|
||||||
|
JGitText.get().wrongDecompressedLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
int used = bAvail - inf.getRemaining();
|
||||||
|
if (0 < used) {
|
||||||
|
crc.update(buf, p, used);
|
||||||
|
use(used);
|
||||||
|
}
|
||||||
|
|
||||||
|
inf.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue