Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions dev-support/spotbugs-exclude.xml
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,16 @@
<Bug pattern="ML_SYNC_ON_UPDATED_FIELD"/>
</Match>

<!--
Given it's a singleton, the instance must be returned. We need the same instance to be shared
between all BlockCacheKey objects, as well as the BucketCache instance.
-->
<Match>
<Class name="org.apache.hadoop.hbase.io.hfile.bucket.FilePathStringPool"/>
<Or>
<Method name="getInstance"/>
</Or>
<Bug pattern="MS_EXPOSE_REP"/>
</Match>

</FindBugsFilter>
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ message BlockCacheKey {
required int64 offset = 2;
required BlockType block_type = 3;
required bool primary_replica_block = 4;
optional string region_name = 5;
optional string family_name = 6;
optional bool archived = 7;
}

enum BlockType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,6 @@ Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,
*/
int evictBlocksByHfileName(String hfileName);

/**
* Evicts all blocks for the given HFile by path.
* @return the number of blocks evicted
*/
default int evictBlocksByHfilePath(Path hfilePath) {
return evictBlocksByHfileName(hfilePath.getName());
}

/**
* Get the statistics for this block cache.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,83 +19,156 @@

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.io.HeapSize;
import org.apache.hadoop.hbase.io.hfile.bucket.FilePathStringPool;
import org.apache.hadoop.hbase.util.ClassSize;
import org.apache.hadoop.hbase.util.HFileArchiveUtil;
import org.apache.yetus.audience.InterfaceAudience;

/**
* Cache Key for use with implementations of {@link BlockCache}
*/
@InterfaceAudience.Private
public class BlockCacheKey implements HeapSize, java.io.Serializable {
private static final long serialVersionUID = -5199992013113130534L;
private final String hfileName;
private static final long serialVersionUID = -5199992013113130535L; // Changed due to format
// change

// New compressed format using integer file ID (when codec is available)
private final int hfileNameId;

private transient final FilePathStringPool stringPool;

private final int regionId;

private final int cfId;

private final long offset;

private BlockType blockType;

private final boolean isPrimaryReplicaBlock;

private Path filePath;
private final boolean archived;

/**
* Construct a new BlockCacheKey
* Constructs a new BlockCacheKey with the file name and offset only. To be used for cache lookups
* only, DO NOT use this for creating keys when inserting into the cache. Use either the
* overriding constructors with the path parameter or the region and cf parameters, otherwise,
* region cache metrics won't be recorded properly.
* @param hfileName The name of the HFile this block belongs to.
* @param offset Offset of the block into the file
*/
public BlockCacheKey(String hfileName, long offset) {
this(hfileName, offset, true, BlockType.DATA);
this(hfileName, null, null, offset, true, BlockType.DATA, false);
}

/**
* Constructs a new BlockCacheKey with the file name, offset, replica and type only. To be used
* for cache lookups only, DO NOT use this for creating keys when inserting into the cache. Use
* either the overriding constructors with the path parameter or the region and cf parameters,
* otherwise, region cache metrics won't be recorded properly.
* @param hfileName The name of the HFile this block belongs to.
* @param offset Offset of the block into the file
* @param isPrimaryReplica Whether this is from primary replica
* @param blockType Type of block
*/
public BlockCacheKey(String hfileName, long offset, boolean isPrimaryReplica,
BlockType blockType) {
this(hfileName, null, null, offset, isPrimaryReplica, blockType, false);
}

/**
* Construct a new BlockCacheKey, with file, column family and region information. This should be
* used when inserting keys into the cache, so that region cache metrics are recorded properly.
* @param hfileName The name of the HFile this block belongs to.
* @param cfName The column family name
* @param regionName The region name
* @param offset Offset of the block into the file
* @param isPrimaryReplica Whether this is from primary replica
* @param blockType Type of block
*/
public BlockCacheKey(String hfileName, String cfName, String regionName, long offset,
boolean isPrimaryReplica, BlockType blockType, boolean archived) {
this.isPrimaryReplicaBlock = isPrimaryReplica;
this.hfileName = hfileName;
this.offset = offset;
this.blockType = blockType;
this.stringPool = FilePathStringPool.getInstance();
// Use string pool for file, region and cf values
this.hfileNameId = stringPool.encode(hfileName);
this.regionId = (regionName != null) ? stringPool.encode(regionName) : -1;
this.cfId = (cfName != null) ? stringPool.encode(cfName) : -1;
this.archived = archived;
}

/**
* Construct a new BlockCacheKey using a file path. File, column family and region information
* will be extracted from the passed path. This should be used when inserting keys into the cache,
* so that region cache metrics are recorded properly.
* @param hfilePath The path to the HFile
* @param offset Offset of the block into the file
* @param isPrimaryReplica Whether this is from primary replica
* @param blockType Type of block
*/
public BlockCacheKey(Path hfilePath, long offset, boolean isPrimaryReplica, BlockType blockType) {
this.filePath = hfilePath;
this.isPrimaryReplicaBlock = isPrimaryReplica;
this.hfileName = hfilePath.getName();
this.offset = offset;
this.blockType = blockType;
this(hfilePath.getName(), hfilePath.getParent().getName(),
hfilePath.getParent().getParent().getName(), offset, isPrimaryReplica, blockType,
HFileArchiveUtil.isHFileArchived(hfilePath));
}

@Override
public int hashCode() {
return hfileName.hashCode() * 127 + (int) (offset ^ (offset >>> 32));
return hfileNameId * 127 + (int) (offset ^ (offset >>> 32));
}

@Override
public boolean equals(Object o) {
if (o instanceof BlockCacheKey) {
BlockCacheKey k = (BlockCacheKey) o;
return offset == k.offset
&& (hfileName == null ? k.hfileName == null : hfileName.equals(k.hfileName));
} else {
return false;
if (offset != k.offset) {
return false;
}
return getHfileName().equals(k.getHfileName());
}
return false;
}

@Override
public String toString() {
return this.hfileName + '_' + this.offset;
return getHfileName() + '_' + this.offset;
}

public static final long FIXED_OVERHEAD = ClassSize.estimateBase(BlockCacheKey.class, false);

/**
* Strings have two bytes per character due to default Java Unicode encoding (hence length times
* 2).
* With the compressed format using integer file IDs, the heap size is significantly reduced. We
* now only store a 4-byte integer instead of the full file name string.
*/
@Override
public long heapSize() {
return ClassSize.align(FIXED_OVERHEAD + ClassSize.STRING + 2 * hfileName.length());
return ClassSize.align(FIXED_OVERHEAD);
}

// can't avoid this unfortunately
/** Returns The hfileName portion of this cache key */
/**
* Returns the hfileName portion of this cache key.
* @return The file name
*/
public String getHfileName() {
return hfileName;
return stringPool.decode(hfileNameId);
}

/**
* Returns the region name portion of this cache key.
* @return The region name
*/
public String getRegionName() {
return stringPool.decode(regionId);
}

/**
* Returns the column family name portion of this cache key.
* @return The column family name
*/
public String getCfName() {
return stringPool.decode(cfId);
}

public boolean isPrimary() {
Expand All @@ -114,12 +187,8 @@ public void setBlockType(BlockType blockType) {
this.blockType = blockType;
}

public Path getFilePath() {
return filePath;
}

public void setFilePath(Path filePath) {
this.filePath = filePath;
public boolean isArchived() {
return archived;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,6 @@ public int evictBlocksByHfileName(String hfileName) {
return l1Cache.evictBlocksByHfileName(hfileName) + l2Cache.evictBlocksByHfileName(hfileName);
}

@Override
public int evictBlocksByHfilePath(Path hfilePath) {
return l1Cache.evictBlocksByHfilePath(hfilePath) + l2Cache.evictBlocksByHfilePath(hfilePath);
}

@Override
public CacheStats getStats() {
return this.combinedCacheStats;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public void close(boolean evictOnClose) throws IOException {
// Deallocate data blocks
cacheConf.getBlockCache().ifPresent(cache -> {
if (evictOnClose) {
int numEvicted = cache.evictBlocksByHfilePath(path);
int numEvicted = cache.evictBlocksByHfileName(name);
if (LOG.isTraceEnabled()) {
LOG.trace("On close, file= {} evicted= {} block(s)", name, numEvicted);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,7 @@ public HFileBlock getMetaBlock(String metaBlockName, boolean cacheBlock) throws
// Check cache for block. If found return.
long metaBlockOffset = metaBlockIndexReader.getRootBlockOffset(block);
BlockCacheKey cacheKey =
new BlockCacheKey(name, metaBlockOffset, this.isPrimaryReplicaReader(), BlockType.META);
new BlockCacheKey(path, metaBlockOffset, this.isPrimaryReplicaReader(), BlockType.META);

cacheBlock &=
cacheConf.shouldCacheBlockOnRead(BlockType.META.getCategory(), getHFileInfo(), conf);
Expand Down
Loading