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 edu.umd.cs.findbugs.annotations.Nullable; 021import org.apache.hadoop.conf.Configuration; 022import org.apache.hadoop.hbase.CellComparator; 023import org.apache.hadoop.hbase.HConstants; 024import org.apache.hadoop.hbase.InnerStoreCellComparator; 025import org.apache.hadoop.hbase.io.HeapSize; 026import org.apache.hadoop.hbase.io.compress.Compression; 027import org.apache.hadoop.hbase.io.crypto.Encryption; 028import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding; 029import org.apache.hadoop.hbase.io.encoding.IndexBlockEncoding; 030import org.apache.hadoop.hbase.util.Bytes; 031import org.apache.hadoop.hbase.util.ChecksumType; 032import org.apache.hadoop.hbase.util.ClassSize; 033import org.apache.yetus.audience.InterfaceAudience; 034 035/** 036 * Read-only HFile Context Information. Meta data that is used by HFileWriter/Readers and by 037 * HFileBlocks. Create one using the {@link HFileContextBuilder} (See HFileInfo and the HFile 038 * Trailer class). 039 * @see HFileContextBuilder 040 */ 041@InterfaceAudience.Private 042public class HFileContext implements HeapSize, Cloneable { 043 public static final long FIXED_OVERHEAD = ClassSize.estimateBase(HFileContext.class, false); 044 045 private static final int DEFAULT_BYTES_PER_CHECKSUM = 16 * 1024; 046 047 /** Whether checksum is enabled or not **/ 048 private boolean usesHBaseChecksum = true; 049 /** Whether mvcc is to be included in the Read/Write **/ 050 private boolean includesMvcc = true; 051 /** Whether tags are to be included in the Read/Write **/ 052 private boolean includesTags; 053 /** Compression algorithm used **/ 054 private Compression.Algorithm compressAlgo = Compression.Algorithm.NONE; 055 /** 056 * Details used by compression algorithm that are more efficiently loaded once and then reused 057 **/ 058 @Nullable 059 private Compression.HFileDecompressionContext decompressionContext = null; 060 /** Whether tags to be compressed or not **/ 061 private boolean compressTags; 062 /** the checksum type **/ 063 private ChecksumType checksumType = ChecksumType.getDefaultChecksumType(); 064 /** the number of bytes per checksum value **/ 065 private int bytesPerChecksum = DEFAULT_BYTES_PER_CHECKSUM; 066 /** Number of uncompressed bytes we allow per block. */ 067 private int blockSize = HConstants.DEFAULT_BLOCKSIZE; 068 private DataBlockEncoding encoding = DataBlockEncoding.NONE; 069 private IndexBlockEncoding indexBlockEncoding = IndexBlockEncoding.NONE; 070 /** Encryption algorithm and key used */ 071 private Encryption.Context cryptoContext = Encryption.Context.NONE; 072 private long fileCreateTime; 073 private String hfileName; 074 private byte[] columnFamily; 075 private byte[] tableName; 076 private CellComparator cellComparator; 077 078 // Empty constructor. Go with setters 079 public HFileContext() { 080 } 081 082 /** 083 * Copy constructor 084 */ 085 public HFileContext(HFileContext context) { 086 this.usesHBaseChecksum = context.usesHBaseChecksum; 087 this.includesMvcc = context.includesMvcc; 088 this.includesTags = context.includesTags; 089 this.compressAlgo = context.compressAlgo; 090 this.decompressionContext = context.decompressionContext; 091 this.compressTags = context.compressTags; 092 this.checksumType = context.checksumType; 093 this.bytesPerChecksum = context.bytesPerChecksum; 094 this.blockSize = context.blockSize; 095 this.encoding = context.encoding; 096 this.cryptoContext = context.cryptoContext; 097 this.fileCreateTime = context.fileCreateTime; 098 this.hfileName = context.hfileName; 099 this.columnFamily = context.columnFamily; 100 this.tableName = context.tableName; 101 this.cellComparator = context.cellComparator; 102 this.indexBlockEncoding = context.indexBlockEncoding; 103 } 104 105 HFileContext(boolean useHBaseChecksum, boolean includesMvcc, boolean includesTags, 106 Compression.Algorithm compressAlgo, Compression.HFileDecompressionContext decompressionContext, 107 boolean compressTags, ChecksumType checksumType, int bytesPerChecksum, int blockSize, 108 DataBlockEncoding encoding, Encryption.Context cryptoContext, long fileCreateTime, 109 String hfileName, byte[] columnFamily, byte[] tableName, CellComparator cellComparator, 110 IndexBlockEncoding indexBlockEncoding) { 111 this.usesHBaseChecksum = useHBaseChecksum; 112 this.includesMvcc = includesMvcc; 113 this.includesTags = includesTags; 114 this.compressAlgo = compressAlgo; 115 this.decompressionContext = decompressionContext; 116 this.compressTags = compressTags; 117 this.checksumType = checksumType; 118 this.bytesPerChecksum = bytesPerChecksum; 119 this.blockSize = blockSize; 120 if (encoding != null) { 121 this.encoding = encoding; 122 } 123 if (indexBlockEncoding != null) { 124 this.indexBlockEncoding = indexBlockEncoding; 125 } 126 this.cryptoContext = cryptoContext; 127 this.fileCreateTime = fileCreateTime; 128 this.hfileName = hfileName; 129 this.columnFamily = columnFamily; 130 this.tableName = tableName; 131 // If no cellComparator specified, make a guess based off tablename. If hbase:meta, then should 132 // be the meta table comparator. Comparators are per table. 133 this.cellComparator = cellComparator != null ? cellComparator 134 : this.tableName != null 135 ? InnerStoreCellComparator.getInnerStoreCellComparator(this.tableName) 136 : InnerStoreCellComparator.INNER_STORE_COMPARATOR; 137 } 138 139 /** Returns true when on-disk blocks are compressed, and/or encrypted; false otherwise. */ 140 public boolean isCompressedOrEncrypted() { 141 Compression.Algorithm compressAlgo = getCompression(); 142 boolean compressed = compressAlgo != null && compressAlgo != Compression.Algorithm.NONE; 143 144 Encryption.Context cryptoContext = getEncryptionContext(); 145 boolean encrypted = cryptoContext != null && cryptoContext != Encryption.Context.NONE; 146 147 return compressed || encrypted; 148 } 149 150 public Compression.Algorithm getCompression() { 151 return compressAlgo; 152 } 153 154 /** 155 * Get an object that, if non-null, may be cast into a codec-specific type that exposes some 156 * information from the store-file-specific Configuration that is relevant to decompression. For 157 * example, ZSTD tables can have "hbase.io.compress.zstd.dictionary" on their table descriptor, 158 * and decompressions of blocks in that table must use that dictionary. It's cheaper for HBase to 159 * load these settings into an object of their own once and check this upon each block 160 * decompression, than it is to call into {@link Configuration#get(String)} on each block 161 * decompression. 162 */ 163 @Nullable 164 public Compression.HFileDecompressionContext getDecompressionContext() { 165 return decompressionContext; 166 } 167 168 public boolean isUseHBaseChecksum() { 169 return usesHBaseChecksum; 170 } 171 172 public boolean isIncludesMvcc() { 173 return includesMvcc; 174 } 175 176 public void setIncludesMvcc(boolean includesMvcc) { 177 this.includesMvcc = includesMvcc; 178 } 179 180 public boolean isIncludesTags() { 181 return includesTags; 182 } 183 184 public void setIncludesTags(boolean includesTags) { 185 this.includesTags = includesTags; 186 } 187 188 public void setFileCreateTime(long fileCreateTime) { 189 this.fileCreateTime = fileCreateTime; 190 } 191 192 public boolean isCompressTags() { 193 return compressTags; 194 } 195 196 public void setCompressTags(boolean compressTags) { 197 this.compressTags = compressTags; 198 } 199 200 public ChecksumType getChecksumType() { 201 return checksumType; 202 } 203 204 public int getBytesPerChecksum() { 205 return bytesPerChecksum; 206 } 207 208 public int getBlocksize() { 209 return blockSize; 210 } 211 212 public long getFileCreateTime() { 213 return fileCreateTime; 214 } 215 216 public DataBlockEncoding getDataBlockEncoding() { 217 return encoding; 218 } 219 220 public IndexBlockEncoding getIndexBlockEncoding() { 221 return indexBlockEncoding; 222 } 223 224 public Encryption.Context getEncryptionContext() { 225 return cryptoContext; 226 } 227 228 public void setEncryptionContext(Encryption.Context cryptoContext) { 229 this.cryptoContext = cryptoContext; 230 } 231 232 public String getHFileName() { 233 return this.hfileName; 234 } 235 236 public byte[] getColumnFamily() { 237 return this.columnFamily; 238 } 239 240 public byte[] getTableName() { 241 return this.tableName; 242 } 243 244 public CellComparator getCellComparator() { 245 return this.cellComparator; 246 } 247 248 /** 249 * HeapSize implementation. NOTE : The heap size should be altered when new state variable are 250 * added. 251 * @return heap size of the HFileContext 252 */ 253 @Override 254 public long heapSize() { 255 long size = FIXED_OVERHEAD; 256 if (this.hfileName != null) { 257 size += ClassSize.STRING + this.hfileName.length(); 258 } 259 if (this.columnFamily != null) { 260 size += ClassSize.sizeOfByteArray(this.columnFamily.length); 261 } 262 if (this.tableName != null) { 263 size += ClassSize.sizeOfByteArray(this.tableName.length); 264 } 265 if (this.decompressionContext != null) { 266 size += this.decompressionContext.heapSize(); 267 } 268 return size; 269 } 270 271 @Override 272 public HFileContext clone() { 273 try { 274 return (HFileContext) super.clone(); 275 } catch (CloneNotSupportedException e) { 276 throw new AssertionError(); // Won't happen 277 } 278 } 279 280 @Override 281 public String toString() { 282 StringBuilder sb = new StringBuilder(); 283 sb.append("["); 284 sb.append("usesHBaseChecksum="); 285 sb.append(usesHBaseChecksum); 286 sb.append(", checksumType="); 287 sb.append(checksumType); 288 sb.append(", bytesPerChecksum="); 289 sb.append(bytesPerChecksum); 290 sb.append(", blocksize="); 291 sb.append(blockSize); 292 sb.append(", encoding="); 293 sb.append(encoding); 294 sb.append(", indexBlockEncoding="); 295 sb.append(indexBlockEncoding); 296 sb.append(", includesMvcc="); 297 sb.append(includesMvcc); 298 sb.append(", includesTags="); 299 sb.append(includesTags); 300 sb.append(", compressAlgo="); 301 sb.append(compressAlgo); 302 sb.append(", compressTags="); 303 sb.append(compressTags); 304 sb.append(", decompressionContext="); 305 sb.append(decompressionContext); 306 sb.append(", cryptoContext=["); 307 sb.append(cryptoContext); 308 sb.append("]"); 309 if (hfileName != null) { 310 sb.append(", name="); 311 sb.append(hfileName); 312 } 313 if (tableName != null) { 314 sb.append(", tableName="); 315 sb.append(Bytes.toStringBinary(tableName)); 316 } 317 if (columnFamily != null) { 318 sb.append(", columnFamily="); 319 sb.append(Bytes.toStringBinary(columnFamily)); 320 } 321 sb.append(", cellComparator="); 322 sb.append(this.cellComparator); 323 sb.append("]"); 324 return sb.toString(); 325 } 326}