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