1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.hadoop.hbase.regionserver.wal; 20 21 import java.io.DataInput; 22 import java.io.DataOutput; 23 import java.io.IOException; 24 25 import org.apache.hadoop.hbase.classification.InterfaceAudience; 26 import org.apache.hadoop.hbase.KeyValue; 27 import org.apache.hadoop.hbase.util.Bytes; 28 import org.apache.hadoop.io.WritableUtils; 29 30 /** 31 * DO NOT USE. This class is deprecated and should only be used in pre-PB WAL. 32 * 33 * Compression class for {@link KeyValue}s written to the WAL. This is not 34 * synchronized, so synchronization should be handled outside. 35 * 36 * Class only compresses and uncompresses row keys, family names, and the 37 * qualifier. More may be added depending on use patterns. 38 */ 39 @Deprecated 40 @InterfaceAudience.Private 41 class KeyValueCompression { 42 /** 43 * Uncompresses a KeyValue from a DataInput and returns it. 44 * 45 * @param in the DataInput 46 * @param readContext the compressionContext to use. 47 * @return an uncompressed KeyValue 48 * @throws IOException 49 */ 50 readKV(DataInput in, CompressionContext readContext)51 public static KeyValue readKV(DataInput in, CompressionContext readContext) 52 throws IOException { 53 int keylength = WritableUtils.readVInt(in); 54 int vlength = WritableUtils.readVInt(in); 55 int tagsLength = WritableUtils.readVInt(in); 56 int length = (int) KeyValue.getKeyValueDataStructureSize(keylength, vlength, tagsLength); 57 58 byte[] backingArray = new byte[length]; 59 int pos = 0; 60 pos = Bytes.putInt(backingArray, pos, keylength); 61 pos = Bytes.putInt(backingArray, pos, vlength); 62 63 // the row 64 int elemLen = Compressor.uncompressIntoArray(backingArray, 65 pos + Bytes.SIZEOF_SHORT, in, readContext.rowDict); 66 checkLength(elemLen, Short.MAX_VALUE); 67 pos = Bytes.putShort(backingArray, pos, (short)elemLen); 68 pos += elemLen; 69 70 // family 71 elemLen = Compressor.uncompressIntoArray(backingArray, 72 pos + Bytes.SIZEOF_BYTE, in, readContext.familyDict); 73 checkLength(elemLen, Byte.MAX_VALUE); 74 pos = Bytes.putByte(backingArray, pos, (byte)elemLen); 75 pos += elemLen; 76 77 // qualifier 78 elemLen = Compressor.uncompressIntoArray(backingArray, pos, in, 79 readContext.qualifierDict); 80 pos += elemLen; 81 82 // the rest 83 in.readFully(backingArray, pos, length - pos); 84 85 return new KeyValue(backingArray, 0, length); 86 } 87 checkLength(int len, int max)88 private static void checkLength(int len, int max) throws IOException { 89 if (len < 0 || len > max) { 90 throw new IOException( 91 "Invalid length for compresesed portion of keyvalue: " + len); 92 } 93 } 94 95 /** 96 * Compresses and writes ourKV to out, a DataOutput. 97 * 98 * @param out the DataOutput 99 * @param keyVal the KV to compress and write 100 * @param writeContext the compressionContext to use. 101 * @throws IOException 102 */ writeKV(final DataOutput out, KeyValue keyVal, CompressionContext writeContext)103 public static void writeKV(final DataOutput out, KeyValue keyVal, 104 CompressionContext writeContext) throws IOException { 105 byte[] backingArray = keyVal.getBuffer(); 106 int offset = keyVal.getOffset(); 107 108 // we first write the KeyValue infrastructure as VInts. 109 WritableUtils.writeVInt(out, keyVal.getKeyLength()); 110 WritableUtils.writeVInt(out, keyVal.getValueLength()); 111 WritableUtils.writeVInt(out, keyVal.getTagsLength()); 112 113 // now we write the row key, as the row key is likely to be repeated 114 // We save space only if we attempt to compress elements with duplicates 115 Compressor.writeCompressed(keyVal.getBuffer(), keyVal.getRowOffset(), 116 keyVal.getRowLength(), out, writeContext.rowDict); 117 118 119 // now family, if it exists. if it doesn't, we write a 0 length array. 120 Compressor.writeCompressed(keyVal.getBuffer(), keyVal.getFamilyOffset(), 121 keyVal.getFamilyLength(), out, writeContext.familyDict); 122 123 // qualifier next 124 Compressor.writeCompressed(keyVal.getBuffer(), keyVal.getQualifierOffset(), 125 keyVal.getQualifierLength(), out, 126 writeContext.qualifierDict); 127 128 // now we write the rest uncompressed 129 int pos = keyVal.getTimestampOffset(); 130 int remainingLength = keyVal.getLength() + offset - (pos); 131 out.write(backingArray, pos, remainingLength); 132 } 133 } 134