View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with this
4    * work for additional information regarding copyright ownership. The ASF
5    * licenses this file to you under the Apache License, Version 2.0 (the
6    * "License"); you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14   * License for the specific language governing permissions and limitations
15   * under the License.
16   */
17  package org.apache.hadoop.hbase.io.encoding;
18  
19  import java.nio.ByteBuffer;
20  
21  import org.apache.hadoop.hbase.KeyValue;
22  import org.apache.hadoop.hbase.util.ByteBufferUtils;
23  
24  /**
25   * Stores the state of data block encoder at the beginning of new key.
26   */
27  class CompressionState {
28    int keyLength;
29    int valueLength;
30  
31    short rowLength;
32    int prevOffset = FIRST_KEY;
33    byte familyLength;
34    int qualifierLength;
35    byte type;
36  
37    private final static int FIRST_KEY = -1;
38  
39    boolean isFirst() {
40      return prevOffset == FIRST_KEY;
41    }
42  
43    /**
44     * Analyze the key and fill the state.
45     * Uses mark() and reset() in ByteBuffer.
46     * @param in Buffer at the position where key starts
47     * @param keyLength Length of key in bytes
48     * @param valueLength Length of values in bytes
49     */
50    void readKey(ByteBuffer in, int keyLength, int valueLength) {
51      readKey(in, keyLength, valueLength, 0, null);
52    }
53  
54    /** 
55     * Analyze the key and fill the state assuming we know previous state.
56     * Uses mark() and reset() in ByteBuffer to avoid moving the position.
57     * <p>
58     * This method overrides all the fields of this instance, except
59     * {@link #prevOffset}, which is usually manipulated directly by encoders
60     * and decoders.
61     * @param in Buffer at the position where key starts
62     * @param keyLength Length of key in bytes
63     * @param valueLength Length of values in bytes
64     * @param commonPrefix how many first bytes are common with previous KeyValue
65     * @param previousState State from previous KeyValue
66     */
67    void readKey(ByteBuffer in, int keyLength, int valueLength,
68        int commonPrefix, CompressionState previousState) {
69      this.keyLength = keyLength;
70      this.valueLength = valueLength;
71  
72      // fill the state
73      in.mark(); // mark beginning of key
74  
75      if (commonPrefix < KeyValue.ROW_LENGTH_SIZE) {
76        rowLength = in.getShort();
77        ByteBufferUtils.skip(in, rowLength);
78  
79        familyLength = in.get();
80  
81        qualifierLength = keyLength - rowLength - familyLength -
82            KeyValue.KEY_INFRASTRUCTURE_SIZE;
83        ByteBufferUtils.skip(in, familyLength + qualifierLength);
84      } else {
85        rowLength = previousState.rowLength;
86        familyLength = previousState.familyLength;
87        qualifierLength = previousState.qualifierLength +
88            keyLength - previousState.keyLength;
89        ByteBufferUtils.skip(in, (KeyValue.ROW_LENGTH_SIZE +
90            KeyValue.FAMILY_LENGTH_SIZE) +
91            rowLength + familyLength + qualifierLength);
92      }
93  
94      readTimestamp(in);
95  
96      type = in.get();
97  
98      in.reset();
99    }
100 
101   protected void readTimestamp(ByteBuffer in) {
102     // used in subclasses to add timestamp to state
103     ByteBufferUtils.skip(in, KeyValue.TIMESTAMP_SIZE);
104   }
105 
106   void copyFrom(CompressionState state) {
107     keyLength = state.keyLength;
108     valueLength = state.valueLength;
109 
110     rowLength = state.rowLength;
111     prevOffset = state.prevOffset;
112     familyLength = state.familyLength;
113     qualifierLength = state.qualifierLength;
114     type = state.type;
115   }
116 }