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.bucket; 019 020import static org.junit.Assert.assertTrue; 021 022import java.io.IOException; 023import java.nio.ByteBuffer; 024import org.apache.hadoop.hbase.HBaseClassTestRule; 025import org.apache.hadoop.hbase.io.hfile.Cacheable; 026import org.apache.hadoop.hbase.io.hfile.Cacheable.MemoryType; 027import org.apache.hadoop.hbase.io.hfile.CacheableDeserializer; 028import org.apache.hadoop.hbase.nio.ByteBuff; 029import org.apache.hadoop.hbase.testclassification.IOTests; 030import org.apache.hadoop.hbase.testclassification.SmallTests; 031import org.junit.ClassRule; 032import org.junit.Test; 033import org.junit.experimental.categories.Category; 034 035/** 036 * Basic test for {@link ByteBufferIOEngine} 037 */ 038@Category({IOTests.class, SmallTests.class}) 039public class TestByteBufferIOEngine { 040 041 @ClassRule 042 public static final HBaseClassTestRule CLASS_RULE = 043 HBaseClassTestRule.forClass(TestByteBufferIOEngine.class); 044 045 @Test 046 public void testByteBufferIOEngine() throws Exception { 047 int capacity = 32 * 1024 * 1024; // 32 MB 048 int testNum = 100; 049 int maxBlockSize = 64 * 1024; 050 ByteBufferIOEngine ioEngine = new ByteBufferIOEngine(capacity); 051 int testOffsetAtStartNum = testNum / 10; 052 int testOffsetAtEndNum = testNum / 10; 053 for (int i = 0; i < testNum; i++) { 054 byte val = (byte) (Math.random() * 255); 055 int blockSize = (int) (Math.random() * maxBlockSize); 056 if (blockSize == 0) { 057 blockSize = 1; 058 } 059 byte[] byteArray = new byte[blockSize]; 060 for (int j = 0; j < byteArray.length; ++j) { 061 byteArray[j] = val; 062 } 063 ByteBuffer srcBuffer = ByteBuffer.wrap(byteArray); 064 int offset = 0; 065 if (testOffsetAtStartNum > 0) { 066 testOffsetAtStartNum--; 067 offset = 0; 068 } else if (testOffsetAtEndNum > 0) { 069 testOffsetAtEndNum--; 070 offset = capacity - blockSize; 071 } else { 072 offset = (int) (Math.random() * (capacity - maxBlockSize)); 073 } 074 ioEngine.write(srcBuffer, offset); 075 BufferGrabbingDeserializer deserializer = new BufferGrabbingDeserializer(); 076 ioEngine.read(offset, blockSize, deserializer); 077 ByteBuff dstBuffer = deserializer.buf; 078 for (int j = 0; j < byteArray.length; ++j) { 079 assertTrue(byteArray[j] == dstBuffer.get(j)); 080 } 081 } 082 assert testOffsetAtStartNum == 0; 083 assert testOffsetAtEndNum == 0; 084 } 085 086 /** 087 * A CacheableDeserializer implementation which just store reference to the {@link ByteBuff} to be 088 * deserialized. Use {@link #getDeserializedByteBuff()} to get this reference. 089 */ 090 static class BufferGrabbingDeserializer implements CacheableDeserializer<Cacheable> { 091 private ByteBuff buf; 092 093 @Override 094 public Cacheable deserialize(ByteBuff b) throws IOException { 095 return null; 096 } 097 098 @Override 099 public Cacheable deserialize(final ByteBuff b, boolean reuse, MemoryType memType) 100 throws IOException { 101 this.buf = b; 102 return null; 103 } 104 105 @Override 106 public int getDeserialiserIdentifier() { 107 return 0; 108 } 109 110 public ByteBuff getDeserializedByteBuff() { 111 return this.buf; 112 } 113 } 114 115 @Test 116 public void testByteBufferIOEngineWithMBB() throws Exception { 117 int capacity = 32 * 1024 * 1024; // 32 MB 118 int testNum = 100; 119 int maxBlockSize = 64 * 1024; 120 ByteBufferIOEngine ioEngine = new ByteBufferIOEngine(capacity); 121 int testOffsetAtStartNum = testNum / 10; 122 int testOffsetAtEndNum = testNum / 10; 123 for (int i = 0; i < testNum; i++) { 124 byte val = (byte) (Math.random() * 255); 125 int blockSize = (int) (Math.random() * maxBlockSize); 126 if (blockSize == 0) { 127 blockSize = 1; 128 } 129 byte[] byteArray = new byte[blockSize]; 130 for (int j = 0; j < byteArray.length; ++j) { 131 byteArray[j] = val; 132 } 133 ByteBuffer srcBuffer = ByteBuffer.wrap(byteArray); 134 int offset = 0; 135 if (testOffsetAtStartNum > 0) { 136 testOffsetAtStartNum--; 137 offset = 0; 138 } else if (testOffsetAtEndNum > 0) { 139 testOffsetAtEndNum--; 140 offset = capacity - blockSize; 141 } else { 142 offset = (int) (Math.random() * (capacity - maxBlockSize)); 143 } 144 ioEngine.write(srcBuffer, offset); 145 BufferGrabbingDeserializer deserializer = new BufferGrabbingDeserializer(); 146 ioEngine.read(offset, blockSize, deserializer); 147 ByteBuff dstBuffer = deserializer.buf; 148 for (int j = 0; j < byteArray.length; ++j) { 149 assertTrue(srcBuffer.get(j) == dstBuffer.get(j)); 150 } 151 } 152 assert testOffsetAtStartNum == 0; 153 assert testOffsetAtEndNum == 0; 154 } 155}