001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.hbase.thrift; 020 021import static org.apache.hadoop.hbase.util.Bytes.getBytes; 022 023import java.nio.ByteBuffer; 024import java.util.ArrayList; 025import java.util.List; 026import java.util.Locale; 027import java.util.TreeMap; 028 029import org.apache.hadoop.hbase.Cell; 030import org.apache.hadoop.hbase.CellUtil; 031import org.apache.hadoop.hbase.HColumnDescriptor; 032import org.apache.hadoop.hbase.KeyValue; 033import org.apache.hadoop.hbase.client.Append; 034import org.apache.hadoop.hbase.client.Increment; 035import org.apache.hadoop.hbase.client.Result; 036import org.apache.hadoop.hbase.io.compress.Compression; 037import org.apache.hadoop.hbase.regionserver.BloomType; 038import org.apache.hadoop.hbase.thrift.generated.ColumnDescriptor; 039import org.apache.hadoop.hbase.thrift.generated.IllegalArgument; 040import org.apache.hadoop.hbase.thrift.generated.TAppend; 041import org.apache.hadoop.hbase.thrift.generated.TCell; 042import org.apache.hadoop.hbase.thrift.generated.TColumn; 043import org.apache.hadoop.hbase.thrift.generated.TIncrement; 044import org.apache.hadoop.hbase.thrift.generated.TRowResult; 045import org.apache.hadoop.hbase.util.Bytes; 046import org.apache.yetus.audience.InterfaceAudience; 047 048@InterfaceAudience.Private 049public class ThriftUtilities { 050 051 /** 052 * This utility method creates a new Hbase HColumnDescriptor object based on a 053 * Thrift ColumnDescriptor "struct". 054 * 055 * @param in 056 * Thrift ColumnDescriptor object 057 * @return HColumnDescriptor 058 * @throws IllegalArgument 059 */ 060 static public HColumnDescriptor colDescFromThrift(ColumnDescriptor in) 061 throws IllegalArgument { 062 Compression.Algorithm comp = 063 Compression.getCompressionAlgorithmByName(in.compression.toLowerCase(Locale.ROOT)); 064 BloomType bt = 065 BloomType.valueOf(in.bloomFilterType); 066 067 if (in.name == null || !in.name.hasRemaining()) { 068 throw new IllegalArgument("column name is empty"); 069 } 070 byte [] parsedName = CellUtil.parseColumn(Bytes.getBytes(in.name))[0]; 071 HColumnDescriptor col = new HColumnDescriptor(parsedName) 072 .setMaxVersions(in.maxVersions) 073 .setCompressionType(comp) 074 .setInMemory(in.inMemory) 075 .setBlockCacheEnabled(in.blockCacheEnabled) 076 .setTimeToLive(in.timeToLive > 0 ? in.timeToLive : Integer.MAX_VALUE) 077 .setBloomFilterType(bt); 078 return col; 079 } 080 081 /** 082 * This utility method creates a new Thrift ColumnDescriptor "struct" based on 083 * an Hbase HColumnDescriptor object. 084 * 085 * @param in 086 * Hbase HColumnDescriptor object 087 * @return Thrift ColumnDescriptor 088 */ 089 static public ColumnDescriptor colDescFromHbase(HColumnDescriptor in) { 090 ColumnDescriptor col = new ColumnDescriptor(); 091 col.name = ByteBuffer.wrap(Bytes.add(in.getName(), KeyValue.COLUMN_FAMILY_DELIM_ARRAY)); 092 col.maxVersions = in.getMaxVersions(); 093 col.compression = in.getCompressionType().toString(); 094 col.inMemory = in.isInMemory(); 095 col.blockCacheEnabled = in.isBlockCacheEnabled(); 096 col.bloomFilterType = in.getBloomFilterType().toString(); 097 col.timeToLive = in.getTimeToLive(); 098 return col; 099 } 100 101 /** 102 * This utility method creates a list of Thrift TCell "struct" based on 103 * an Hbase Cell object. The empty list is returned if the input is null. 104 * 105 * @param in 106 * Hbase Cell object 107 * @return Thrift TCell array 108 */ 109 static public List<TCell> cellFromHBase(Cell in) { 110 List<TCell> list = new ArrayList<>(1); 111 if (in != null) { 112 list.add(new TCell(ByteBuffer.wrap(CellUtil.cloneValue(in)), in.getTimestamp())); 113 } 114 return list; 115 } 116 117 /** 118 * This utility method creates a list of Thrift TCell "struct" based on 119 * an Hbase Cell array. The empty list is returned if the input is null. 120 * @param in Hbase Cell array 121 * @return Thrift TCell array 122 */ 123 static public List<TCell> cellFromHBase(Cell[] in) { 124 List<TCell> list = null; 125 if (in != null) { 126 list = new ArrayList<>(in.length); 127 for (int i = 0; i < in.length; i++) { 128 list.add(new TCell(ByteBuffer.wrap(CellUtil.cloneValue(in[i])), in[i].getTimestamp())); 129 } 130 } else { 131 list = new ArrayList<>(0); 132 } 133 return list; 134 } 135 136 /** 137 * This utility method creates a list of Thrift TRowResult "struct" based on 138 * an Hbase RowResult object. The empty list is returned if the input is 139 * null. 140 * 141 * @param in 142 * Hbase RowResult object 143 * @param sortColumns 144 * This boolean dictates if row data is returned in a sorted order 145 * sortColumns = True will set TRowResult's sortedColumns member 146 * which is an ArrayList of TColumn struct 147 * sortColumns = False will set TRowResult's columns member which is 148 * a map of columnName and TCell struct 149 * @return Thrift TRowResult array 150 */ 151 static public List<TRowResult> rowResultFromHBase(Result[] in, boolean sortColumns) { 152 List<TRowResult> results = new ArrayList<>(in.length); 153 for ( Result result_ : in) { 154 if(result_ == null || result_.isEmpty()) { 155 continue; 156 } 157 TRowResult result = new TRowResult(); 158 result.row = ByteBuffer.wrap(result_.getRow()); 159 if (sortColumns) { 160 result.sortedColumns = new ArrayList<>(); 161 for (Cell kv : result_.rawCells()) { 162 result.sortedColumns.add(new TColumn( 163 ByteBuffer.wrap(CellUtil.makeColumn(CellUtil.cloneFamily(kv), 164 CellUtil.cloneQualifier(kv))), 165 new TCell(ByteBuffer.wrap(CellUtil.cloneValue(kv)), kv.getTimestamp()))); 166 } 167 } else { 168 result.columns = new TreeMap<>(); 169 for (Cell kv : result_.rawCells()) { 170 result.columns.put( 171 ByteBuffer.wrap(CellUtil.makeColumn(CellUtil.cloneFamily(kv), 172 CellUtil.cloneQualifier(kv))), 173 new TCell(ByteBuffer.wrap(CellUtil.cloneValue(kv)), kv.getTimestamp())); 174 } 175 } 176 results.add(result); 177 } 178 return results; 179 } 180 181 /** 182 * This utility method creates a list of Thrift TRowResult "struct" based on 183 * an array of Hbase RowResult objects. The empty list is returned if the input is 184 * null. 185 * 186 * @param in 187 * Array of Hbase RowResult objects 188 * @return Thrift TRowResult array 189 */ 190 static public List<TRowResult> rowResultFromHBase(Result[] in) { 191 return rowResultFromHBase(in, false); 192 } 193 194 static public List<TRowResult> rowResultFromHBase(Result in) { 195 Result [] result = { in }; 196 return rowResultFromHBase(result); 197 } 198 199 /** 200 * From a {@link TIncrement} create an {@link Increment}. 201 * @param tincrement the Thrift version of an increment 202 * @return an increment that the {@link TIncrement} represented. 203 */ 204 public static Increment incrementFromThrift(TIncrement tincrement) { 205 Increment inc = new Increment(tincrement.getRow()); 206 byte[][] famAndQf = CellUtil.parseColumn(tincrement.getColumn()); 207 if (famAndQf.length != 2) return null; 208 inc.addColumn(famAndQf[0], famAndQf[1], tincrement.getAmmount()); 209 return inc; 210 } 211 212 /** 213 * From a {@link TAppend} create an {@link Append}. 214 * @param tappend the Thrift version of an append. 215 * @return an increment that the {@link TAppend} represented. 216 */ 217 public static Append appendFromThrift(TAppend tappend) { 218 Append append = new Append(tappend.getRow()); 219 List<ByteBuffer> columns = tappend.getColumns(); 220 List<ByteBuffer> values = tappend.getValues(); 221 222 if (columns.size() != values.size()) { 223 throw new IllegalArgumentException( 224 "Sizes of columns and values in tappend object are not matching"); 225 } 226 227 int length = columns.size(); 228 229 for (int i = 0; i < length; i++) { 230 byte[][] famAndQf = CellUtil.parseColumn(getBytes(columns.get(i))); 231 append.addColumn(famAndQf[0], famAndQf[1], getBytes(values.get(i))); 232 } 233 return append; 234 } 235}