This is an automated email from the ASF dual-hosted git repository. amashenkov pushed a commit to branch ignite-15163 in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit b48b4485824d242994d62c208deee542378c58c0 Author: Andrew Mashenkov <andrey.mashen...@gmail.com> AuthorDate: Fri Aug 20 15:36:05 2021 +0300 Support BitSet, Number and Decimal types. --- .../apache/ignite/client/proto/ClientDataType.java | 3 + .../ignite/client/proto/ClientMessagePacker.java | 50 ++++++++++-- .../ignite/client/proto/ClientMessageUnpacker.java | 60 ++++++++++++-- .../ignite/client/proto/ClientMsgPackType.java | 3 + .../proto/ClientMessagePackerUnpackerTest.java | 95 +++++++++++++++++++++- .../internal/testframework/IgniteTestUtils.java | 13 +++ modules/schema/pom.xml | 7 ++ .../apache/ignite/internal/schema/TestUtils.java | 15 +--- .../schema/marshaller/JavaSerializerTest.java | 2 +- .../marshaller/reflection/FieldAccessorTest.java | 2 +- 10 files changed, 219 insertions(+), 31 deletions(-) diff --git a/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientDataType.java b/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientDataType.java index 45d1280..d744987 100644 --- a/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientDataType.java +++ b/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientDataType.java @@ -53,4 +53,7 @@ public class ClientDataType { /** BitMask. */ public static final int BITMASK = 11; + + /** Number. */ + public static final int NUMBER = 12; } diff --git a/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMessagePacker.java b/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMessagePacker.java index facefa2..bbe0758 100644 --- a/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMessagePacker.java +++ b/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMessagePacker.java @@ -17,6 +17,8 @@ package org.apache.ignite.client.proto; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufOutputStream; import java.io.IOException; import java.io.UncheckedIOException; import java.math.BigDecimal; @@ -24,8 +26,6 @@ import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.BitSet; import java.util.UUID; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufOutputStream; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; import org.msgpack.core.buffer.OutputStreamBufferOutput; @@ -316,7 +316,7 @@ public class ClientMessagePacker extends MessagePacker { bb.putLong(val.getMostSignificantBits()); bb.putLong(val.getLeastSignificantBits()); - writePayload(bytes); + addPayload(bytes); return this; } @@ -326,25 +326,58 @@ public class ClientMessagePacker extends MessagePacker { * * @param val Decimal value. * @return This instance. - * @throws UnsupportedOperationException Not supported. */ public ClientMessagePacker packDecimal(BigDecimal val) { assert !closed : "Packer is closed"; - throw new UnsupportedOperationException("TODO: IGNITE-15163"); + // TODO: Pack directly to ByteBuf without allocating IGNITE-15234. + byte[] unscaledValue = val.unscaledValue().toByteArray(); + + packExtensionTypeHeader(ClientMsgPackType.DECIMAL, 4 + unscaledValue.length); // Scale length + data length + + addPayload(ByteBuffer.wrap(new byte[4]).putInt(val.scale()).array()); + addPayload(unscaledValue); + + return this; } /** + * Writes a decimal. + * + * @param val Decimal value. + * @return This instance. + */ + public ClientMessagePacker packNumber(BigInteger val) { + assert !closed : "Packer is closed"; + + // TODO: Pack directly to ByteBuf without allocating IGNITE-15234. + byte[] data = val.toByteArray(); + + packExtensionTypeHeader(ClientMsgPackType.NUMBER, data.length); + + addPayload(data); + + return this; + } + + + /** * Writes a bit set. * * @param val Bit set value. * @return This instance. - * @throws UnsupportedOperationException Not supported. */ public ClientMessagePacker packBitSet(BitSet val) { assert !closed : "Packer is closed"; - throw new UnsupportedOperationException("TODO: IGNITE-15163"); + // TODO: Pack directly to ByteBuf without allocating IGNITE-15234. + byte[] data = val.toByteArray(); + + packExtensionTypeHeader(ClientMsgPackType.BITMASK, data.length); + + addPayload(data); + + return this; } /** @@ -381,6 +414,9 @@ public class ClientMessagePacker extends MessagePacker { if (val instanceof BigDecimal) return packDecimal((BigDecimal) val); + if (val instanceof BigInteger) + return packNumber((BigInteger)val); + if (val instanceof BitSet) return packBitSet((BitSet) val); diff --git a/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMessageUnpacker.java b/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMessageUnpacker.java index a058c9c..c0c6aec 100644 --- a/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMessageUnpacker.java +++ b/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMessageUnpacker.java @@ -17,6 +17,8 @@ package org.apache.ignite.client.proto; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; import java.io.IOException; import java.io.UncheckedIOException; import java.math.BigDecimal; @@ -24,8 +26,6 @@ import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.BitSet; import java.util.UUID; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufInputStream; import org.apache.ignite.lang.IgniteException; import org.msgpack.core.ExtensionTypeHeader; import org.msgpack.core.MessageFormat; @@ -45,6 +45,7 @@ import static org.apache.ignite.client.proto.ClientDataType.INT16; import static org.apache.ignite.client.proto.ClientDataType.INT32; import static org.apache.ignite.client.proto.ClientDataType.INT64; import static org.apache.ignite.client.proto.ClientDataType.INT8; +import static org.apache.ignite.client.proto.ClientDataType.NUMBER; import static org.apache.ignite.client.proto.ClientDataType.STRING; /** @@ -325,7 +326,7 @@ public class ClientMessageUnpacker extends MessageUnpacker { var len = hdr.getLength(); if (type != ClientMsgPackType.UUID) - throw new MessageTypeException("Expected UUID extension (1), but got " + type); + throw new MessageTypeException("Expected UUID extension (3), but got " + type); if (len != 16) throw new MessageSizeException("Expected 16 bytes for UUID extension, but got " + len, len); @@ -346,19 +347,60 @@ public class ClientMessageUnpacker extends MessageUnpacker { public BigDecimal unpackDecimal() { assert refCnt > 0 : "Unpacker is closed"; - throw new UnsupportedOperationException("TODO: IGNITE-15163"); + var hdr = unpackExtensionTypeHeader(); + var type = hdr.getType(); + var len = hdr.getLength(); + + if (type != ClientMsgPackType.DECIMAL) + throw new MessageTypeException("Expected DECIMAL extension (2), but got " + type); + + var bytes = readPayload(len); + + ByteBuffer bb = ByteBuffer.wrap(bytes); + + int scale = bb.getInt(); + + return new BigDecimal(new BigInteger(bytes, bb.position(), bb.remaining()), scale); } /** * Reads a bit set. * * @return Bit set. - * @throws UnsupportedOperationException Not supported yet. */ public BitSet unpackBitSet() { assert refCnt > 0 : "Unpacker is closed"; - throw new UnsupportedOperationException("TODO: IGNITE-15163"); + var hdr = unpackExtensionTypeHeader(); + var type = hdr.getType(); + var len = hdr.getLength(); + + if (type != ClientMsgPackType.BITMASK) + throw new MessageTypeException("Expected DECIMAL extension (7), but got " + type); + + var bytes = readPayload(len); + + return BitSet.valueOf(bytes); + } + + /** + * Reads a big number. + * + * @return Bit set. + */ + public BigInteger unpackNumber() { + assert refCnt > 0 : "Unpacker is closed"; + + var hdr = unpackExtensionTypeHeader(); + var type = hdr.getType(); + var len = hdr.getLength(); + + if (type != ClientMsgPackType.NUMBER) + throw new MessageTypeException("Expected NUMBER extension (1), but got " + type); + + var bytes = readPayload(len); + + return new BigInteger(bytes); } /** @@ -398,16 +440,20 @@ public class ClientMessageUnpacker extends MessageUnpacker { case STRING: return unpackString(); - case BYTES: + case BYTES: { var cnt = unpackBinaryHeader(); return readPayload(cnt); + } case DECIMAL: return unpackDecimal(); case BITMASK: return unpackBitSet(); + + case NUMBER: + return unpackNumber(); } throw new IgniteException("Unknown client data type: " + dataType); diff --git a/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMsgPackType.java b/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMsgPackType.java index dd92c46..7db9de5 100644 --- a/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMsgPackType.java +++ b/modules/client-common/src/main/java/org/apache/ignite/client/proto/ClientMsgPackType.java @@ -38,4 +38,7 @@ public class ClientMsgPackType { /** DateTime. */ public static final byte DATETIME = 6; + + /** Bit mask. */ + public static final byte BITMASK = 7; } diff --git a/modules/client-common/src/test/java/org/apache/ignite/client/proto/ClientMessagePackerUnpackerTest.java b/modules/client-common/src/test/java/org/apache/ignite/client/proto/ClientMessagePackerUnpackerTest.java index 3d04434..92f0e55 100644 --- a/modules/client-common/src/test/java/org/apache/ignite/client/proto/ClientMessagePackerUnpackerTest.java +++ b/modules/client-common/src/test/java/org/apache/ignite/client/proto/ClientMessagePackerUnpackerTest.java @@ -17,12 +17,18 @@ package org.apache.ignite.client.proto; -import java.io.IOException; -import java.util.UUID; import io.netty.buffer.PooledByteBufAllocator; import io.netty.buffer.Unpooled; +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.BitSet; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; +import org.apache.ignite.internal.testframework.IgniteTestUtils; import org.junit.jupiter.api.Test; +import static org.apache.ignite.internal.testframework.IgniteTestUtils.randomBytes; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -73,6 +79,55 @@ public class ClientMessagePackerUnpackerTest { testUUID(new UUID(0, 0)); } + @Test + public void testNumber() throws IOException { + testNumber(BigInteger.ZERO); + testNumber(BigInteger.valueOf(Long.MIN_VALUE)); + testNumber(BigInteger.valueOf(Long.MAX_VALUE)); + + testNumber(new BigInteger(randomBytes(ThreadLocalRandom.current(), 100))); + testNumber(new BigInteger(randomBytes(ThreadLocalRandom.current(), 250))); + testNumber(new BigInteger(randomBytes(ThreadLocalRandom.current(), 1000))); + } + + @Test + public void testDecimal() throws IOException { + testDecimal(BigDecimal.ZERO); + testDecimal(BigDecimal.valueOf(Long.MIN_VALUE)); + testDecimal(BigDecimal.valueOf(Long.MAX_VALUE)); + + testDecimal(new BigDecimal(new BigInteger(randomBytes(ThreadLocalRandom.current(), 100)), 50)); + testDecimal(new BigDecimal(new BigInteger(randomBytes(ThreadLocalRandom.current(), 250)), 200)); + testDecimal(new BigDecimal(new BigInteger(randomBytes(ThreadLocalRandom.current(), 1000)), 500)); + } + + + @Test + public void testBitSet() throws IOException { + testBitSet(BitSet.valueOf(new byte[0])); + testBitSet(BitSet.valueOf(randomBytes(ThreadLocalRandom.current(), 1))); + testBitSet(BitSet.valueOf(randomBytes(ThreadLocalRandom.current(), 100))); + testBitSet(BitSet.valueOf(randomBytes(ThreadLocalRandom.current(), 1000))); + } + + private void testBitSet(BitSet val) { + try (var packer = new ClientMessagePacker(PooledByteBufAllocator.DEFAULT.directBuffer())) { + packer.packBitSet(val); + + var buf = packer.getBuffer(); + var len = buf.readInt(); + + byte[] data = new byte[buf.readableBytes()]; + buf.readBytes(data); + + try (var unpacker = new ClientMessageUnpacker(Unpooled.wrappedBuffer(data))) { + var res = unpacker.unpackBitSet(); + + assertEquals(val, res); + } + } + } + private void testUUID(UUID u) throws IOException { try (var packer = new ClientMessagePacker(PooledByteBufAllocator.DEFAULT.directBuffer())) { packer.packUuid(u); @@ -91,4 +146,40 @@ public class ClientMessagePackerUnpackerTest { } } } + + private void testNumber(BigInteger val) { + try (var packer = new ClientMessagePacker(PooledByteBufAllocator.DEFAULT.directBuffer())) { + packer.packNumber(val); + + var buf = packer.getBuffer(); + var len = buf.readInt(); + + byte[] data = new byte[buf.readableBytes()]; + buf.readBytes(data); + + try (var unpacker = new ClientMessageUnpacker(Unpooled.wrappedBuffer(data))) { + var res = unpacker.unpackNumber(); + + assertEquals(val, res); + } + } + } + + private void testDecimal(BigDecimal val) { + try (var packer = new ClientMessagePacker(PooledByteBufAllocator.DEFAULT.directBuffer())) { + packer.packDecimal(val); + + var buf = packer.getBuffer(); + var len = buf.readInt(); + + byte[] data = new byte[buf.readableBytes()]; + buf.readBytes(data); + + try (var unpacker = new ClientMessageUnpacker(Unpooled.wrappedBuffer(data))) { + var res = unpacker.unpackDecimal(); + + assertEquals(val, res); + } + } + } } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/testframework/IgniteTestUtils.java b/modules/core/src/test/java/org/apache/ignite/internal/testframework/IgniteTestUtils.java index 838b7eb..dfceebd 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/testframework/IgniteTestUtils.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/testframework/IgniteTestUtils.java @@ -19,6 +19,7 @@ package org.apache.ignite.internal.testframework; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.util.Random; import java.util.function.BooleanSupplier; import org.apache.ignite.lang.IgniteInternalException; import org.jetbrains.annotations.NotNull; @@ -207,4 +208,16 @@ public final class IgniteTestUtils { return false; } + + /** + * @param rnd Random generator. + * @param len Byte array length. + * @return Random byte array. + */ + public static byte[] randomBytes(Random rnd, int len) { + byte[] data = new byte[len]; + rnd.nextBytes(data); + + return data; + } } diff --git a/modules/schema/pom.xml b/modules/schema/pom.xml index cb3f3c7..6faa0d5 100644 --- a/modules/schema/pom.xml +++ b/modules/schema/pom.xml @@ -68,6 +68,13 @@ </dependency> <dependency> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-core</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + + <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/TestUtils.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/TestUtils.java index 878fb76..8758b5b 100644 --- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/TestUtils.java +++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/TestUtils.java @@ -21,6 +21,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.BitSet; import java.util.Random; +import org.apache.ignite.internal.testframework.IgniteTestUtils; /** * Test utility class. @@ -60,7 +61,7 @@ public final class TestUtils { return randomString(rnd, rnd.nextInt(255)); case BYTES: - return randomBytes(rnd, rnd.nextInt(255)); + return IgniteTestUtils.randomBytes(rnd, rnd.nextInt(255)); case NUMBER: return BigInteger.probablePrime(12, rnd); @@ -97,18 +98,6 @@ public final class TestUtils { /** * @param rnd Random generator. - * @param len Byte array length. - * @return Random byte array. - */ - public static byte[] randomBytes(Random rnd, int len) { - byte[] data = new byte[len]; - rnd.nextBytes(data); - - return data; - } - - /** - * @param rnd Random generator. * @param len String length. * @return Random string. */ diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java index 84e32da..c25eef3 100644 --- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java +++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java @@ -476,7 +476,7 @@ public class JavaSerializerTest { obj.uuidCol = new UUID(rnd.nextLong(), rnd.nextLong()); obj.bitmaskCol = TestUtils.randomBitSet(rnd, 42); obj.stringCol = TestUtils.randomString(rnd, rnd.nextInt(255)); - obj.bytesCol = TestUtils.randomBytes(rnd, rnd.nextInt(255)); + obj.bytesCol = IgniteTestUtils.randomBytes(rnd, rnd.nextInt(255)); obj.numberCol = (BigInteger)TestUtils.generateRandomValue(rnd, NativeTypes.numberOf(12)); obj.decimalCol = (BigDecimal)TestUtils.generateRandomValue(rnd, NativeTypes.decimalOf(19, 3)); diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java index 0c75ceb..951824a 100644 --- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java +++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessorTest.java @@ -320,7 +320,7 @@ public class FieldAccessorTest { obj.uuidCol = new UUID(rnd.nextLong(), rnd.nextLong()); obj.bitmaskCol = TestUtils.randomBitSet(rnd, rnd.nextInt(42)); obj.stringCol = TestUtils.randomString(rnd, rnd.nextInt(255)); - obj.bytesCol = TestUtils.randomBytes(rnd, rnd.nextInt(255)); + obj.bytesCol = IgniteTestUtils.randomBytes(rnd, rnd.nextInt(255)); obj.numberCol = (BigInteger)TestUtils.generateRandomValue(rnd, NativeTypes.numberOf(12)); obj.decimalCol = (BigDecimal) TestUtils.generateRandomValue(rnd, NativeTypes.decimalOf(19, 3));