View Javadoc

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  
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  
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    */
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 }