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.encoding; 019 020import java.io.DataInputStream; 021import java.io.DataOutputStream; 022import java.io.IOException; 023import java.nio.ByteBuffer; 024import org.apache.hadoop.hbase.Cell; 025import org.apache.hadoop.hbase.nio.ByteBuff; 026import org.apache.hadoop.hbase.util.ByteBufferUtils; 027import org.apache.hadoop.hbase.util.Bytes; 028import org.apache.yetus.audience.InterfaceAudience; 029 030/** 031 * Just copy data, do not do any kind of compression. Use for comparison and benchmarking. 032 */ 033@InterfaceAudience.Private 034public class CopyKeyDataBlockEncoder extends BufferedDataBlockEncoder { 035 036 private static class CopyKeyEncodingState extends EncodingState { 037 NoneEncoder encoder = null; 038 } 039 040 @Override 041 public void startBlockEncoding(HFileBlockEncodingContext blkEncodingCtx, DataOutputStream out) 042 throws IOException { 043 if (blkEncodingCtx.getClass() != HFileBlockDefaultEncodingContext.class) { 044 throw new IOException(this.getClass().getName() + " only accepts " 045 + HFileBlockDefaultEncodingContext.class.getName() + " as the " + "encoding context."); 046 } 047 048 HFileBlockDefaultEncodingContext encodingCtx = 049 (HFileBlockDefaultEncodingContext) blkEncodingCtx; 050 encodingCtx.prepareEncoding(out); 051 052 NoneEncoder encoder = new NoneEncoder(out, encodingCtx); 053 CopyKeyEncodingState state = new CopyKeyEncodingState(); 054 state.encoder = encoder; 055 blkEncodingCtx.setEncodingState(state); 056 } 057 058 @Override 059 public int internalEncode(Cell cell, HFileBlockDefaultEncodingContext encodingContext, 060 DataOutputStream out) throws IOException { 061 CopyKeyEncodingState state = (CopyKeyEncodingState) encodingContext.getEncodingState(); 062 NoneEncoder encoder = state.encoder; 063 return encoder.write(cell); 064 } 065 066 @Override 067 public Cell getFirstKeyCellInBlock(ByteBuff block) { 068 int keyLength = block.getIntAfterPosition(Bytes.SIZEOF_INT); 069 int pos = 3 * Bytes.SIZEOF_INT; 070 ByteBuffer key = block.asSubByteBuffer(pos + keyLength).duplicate(); 071 return createFirstKeyCell(key, keyLength); 072 } 073 074 @Override 075 public String toString() { 076 return CopyKeyDataBlockEncoder.class.getSimpleName(); 077 } 078 079 @Override 080 public EncodedSeeker createSeeker(final HFileBlockDecodingContext decodingCtx) { 081 return new SeekerStateBufferedEncodedSeeker(decodingCtx); 082 } 083 084 @Override 085 protected ByteBuffer internalDecodeKeyValues(DataInputStream source, int allocateHeaderLength, 086 int skipLastBytes, HFileBlockDefaultDecodingContext decodingCtx) throws IOException { 087 int decompressedSize = source.readInt(); 088 ByteBuffer buffer = ByteBuffer.allocate(decompressedSize + allocateHeaderLength); 089 buffer.position(allocateHeaderLength); 090 ByteBufferUtils.copyFromStreamToBuffer(buffer, source, decompressedSize); 091 092 return buffer; 093 } 094 095 private static class SeekerStateBufferedEncodedSeeker extends BufferedEncodedSeeker<SeekerState> { 096 097 private SeekerStateBufferedEncodedSeeker(HFileBlockDecodingContext decodingCtx) { 098 super(decodingCtx); 099 } 100 101 @Override 102 protected void decodeNext() { 103 current.keyLength = currentBuffer.getInt(); 104 current.valueLength = currentBuffer.getInt(); 105 current.ensureSpaceForKey(); 106 currentBuffer.get(current.keyBuffer, 0, current.keyLength); 107 current.valueOffset = currentBuffer.position(); 108 currentBuffer.skip(current.valueLength); 109 if (includesTags()) { 110 // Read short as unsigned, high byte first 111 current.tagsLength = ((currentBuffer.get() & 0xff) << 8) ^ (currentBuffer.get() & 0xff); 112 currentBuffer.skip(current.tagsLength); 113 } 114 if (includesMvcc()) { 115 current.memstoreTS = ByteBufferUtils.readVLong(currentBuffer); 116 } else { 117 current.memstoreTS = 0; 118 } 119 current.nextKvOffset = currentBuffer.position(); 120 } 121 122 @Override 123 protected void decodeFirst() { 124 currentBuffer.skip(Bytes.SIZEOF_INT); 125 current.lastCommonPrefix = 0; 126 decodeNext(); 127 } 128 } 129 130}