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