Browse Source

Strongly reference indices in DfsPackFile

DfsBlockCache.Ref might get cleared out if the JVM is running out of
memory. As a result, the index is not persisted for the request and
will be reloaded unnecessarily.

Change-Id: I3b57ad5e6673f77f2dc66177a649ac412a97fe20
Signed-off-by: Minh Thai <mthai@google.com>
stable-5.4
Minh Thai 6 years ago
parent
commit
01f084f5d9
  1. 129
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java

129
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java

@ -98,13 +98,13 @@ public final class DfsPackFile extends BlockBasedFile {
private final Object initLock = new Object(); private final Object initLock = new Object();
/** Index mapping {@link ObjectId} to position within the pack stream. */ /** Index mapping {@link ObjectId} to position within the pack stream. */
private volatile DfsBlockCache.Ref<PackIndex> index; private volatile PackIndex index;
/** Reverse version of {@link #index} mapping position to {@link ObjectId}. */ /** Reverse version of {@link #index} mapping position to {@link ObjectId}. */
private volatile DfsBlockCache.Ref<PackReverseIndex> reverseIndex; private volatile PackReverseIndex reverseIndex;
/** Index of compressed bitmap mapping entire object graph. */ /** Index of compressed bitmap mapping entire object graph. */
private volatile DfsBlockCache.Ref<PackBitmapIndex> bitmapIndex; private volatile PackBitmapIndex bitmapIndex;
/** /**
* Objects we have tried to read, and discovered to be corrupt. * Objects we have tried to read, and discovered to be corrupt.
@ -150,15 +150,15 @@ public final class DfsPackFile extends BlockBasedFile {
* @return whether the pack index file is loaded and cached in memory. * @return whether the pack index file is loaded and cached in memory.
*/ */
public boolean isIndexLoaded() { public boolean isIndexLoaded() {
DfsBlockCache.Ref<PackIndex> idxref = index; return index != null;
return idxref != null && idxref.has();
} }
void setPackIndex(PackIndex idx) { void setPackIndex(PackIndex idx) {
long objCnt = idx.getObjectCount(); long objCnt = idx.getObjectCount();
int recSize = Constants.OBJECT_ID_LENGTH + 8; int recSize = Constants.OBJECT_ID_LENGTH + 8;
long sz = objCnt * recSize; long sz = objCnt * recSize;
index = cache.putRef(desc.getStreamKey(INDEX), sz, idx); cache.putRef(desc.getStreamKey(INDEX), sz, idx);
index = idx;
} }
/** /**
@ -176,12 +176,8 @@ public final class DfsPackFile extends BlockBasedFile {
} }
private PackIndex idx(DfsReader ctx) throws IOException { private PackIndex idx(DfsReader ctx) throws IOException {
DfsBlockCache.Ref<PackIndex> idxref = index; if (index != null) {
if (idxref != null) { return index;
PackIndex idx = idxref.get();
if (idx != null) {
return idx;
}
} }
if (invalid) { if (invalid) {
@ -192,23 +188,21 @@ public final class DfsPackFile extends BlockBasedFile {
.dispatch(new BeforeDfsPackIndexLoadedEvent(this)); .dispatch(new BeforeDfsPackIndexLoadedEvent(this));
synchronized (initLock) { synchronized (initLock) {
idxref = index; if (index != null) {
if (idxref != null) { return index;
PackIndex idx = idxref.get();
if (idx != null) {
return idx;
}
} }
DfsStreamKey idxKey = desc.getStreamKey(INDEX);
try { try {
idxref = cache.getOrLoadRef(idxKey, () -> { DfsStreamKey idxKey = desc.getStreamKey(INDEX);
DfsBlockCache.Ref<PackIndex> idxref = cache.getOrLoadRef(idxKey,
() -> {
try { try {
ctx.stats.readIdx++; ctx.stats.readIdx++;
long start = System.nanoTime(); long start = System.nanoTime();
try (ReadableChannel rc = ctx.db.openFile(desc, try (ReadableChannel rc = ctx.db.openFile(desc,
INDEX)) { INDEX)) {
InputStream in = Channels.newInputStream(rc); InputStream in = Channels
.newInputStream(rc);
int wantSize = 8192; int wantSize = 8192;
int bs = rc.blockSize(); int bs = rc.blockSize();
if (0 < bs && bs < wantSize) { if (0 < bs && bs < wantSize) {
@ -216,15 +210,18 @@ public final class DfsPackFile extends BlockBasedFile {
} else if (bs <= 0) { } else if (bs <= 0) {
bs = wantSize; bs = wantSize;
} }
PackIndex idx = PackIndex PackIndex idx = PackIndex.read(
.read(new BufferedInputStream(in, bs)); new BufferedInputStream(in, bs));
int sz = (int) Math.min( int sz = (int) Math.min(
idx.getObjectCount() * REC_SIZE, idx.getObjectCount() * REC_SIZE,
Integer.MAX_VALUE); Integer.MAX_VALUE);
ctx.stats.readIdxBytes += rc.position(); ctx.stats.readIdxBytes += rc.position();
return new DfsBlockCache.Ref<>(idxKey, 0, sz, idx); index = idx;
return new DfsBlockCache.Ref<>(idxKey, 0,
sz, idx);
} finally { } finally {
ctx.stats.readIdxMicros += elapsedMicros(start); ctx.stats.readIdxMicros += elapsedMicros(
start);
} }
} catch (EOFException e) { } catch (EOFException e) {
throw new IOException(MessageFormat.format( throw new IOException(MessageFormat.format(
@ -236,15 +233,15 @@ public final class DfsPackFile extends BlockBasedFile {
desc.getFileName(INDEX)), e); desc.getFileName(INDEX)), e);
} }
}); });
PackIndex idx = idxref.get();
if (index == null && idx != null) {
index = idx;
}
return index;
} catch (IOException e) { } catch (IOException e) {
invalid = true; invalid = true;
throw e; throw e;
} }
PackIndex idx = idxref.get();
if (idx != null) {
index = idxref;
}
return idx;
} }
} }
@ -257,30 +254,24 @@ public final class DfsPackFile extends BlockBasedFile {
return null; return null;
} }
DfsBlockCache.Ref<PackBitmapIndex> idxref = bitmapIndex; if (bitmapIndex != null) {
if (idxref != null) { return bitmapIndex;
PackBitmapIndex bmidx = idxref.get();
if (bmidx != null) {
return bmidx;
}
} }
synchronized (initLock) { synchronized (initLock) {
idxref = bitmapIndex; if (bitmapIndex != null) {
if (idxref != null) { return bitmapIndex;
PackBitmapIndex bmidx = idxref.get();
if (bmidx != null) {
return bmidx;
}
} }
PackIndex idx = idx(ctx); PackIndex idx = idx(ctx);
PackReverseIndex revidx = getReverseIdx(ctx); PackReverseIndex revidx = getReverseIdx(ctx);
DfsStreamKey bitmapKey = desc.getStreamKey(BITMAP_INDEX); DfsStreamKey bitmapKey = desc.getStreamKey(BITMAP_INDEX);
idxref = cache.getOrLoadRef(bitmapKey, () -> { DfsBlockCache.Ref<PackBitmapIndex> idxref = cache
.getOrLoadRef(bitmapKey, () -> {
ctx.stats.readBitmap++; ctx.stats.readBitmap++;
long start = System.nanoTime(); long start = System.nanoTime();
try (ReadableChannel rc = ctx.db.openFile(desc, BITMAP_INDEX)) { try (ReadableChannel rc = ctx.db.openFile(desc,
BITMAP_INDEX)) {
long size; long size;
PackBitmapIndex bmidx; PackBitmapIndex bmidx;
try { try {
@ -300,59 +291,53 @@ public final class DfsPackFile extends BlockBasedFile {
ctx.stats.readIdxMicros += elapsedMicros(start); ctx.stats.readIdxMicros += elapsedMicros(start);
} }
int sz = (int) Math.min(size, Integer.MAX_VALUE); int sz = (int) Math.min(size, Integer.MAX_VALUE);
return new DfsBlockCache.Ref<>(bitmapKey, 0, sz, bmidx); bitmapIndex = bmidx;
return new DfsBlockCache.Ref<>(bitmapKey, 0, sz,
bmidx);
} catch (EOFException e) { } catch (EOFException e) {
throw new IOException( throw new IOException(MessageFormat.format(
MessageFormat.format(DfsText.get().shortReadOfIndex, DfsText.get().shortReadOfIndex,
desc.getFileName(BITMAP_INDEX)), desc.getFileName(BITMAP_INDEX)), e);
e);
} catch (IOException e) { } catch (IOException e) {
throw new IOException( throw new IOException(MessageFormat.format(
MessageFormat.format(DfsText.get().cannotReadIndex, DfsText.get().cannotReadIndex,
desc.getFileName(BITMAP_INDEX)), desc.getFileName(BITMAP_INDEX)), e);
e);
} }
}); });
PackBitmapIndex bmidx = idxref.get(); PackBitmapIndex bmidx = idxref.get();
if (bmidx != null) { if (bitmapIndex == null && bmidx != null) {
bitmapIndex = idxref; bitmapIndex = bmidx;
} }
return bmidx; return bitmapIndex;
} }
} }
PackReverseIndex getReverseIdx(DfsReader ctx) throws IOException { PackReverseIndex getReverseIdx(DfsReader ctx) throws IOException {
DfsBlockCache.Ref<PackReverseIndex> revref = reverseIndex; if (reverseIndex != null) {
if (revref != null) { return reverseIndex;
PackReverseIndex revidx = revref.get();
if (revidx != null) {
return revidx;
}
} }
synchronized (initLock) { synchronized (initLock) {
revref = reverseIndex; if (reverseIndex != null) {
if (revref != null) { return reverseIndex;
PackReverseIndex revidx = revref.get();
if (revidx != null) {
return revidx;
}
} }
PackIndex idx = idx(ctx); PackIndex idx = idx(ctx);
DfsStreamKey revKey = new DfsStreamKey.ForReverseIndex( DfsStreamKey revKey = new DfsStreamKey.ForReverseIndex(
desc.getStreamKey(INDEX)); desc.getStreamKey(INDEX));
revref = cache.getOrLoadRef(revKey, () -> { DfsBlockCache.Ref<PackReverseIndex> revref = cache
.getOrLoadRef(revKey, () -> {
PackReverseIndex revidx = new PackReverseIndex(idx); PackReverseIndex revidx = new PackReverseIndex(idx);
int sz = (int) Math.min(idx.getObjectCount() * 8, int sz = (int) Math.min(idx.getObjectCount() * 8,
Integer.MAX_VALUE); Integer.MAX_VALUE);
reverseIndex = revidx;
return new DfsBlockCache.Ref<>(revKey, 0, sz, revidx); return new DfsBlockCache.Ref<>(revKey, 0, sz, revidx);
}); });
PackReverseIndex revidx = revref.get(); PackReverseIndex revidx = revref.get();
if (revidx != null) { if (reverseIndex == null && revidx != null) {
reverseIndex = revref; reverseIndex = revidx;
} }
return revidx; return reverseIndex;
} }
} }

Loading…
Cancel
Save