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.KeyValue;
26  import org.apache.hadoop.hbase.util.Bytes;
27  import org.apache.hadoop.io.WritableUtils;
28  
29  /**
30   * DO NOT USE. This class is deprecated and should only be used in pre-PB WAL.
31   * 
32   * Compression class for {@link KeyValue}s written to the WAL. This is not
33   * synchronized, so synchronization should be handled outside.
34   * 
35   * Class only compresses and uncompresses row keys, family names, and the
36   * qualifier. More may be added depending on use patterns.
37   */
38  @Deprecated
39  class KeyValueCompression {
40    /**
41     * Uncompresses a KeyValue from a DataInput and returns it.
42     * 
43     * @param in the DataInput
44     * @param readContext the compressionContext to use.
45     * @return an uncompressed KeyValue
46     * @throws IOException
47     */
48  
49    public static KeyValue readKV(DataInput in, CompressionContext readContext)
50        throws IOException {
51      int keylength = WritableUtils.readVInt(in);
52      int vlength = WritableUtils.readVInt(in);
53      int tagsLength = WritableUtils.readVInt(in);
54      int length = (int) KeyValue.getKeyValueDataStructureSize(keylength, vlength, tagsLength);
55  
56      byte[] backingArray = new byte[length];
57      int pos = 0;
58      pos = Bytes.putInt(backingArray, pos, keylength);
59      pos = Bytes.putInt(backingArray, pos, vlength);
60  
61      // the row
62      int elemLen = Compressor.uncompressIntoArray(backingArray,
63          pos + Bytes.SIZEOF_SHORT, in, readContext.rowDict);
64      checkLength(elemLen, Short.MAX_VALUE);
65      pos = Bytes.putShort(backingArray, pos, (short)elemLen);
66      pos += elemLen;
67  
68      // family
69      elemLen = Compressor.uncompressIntoArray(backingArray,
70          pos + Bytes.SIZEOF_BYTE, in, readContext.familyDict);
71      checkLength(elemLen, Byte.MAX_VALUE);
72      pos = Bytes.putByte(backingArray, pos, (byte)elemLen);
73      pos += elemLen;
74  
75      // qualifier
76      elemLen = Compressor.uncompressIntoArray(backingArray, pos, in,
77          readContext.qualifierDict);
78      pos += elemLen;
79  
80      // the rest
81      in.readFully(backingArray, pos, length - pos);
82  
83      return new KeyValue(backingArray, 0, length);
84    }
85  
86    private static void checkLength(int len, int max) throws IOException {
87      if (len < 0 || len > max) {
88        throw new IOException(
89            "Invalid length for compresesed portion of keyvalue: " + len);
90      }
91    }
92  
93    /**
94     * Compresses and writes ourKV to out, a DataOutput.
95     * 
96     * @param out the DataOutput
97     * @param keyVal the KV to compress and write
98     * @param writeContext the compressionContext to use.
99     * @throws IOException
100    */
101   public static void writeKV(final DataOutput out, KeyValue keyVal,
102       CompressionContext writeContext) throws IOException {
103     byte[] backingArray = keyVal.getBuffer();
104     int offset = keyVal.getOffset();
105 
106     // we first write the KeyValue infrastructure as VInts.
107     WritableUtils.writeVInt(out, keyVal.getKeyLength());
108     WritableUtils.writeVInt(out, keyVal.getValueLength());
109     WritableUtils.writeVInt(out, keyVal.getTagsLength());
110 
111     // now we write the row key, as the row key is likely to be repeated
112     // We save space only if we attempt to compress elements with duplicates
113     Compressor.writeCompressed(keyVal.getBuffer(), keyVal.getRowOffset(),
114         keyVal.getRowLength(), out, writeContext.rowDict);
115 
116   
117     // now family, if it exists. if it doesn't, we write a 0 length array.
118     Compressor.writeCompressed(keyVal.getBuffer(), keyVal.getFamilyOffset(),
119         keyVal.getFamilyLength(), out, writeContext.familyDict);
120 
121     // qualifier next
122     Compressor.writeCompressed(keyVal.getBuffer(), keyVal.getQualifierOffset(),
123         keyVal.getQualifierLength(), out,
124         writeContext.qualifierDict);
125 
126     // now we write the rest uncompressed
127     int pos = keyVal.getTimestampOffset();
128     int remainingLength = keyVal.getLength() + offset - (pos);
129     out.write(backingArray, pos, remainingLength);
130   }
131 }