/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.hbase.codec.prefixtree.encode.column; import java.io.IOException; import java.io.OutputStream; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.codec.prefixtree.PrefixTreeBlockMeta; import org.apache.hadoop.hbase.codec.prefixtree.encode.other.ColumnNodeType; import org.apache.hadoop.hbase.codec.prefixtree.encode.tokenize.TokenizerNode; import org.apache.hadoop.hbase.util.ByteRange; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Strings; import org.apache.hadoop.hbase.util.vint.UFIntTool; import org.apache.hadoop.hbase.util.vint.UVIntTool; /** * <p> * Column nodes can be either family nodes or qualifier nodes, as both sections encode similarly. * The family and qualifier sections of the data block are made of 1 or more of these nodes. * </p> * Each node is composed of 3 sections:<br> * <ul> * <li>tokenLength: UVInt (normally 1 byte) indicating the number of token bytes * <li>token[]: the actual token bytes * <li>parentStartPosition: the offset of the next node from the start of the family or qualifier * section * </ul> */ @InterfaceAudience.Private public class ColumnNodeWriter{ /************* fields ****************************/ protected TokenizerNode builderNode; protected PrefixTreeBlockMeta blockMeta; protected int tokenLength; protected byte[] token; protected int parentStartPosition; protected ColumnNodeType nodeType; /*************** construct **************************/ public ColumnNodeWriter(PrefixTreeBlockMeta blockMeta, TokenizerNode builderNode, ColumnNodeType nodeType) { this.blockMeta = blockMeta; this.builderNode = builderNode; this.nodeType = nodeType; calculateTokenLength(); } /************* methods *******************************/ public boolean isRoot() { return parentStartPosition == 0; } private void calculateTokenLength() { tokenLength = builderNode.getTokenLength(); token = new byte[tokenLength]; } /** * This method is called before blockMeta.qualifierOffsetWidth is known, so we pass in a * placeholder. * @param offsetWidthPlaceholder the placeholder * @return node width */ public int getWidthUsingPlaceholderForOffsetWidth(int offsetWidthPlaceholder) { int width = 0; width += UVIntTool.numBytes(tokenLength); width += token.length; width += offsetWidthPlaceholder; return width; } public void writeBytes(OutputStream os) throws IOException { int parentOffsetWidth; if (this.nodeType == ColumnNodeType.FAMILY) { parentOffsetWidth = blockMeta.getFamilyOffsetWidth(); } else if (this.nodeType == ColumnNodeType.QUALIFIER) { parentOffsetWidth = blockMeta.getQualifierOffsetWidth(); } else { parentOffsetWidth = blockMeta.getTagsOffsetWidth(); } UVIntTool.writeBytes(tokenLength, os); os.write(token); UFIntTool.writeBytes(parentOffsetWidth, parentStartPosition, os); } public void setTokenBytes(ByteRange source) { source.deepCopySubRangeTo(0, tokenLength, token, 0); } /****************** standard methods ************************/ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(Strings.padFront(builderNode.getOutputArrayOffset() + "", ' ', 3) + ","); sb.append("["); sb.append(Bytes.toString(token)); sb.append("]->"); sb.append(parentStartPosition); return sb.toString(); } /************************** get/set ***********************/ public void setParentStartPosition(int parentStartPosition) { this.parentStartPosition = parentStartPosition; } }