diff --git a/src/main/java/org/apache/hadoop/hbase/io/hfile/slab/SingleSizeCache.java b/src/main/java/org/apache/hadoop/hbase/io/hfile/slab/SingleSizeCache.java index 47b9fd7..06f3fa7 100644 --- a/src/main/java/org/apache/hadoop/hbase/io/hfile/slab/SingleSizeCache.java +++ b/src/main/java/org/apache/hadoop/hbase/io/hfile/slab/SingleSizeCache.java @@ -118,8 +118,16 @@ public class SingleSizeCache implements BlockCache { @Override public synchronized void cacheBlock(String blockName, Cacheable toBeCached) { - ByteBuffer storedBlock = backingStore.alloc(toBeCached - .getSerializedLength()); + ByteBuffer storedBlock; + + /* + * Spinlock if empty, Guava Mapmaker guarantees that we will not store more + * items than the memory we have allocated, but the Slab Allocator may still + * be empty if we have not yet completed eviction + */ + do { + storedBlock = backingStore.alloc(toBeCached.getSerializedLength()); + } while (storedBlock == null); CacheablePair newEntry = new CacheablePair(toBeCached.getDeserializer(), storedBlock); diff --git a/src/main/java/org/apache/hadoop/hbase/io/hfile/slab/Slab.java b/src/main/java/org/apache/hadoop/hbase/io/hfile/slab/Slab.java index 7078125..9811c6b 100644 --- a/src/main/java/org/apache/hadoop/hbase/io/hfile/slab/Slab.java +++ b/src/main/java/org/apache/hadoop/hbase/io/hfile/slab/Slab.java @@ -108,16 +108,17 @@ class Slab implements org.apache.hadoop.hbase.io.HeapSize { } /* - * This spinlocks if empty. Make sure your program can deal with that, and - * will complete eviction on time. + * This returns null if empty. Throws an exception if you try to allocate a + * bigger size than the allocator can handle. */ ByteBuffer alloc(int bufferSize) { int newCapacity = Preconditions.checkPositionIndex(bufferSize, blockSize); ByteBuffer returnedBuffer = buffers.poll(); - while(returnedBuffer == null){ - returnedBuffer = buffers.poll(); + if (returnedBuffer == null) { + return null; } + returnedBuffer.clear().limit(newCapacity); return returnedBuffer; }