HBASE-18641 Include block content verification logic used in lruCache in bucketCache
Signed-off-by: tedyu <yuzhihong@gmail.com>
This commit is contained in:
parent
359fed7b4b
commit
af21572427
|
@ -18,6 +18,7 @@
|
||||||
package org.apache.hadoop.hbase.io.hfile;
|
package org.apache.hadoop.hbase.io.hfile;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.NavigableMap;
|
import java.util.NavigableMap;
|
||||||
import java.util.NavigableSet;
|
import java.util.NavigableSet;
|
||||||
import java.util.concurrent.ConcurrentSkipListMap;
|
import java.util.concurrent.ConcurrentSkipListMap;
|
||||||
|
@ -26,6 +27,7 @@ import java.util.concurrent.ConcurrentSkipListSet;
|
||||||
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.hbase.metrics.impl.FastLongHistogram;
|
import org.apache.hadoop.hbase.metrics.impl.FastLongHistogram;
|
||||||
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.codehaus.jackson.JsonGenerationException;
|
import org.codehaus.jackson.JsonGenerationException;
|
||||||
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||||
import org.codehaus.jackson.map.JsonMappingException;
|
import org.codehaus.jackson.map.JsonMappingException;
|
||||||
|
@ -172,6 +174,15 @@ public class BlockCacheUtil {
|
||||||
return cbsbf;
|
return cbsbf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int compareCacheBlock(Cacheable left, Cacheable right) {
|
||||||
|
ByteBuffer l = ByteBuffer.allocate(left.getSerializedLength());
|
||||||
|
left.serialize(l);
|
||||||
|
ByteBuffer r = ByteBuffer.allocate(right.getSerializedLength());
|
||||||
|
right.serialize(r);
|
||||||
|
return Bytes.compareTo(l.array(), l.arrayOffset(), l.limit(),
|
||||||
|
r.array(), r.arrayOffset(), r.limit());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use one of these to keep a running account of cached blocks by file. Throw it away when done.
|
* Use one of these to keep a running account of cached blocks by file. Throw it away when done.
|
||||||
* This is different than metrics in that it is stats on current state of a cache.
|
* This is different than metrics in that it is stats on current state of a cache.
|
||||||
|
|
|
@ -379,7 +379,7 @@ public class LruBlockCache implements ResizableBlockCache, HeapSize {
|
||||||
LruCachedBlock cb = map.get(cacheKey);
|
LruCachedBlock cb = map.get(cacheKey);
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
// compare the contents, if they are not equal, we are in big trouble
|
// compare the contents, if they are not equal, we are in big trouble
|
||||||
if (compare(buf, cb.getBuffer()) != 0) {
|
if (BlockCacheUtil.compareCacheBlock(buf, cb.getBuffer()) != 0) {
|
||||||
throw new RuntimeException("Cached block contents differ, which should not have happened."
|
throw new RuntimeException("Cached block contents differ, which should not have happened."
|
||||||
+ "cacheKey:" + cacheKey);
|
+ "cacheKey:" + cacheKey);
|
||||||
}
|
}
|
||||||
|
@ -439,15 +439,6 @@ public class LruBlockCache implements ResizableBlockCache, HeapSize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int compare(Cacheable left, Cacheable right) {
|
|
||||||
ByteBuffer l = ByteBuffer.allocate(left.getSerializedLength());
|
|
||||||
left.serialize(l);
|
|
||||||
ByteBuffer r = ByteBuffer.allocate(right.getSerializedLength());
|
|
||||||
right.serialize(r);
|
|
||||||
return Bytes.compareTo(l.array(), l.arrayOffset(), l.limit(),
|
|
||||||
r.array(), r.arrayOffset(), r.limit());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache the block with the specified name and buffer.
|
* Cache the block with the specified name and buffer.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -589,7 +580,7 @@ public class LruBlockCache implements ResizableBlockCache, HeapSize {
|
||||||
boolean wait = getCurrentSize() < acceptableSize();
|
boolean wait = getCurrentSize() < acceptableSize();
|
||||||
boolean inMemory = block.getPriority() == BlockPriority.MEMORY;
|
boolean inMemory = block.getPriority() == BlockPriority.MEMORY;
|
||||||
((BucketCache) victimHandler).cacheBlockWithWait(block.getCacheKey(), block.getBuffer(),
|
((BucketCache) victimHandler).cacheBlockWithWait(block.getCacheKey(), block.getBuffer(),
|
||||||
inMemory, wait);
|
inMemory, true, wait);
|
||||||
} else {
|
} else {
|
||||||
victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());
|
victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());
|
||||||
}
|
}
|
||||||
|
|
|
@ -411,7 +411,7 @@ public class BucketCache implements BlockCache, HeapSize {
|
||||||
@Override
|
@Override
|
||||||
public void cacheBlock(BlockCacheKey cacheKey, Cacheable cachedItem, boolean inMemory,
|
public void cacheBlock(BlockCacheKey cacheKey, Cacheable cachedItem, boolean inMemory,
|
||||||
final boolean cacheDataInL1) {
|
final boolean cacheDataInL1) {
|
||||||
cacheBlockWithWait(cacheKey, cachedItem, inMemory, wait_when_cache);
|
cacheBlockWithWait(cacheKey, cachedItem, inMemory, cacheDataInL1, wait_when_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -422,13 +422,26 @@ public class BucketCache implements BlockCache, HeapSize {
|
||||||
* @param wait if true, blocking wait when queue is full
|
* @param wait if true, blocking wait when queue is full
|
||||||
*/
|
*/
|
||||||
public void cacheBlockWithWait(BlockCacheKey cacheKey, Cacheable cachedItem, boolean inMemory,
|
public void cacheBlockWithWait(BlockCacheKey cacheKey, Cacheable cachedItem, boolean inMemory,
|
||||||
boolean wait) {
|
boolean cacheDataInL1, boolean wait) {
|
||||||
if (LOG.isTraceEnabled()) LOG.trace("Caching key=" + cacheKey + ", item=" + cachedItem);
|
if (LOG.isTraceEnabled()) LOG.trace("Caching key=" + cacheKey + ", item=" + cachedItem);
|
||||||
if (!cacheEnabled) {
|
if (!cacheEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backingMap.containsKey(cacheKey)) {
|
if (backingMap.containsKey(cacheKey)) {
|
||||||
|
/*
|
||||||
|
* Compare already cached block only if lruBlockCache is not used to cache data blocks
|
||||||
|
*/
|
||||||
|
if (!cacheDataInL1) {
|
||||||
|
Cacheable existingBlock = getBlock(cacheKey, false, false, false);
|
||||||
|
if (BlockCacheUtil.compareCacheBlock(cachedItem, existingBlock) != 0) {
|
||||||
|
throw new RuntimeException("Cached block contents differ, which should not have happened."
|
||||||
|
+ "cacheKey:" + cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String msg = "Caching an already cached block: " + cacheKey;
|
||||||
|
msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";
|
||||||
|
LOG.warn(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue