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}