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.hadoop.hbase.Cell; 023import org.apache.hadoop.hbase.io.encoding.DataBlockEncoder; 024import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding; 025import org.apache.hadoop.hbase.io.encoding.HFileBlockDecodingContext; 026import org.apache.hadoop.hbase.io.encoding.HFileBlockDefaultDecodingContext; 027import org.apache.hadoop.hbase.io.encoding.HFileBlockDefaultEncodingContext; 028import org.apache.hadoop.hbase.io.encoding.HFileBlockEncodingContext; 029import org.apache.hadoop.hbase.util.Bytes; 030import org.apache.yetus.audience.InterfaceAudience; 031 032/** 033 * Do different kinds of data block encoding according to column family 034 * options. 035 */ 036@InterfaceAudience.Private 037public class HFileDataBlockEncoderImpl implements HFileDataBlockEncoder { 038 private final DataBlockEncoding encoding; 039 040 /** 041 * Do data block encoding with specified options. 042 * @param encoding What kind of data block encoding will be used. 043 */ 044 public HFileDataBlockEncoderImpl(DataBlockEncoding encoding) { 045 this.encoding = encoding != null ? encoding : DataBlockEncoding.NONE; 046 } 047 048 public static HFileDataBlockEncoder createFromFileInfo( 049 HFileInfo fileInfo) throws IOException { 050 DataBlockEncoding encoding = DataBlockEncoding.NONE; 051 byte[] dataBlockEncodingType = fileInfo.get(DATA_BLOCK_ENCODING); 052 if (dataBlockEncodingType != null) { 053 String dataBlockEncodingStr = Bytes.toString(dataBlockEncodingType); 054 try { 055 encoding = DataBlockEncoding.valueOf(dataBlockEncodingStr); 056 } catch (IllegalArgumentException ex) { 057 throw new IOException("Invalid data block encoding type in file info: " 058 + dataBlockEncodingStr, ex); 059 } 060 } 061 062 if (encoding == DataBlockEncoding.NONE) { 063 return NoOpDataBlockEncoder.INSTANCE; 064 } 065 return new HFileDataBlockEncoderImpl(encoding); 066 } 067 068 @Override 069 public void saveMetadata(HFile.Writer writer) throws IOException { 070 writer.appendFileInfo(DATA_BLOCK_ENCODING, encoding.getNameInBytes()); 071 } 072 073 @Override 074 public DataBlockEncoding getDataBlockEncoding() { 075 return encoding; 076 } 077 078 public boolean useEncodedScanner(boolean isCompaction) { 079 if (isCompaction && encoding == DataBlockEncoding.NONE) { 080 return false; 081 } 082 return encoding != DataBlockEncoding.NONE; 083 } 084 085 @Override 086 public DataBlockEncoding getEffectiveEncodingInCache(boolean isCompaction) { 087 if (!useEncodedScanner(isCompaction)) { 088 return DataBlockEncoding.NONE; 089 } 090 return encoding; 091 } 092 093 @Override 094 public void encode(Cell cell, HFileBlockEncodingContext encodingCtx, DataOutputStream out) 095 throws IOException { 096 this.encoding.getEncoder().encode(cell, encodingCtx, out); 097 } 098 099 @Override 100 public boolean useEncodedScanner() { 101 return encoding != DataBlockEncoding.NONE; 102 } 103 104 105 @Override 106 public String toString() { 107 return getClass().getSimpleName() + "(encoding=" + encoding + ")"; 108 } 109 110 @Override 111 public HFileBlockEncodingContext newDataBlockEncodingContext( 112 byte[] dummyHeader, HFileContext fileContext) { 113 DataBlockEncoder encoder = encoding.getEncoder(); 114 if (encoder != null) { 115 return encoder.newDataBlockEncodingContext(encoding, dummyHeader, fileContext); 116 } 117 return new HFileBlockDefaultEncodingContext(null, dummyHeader, fileContext); 118 } 119 120 @Override 121 public HFileBlockDecodingContext newDataBlockDecodingContext(HFileContext fileContext) { 122 DataBlockEncoder encoder = encoding.getEncoder(); 123 if (encoder != null) { 124 return encoder.newDataBlockDecodingContext(fileContext); 125 } 126 return new HFileBlockDefaultDecodingContext(fileContext); 127 } 128 129 @Override 130 public void startBlockEncoding(HFileBlockEncodingContext encodingCtx, DataOutputStream out) 131 throws IOException { 132 if (this.encoding != null && this.encoding != DataBlockEncoding.NONE) { 133 this.encoding.getEncoder().startBlockEncoding(encodingCtx, out); 134 } 135 } 136 137 @Override 138 public void endBlockEncoding(HFileBlockEncodingContext encodingCtx, DataOutputStream out, 139 byte[] uncompressedBytesWithHeader, BlockType blockType) throws IOException { 140 this.encoding.getEncoder().endBlockEncoding(encodingCtx, out, uncompressedBytesWithHeader); 141 } 142}