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.other.ColumnNodeType;
27  import org.apache.hadoop.hbase.codec.prefixtree.encode.tokenize.TokenizerNode;
28  import org.apache.hadoop.hbase.util.ByteRange;
29  import org.apache.hadoop.hbase.util.Bytes;
30  import org.apache.hadoop.hbase.util.Strings;
31  import org.apache.hadoop.hbase.util.vint.UFIntTool;
32  import org.apache.hadoop.hbase.util.vint.UVIntTool;
33  
34  /**
35   * Column nodes can be either family nodes or qualifier nodes, as both sections encode similarly.
36   * The family and qualifier sections of the data block are made of 1 or more of these nodes.
37   * <p/>
38   * Each node is composed of 3 sections:<br/>
39   * <li>tokenLength: UVInt (normally 1 byte) indicating the number of token bytes
40   * <li>token[]: the actual token bytes
41   * <li>parentStartPosition: the offset of the next node from the start of the family or qualifier
42   * section
43   */
44  @InterfaceAudience.Private
45  public class ColumnNodeWriter{
46  
47    /************* fields ****************************/
48  
49    protected TokenizerNode builderNode;
50    protected PrefixTreeBlockMeta blockMeta;
51  
52    protected int tokenLength;
53    protected byte[] token;
54    protected int parentStartPosition;
55    protected ColumnNodeType nodeType;
56  
57  
58    /*************** construct **************************/
59  
60    public ColumnNodeWriter(PrefixTreeBlockMeta blockMeta, TokenizerNode builderNode,
61        ColumnNodeType nodeType) {
62      this.blockMeta = blockMeta;
63      this.builderNode = builderNode;
64      this.nodeType = nodeType;
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 (this.nodeType == ColumnNodeType.FAMILY) {
97        parentOffsetWidth = blockMeta.getFamilyOffsetWidth();
98      } else if (this.nodeType == ColumnNodeType.QUALIFIER) {
99        parentOffsetWidth = blockMeta.getQualifierOffsetWidth();
100     } else {
101       parentOffsetWidth = blockMeta.getTagsOffsetWidth();
102     }
103     UVIntTool.writeBytes(tokenLength, os);
104     os.write(token);
105     UFIntTool.writeBytes(parentOffsetWidth, parentStartPosition, os);
106   }
107 
108   public void setTokenBytes(ByteRange source) {
109     source.deepCopySubRangeTo(0, tokenLength, token, 0);
110   }
111 
112 
113   /****************** standard methods ************************/
114 
115   @Override
116   public String toString() {
117     StringBuilder sb = new StringBuilder();
118     sb.append(Strings.padFront(builderNode.getOutputArrayOffset() + "", ' ', 3) + ",");
119     sb.append("[");
120     sb.append(Bytes.toString(token));
121     sb.append("]->");
122     sb.append(parentStartPosition);
123     return sb.toString();
124   }
125 
126 
127   /************************** get/set ***********************/
128 
129   public void setParentStartPosition(int parentStartPosition) {
130     this.parentStartPosition = parentStartPosition;
131   }
132 
133 }