| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.lucene.index; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.apache.lucene.util.Counter; |
| import org.apache.lucene.util.IntBlockPool; |
| import org.apache.lucene.util.LuceneTestCase; |
| |
| /** |
| * tests basic {@link IntBlockPool} functionality |
| */ |
| public class TestIntBlockPool extends LuceneTestCase { |
| |
| public void testSingleWriterReader() { |
| Counter bytesUsed = Counter.newCounter(); |
| IntBlockPool pool = new IntBlockPool(new ByteTrackingAllocator(bytesUsed)); |
| |
| for (int j = 0; j < 2; j++) { |
| IntBlockPool.SliceWriter writer = new IntBlockPool.SliceWriter(pool); |
| int start = writer.startNewSlice(); |
| int num = atLeast(100); |
| for (int i = 0; i < num; i++) { |
| writer.writeInt(i); |
| } |
| |
| int upto = writer.getCurrentOffset(); |
| IntBlockPool.SliceReader reader = new IntBlockPool.SliceReader(pool); |
| reader.reset(start, upto); |
| for (int i = 0; i < num; i++) { |
| assertEquals(i, reader.readInt()); |
| } |
| assertTrue(reader.endOfSlice()); |
| if (random().nextBoolean()) { |
| pool.reset(true, false); |
| assertEquals(0, bytesUsed.get()); |
| } else { |
| pool.reset(true, true); |
| assertEquals(IntBlockPool.INT_BLOCK_SIZE * Integer.BYTES, bytesUsed.get()); |
| } |
| } |
| } |
| |
| public void testMultipleWriterReader() { |
| Counter bytesUsed = Counter.newCounter(); |
| IntBlockPool pool = new IntBlockPool(new ByteTrackingAllocator(bytesUsed)); |
| for (int j = 0; j < 2; j++) { |
| List<StartEndAndValues> holders = new ArrayList<>(); |
| int num = atLeast(4); |
| for (int i = 0; i < num; i++) { |
| holders.add(new StartEndAndValues(random().nextInt(1000))); |
| } |
| IntBlockPool.SliceWriter writer = new IntBlockPool.SliceWriter(pool); |
| IntBlockPool.SliceReader reader = new IntBlockPool.SliceReader(pool); |
| |
| int numValuesToWrite = atLeast(10000); |
| for (int i = 0; i < numValuesToWrite; i++) { |
| StartEndAndValues values = holders |
| .get(random().nextInt(holders.size())); |
| if (values.valueCount == 0) { |
| values.start = writer.startNewSlice(); |
| } else { |
| writer.reset(values.end); |
| } |
| writer.writeInt(values.nextValue()); |
| values.end = writer.getCurrentOffset(); |
| if (random().nextInt(5) == 0) { |
| // pick one and reader the ints |
| assertReader(reader, holders.get(random().nextInt(holders.size()))); |
| } |
| } |
| |
| while (!holders.isEmpty()) { |
| StartEndAndValues values = holders.remove(random().nextInt( |
| holders.size())); |
| assertReader(reader, values); |
| } |
| if (random().nextBoolean()) { |
| pool.reset(true, false); |
| assertEquals(0, bytesUsed.get()); |
| } else { |
| pool.reset(true, true); |
| assertEquals(IntBlockPool.INT_BLOCK_SIZE * Integer.BYTES, bytesUsed.get()); |
| } |
| } |
| } |
| |
| private static class ByteTrackingAllocator extends IntBlockPool.Allocator { |
| private final Counter bytesUsed; |
| |
| public ByteTrackingAllocator(Counter bytesUsed) { |
| this(IntBlockPool.INT_BLOCK_SIZE, bytesUsed); |
| } |
| |
| public ByteTrackingAllocator(int blockSize, Counter bytesUsed) { |
| super(blockSize); |
| this.bytesUsed = bytesUsed; |
| } |
| |
| @Override |
| public int[] getIntBlock() { |
| bytesUsed.addAndGet(blockSize * Integer.BYTES); |
| return new int[blockSize]; |
| } |
| |
| @Override |
| public void recycleIntBlocks(int[][] blocks, int start, int end) { |
| bytesUsed |
| .addAndGet(-((end - start) * blockSize * Integer.BYTES)); |
| } |
| |
| } |
| |
| private void assertReader(IntBlockPool.SliceReader reader, |
| StartEndAndValues values) { |
| reader.reset(values.start, values.end); |
| for (int i = 0; i < values.valueCount; i++) { |
| assertEquals(values.valueOffset + i, reader.readInt()); |
| } |
| assertTrue(reader.endOfSlice()); |
| } |
| |
| private static class StartEndAndValues { |
| int valueOffset; |
| int valueCount; |
| int start; |
| int end; |
| |
| public StartEndAndValues(int valueOffset) { |
| this.valueOffset = valueOffset; |
| } |
| |
| public int nextValue() { |
| return valueOffset + valueCount++; |
| } |
| |
| } |
| |
| } |