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 */ 018package org.apache.hadoop.hbase; 019 020import static junit.framework.TestCase.assertTrue; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertFalse; 023 024import java.nio.ByteBuffer; 025import java.util.ArrayList; 026import java.util.List; 027import java.util.concurrent.ConcurrentSkipListMap; 028 029import org.apache.hadoop.hbase.KeyValue.Type; 030import org.apache.hadoop.hbase.testclassification.MiscTests; 031import org.apache.hadoop.hbase.testclassification.SmallTests; 032import org.apache.hadoop.hbase.util.ByteBufferUtils; 033import org.apache.hadoop.hbase.util.Bytes; 034import org.junit.ClassRule; 035import org.junit.Test; 036import org.junit.experimental.categories.Category; 037 038@Category({ MiscTests.class, SmallTests.class }) 039public class TestByteBufferKeyValue { 040 041 @ClassRule 042 public static final HBaseClassTestRule CLASS_RULE = 043 HBaseClassTestRule.forClass(TestByteBufferKeyValue.class); 044 045 private static final String QUAL2 = "qual2"; 046 private static final String FAM2 = "fam2"; 047 private static final String QUAL1 = "qual1"; 048 private static final String FAM1 = "fam1"; 049 private static final String ROW1 = "row1"; 050 private static final byte[] row1 = Bytes.toBytes(ROW1); 051 private static final byte[] fam1 = Bytes.toBytes(FAM1); 052 private static final byte[] fam2 = Bytes.toBytes(FAM2); 053 private static final byte[] qual1 = Bytes.toBytes(QUAL1); 054 private static final byte[] qual2 = Bytes.toBytes(QUAL2); 055 private static final Tag t1 = new ArrayBackedTag((byte) 1, Bytes.toBytes("TAG1")); 056 private static final Tag t2 = new ArrayBackedTag((byte) 2, Bytes.toBytes("TAG2")); 057 private static final ArrayList<Tag> tags = new ArrayList<Tag>(); 058 static { 059 tags.add(t1); 060 tags.add(t2); 061 } 062 063 @Test 064 public void testCompare() { 065 Cell cell1 = getOffheapCell(row1, fam1, qual1); 066 Cell cell2 = getOffheapCell(row1, fam1, qual2); 067 assertTrue(CellComparatorImpl.COMPARATOR.compare(cell1, cell2) < 0); 068 Cell cell3 = getOffheapCell(row1, Bytes.toBytes("wide_family"), qual2); 069 assertTrue(CellComparatorImpl.COMPARATOR.compare(cell1, cell3) < 0); 070 Cell cell4 = getOffheapCell(row1, Bytes.toBytes("f"), qual2); 071 assertTrue(CellComparatorImpl.COMPARATOR.compare(cell1, cell4) > 0); 072 BBKVComparator comparator = new BBKVComparator(null); 073 assertTrue(comparator.compare(cell1, cell2) < 0); 074 assertTrue(comparator.compare(cell1, cell3) < 0); 075 assertTrue(comparator.compare(cell1, cell4) > 0); 076 ByteBuffer buf = ByteBuffer.allocate(row1.length); 077 ByteBufferUtils.copyFromArrayToBuffer(buf, row1, 0, row1.length); 078 079 ConcurrentSkipListMap<ByteBufferKeyValue, ByteBufferKeyValue> map = 080 new ConcurrentSkipListMap<>(comparator); 081 map.put((ByteBufferKeyValue)cell1, (ByteBufferKeyValue)cell1); 082 map.put((ByteBufferKeyValue)cell2, (ByteBufferKeyValue)cell2); 083 map.put((ByteBufferKeyValue)cell3, (ByteBufferKeyValue)cell3); 084 map.put((ByteBufferKeyValue)cell1, (ByteBufferKeyValue)cell1); 085 map.put((ByteBufferKeyValue)cell1, (ByteBufferKeyValue)cell1); 086 } 087 088 private static Cell getOffheapCell(byte [] row, byte [] family, byte [] qualifier) { 089 KeyValue kvCell = new KeyValue(row, family, qualifier, 0L, Type.Put, row); 090 ByteBuffer buf = ByteBuffer.allocateDirect(kvCell.getBuffer().length); 091 ByteBufferUtils.copyFromArrayToBuffer(buf, kvCell.getBuffer(), 0, kvCell.getBuffer().length); 092 return new ByteBufferKeyValue(buf, 0, buf.capacity(), 0L); 093 } 094 095 @Test 096 public void testByteBufferBackedKeyValue() throws Exception { 097 KeyValue kvCell = new KeyValue(row1, fam1, qual1, 0L, Type.Put, row1); 098 ByteBuffer buf = ByteBuffer.allocateDirect(kvCell.getBuffer().length); 099 ByteBufferUtils.copyFromArrayToBuffer(buf, kvCell.getBuffer(), 0, kvCell.getBuffer().length); 100 ByteBufferExtendedCell offheapKV = new ByteBufferKeyValue(buf, 0, buf.capacity(), 0L); 101 assertEquals( 102 ROW1, 103 ByteBufferUtils.toStringBinary(offheapKV.getRowByteBuffer(), 104 offheapKV.getRowPosition(), offheapKV.getRowLength())); 105 assertEquals( 106 FAM1, 107 ByteBufferUtils.toStringBinary(offheapKV.getFamilyByteBuffer(), 108 offheapKV.getFamilyPosition(), offheapKV.getFamilyLength())); 109 assertEquals( 110 QUAL1, 111 ByteBufferUtils.toStringBinary(offheapKV.getQualifierByteBuffer(), 112 offheapKV.getQualifierPosition(), offheapKV.getQualifierLength())); 113 assertEquals( 114 ROW1, 115 ByteBufferUtils.toStringBinary(offheapKV.getValueByteBuffer(), 116 offheapKV.getValuePosition(), offheapKV.getValueLength())); 117 assertEquals(0L, offheapKV.getTimestamp()); 118 assertEquals(Type.Put.getCode(), offheapKV.getTypeByte()); 119 120 // Use the array() APIs 121 assertEquals( 122 ROW1, 123 Bytes.toStringBinary(offheapKV.getRowArray(), 124 offheapKV.getRowOffset(), offheapKV.getRowLength())); 125 assertEquals( 126 FAM1, 127 Bytes.toStringBinary(offheapKV.getFamilyArray(), 128 offheapKV.getFamilyOffset(), offheapKV.getFamilyLength())); 129 assertEquals( 130 QUAL1, 131 Bytes.toStringBinary(offheapKV.getQualifierArray(), 132 offheapKV.getQualifierOffset(), offheapKV.getQualifierLength())); 133 assertEquals( 134 ROW1, 135 Bytes.toStringBinary(offheapKV.getValueArray(), 136 offheapKV.getValueOffset(), offheapKV.getValueLength())); 137 assertEquals(0L, offheapKV.getTimestamp()); 138 assertEquals(Type.Put.getCode(), offheapKV.getTypeByte()); 139 140 kvCell = new KeyValue(row1, fam2, qual2, 0L, Type.Put, row1); 141 buf = ByteBuffer.allocateDirect(kvCell.getBuffer().length); 142 ByteBufferUtils.copyFromArrayToBuffer(buf, kvCell.getBuffer(), 0, kvCell.getBuffer().length); 143 offheapKV = new ByteBufferKeyValue(buf, 0, buf.capacity(), 0L); 144 assertEquals( 145 FAM2, 146 ByteBufferUtils.toStringBinary(offheapKV.getFamilyByteBuffer(), 147 offheapKV.getFamilyPosition(), offheapKV.getFamilyLength())); 148 assertEquals( 149 QUAL2, 150 ByteBufferUtils.toStringBinary(offheapKV.getQualifierByteBuffer(), 151 offheapKV.getQualifierPosition(), offheapKV.getQualifierLength())); 152 byte[] nullQualifier = new byte[0]; 153 kvCell = new KeyValue(row1, fam1, nullQualifier, 0L, Type.Put, row1); 154 buf = ByteBuffer.allocateDirect(kvCell.getBuffer().length); 155 ByteBufferUtils.copyFromArrayToBuffer(buf, kvCell.getBuffer(), 0, kvCell.getBuffer().length); 156 offheapKV = new ByteBufferKeyValue(buf, 0, buf.capacity(), 0L); 157 assertEquals( 158 ROW1, 159 ByteBufferUtils.toStringBinary(offheapKV.getRowByteBuffer(), 160 offheapKV.getRowPosition(), offheapKV.getRowLength())); 161 assertEquals( 162 FAM1, 163 ByteBufferUtils.toStringBinary(offheapKV.getFamilyByteBuffer(), 164 offheapKV.getFamilyPosition(), offheapKV.getFamilyLength())); 165 assertEquals( 166 "", 167 ByteBufferUtils.toStringBinary(offheapKV.getQualifierByteBuffer(), 168 offheapKV.getQualifierPosition(), offheapKV.getQualifierLength())); 169 assertEquals( 170 ROW1, 171 ByteBufferUtils.toStringBinary(offheapKV.getValueByteBuffer(), 172 offheapKV.getValuePosition(), offheapKV.getValueLength())); 173 assertEquals(0L, offheapKV.getTimestamp()); 174 assertEquals(Type.Put.getCode(), offheapKV.getTypeByte()); 175 } 176 177 @Test 178 public void testByteBufferBackedKeyValueWithTags() throws Exception { 179 KeyValue kvCell = new KeyValue(row1, fam1, qual1, 0L, Type.Put, row1, tags); 180 ByteBuffer buf = ByteBuffer.allocateDirect(kvCell.getBuffer().length); 181 ByteBufferUtils.copyFromArrayToBuffer(buf, kvCell.getBuffer(), 0, kvCell.getBuffer().length); 182 ByteBufferKeyValue offheapKV = new ByteBufferKeyValue(buf, 0, buf.capacity(), 0L); 183 assertEquals( 184 ROW1, 185 ByteBufferUtils.toStringBinary(offheapKV.getRowByteBuffer(), 186 offheapKV.getRowPosition(), offheapKV.getRowLength())); 187 assertEquals( 188 FAM1, 189 ByteBufferUtils.toStringBinary(offheapKV.getFamilyByteBuffer(), 190 offheapKV.getFamilyPosition(), offheapKV.getFamilyLength())); 191 assertEquals( 192 QUAL1, 193 ByteBufferUtils.toStringBinary(offheapKV.getQualifierByteBuffer(), 194 offheapKV.getQualifierPosition(), offheapKV.getQualifierLength())); 195 assertEquals( 196 ROW1, 197 ByteBufferUtils.toStringBinary(offheapKV.getValueByteBuffer(), 198 offheapKV.getValuePosition(), offheapKV.getValueLength())); 199 assertEquals(0L, offheapKV.getTimestamp()); 200 assertEquals(Type.Put.getCode(), offheapKV.getTypeByte()); 201 // change tags to handle both onheap and offheap stuff 202 List<Tag> resTags = PrivateCellUtil.getTags(offheapKV); 203 Tag tag1 = resTags.get(0); 204 assertEquals(t1.getType(), tag1.getType()); 205 assertEquals(Tag.getValueAsString(t1), 206 Tag.getValueAsString(tag1)); 207 Tag tag2 = resTags.get(1); 208 assertEquals(tag2.getType(), tag2.getType()); 209 assertEquals(Tag.getValueAsString(t2), 210 Tag.getValueAsString(tag2)); 211 Tag res = PrivateCellUtil.getTag(offheapKV, (byte) 2).get(); 212 assertEquals(Tag.getValueAsString(t2), 213 Tag.getValueAsString(tag2)); 214 assertFalse(PrivateCellUtil.getTag(offheapKV, (byte) 3).isPresent()); 215 } 216 217 @Test 218 public void testGetKeyMethods() throws Exception { 219 KeyValue kvCell = new KeyValue(row1, fam1, qual1, 0L, Type.Put, row1, tags); 220 ByteBuffer buf = ByteBuffer.allocateDirect(kvCell.getKeyLength()); 221 ByteBufferUtils.copyFromArrayToBuffer(buf, kvCell.getBuffer(), kvCell.getKeyOffset(), 222 kvCell.getKeyLength()); 223 ByteBufferExtendedCell offheapKeyOnlyKV = new ByteBufferKeyOnlyKeyValue(buf, 0, buf.capacity()); 224 assertEquals( 225 ROW1, 226 ByteBufferUtils.toStringBinary(offheapKeyOnlyKV.getRowByteBuffer(), 227 offheapKeyOnlyKV.getRowPosition(), offheapKeyOnlyKV.getRowLength())); 228 assertEquals( 229 FAM1, 230 ByteBufferUtils.toStringBinary(offheapKeyOnlyKV.getFamilyByteBuffer(), 231 offheapKeyOnlyKV.getFamilyPosition(), offheapKeyOnlyKV.getFamilyLength())); 232 assertEquals( 233 QUAL1, 234 ByteBufferUtils.toStringBinary(offheapKeyOnlyKV.getQualifierByteBuffer(), 235 offheapKeyOnlyKV.getQualifierPosition(), 236 offheapKeyOnlyKV.getQualifierLength())); 237 assertEquals(0L, offheapKeyOnlyKV.getTimestamp()); 238 assertEquals(Type.Put.getCode(), offheapKeyOnlyKV.getTypeByte()); 239 } 240}