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.codec.prefixtree.encode.column;
20  
21  import java.io.IOException;
22  import java.io.OutputStream;
23  
24  import org.apache.hadoop.classification.InterfaceAudience;
25  import org.apache.hadoop.hbase.codec.prefixtree.PrefixTreeBlockMeta;
26  import org.apache.hadoop.hbase.codec.prefixtree.encode.tokenize.TokenizerNode;
27  import org.apache.hadoop.hbase.util.ByteRange;
28  import org.apache.hadoop.hbase.util.Bytes;
29  import org.apache.hadoop.hbase.util.Strings;
30  import org.apache.hadoop.hbase.util.vint.UFIntTool;
31  import org.apache.hadoop.hbase.util.vint.UVIntTool;
32  
33  /**
34   * Column nodes can be either family nodes or qualifier nodes, as both sections encode similarly.
35   * The family and qualifier sections of the data block are made of 1 or more of these nodes.
36   * <p/>
37   * Each node is composed of 3 sections:<br/>
38   * <li>tokenLength: UVInt (normally 1 byte) indicating the number of token bytes
39   * <li>token[]: the actual token bytes
40   * <li>parentStartPosition: the offset of the next node from the start of the family or qualifier
41   * section
42   */
43  @InterfaceAudience.Private
44  public class ColumnNodeWriter{
45  
46    /************* fields ****************************/
47  
48    protected TokenizerNode builderNode;
49    protected PrefixTreeBlockMeta blockMeta;
50  
51    protected boolean familyVsQualifier;
52  
53    protected int tokenLength;
54    protected byte[] token;
55    protected int parentStartPosition;
56  
57  
58    /*************** construct **************************/
59  
60    public ColumnNodeWriter(PrefixTreeBlockMeta blockMeta, TokenizerNode builderNode,
61        boolean familyVsQualifier) {
62      this.blockMeta = blockMeta;
63      this.builderNode = builderNode;
64      this.familyVsQualifier = familyVsQualifier;
65      calculateTokenLength();
66    }
67  
68  
69    /************* methods *******************************/
70  
71    public boolean isRoot() {
72      return parentStartPosition == 0;
73    }
74  
75    private void calculateTokenLength() {
76      tokenLength = builderNode.getTokenLength();
77      token = new byte[tokenLength];
78    }
79  
80    /**
81     * This method is called before blockMeta.qualifierOffsetWidth is known, so we pass in a
82     * placeholder.
83     * @param offsetWidthPlaceholder the placeholder
84     * @return node width
85     */
86    public int getWidthUsingPlaceholderForOffsetWidth(int offsetWidthPlaceholder) {
87      int width = 0;
88      width += UVIntTool.numBytes(tokenLength);
89      width += token.length;
90      width += offsetWidthPlaceholder;
91      return width;
92    }
93  
94    public void writeBytes(OutputStream os) throws IOException {
95      int parentOffsetWidth;
96      if (familyVsQualifier) {
97        parentOffsetWidth = blockMeta.getFamilyOffsetWidth();
98      } else {
99        parentOffsetWidth = blockMeta.getQualifierOffsetWidth();
100     }
101     UVIntTool.writeBytes(tokenLength, os);
102     os.write(token);
103     UFIntTool.writeBytes(parentOffsetWidth, parentStartPosition, os);
104   }
105 
106   public void setTokenBytes(ByteRange source) {
107     source.deepCopySubRangeTo(0, tokenLength, token, 0);
108   }
109 
110 
111   /****************** standard methods ************************/
112 
113   @Override
114   public String toString() {
115     StringBuilder sb = new StringBuilder();
116     sb.append(Strings.padFront(builderNode.getOutputArrayOffset() + "", ' ', 3) + ",");
117     sb.append("[");
118     sb.append(Bytes.toString(token));
119     sb.append("]->");
120     sb.append(parentStartPosition);
121     return sb.toString();
122   }
123 
124 
125   /************************** get/set ***********************/
126 
127   public void setParentStartPosition(int parentStartPosition) {
128     this.parentStartPosition = parentStartPosition;
129   }
130 
131 }