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.io.hfile; 019 020import static org.apache.hadoop.hbase.io.ByteBuffAllocator.MIN_ALLOCATE_SIZE_KEY; 021import static org.junit.Assert.assertArrayEquals; 022import static org.junit.Assert.assertEquals; 023import static org.junit.Assert.assertTrue; 024 025import java.io.IOException; 026import java.nio.ByteBuffer; 027import java.util.ArrayList; 028import java.util.List; 029import org.apache.hadoop.conf.Configuration; 030import org.apache.hadoop.fs.FileSystem; 031import org.apache.hadoop.fs.Path; 032import org.apache.hadoop.hbase.CellComparatorImpl; 033import org.apache.hadoop.hbase.CellUtil; 034import org.apache.hadoop.hbase.HBaseClassTestRule; 035import org.apache.hadoop.hbase.HBaseTestingUtil; 036import org.apache.hadoop.hbase.KeyValue; 037import org.apache.hadoop.hbase.SizeCachedNoTagsByteBufferKeyValue; 038import org.apache.hadoop.hbase.SizeCachedNoTagsKeyValue; 039import org.apache.hadoop.hbase.io.ByteBuffAllocator; 040import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding; 041import org.apache.hadoop.hbase.testclassification.IOTests; 042import org.apache.hadoop.hbase.testclassification.MediumTests; 043import org.apache.hadoop.hbase.util.Bytes; 044import org.junit.Before; 045import org.junit.ClassRule; 046import org.junit.Test; 047import org.junit.experimental.categories.Category; 048 049@Category({ IOTests.class, MediumTests.class }) 050public class TestRowIndexV1RoundTrip { 051 @ClassRule 052 public static final HBaseClassTestRule CLASS_RULE = 053 HBaseClassTestRule.forClass(TestRowIndexV1RoundTrip.class); 054 private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 055 private static final DataBlockEncoding DATA_BLOCK_ENCODING = DataBlockEncoding.ROW_INDEX_V1; 056 private static final int ENTRY_COUNT = 100; 057 058 private Configuration conf; 059 private FileSystem fs; 060 061 @Before 062 public void setUp() throws IOException { 063 conf = TEST_UTIL.getConfiguration(); 064 conf.setLong(MIN_ALLOCATE_SIZE_KEY, 0); 065 fs = FileSystem.get(conf); 066 } 067 068 @Test 069 public void testReadMyWritesOnHeap() throws IOException { 070 Path hfilePath = new Path(TEST_UTIL.getDataTestDir(), "testHFileFormatV3"); 071 writeDataToHFile(hfilePath, ENTRY_COUNT); 072 readDataFromHFile(hfilePath, ENTRY_COUNT, true); 073 } 074 075 @Test 076 public void testReadMyWritesOnDirectMem() throws IOException { 077 Path hfilePath = new Path(TEST_UTIL.getDataTestDir(), "testHFileFormatV3"); 078 writeDataToHFile(hfilePath, ENTRY_COUNT); 079 readDataFromHFile(hfilePath, ENTRY_COUNT, false); 080 } 081 082 private void writeDataToHFile(Path hfilePath, int entryCount) throws IOException { 083 HFileContext context = 084 new HFileContextBuilder().withBlockSize(1024).withDataBlockEncoding(DATA_BLOCK_ENCODING) 085 .withCellComparator(CellComparatorImpl.COMPARATOR).build(); 086 CacheConfig cacheConfig = new CacheConfig(conf); 087 HFile.Writer writer = new HFile.WriterFactory(conf, cacheConfig).withPath(fs, hfilePath) 088 .withFileContext(context).create(); 089 090 List<KeyValue> keyValues = new ArrayList<>(entryCount); 091 092 writeKeyValues(entryCount, writer, keyValues); 093 } 094 095 private void writeKeyValues(int entryCount, HFile.Writer writer, List<KeyValue> keyValues) 096 throws IOException { 097 for (int i = 0; i < entryCount; ++i) { 098 byte[] keyBytes = intToBytes(i); 099 100 byte[] valueBytes = Bytes.toBytes(String.format("value %d", i)); 101 KeyValue keyValue = new KeyValue(keyBytes, null, null, valueBytes); 102 103 writer.append(keyValue); 104 keyValues.add(keyValue); 105 } 106 writer.close(); 107 } 108 109 private void readDataFromHFile(Path hfilePath, int entryCount, boolean onHeap) 110 throws IOException { 111 CacheConfig cacheConfig; 112 if (onHeap) { 113 cacheConfig = new CacheConfig(conf); 114 } else { 115 ByteBuffAllocator allocator = ByteBuffAllocator.create(conf, true); 116 cacheConfig = new CacheConfig(conf, null, null, allocator); 117 } 118 HFile.Reader reader = HFile.createReader(fs, hfilePath, cacheConfig, false, conf); 119 HFileScanner scanner = reader.getScanner(conf, false, false); 120 scanner.seekTo(); 121 int i = 1; 122 while (scanner.next()) { 123 byte[] keyBytes = intToBytes(i); 124 // check row key from getKey() and getCell() separately because they use different code paths 125 assertArrayEquals(keyBytes, CellUtil.cloneRow(scanner.getKey())); 126 assertArrayEquals(keyBytes, CellUtil.cloneRow(scanner.getCell())); 127 assertArrayEquals(Bytes.toBytes(String.format("value %d", i)), 128 CellUtil.cloneValue(scanner.getCell())); 129 if (onHeap) { 130 assertTrue(scanner.getCell() instanceof SizeCachedNoTagsKeyValue); 131 } else { 132 assertTrue(scanner.getCell() instanceof SizeCachedNoTagsByteBufferKeyValue); 133 } 134 i += 1; 135 } 136 assertEquals(entryCount, i); 137 } 138 139 private byte[] intToBytes(final int i) { 140 ByteBuffer bb = ByteBuffer.allocate(4); 141 bb.putInt(i); 142 return bb.array(); 143 } 144}