Lazily open ReadableChannel in BlockBasedFile.getOrLoadBlock

To avoid opening the readable channel in case of DfsBlockCache
hits. Also cleaning up typos around DfsBlockCache.

Change-Id: I615e349cb4838387c1e6743cdc384d1b81b54369
Signed-off-by: Minh Thai <mthai@google.com>
This commit is contained in:
Minh Thai 2019-01-09 12:53:51 -08:00
parent 23c30c6310
commit 513d80db10
4 changed files with 42 additions and 7 deletions

View File

@ -129,8 +129,8 @@ else if (size < cache.getBlockSize())
}
DfsBlock getOrLoadBlock(long pos, DfsReader ctx) throws IOException {
try (ReadableChannel rc = ctx.db.openFile(desc, ext)) {
return cache.getOrLoad(this, pos, ctx, () -> rc);
try (LazyChannel c = new LazyChannel(ctx, desc, ext)) {
return cache.getOrLoad(this, pos, ctx, c);
}
}
@ -203,4 +203,41 @@ static int read(ReadableChannel rc, ByteBuffer buf) throws IOException {
static long elapsedMicros(long start) {
return (System.nanoTime() - start) / 1000L;
}
/**
* A supplier of readable channel that opens the channel lazily.
*/
private static class LazyChannel
implements AutoCloseable, DfsBlockCache.ReadableChannelSupplier {
private final DfsReader ctx;
private final DfsPackDescription desc;
private final PackExt ext;
private ReadableChannel rc = null;
LazyChannel(DfsReader ctx, DfsPackDescription desc, PackExt ext) {
this.ctx = ctx;
this.desc = desc;
this.ext = ext;
}
@Override
public ReadableChannel get() throws IOException {
if (rc == null) {
synchronized (this) {
if (rc == null) {
rc = ctx.db.openFile(desc, ext);
}
}
}
return rc;
}
@Override
public void close() throws IOException {
if (rc != null) {
rc.close();
}
}
}
}

View File

@ -754,7 +754,7 @@ interface RefLoader<T> {
* Supplier for readable channel
*/
@FunctionalInterface
public interface ReadableChannelSupplier {
interface ReadableChannelSupplier {
/**
* @return ReadableChannel
* @throws IOException

View File

@ -212,7 +212,7 @@ public Consumer<Long> getRefLockWaitTimeConsumer() {
* consumer of wait time in milliseconds.
* @return {@code this}
*/
public DfsBlockCacheConfig setReflockWaitTimeConsumer(Consumer<Long> c) {
public DfsBlockCacheConfig setRefLockWaitTimeConsumer(Consumer<Long> c) {
refLock = c;
return this;
}

View File

@ -128,9 +128,7 @@ public ByteBuffer read(long pos, int cnt) throws IOException {
open().setReadAheadBytes(readAhead);
}
DfsBlock block = cache.getOrLoad(file, pos, ctx, () -> {
return open();
});
DfsBlock block = cache.getOrLoad(file, pos, ctx, () -> open());
if (block.start == pos && block.size() >= cnt) {
return block.zeroCopyByteBuffer(cnt);
}