blob: ff328e89bff5eb6d1527167a59c3faac93248ac0 [file] [log] [blame]
/*
* 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.ignite.internal.processors.compress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Function;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
import org.apache.ignite.configuration.DiskPageCompression;
import org.apache.ignite.internal.pagemem.PageIdAllocator;
import org.apache.ignite.internal.pagemem.PageIdUtils;
import org.apache.ignite.internal.pagemem.PageUtils;
import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusInnerIO;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusLeafIO;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.DataPagePayload;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.SimpleDataPageIO;
import org.apache.ignite.internal.util.GridIntList;
import org.apache.ignite.internal.util.GridUnsafe;
import org.apache.ignite.testframework.junits.GridTestKernalContext;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;
import static org.apache.ignite.configuration.DiskPageCompression.LZ4;
import static org.apache.ignite.configuration.DiskPageCompression.SKIP_GARBAGE;
import static org.apache.ignite.configuration.DiskPageCompression.SNAPPY;
import static org.apache.ignite.configuration.DiskPageCompression.ZSTD;
import static org.apache.ignite.internal.processors.compress.CompressionProcessor.LZ4_MAX_LEVEL;
import static org.apache.ignite.internal.processors.compress.CompressionProcessor.LZ4_MIN_LEVEL;
import static org.apache.ignite.internal.processors.compress.CompressionProcessor.UNCOMPRESSED_PAGE;
import static org.apache.ignite.internal.processors.compress.CompressionProcessor.ZSTD_MAX_LEVEL;
import static org.apache.ignite.internal.processors.compress.CompressionProcessorImpl.allocateDirectBuffer;
import static org.apache.ignite.internal.processors.compress.CompressionProcessorTest.TestInnerIO.INNER_IO;
import static org.apache.ignite.internal.processors.compress.CompressionProcessorTest.TestLeafIO.LEAF_IO;
import static org.apache.ignite.internal.util.GridUnsafe.bufferAddress;
/**
*/
public class CompressionProcessorTest extends GridCommonAbstractTest {
/** */
private static final int ITEM_SIZE = 6; // To fill the whole page.
/** */
private int blockSize = 16;
/** */
private int pageSize = 4 * 1024;
/** */
private DiskPageCompression compression;
/** */
private int compressLevel;
/** */
private CompressionProcessor p;
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
super.beforeTestsStarted();
PageIO.registerTest(INNER_IO, LEAF_IO);
}
/** {@inheritDoc} */
@Override protected void beforeTest() {
p = new CompressionProcessorImpl(new GridTestKernalContext(log));
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageCompact16() throws IgniteCheckedException {
blockSize = 16;
compression = SKIP_GARBAGE;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageCompact128() throws IgniteCheckedException {
blockSize = 128;
compression = SKIP_GARBAGE;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageCompact1k() throws IgniteCheckedException {
blockSize = 1024;
compression = SKIP_GARBAGE;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageCompact2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = SKIP_GARBAGE;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageZstd16() throws IgniteCheckedException {
blockSize = 16;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageZstd128() throws IgniteCheckedException {
blockSize = 128;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageZstd1k() throws IgniteCheckedException {
blockSize = 1024;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageZstd2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageSnappy16() throws IgniteCheckedException {
blockSize = 16;
compression = SNAPPY;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageSnappy128() throws IgniteCheckedException {
blockSize = 128;
compression = SNAPPY;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageSnappy1k() throws IgniteCheckedException {
blockSize = 1024;
compression = SNAPPY;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageSnappy2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = SNAPPY;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageLz4Fast16() throws IgniteCheckedException {
blockSize = 16;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageLz4Fast128() throws IgniteCheckedException {
blockSize = 128;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageLz4Fast1k() throws IgniteCheckedException {
blockSize = 1024;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageLz4Fast2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageLz4Slow16() throws IgniteCheckedException {
blockSize = 16;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageLz4Slow128() throws IgniteCheckedException {
blockSize = 128;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageLz4Slow1k() throws IgniteCheckedException {
blockSize = 1024;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testDataPageLz4Slow2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestDataPage();
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageCompact16() throws IgniteCheckedException {
blockSize = 16;
compression = SKIP_GARBAGE;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageCompact16() throws IgniteCheckedException {
blockSize = 16;
compression = SKIP_GARBAGE;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageZstd16() throws IgniteCheckedException {
blockSize = 16;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageZstd16() throws IgniteCheckedException {
blockSize = 16;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageLz4Fast16() throws IgniteCheckedException {
blockSize = 16;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageLz4Fast16() throws IgniteCheckedException {
blockSize = 16;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageLz4Slow16() throws IgniteCheckedException {
blockSize = 16;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageLz4Slow16() throws IgniteCheckedException {
blockSize = 16;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageSnappy16() throws IgniteCheckedException {
blockSize = 16;
compression = SNAPPY;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageSnappy16() throws IgniteCheckedException {
blockSize = 16;
compression = SNAPPY;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageCompact128() throws IgniteCheckedException {
blockSize = 128;
compression = SKIP_GARBAGE;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageCompact128() throws IgniteCheckedException {
blockSize = 128;
compression = SKIP_GARBAGE;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageZstd128() throws IgniteCheckedException {
blockSize = 128;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageZstd128() throws IgniteCheckedException {
blockSize = 128;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageLz4Fast128() throws IgniteCheckedException {
blockSize = 128;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageLz4Fast128() throws IgniteCheckedException {
blockSize = 128;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageLz4Slow128() throws IgniteCheckedException {
blockSize = 128;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageLz4Slow128() throws IgniteCheckedException {
blockSize = 128;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageSnappy128() throws IgniteCheckedException {
blockSize = 128;
compression = SNAPPY;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageSnappy128() throws IgniteCheckedException {
blockSize = 128;
compression = SNAPPY;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageCompact1k() throws IgniteCheckedException {
blockSize = 1024;
compression = SKIP_GARBAGE;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageCompact1k() throws IgniteCheckedException {
blockSize = 1024;
compression = SKIP_GARBAGE;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageZstd1k() throws IgniteCheckedException {
blockSize = 1024;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageZstd1k() throws IgniteCheckedException {
blockSize = 1024;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageLz4Fast1k() throws IgniteCheckedException {
blockSize = 1024;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageLz4Fast1k() throws IgniteCheckedException {
blockSize = 1024;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageLz4Slow1k() throws IgniteCheckedException {
blockSize = 1024;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageLz4Slow1k() throws IgniteCheckedException {
blockSize = 1024;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageSnappy1k() throws IgniteCheckedException {
blockSize = 1024;
compression = SNAPPY;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageSnappy1k() throws IgniteCheckedException {
blockSize = 1024;
compression = SNAPPY;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageCompact2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = SKIP_GARBAGE;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageCompact2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = SKIP_GARBAGE;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageZstd2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageZstd2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = ZSTD;
compressLevel = ZSTD_MAX_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageLz4Fast2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageLz4Fast2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = LZ4;
compressLevel = LZ4_MIN_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageLz4Slow2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageLz4Slow2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = LZ4;
compressLevel = LZ4_MAX_LEVEL;
doTestBTreePage(LEAF_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testInnerPageSnappy2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = SNAPPY;
doTestBTreePage(INNER_IO);
}
/**
* @throws IgniteCheckedException If failed.
*/
@Test
public void testLeafPageSnappy2k() throws IgniteCheckedException {
blockSize = 2 * 1024;
compression = SNAPPY;
doTestBTreePage(LEAF_IO);
}
/**
* @param io Page IO.
* @throws IgniteCheckedException If failed.
*/
private void doTestBTreePage(BPlusIO<byte[]> io) throws IgniteCheckedException {
Random rnd = ThreadLocalRandom.current();
final byte[][] rows = new byte[3][io.getItemSize()];
for (int i = 0; i < rows.length; i++)
rnd.nextBytes(rows[i]);
ByteBuffer page = allocateDirectBuffer(pageSize);
long pageAddr = bufferAddress(page);
long pageId = PageIdUtils.pageId(PageIdAllocator.INDEX_PARTITION, PageIdAllocator.FLAG_IDX, 171717);
io.initNewPage(pageAddr, pageId, pageSize, null);
checkIo(io, page);
Function<ByteBuffer, List<?>> getContents = (buf) -> {
long addr = bufferAddress(buf);
int cnt = io.getCount(addr);
List<Object> list = new ArrayList<>(cnt);
for (int i = 0; i < cnt; i++) {
if (!io.isLeaf())
list.add(((BPlusInnerIO)io).getLeft(addr, i));
try {
list.add(new Bytes(io.getLookupRow(null, addr, i)));
}
catch (IgniteCheckedException e) {
throw new IllegalStateException(e);
}
if (!io.isLeaf())
list.add(((BPlusInnerIO)io).getRight(addr, i));
}
return list;
};
// Empty page.
checkCompressDecompress(page, getContents, false);
int cnt = io.getMaxCount(pageAddr, pageSize);
for (int i = 0; i < cnt; i++) {
byte[] row = rows[rnd.nextInt(rows.length)];
io.insert(pageAddr, i, row, row, 777_000 + i, false);
}
if (io.isLeaf())
assertEquals(pageSize, io.getItemsEnd(pageAddr)); // Page must be full.
// Full page.
checkCompressDecompress(page, getContents, io.isLeaf());
io.setCount(pageAddr, cnt / 2);
// Half page.
checkCompressDecompress(page, getContents, false);
}
/**
* @throws IgniteCheckedException If failed.
*/
private void doTestDataPage() throws IgniteCheckedException {
Random rnd = ThreadLocalRandom.current();
final byte[][] rows = new byte[][]{
new byte[17], new byte[37], new byte[71]
};
for (int i = 0; i < rows.length; i++)
rnd.nextBytes(rows[i]);
ByteBuffer page = allocateDirectBuffer(pageSize);
long pageAddr = bufferAddress(page);
SimpleDataPageIO io = SimpleDataPageIO.VERSIONS.latest();
long pageId = PageIdUtils.pageId(PageIdAllocator.MAX_PARTITION_ID, PageIdAllocator.FLAG_DATA, 171717);
io.initNewPage(pageAddr, pageId, pageSize, null);
checkIo(io, page);
Function<ByteBuffer, List<Bytes>> getContents = (buf) -> {
try {
long addr = bufferAddress(buf);
return io.forAllItems(addr, (link) -> {
DataPagePayload payload = io.readPayload(addr, PageIdUtils.itemId(link), pageSize);
return new Bytes(payload.getBytes(addr));
});
}
catch (IgniteCheckedException e) {
throw new IgniteException(e);
}
};
// Empty data page.
checkCompressDecompress(page, getContents, false);
GridIntList itemIds = new GridIntList();
for (;;) {
byte[] row = rows[rnd.nextInt(rows.length)];
if (io.getFreeSpace(pageAddr) < row.length)
break;
itemIds.add(io.addRow(pageAddr, row, pageSize));
}
int freeSpace = io.getFreeSpace(pageAddr);
if (freeSpace != 0) {
byte[] lastRow = new byte[freeSpace];
rnd.nextBytes(lastRow);
io.addRowFragment(pageId, pageAddr, lastRow, 777L, pageSize);
assertEquals(0, io.getRealFreeSpace(pageAddr));
}
// Full data page.
checkCompressDecompress(page, getContents, io.getRealFreeSpace(pageAddr) == 0);
for (int i = 0; i < itemIds.size(); i += 2)
io.removeRow(pageAddr, itemIds.get(i), pageSize);
// Half-filled data page.
checkCompressDecompress(page, getContents, false);
}
/** */
private void checkIo(PageIO io, ByteBuffer page) throws IgniteCheckedException {
assertSame(io, PageIO.getPageIO(bufferAddress(page)));
assertSame(io, PageIO.getPageIO(page));
}
/** */
private void checkCompressDecompress(ByteBuffer page, Function<ByteBuffer, ?> getPageContents, boolean fullPage)
throws IgniteCheckedException {
PageIO.setCrc(page, 0xABCDEF13);
long pageId = PageIO.getPageId(page);
PageIO io = PageIO.getPageIO(page);
ByteBuffer compressed = p.compressPage(page, pageSize, blockSize, compression, compressLevel);
int compressedSize = PageIO.getCompressedSize(compressed);
assertNotSame(page, compressed); // This is generally possible but not interesting in this test.
assertTrue(compressedSize > 0);
assertTrue(compressedSize <= pageSize);
assertEquals(compressedSize, compressed.limit());
if (!fullPage || compression != SKIP_GARBAGE)
assertTrue(pageSize > compressedSize);
assertEquals(0, compressed.position());
checkIo(io, compressed);
assertEquals(0, page.position());
assertEquals(pageSize, page.limit());
info(io.getClass().getSimpleName() + " " + compression + " " + compressLevel + ": " + compressedSize + "/" + pageSize);
if (!fullPage || compression != SKIP_GARBAGE)
assertTrue(compressedSize < pageSize);
assertEquals(pageId, PageIO.getPageId(compressed));
ByteBuffer decompress = allocateDirectBuffer(pageSize);
decompress.put(compressed).clear();
p.decompressPage(decompress, pageSize);
assertEquals(0, decompress.position());
assertEquals(pageSize, decompress.limit());
checkIo(io, decompress);
assertEquals(UNCOMPRESSED_PAGE, PageIO.getCompressionType(page));
assertEquals(0, PageIO.getCompressedSize(page));
assertEquals(0, PageIO.getCompactedSize(page));
assertTrue(Arrays.equals(getPageCommonHeader(page), getPageCommonHeader(decompress)));
assertEquals(getPageContents.apply(page), getPageContents.apply(decompress));
}
/**
* @param page Page.
* @return Page header.
*/
private static byte[] getPageCommonHeader(ByteBuffer page) {
return PageUtils.getBytes(GridUnsafe.bufferAddress(page), 0, PageIO.COMMON_HEADER_END);
}
/**
*/
private static class Bytes {
/** */
private final byte[] bytes;
/**
* @param bytes Bytes.
*/
private Bytes(byte[] bytes) {
assert bytes != null;
this.bytes = bytes;
}
/** {@inheritDoc} */
@Override public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Bytes bytes1 = (Bytes)o;
return Arrays.equals(bytes, bytes1.bytes);
}
/** {@inheritDoc} */
@Override public int hashCode() {
return Arrays.hashCode(bytes);
}
}
/**
*/
static class TestLeafIO extends BPlusLeafIO<byte[]> {
/** */
static final TestLeafIO LEAF_IO = new TestLeafIO();
/**
*/
TestLeafIO() {
super(29_501, 1, ITEM_SIZE);
}
/** {@inheritDoc} */
@Override public void storeByOffset(long pageAddr, int off, byte[] row) {
PageUtils.putBytes(pageAddr, off, row);
}
/** {@inheritDoc} */
@Override public void store(long dstPageAddr, int dstIdx, BPlusIO<byte[]> srcIo, long srcPageAddr,
int srcIdx) throws IgniteCheckedException {
storeByOffset(dstPageAddr, offset(dstIdx), srcIo.getLookupRow(null, srcPageAddr, srcIdx));
}
/** {@inheritDoc} */
@Override public byte[] getLookupRow(BPlusTree<byte[], ?> tree, long pageAddr, int idx) {
return PageUtils.getBytes(pageAddr, offset(idx), itemSize);
}
}
/**
*/
static class TestInnerIO extends BPlusInnerIO<byte[]> {
/** */
static TestInnerIO INNER_IO = new TestInnerIO();
/**
*/
TestInnerIO() {
super(29_502, 1, true, ITEM_SIZE);
}
/** {@inheritDoc} */
@Override public void storeByOffset(long pageAddr, int off, byte[] row) {
PageUtils.putBytes(pageAddr, off, row);
}
/** {@inheritDoc} */
@Override public void store(long dstPageAddr, int dstIdx, BPlusIO<byte[]> srcIo, long srcPageAddr,
int srcIdx) throws IgniteCheckedException {
storeByOffset(dstPageAddr, offset(dstIdx), srcIo.getLookupRow(null, srcPageAddr, srcIdx));
}
/** {@inheritDoc} */
@Override public byte[] getLookupRow(BPlusTree<byte[], ?> tree, long pageAddr, int idx) {
return PageUtils.getBytes(pageAddr, offset(idx), itemSize);
}
}
}