001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.io.hfile; 019 020import com.google.errorprone.annotations.RestrictedApi; 021import org.apache.hadoop.fs.Path; 022import org.apache.hadoop.hbase.io.HeapSize; 023import org.apache.hadoop.hbase.util.ClassSize; 024import org.apache.hadoop.hbase.util.FastStringPool; 025import org.apache.yetus.audience.InterfaceAudience; 026 027/** 028 * Cache Key for use with implementations of {@link BlockCache} 029 */ 030@InterfaceAudience.Private 031public class BlockCacheKey implements HeapSize, java.io.Serializable { 032 // Changed due to format change 033 private static final long serialVersionUID = -5199992013113130535L; 034 035 private static final FastStringPool HFILE_NAME_POOL = new FastStringPool(); 036 037 private static final FastStringPool REGION_NAME_POOL = new FastStringPool(); 038 039 private static final FastStringPool CF_NAME_POOL = new FastStringPool(); 040 041 private final String hfileName; 042 043 private final String regionName; 044 045 private final String cfName; 046 047 private final long offset; 048 049 private BlockType blockType; 050 051 private final boolean isPrimaryReplicaBlock; 052 053 private final boolean archived; 054 055 /** 056 * Constructs a new BlockCacheKey with the file name and offset only. To be used for cache lookups 057 * only, DO NOT use this for creating keys when inserting into the cache. Use either the 058 * overriding constructors with the path parameter or the region and cf parameters, otherwise, 059 * region cache metrics won't be recorded properly. 060 * @param hfileName The name of the HFile this block belongs to. 061 * @param offset Offset of the block into the file 062 */ 063 public BlockCacheKey(String hfileName, long offset) { 064 this(hfileName, null, null, offset, true, BlockType.DATA, false); 065 } 066 067 /** 068 * Constructs a new BlockCacheKey with the file name, offset, replica and type only. To be used 069 * for cache lookups only, DO NOT use this for creating keys when inserting into the cache. Use 070 * either the overriding constructors with the path parameter or the region and cf parameters, 071 * otherwise, region cache metrics won't be recorded properly. 072 * @param hfileName The name of the HFile this block belongs to. 073 * @param offset Offset of the block into the file 074 * @param isPrimaryReplica Whether this is from primary replica 075 * @param blockType Type of block 076 */ 077 public BlockCacheKey(String hfileName, long offset, boolean isPrimaryReplica, 078 BlockType blockType) { 079 this(hfileName, null, null, offset, isPrimaryReplica, blockType, false); 080 } 081 082 /** 083 * Construct a new BlockCacheKey, with file, column family and region information. This should be 084 * used when inserting keys into the cache, so that region cache metrics are recorded properly. 085 * @param hfileName The name of the HFile this block belongs to. 086 * @param cfName The column family name 087 * @param regionName The region name 088 * @param offset Offset of the block into the file 089 * @param isPrimaryReplica Whether this is from primary replica 090 * @param blockType Type of block 091 * @param archived Whether the file is archived or not. This is relevant for proper cache 092 * metrics computation. 093 */ 094 public BlockCacheKey(String hfileName, String cfName, String regionName, long offset, 095 boolean isPrimaryReplica, BlockType blockType, boolean archived) { 096 this.isPrimaryReplicaBlock = isPrimaryReplica; 097 this.offset = offset; 098 this.blockType = blockType; 099 // Use string pool for file, region and cf values 100 this.hfileName = HFILE_NAME_POOL.intern(hfileName); 101 this.regionName = (regionName != null) ? REGION_NAME_POOL.intern(regionName) : null; 102 this.cfName = (cfName != null) ? CF_NAME_POOL.intern(cfName) : null; 103 this.archived = archived; 104 } 105 106 /** 107 * Construct a new BlockCacheKey using a file path. File, column family and region information 108 * will be extracted from the passed path, so that region cache metrics are recorded properly. 109 * NOTE: This should be used when inserting keys into the cache from tests only, as the region and 110 * cf name parsing from the path can be costly and induce a 10% performance degradation on the 111 * read path, when this parsing is performed on each key creation time. 112 * @param hfilePath The path to the HFile 113 * @param offset Offset of the block into the file 114 * @param isPrimaryReplica Whether this is from primary replica 115 * @param blockType Type of block 116 */ 117 @RestrictedApi(explanation = "Should only be called in tests due to costly path parsing", 118 link = "", allowedOnPath = ".*/src/test/.*") 119 public BlockCacheKey(Path hfilePath, long offset, boolean isPrimaryReplica, BlockType blockType) { 120 this(hfilePath.getName(), hfilePath.getParent().getName(), 121 hfilePath.getParent().getParent().getName(), offset, isPrimaryReplica, blockType, false); 122 } 123 124 @Override 125 public int hashCode() { 126 return hfileName.hashCode() * 127 + (int) (offset ^ (offset >>> 32)); 127 } 128 129 @Override 130 public boolean equals(Object o) { 131 if (o instanceof BlockCacheKey) { 132 BlockCacheKey k = (BlockCacheKey) o; 133 if (offset != k.offset) { 134 return false; 135 } 136 return getHfileName().equals(k.getHfileName()); 137 } 138 return false; 139 } 140 141 @Override 142 public String toString() { 143 return getHfileName() + '_' + this.offset; 144 } 145 146 public static final long FIXED_OVERHEAD = ClassSize.estimateBase(BlockCacheKey.class, false); 147 148 /** 149 * With the compressed format using integer file IDs, the heap size is significantly reduced. We 150 * now only store a 4-byte integer instead of the full file name string. 151 */ 152 @Override 153 public long heapSize() { 154 return ClassSize.align(FIXED_OVERHEAD); 155 } 156 157 /** 158 * Returns the hfileName portion of this cache key. 159 * @return The file name 160 */ 161 public String getHfileName() { 162 return hfileName; 163 } 164 165 /** 166 * Returns the region name portion of this cache key. 167 * @return The region name 168 */ 169 public String getRegionName() { 170 return regionName; 171 } 172 173 /** 174 * Returns the column family name portion of this cache key. 175 * @return The column family name 176 */ 177 public String getCfName() { 178 return cfName; 179 } 180 181 public boolean isPrimary() { 182 return isPrimaryReplicaBlock; 183 } 184 185 public long getOffset() { 186 return offset; 187 } 188 189 public BlockType getBlockType() { 190 return blockType; 191 } 192 193 public void setBlockType(BlockType blockType) { 194 this.blockType = blockType; 195 } 196 197 public boolean isArchived() { 198 return archived; 199 } 200}