001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with this 004 * work for additional information regarding copyright ownership. The ASF 005 * licenses this file to you under the Apache License, Version 2.0 (the 006 * "License"); you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations 015 * under the License. 016 */ 017package org.apache.hadoop.hbase.io.hfile; 018 019import java.io.DataOutputStream; 020import java.io.IOException; 021 022import org.apache.yetus.audience.InterfaceAudience; 023import org.apache.hadoop.hbase.Cell; 024import org.apache.hadoop.hbase.io.encoding.DataBlockEncoder; 025import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding; 026import org.apache.hadoop.hbase.io.encoding.HFileBlockDecodingContext; 027import org.apache.hadoop.hbase.io.encoding.HFileBlockDefaultDecodingContext; 028import org.apache.hadoop.hbase.io.encoding.HFileBlockDefaultEncodingContext; 029import org.apache.hadoop.hbase.io.encoding.HFileBlockEncodingContext; 030import org.apache.hadoop.hbase.io.hfile.HFile.FileInfo; 031import org.apache.hadoop.hbase.util.Bytes; 032 033/** 034 * Do different kinds of data block encoding according to column family 035 * options. 036 */ 037@InterfaceAudience.Private 038public class HFileDataBlockEncoderImpl implements HFileDataBlockEncoder { 039 private final DataBlockEncoding encoding; 040 041 /** 042 * Do data block encoding with specified options. 043 * @param encoding What kind of data block encoding will be used. 044 */ 045 public HFileDataBlockEncoderImpl(DataBlockEncoding encoding) { 046 this.encoding = encoding != null ? encoding : DataBlockEncoding.NONE; 047 } 048 049 public static HFileDataBlockEncoder createFromFileInfo( 050 FileInfo fileInfo) throws IOException { 051 DataBlockEncoding encoding = DataBlockEncoding.NONE; 052 byte[] dataBlockEncodingType = fileInfo.get(DATA_BLOCK_ENCODING); 053 if (dataBlockEncodingType != null) { 054 String dataBlockEncodingStr = Bytes.toString(dataBlockEncodingType); 055 try { 056 encoding = DataBlockEncoding.valueOf(dataBlockEncodingStr); 057 } catch (IllegalArgumentException ex) { 058 throw new IOException("Invalid data block encoding type in file info: " 059 + dataBlockEncodingStr, ex); 060 } 061 } 062 063 if (encoding == DataBlockEncoding.NONE) { 064 return NoOpDataBlockEncoder.INSTANCE; 065 } 066 return new HFileDataBlockEncoderImpl(encoding); 067 } 068 069 @Override 070 public void saveMetadata(HFile.Writer writer) throws IOException { 071 writer.appendFileInfo(DATA_BLOCK_ENCODING, encoding.getNameInBytes()); 072 } 073 074 @Override 075 public DataBlockEncoding getDataBlockEncoding() { 076 return encoding; 077 } 078 079 public boolean useEncodedScanner(boolean isCompaction) { 080 if (isCompaction && encoding == DataBlockEncoding.NONE) { 081 return false; 082 } 083 return encoding != DataBlockEncoding.NONE; 084 } 085 086 @Override 087 public DataBlockEncoding getEffectiveEncodingInCache(boolean isCompaction) { 088 if (!useEncodedScanner(isCompaction)) { 089 return DataBlockEncoding.NONE; 090 } 091 return encoding; 092 } 093 094 @Override 095 public int encode(Cell cell, HFileBlockEncodingContext encodingCtx, DataOutputStream out) 096 throws IOException { 097 return this.encoding.getEncoder().encode(cell, encodingCtx, out); 098 } 099 100 @Override 101 public boolean useEncodedScanner() { 102 return encoding != DataBlockEncoding.NONE; 103 } 104 105 106 @Override 107 public String toString() { 108 return getClass().getSimpleName() + "(encoding=" + encoding + ")"; 109 } 110 111 @Override 112 public HFileBlockEncodingContext newDataBlockEncodingContext( 113 byte[] dummyHeader, HFileContext fileContext) { 114 DataBlockEncoder encoder = encoding.getEncoder(); 115 if (encoder != null) { 116 return encoder.newDataBlockEncodingContext(encoding, dummyHeader, fileContext); 117 } 118 return new HFileBlockDefaultEncodingContext(null, dummyHeader, fileContext); 119 } 120 121 @Override 122 public HFileBlockDecodingContext newDataBlockDecodingContext(HFileContext fileContext) { 123 DataBlockEncoder encoder = encoding.getEncoder(); 124 if (encoder != null) { 125 return encoder.newDataBlockDecodingContext(fileContext); 126 } 127 return new HFileBlockDefaultDecodingContext(fileContext); 128 } 129 130 @Override 131 public void startBlockEncoding(HFileBlockEncodingContext encodingCtx, DataOutputStream out) 132 throws IOException { 133 if (this.encoding != null && this.encoding != DataBlockEncoding.NONE) { 134 this.encoding.getEncoder().startBlockEncoding(encodingCtx, out); 135 } 136 } 137 138 @Override 139 public void endBlockEncoding(HFileBlockEncodingContext encodingCtx, DataOutputStream out, 140 byte[] uncompressedBytesWithHeader, BlockType blockType) throws IOException { 141 this.encoding.getEncoder().endBlockEncoding(encodingCtx, out, uncompressedBytesWithHeader); 142 } 143}