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 length = KeyValue.KEYVALUE_INFRASTRUCTURE_SIZE + keylength + vlength;
54  
55      byte[] backingArray = new byte[length];
56      int pos = 0;
57      pos = Bytes.putInt(backingArray, pos, keylength);
58      pos = Bytes.putInt(backingArray, pos, vlength);
59  
60      // the row
61      int elemLen = Compressor.uncompressIntoArray(backingArray,
62          pos + Bytes.SIZEOF_SHORT, in, readContext.rowDict);
63      checkLength(elemLen, Short.MAX_VALUE);
64      pos = Bytes.putShort(backingArray, pos, (short)elemLen);
65      pos += elemLen;
66  
67      // family
68      elemLen = Compressor.uncompressIntoArray(backingArray,
69          pos + Bytes.SIZEOF_BYTE, in, readContext.familyDict);
70      checkLength(elemLen, Byte.MAX_VALUE);
71      pos = Bytes.putByte(backingArray, pos, (byte)elemLen);
72      pos += elemLen;
73  
74      // qualifier
75      elemLen = Compressor.uncompressIntoArray(backingArray, pos, in,
76          readContext.qualifierDict);
77      pos += elemLen;
78  
79      // the rest
80      in.readFully(backingArray, pos, length - pos);
81  
82      return new KeyValue(backingArray);
83    }
84  
85    private static void checkLength(int len, int max) throws IOException {
86      if (len < 0 || len > max) {
87        throw new IOException(
88            "Invalid length for compresesed portion of keyvalue: " + len);
89      }
90    }
91  
92    /**
93     * Compresses and writes ourKV to out, a DataOutput.
94     * 
95     * @param out the DataOutput
96     * @param keyVal the KV to compress and write
97     * @param writeContext the compressionContext to use.
98     * @throws IOException
99     */
100   public static void writeKV(final DataOutput out, KeyValue keyVal,
101       CompressionContext writeContext) throws IOException {
102     byte[] backingArray = keyVal.getBuffer();
103     int offset = keyVal.getOffset();
104 
105     // we first write the KeyValue infrastructure as VInts.
106     WritableUtils.writeVInt(out, keyVal.getKeyLength());
107     WritableUtils.writeVInt(out, keyVal.getValueLength());
108 
109     // now we write the row key, as the row key is likely to be repeated
110     // We save space only if we attempt to compress elements with duplicates
111     Compressor.writeCompressed(keyVal.getBuffer(), keyVal.getRowOffset(),
112         keyVal.getRowLength(), out, writeContext.rowDict);
113 
114   
115     // now family, if it exists. if it doesn't, we write a 0 length array.
116     Compressor.writeCompressed(keyVal.getBuffer(), keyVal.getFamilyOffset(),
117         keyVal.getFamilyLength(), out, writeContext.familyDict);
118 
119     // qualifier next
120     Compressor.writeCompressed(keyVal.getBuffer(), keyVal.getQualifierOffset(),
121         keyVal.getQualifierLength(), out,
122         writeContext.qualifierDict);
123 
124     // now we write the rest uncompressed
125     int pos = keyVal.getTimestampOffset();
126     int remainingLength = keyVal.getLength() + offset - (pos);
127     out.write(backingArray, pos, remainingLength);
128   }
129 }