You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2021/06/09 19:36:12 UTC

[ignite-3] branch ignite-14743 created (now e5d6b43)

This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a change to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git.


      at e5d6b43  WIP. Styles.

This branch includes the following new commits:

     new b0bc9e5  Add tiny,normal,large chunk formats.
     new 0e66f15  Merge branch 'main' into gg-14743
     new 0d336b6  Optimize serialized row size.
     new 87f9fe5  Fix tests.
     new 926ef7f  Minor.
     new 1d9efdd  Styles.
     new d55c967  Merge branch 'main' into gg-14743
     new da99bed  Revert to format independent hashcode.
     new d1ff1cf  Minor.
     new d9d414d  WIP.
     new cdb9015  WIP.
     new abcb9e0  Merge branch 'main' into gg-14743
     new c913679  WIP.
     new 37ca010  Merge branch 'main' into gg-14743
     new e5d6b43  WIP. Styles.

The 15 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[ignite-3] 12/15: Merge branch 'main' into gg-14743

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit abcb9e02223f8d4f74e19588a4e63809396dd417
Merge: cdb9015 fb14a5f
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Wed Jun 9 11:04:46 2021 +0300

    Merge branch 'main' into gg-14743
    
    # Conflicts:
    #	modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java
    #	modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
    #	modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java

 .../asm/IdentityMarshallerCodeGenerator.java       |   3 +-
 .../asm/ObjectMarshallerCodeGenerator.java         |   5 +-
 .../org/apache/ignite/internal/schema/row/Row.java |   4 +-
 .../internal/schema/ExpandableByteBufTest.java     |  29 +-
 .../schema/RowAssemblerAdvancedSchemaTest.java     | 307 ++++++++++
 .../schema/RowAssemblerSimpleSchemaTest.java       | 643 +++++++++++++++++++++
 6 files changed, 981 insertions(+), 10 deletions(-)

diff --cc modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
index c3dd7f7,973e8b2..963ac1a
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
@@@ -368,31 -365,15 +368,31 @@@ public class Row implements BinaryRow 
              throw new InvalidTypeException("Invalid column type requested [requested=" + type +
                  ", column=" + cols.column(colIdx) + ']');
  
 -        boolean hasVarTable = ((keyCol ? RowFlags.OMIT_KEY_VARTBL_FLAG : RowFlags.OMIT_VAL_VARTBL_FLAG) & flags) == 0;
 -        boolean hasNullMap = ((keyCol ? RowFlags.OMIT_KEY_NULL_MAP_FLAG : RowFlags.OMIT_VAL_NULL_MAP_FLAG) & flags) == 0;
 +        assert reader != null;
  
 -        if (hasNullMap && isNull(off, colIdx))
 +        if (reader.isNull(colIdx))
              return -1;
  
 +        assert reader.hasVartable() || type.fixedLength();
 +
          return type.fixedLength() ?
-             reader.fixlenColumnOffset(cols, colIdx) :
-             reader.varlenColumnOffsetAndLength(cols, colIdx);
 -            fixlenColumnOffset(cols, off, colIdx, hasVarTable, hasNullMap) :
 -            varlenColumnOffsetAndLength(cols, off, colIdx, hasVarTable, hasNullMap);
++            reader.fixlenColumnOffset(cols, off, colIdx, hasVarTable, hasNullMap) :
++            reader.varlenColumnOffsetAndLength(cols, off, colIdx, hasVarTable, hasNullMap);
 +    }
 +
 +    private ChunkReader valueReader() {
 +        if (valReader != null)
 +            return valReader;
 +
 +        final short flags = readShort(FLAGS_FIELD_OFFSET);
 +
 +        assert (flags & RowFlags.NO_VALUE_FLAG) == 0 : "Row has no value.";
 +
 +        return (valReader = ChunkFormat.createReader(
 +            this,
 +            KEY_CHUNK_OFFSET + keyReader.chunkLength(),
 +            schema.keyColumns().nullMapSize(),
 +            (byte)(flags >>> RowFlags.VAL_FLAGS_OFFSET)));
      }
  
      /**

[ignite-3] 08/15: Revert to format independent hashcode.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit da99beda5ca122bba3b7a3a9ee9dc444651428f8
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Mon Jun 7 17:16:59 2021 +0300

    Revert to format independent hashcode.
---
 .../ignite/internal/schema/row/RowAssembler.java   | 45 ++++++++++++++++++++--
 1 file changed, 42 insertions(+), 3 deletions(-)

diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
index 4024a50..cd8a2ea 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.schema.row;
 
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
 import java.util.BitSet;
 import java.util.UUID;
 import org.apache.ignite.internal.schema.AssemblyException;
@@ -64,6 +65,9 @@ public class RowAssembler {
     /** Current field index (the field is unset). */
     private int curCol;
 
+    /** Hash. */
+    private int hash;
+
     /** Flags. */
     private short flags;
 
@@ -247,6 +251,9 @@ public class RowAssembler {
             throw new IllegalArgumentException("Failed to set column (null was passed, but column is not nullable): " +
                 col);
 
+        if (isKeyColumn())
+            hash = 31 * hash;
+
         chunkWriter.setNull(curCol);
 
         shiftColumn();
@@ -260,6 +267,9 @@ public class RowAssembler {
     public void appendByte(byte val) {
         checkType(NativeTypes.BYTE);
 
+        if (isKeyColumn())
+            hash = 31 * hash + Byte.hashCode(val);
+
         chunkWriter.appendByte(val);
 
         shiftColumn();
@@ -273,6 +283,9 @@ public class RowAssembler {
     public void appendShort(short val) {
         checkType(NativeTypes.SHORT);
 
+        if (isKeyColumn())
+            hash = 31 * hash + Short.hashCode(val);
+
         chunkWriter.appendShort(val);
 
         shiftColumn();
@@ -286,6 +299,9 @@ public class RowAssembler {
     public void appendInt(int val) {
         checkType(NativeTypes.INTEGER);
 
+        if (isKeyColumn())
+            hash = 31 * hash + Integer.hashCode(val);
+
         chunkWriter.appendInt(val);
 
         shiftColumn();
@@ -299,6 +315,9 @@ public class RowAssembler {
     public void appendLong(long val) {
         checkType(NativeTypes.LONG);
 
+        if (isKeyColumn())
+            hash = 31 * hash + Long.hashCode(val);
+
         chunkWriter.appendLong(val);
 
         shiftColumn();
@@ -312,6 +331,9 @@ public class RowAssembler {
     public void appendFloat(float val) {
         checkType(NativeTypes.FLOAT);
 
+        if (isKeyColumn())
+            hash = 31 * hash + Float.hashCode(val);
+
         chunkWriter.appendFloat(val);
 
         shiftColumn();
@@ -325,6 +347,9 @@ public class RowAssembler {
     public void appendDouble(double val) {
         checkType(NativeTypes.DOUBLE);
 
+        if (isKeyColumn())
+            hash = 31 * hash + Double.hashCode(val);
+
         chunkWriter.appendDouble(val);
 
         shiftColumn();
@@ -338,6 +363,9 @@ public class RowAssembler {
     public void appendUuid(UUID uuid) {
         checkType(NativeTypes.UUID);
 
+        if (isKeyColumn())
+            hash = 31 * hash + uuid.hashCode();
+
         chunkWriter.appendUuid(uuid);
 
         shiftColumn();
@@ -354,6 +382,9 @@ public class RowAssembler {
         assert (flags & (schema.keyColumns() == curCols ? OMIT_KEY_VARTBL_FLAG : OMIT_VAL_VARTBL_FLAG)) == 0 :
             "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
 
+        if (isKeyColumn())
+            hash = 31 * hash + val.hashCode();
+
         chunkWriter.appendString(val, encoder());
 
         shiftColumn();
@@ -370,6 +401,9 @@ public class RowAssembler {
         assert (flags & (schema.keyColumns() == curCols ? OMIT_KEY_VARTBL_FLAG : OMIT_VAL_VARTBL_FLAG)) == 0 :
             "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
 
+        if (isKeyColumn())
+            hash = 31 * hash + Arrays.hashCode(val);
+
         chunkWriter.appendBytes(val);
 
         shiftColumn();
@@ -391,6 +425,9 @@ public class RowAssembler {
             throw new IllegalArgumentException("Failed to set bitmask for column '" + col.name() + "' " +
                 "(mask size exceeds allocated size) [mask=" + bitSet + ", maxSize=" + maskType.bits() + "]");
 
+        if (isKeyColumn())
+            hash = 31 * hash + bitSet.hashCode();
+
         chunkWriter.appendBitmask(bitSet, maskType.sizeInBytes());
 
         shiftColumn();
@@ -410,10 +447,15 @@ public class RowAssembler {
         }
 
         buf.putShort(BinaryRow.FLAGS_FIELD_OFFSET, flags);
+        buf.putInt(KEY_HASH_FIELD_OFFSET, hash);
 
         return buf.toArray();
     }
 
+    private boolean isKeyColumn () {
+        return curCols == schema.keyColumns();
+    }
+
     /**
      * @return UTF-8 string encoder.
      */
@@ -460,9 +502,6 @@ public class RowAssembler {
             if (schema.valueColumns() == curCols)
                 return; // No more columns.
 
-            // Write key hash.
-            buf.putInt(KEY_HASH_FIELD_OFFSET, XXHash32.hash(buf.unwrap(), chunkWriter.dataOff, chunkWriter.curOff - chunkWriter.dataOff));
-
             // Switch key->value columns.
             curCols = schema.valueColumns();
             curCol = 0;

[ignite-3] 14/15: Merge branch 'main' into gg-14743

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 37ca010cb9e966ff2700c81d3422bb4e7bc63229
Merge: c913679 67e8ede
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Wed Jun 9 13:57:28 2021 +0300

    Merge branch 'main' into gg-14743

 modules/bytecode/pom.xml                           |    2 +-
 modules/calcite/pom.xml                            |    5 +
 .../internal/processors/query/calcite/Stubs.java   |    5 +
 .../query/calcite/externalize/RelInputEx.java}     |   17 +-
 .../query/calcite/externalize/RelJson.java         |  918 +++++
 .../query/calcite/externalize/RelJsonReader.java   |  330 ++
 .../query/calcite/externalize/RelJsonWriter.java   |  168 +
 .../query/calcite/metadata/ColocationGroup.java    |  230 ++
 .../metadata/ColocationMappingException.java}      |   18 +-
 .../query/calcite/metadata/FragmentMapping.java    |  147 +
 .../calcite/metadata/FragmentMappingException.java |   58 +
 .../calcite/metadata/IgniteMdFragmentMapping.java  |  226 ++
 .../query/calcite/metadata/IgniteMetadata.java     |   24 +
 .../query/calcite/metadata/MappingService.java     |   41 +
 .../NodeMappingException.java}                     |   35 +-
 .../query/calcite/metadata/RelMetadataQueryEx.java |   28 +
 .../calcite/prepare/AbstractMultiStepPlan.java     |  101 +
 .../processors/query/calcite/prepare/Cloner.java   |  257 ++
 .../{Stubs.java => prepare/ExecutionPlan.java}     |   32 +-
 .../processors/query/calcite/prepare/Fragment.java |  193 ++
 .../query/calcite/prepare/FragmentSplitter.java    |  144 +
 .../{Stubs.java => prepare/IdGenerator.java}       |   21 +-
 .../query/calcite/prepare/MultiStepPlan.java       |   54 +
 .../MultiStepQueryPlan.java}                       |   29 +-
 .../query/calcite/prepare/PlanningContext.java     |   31 +-
 .../query/calcite/prepare/QueryPlan.java}          |   22 +-
 .../query/calcite/prepare/QueryTemplate.java       |  136 +
 .../processors/query/calcite/prepare/Splitter.java |  125 +
 .../query/calcite/rel/AbstractIgniteSpool.java     |   47 +
 .../query/calcite/rel/IgniteHashIndexSpool.java    |    4 +-
 .../query/calcite/rel/IgniteMergeJoin.java         |    5 +-
 .../query/calcite/rel/IgniteSortedIndexSpool.java  |    4 +-
 .../query/calcite/rel/IgniteTableFunctionScan.java |   11 +
 .../query/calcite/rel/IgniteTableModify.java       |    2 +-
 .../query/calcite/rel/IgniteTableSpool.java        |    5 +-
 .../query/calcite/schema/IgniteTable.java          |   10 +
 .../query/calcite/util/IgniteMethod.java           |   50 +
 .../query/calcite/planner/AbstractPlannerTest.java |   96 +
 .../query/calcite/planner/PlannerTest.java         | 1847 ++++++++++
 .../apache/ignite/internal/util/ArrayUtils.java    |   56 +
 .../ignite/internal/util/IgniteIntIterator.java}   |   19 +-
 .../apache/ignite/internal/util/IgniteIntList.java |  526 +++
 .../apache/ignite/internal/util/IgniteUtils.java   |   82 +
 .../internal/testframework/IgniteTestUtils.java    |  116 +
 .../client/ITMetaStorageServiceTest.java           |    4 +-
 .../ignite/network/internal/netty/NettyServer.java |    3 +
 modules/raft/pom.xml                               |   57 +-
 .../ignite/raft/jraft/core/ITCliServiceTest.java   |  558 +++
 .../apache/ignite/raft/jraft/core/ITNodeTest.java  | 3580 ++++++++++++++++++++
 .../apache/ignite/raft/server/CounterListener.java |   59 +-
 .../ignite/raft/server/CounterSnapshotFile.java    |   81 +
 .../apache/ignite/raft/server/GetValueCommand.java |    4 +-
 .../raft/server/ITJRaftCounterServerTest.java      |  565 +++
 ...verTest.java => ITSimpleCounterServerTest.java} |   54 +-
 .../ignite/raft/server/IncrementAndGetCommand.java |    8 +-
 ...stractTest.java => RaftServerAbstractTest.java} |   48 +-
 .../java/org/apache/ignite/internal/raft/Loza.java |    4 +-
 .../{ => internal}/raft/server/RaftServer.java     |   15 +-
 .../internal/raft/server/impl/JRaftServerImpl.java |  314 ++
 .../raft/server/impl/RaftServerImpl.java           |   14 +-
 .../org/apache/ignite/raft/jraft/CliService.java   |  175 +
 .../org/apache/ignite/raft/jraft/Closure.java}     |   16 +-
 .../org/apache/ignite/raft/jraft/FSMCaller.java    |  116 +
 .../org/apache/ignite/raft/jraft/Iterator.java     |   66 +
 .../ignite/raft/jraft/JRaftServiceFactory.java     |   71 +
 .../org/apache/ignite/raft/jraft/JRaftUtils.java   |  205 ++
 .../org/apache/ignite/raft/jraft/Lifecycle.java}   |   19 +-
 .../java/org/apache/ignite/raft/jraft/Node.java    |  301 ++
 .../org/apache/ignite/raft/jraft/NodeManager.java  |   99 +
 .../apache/ignite/raft/jraft/RaftGroupService.java |  278 ++
 .../apache/ignite/raft/jraft/ReadOnlyService.java  |   50 +
 .../apache/ignite/raft/jraft/ReplicatorGroup.java  |  210 ++
 .../org/apache/ignite/raft/jraft/StateMachine.java |  123 +
 .../java/org/apache/ignite/raft/jraft/Status.java  |  235 ++
 .../raft/jraft/ThreadPoolMetricsSignalHandler.java |   58 +
 .../ignite/raft/jraft/closure/CatchUpClosure.java  |   67 +
 .../ignite/raft/jraft/closure/ClosureQueue.java    |   65 +
 .../raft/jraft/closure/ClosureQueueImpl.java       |  147 +
 .../ignite/raft/jraft/closure/JoinableClosure.java |   57 +
 .../raft/jraft/closure/LoadSnapshotClosure.java}   |   17 +-
 .../raft/jraft/closure/ReadIndexClosure.java       |  101 +
 .../raft/jraft/closure/SaveSnapshotClosure.java}   |   31 +-
 .../raft/jraft/closure/SynchronizedClosure.java    |   77 +
 .../ignite/raft/jraft/closure/TaskClosure.java}    |   29 +-
 .../ignite/raft/jraft/conf/Configuration.java      |  321 ++
 .../ignite/raft/jraft/conf/ConfigurationEntry.java |  124 +
 .../raft/jraft/conf/ConfigurationManager.java      |  106 +
 .../apache/ignite/raft/jraft/core/BallotBox.java   |  281 ++
 .../ignite/raft/jraft/core/CliServiceImpl.java     |  702 ++++
 .../jraft/core/DefaultJRaftServiceFactory.java     |   60 +
 .../ignite/raft/jraft/core/ElectionPriority.java}  |   28 +-
 .../ignite/raft/jraft/core/FSMCallerImpl.java      |  720 ++++
 .../ignite/raft/jraft/core/IteratorImpl.java       |  160 +
 .../ignite/raft/jraft/core/IteratorWrapper.java    |   74 +
 .../apache/ignite/raft/jraft/core/NodeImpl.java    | 3515 +++++++++++++++++++
 .../apache/ignite/raft/jraft/core/NodeMetrics.java |  106 +
 .../raft/jraft/core/ReadOnlyServiceImpl.java       |  423 +++
 .../apache/ignite/raft/jraft/core/Replicator.java  | 1806 ++++++++++
 .../raft/jraft/core/ReplicatorGroupImpl.java       |  330 ++
 .../ignite/raft/jraft/core/ReplicatorType.java}    |   18 +-
 .../apache/ignite/raft/jraft/core/Scheduler.java   |   72 +
 .../org/apache/ignite/raft/jraft/core/State.java}  |   36 +-
 .../raft/jraft/core/StateMachineAdapter.java       |  104 +
 .../ignite/raft/jraft/core/TimerManager.java       |   65 +
 .../apache/ignite/raft/jraft/entity/Ballot.java    |  135 +
 .../apache/ignite/raft/jraft/entity/Checksum.java} |   31 +-
 .../ignite/raft/jraft/entity/EnumOutter.java       |  150 +
 .../raft/jraft/entity/LeaderChangeContext.java     |  113 +
 .../raft/jraft/entity/LocalFileMetaOutter.java     |   94 +
 .../raft/jraft/entity/LocalStorageOutter.java      |  112 +
 .../apache/ignite/raft/jraft/entity/LogEntry.java  |  255 ++
 .../org/apache/ignite/raft/jraft/entity/LogId.java |  121 +
 .../apache/ignite/raft/jraft/entity/NodeId.java    |  100 +
 .../apache/ignite/raft/jraft/entity/PeerId.java    |  288 ++
 .../ignite/raft/jraft/entity/RaftOutter.java       |  133 +
 .../ignite/raft/jraft/entity/ReadIndexState.java   |   63 +
 .../ignite/raft/jraft/entity/ReadIndexStatus.java  |   54 +
 .../org/apache/ignite/raft/jraft/entity/Task.java  |  169 +
 .../apache/ignite/raft/jraft/entity/UserLog.java   |   62 +
 .../jraft/entity/codec/AutoDetectDecoder.java}     |   40 +-
 .../entity/codec/DefaultLogEntryCodecFactory.java} |   39 +-
 .../jraft/entity/codec/LogEntryCodecFactory.java}  |   30 +-
 .../raft/jraft/entity/codec/LogEntryDecoder.java}  |   18 +-
 .../raft/jraft/entity/codec/LogEntryEncoder.java}  |   18 +-
 .../entity/codec/v1/LogEntryV1CodecFactory.java    |   55 +
 .../raft/jraft/entity/codec/v1/V1Decoder.java      |  148 +
 .../raft/jraft/entity/codec/v1/V1Encoder.java      |  175 +
 .../raft/jraft/error/InvokeTimeoutException.java}  |   37 +-
 .../ignite/raft/jraft/error/JRaftException.java}   |   36 +-
 .../jraft/error/LogEntryCorruptedException.java    |   51 +
 .../jraft/error/LogIndexOutOfBoundsException.java  |   50 +
 .../raft/jraft/error/LogNotFoundException.java}    |   33 +-
 .../error/MessageClassNotFoundException.java}      |   38 +-
 .../apache/ignite/raft/jraft/error/RaftError.java  |  269 ++
 .../ignite/raft/jraft/error/RaftException.java     |   80 +
 .../raft/jraft/error/RemotingException.java}       |   36 +-
 .../raft/jraft/error/RetryAgainException.java}     |   42 +-
 .../raft/jraft/option/BallotBoxOptions.java}       |   37 +-
 .../ignite/raft/jraft/option/BootstrapOptions.java |  133 +
 .../ignite/raft/jraft/option/CliOptions.java}      |   33 +-
 .../ignite/raft/jraft/option/CopyOptions.java}     |   42 +-
 .../ignite/raft/jraft/option/FSMCallerOptions.java |   96 +
 .../raft/jraft/option/LogManagerOptions.java       |  103 +
 .../raft/jraft/option/LogStorageOptions.java       |   47 +
 .../ignite/raft/jraft/option/NodeOptions.java      |  538 +++
 .../raft/jraft/option/RaftMetaStorageOptions.java} |   18 +-
 .../ignite/raft/jraft/option/RaftOptions.java      |  302 ++
 .../ignite/raft/jraft/option/ReadOnlyOption.java}  |   19 +-
 .../raft/jraft/option/ReadOnlyServiceOptions.java} |   46 +-
 .../raft/jraft/option/ReplicatorGroupOptions.java  |  120 +
 .../raft/jraft/option/ReplicatorOptions.java       |  224 ++
 .../ignite/raft/jraft/option/RpcOptions.java       |  136 +
 .../raft/jraft/option/SnapshotCopierOptions.java   |   76 +
 .../raft/jraft/option/SnapshotExecutorOptions.java |  103 +
 .../ignite/raft/jraft/rpc/CliClientService.java    |  147 +
 .../apache/ignite/raft/jraft/rpc/CliRequests.java  |  461 +++
 .../ignite/raft/jraft/rpc/ClientService.java       |   47 +
 .../ignite/raft/jraft/rpc/InvokeCallback.java}     |   15 +-
 .../ignite/raft/jraft/rpc/InvokeContext.java}      |   41 +-
 .../org/apache/ignite/raft/jraft/rpc/Message.java} |   29 +-
 .../raft/jraft/rpc/MessageBuilderFactory.java      |  102 +
 .../ignite/raft/jraft/rpc/RaftClientService.java   |  106 +
 .../ignite/raft/jraft/rpc/RaftRpcFactory.java}     |   13 +-
 .../ignite/raft/jraft/rpc/RaftServerService.java   |   81 +
 .../apache/ignite/raft/jraft/rpc/RpcClient.java    |   95 +
 .../apache/ignite/raft/jraft/rpc/RpcClientEx.java} |   21 +-
 .../apache/ignite/raft/jraft/rpc/RpcContext.java}  |   38 +-
 .../apache/ignite/raft/jraft/rpc/RpcProcessor.java |   72 +
 .../ignite/raft/jraft/rpc/RpcRequestClosure.java   |   68 +
 .../ignite/raft/jraft/rpc/RpcRequestProcessor.java |   68 +
 .../apache/ignite/raft/jraft/rpc/RpcRequests.java  |  471 +++
 .../ignite/raft/jraft/rpc/RpcResponseClosure.java} |   21 +-
 .../raft/jraft/rpc/RpcResponseClosureAdapter.java} |   33 +-
 .../ignite/raft/jraft/rpc/RpcResponseFactory.java  |   76 +
 .../apache/ignite/raft/jraft/rpc/RpcServer.java}   |   33 +-
 .../raft/jraft/rpc/impl/AbstractClientService.java |  276 ++
 .../rpc/impl/ConnectionClosedEventListener.java}   |   12 +-
 .../ignite/raft/jraft/rpc/impl/FutureImpl.java}    |   13 +-
 .../raft/jraft/rpc/impl/IgniteRpcClient.java       |  222 ++
 .../raft/jraft/rpc/impl/IgniteRpcServer.java       |  218 ++
 .../raft/jraft/rpc/impl/PingRequestProcessor.java  |   55 +
 .../rpc/impl/cli/AddLearnersRequestProcessor.java  |   97 +
 .../rpc/impl/cli/AddPeerRequestProcessor.java      |   91 +
 .../rpc/impl/cli/BaseCliRequestProcessor.java      |  145 +
 .../rpc/impl/cli/ChangePeersRequestProcessor.java  |   89 +
 .../jraft/rpc/impl/cli/CliClientServiceImpl.java   |  126 +
 .../rpc/impl/cli/GetLeaderRequestProcessor.java    |  100 +
 .../rpc/impl/cli/GetPeersRequestProcessor.java     |   73 +
 .../impl/cli/RemoveLearnersRequestProcessor.java   |   92 +
 .../rpc/impl/cli/RemovePeerRequestProcessor.java   |   85 +
 .../impl/cli/ResetLearnersRequestProcessor.java    |   93 +
 .../rpc/impl/cli/ResetPeerRequestProcessor.java    |   75 +
 .../rpc/impl/cli/SnapshotRequestProcessor.java     |   57 +
 .../impl/cli/TransferLeaderRequestProcessor.java   |   68 +
 .../rpc/impl/client/ActionRequestProcessor.java    |  207 ++
 .../rpc/impl/client/GetLeaderRequestProcessor.java |   74 +
 .../rpc/impl/client/SnapshotRequestProcessor.java  |   75 +
 .../impl/core/AppendEntriesRequestProcessor.java   |  468 +++
 .../rpc/impl/core/DefaultRaftClientService.java    |  154 +
 .../rpc/impl/core/GetFileRequestProcessor.java     |   45 +
 .../impl/core/InstallSnapshotRequestProcessor.java |   57 +
 .../jraft/rpc/impl/core/NodeRequestProcessor.java  |   68 +
 .../rpc/impl/core/ReadIndexRequestProcessor.java   |   72 +
 .../rpc/impl/core/RequestVoteRequestProcessor.java |   60 +
 .../rpc/impl/core/TimeoutNowRequestProcessor.java  |   57 +
 .../jraft/rpc/message/AddLearnersRequestImpl.java  |   69 +
 .../raft/jraft/rpc/message/AddPeerRequestImpl.java |   59 +
 .../jraft/rpc/message/AddPeerResponseImpl.java     |   66 +
 .../rpc/message/AppendEntriesRequestImpl.java      |  186 +
 .../rpc/message/AppendEntriesResponseImpl.java     |   59 +
 .../jraft/rpc/message/ChangePeerRequestImpl.java   |   69 +
 .../jraft/rpc/message/ChangePeersResponseImpl.java |   66 +
 .../rpc/message/DefaultMessageBuilderFactory.java  |  174 +
 .../raft/jraft/rpc/message/EntryMetaImpl.java      |  186 +
 .../raft/jraft/rpc/message/ErrorResponseImpl.java} |   40 +-
 .../raft/jraft/rpc/message/GetFileRequestImpl.java |  109 +
 .../jraft/rpc/message/GetFileResponseImpl.java     |   60 +
 .../jraft/rpc/message/GetLeaderRequestImpl.java}   |   44 +-
 .../jraft/rpc/message/GetLeaderResponseImpl.java}  |   29 +-
 .../jraft/rpc/message/GetPeersRequestImpl.java     |   59 +
 .../jraft/rpc/message/GetPeersResponseImpl.java    |   66 +
 .../rpc/message/InstallSnapshotRequestImpl.java    |  124 +
 .../rpc/message/InstallSnapshotResponseImpl.java}  |   40 +-
 .../jraft/rpc/message/LearnersOpResponseImpl.java  |   66 +
 .../raft/jraft/rpc/message/LocalFileMetaImpl.java  |   83 +
 .../rpc/message/LocalSnapshotMetaFileImpl.java     |   49 +
 .../jraft/rpc/message/LocalSnapshotMetaImpl.java   |   68 +
 .../raft/jraft/rpc/message/PingRequestImpl.java}   |   29 +-
 .../raft/jraft/rpc/message/PreVoteRequestImpl.java |  103 +
 .../jraft/rpc/message/ReadIndexRequestImpl.java    |   92 +
 .../jraft/rpc/message/ReadIndexResponseImpl.java}  |   40 +-
 .../rpc/message/RemoveLearnersRequestImpl.java     |   69 +
 .../jraft/rpc/message/RemovePeerRequestImpl.java   |   59 +
 .../jraft/rpc/message/RemovePeerResponseImpl.java  |   66 +
 .../rpc/message/RequestVoteResponseImpl.java}      |   40 +-
 .../rpc/message/ResetLearnersRequestImpl.java      |   69 +
 .../jraft/rpc/message/ResetPeerRequestImpl.java    |   82 +
 .../raft/jraft/rpc/message/SnapshotMetaImpl.java   |  157 +
 .../jraft/rpc/message/SnapshotRequestImpl.java}    |   40 +-
 .../ignite/raft/jraft/rpc/message/StableMeta.java} |   40 +-
 .../jraft/rpc/message/TimeoutNowRequestImpl.java   |   95 +
 .../jraft/rpc/message/TimeoutNowResponseImpl.java} |   40 +-
 .../rpc/message/TransferLeaderRequestImpl.java     |   63 +
 .../ignite/raft/jraft/storage/FileService.java     |  150 +
 .../ignite/raft/jraft/storage/LogManager.java      |  224 ++
 .../ignite/raft/jraft/storage/LogStorage.java      |   77 +
 .../raft/jraft/storage/RaftMetaStorage.java}       |   40 +-
 .../raft/jraft/storage/SnapshotExecutor.java       |   84 +
 .../ignite/raft/jraft/storage/SnapshotStorage.java |   68 +
 .../raft/jraft/storage/SnapshotThrottle.java}      |   17 +-
 .../apache/ignite/raft/jraft/storage/Storage.java} |   14 +-
 .../raft/jraft/storage/impl/LocalLogStorage.java   |  278 ++
 .../jraft/storage/impl/LocalRaftMetaStorage.java   |  194 ++
 .../raft/jraft/storage/impl/LogManagerImpl.java    | 1227 +++++++
 .../raft/jraft/storage/impl/RocksDBLogStorage.java |  768 +++++
 .../ignite/raft/jraft/storage/io/FileReader.java   |   52 +
 .../raft/jraft/storage/io/LocalDirReader.java      |   94 +
 .../ignite/raft/jraft/storage/io/MessageFile.java  |   99 +
 .../raft/jraft/storage/snapshot/Snapshot.java      |   53 +
 .../jraft/storage/snapshot/SnapshotCopier.java}    |   35 +-
 .../storage/snapshot/SnapshotExecutorImpl.java     |  736 ++++
 .../jraft/storage/snapshot/SnapshotReader.java}    |   27 +-
 .../jraft/storage/snapshot/SnapshotWriter.java     |   72 +
 .../snapshot/ThroughputSnapshotThrottle.java       |   82 +
 .../storage/snapshot/local/LocalSnapshot.java      |   58 +
 .../snapshot/local/LocalSnapshotCopier.java        |  472 +++
 .../snapshot/local/LocalSnapshotMetaTable.java     |  180 +
 .../snapshot/local/LocalSnapshotReader.java        |  162 +
 .../snapshot/local/LocalSnapshotStorage.java       |  347 ++
 .../snapshot/local/LocalSnapshotWriter.java        |  133 +
 .../storage/snapshot/local/SnapshotFileReader.java |   87 +
 .../jraft/storage/snapshot/remote/CopySession.java |  298 ++
 .../storage/snapshot/remote/RemoteFileCopier.java  |  194 ++
 .../jraft/storage/snapshot/remote/Session.java}    |   31 +-
 .../raft/jraft/util/AdaptiveBufAllocator.java      |  206 ++
 .../apache/ignite/raft/jraft/util/ArrayDeque.java  |  103 +
 .../ignite/raft/jraft/util/AsciiStringUtil.java    |   60 +
 .../org/apache/ignite/raft/jraft/util/Bits.java    |   49 +
 .../raft/jraft/util/ByteBufferCollector.java       |  148 +
 .../apache/ignite/raft/jraft/util/ByteString.java  |  103 +
 .../org/apache/ignite/raft/jraft/util/Bytes.java   |  140 +
 .../apache/ignite/raft/jraft/util/BytesUtil.java   |  179 +
 .../org/apache/ignite/raft/jraft/util/CRC64.java   |  127 +
 .../apache/ignite/raft/jraft/util/Copiable.java}   |   19 +-
 .../ignite/raft/jraft/util/CountDownEvent.java     |   74 +
 .../org/apache/ignite/raft/jraft/util/CrcUtil.java |   82 +
 .../ignite/raft/jraft/util/DebugStatistics.java}   |   19 +-
 .../apache/ignite/raft/jraft/util/Describer.java   |   67 +
 .../ignite/raft/jraft/util/DirectExecutor.java}    |   20 +-
 .../ignite/raft/jraft/util/DisruptorBuilder.java   |   95 +
 .../ignite/raft/jraft/util/DisruptorMetricSet.java |   50 +
 .../apache/ignite/raft/jraft/util/Endpoint.java    |   94 +
 .../raft/jraft/util/ExecutorServiceHelper.java     |   70 +
 .../raft/jraft/util/FileOutputSignalHandler.java   |   50 +
 .../ignite/raft/jraft/util/HeapByteBufUtil.java    |  133 +
 .../org/apache/ignite/raft/jraft/util/Ints.java    |   82 +
 .../ignite/raft/jraft/util/JDKMarshaller.java      |   57 +
 .../raft/jraft/util/JRaftSignalHandler.java}       |   11 +-
 .../raft/jraft/util/LogExceptionHandler.java       |   65 +
 .../jraft/util/LogScheduledThreadPoolExecutor.java |   92 +
 .../raft/jraft/util/LogThreadPoolExecutor.java     |   97 +
 .../apache/ignite/raft/jraft/util/Marshaller.java} |    9 +-
 .../ignite/raft/jraft/util/MetricReporter.java     |  435 +++
 .../util/MetricScheduledThreadPoolExecutor.java    |   72 +
 .../raft/jraft/util/MetricThreadPoolExecutor.java  |   79 +
 .../org/apache/ignite/raft/jraft/util/Mpsc.java}   |   32 +-
 .../ignite/raft/jraft/util/NamedThreadFactory.java |   62 +
 .../ignite/raft/jraft/util/NonReentrantLock.java   |   92 +
 .../ignite/raft/jraft/util/OnlyForTest.java}       |   35 +-
 .../apache/ignite/raft/jraft/util/Platform.java    |   67 +
 .../apache/ignite/raft/jraft/util/Recyclable.java} |   14 +-
 .../raft/jraft/util/RecyclableByteBufferList.java  |  149 +
 .../ignite/raft/jraft/util/RecycleUtil.java}       |   17 +-
 .../apache/ignite/raft/jraft/util/Recyclers.java   |  417 +++
 .../ignite/raft/jraft/util/RepeatedTimer.java      |  296 ++
 .../apache/ignite/raft/jraft/util/Requires.java    |   98 +
 .../apache/ignite/raft/jraft/util/SegmentList.java |  371 ++
 .../raft/jraft/util/StorageOptionsFactory.java     |  342 ++
 .../apache/ignite/raft/jraft/util/StringUtils.java |  361 ++
 .../ignite/raft/jraft/util/SystemPropertyUtil.java |  178 +
 .../ignite/raft/jraft/util/ThreadHelper.java}      |   34 +-
 .../apache/ignite/raft/jraft/util/ThreadId.java    |  173 +
 .../raft/jraft/util/ThreadPoolMetricRegistry.java} |   28 +-
 .../raft/jraft/util/ThreadPoolMetricSet.java       |   52 +
 .../ignite/raft/jraft/util/ThreadPoolUtil.java     |  263 ++
 .../org/apache/ignite/raft/jraft/util/Utils.java   |  540 +++
 .../jraft/util/concurrent/AdjustableSemaphore.java |  126 +
 .../jraft/util/concurrent/ConcurrentHashSet.java   |   93 +
 .../concurrent/DefaultExecutorChooserFactory.java  |   80 +
 .../DefaultFixedThreadsExecutorGroup.java          |  121 +
 .../DefaultFixedThreadsExecutorGroupFactory.java   |   79 +
 .../concurrent/DefaultSingleThreadExecutor.java    |  115 +
 .../util/concurrent/ExecutorChooserFactory.java}   |   35 +-
 .../util/concurrent/FixedThreadsExecutorGroup.java |   63 +
 .../FixedThreadsExecutorGroupFactory.java          |   42 +
 .../concurrent/LongHeldDetectingReadWriteLock.java |  149 +
 .../util/concurrent/MpscSingleThreadExecutor.java  |  404 +++
 .../util/concurrent/RejectedExecutionHandler.java} |   29 +-
 .../concurrent/RejectedExecutionHandlers.java}     |   29 +-
 .../util/concurrent/SingleThreadExecutor.java}     |   32 +-
 .../jraft/util/internal/IntegerFieldUpdater.java}  |   11 +-
 .../jraft/util/internal/LongFieldUpdater.java}     |   11 +-
 .../util/internal/ReferenceFieldUpdater.java}      |   11 +-
 .../internal/ReflectionIntegerFieldUpdater.java    |   52 +
 .../util/internal/ReflectionLongFieldUpdater.java  |   52 +
 .../internal/ReflectionReferenceFieldUpdater.java  |   51 +
 .../ignite/raft/jraft/util/internal/ThrowUtil.java |   64 +
 .../raft/jraft/util/internal/UnsafeUtil.java       |  618 ++++
 .../ignite/raft/jraft/util/internal/Updaters.java  |   88 +
 .../jraft/util/timer/DefaultRaftTimerFactory.java  |   57 +
 .../ignite/raft/jraft/util/timer/DefaultTimer.java |  121 +
 .../raft/jraft/util/timer/HashedWheelTimer.java    |  736 ++++
 .../raft/jraft/util/timer/RaftTimerFactory.java}   |   32 +-
 .../ignite/raft/jraft/util/timer/Timeout.java      |   51 +
 .../apache/ignite/raft/jraft/util/timer/Timer.java |   47 +
 .../ignite/raft/jraft/util/timer/TimerTask.java    |   29 +
 .../org/apache/ignite/raft/jraft/StatusTest.java   |   92 +
 .../raft/jraft/closure/ClosureQueueTest.java       |  115 +
 .../jraft/closure/SynchronizedClosureTest.java     |   78 +
 .../raft/jraft/conf/ConfigurationEntryTest.java    |   87 +
 .../raft/jraft/conf/ConfigurationManagerTest.java  |  109 +
 .../ignite/raft/jraft/conf/ConfigurationTest.java  |  171 +
 .../ignite/raft/jraft/core/BallotBoxTest.java      |  158 +
 .../ignite/raft/jraft/core/ExpectClosure.java      |   65 +
 .../ignite/raft/jraft/core/FSMCallerTest.java      |  293 ++
 .../ignite/raft/jraft/core/IteratorImplTest.java   |  144 +
 .../ignite/raft/jraft/core/IteratorTest.java       |  113 +
 .../ignite/raft/jraft/core/MockClosure.java}       |   16 +-
 .../ignite/raft/jraft/core/MockStateMachine.java   |  235 ++
 .../raft/jraft/core/ReadOnlyServiceTest.java       |  268 ++
 .../raft/jraft/core/ReplicatorGroupTest.java       |  290 ++
 .../ignite/raft/jraft/core/ReplicatorTest.java     |  820 +++++
 .../apache/ignite/raft/jraft/core/TestCluster.java |  460 +++
 .../raft/jraft/core/TestJRaftServiceFactory.java}  |   27 +-
 .../ignite/raft/jraft/entity/BallotTest.java       |   50 +
 .../ignite/raft/jraft/entity/LogEntryTest.java     |  124 +
 .../apache/ignite/raft/jraft/entity/LogIdTest.java |   51 +
 .../ignite/raft/jraft/entity/PeerIdTest.java       |  144 +
 .../entity/codec/BaseLogEntryCodecFactoryTest.java |  143 +
 .../jraft/entity/codec/LogEntryCodecPerfTest.java  |  120 +
 .../codec/v1/LogEntryV1CodecFactoryTest.java}      |   27 +-
 .../raft/jraft/rpc/AbstractClientServiceTest.java  |  242 ++
 .../ignite/raft/jraft/rpc/AbstractRpcTest.java     |  370 ++
 .../raft/jraft/rpc/AppendEntriesBenchmark.java     |  244 ++
 .../ignite/raft/jraft/rpc/IgniteRpcTest.java}      |   87 +-
 .../raft/jraft/rpc/RpcResponseFactoryTest.java     |   65 +
 .../ignite/raft/jraft/rpc/TestIgniteRpcServer.java |   80 +
 .../ignite/raft/jraft/rpc/impl/FutureTest.java     |  140 +
 .../jraft/rpc/impl/PingRequestProcessorTest.java}  |   33 +-
 .../impl/cli/AbstractCliRequestProcessorTest.java  |   93 +
 .../impl/cli/AddLearnersRequestProcessorTest.java  |   66 +
 .../rpc/impl/cli/AddPeerRequestProcessorTest.java  |   61 +
 .../rpc/impl/cli/BaseCliRequestProcessorTest.java  |  192 ++
 .../impl/cli/ChangePeersRequestProcessorTest.java  |   63 +
 .../rpc/impl/cli/GetPeersRequestProcessorTest.java |   53 +
 .../cli/RemoveLearnersRequestProcessorTest.java    |   62 +
 .../impl/cli/RemovePeerRequestProcessorTest.java   |   61 +
 .../cli/ResetLearnersRequestProcessorTest.java     |   66 +
 .../impl/cli/ResetPeersRequestProcessorTest.java   |   52 +
 .../rpc/impl/cli/SnapshotRequestProcessorTest.java |   49 +
 .../TransferLeadershipRequestProcessorTest.java    |   50 +
 .../core/AppendEntriesRequestProcessorTest.java    |  189 ++
 .../impl/core/BaseNodeRequestProcessorTest.java    |   86 +
 .../core/InstallSnapshotRequestProcessorTest.java  |   54 +
 .../rpc/impl/core/NodeRequestProcessorTest.java    |  123 +
 .../rpc/impl/core/PreVoteRequestProcessorTest.java |   53 +
 .../impl/core/ReadIndexRequestProcessorTest.java   |   50 +
 .../impl/core/RequestVoteRequestProcessorTest.java |   53 +
 .../impl/core/TimeoutNowRequestProcessorTest.java  |   50 +
 .../raft/jraft/storage/BaseStorageTest.java}       |   38 +-
 .../ignite/raft/jraft/storage/FileServiceTest.java |  164 +
 .../raft/jraft/storage/SnapshotExecutorTest.java   |  302 ++
 .../jraft/storage/impl/BaseLogStorageTest.java     |  242 ++
 .../jraft/storage/impl/LocalLogStorageTest.java}   |   13 +-
 .../storage/impl/LocalRaftMetaStorageTest.java     |   95 +
 .../raft/jraft/storage/impl/LogManagerTest.java    |  429 +++
 .../jraft/storage/impl/LogStorageBenchmark.java    |  142 +
 .../jraft/storage/impl/RocksDBLogManagerTest.java} |   12 +-
 .../jraft/storage/impl/RocksDBLogStorageTest.java} |   13 +-
 .../raft/jraft/storage/io/LocalFileReaderTest.java |  105 +
 .../raft/jraft/storage/io/MessageFileTest.java     |   49 +
 .../snapshot/ThroughputSnapshotThrottleTest.java   |   43 +
 .../snapshot/local/LocalSnapshotCopierTest.java    |  209 ++
 .../snapshot/local/LocalSnapshotMetaTableTest.java |  116 +
 .../snapshot/local/LocalSnapshotReaderTest.java    |   83 +
 .../snapshot/local/LocalSnapshotStorageTest.java   |   92 +
 .../snapshot/local/LocalSnapshotWriterTest.java    |   90 +
 .../snapshot/local/SnapshotFileReaderTest.java     |   90 +
 .../storage/snapshot/remote/CopySessionTest.java   |  181 +
 .../snapshot/remote/RemoteFileCopierTest.java      |   66 +
 .../ignite/raft/jraft/test/MockAsyncContext.java   |   57 +
 .../apache/ignite/raft/jraft/test/TestUtils.java   |  195 ++
 .../raft/jraft/util/AdaptiveBufAllocatorTest.java  |   75 +
 .../ignite/raft/jraft/util/ArrayDequeTest.java     |   73 +
 .../raft/jraft/util/AsciiCodecBenchmark.java       |   92 +
 .../raft/jraft/util/AsciiStringUtilTest.java}      |   34 +-
 .../apache/ignite/raft/jraft/util/BitsTest.java}   |   33 +-
 .../raft/jraft/util/ByteBufferCollectorTest.java   |   68 +
 .../ignite/raft/jraft/util/BytesUtilTest.java      |  124 +
 .../ignite/raft/jraft/util/CountDownEventTest.java |   83 +
 .../ignite/raft/jraft/util/CrcUtilTest.java}       |   36 +-
 .../ignite/raft/jraft/util/EndpointTest.java       |   47 +
 .../jraft/util/FileOutputSignalHandlerTest.java    |   61 +
 .../jraft/util/RecyclableByteBufferListTest.java   |   53 +
 .../ignite/raft/jraft/util/RecyclersTest.java      |  145 +
 .../ignite/raft/jraft/util/RepeatedTimerTest.java  |  135 +
 .../ignite/raft/jraft/util/SegmentListTest.java    |  299 ++
 .../ignite/raft/jraft/util/ThreadIdTest.java       |  107 +
 .../ignite/raft/jraft/util/Utf8CodecBenchmark.java |   98 +
 .../apache/ignite/raft/jraft/util/UtilsTest.java   |  202 ++
 .../util/concurrent/AdjustableSemaphoreTest.java   |   68 +
 .../LongHeldDetectingReadWriteLockTest.java        |  141 +
 .../concurrent/MpscSingleThreadExecutorTest.java   |  167 +
 .../concurrent/SingleThreadExecutorBenchmark.java  |  166 +
 .../ignite/distributed/ITDistributedTableTest.java |    4 +-
 parent/pom.xml                                     |   43 +-
 456 files changed, 63919 insertions(+), 1211 deletions(-)


[ignite-3] 11/15: WIP.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit cdb9015da5840fd641edc8ec43075c4ee11ac563
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Tue Jun 8 22:11:15 2021 +0300

    WIP.
---
 .../apache/ignite/internal/schema/BinaryRow.java   |  22 +-
 .../ignite/internal/schema/ByteBufferRow.java      |  10 +-
 .../ignite/internal/schema/row/ChunkFormat.java    | 375 +++++++++------------
 .../ignite/internal/schema/row/ChunkReader.java    |  48 ++-
 .../ignite/internal/schema/row/ChunkWriter.java    |  70 +++-
 .../internal/schema/row/LongChunkWriter.java       |  90 -----
 .../internal/schema/row/MeduimChunkWriter.java     |  97 ------
 .../org/apache/ignite/internal/schema/row/Row.java |  38 ++-
 .../ignite/internal/schema/row/RowAssembler.java   |  39 +--
 .../internal/schema/row/TinyChunkWriter.java       |  62 ----
 10 files changed, 295 insertions(+), 556 deletions(-)

diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
index 9f13385..1826684 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
@@ -145,24 +145,14 @@ public interface BinaryRow {
         /** Flag indicates row has no value chunk. */
         public static final int NO_VALUE_FLAG = 1;
 
-        /** Flag indicates key chunk omits null map. */
-        public static final int OMIT_KEY_NULL_MAP_FLAG = 1 << 1;
+        /** Chunk flags mask. */
+        public static final int CHUNK_FLAGS_MASK = 0x0F;
 
-        /** Flag indicates value chunk omits null map. */
-        public static final int OMIT_VAL_NULL_MAP_FLAG = 1 << 2;
+        /** Key specific flags. */
+        public static final int KEY_FLAGS_OFFSET = 8;
 
-        /** Flag indicates key chunk omits varlen table. */
-        public static final int OMIT_KEY_VARTBL_FLAG = 1 << 3;
-
-        /** Flag indicates value chunk omits varlen table. */
-        public static final int OMIT_VAL_VARTBL_FLAG = 1 << 4;
-
-        /** Flag indicates value chunk is written in Tiny format. */
-        public static final int VAL_TYNY_FORMAT = 1 << 6;
-
-        /** Flag indicates key chunk is written in Tiny format. */
-        public static final int KEY_FORMAT_MASK = (2 ^ 4 - 1) << 8;
-        public static final int VALUE_FORMAT_MASK = (2 ^ 4 - 1) << 12;
+        /** Value specific flags. */
+        public static final int VAL_FLAGS_OFFSET = 12;
 
         /** Stub. */
         private RowFlags() {
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
index 0f3b484..170028e 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
@@ -132,7 +132,7 @@ public class ByteBufferRow implements BinaryRow {
         final short flags = readShort(FLAGS_FIELD_OFFSET);
 
         final int off = KEY_CHUNK_OFFSET;
-        final int len = (flags & RowFlags.KEY_TYNY_FORMAT) == 0 ? readInteger(off) : (readByte(off) & 0xFF);
+        final int len = readInteger(off);
 
         try {
             return buf.limit(off + len).position(off).slice();
@@ -145,12 +145,8 @@ public class ByteBufferRow implements BinaryRow {
 
     /** {@inheritDoc} */
     @Override public ByteBuffer valueSlice() {
-        final short flags = readShort(FLAGS_FIELD_OFFSET);
-
-        int off = KEY_CHUNK_OFFSET +
-            ((flags & RowFlags.KEY_TYNY_FORMAT) == 0 ? readInteger(KEY_CHUNK_OFFSET) : (readByte(KEY_CHUNK_OFFSET) & 0xFF));
-
-        int len = hasValue() ? (flags & RowFlags.VAL_TYNY_FORMAT) == 0 ? readInteger(off) : (readByte(off) & 0xFF) : 0;
+        int off = KEY_CHUNK_OFFSET + readInteger(KEY_CHUNK_OFFSET);
+        int len = hasValue() ? readInteger(off) : 0;
 
         try {
             return buf.limit(off + len).position(off).slice();
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java
index d5e8d17..270420f 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java
@@ -23,267 +23,222 @@ import org.apache.ignite.internal.schema.BinaryRow;
  * Chunk writers factory.
  */
 abstract class ChunkFormat {
-    /** Writer factory for tiny-sized chunks. */
-    private static final ChunkFormat TINY = new TinyChunkFormat();
+    /** First 2 bits in chunk flags. */
+    public static final int FORMAT_CODE_MASK = 0x03;
 
-    /** Writer factory for med-sized chunks. */
-    private static final ChunkFormat MEDIUM = new MedChunkFormat();
+    /** Flag indicates key chunk omits varlen table. */
+    public static final int OMIT_NULL_MAP_FLAG = 1 << 2;
 
-    /** Writer factory for large-sized chunks. */
-    private static final ChunkFormat LARGE = new LargeChunkFormat();
+    /** Flag indicates value chunk omits null map. */
+    public static final int OMIT_VARTBL_FLAG = 1 << 3;
 
-    /**
-     * Check if chunk fits to max size.
-     *
-     * @param payloadLen Payload size in bytes.
-     * @param nullMapLen Null-map size in bytes.
-     * @param vartblSize Amount of vartable items.
-     * @return {@code true} if a chunk is tiny, {@code false} otherwise.
-     */
-    static ChunkFormat writeMode(int payloadLen, int nullMapLen, int vartblSize) {
-        if (TINY.chunkSize(payloadLen, nullMapLen, vartblSize) < 256)
-            return TINY;
-
-        if (MEDIUM.chunkSize(payloadLen, nullMapLen, vartblSize) < 64 * 1024)
-            return MEDIUM;
-
-        return LARGE;
-    }
+    /** Writer factory for tiny-sized chunks. */
+    private static final ChunkFormat TINY = new ChunkFormat(Byte.BYTES, Byte.BYTES, (byte)1) {
+        @Override void writeOffset(ExpandableByteBuf buf, int itemOff, int off) {
+            assert off < (1 << 8) && off >= 0 : "Varlen offset overflow: offset=" + off;
 
-    /**
-     * @param payloadLen Row payload length in bytes.
-     * @param nullMapLen Null-map length in bytes.
-     * @param vartblItems Number of vartable items.
-     * @return Chunk size.
-     */
-    abstract int chunkSize(int payloadLen, int nullMapLen, int vartblItems);
+            buf.put(itemOff, (byte)off);
+        }
 
-    /**
-     * Returns mode flags. First 4-bits are used.
-     *
-     * @return Chunk specific flags.
-     */
-    byte modeFlags() {
-        return 0;
-    }
+        @Override int readOffset(BinaryRow row, int itemOff) {
+            return row.readByte(itemOff) & 0xFF;
+        }
 
-    /**
-     * Calculates vartable length (in bytes).
-     *
-     * @param items Vartable items.
-     * @return Vartable size in bytes.
-     */
-    protected abstract int vartableLength(int items);
+        @Override void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size) {
+            assert size < (1 << 8) && size >= 0 : "Vartable size overflow: size=" + size;
 
-    /**
-     * Chunk writer factory method.
-     *
-     * @param buf Row buffer.
-     * @param baseOff Chunk base offset.
-     * @param nullMapLen Null-map length.
-     * @param vartblSize Vartable length.
-     * @return Chunk writer.
-     */
-    abstract ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize);
+            buf.put(vartblOff, (byte)vartblOff);
+        }
 
-    abstract ChunkReader reader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable);
+        @Override int readVartblSize(BinaryRow row, int vartblOff) {
+            return row.readByte(vartblOff) & 0xFF;
+        }
+    };
 
-    /**
-     * Writer factory for tiny-sized chunks.
-     */
-    private static class TinyChunkFormat extends ChunkFormat {
+    /** Writer factory for med-sized chunks. */
+    private static final ChunkFormat MEDIUM = new ChunkFormat(Short.BYTES, Short.BYTES, (byte)2) {
+        @Override void writeOffset(ExpandableByteBuf buf, int itemOff, int off) {
+            assert off < (1 << 16) && off >= 0 : "Varlen offset overflow: offset=" + off;
 
-        /** {@inheritDoc} */
-        @Override protected int vartableLength(int items) {
-            return items == 0 ? 0 : Byte.BYTES /* Table size */ + items * Byte.BYTES;
+            buf.putShort(itemOff, (short)off);
         }
 
-        /** {@inheritDoc} */
-        @Override int chunkSize(int payloadLen, int nullMapLen, int vartblItems) {
-            return Byte.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblItems) + payloadLen;
+        @Override int readOffset(BinaryRow row, int itemOff) {
+            return row.readShort(itemOff) & 0xFFFF;
         }
 
-        /** {@inheritDoc} */
-        @Override byte modeFlags() {
-            return 1;
-        }
+        @Override void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size) {
+            assert size < (1 << 16) && size >= 0 : "Vartable size overflow: size=" + size;
 
-        /** {@inheritDoc} */
-        @Override ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize) {
-            return new TinyChunkWriter(buf,
-                baseOff,
-                baseOff + Byte.BYTES /* Chunk size */,
-                baseOff + Byte.BYTES + nullMapLen,
-                baseOff + Byte.BYTES + nullMapLen + vartableLength(vartblSize));
+            buf.putShort(vartblOff, (short)vartblOff);
         }
 
-        /** {@inheritDoc} */
-        @Override ChunkReader reader(BinaryRow row,int baseOff, int nullMapLen, boolean hasVarTable) {
-            return new TinyChunkReader(row, baseOff,  nullMapLen, hasVarTable);
+        @Override int readVartblSize(BinaryRow row, int vartblOff) {
+            return row.readShort(vartblOff) & 0xFFFF;
         }
-    }
+    };
 
-    /**
-     * Writer factory for med-size chunks.
-     */
-    private static class MedChunkFormat extends ChunkFormat {
-        /** {@inheritDoc} */
-        @Override protected int vartableLength(int items) {
-            return items == 0 ? 0 : Short.BYTES /* Table size */ + items * Short.BYTES;
+    /** Writer factory for large-sized chunks. */
+    private static final ChunkFormat LARGE = new ChunkFormat(Short.BYTES, Integer.BYTES, (byte)0) {
+        @Override void writeOffset(ExpandableByteBuf buf, int itemOff, int off) {
+            buf.putInt(itemOff, off);
         }
 
-        /** {@inheritDoc} */
-        @Override int chunkSize(int payloadLen, int nullMapLen, int vartblItems) {
-            return Short.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblItems) + payloadLen;
+        @Override int readOffset(BinaryRow row, int itemOff) {
+            return row.readInteger(itemOff);
         }
 
-        /** {@inheritDoc} */
-        @Override byte modeFlags() {
-            return 2;
-        }
+        @Override void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size) {
+            assert size < (1 << 16) && size >= 0 : "Vartable size overflow: size=" + size;
 
-        /** {@inheritDoc} */
-        @Override ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize) {
-            return new MeduimChunkWriter(buf,
-                baseOff,
-                baseOff + Short.BYTES /* Chunk size */,
-                baseOff + Short.BYTES + nullMapLen,
-                baseOff + Short.BYTES + nullMapLen + vartableLength(vartblSize));
+            buf.putShort(vartblOff, (short)vartblOff);
         }
 
-        /** {@inheritDoc} */
-        @Override ChunkReader reader(BinaryRow row,int baseOff, int nullMapLen, boolean hasVarTable) {
-            return new MediumChunkReader(row, baseOff,  nullMapLen, hasVarTable);
+        @Override int readVartblSize(BinaryRow row, int vartblOff) {
+            return row.readShort(vartblOff) & 0xFFFF;
         }
-    }
+    };
+
+    /** Chunk length field size. */
+    public static final int CHUNK_LEN_FLD_SIZE = Integer.BYTES;
+
+    private final int vartableItemSize;
+
+    private final int vartableSizeFieldLen;
+
+    private final byte modeFlags;
 
     /**
-     * Writer factory for large-sized chunks.
+     * Return chunk formatter.
+     *
+     * @param payloadLen Payload size in bytes.
+     * @return Chunk formatter.
      */
-    private static class LargeChunkFormat extends ChunkFormat {
-        /** {@inheritDoc} */
-        @Override protected int vartableLength(int items) {
-            return items == 0 ? 0 : Integer.BYTES /* Table size */ + items * Integer.BYTES;
-        }
+    static ChunkFormat formatter(int payloadLen) {
+        if (payloadLen < 256)
+            return TINY;
 
-        /** {@inheritDoc} */
-        @Override int chunkSize(int payloadLen, int nullMapLen, int vartblItems) {
-            return Integer.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblItems) + payloadLen;
-        }
+        if (payloadLen < 64 * 1024)
+            return MEDIUM;
 
-        /** {@inheritDoc} */
-        @Override ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize) {
-            return new TinyChunkWriter(buf,
-                baseOff,
-                baseOff + Integer.BYTES /* Chunk size */,
-                baseOff + Integer.BYTES + nullMapLen,
-                baseOff + Integer.BYTES + nullMapLen + vartableLength(vartblSize));
-        }
-        /** {@inheritDoc} */
-        @Override ChunkReader reader(BinaryRow row,int baseOff, int nullMapLen, boolean hasVarTable) {
-            return new LargeChunkReader(row, baseOff,  nullMapLen, hasVarTable);
-        }
+        return LARGE;
     }
 
     /**
-     * Tiny chunk format reader.
+     * @param row Binary row.
+     * @param offset Offset.
+     * @param nullMapSize Default null-map size.
+     * @param chunkFlags Chunk flags.
+     * @return Reader.
      */
-    private static class TinyChunkReader extends ChunkReader {
-        /**
-         * @param row Row.
-         * @param baseOff Base offset.
-         * @param nullMapLen Null-map length in bytes.
-         * @param hasVarTable Vartable presence flag.
-         */
-        TinyChunkReader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable) {
-            super(row, baseOff);
-
-            nullMapOff = baseOff + Byte.BYTES;
-            varTableOff = nullMapOff + nullMapLen;
-            dataOff = varTableOff + (hasVarTable ? Byte.BYTES + (row.readByte(varTableOff) & 0xFF) * Byte.BYTES : 0);
-        }
-
-        /** {@inheritDoc} */
-        @Override int chunkLength() {
-            return row.readByte(baseOff) & 0xFF;
-        }
+    static ChunkReader createReader(BinaryRow row, int offset, int nullMapSize, byte chunkFlags) {
+        return fromFlags(chunkFlags).reader(row, offset,
+            (chunkFlags & OMIT_NULL_MAP_FLAG) == 0 ? nullMapSize : 0,
+            (chunkFlags & OMIT_VARTBL_FLAG) == 0);
+    }
 
-        /** {@inheritDoc} */
-        @Override int vartableItems() {
-            return hasVartable() ? (row.readByte(varTableOff) & 0xFF) : 0;
-        }
+    /**
+     * Chunk formatter from given flags.
+     *
+     * @param chunkFlags Chunk specific flags.
+     * @return Chunk formatter.
+     */
+    private static ChunkFormat fromFlags(byte chunkFlags) {
+        final int mode = chunkFlags & FORMAT_CODE_MASK;
 
-        /** {@inheritDoc} */
-        @Override protected int varlenItemOffset(int itemIdx) {
-            return dataOff + (row.readByte(varTableOff + Byte.BYTES + itemIdx * Byte.BYTES) & 0xFF);
+        switch (mode) {
+            case 1:
+                return TINY;
+            case 2:
+                return MEDIUM;
+            default:
+                return LARGE;
         }
     }
 
     /**
-     * Medium chunk format reader.
+     * @param vartableSizeFieldLen Vartalble size field length.
+     * @param vartableItemSize Vartable item size.
      */
-    private static class MediumChunkReader extends ChunkReader {
-        /**
-         * @param row Row.
-         * @param baseOff Base offset.
-         * @param nullMapLen Null-map length in bytes.
-         * @param hasVarTable Vartable presence flag.
-         */
-        MediumChunkReader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable) {
-            super(row, baseOff);
-
-            nullMapOff = baseOff + Short.BYTES;
-            varTableOff = nullMapOff + nullMapLen;
-            dataOff = varTableOff + (hasVarTable ? Short.BYTES + (row.readShort(varTableOff) & 0xFFFF) * Short.BYTES : 0);
-        }
+    public ChunkFormat(int vartableSizeFieldLen, int vartableItemSize, byte modeFlags) {
+        this.vartableItemSize = vartableItemSize;
+        this.vartableSizeFieldLen = vartableSizeFieldLen;
+        this.modeFlags = modeFlags;
+    }
 
-        /** {@inheritDoc} */
-        @Override int chunkLength() {
-            return row.readShort(baseOff) & 0xFF;
-        }
+    int vartableSizeFieldLen() {
+        return vartableSizeFieldLen;
+    }
 
-        /** {@inheritDoc} */
-        @Override int vartableItems() {
-            return hasVartable() ? (row.readShort(varTableOff) & 0xFFFF) : 0;
-        }
+    int vartableItemSize() {
+        return vartableItemSize;
+    }
 
-        /** {@inheritDoc} */
-        @Override protected int varlenItemOffset(int itemIdx) {
-            return dataOff + (row.readShort(varTableOff + Short.BYTES + itemIdx * Short.BYTES) & 0xFFFF);
-        }
+    public byte modeFlags() {
+        return modeFlags;
     }
 
     /**
-     * Large chunk format reader.
+     * @param payloadLen Row payload length in bytes.
+     * @param nullMapLen Null-map length in bytes.
+     * @param vartblItems Number of vartable items.
+     * @return Chunk size.
      */
-    private static class LargeChunkReader extends ChunkReader {
-        /**
-         * @param row Row.
-         * @param baseOff Base offset.
-         * @param nullMapLen Null-map length in bytes.
-         * @param hasVarTable Vartable presence flag.
-         */
-        LargeChunkReader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable) {
-            super(row, baseOff);
-
-            nullMapOff = baseOff + Integer.BYTES;
-            varTableOff = baseOff + Integer.BYTES + nullMapLen;
-            dataOff = varTableOff + (hasVarTable ? Integer.BYTES + row.readInteger(varTableOff) * Integer.BYTES : 0);
-        }
+    int chunkSize(int payloadLen, int nullMapLen, int vartblItems) {
+        return CHUNK_LEN_FLD_SIZE /* Chunk len. */ + nullMapLen + vartableLength(vartblItems) + payloadLen;
+    }
 
-        /** {@inheritDoc} */
-        @Override public int chunkLength() {
-            return row.readInteger(baseOff);
-        }
+    /**
+     * Calculates vartable length (in bytes).
+     *
+     * @param items Vartable items.
+     * @return Vartable size in bytes.
+     */
+    protected int vartableLength(int items) {
+        return items == 0 ? 0 : vartableSizeFieldLen /* Table size */ + items * vartableItemSize;
+    }
 
-        /** {@inheritDoc} */
-        @Override int vartableItems() {
-            return hasVartable() ? row.readInteger(varTableOff) : 0;
-        }
+    /**
+     * Calculates vartable item offset.
+     *
+     * @param idx Vartable item idx.
+     * @return Vartable item offset.
+     */
+    int vartblItemOff(int idx) {
+        return vartableSizeFieldLen /* Table size */ + idx * vartableItemSize;
+    }
 
-        /** {@inheritDoc} */
-        @Override protected int varlenItemOffset(int itemIdx) {
-            return dataOff + row.readInteger(varTableOff + Integer.BYTES + itemIdx * Integer.BYTES);
-        }
+    abstract void writeOffset(ExpandableByteBuf buf, int vartblItemOff, int off);
+
+    abstract int readOffset(BinaryRow row, int vartblOff);
+
+    abstract void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size);
+
+    abstract int readVartblSize(BinaryRow row, int vartblOff);
+
+    /**
+     * Chunk writer factory method.
+     *
+     * @param buf Row buffer.
+     * @param baseOff Chunk base offset.
+     * @param nullMapLen Null-map length.
+     * @param vartblItems Vartable items.
+     * @return Chunk writer.
+     */
+    ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblItems) {
+        return new ChunkWriter(buf, baseOff, nullMapLen, vartblItems, this);
+    }
+
+    /**
+     * Chunk reader factory method.
+     *
+     * @param row Row buffer.
+     * @param baseOff Chunk base offset.
+     * @param nullMapLen Null-map length.
+     * @param hasVarTable Has vartable flag.
+     * @return Chunk reader.
+     */
+    ChunkReader reader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable) {
+        return new ChunkReader(row, baseOff, nullMapLen, hasVarTable, this);
     }
-}
+}
\ No newline at end of file
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
index fd02415..30e4db9 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
@@ -23,15 +23,15 @@ import org.apache.ignite.internal.schema.Columns;
 /**
  * Abstract chunk reader.
  */
-abstract class ChunkReader {
+class ChunkReader {
     /** Row. */
     protected final BinaryRow row;
 
     /** Base offset. */
     protected final int baseOff;
 
-    /** Null-map offset. */
-    protected int nullMapOff;
+    /** Chunk format. */
+    private final ChunkFormat format;
 
     /** Vartable offset. */
     protected int varTableOff;
@@ -40,22 +40,34 @@ abstract class ChunkReader {
     protected int dataOff;
 
     /**
-     * @param baseOff Chunk base offset.
+     * @param row
+     * @param baseOff
+     * @param nullMapLen
+     * @param hasVarTable
+     * @param format
      */
-    ChunkReader(BinaryRow row, int baseOff) {
+    ChunkReader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable, ChunkFormat format) {
         this.row = row;
         this.baseOff = baseOff;
+        this.format = format;
+        varTableOff = nullmapOff() + nullMapLen;
+        dataOff = varTableOff + (hasVarTable ? format.vartableLength(format.readVartblSize(row, varTableOff)) : 0);
     }
 
     /**
      * @return Chunk length in bytes
      */
-    abstract int chunkLength();
+    /** {@inheritDoc} */
+    int chunkLength() {
+        return row.readInteger(baseOff);
+    }
 
     /**
      * @return Number of items in vartable.
      */
-    abstract int vartableItems();
+    int vartableItems() {
+       return format.readVartblSize(row, varTableOff);
+    }
 
     /**
      * Checks the row's null map for the given column index in the chunk.
@@ -71,11 +83,15 @@ abstract class ChunkReader {
         int nullByte = idx / 8;
         int posInByte = idx % 8;
 
-        int map = row.readByte(nullMapOff + nullByte);
+        int map = row.readByte(nullmapOff() + nullByte);
 
         return (map & (1 << posInByte)) != 0;
     }
 
+    private int nullmapOff() {
+        return baseOff + Integer.BYTES;
+    }
+
     /**
      * @return {@code True} if chunk has vartable.
      */
@@ -87,14 +103,20 @@ abstract class ChunkReader {
      * @return {@code True} if chunk has nullmap.
      */
     protected boolean hasNullmap() {
-        return varTableOff > nullMapOff;
+        return varTableOff > nullmapOff();
     }
 
     /**
      * @param itemIdx Varlen table item index.
      * @return Varlen item offset.
      */
-    protected abstract int varlenItemOffset(int itemIdx);
+    protected int varlenItemOffset(int itemIdx) {
+        assert hasVartable() : "Vartable is ommited.";
+
+        final int off = format.vartblItemOff(itemIdx);
+
+        return format.readOffset(row, off);
+    }
 
     /**
      * Calculates the offset of the fixlen column with the given index in the row. It essentially folds the null map
@@ -119,9 +141,9 @@ abstract class ChunkReader {
             if (hasNullmap()) {
                 // Fold offset based on the whole map bytes in the schema
                 for (int i = 0; i < colByteIdx; i++)
-                    colOff += cols.foldFixedLength(i, row.readByte(nullMapOff + i));
+                    colOff += cols.foldFixedLength(i, row.readByte(nullmapOff() + i));
 
-                colOff += cols.foldFixedLength(colByteIdx, row.readByte(nullMapOff + colByteIdx) | mask);
+                colOff += cols.foldFixedLength(colByteIdx, row.readByte(nullmapOff() + colByteIdx) | mask);
             }
             else {
                 for (int i = 0; i < colByteIdx; i++)
@@ -158,7 +180,7 @@ abstract class ChunkReader {
             int numNullsBefore = 0;
 
             for (int i = nullStartByte; i <= nullEndByte; i++) {
-                byte nullmapByte = row.readByte(nullMapOff + i);
+                byte nullmapByte = row.readByte(nullmapOff() + i);
 
                 if (i == nullStartByte)
                     // We need to clear startBitInByte least significant bits
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
index cb49e72..dc65302 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
@@ -27,16 +27,13 @@ import org.apache.ignite.internal.schema.NativeTypes;
 /**
  * Abstract row chunk writer.
  */
-abstract class ChunkWriter {
+class ChunkWriter {
     /** Chunk buffer. */
     protected final ExpandableByteBuf buf;
 
     /** Base offset of the chunk */
     protected final int baseOff;
 
-    /** Offset of the null map for the chunk. */
-    protected final int nullMapOff;
-
     /** Offset of the varlen table for the chunk. */
     protected final int varTblOff;
 
@@ -49,20 +46,34 @@ abstract class ChunkWriter {
     /** Current offset for the next column to be appended. */
     protected int curOff;
 
+    /** Chunk flags. */
+    private byte flags;
+
+    /** Chunk format. */
+    ChunkFormat format;
+
     /**
      * @param buf Row buffer.
      * @param baseOff Chunk base offset.
-     * @param nullMapOff Null-map offset.
-     * @param varTblOff Vartable offset.
+     * @param nullMapLen Null-map length in bytes.
+     * @param vartblItems Vartable length in bytes.
      */
-    protected ChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapOff, int varTblOff, int dataOff) {
+    protected ChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblItems, ChunkFormat format) {
         this.buf = buf;
         this.baseOff = baseOff;
-        this.nullMapOff = nullMapOff;
-        this.varTblOff = varTblOff;
-        this.dataOff = dataOff;
+        this.format = format;
+        this.flags = format.modeFlags();
+
+        varTblOff = nullmapOff() + nullMapLen;
+        dataOff = varTblOff + format.vartableLength(vartblItems);
         curOff = dataOff;
         curVartblItem = 0;
+
+        if (nullmapOff() == baseOff)
+            this.flags |= ChunkFormat.OMIT_NULL_MAP_FLAG;
+
+        if (dataOff == varTblOff)
+            this.flags |= ChunkFormat.OMIT_VARTBL_FLAG;
     }
 
     /**
@@ -149,6 +160,9 @@ abstract class ChunkWriter {
      * @param val Column value.
      */
     public void appendString(String val, CharsetEncoder encoder) {
+        assert (flags & ChunkFormat.OMIT_VARTBL_FLAG) == 0 :
+            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
+
         try {
             int written = buf.putString(curOff, val, encoder);
 
@@ -168,6 +182,9 @@ abstract class ChunkWriter {
      * @param val Column value.
      */
     public void appendBytes(byte[] val) {
+        assert (flags & ChunkFormat.OMIT_VARTBL_FLAG) == 0 :
+            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
+
         buf.putBytes(curOff, val);
 
         writeOffset(curVartblItem, curOff - dataOff);
@@ -202,15 +219,28 @@ abstract class ChunkWriter {
     /**
      * Post-write action.
      */
-    abstract void flush();
+    void flush() {
+        final int size = chunkLength();
+
+        buf.putInt(baseOff, size);
+
+        if (curVartblItem > 0)
+            format.writeVartblSize(buf, varTblOff, curVartblItem);
+    }
 
     /**
      * Writes the given offset to the varlen table entry with the given index.
      *
-     * @param tblEntryIdx Varlen table entry index.
+     * @param tblItemIdx Varlen table entry index.
      * @param off Offset to write.
      */
-    protected abstract void writeOffset(int tblEntryIdx, int off);
+    protected void writeOffset(int tblItemIdx, int off) {
+        final int itemOff = varTblOff + format.vartblItemOff(tblItemIdx);
+
+        assert itemOff < dataOff : "Vartable overflow: size=" + itemOff;
+
+        format.writeOffset(buf, itemOff, off);
+    }
 
     /**
      * Sets null flag in the null map for the given column.
@@ -218,13 +248,21 @@ abstract class ChunkWriter {
      * @param colIdx Column index.
      */
     protected void setNull(int colIdx) {
-        assert nullMapOff < varTblOff : "Null map is omitted.";
+        assert (flags & ChunkFormat.OMIT_NULL_MAP_FLAG) == 0 : "Null map is omitted.";
 
         int byteInMap = colIdx / 8;
         int bitInByte = colIdx % 8;
 
-        buf.ensureCapacity(nullMapOff + byteInMap + 1);
+        buf.ensureCapacity(nullmapOff() + byteInMap + 1);
+
+        buf.put(nullmapOff() + byteInMap, (byte)(buf.get(nullmapOff() + byteInMap) | (1 << bitInByte)));
+    }
+
+    private int nullmapOff() {
+        return baseOff + Integer.BYTES;
+    }
 
-        buf.put(nullMapOff + byteInMap, (byte)(buf.get(nullMapOff + byteInMap) | (1 << bitInByte)));
+    public short flags() {
+        return flags;
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/LongChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/LongChunkWriter.java
deleted file mode 100644
index a7e94a2..0000000
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/LongChunkWriter.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.schema.row;
-
-/**
- * Row chunk writer for long key/value chunks.
- *
- * Uses {@code int} values for coding sizes/offsets,
- * supports chunks with payload up to 2 GiB.
- */
-class LongChunkWriter extends ChunkWriter {
-    /**
-     * Calculates vartable length (in bytes).
-     *
-     * @param items Vartable items.
-     * @return Vartable size in bytes.
-     */
-    static int vartableLength(int items) {
-        return items == 0 ? 0 : Integer.BYTES /* Table size */ + items * Integer.BYTES;
-    }
-
-    /**
-     * Calculates chunk size.
-     *
-     * @param payloadLen Payload size in bytes.
-     * @param nullMapLen Null-map size in bytes.
-     * @param vartblSize Amount of vartable items.
-     * @return Bytes required to write a chunk or {@code -1} if a chunk is too long.
-     */
-    static int chunkSize(int payloadLen, int nullMapLen, int vartblSize) {
-        return Integer.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblSize) + payloadLen;
-    }
-
-    /**
-     * Creates chunk writer for long chunk format.
-     *
-     * @param buf Row buffer.
-     * @param baseOff Chunk base offset.
-     * @param nullMapLen Null-map size in bytes.
-     * @param vartblSize Amount of vartable items.
-     */
-    LongChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize) {
-        super(
-            buf,
-            baseOff,
-            baseOff + Integer.BYTES /* Chunk size */,
-            baseOff + Integer.BYTES /* Chunk size */ + nullMapLen,
-            baseOff + Integer.BYTES /* Chunk size */ + nullMapLen + vartableLength(vartblSize));
-
-        curVartblItem = 0;
-    }
-
-    /** {@inheritDoc} */
-    @Override void flush() {
-        final int size = chunkLength();
-
-        assert size > 0 : "Size field value overflow: " + size;
-        assert varTblOff + vartableLength(curVartblItem) == dataOff : "Vartable underflowed.";
-
-        buf.putInt(baseOff, size);
-
-        if (curVartblItem > 0)
-            buf.putInt(varTblOff, curVartblItem);
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void writeOffset(int tblEntryIdx, int off) {
-        final int itemOff = varTblOff + Integer.BYTES + tblEntryIdx * Integer.BYTES;
-
-        assert off >= 0 : "Varlen offset overflow: offset=" + off;
-        assert itemOff < dataOff : "Vartable overflow: size=" + itemOff;
-
-        buf.putInt(itemOff, off);
-    }
-}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/MeduimChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/MeduimChunkWriter.java
deleted file mode 100644
index 172dae1..0000000
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/MeduimChunkWriter.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.schema.row;
-
-/**
- * Row chunk writer for small key/value chunks.
- *
- * Uses {@code byte} values for coding sizes/offsets,
- * supports chunks with payload less upt to 255 bytes.
- */
-class MeduimChunkWriter extends ChunkWriter {
-    /**
-     * Calculates vartable length (in bytes).
-     *
-     * @param items Vartable items.
-     * @return Vartable size in bytes.
-     */
-    static int vartableLength(int items) {
-        return items == 0 ? 0 : Short.BYTES /* Table size */ + items * Short.BYTES;
-    }
-
-    /**
-     * Calculates chunk size.
-     *
-     * @param payloadLen Payload size in bytes.
-     * @param nullMapLen Null-map size in bytes.
-     * @param vartblSize Amount of vartable items.
-     * @return Bytes required to write a chunk or {@code -1} if a chunk is too long.
-     */
-    static int chunkSize(int payloadLen, int nullMapLen, int vartblSize) {
-        return Short.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblSize) + payloadLen;
-    }
-
-    /**
-     * Check if chunk fits to max size.
-     *
-     * @param payloadLen Payload size in bytes.
-     * @param nullMapLen Null-map size in bytes.
-     * @param vartblSize Amount of vartable items.
-     * @return {@code true} if a chunk is tiny, {@code false} otherwise.
-     */
-    static boolean isMediumChunk(int payloadLen, int nullMapLen, int vartblSize) {
-        return chunkSize(payloadLen, nullMapLen, vartblSize) < 64 * 1024;
-    }
-
-    /**
-     * Creates chunk writer to write chunk in tiny format.
-     *
-     * @param buf Row buffer.
-     * @param baseOff Chunk base offset.
-     * @param nullMapLen Null-map size in bytes.
-     * @param vartblSize Amount of vartable items.
-     */
-    MeduimChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapOff, int varTblOff, int dataOff) {
-        super(buf,baseOff, nullMapOff, varTblOff, dataOff);
-
-
-        curVartblItem = 0;
-    }
-
-    /** {@inheritDoc} */
-    @Override void flush() {
-        final int size = chunkLength();
-
-        assert size < (2 << 16) && size > 0 : "Size field value overflow: " + size;
-
-        buf.putShort(baseOff, (short)size);
-
-        if (curVartblItem > 0)
-            buf.putShort(varTblOff, (short)curVartblItem);
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void writeOffset(int tblEntryIdx, int off) {
-        final int itemOff = varTblOff + Short.BYTES + tblEntryIdx * Short.BYTES;
-
-        assert off < (2 << 8) && off >= 0 : "Varlen offset overflow: offset=" + off;
-        assert itemOff < dataOff : "Vartable overflow: size=" + itemOff;
-
-        buf.putShort(itemOff, (short)off);
-    }
-}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
index ce80945..c3dd7f7 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
@@ -29,7 +29,6 @@ import org.apache.ignite.internal.schema.Columns;
 import org.apache.ignite.internal.schema.InvalidTypeException;
 import org.apache.ignite.internal.schema.NativeTypeSpec;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
-import org.jetbrains.annotations.NotNull;
 
 /**
  * Schema-aware row.
@@ -49,7 +48,7 @@ public class Row implements BinaryRow {
     private final ChunkReader keyReader;
 
     /** Value reader. */
-    private final ChunkReader valReader;
+    private ChunkReader valReader;
 
     /**
      * Constructor.
@@ -65,21 +64,13 @@ public class Row implements BinaryRow {
 
         final short flags = readShort(FLAGS_FIELD_OFFSET);
 
-        keyReader = createReader(KEY_CHUNK_OFFSET,
-            (flags & RowFlags.KEY_TYNY_FORMAT) != 0,
-            (flags & RowFlags.OMIT_KEY_NULL_MAP_FLAG) == 0 ? schema.keyColumns().nullMapSize() : 0,
-            (flags & RowFlags.OMIT_KEY_VARTBL_FLAG) == 0);
-
-        valReader = ((flags & RowFlags.NO_VALUE_FLAG) == 0) ?
-            createReader(
-                KEY_CHUNK_OFFSET + keyReader.chunkLength(),
-                (flags & RowFlags.VAL_TYNY_FORMAT) != 0,
-                (flags & RowFlags.OMIT_VAL_NULL_MAP_FLAG) == 0 ? schema.valueColumns().nullMapSize() : 0,
-                (flags & RowFlags.OMIT_VAL_VARTBL_FLAG) == 0) :
-            null;
+        keyReader = ChunkFormat.createReader(
+            this,
+            KEY_CHUNK_OFFSET,
+            schema.keyColumns().nullMapSize(),
+            (byte)((flags >>> RowFlags.KEY_FLAGS_OFFSET) & RowFlags.CHUNK_FLAGS_MASK));
     }
 
-
     /**
      * @return Row schema.
      */
@@ -370,7 +361,7 @@ public class Row implements BinaryRow {
         if (!isKeyCol)
             colIdx -= schema.keyColumns().length();
 
-        ChunkReader reader = isKeyCol ? keyReader : valReader;
+        ChunkReader reader = isKeyCol ? keyReader : valueReader();
         Columns cols = isKeyCol ? schema.keyColumns() : schema.valueColumns();
 
         if (cols.column(colIdx).type().spec() != type)
@@ -389,6 +380,21 @@ public class Row implements BinaryRow {
             reader.varlenColumnOffsetAndLength(cols, colIdx);
     }
 
+    private ChunkReader valueReader() {
+        if (valReader != null)
+            return valReader;
+
+        final short flags = readShort(FLAGS_FIELD_OFFSET);
+
+        assert (flags & RowFlags.NO_VALUE_FLAG) == 0 : "Row has no value.";
+
+        return (valReader = ChunkFormat.createReader(
+            this,
+            KEY_CHUNK_OFFSET + keyReader.chunkLength(),
+            schema.keyColumns().nullMapSize(),
+            (byte)(flags >>> RowFlags.VAL_FLAGS_OFFSET)));
+    }
+
     /**
      * @param colIdx Column index.
      * @return Column length.
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
index 0d43da4..c245d9f 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
@@ -35,8 +35,8 @@ import org.apache.ignite.internal.schema.SchemaDescriptor;
 
 import static org.apache.ignite.internal.schema.BinaryRow.KEY_CHUNK_OFFSET;
 import static org.apache.ignite.internal.schema.BinaryRow.KEY_HASH_FIELD_OFFSET;
-import static org.apache.ignite.internal.schema.BinaryRow.RowFlags.OMIT_KEY_VARTBL_FLAG;
-import static org.apache.ignite.internal.schema.BinaryRow.RowFlags.OMIT_VAL_VARTBL_FLAG;
+import static org.apache.ignite.internal.schema.BinaryRow.RowFlags.KEY_FLAGS_OFFSET;
+import static org.apache.ignite.internal.schema.BinaryRow.RowFlags.VAL_FLAGS_OFFSET;
 
 /**
  * Utility class to build rows using column appending pattern. The external user of this class must consult
@@ -189,16 +189,8 @@ public class RowAssembler {
         final int keyNullMapSize = keyHasNulls ? schema.keyColumns().nullMapSize() : 0;
         final int valNullMapSize = valHasNulls ? schema.valueColumns().nullMapSize() : 0;
 
-        final ChunkFormat keyWriteMode = ChunkFormat.writeMode(keyDataSize, keyNullMapSize, keyVarlenCols);
-        valWriteMode = ChunkFormat.writeMode(valDataSize, keyNullMapSize, valVarlenCols);
-
-        // Key flags.
-        if (schema.keyColumns().nullMapSize() == 0)
-            flags |= RowFlags.OMIT_KEY_NULL_MAP_FLAG;
-        if (keyVarlenCols == 0)
-            flags |= OMIT_KEY_VARTBL_FLAG;
-
-        flags |= keyWriteMode.modeFlags() & 0x0F << 8;
+        final ChunkFormat keyWriteMode = ChunkFormat.formatter(keyDataSize);
+        valWriteMode = ChunkFormat.formatter(valDataSize);
 
         int size = BinaryRow.HEADER_SIZE +
             keyWriteMode.chunkSize(keyDataSize, keyNullMapSize, keyDataSize) +
@@ -348,9 +340,6 @@ public class RowAssembler {
     public void appendString(String val) {
         checkType(NativeTypes.STRING);
 
-        assert (flags & (schema.keyColumns() == curCols ? OMIT_KEY_VARTBL_FLAG : OMIT_VAL_VARTBL_FLAG)) == 0 :
-            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
-
         if (isKeyColumn())
             hash = 31 * hash + val.hashCode();
 
@@ -367,9 +356,6 @@ public class RowAssembler {
     public void appendBytes(byte[] val) {
         checkType(NativeTypes.BYTES);
 
-        assert (flags & (schema.keyColumns() == curCols ? OMIT_KEY_VARTBL_FLAG : OMIT_VAL_VARTBL_FLAG)) == 0 :
-            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
-
         if (isKeyColumn())
             hash = 31 * hash + Arrays.hashCode(val);
 
@@ -421,7 +407,7 @@ public class RowAssembler {
         return buf.toArray();
     }
 
-    private boolean isKeyColumn () {
+    private boolean isKeyColumn() {
         return curCols == schema.keyColumns();
     }
 
@@ -468,22 +454,17 @@ public class RowAssembler {
             // Write sizes.
             chunkWriter.flush();
 
-            if (schema.valueColumns() == curCols)
+            if (schema.valueColumns() == curCols) {
+                flags |= (chunkWriter.flags() & 0x0F) << VAL_FLAGS_OFFSET;
+
                 return; // No more columns.
+            }
 
             // Switch key->value columns.
             curCols = schema.valueColumns();
             curCol = 0;
 
-            // Write value flags.
-            if (valVarlenCols == 0)
-                flags |= OMIT_VAL_VARTBL_FLAG;
-            else {
-                if (schema.valueColumns().nullMapSize() == 0)
-                    flags |= RowFlags.OMIT_VAL_NULL_MAP_FLAG;
-
-                flags |= valWriteMode.modeFlags() & 0x0F << 14;
-            }
+            flags |= (chunkWriter.flags() & 0x0F) << KEY_FLAGS_OFFSET;
 
             // Create value chunk writer.
             chunkWriter = valWriteMode.writer(buf,
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
deleted file mode 100644
index 25392a9..0000000
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.schema.row;
-
-/**
- * Row chunk writer for small key/value chunks.
- * <p>
- * Uses {@code byte} values for coding sizes/offsets,
- * supports chunks with payload less upt to 255 bytes.
- */
-class TinyChunkWriter extends ChunkWriter {
-    /**
-     * Creates chunk writer to write chunk in tiny format.
-     *
-     * @param buf Row buffer.
-     * @param baseOff Chunk base offset.
-     * @param nullMapOff Null-map offset.
-     * @param varTblOff Vartable offset.
-     */
-    TinyChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapOff, int varTblOff, int dataOff) {
-        super(buf,baseOff, nullMapOff, varTblOff, dataOff);
-
-        curVartblItem = 0;
-    }
-
-    /** {@inheritDoc} */
-    @Override void flush() {
-        final int size = chunkLength();
-
-        assert size < (2 << 8) && size > 0 : "Size field value overflow: " + size;
-
-        buf.put(baseOff, (byte)size);
-
-        if (curVartblItem > 0)
-            buf.put(varTblOff, (byte)curVartblItem);
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void writeOffset(int tblEntryIdx, int off) {
-        final int itemOff = varTblOff + Byte.BYTES + tblEntryIdx * Byte.BYTES;
-
-        assert off < (2 << 8) && off >= 0 : "Varlen offset overflow: offset=" + off;
-        assert itemOff < dataOff : "Vartable overflow: size=" + itemOff;
-
-        buf.put(itemOff, (byte)off);
-    }
-}

[ignite-3] 15/15: WIP. Styles.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit e5d6b43683d0ccc87543467aca7e0ce6e6c909bf
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Wed Jun 9 14:18:40 2021 +0300

    WIP. Styles.
---
 .../apache/ignite/internal/schema/BinaryRow.java   |  22 +-
 .../ignite/internal/schema/ByteBufferRow.java      |   2 -
 .../org/apache/ignite/internal/schema/Columns.java |   3 +
 .../asm/IdentityMarshallerCodeGenerator.java       |   2 +-
 .../asm/ObjectMarshallerCodeGenerator.java         |   2 +-
 .../marshaller/reflection/JavaSerializer.java      |  10 +-
 .../ignite/internal/schema/row/ChunkFormat.java    | 231 ++++---
 .../ignite/internal/schema/row/ChunkReader.java    | 128 ++--
 .../ignite/internal/schema/row/ChunkWriter.java    |  87 +--
 .../internal/schema/row/ExpandableByteBuf.java     |   6 +-
 .../org/apache/ignite/internal/schema/row/Row.java |  12 +-
 .../ignite/internal/schema/row/RowAssembler.java   |  75 ++-
 .../schema/RowAssemblerAdvancedSchemaTest.java     | 118 ++--
 .../schema/RowAssemblerSimpleSchemaTest.java       | 218 +++---
 .../ignite/internal/schema/RowAssemblerTest.java   | 738 ---------------------
 .../org/apache/ignite/internal/schema/RowTest.java |  26 +-
 .../ignite/internal/table/TupleMarshallerImpl.java |  10 +-
 17 files changed, 538 insertions(+), 1152 deletions(-)

diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
index 1826684..8619449 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
@@ -26,30 +26,21 @@ import java.nio.ByteBuffer;
  * The class contains low-level methods to read row data.
  */
 public interface BinaryRow {
-    /** */
+    /** Row schema version field offset. */
     int SCHEMA_VERSION_OFFSET = 0;
 
-    /** */
+    /** Row flags field offset. */
     int FLAGS_FIELD_OFFSET = SCHEMA_VERSION_OFFSET + 2 /* version length */;
 
-    /** */
+    /** Key hash field offset. */
     int KEY_HASH_FIELD_OFFSET = FLAGS_FIELD_OFFSET + 2 /* flags length */;
 
-    /** */
+    /** Key chunk field offset. */
     int KEY_CHUNK_OFFSET = KEY_HASH_FIELD_OFFSET + 4 /* hash length */;
 
-    /** */
+    /** Row header size. */
     int HEADER_SIZE = KEY_CHUNK_OFFSET;
 
-    /** */
-    int CHUNK_LEN_FIELD_SIZE = 4;
-
-    /** */
-    int VARLEN_TABLE_SIZE_FIELD_SIZE = 2;
-
-    /** */
-    int VARLEN_COLUMN_OFFSET_FIELD_SIZE = 2;
-
     /**
      * @return Row schema version.
      */
@@ -60,9 +51,6 @@ public interface BinaryRow {
      */
     boolean hasValue();
 
-    // TODO: IGNITE-14199. Add row version.
-    //GridRowVersion version();
-
     /**
      * Row hash code is a result of hash function applied to the row affinity columns values.
      *
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
index 170028e..6ae8889 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
@@ -129,8 +129,6 @@ public class ByteBufferRow implements BinaryRow {
 
     /** {@inheritDoc} */
     @Override public ByteBuffer keySlice() {
-        final short flags = readShort(FLAGS_FIELD_OFFSET);
-
         final int off = KEY_CHUNK_OFFSET;
         final int len = readInteger(off);
 
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java
index 72ca1ae..d5259bc 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java
@@ -188,6 +188,9 @@ public class Columns implements Serializable {
         return firstVarlenColIdx != -1;
     }
 
+    /**
+     * @return Fixsize columns size upper bound.
+     */
     public int fixsizeMaxLen() {
         return fixsizeMaxLen;
     }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/IdentityMarshallerCodeGenerator.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/IdentityMarshallerCodeGenerator.java
index 3e7f05d..991c4fb 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/IdentityMarshallerCodeGenerator.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/IdentityMarshallerCodeGenerator.java
@@ -21,7 +21,7 @@ import com.facebook.presto.bytecode.BytecodeNode;
 import com.facebook.presto.bytecode.ParameterizedType;
 import com.facebook.presto.bytecode.Variable;
 import com.facebook.presto.bytecode.expression.BytecodeExpressions;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.schema.marshaller.Serializer;
 
 /**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/ObjectMarshallerCodeGenerator.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/ObjectMarshallerCodeGenerator.java
index 8f47eda..fe55ca0 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/ObjectMarshallerCodeGenerator.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/ObjectMarshallerCodeGenerator.java
@@ -34,7 +34,7 @@ import java.lang.reflect.Field;
 import java.util.Collections;
 import java.util.EnumSet;
 import org.apache.ignite.internal.schema.Columns;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.schema.marshaller.MarshallerUtil;
 import org.apache.ignite.internal.schema.marshaller.Serializer;
 import org.apache.ignite.lang.IgniteInternalException;
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
index 9e98d30..57b5bdd 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
@@ -85,7 +85,7 @@ public class JavaSerializer extends AbstractSerializer {
         ObjectStatistic keyStat = collectObjectStats(schema.keyColumns(), keyMarsh, key);
         ObjectStatistic valStat = collectObjectStats(schema.valueColumns(), valMarsh, val);
 
-        return new RowAssembler(schema, keyStat.nonNullCols, valStat.nonNullCols);
+        return new RowAssembler(schema, keyStat.maxChunkDataSize, keyStat.nonNullCols, valStat.maxChunkDataSize, valStat.nonNullCols);
     }
 
     /**
@@ -101,7 +101,7 @@ public class JavaSerializer extends AbstractSerializer {
             return new ObjectStatistic(0, 0);
 
         int cnt = 0;
-        int size = 0;
+        int size = cols.fixsizeMaxLen();
 
         for (int i = cols.firstVarlengthColumn(); i < cols.length(); i++) {
             final Object val = marsh.value(obj, i);
@@ -142,12 +142,12 @@ public class JavaSerializer extends AbstractSerializer {
         int nonNullCols;
 
         /** Length of all non-null columns of varlen types. */
-        int nonNullColsSize;
+        int maxChunkDataSize;
 
         /** Constructor. */
-        ObjectStatistic(int nonNullCols, int nonNullColsSize) {
+        ObjectStatistic(int nonNullCols, int maxRowSize) {
             this.nonNullCols = nonNullCols;
-            this.nonNullColsSize = nonNullColsSize;
+            this.maxChunkDataSize = maxRowSize;
         }
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java
index 270420f..ba2588c 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java
@@ -20,13 +20,13 @@ package org.apache.ignite.internal.schema.row;
 import org.apache.ignite.internal.schema.BinaryRow;
 
 /**
- * Chunk writers factory.
+ * Chunk format.
  */
 abstract class ChunkFormat {
-    /** First 2 bits in chunk flags. */
+    /** First two flag bits reserved for format code. */
     public static final int FORMAT_CODE_MASK = 0x03;
 
-    /** Flag indicates key chunk omits varlen table. */
+    /** Flag indicates key chunk omits vartable. */
     public static final int OMIT_NULL_MAP_FLAG = 1 << 2;
 
     /** Flag indicates value chunk omits null map. */
@@ -34,80 +34,83 @@ abstract class ChunkFormat {
 
     /** Writer factory for tiny-sized chunks. */
     private static final ChunkFormat TINY = new ChunkFormat(Byte.BYTES, Byte.BYTES, (byte)1) {
-        @Override void writeOffset(ExpandableByteBuf buf, int itemOff, int off) {
+        /** {@inheritDoc} */
+        @Override void writeVarlenOffset(ExpandableByteBuf buf, int vartblOff, int entryIdx, int off) {
             assert off < (1 << 8) && off >= 0 : "Varlen offset overflow: offset=" + off;
 
-            buf.put(itemOff, (byte)off);
+            buf.put(vartblOff + vartableEntryOffset(entryIdx), (byte)off);
         }
 
-        @Override int readOffset(BinaryRow row, int itemOff) {
-            return row.readByte(itemOff) & 0xFF;
+        /** {@inheritDoc} */
+        @Override int readVarlenOffset(BinaryRow row, int vartblOff, int entryIdx) {
+            return row.readByte(vartblOff + vartableEntryOffset(entryIdx)) & 0xFF;
         }
 
-        @Override void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size) {
+        /** {@inheritDoc} */
+        @Override void writeVartableSize(ExpandableByteBuf buf, int vartblOff, int size) {
             assert size < (1 << 8) && size >= 0 : "Vartable size overflow: size=" + size;
 
-            buf.put(vartblOff, (byte)vartblOff);
+            buf.put(vartblOff, (byte)size);
         }
 
-        @Override int readVartblSize(BinaryRow row, int vartblOff) {
+        /** {@inheritDoc} */
+        @Override int readVartableSize(BinaryRow row, int vartblOff) {
             return row.readByte(vartblOff) & 0xFF;
         }
     };
 
     /** Writer factory for med-sized chunks. */
     private static final ChunkFormat MEDIUM = new ChunkFormat(Short.BYTES, Short.BYTES, (byte)2) {
-        @Override void writeOffset(ExpandableByteBuf buf, int itemOff, int off) {
+        /** {@inheritDoc} */
+        @Override void writeVarlenOffset(ExpandableByteBuf buf, int vartblOff, int entryIdx, int off) {
             assert off < (1 << 16) && off >= 0 : "Varlen offset overflow: offset=" + off;
 
-            buf.putShort(itemOff, (short)off);
+            buf.putShort(vartblOff + vartableEntryOffset(entryIdx), (short)off);
         }
 
-        @Override int readOffset(BinaryRow row, int itemOff) {
-            return row.readShort(itemOff) & 0xFFFF;
+        /** {@inheritDoc} */
+        @Override int readVarlenOffset(BinaryRow row, int vartblOff, int entryIdx) {
+            return row.readShort(vartblOff + vartableEntryOffset(entryIdx)) & 0xFFFF;
         }
 
-        @Override void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size) {
+        /** {@inheritDoc} */
+        @Override void writeVartableSize(ExpandableByteBuf buf, int vartblOff, int size) {
             assert size < (1 << 16) && size >= 0 : "Vartable size overflow: size=" + size;
 
-            buf.putShort(vartblOff, (short)vartblOff);
+            buf.putShort(vartblOff, (short)size);
         }
 
-        @Override int readVartblSize(BinaryRow row, int vartblOff) {
+        /** {@inheritDoc} */
+        @Override int readVartableSize(BinaryRow row, int vartblOff) {
             return row.readShort(vartblOff) & 0xFFFF;
         }
     };
 
     /** Writer factory for large-sized chunks. */
     private static final ChunkFormat LARGE = new ChunkFormat(Short.BYTES, Integer.BYTES, (byte)0) {
-        @Override void writeOffset(ExpandableByteBuf buf, int itemOff, int off) {
-            buf.putInt(itemOff, off);
+        /** {@inheritDoc} */
+        @Override void writeVarlenOffset(ExpandableByteBuf buf, int vartblOff, int entryIdx, int off) {
+            buf.putInt(vartblOff + vartableEntryOffset(entryIdx), off);
         }
 
-        @Override int readOffset(BinaryRow row, int itemOff) {
-            return row.readInteger(itemOff);
+        /** {@inheritDoc} */
+        @Override int readVarlenOffset(BinaryRow row, int vartblOff, int entryIdx) {
+            return row.readInteger(vartblOff + vartableEntryOffset(entryIdx));
         }
 
-        @Override void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size) {
+        /** {@inheritDoc} */
+        @Override void writeVartableSize(ExpandableByteBuf buf, int vartblOff, int size) {
             assert size < (1 << 16) && size >= 0 : "Vartable size overflow: size=" + size;
 
-            buf.putShort(vartblOff, (short)vartblOff);
+            buf.putShort(vartblOff, (short)size);
         }
 
-        @Override int readVartblSize(BinaryRow row, int vartblOff) {
+        /** {@inheritDoc} */
+        @Override int readVartableSize(BinaryRow row, int vartblOff) {
             return row.readShort(vartblOff) & 0xFFFF;
         }
     };
 
-    /** Chunk length field size. */
-    public static final int CHUNK_LEN_FLD_SIZE = Integer.BYTES;
-
-    private final int vartableItemSize;
-
-    private final int vartableSizeFieldLen;
-
-    private final byte modeFlags;
-
     /**
      * Return chunk formatter.
      *
@@ -115,33 +118,35 @@ abstract class ChunkFormat {
      * @return Chunk formatter.
      */
     static ChunkFormat formatter(int payloadLen) {
-        if (payloadLen < 256)
-            return TINY;
+        if (payloadLen > 0) {
+            if (payloadLen < 256)
+                return TINY;
 
-        if (payloadLen < 64 * 1024)
-            return MEDIUM;
+            if (payloadLen < 64 * 1024)
+                return MEDIUM;
+        }
 
         return LARGE;
     }
 
     /**
+     * Creates chunk reader.
+     *
      * @param row Binary row.
-     * @param offset Offset.
-     * @param nullMapSize Default null-map size.
-     * @param chunkFlags Chunk flags.
-     * @return Reader.
+     * @param offset Chunk offset.
+     * @param nullMapSize Default chunk null-map size.
+     * @param chunkFlags Chunk flags. First 4-bits are meaningful.
+     * @return Chunk reader.
      */
     static ChunkReader createReader(BinaryRow row, int offset, int nullMapSize, byte chunkFlags) {
-        return fromFlags(chunkFlags).reader(row, offset,
-            (chunkFlags & OMIT_NULL_MAP_FLAG) == 0 ? nullMapSize : 0,
-            (chunkFlags & OMIT_VARTBL_FLAG) == 0);
+        return fromFlags(chunkFlags).reader(row, offset, nullMapSize, chunkFlags);
     }
 
     /**
-     * Chunk formatter from given flags.
+     * Chunk format factory method.
      *
-     * @param chunkFlags Chunk specific flags.
-     * @return Chunk formatter.
+     * @param chunkFlags Chunk specific flags. Only first 4-bits are meaningful.
+     * @return Chunk formatter regarding the provided flags.
      */
     private static ChunkFormat fromFlags(byte chunkFlags) {
         final int mode = chunkFlags & FORMAT_CODE_MASK;
@@ -156,65 +161,105 @@ abstract class ChunkFormat {
         }
     }
 
-    /**
-     * @param vartableSizeFieldLen Vartalble size field length.
-     * @param vartableItemSize Vartable item size.
-     */
-    public ChunkFormat(int vartableSizeFieldLen, int vartableItemSize, byte modeFlags) {
-        this.vartableItemSize = vartableItemSize;
-        this.vartableSizeFieldLen = vartableSizeFieldLen;
-        this.modeFlags = modeFlags;
-    }
+    /** Size of chunk length field. */
+    public static final int CHUNK_LEN_FLD_SIZE = Integer.BYTES;
 
-    int vartableSizeFieldLen() {
-        return vartableSizeFieldLen;
-    }
+    /** Size of vartable entry. */
+    private final int vartblEntrySize;
+
+    /** Size of cartable size field. */
+    private final int vartblSizeFieldSize;
 
-    int vartableItemSize() {
-        return vartableItemSize;
+    /** Format flags. */
+    private final byte flags;
+
+    /**
+     * @param vartblSizeFieldSize Size of vartalble size field (in bytes).
+     * @param vartblEntrySize Size of vartable entry (in bytes).
+     * @param flags Format specific flags.
+     */
+    ChunkFormat(int vartblSizeFieldSize, int vartblEntrySize, byte flags) {
+        this.vartblEntrySize = vartblEntrySize;
+        this.vartblSizeFieldSize = vartblSizeFieldSize;
+        this.flags = flags;
     }
 
-    public byte modeFlags() {
-        return modeFlags;
+    /**
+     * @return Format specific flags for a chunk.
+     */
+    public byte formatFlags() {
+        return flags;
     }
 
     /**
+     * Calculates chunk size for the format.
+     *
      * @param payloadLen Row payload length in bytes.
      * @param nullMapLen Null-map length in bytes.
-     * @param vartblItems Number of vartable items.
-     * @return Chunk size.
+     * @param vartblEntries Number of vartable entries.
+     * @return Total chunk size.
      */
-    int chunkSize(int payloadLen, int nullMapLen, int vartblItems) {
-        return CHUNK_LEN_FLD_SIZE /* Chunk len. */ + nullMapLen + vartableLength(vartblItems) + payloadLen;
+    int chunkSize(int payloadLen, int nullMapLen, int vartblEntries) {
+        return CHUNK_LEN_FLD_SIZE /* Chunk len. */ + nullMapLen + vartableLength(vartblEntries - 1) + payloadLen;
     }
 
     /**
-     * Calculates vartable length (in bytes).
+     * Calculates vartable size in bytes.
      *
-     * @param items Vartable items.
+     * @param entries Vartable entries.
      * @return Vartable size in bytes.
      */
-    protected int vartableLength(int items) {
-        return items == 0 ? 0 : vartableSizeFieldLen /* Table size */ + items * vartableItemSize;
+    int vartableLength(int entries) {
+        return entries <= 0 ? 0 : vartblSizeFieldSize /* Table size */ + entries * vartblEntrySize;
     }
 
     /**
-     * Calculates vartable item offset.
+     * Calculates vartable entry offset.
      *
-     * @param idx Vartable item idx.
-     * @return Vartable item offset.
+     * @param idx Vartable entry idx.
+     * @return Vartable entry offset.
      */
-    int vartblItemOff(int idx) {
-        return vartableSizeFieldLen /* Table size */ + idx * vartableItemSize;
+    int vartableEntryOffset(int idx) {
+        return vartblSizeFieldSize /* Table size */ + idx * vartblEntrySize;
     }
 
-    abstract void writeOffset(ExpandableByteBuf buf, int vartblItemOff, int off);
+    /**
+     * Writes varlen offset to vartable.
+     *
+     * @param buf Row buffer.
+     * @param vartblOff Vartable offset.
+     * @param entryIdx Vartable entry index.
+     * @param off Varlen offset to be written.
+     */
+    abstract void writeVarlenOffset(ExpandableByteBuf buf, int vartblOff, int entryIdx, int off);
 
-    abstract int readOffset(BinaryRow row, int vartblOff);
+    /**
+     * Readss varlen offset from vartable.
+     *
+     * @param row Row.
+     * @param vartblOff Vartable offset.
+     * @param entryIdx Vartable entry index.
+     * @return Varlen offset.
+     */
+    abstract int readVarlenOffset(BinaryRow row, int vartblOff, int entryIdx);
 
-    abstract void writeVartblSize(ExpandableByteBuf buf, int vartblOff, int size);
+    /**
+     * Writes vartable size.
+     *
+     * @param buf Row buffer.
+     * @param vartblOff Vartable offset.
+     * @param size Number of entries in the vartable.
+     */
+    abstract void writeVartableSize(ExpandableByteBuf buf, int vartblOff, int size);
 
-    abstract int readVartblSize(BinaryRow row, int vartblOff);
+    /**
+     * Reads vartable size.
+     *
+     * @param row Row.
+     * @param vartblOff Vartable offset.
+     * @return Number of entries in the vartable.
+     */
+    abstract int readVartableSize(BinaryRow row, int vartblOff);
 
     /**
      * Chunk writer factory method.
@@ -222,11 +267,16 @@ abstract class ChunkFormat {
      * @param buf Row buffer.
      * @param baseOff Chunk base offset.
      * @param nullMapLen Null-map length.
-     * @param vartblItems Vartable items.
+     * @param nonNullVarlens Number of entries in vartable.
      * @return Chunk writer.
      */
-    ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblItems) {
-        return new ChunkWriter(buf, baseOff, nullMapLen, vartblItems, this);
+    ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int nonNullVarlens) {
+        return new ChunkWriter(
+            buf,
+            baseOff,
+            nullMapLen,
+            vartableLength(nonNullVarlens - 1),
+            this);
     }
 
     /**
@@ -234,11 +284,16 @@ abstract class ChunkFormat {
      *
      * @param row Row buffer.
      * @param baseOff Chunk base offset.
-     * @param nullMapLen Null-map length.
-     * @param hasVarTable Has vartable flag.
+     * @param nullMapSize Default chunk null-map size.
+     * @param chunkFlags Chunk flags.
      * @return Chunk reader.
      */
-    ChunkReader reader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable) {
-        return new ChunkReader(row, baseOff, nullMapLen, hasVarTable, this);
+    ChunkReader reader(BinaryRow row, int baseOff, int nullMapSize, byte chunkFlags) {
+        return new ChunkReader(
+            row,
+            baseOff,
+            (chunkFlags & OMIT_NULL_MAP_FLAG) == 0 ? nullMapSize : 0,
+            (chunkFlags & OMIT_VARTBL_FLAG) == 0,
+            this);
     }
-}
\ No newline at end of file
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
index c0e0177..6a1bc10 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
@@ -21,7 +21,7 @@ import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.schema.Columns;
 
 /**
- * Abstract chunk reader.
+ * Chunk reader.
  */
 class ChunkReader {
     /** Row. */
@@ -34,48 +34,41 @@ class ChunkReader {
     private final ChunkFormat format;
 
     /** Vartable offset. */
-    protected int varTableOff;
+    protected int varTblOff;
 
-    /** Payload offset. */
+    /** Data offset. */
     protected int dataOff;
 
     /**
-     * @param row
-     * @param baseOff
-     * @param nullMapLen
-     * @param hasVarTable
-     * @param format
+     * @param row Row.
+     * @param baseOff Chunk base offset.
+     * @param nullMapLen Null-map size in bytes.
+     * @param hasVarTable {@code true} if chunk has vartable, {@code false} otherwise.
+     * @param format Chunk format.
      */
     ChunkReader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable, ChunkFormat format) {
         this.row = row;
         this.baseOff = baseOff;
         this.format = format;
-        varTableOff = nullmapOff() + nullMapLen;
-        dataOff = varTableOff + (hasVarTable ? format.vartableLength(format.readVartblSize(row, varTableOff)) : 0);
+        varTblOff = nullmapOff() + nullMapLen;
+        dataOff = varTblOff + (hasVarTable ? format.vartableLength(format.readVartableSize(row, varTblOff)) : 0);
     }
 
     /**
+     * Reads chunk total length.
+     *
      * @return Chunk length in bytes
      */
-    /** {@inheritDoc} */
     int chunkLength() {
         return row.readInteger(baseOff);
     }
 
     /**
-     * @return Number of items in vartable.
-     */
-    int vartableItems() {
-       return format.readVartblSize(row, varTableOff);
-    }
-
-    /**
-     * Checks the row's null map for the given column index in the chunk.
+     * Checks the row's null-map for the given column index in the chunk.
      *
      * @param idx Offset of the column in the chunk.
-     * @return {@code true} if the column value is {@code null}.
+     * @return {@code true} if the column value is {@code null}, {@code false} otherwise.
      */
-    /** {@inheritDoc} */
     protected boolean isNull(int idx) {
         if (!hasNullmap())
             return false;
@@ -88,38 +81,29 @@ class ChunkReader {
         return (map & (1 << posInByte)) != 0;
     }
 
+    /**
+     * @return Null-map offset
+     */
     private int nullmapOff() {
         return baseOff + Integer.BYTES;
     }
 
     /**
-     * @return {@code True} if chunk has vartable.
+     * @return {@code True} if chunk has vartable, {@code false} otherwise.
      */
     protected boolean hasVartable() {
-        return dataOff > varTableOff;
+        return dataOff > varTblOff;
     }
 
     /**
-     * @return {@code True} if chunk has nullmap.
+     * @return {@code True} if chunk has null-map, {@code false} otherwise.
      */
     protected boolean hasNullmap() {
-        return varTableOff > nullmapOff();
+        return varTblOff > nullmapOff();
     }
 
     /**
-     * @param itemIdx Varlen table item index.
-     * @return Varlen item offset.
-     */
-    protected int varlenItemOffset(int itemIdx) {
-        assert hasVartable() : "Vartable is ommited.";
-
-        final int off = format.vartblItemOff(itemIdx);
-
-        return format.readOffset(row, off);
-    }
-
-    /**
-     * Calculates the offset of the fixlen column with the given index in the row. It essentially folds the null map
+     * Calculates the offset of the fixlen column with the given index in the row. It essentially folds the null-map
      * with the column lengths to calculate the size of non-null columns preceding the requested column.
      *
      * @param cols Columns chunk.
@@ -130,27 +114,25 @@ class ChunkReader {
         int colOff = 0;
 
         // Calculate fixlen column offset.
-        {
-            int colByteIdx = idx / 8;
+        int colByteIdx = idx / 8;
 
-            // Set bits starting from posInByte, inclusive, up to either the end of the byte or the last column index, inclusive
-            int startBit = idx % 8;
-            int endBit = colByteIdx == (cols.length() + 7) / 8 - 1 ? ((cols.numberOfFixsizeColumns() - 1) % 8) : 7;
-            int mask = (0xFF >> (7 - endBit)) & (0xFF << startBit);
+        // Set bits starting from posInByte, inclusive, up to either the end of the byte or the last column index, inclusive
+        int startBit = idx % 8;
+        int endBit = colByteIdx == (cols.length() + 7) / 8 - 1 ? ((cols.numberOfFixsizeColumns() - 1) % 8) : 7;
+        int mask = (0xFF >> (7 - endBit)) & (0xFF << startBit);
 
-            if (hasNullmap()) {
-                // Fold offset based on the whole map bytes in the schema
-                for (int i = 0; i < colByteIdx; i++)
-                    colOff += cols.foldFixedLength(i, row.readByte(nullmapOff() + i));
+        if (hasNullmap()) {
+            // Fold offset based on the whole map bytes in the schema
+            for (int i = 0; i < colByteIdx; i++)
+                colOff += cols.foldFixedLength(i, row.readByte(nullmapOff() + i));
 
-                colOff += cols.foldFixedLength(colByteIdx, row.readByte(nullmapOff() + colByteIdx) | mask);
-            }
-            else {
-                for (int i = 0; i < colByteIdx; i++)
-                    colOff += cols.foldFixedLength(i, 0);
+            colOff += cols.foldFixedLength(colByteIdx, row.readByte(nullmapOff() + colByteIdx) | mask);
+        }
+        else {
+            for (int i = 0; i < colByteIdx; i++)
+                colOff += cols.foldFixedLength(i, 0);
 
-                colOff += cols.foldFixedLength(colByteIdx, mask);
-            }
+            colOff += cols.foldFixedLength(colByteIdx, mask);
         }
 
         return dataOff + colOff;
@@ -158,19 +140,21 @@ class ChunkReader {
 
     /**
      * Calculates the offset and length of varlen column. First, it calculates the number of non-null columns
-     * preceding the requested column by folding the null map bits. This number is used to adjust the column index
+     * preceding the requested column by folding the null-map bits. This number is used to adjust the column index
      * and find the corresponding entry in the varlen table. The length of the column is calculated either by
      * subtracting two adjacent varlen table offsets, or by subtracting the last varlen table offset from the chunk
      * length.
+     * <p>
+     * Note: Offset for the very fisrt varlen is skipped in vartable and calculated from fixlen columns sizes.
      *
      * @param cols Columns chunk.
      * @param idx Column index in the chunk.
      * @return Encoded offset (from the row start) and length of the column with the given index.
      */
     long varlenColumnOffsetAndLength(Columns cols, int idx) {
-        assert hasVartable() : "Chunk has no vartable: colId=" + idx;
+        assert cols.hasVarlengthColumns() && cols.firstVarlengthColumn() <= idx : "Invalid varlen column index: colId=" + idx;
 
-        if (hasNullmap()) {
+        if (hasNullmap()) { // Calculates fixlen columns chunk size regarding the 'null' flags.
             int nullStartByte = cols.firstVarlengthColumn() / 8;
             int startBitInByte = cols.firstVarlengthColumn() % 8;
 
@@ -198,29 +182,31 @@ class ChunkReader {
 
         idx -= cols.numberOfFixsizeColumns();
 
-        if (idx == 0) { // Very first non-null varlen column.
-            int off = cols.numberOfFixsizeColumns() == 0 ?
-                 varTableOff + varlenItemOffset(readShort(vartableOff)) : vartableOff) :
-                fixlenColumnOffset(cols, baseOff, cols.numberOfFixsizeColumns(), hasVarTbl, hasNullMap);
+        // Calculate length and offset for very first (non-null) varlen column
+        // as vartable don't store the offset for the first varlen.
+        if (idx == 0) {
+            int off = cols.numberOfFixsizeColumns() == 0 ? dataOff : fixlenColumnOffset(cols, cols.numberOfFixsizeColumns());
 
-            long len = hasVarTbl ?
-                readShort(vartableOff + varlenItemOffset(0)) - (off - baseOff) :
-                readInteger(baseOff) - (off - baseOff);
+            long len = hasVartable() ? // Length is either diff between current offset and next varlen offset or end-of-chunk.
+                format.readVarlenOffset(row, varTblOff, 0) - (off - dataOff) :
+                (baseOff + chunkLength()) - off;
 
             return (len << 32) | off;
         }
 
-        int vartableSize = readShort(vartableOff);
+        final int vartblSize = format.readVartableSize(row, varTblOff);
+
+        assert idx > 0 && vartblSize >= idx : "Vartable index is out of bound: colId=" + idx;
 
         // Offset of idx-th column is from base offset.
-        int resOff = readShort(vartableOff + varlenItemOffset(idx - 1));
+        int resOff = format.readVarlenOffset(row, varTblOff, idx - 1);
 
-        long len = (idx == vartableSize) ?
+        long len = (vartblSize == idx) ?
             // totalLength - columnStartOffset
-            readInteger(baseOff) - resOff :
+            (baseOff + chunkLength()) - (dataOff + resOff) :
             // nextColumnStartOffset - columnStartOffset
-            readShort(vartableOff + varlenItemOffset(idx)) - resOff;
+            format.readVarlenOffset(row, varTblOff, idx) - resOff;
 
-        return (len << 32) | (resOff + baseOff);
+        return (len << 32) | (dataOff + resOff);
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
index dc65302..dbe5f9e 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
@@ -40,8 +40,11 @@ class ChunkWriter {
     /** Offset of data for the chunk. */
     protected final int dataOff;
 
+    /** Chunk format. */
+    private final ChunkFormat format;
+
     /** Index of the current varlen table entry. Incremented each time non-null varlen column is appended. */
-    protected int curVartblItem;
+    protected int curVartblEntry;
 
     /** Current offset for the next column to be appended. */
     protected int curOff;
@@ -49,31 +52,30 @@ class ChunkWriter {
     /** Chunk flags. */
     private byte flags;
 
-    /** Chunk format. */
-    ChunkFormat format;
 
     /**
      * @param buf Row buffer.
      * @param baseOff Chunk base offset.
      * @param nullMapLen Null-map length in bytes.
-     * @param vartblItems Vartable length in bytes.
+     * @param vartblLen Vartable length in bytes.
+     * @param format Chunk format.
      */
-    protected ChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblItems, ChunkFormat format) {
+    protected ChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblLen, ChunkFormat format) {
         this.buf = buf;
         this.baseOff = baseOff;
         this.format = format;
-        this.flags = format.modeFlags();
 
+        flags = format.formatFlags();
         varTblOff = nullmapOff() + nullMapLen;
-        dataOff = varTblOff + format.vartableLength(vartblItems);
+        dataOff = varTblOff + vartblLen;
         curOff = dataOff;
-        curVartblItem = 0;
+        curVartblEntry = 0;
 
-        if (nullmapOff() == baseOff)
-            this.flags |= ChunkFormat.OMIT_NULL_MAP_FLAG;
+        if (nullMapLen == 0)
+            flags |= ChunkFormat.OMIT_NULL_MAP_FLAG;
 
-        if (dataOff == varTblOff)
-            this.flags |= ChunkFormat.OMIT_VARTBL_FLAG;
+        if (vartblLen == 0)
+            flags |= ChunkFormat.OMIT_VARTBL_FLAG;
     }
 
     /**
@@ -160,15 +162,12 @@ class ChunkWriter {
      * @param val Column value.
      */
     public void appendString(String val, CharsetEncoder encoder) {
-        assert (flags & ChunkFormat.OMIT_VARTBL_FLAG) == 0 :
-            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
-
         try {
             int written = buf.putString(curOff, val, encoder);
 
-            writeOffset(curVartblItem, curOff - dataOff);
+            writeVarlenOffset(curVartblEntry, curOff - dataOff);
 
-            curVartblItem++;
+            curVartblEntry++;
             curOff += written;
         }
         catch (CharacterCodingException e) {
@@ -182,14 +181,11 @@ class ChunkWriter {
      * @param val Column value.
      */
     public void appendBytes(byte[] val) {
-        assert (flags & ChunkFormat.OMIT_VARTBL_FLAG) == 0 :
-            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
-
         buf.putBytes(curOff, val);
 
-        writeOffset(curVartblItem, curOff - dataOff);
+        writeVarlenOffset(curVartblEntry, curOff - dataOff);
 
-        curVartblItem++;
+        curVartblEntry++;
         curOff += val.length;
     }
 
@@ -210,6 +206,20 @@ class ChunkWriter {
     }
 
     /**
+     * @return Null-map offset.
+     */
+    private int nullmapOff() {
+        return baseOff + ChunkFormat.CHUNK_LEN_FLD_SIZE;
+    }
+
+    /**
+     * @return Chunk flags.
+     */
+    public short chunkFlags() {
+        return flags;
+    }
+
+    /**
      * @return Chunk size in bytes.
      */
     public int chunkLength() {
@@ -220,35 +230,38 @@ class ChunkWriter {
      * Post-write action.
      */
     void flush() {
-        final int size = chunkLength();
+        buf.putInt(baseOff,  chunkLength());
 
-        buf.putInt(baseOff, size);
+        if (curVartblEntry > 1) {
+            assert varTblOff + format.vartableLength(curVartblEntry - 1) == dataOff : "Vartable overlow: size=" + curVartblEntry;
 
-        if (curVartblItem > 0)
-            format.writeVartblSize(buf, varTblOff, curVartblItem);
+            format.writeVartableSize(buf, varTblOff, curVartblEntry - 1);
+        }
     }
 
     /**
      * Writes the given offset to the varlen table entry with the given index.
      *
-     * @param tblItemIdx Varlen table entry index.
+     * @param entryIdx Vartable entry index.
      * @param off Offset to write.
      */
-    protected void writeOffset(int tblItemIdx, int off) {
-        final int itemOff = varTblOff + format.vartblItemOff(tblItemIdx);
+    protected void writeVarlenOffset(int entryIdx, int off) {
+        if (entryIdx == 0)
+            return; // Omit offset for very first varlen.
 
-        assert itemOff < dataOff : "Vartable overflow: size=" + itemOff;
+        assert (flags & ChunkFormat.OMIT_VARTBL_FLAG) == 0 :
+            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
 
-        format.writeOffset(buf, itemOff, off);
+        format.writeVarlenOffset(buf, varTblOff, entryIdx - 1, off);
     }
 
     /**
-     * Sets null flag in the null map for the given column.
+     * Sets null flag in the null-map for the given column.
      *
      * @param colIdx Column index.
      */
     protected void setNull(int colIdx) {
-        assert (flags & ChunkFormat.OMIT_NULL_MAP_FLAG) == 0 : "Null map is omitted.";
+        assert (flags & ChunkFormat.OMIT_NULL_MAP_FLAG) == 0 : "Null-map is omitted.";
 
         int byteInMap = colIdx / 8;
         int bitInByte = colIdx % 8;
@@ -257,12 +270,4 @@ class ChunkWriter {
 
         buf.put(nullmapOff() + byteInMap, (byte)(buf.get(nullmapOff() + byteInMap) | (1 << bitInByte)));
     }
-
-    private int nullmapOff() {
-        return baseOff + Integer.BYTES;
-    }
-
-    public short flags() {
-        return flags;
-    }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ExpandableByteBuf.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ExpandableByteBuf.java
index 96401b3..74f5099 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ExpandableByteBuf.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ExpandableByteBuf.java
@@ -57,7 +57,9 @@ public class ExpandableByteBuf {
     private int len;
 
     /**
-     * @param size Start buffer size.
+     * Creates expandable row buffer.
+     *
+     * @param size Initial buffer size.
      */
     public ExpandableByteBuf(int size) {
         if (size <= 0)
@@ -282,7 +284,7 @@ public class ExpandableByteBuf {
     /**
      * Unwrap to ByteBuffer.
      *
-     * @return Byte buffer.
+     * @return internal buffer.
      */
     ByteBuffer unwrap() {
         return buf;
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
index 027da41..20d88d2 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
@@ -373,13 +373,14 @@ public class Row implements BinaryRow {
         if (reader.isNull(colIdx))
             return -1;
 
-        assert reader.hasVartable() || type.fixedLength();
-
         return type.fixedLength() ?
-            reader.fixlenColumnOffset(cols, off, colIdx, hasVarTable, hasNullMap) :
+            reader.fixlenColumnOffset(cols, colIdx) :
             reader.varlenColumnOffsetAndLength(cols, colIdx);
     }
 
+    /**
+     * @return Reader for value chunk.
+     */
     private ChunkReader valueReader() {
         if (valReader != null)
             return valReader;
@@ -391,8 +392,8 @@ public class Row implements BinaryRow {
         return (valReader = ChunkFormat.createReader(
             this,
             KEY_CHUNK_OFFSET + keyReader.chunkLength(),
-            schema.keyColumns().nullMapSize(),
-            (byte)(flags >>> RowFlags.VAL_FLAGS_OFFSET)));
+            schema.valueColumns().nullMapSize(),
+            (byte)((flags >>> RowFlags.VAL_FLAGS_OFFSET)& RowFlags.CHUNK_FLAGS_MASK)));
     }
 
     /**
@@ -491,5 +492,4 @@ public class Row implements BinaryRow {
     @Override public byte[] readBytes(int off, int len) {
         return row.readBytes(off, len);
     }
-
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
index c245d9f..6e0f45a 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
@@ -50,11 +50,14 @@ public class RowAssembler {
     /** Schema. */
     private final SchemaDescriptor schema;
 
+    /** Target byte buffer to write to. */
+    private final ExpandableByteBuf buf;
+
     /** The number of non-null varlen columns in values chunk. */
     private final int valVarlenCols;
 
-    /** Target byte buffer to write to. */
-    private final ExpandableByteBuf buf;
+    /** Value write mode. */
+    private final ChunkFormat valWriteMode;
 
     /** Current columns chunk. */
     private Columns curCols;
@@ -74,9 +77,6 @@ public class RowAssembler {
     /** Current chunk writer. */
     private ChunkWriter chunkWriter;
 
-    /** Value write mode. */
-    private ChunkFormat valWriteMode;
-
     /**
      * Calculates encoded string length.
      *
@@ -184,6 +184,7 @@ public class RowAssembler {
         curCols = schema.keyColumns();
         curCol = 0;
         flags = 0;
+        hash = 0;
         strEncoder = null;
 
         final int keyNullMapSize = keyHasNulls ? schema.keyColumns().nullMapSize() : 0;
@@ -204,8 +205,10 @@ public class RowAssembler {
 
     /**
      * Appends {@code null} value for the current column to the chunk.
+     *
+     * @return {@code this} for chaining.
      */
-    public void appendNull() {
+    public RowAssembler appendNull() {
         Column col = curCols.column(curCol);
 
         if (!col.nullable())
@@ -218,14 +221,17 @@ public class RowAssembler {
         chunkWriter.setNull(curCol);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends byte value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendByte(byte val) {
+    public RowAssembler appendByte(byte val) {
         checkType(NativeTypes.BYTE);
 
         if (isKeyColumn())
@@ -234,14 +240,17 @@ public class RowAssembler {
         chunkWriter.appendByte(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends short value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendShort(short val) {
+    public RowAssembler appendShort(short val) {
         checkType(NativeTypes.SHORT);
 
         if (isKeyColumn())
@@ -250,14 +259,17 @@ public class RowAssembler {
         chunkWriter.appendShort(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends int value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendInt(int val) {
+    public RowAssembler appendInt(int val) {
         checkType(NativeTypes.INTEGER);
 
         if (isKeyColumn())
@@ -266,14 +278,17 @@ public class RowAssembler {
         chunkWriter.appendInt(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends long value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendLong(long val) {
+    public RowAssembler appendLong(long val) {
         checkType(NativeTypes.LONG);
 
         if (isKeyColumn())
@@ -282,14 +297,17 @@ public class RowAssembler {
         chunkWriter.appendLong(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends float value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendFloat(float val) {
+    public RowAssembler appendFloat(float val) {
         checkType(NativeTypes.FLOAT);
 
         if (isKeyColumn())
@@ -298,14 +316,17 @@ public class RowAssembler {
         chunkWriter.appendFloat(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends double value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendDouble(double val) {
+    public RowAssembler appendDouble(double val) {
         checkType(NativeTypes.DOUBLE);
 
         if (isKeyColumn())
@@ -314,14 +335,17 @@ public class RowAssembler {
         chunkWriter.appendDouble(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends UUID value for the current column to the chunk.
      *
      * @param uuid Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendUuid(UUID uuid) {
+    public RowAssembler appendUuid(UUID uuid) {
         checkType(NativeTypes.UUID);
 
         if (isKeyColumn())
@@ -330,14 +354,17 @@ public class RowAssembler {
         chunkWriter.appendUuid(uuid);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends String value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendString(String val) {
+    public RowAssembler appendString(String val) {
         checkType(NativeTypes.STRING);
 
         if (isKeyColumn())
@@ -346,14 +373,17 @@ public class RowAssembler {
         chunkWriter.appendString(val, encoder());
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends byte[] value for the current column to the chunk.
      *
      * @param val Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendBytes(byte[] val) {
+    public RowAssembler appendBytes(byte[] val) {
         checkType(NativeTypes.BYTES);
 
         if (isKeyColumn())
@@ -362,14 +392,17 @@ public class RowAssembler {
         chunkWriter.appendBytes(val);
 
         shiftColumn();
+
+        return this;
     }
 
     /**
      * Appends BitSet value for the current column to the chunk.
      *
      * @param bitSet Column value.
+     * @return {@code this} for chaining.
      */
-    public void appendBitmask(BitSet bitSet) {
+    public RowAssembler appendBitmask(BitSet bitSet) {
         Column col = curCols.column(curCol);
 
         checkType(NativeTypeSpec.BITMASK);
@@ -386,6 +419,8 @@ public class RowAssembler {
         chunkWriter.appendBitmask(bitSet, maskType.sizeInBytes());
 
         shiftColumn();
+
+        return this;
     }
 
     /**
@@ -455,7 +490,9 @@ public class RowAssembler {
             chunkWriter.flush();
 
             if (schema.valueColumns() == curCols) {
-                flags |= (chunkWriter.flags() & 0x0F) << VAL_FLAGS_OFFSET;
+                assert (chunkWriter.chunkFlags() & (~0x0F)) == 0 : "Value chunk flags overflow: flags=" + chunkWriter.chunkFlags();
+
+                flags |= (chunkWriter.chunkFlags() & 0x0F) << VAL_FLAGS_OFFSET;
 
                 return; // No more columns.
             }
@@ -464,7 +501,9 @@ public class RowAssembler {
             curCols = schema.valueColumns();
             curCol = 0;
 
-            flags |= (chunkWriter.flags() & 0x0F) << KEY_FLAGS_OFFSET;
+            assert (chunkWriter.chunkFlags() & (~0x0F)) == 0 : "Key chunk flags overflow: flags=" + chunkWriter.chunkFlags();
+
+            flags |= (chunkWriter.chunkFlags() & 0x0F) << KEY_FLAGS_OFFSET;
 
             // Create value chunk writer.
             chunkWriter = valWriteMode.writer(buf,
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerAdvancedSchemaTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerAdvancedSchemaTest.java
index d4f9daf..ec6be58 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerAdvancedSchemaTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerAdvancedSchemaTest.java
@@ -19,6 +19,8 @@ package org.apache.ignite.internal.schema;
 
 import java.util.Arrays;
 import java.util.UUID;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
@@ -27,6 +29,8 @@ import static org.apache.ignite.internal.schema.NativeTypes.INTEGER;
 import static org.apache.ignite.internal.schema.NativeTypes.SHORT;
 import static org.apache.ignite.internal.schema.NativeTypes.STRING;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
 
 /**
  * Validate row layout for different schema configurations.
@@ -54,8 +58,8 @@ public class RowAssemblerAdvancedSchemaTest {
 
         // Last col null
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, -11, 43, 0, 0, 8, 0, 0, 0, 4, 11, 22, 0, 8, 0, 0, 0, 4, -44, -66, -1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, -11, 43, 0, 0, 8, 0, 0, 0, 4, 11, 22, 0, 8, 0, 0, 0, 4, -44, -66, -1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendByte((byte)11)
                 .appendShort((short)22)
                 .appendNull()
@@ -66,8 +70,8 @@ public class RowAssemblerAdvancedSchemaTest {
 
         // First col null.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, -53, 2, 0, 0, 11, 0, 0, 0, 1, 22, 0, 33, 0, 0, 0, 11, 0, 0, 0, 1, -55, -1, -66, -1, -1, -1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, -53, 2, 0, 0, 11, 0, 0, 0, 1, 22, 0, 33, 0, 0, 0, 11, 0, 0, 0, 1, -55, -1, -66, -1, -1, -1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendShort((byte)22)
                 .appendInt(33)
@@ -77,8 +81,8 @@ public class RowAssemblerAdvancedSchemaTest {
                 .build());
 
         // Middle col null.
-        assertRowBytesEquals(new byte[] {42, 0, 24, 0, 108, 41, 0, 0, 10, 0, 0, 0, 2, 11, 33, 0, 0, 0, 10, 0, 0, 0, 2, -44, -66, -1, -1, -1},
-            new RowAssembler(schema, 0, 0, 0)
+        assertRowBytesEquals(new byte[] {42, 0, 0, -103, 108, 41, 0, 0, 10, 0, 0, 0, 2, 11, 33, 0, 0, 0, 10, 0, 0, 0, 2, -44, -66, -1, -1, -1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendByte((byte)11)
                 .appendNull()
                 .appendInt(33)
@@ -88,8 +92,8 @@ public class RowAssemblerAdvancedSchemaTest {
                 .build());
 
         // Null both.
-        assertRowBytesEquals(new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 7, 5, 0, 0, 0, 7},
-            new RowAssembler(schema, 0, 0, 0)
+        assertRowBytesEquals(new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 7, 5, 0, 0, 0, 7},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .appendNull()
@@ -99,14 +103,43 @@ public class RowAssemblerAdvancedSchemaTest {
                 .build());
 
         // No value.
-        assertRowBytesEquals(new byte[] {42, 0, 25, 0, 22, 44, 0, 0, 12, 0, 0, 0, 0, 11, 22, 0, 33, 0, 0, 0},
-            new RowAssembler(schema, 0, 0, 0)
+        assertRowBytesEquals(new byte[] {42, 0, 1, 9, 22, 44, 0, 0, 12, 0, 0, 0, 0, 11, 22, 0, 33, 0, 0, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendByte((byte)11)
                 .appendShort((short)22)
                 .appendInt(33)
                 .build());
     }
+    /**
+     * Validate row layout for schema of fix-len nullable key and fix-len nullable value.
+     */
+    @Test
+    public void varlenNullableColumns2() {
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42,
+            new Column[] {
+                new Column("keyCol2", BYTES, true),
+                new Column("keyCol3", STRING, true)
+            },
+            new Column[] {
+                new Column("valCol2", BYTES, true),
+                new Column("valCol3", STRING, true)
+            });
 
+        final byte[] data = new RowAssembler(schema, 128, 1, 128, 1)
+            .appendNull()
+            .appendString("A我愛我愛我愛我愛我愛")
+            .appendNull()
+            .appendString("A我愛我愛我愛我愛我愛")
+            .build();
+
+        final Row row = new Row(schema, new ByteBufferRow(data));
+
+        assertNull(row.bytesValue(0));
+//        assertArrayEquals(new byte[] {33, -77}, row.bytesValue(0));
+        assertEquals("A我愛我愛我愛我愛我愛", row.stringValue(1));
+//        assertArrayEquals(new byte[] {33, -77}, row.bytesValue(2));
+        assertEquals("A我愛我愛我愛我愛我愛", row.stringValue(3));
+    }
     /**
      * Validate row layout for schema of fix-len nullable key and fix-len nullable value.
      */
@@ -127,10 +160,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Last col null
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 0, 0, 47, -30, -119, -81,
-                17, 0, 0, 0, 4, 1, 0, 12, 0, 33, -77, 120, 97, 115, 99, 105, 105,
-                21, 0, 0, 0, 4, 1, 0, 11, 0, 33, -77, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97},
-            new RowAssembler(schema, 25, 2, 2)
+                42, 0, 0, 17, -12, -36, 109, -81,
+                15, 0, 0, 0, 4, 1, 3, 33, -77, 120, 97, 115, 99, 105, 105,
+                19, 0, 0, 0, 4, 1, 2, 33, -77, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97},
+            new RowAssembler(schema, 128, 2, 128, 2)
                 .appendBytes(new byte[] {33, -77, 120})
                 .appendString("ascii")
                 .appendNull()
@@ -142,10 +175,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Fist col null.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 0, 0, -116, -92, 12, 98,
-                24, 0, 0, 0, 1, 1, 0, 14, 0, 97, 115, 99, 105, 105, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
-                24, 0, 0, 0, 1, 1, 0, 19, 0, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97, 97, 115, 99, 105, 105},
-            new RowAssembler(schema, 0, 2, 2)
+                42, 0, 0, 17, 59, -11, 127, 92,
+                22, 0, 0, 0, 1, 1, 5, 97, 115, 99, 105, 105, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
+                22, 0, 0, 0, 1, 1, 10, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97, 97, 115, 99, 105, 105},
+            new RowAssembler(schema, 128, 2, 128, 2)
                 .appendNull()
                 .appendString("ascii")
                 .appendString("我愛Java")
@@ -157,10 +190,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Middle col null.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 0, 0, -52, 97, -9, -77,
-                22, 0, 0, 0, 2, 1, 0, 12, 0, 33, -77, 120, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
-                16, 0, 0, 0, 2, 1, 0, 11, 0, 33, -77, 97, 115, 99, 105, 105},
-            new RowAssembler(schema, 0, 2, 2)
+                42, 0, 0, 17, -111, 92, -37, -77,
+                20, 0, 0, 0, 2, 1, 3, 33, -77, 120, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
+                14, 0, 0, 0, 2, 1, 2, 33, -77, 97, 115, 99, 105, 105},
+            new RowAssembler(schema, 128, 2, 128, 2)
                 .appendBytes(new byte[] {33, -77, 120})
                 .appendNull()
                 .appendString("我愛Java")
@@ -171,8 +204,8 @@ public class RowAssemblerAdvancedSchemaTest {
 
         // Null both.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 7, 5, 0, 0, 0, 7},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 7, 5, 0, 0, 0, 7},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .appendNull()
@@ -184,9 +217,9 @@ public class RowAssemblerAdvancedSchemaTest {
         // No value.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 17, 0, -47, -112, 1, 24,
-                29, 0, 0, 0, 0, 2, 0, 14, 0, 24, 0, 33, -77, 120, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97, 97, 115, 99, 105, 105},
-            new RowAssembler(schema, 0, 3, 0)
+                42, 0, 1, 1, -118, -28, 81, 103,
+                26, 0, 0, 0, 0, 2, 3, 13, 33, -77, 120, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97, 97, 115, 99, 105, 105},
+            new RowAssembler(schema, 128, 3, 128, 0)
                 .appendBytes(new byte[] {33, -77, 120})
                 .appendString("我愛Java")
                 .appendString("ascii")
@@ -215,10 +248,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Check null/non-null all fixlen/varlen.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 0, 0, -85, 82, 5, 0,
-                12, 0, 0, 0, 12, 1, 0, 0, 0, 11, 22, 0,
-                16, 0, 0, 0, 3, 1, 0, 11, 0, 77, -88, 97, 115, 99, 105, 105},
-            new RowAssembler(schema, 0, 2, 2)
+                42, 0, 0, 25, -85, 82, 5, 0,
+                8, 0, 0, 0, 12, 11, 22, 0,
+                14, 0, 0, 0, 3, 1, 2, 77, -88, 97, 115, 99, 105, 105},
+            new RowAssembler(schema, 128, 0, 128, 2)
                 .appendByte((byte)11)
                 .appendShort((short)22)
                 .appendNull()
@@ -232,10 +265,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Check null/non-null fixlen.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 0, 0, -20, 4, 120, -80,
-                23, 0, 0, 0, 1, 1, 0, 13, 0, 22, 0, 33, -44, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
-                17, 0, 0, 0, 2, 1, 0, 12, 0, 55, 77, -88, 97, 115, 99, 105, 105},
-            new RowAssembler(schema, 0, 2, 2)
+                42, 0, 0, 17, -18, -9, 119, -80,
+                21, 0, 0, 0, 1, 1, 4, 22, 0, 33, -44, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
+                15, 0, 0, 0, 2, 1, 3, 55, 77, -88, 97, 115, 99, 105, 105},
+            new RowAssembler(schema, 128, 2, 128, 2)
                 .appendNull()
                 .appendShort((short)22)
                 .appendBytes(new byte[] {33, -44})
@@ -249,10 +282,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Check null/non-null varlen.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 24, 0, 12, 57, 124, -80,
+                42, 0, 0, -120, 23, 13, 124, -80,
                 18, 0, 0, 0, 4, 11, 22, 0, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
                 10, 0, 0, 0, 8, 55, 22, 0, 77, -88},
-            new RowAssembler(schema, 0, 1, 1)
+            new RowAssembler(schema, 1, 1)
                 .appendByte((byte)11)
                 .appendShort((short)22)
                 .appendNull()
@@ -266,10 +299,10 @@ public class RowAssemblerAdvancedSchemaTest {
         // Check null/non-null mixed.
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 24, 0, -52, -29, 123, -80,
+                42, 0, 0, -120, -127, -70, 123, -80,
                 16, 0, 0, 0, 6, 11, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
                 9, 0, 0, 0, 9, 22, 0, 77, -88},
-            new RowAssembler(schema, 0, 1, 1)
+            new RowAssembler(schema, 1, 1)
                 .appendByte((byte)11)
                 .appendNull()
                 .appendNull()
@@ -282,10 +315,11 @@ public class RowAssemblerAdvancedSchemaTest {
 
         // Check all null/non-null.
         assertRowBytesEquals(
-            new byte[] {42, 0, 16, 0, -20, 88, 125, -80,
-                24, 0, 0, 0, 0, 1, 0, 14, 0, 11, 22, 0, 33, -44, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
+            new byte[] {
+                42, 0, 0, -111, 3, -8, 124, -80,
+                22, 0, 0, 0, 0, 1, 5, 11, 22, 0, 33, -44, -26, -120, -111, -26, -124, -101, 74, 97, 118, 97,
                 5, 0, 0, 0, 15},
-            new RowAssembler(schema, 0, 2, 0)
+            new RowAssembler(schema, 128, 2, 128, 0)
                 .appendByte((byte)11)
                 .appendShort((short)22)
                 .appendBytes(new byte[] {33, -44})
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerSimpleSchemaTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerSimpleSchemaTest.java
index 7733b5a..aa02135 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerSimpleSchemaTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerSimpleSchemaTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.schema;
 
 import java.util.Arrays;
 import java.util.UUID;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
@@ -49,24 +50,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valIntCol", INTEGER, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0, 9, 0, 0, 0, 0, -71, -1, -1, -1},
-            new RowAssembler(schema, 24, 0, 0)
+            new byte[] {42, 0, 0, -99, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0, 9, 0, 0, 0, 0, -71, -1, -1, -1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendInt(33)
                 .appendInt(-71)
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 21, 0, 0)
+            new byte[] {42, 0, 0, -99, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendInt(33)
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 27, 0, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0},
-            new RowAssembler(schema, 16, 0, 0)
+            new byte[] {42, 0, 1, 13, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendInt(33)
                 .build());
     }
@@ -82,16 +83,16 @@ public class RowAssemblerSimpleSchemaTest {
 
         // With value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 30, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 6, 0, 0, 0, -71, -1},
-            new RowAssembler(schema, 20, 0, 0)
+            new byte[] {42, 0, 0, -35, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 6, 0, 0, 0, -71, -1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .appendShort((short)-71)
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 31, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 14, 0, 0)
+            new byte[] {42, 0, 1, 13, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
     }
@@ -106,24 +107,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valStrCol", STRING, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, -33, -1, -1, -1, 6, 0, 0, 0, -33, -1, 8, 0, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -99, -33, -1, -1, -1, 6, 0, 0, 0, -33, -1, 8, 0, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendShort((short)-33)
                 .appendString("val")
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -99, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 27, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 13, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
     }
@@ -138,16 +139,16 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valStrCol", STRING, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 30, 0, -33, -1, -1, -1, 6, 0, 0, 0, -33, -1, 7, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -35, -33, -1, -1, -1, 6, 0, 0, 0, -33, -1, 7, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendShort((short)-33)
                 .appendString("val")
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 31, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 13, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
     }
@@ -162,24 +163,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valByteCol", BYTE, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, -33, -1, -1, -1, 7, 0, 0, 0, 0, -33, -1, 5, 0, 0, 0, 71},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -39, -33, -1, -1, -1, 7, 0, 0, 0, 0, -33, -1, 5, 0, 0, 0, 71},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)-33)
                 .appendByte((byte)71)
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, -71},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -39, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, -71},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendByte((byte)-71)
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 29, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 9, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
     }
@@ -195,32 +196,32 @@ public class RowAssemblerSimpleSchemaTest {
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendShort((short)33)
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .appendNull()
                 .build());
 
         // Null both.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 25, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 9, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
 
@@ -236,40 +237,40 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valStrCol", STRING, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 8, 0, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -103, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 8, 0, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendShort((short)33)
                 .appendString("val")
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 8, 0, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 8, 0, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendNull()
                 .appendString("val")
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .appendNull()
                 .build());
 
         // Null both.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 25, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 9, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendShort((short)33)
                 .build());
     }
@@ -284,22 +285,22 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valStrCol", STRING, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 33, 0, 0, 0, 6, 0, 0, 0, 0, 33, 7, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -39, 33, 0, 0, 0, 6, 0, 0, 0, 0, 33, 7, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendByte((byte)33)
                 .appendString("val").build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 118, 97, 108},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -39, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 118, 97, 108},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendNull()
                 .appendString("val").build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 29, 0, 33, 0, 0, 0, 6, 0, 0, 0, 0, 33},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 1, 9, 33, 0, 0, 0, 6, 0, 0, 0, 0, 33},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendByte((byte)33)
                 .build());
     }
@@ -315,26 +316,25 @@ public class RowAssemblerSimpleSchemaTest {
 
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 26, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121,
+                42, 0, 0, -99, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121,
                 21, 0, 0, 0, 0, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73},
-            new RowAssembler(schema, 0, 1, 0)
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendUuid(uuidVal)
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 95, -98, 1, 0, 7, 0, 0, 0,107, 101, 121, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 1, 0)
-
+            new byte[] {42, 0, 0, -99, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 27, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 13, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
 
@@ -351,17 +351,17 @@ public class RowAssemblerSimpleSchemaTest {
 
         assertRowBytesEquals(
             new byte[] {
-                42, 0, 30, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121,
+                42, 0, 0, -35, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121,
                 20, 0, 0, 0, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73},
-            new RowAssembler(schema, 0, 1, 0)
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendUuid(uuidVal)
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 31, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 13, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
 
@@ -377,24 +377,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 9, 0, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 1, 1)
+            new byte[] {42, 0, 0, -99, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 9, 0, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 1, 128, 1)
                 .appendString("key")
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 26, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 0, -99, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 27, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 13, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
 
@@ -410,16 +410,16 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valBytesCol", BYTES, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 30, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 8, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 1, 1)
+            new byte[] {42, 0, 0, -35, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121, 8, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 1, 128, 1)
                 .appendString("key")
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 31, 0, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 13, 95, -98, 1, 0, 7, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
     }
@@ -434,40 +434,40 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valShortCol", SHORT, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 7, 0, 0, 0, 0, -71, -1},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 0, -103, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 7, 0, 0, 0, 0, -71, -1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendShort((short)-71)
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 0, 71, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 0, 71, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendShort((short)71)
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 0, -103, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendNull()
                 .build());
 
         // Null both.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 25, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 9, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
 
@@ -483,24 +483,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valShortCol", SHORT, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 6, 0, 0, 0, -71, -1},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 0, -39, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 6, 0, 0, 0, -71, -1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendShort((short)-71L)
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 6, 0, 0, 0, 71, 0},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -39, 0, 0, 0, 0, 5, 0, 0, 0, 1, 6, 0, 0, 0, 71, 0},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendShort((short)71)
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 29, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 9, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
     }
@@ -515,40 +515,40 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valBytesCol", BYTES, true)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 9, 0, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 1, 1)
+            new byte[] {42, 0, 0, -103, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 9, 0, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 1, 128, 1)
                 .appendString("key")
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 9, 0, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 9, 0, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendNull()
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // Null value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 0, -103, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .appendNull()
                 .build());
 
         // Null both.
         assertRowBytesEquals(
-            new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
-            new RowAssembler(schema, 0, 0, 0)
+            new byte[] {42, 0, 0, -103, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1},
+            new RowAssembler(schema, 128, 0, 128, 0)
                 .appendNull()
                 .appendNull()
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 25, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 9, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
     }
@@ -563,24 +563,24 @@ public class RowAssemblerSimpleSchemaTest {
             new Column[] {new Column("valBytesCol", BYTES, false)});
 
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 8, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 1, 1)
+            new byte[] {42, 0, 0, -39, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121, 8, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 1, 128, 1)
                 .appendString("key")
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // Null key.
         assertRowBytesEquals(
-            new byte[] {42, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 8, 0, 0, 0, -1, 1, 0, 120},
-            new RowAssembler(schema, 0, 0, 1)
+            new byte[] {42, 0, 0, -39, 0, 0, 0, 0, 5, 0, 0, 0, 1, 8, 0, 0, 0, -1, 1, 0, 120},
+            new RowAssembler(schema, 128, 0, 128, 1)
                 .appendNull()
                 .appendBytes(new byte[] {-1, 1, 0, 120})
                 .build());
 
         // No value.
         assertRowBytesEquals(
-            new byte[] {42, 0, 29, 0, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
-            new RowAssembler(schema, 0, 1, 0)
+            new byte[] {42, 0, 1, 9, 95, -98, 1, 0, 8, 0, 0, 0, 0, 107, 101, 121},
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendString("key")
                 .build());
     }
@@ -601,10 +601,10 @@ public class RowAssemblerSimpleSchemaTest {
             });
 
         assertRowBytesEquals(new byte[] {
-                42, 0, 26, 0, -110, -109, 94, -68,
+                42, 0, 0, -99, 113, -109, 94, -68,
                 12, 0, 0, 0, 33, 0, 107, 101, 121, 115, 116, 114,
                 15, 0, 0, 0, 0, 73, 0, 0, 0, 118, 97, 108, 115, 116, 114},
-            new RowAssembler(schema, 0, 1, 1)
+            new RowAssembler(schema, 128, 1, 128, 1)
                 .appendShort((short)33)
                 .appendString("keystr")
                 .appendInt(73)
@@ -613,10 +613,10 @@ public class RowAssemblerSimpleSchemaTest {
 
         // Null value.
         assertRowBytesEquals(new byte[] {
-                42, 0, 26, 0, 32, 99, 115, -49,
+                42, 0, 0, -99, -1, 98, 115, -49,
                 13, 0, 0, 0, 33, 0, 107, 101, 121, 115, 116, 114, 50,
                 5, 0, 0, 0, 3},
-            new RowAssembler(schema, 0, 1, 0)
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendShort((short)33)
                 .appendString("keystr2")
                 .appendNull()
@@ -625,9 +625,9 @@ public class RowAssemblerSimpleSchemaTest {
 
         // No value.
         assertRowBytesEquals(new byte[] {
-                42, 0, 27, 0, -110, -109, 94, -68,
+                42, 0, 1, 13, 113, -109, 94, -68,
                 12, 0, 0, 0, 33, 0, 107, 101, 121, 115, 116, 114},
-            new RowAssembler(schema, 0, 1, 0)
+            new RowAssembler(schema, 128, 1, 128, 0)
                 .appendShort((short)33)
                 .appendString("keystr")
                 .build());
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
deleted file mode 100644
index 6064fa4..0000000
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * 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.schema;
-
-import java.util.Arrays;
-import java.util.UUID;
-import org.apache.ignite.internal.schema.row.RowAssembler;
-import org.junit.jupiter.api.Test;
-
-import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
-import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
-import static org.apache.ignite.internal.schema.NativeTypes.INTEGER;
-import static org.apache.ignite.internal.schema.NativeTypes.SHORT;
-import static org.apache.ignite.internal.schema.NativeTypes.STRING;
-import static org.apache.ignite.internal.schema.NativeTypes.UUID;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-
-/**
- * Validate row layout for different schema configurations.
- */
-public class RowAssemblerTest {
-    /** Uuid test value. */
-    public final java.util.UUID uuidVal = new UUID(-5204230847775358097L, 4916207022290092939L);
-
-    /** Table ID test value. */
-    public final java.util.UUID tableId = java.util.UUID.randomUUID();
-
-    /**
-     * Validate row layout for schema of fix-len non-null key and fix-len nullable value.
-     */
-    @Test
-    public void fixedKeyFixedNullableValue() {
-        Column[] keyCols = new Column[] {new Column("keyIntCol", INTEGER, false)};
-        Column[] valCols = new Column[] {new Column("valIntCol", INTEGER, true)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendInt(33);
-            asm.appendInt(-71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 122, 0, -10, 54, 5, 7, 5, 33, 0, 0, 0, 6, 0, -71, -1, -1, -1}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendInt(-33);
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 122, 0, 61, 0, -79, 50, 5, -33, -1, -1, -1, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendInt(-33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 123, 0, 61, 0, -79, 50, 5, -33, -1, -1, -1}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len non-null key and fix-len non-null value.
-     */
-    @Test
-    public void fixedKeyFixedValue() {
-        Column[] keyCols = new Column[] {new Column("keyShortCol", SHORT, false)};
-        Column[] valCols = new Column[] {new Column("valShortCol", SHORT, false)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        { // With value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)33);
-            asm.appendShort((short)71L);
-
-            assertRowBytesEquals(new byte[] {42, 0, 126, 0, 1, -101, 57, -89, 3, 33, 0, 3, 71, 0}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)-33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 127, 0, 83, 62, 65, -105, 3, -33, -1}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len non-null key and var-len nullable value.
-     */
-    @Test
-    public void fixedKeyVarlenNullableValue() {
-        Column[] keyCols = new Column[] {new Column("keyShortCol", SHORT, false)};
-        Column[] valCols = new Column[] {new Column("valStrCol", STRING, true)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendShort((short)33);
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 106, 0, 1, -101, 57, -89, 3, 33, 0, 7, 0, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)33);
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 122, 0, 1, -101, 57, -89, 3, 33, 0, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 123, 0, 1, -101, 57, -89, 3, 33, 0}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len non-null key and var-len non-null value.
-     */
-    @Test
-    public void fixedKeyVarlenValue() {
-        Column[] keyCols = new Column[] {new Column("keyShortCol", SHORT, false)};
-        Column[] valCols = new Column[] {new Column("valStrCol", STRING, false)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendShort((short)33);
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 110, 0, 1, -101, 57, -89, 3, 33, 0, 6, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 127, 0, 1, -101, 57, -89, 3, 33, 0}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len nullable key and fix-len non-null value.
-     */
-    @Test
-    public void fixedNullableKeyFixedValue() {
-        Column[] keyCols = new Column[] {new Column("keyShortCol", SHORT, true)};
-        Column[] valCols = new Column[] {new Column("valByteCol", BYTE, false)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)-33);
-            asm.appendByte((byte)71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 124, 0, 83, 62, 65, -105, 4, 0, -33, -1, 2, 71}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendByte((byte)-71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 124, 0, 5, 93, -52, 2, 2, 1, 2, -71}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 125, 0, 1, -101, 57, -89, 4, 0, 33, 0}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len nullable key and fix-len nullable value.
-     */
-    @Test
-    public void fixedNullableKeyFixedNullableValue() {
-        Column[] keyCols = new Column[] {new Column("keyShortCol", SHORT, true)};
-        Column[] valCols = new Column[] {new Column("valShortCol", SHORT, true)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)1133);
-            asm.appendShort((short)1071);
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, -100, -86, -70, -80, 4, 0, 109, 4, 4, 0, 47, 4}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendShort((short)1171);
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 4, 0, -109, 4}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)1133);
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, -100, -86, -70, -80, 4, 0, 109, 4, 2, 1}, asm.build());
-        }
-
-        { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendShort((short)1133);
-
-            assertRowBytesEquals(new byte[] {42, 0, 121, 0, -100, -86, -70, -80, 4, 0, 109, 4}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len nullable key and var-len nullable value.
-     */
-    @Test
-    public void fixedNullableKeyVarlenNullableValue() {
-        Column[] keyCols = new Column[] {new Column("keyIntCol", INTEGER, true)};
-        Column[] valCols = new Column[] {new Column("valStrCol", STRING, true)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendInt(-33);
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 61, 0, -79, 50, 6, 0, -33, -1, -1, -1, 7, 0, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendNull();
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 5, 93, -52, 2, 2, 1, 7, 0, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendInt(33);
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, -10, 54, 5, 7, 6, 0, 33, 0, 0, 0, 2, 1}, asm.build());
-        }
-
-        { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendInt(33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 121, 0, -10, 54, 5, 7, 6, 0, 33, 0, 0, 0}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of fix-len nullable key and var-len non-null value.
-     */
-    @Test
-    public void fixedNullableKeyVarlenValue() {
-        Column[] keyCols = new Column[] {new Column("keyByteCol", BYTE, true)};
-        Column[] valCols = new Column[] {new Column("valStrCol", STRING, false)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendByte((byte)33);
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 108, 0, 116, -97, 78, -100, 3, 0, 33, 6, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendNull();
-            asm.appendString("val");
-
-            assertRowBytesEquals(new byte[] {42, 0, 108, 0, 5, 93, -52, 2, 2, 1, 6, 1, 0, 118, 97, 108}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendByte((byte)33);
-
-            assertRowBytesEquals(new byte[] {42, 0, 125, 0, 116, -97, 78, -100, 3, 0, 33}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len non-null key and fix-len nullable value.
-     */
-    @Test
-    public void varlenKeyFixedNullableValue() {
-        Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, false)};
-        Column[] valCols = new Column[] {new Column("valUuidCol", UUID, true)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendUuid(uuidVal);
-
-            assertRowBytesEquals(new byte[] {
-                42, 0, 114, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121,
-                18, 0, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 114, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 115, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len non-null key and fix-len non-null value.
-     */
-    @Test
-    public void varlenKeyFixedValue() {
-        Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, false)};
-        Column[] valCols = new Column[] {new Column("valUuidCol", UUID, false)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendUuid(uuidVal);
-
-            assertRowBytesEquals(new byte[] {
-                42, 0, 118, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121,
-                17, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 119, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len non-null key and var-len nullable value.
-     */
-    @Test
-    public void varlenKeyVarlenNullableValue() {
-        Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, false)};
-        Column[] valCols = new Column[] {new Column("valBytesCol", BYTES, true)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
-
-            asm.appendString("key");
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 98, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 8, 0, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 114, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 115, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len non-null key and var-len non-null value.
-     */
-    @Test
-    public void varlenKeyVarlenValue() {
-        Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, false)};
-        Column[] valCols = new Column[] {new Column("valBytesCol", BYTES, false)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
-
-            asm.appendString("key");
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 102, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 7, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 119, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len nullable key and fix-len nullable value.
-     */
-    @Test
-    public void varlenNullableKeyFixedNullableValue() {
-        Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, true)};
-        Column[] valCols = new Column[] {new Column("valShortCol", SHORT, true)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendShort((short)-71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 112, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 4, 0, -71, -1}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendShort((short)71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 4, 0, 71, 0}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 112, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 2, 1}, asm.build());
-        }
-
-        { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 113, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len nullable key and fix-len non-null value.
-     */
-    @Test
-    public void varlenNullableKeyFixedValue() {
-        Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, true)};
-        Column[] valCols = new Column[] {new Column("valShortCol", SHORT, false)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendShort((short)-71L);
-
-            assertRowBytesEquals(new byte[] {42, 0, 116, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 3, -71, -1}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendShort((short)71);
-
-            assertRowBytesEquals(new byte[] {42, 0, 124, 0, 5, 93, -52, 2, 2, 1, 3, 71, 0}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 117, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len nullable key and var-len nullable value.
-     */
-    @Test
-    public void varlenNullableKeyVarlenNullableValue() {
-        Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, true)};
-        Column[] valCols = new Column[] {new Column("valBytesCol", BYTES, true)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
-
-            asm.appendString("key");
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 96, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 8, 0, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendNull();
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 5, 93, -52, 2, 2, 1, 8, 0, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 112, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 2, 1}, asm.build());
-        }
-
-        { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
-
-            asm.appendNull();
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 113, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for schema of var-len nullable key and var-len non-null value.
-     */
-    @Test
-    public void varlenNullableKeyVarlenValue() {
-        Column[] keyCols = new Column[] {new Column("keyStrCol", STRING, true)};
-        Column[] valCols = new Column[] {new Column("valBytesCol", BYTES, false)};
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
-
-            asm.appendString("key");
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 100, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 7, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
-
-            asm.appendNull();
-            asm.appendBytes(new byte[] {-1, 1, 0, 120});
-
-            assertRowBytesEquals(new byte[] {42, 0, 108, 0, 5, 93, -52, 2, 2, 1, 7, 1, 0, -1, 1, 0, 120}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendString("key");
-
-            assertRowBytesEquals(new byte[] {42, 0, 117, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
-        }
-    }
-
-    /**
-     * Validate row layout for key\value columns of different types.
-     */
-    @Test
-    public void mixedTypes() {
-        Column[] keyCols = new Column[] {
-            new Column("keyShortCol", SHORT, false),
-            new Column("keyStrCol", STRING, false)
-        };
-        Column[] valCols = new Column[] {
-            new Column("valIntCol", INTEGER, true),
-            new Column("valStrCol", STRING, true)
-        };
-
-        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
-
-        {
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
-
-            asm.appendShort((short)33);
-            asm.appendString("keystr");
-            asm.appendInt(73);
-            asm.appendString("valstr");
-
-            assertRowBytesEquals(new byte[] {
-                42, 0, 98, 0, 5, -39, 55, 59,
-                11, 1, 2, 33, 0, 107, 101, 121, 115, 116, 114,
-                14, 0, 1, 4, 73, 0, 0, 0, 118, 97, 108, 115, 116, 114}, asm.build());
-        }
-
-        { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendShort((short)33);
-            asm.appendString("keystr2");
-            asm.appendNull();
-            asm.appendNull();
-
-            assertRowBytesEquals(new byte[] {
-                42, 0, 114, 0, -80, -78, -91, 1,
-                12, 1, 2, 33, 0, 107, 101, 121, 115, 116, 114, 50,
-                2, 3}, asm.build());
-        }
-
-        { // No value.
-            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
-
-            asm.appendShort((short)33);
-            asm.appendString("keystr");
-
-            assertRowBytesEquals(new byte[] {
-                42, 0, 115, 0, 5, -39, 55, 59,
-                11, 1, 2, 33, 0, 107, 101, 121, 115, 116, 114,}, asm.build());
-        }
-    }
-
-    /**
-     * @param expected Expected row bytes.
-     * @param actual Actual row bytes.
-     */
-    private void assertRowBytesEquals(byte[] expected, byte[] actual) {
-        assertArrayEquals(expected, actual, Arrays.toString(actual));
-    }
-}
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
index 5b87c56..94e0848 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
@@ -263,29 +263,45 @@ public class RowTest {
 
         int nonNullVarLenKeyCols = 0;
         int nonNullVarLenValCols = 0;
+        int nonNullVarLenKeySize = 0;
+        int nonNullVarLenValSize = 0;
 
         for (int i = 0; i < vals.length; i++) {
             NativeTypeSpec type = schema.column(i).type().spec();
 
             if (vals[i] != null && !type.fixedLength()) {
                 if (type == NativeTypeSpec.BYTES) {
-                    if (schema.isKeyColumn(i))
+                    byte[] val = (byte[])vals[i];
+                    if (schema.isKeyColumn(i)) {
                         nonNullVarLenKeyCols++;
-                    else
+                        nonNullVarLenKeySize += val.length;
+                    }
+                    else {
                         nonNullVarLenValCols++;
+                        nonNullVarLenValSize += val.length;
+                    }
                 }
                 else if (type == NativeTypeSpec.STRING) {
-                    if (schema.isKeyColumn(i))
+                    if (schema.isKeyColumn(i)) {
                         nonNullVarLenKeyCols++;
-                    else
+                        nonNullVarLenKeySize += RowAssembler.utf8EncodedLength((CharSequence)vals[i]);
+                    }
+                    else {
                         nonNullVarLenValCols++;
+                        nonNullVarLenValSize += RowAssembler.utf8EncodedLength((CharSequence)vals[i]);
+                    }
                 }
                 else
                     throw new IllegalStateException("Unsupported variable-length type: " + type);
             }
         }
 
-        RowAssembler asm = new RowAssembler(schema, nonNullVarLenKeyCols, nonNullVarLenValCols);
+        RowAssembler asm = new RowAssembler(
+            schema,
+            nonNullVarLenKeySize,
+            nonNullVarLenKeyCols,
+            nonNullVarLenValSize,
+            nonNullVarLenValCols);
 
         for (int i = 0; i < vals.length; i++) {
             if (vals[i] == null)
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
index 2966b92..2be4efb 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
@@ -106,14 +106,12 @@ public class TupleMarshallerImpl implements TupleMarshaller {
 
             if (val == null)
                 chunk.hasNulls = true;
+            else if (col.type().spec().fixedLength())
+                chunk.payloadLen += col.type().sizeInBytes();
             else {
-                if (col.type().spec().fixedLength())
-                    chunk.payloadLen += col.type().sizeInBytes();
-                else {
-                    chunk.nonNullVarlen++;
+                chunk.nonNullVarlen++;
 
-                    chunk.payloadLen += getValueSize(val, col.type());
-                }
+                chunk.payloadLen += getValueSize(val, col.type());
             }
         }
 

[ignite-3] 04/15: Fix tests.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 87f9fe57e8468c861f3196f5e96b81fb27679651
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Thu Jun 3 16:42:59 2021 +0300

    Fix tests.
---
 .../ignite/internal/schema/RowAssemblerTest.java   | 133 ++++++++++-----------
 1 file changed, 66 insertions(+), 67 deletions(-)

diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
index 82a7e3b..6064fa4 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
@@ -56,7 +56,7 @@ public class RowAssemblerTest {
             asm.appendInt(33);
             asm.appendInt(-71);
 
-            assertRowBytesEquals(new byte[] {42, 0, 26, 0, 33, 0, 0, 0, 8, 0, 0, 0, 33, 0, 0, 0, 9, 0, 0, 0, 0, -71, -1, -1, -1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 122, 0, -10, 54, 5, 7, 5, 33, 0, 0, 0, 6, 0, -71, -1, -1, -1}, asm.build());
         }
 
         { // Null value.
@@ -65,7 +65,7 @@ public class RowAssemblerTest {
             asm.appendInt(-33);
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 26, 0, -33, -1, -1, -1, 8, 0, 0, 0, -33, -1, -1, -1, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 122, 0, 61, 0, -79, 50, 5, -33, -1, -1, -1, 2, 1}, asm.build());
         }
 
         { // No value.
@@ -73,7 +73,7 @@ public class RowAssemblerTest {
 
             asm.appendInt(-33);
 
-            assertRowBytesEquals(new byte[] {42, 0, 27, 0, -33, -1, -1, -1, 8, 0, 0, 0, -33, -1, -1, -1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 123, 0, 61, 0, -79, 50, 5, -33, -1, -1, -1}, asm.build());
         }
     }
 
@@ -93,7 +93,7 @@ public class RowAssemblerTest {
             asm.appendShort((short)33);
             asm.appendShort((short)71L);
 
-            assertRowBytesEquals(new byte[] {42, 0, 30, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 6, 0, 0, 0, 71, 0}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 126, 0, 1, -101, 57, -89, 3, 33, 0, 3, 71, 0}, asm.build());
         }
 
         { // No value.
@@ -101,7 +101,7 @@ public class RowAssemblerTest {
 
             asm.appendShort((short)-33);
 
-            assertRowBytesEquals(new byte[] {42, 0, 31, 0, -33, -1, -1, -1, 6, 0, 0, 0, -33, -1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 127, 0, 83, 62, 65, -105, 3, -33, -1}, asm.build());
         }
     }
 
@@ -118,10 +118,10 @@ public class RowAssemblerTest {
         {
             RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
 
-            asm.appendShort((short)-33);
+            asm.appendShort((short)33);
             asm.appendString("val");
 
-            assertRowBytesEquals(new byte[] {42, 0, 10, 0, -33, -1, -1, -1, 6, 0, 0, 0, -33, -1, 12, 0, 0, 0, 0, 1, 0, 9, 0, 118, 97, 108}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 106, 0, 1, -101, 57, -89, 3, 33, 0, 7, 0, 1, 0, 118, 97, 108}, asm.build());
         }
 
         { // Null value.
@@ -130,7 +130,7 @@ public class RowAssemblerTest {
             asm.appendShort((short)33);
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 26, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 122, 0, 1, -101, 57, -89, 3, 33, 0, 2, 1}, asm.build());
         }
 
         { // No value.
@@ -138,7 +138,7 @@ public class RowAssemblerTest {
 
             asm.appendShort((short)33);
 
-            assertRowBytesEquals(new byte[] {42, 0, 27, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 123, 0, 1, -101, 57, -89, 3, 33, 0}, asm.build());
         }
     }
 
@@ -155,10 +155,10 @@ public class RowAssemblerTest {
         {
             RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
 
-            asm.appendShort((short)-33);
+            asm.appendShort((short)33);
             asm.appendString("val");
 
-            assertRowBytesEquals(new byte[] {42, 0, 14, 0, -33, -1, -1, -1, 6, 0, 0, 0, -33, -1, 11, 0, 0, 0, 1, 0, 8, 0, 118, 97, 108}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 110, 0, 1, -101, 57, -89, 3, 33, 0, 6, 1, 0, 118, 97, 108}, asm.build());
         }
 
         { // No value.
@@ -166,7 +166,7 @@ public class RowAssemblerTest {
 
             asm.appendShort((short)33);
 
-            assertRowBytesEquals(new byte[] {42, 0, 31, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 127, 0, 1, -101, 57, -89, 3, 33, 0}, asm.build());
         }
     }
 
@@ -186,7 +186,7 @@ public class RowAssemblerTest {
             asm.appendShort((short)-33);
             asm.appendByte((byte)71);
 
-            assertRowBytesEquals(new byte[] {42, 0, 28, 0, -33, -1, -1, -1, 7, 0, 0, 0, 0, -33, -1, 5, 0, 0, 0, 71}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 124, 0, 83, 62, 65, -105, 4, 0, -33, -1, 2, 71}, asm.build());
         }
 
         { // Null key.
@@ -195,7 +195,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendByte((byte)-71);
 
-            assertRowBytesEquals(new byte[] {42, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, -71}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 124, 0, 5, 93, -52, 2, 2, 1, 2, -71}, asm.build());
         }
 
         { // No value.
@@ -203,7 +203,7 @@ public class RowAssemblerTest {
 
             asm.appendShort((short)33);
 
-            assertRowBytesEquals(new byte[] {42, 0, 29, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 33, 0}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 125, 0, 1, -101, 57, -89, 4, 0, 33, 0}, asm.build());
         }
     }
 
@@ -220,10 +220,10 @@ public class RowAssemblerTest {
         {
             RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
-            asm.appendShort((short)-1133);
-            asm.appendShort((short)-1071);
+            asm.appendShort((short)1133);
+            asm.appendShort((short)1071);
 
-            assertRowBytesEquals(new byte[] {42, 0, 24, 0, -109, -5, -1, -1, 7, 0, 0, 0, 0, -109, -5, 7, 0, 0, 0, 0, -47, -5}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 120, 0, -100, -86, -70, -80, 4, 0, 109, 4, 4, 0, 47, 4}, asm.build());
         }
 
         { // Null key.
@@ -232,7 +232,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendShort((short)1171);
 
-            assertRowBytesEquals(new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 0, -109, 4}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 4, 0, -109, 4}, asm.build());
         }
 
         { // Null value.
@@ -241,7 +241,7 @@ public class RowAssemblerTest {
             asm.appendShort((short)1133);
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 24, 0, 109, 4, 0, 0, 7, 0, 0, 0, 0, 109, 4, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 120, 0, -100, -86, -70, -80, 4, 0, 109, 4, 2, 1}, asm.build());
         }
 
         { // Null both.
@@ -250,7 +250,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
         }
 
         { // No value.
@@ -258,7 +258,7 @@ public class RowAssemblerTest {
 
             asm.appendShort((short)1133);
 
-            assertRowBytesEquals(new byte[] {42, 0, 25, 0, 109, 4, 0, 0, 7, 0, 0, 0, 0, 109, 4}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 121, 0, -100, -86, -70, -80, 4, 0, 109, 4}, asm.build());
         }
     }
 
@@ -278,7 +278,7 @@ public class RowAssemblerTest {
             asm.appendInt(-33);
             asm.appendString("val");
 
-            assertRowBytesEquals(new byte[] {42, 0, 8, 0, -33, -1, -1, -1, 9, 0, 0, 0, 0, -33, -1, -1, -1, 12, 0, 0, 0, 0, 1, 0, 9, 0, 118, 97, 108}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 61, 0, -79, 50, 6, 0, -33, -1, -1, -1, 7, 0, 1, 0, 118, 97, 108}, asm.build());
         }
 
         { // Null key.
@@ -287,7 +287,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendString("val");
 
-            assertRowBytesEquals(new byte[] {42, 0, 8, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 12, 0, 0, 0, 0, 1, 0, 9, 0, 118, 97, 108}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 5, 93, -52, 2, 2, 1, 7, 0, 1, 0, 118, 97, 108}, asm.build());
         }
 
         { // Null value.
@@ -296,7 +296,7 @@ public class RowAssemblerTest {
             asm.appendInt(33);
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 24, 0, 33, 0, 0, 0, 9, 0, 0, 0, 0, 33, 0, 0, 0, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 120, 0, -10, 54, 5, 7, 6, 0, 33, 0, 0, 0, 2, 1}, asm.build());
         }
 
         { // Null both.
@@ -305,7 +305,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
         }
 
         { // No value.
@@ -313,7 +313,7 @@ public class RowAssemblerTest {
 
             asm.appendInt(33);
 
-            assertRowBytesEquals(new byte[] {42, 0, 25, 0, 33, 0, 0, 0, 9, 0, 0, 0, 0, 33, 0, 0, 0}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 121, 0, -10, 54, 5, 7, 6, 0, 33, 0, 0, 0}, asm.build());
         }
     }
 
@@ -330,10 +330,10 @@ public class RowAssemblerTest {
         {
             RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
 
-            asm.appendByte((byte)-33);
+            asm.appendByte((byte)33);
             asm.appendString("val");
 
-            assertRowBytesEquals(new byte[] {42, 0, 12, 0, -33, -1, -1, -1, 6, 0, 0, 0, 0, -33, 11, 0, 0, 0, 1, 0, 8, 0, 118, 97, 108}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 108, 0, 116, -97, 78, -100, 3, 0, 33, 6, 1, 0, 118, 97, 108}, asm.build());
         }
 
         { // Null key.
@@ -342,7 +342,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendString("val");
 
-            assertRowBytesEquals(new byte[] {42, 0, 12, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 11, 0, 0, 0, 1, 0, 8, 0, 118, 97, 108}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 108, 0, 5, 93, -52, 2, 2, 1, 6, 1, 0, 118, 97, 108}, asm.build());
         }
 
         { // No value.
@@ -350,7 +350,7 @@ public class RowAssemblerTest {
 
             asm.appendByte((byte)33);
 
-            assertRowBytesEquals(new byte[] {42, 0, 29, 0, 33, 0, 0, 0, 6, 0, 0, 0, 0, 33}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 125, 0, 116, -97, 78, -100, 3, 0, 33}, asm.build());
         }
     }
 
@@ -371,8 +371,8 @@ public class RowAssemblerTest {
             asm.appendUuid(uuidVal);
 
             assertRowBytesEquals(new byte[] {
-                42, 0, 18, 0, 95, -98, 1, 0, 11, 0, 0, 0, 1, 0, 8, 0, 107, 101, 121,
-                21, 0, 0, 0, 0, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73}, asm.build());
+                42, 0, 114, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121,
+                18, 0, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73}, asm.build());
         }
 
         { // Null value.
@@ -381,7 +381,7 @@ public class RowAssemblerTest {
             asm.appendString("key");
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 18, 0, 95, -98, 1, 0, 11, 0, 0, 0, 1, 0, 8, 0, 107, 101, 121, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 114, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 2, 1}, asm.build());
         }
 
         { // No value.
@@ -389,7 +389,7 @@ public class RowAssemblerTest {
 
             asm.appendString("key");
 
-            assertRowBytesEquals(new byte[] {42, 0, 19, 0, 95, -98, 1, 0, 11, 0, 0, 0, 1, 0, 8, 0, 107, 101, 121}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 115, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
         }
     }
 
@@ -410,8 +410,8 @@ public class RowAssemblerTest {
             asm.appendUuid(uuidVal);
 
             assertRowBytesEquals(new byte[] {
-                42, 0, 22, 0, 95, -98, 1, 0, 11, 0, 0, 0, 1, 0, 8, 0, 107, 101, 121,
-                20, 0, 0, 0, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73}, asm.build());
+                42, 0, 118, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121,
+                17, -117, -61, -31, 85, 61, -32, 57, 68, 111, 67, 56, -3, -99, -37, -58, -73}, asm.build());
         }
 
         { // No value.
@@ -419,7 +419,7 @@ public class RowAssemblerTest {
 
             asm.appendString("key");
 
-            assertRowBytesEquals(new byte[] {42, 0, 23, 0, 95, -98, 1, 0, 11, 0, 0, 0, 1, 0, 8, 0, 107, 101, 121}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 119, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
         }
     }
 
@@ -448,7 +448,7 @@ public class RowAssemblerTest {
             asm.appendString("key");
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 106, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 2, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 114, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 2, 1}, asm.build());
         }
 
         { // No value.
@@ -456,7 +456,7 @@ public class RowAssemblerTest {
 
             asm.appendString("key");
 
-            assertRowBytesEquals(new byte[] {42, 0, 107, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 115, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
         }
     }
 
@@ -476,7 +476,7 @@ public class RowAssemblerTest {
             asm.appendString("key");
             asm.appendBytes(new byte[] {-1, 1, 0, 120});
 
-            assertRowBytesEquals(new byte[] {42, 0, 6, 0, 95, -98, 1, 0, 11, 0, 0, 0, 1, 0, 8, 0, 107, 101, 121, 12, 0, 0, 0, 1, 0, 8, 0, -1, 1, 0, 120}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 102, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 7, 1, 0, -1, 1, 0, 120}, asm.build());
         }
 
         { // No value.
@@ -484,7 +484,7 @@ public class RowAssemblerTest {
 
             asm.appendString("key");
 
-            assertRowBytesEquals(new byte[] {42, 0, 23, 0, 95, -98, 1, 0, 11, 0, 0, 0, 1, 0, 8, 0, 107, 101, 121}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 119, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
         }
     }
 
@@ -504,7 +504,7 @@ public class RowAssemblerTest {
             asm.appendString("key");
             asm.appendShort((short)-71);
 
-            assertRowBytesEquals(new byte[] {42, 0, 104, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 4, 0, -71, -1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 112, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 4, 0, -71, -1}, asm.build());
         }
 
         { // Null key.
@@ -513,7 +513,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendShort((short)71);
 
-            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 5, 93, -52, 2, 2, 1, 4, 0, 71, 0}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 4, 0, 71, 0}, asm.build());
         }
 
         { // Null value.
@@ -522,7 +522,7 @@ public class RowAssemblerTest {
             asm.appendString("key");
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 104, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 2, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 112, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 2, 1}, asm.build());
         }
 
         { // Null both.
@@ -531,7 +531,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
         }
 
         { // No value.
@@ -539,7 +539,7 @@ public class RowAssemblerTest {
 
             asm.appendString("key");
 
-            assertRowBytesEquals(new byte[] {42, 0, 105, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 113, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
         }
     }
 
@@ -559,7 +559,7 @@ public class RowAssemblerTest {
             asm.appendString("key");
             asm.appendShort((short)-71L);
 
-            assertRowBytesEquals(new byte[] {42, 0, 20, 0, 95, -98, 1, 0, 12, 0, 0, 0, 0, 1, 0, 9, 0, 107, 101, 121, 6, 0, 0, 0, -71, -1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 116, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 3, -71, -1}, asm.build());
         }
 
         { // Null key.
@@ -568,7 +568,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendShort((short)71);
 
-            assertRowBytesEquals(new byte[] {42, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 6, 0, 0, 0, 71, 0}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 124, 0, 5, 93, -52, 2, 2, 1, 3, 71, 0}, asm.build());
         }
 
         { // No value.
@@ -576,7 +576,7 @@ public class RowAssemblerTest {
 
             asm.appendString("key");
 
-            assertRowBytesEquals(new byte[] {42, 0, 21, 0, 95, -98, 1, 0, 12, 0, 0, 0, 0, 1, 0, 9, 0, 107, 101, 121}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 117, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
         }
     }
 
@@ -596,7 +596,7 @@ public class RowAssemblerTest {
             asm.appendString("key");
             asm.appendBytes(new byte[] {-1, 1, 0, 120});
 
-            assertRowBytesEquals(new byte[] {42, 0, 0, 0, 95, -98, 1, 0, 12, 0, 0, 0, 0, 1, 0, 9, 0, 107, 101, 121, 13, 0, 0, 0, 0, 1, 0, 9, 0, -1, 1, 0, 120}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 96, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 8, 0, 1, 0, -1, 1, 0, 120}, asm.build());
         }
 
         { // Null key.
@@ -605,7 +605,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendBytes(new byte[] {-1, 1, 0, 120});
 
-            assertRowBytesEquals(new byte[] {42, 0, 8, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 13, 0, 0, 0, 0, 1, 0, 9, 0, -1, 1, 0, 120}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 5, 93, -52, 2, 2, 1, 8, 0, 1, 0, -1, 1, 0, 120}, asm.build());
         }
 
         { // Null value.
@@ -614,7 +614,7 @@ public class RowAssemblerTest {
             asm.appendString("key");
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 16, 0, 95, -98, 1, 0, 12, 0, 0, 0, 0, 1, 0, 9, 0, 107, 101, 121, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 112, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 2, 1}, asm.build());
         }
 
         { // Null both.
@@ -623,7 +623,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 120, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
         }
 
         { // No value.
@@ -631,7 +631,7 @@ public class RowAssemblerTest {
 
             asm.appendString("key");
 
-            assertRowBytesEquals(new byte[] {42, 0, 17, 0, 95, -98, 1, 0, 12, 0, 0, 0, 0, 1, 0, 9, 0, 107, 101, 121}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 113, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
         }
     }
 
@@ -651,7 +651,7 @@ public class RowAssemblerTest {
             asm.appendString("key");
             asm.appendBytes(new byte[] {-1, 1, 0, 120});
 
-            assertRowBytesEquals(new byte[] {42, 0, 4, 0, 95, -98, 1, 0, 12, 0, 0, 0, 0, 1, 0, 9, 0, 107, 101, 121, 12, 0, 0, 0, 1, 0, 8, 0, -1, 1, 0, 120}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 100, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 7, 1, 0, -1, 1, 0, 120}, asm.build());
         }
 
         { // Null key.
@@ -660,7 +660,7 @@ public class RowAssemblerTest {
             asm.appendNull();
             asm.appendBytes(new byte[] {-1, 1, 0, 120});
 
-            assertRowBytesEquals(new byte[] {42, 0, 12, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 12, 0, 0, 0, 1, 0, 8, 0, -1, 1, 0, 120}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 108, 0, 5, 93, -52, 2, 2, 1, 7, 1, 0, -1, 1, 0, 120}, asm.build());
         }
 
         { // No value.
@@ -668,7 +668,7 @@ public class RowAssemblerTest {
 
             asm.appendString("key");
 
-            assertRowBytesEquals(new byte[] {42, 0, 21, 0, 95, -98, 1, 0, 12, 0, 0, 0, 0, 1, 0, 9, 0, 107, 101, 121}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 117, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
         }
     }
 
@@ -697,9 +697,9 @@ public class RowAssemblerTest {
             asm.appendString("valstr");
 
             assertRowBytesEquals(new byte[] {
-                42, 0, 2, 0, -110, -109, 94, -68,
-                16, 0, 0, 0, 1, 0, 10, 0, 33, 0, 107, 101, 121, 115, 116, 114,
-                19, 0, 0, 0, 0, 1, 0, 13, 0, 73, 0, 0, 0, 118, 97, 108, 115, 116, 114}, asm.build());
+                42, 0, 98, 0, 5, -39, 55, 59,
+                11, 1, 2, 33, 0, 107, 101, 121, 115, 116, 114,
+                14, 0, 1, 4, 73, 0, 0, 0, 118, 97, 108, 115, 116, 114}, asm.build());
         }
 
         { // Null value.
@@ -711,9 +711,9 @@ public class RowAssemblerTest {
             asm.appendNull();
 
             assertRowBytesEquals(new byte[] {
-                42, 0, 18, 0, 32, 99, 115, -49,
-                17, 0, 0, 0, 1, 0, 10, 0, 33, 0, 107, 101, 121, 115, 116, 114, 50,
-                5, 0, 0, 0, 3}, asm.build());
+                42, 0, 114, 0, -80, -78, -91, 1,
+                12, 1, 2, 33, 0, 107, 101, 121, 115, 116, 114, 50,
+                2, 3}, asm.build());
         }
 
         { // No value.
@@ -723,9 +723,8 @@ public class RowAssemblerTest {
             asm.appendString("keystr");
 
             assertRowBytesEquals(new byte[] {
-                42, 0, 19, 0, -110, -109, 94, -68,
-                16, 0, 0, 0, 1, 0, 10, 0, 33, 0, 107, 101, 121, 115, 116, 114}, asm.build());
-
+                42, 0, 115, 0, 5, -39, 55, 59,
+                11, 1, 2, 33, 0, 107, 101, 121, 115, 116, 114,}, asm.build());
         }
     }
 

[ignite-3] 03/15: Optimize serialized row size.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 0d336b6ca459283d4184ceb2997b0a649bc392be
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Thu Jun 3 15:21:53 2021 +0300

    Optimize serialized row size.
---
 .../apache/ignite/internal/util/Constants.java}    |  37 +-
 .../apache/ignite/internal/schema/BinaryRow.java   |   8 +-
 .../ignite/internal/schema/ByteBufferRow.java      |  10 +-
 .../ignite/internal/schema/NativeTypeSpec.java     |   1 +
 .../org/apache/ignite/internal/schema/README.md    |   6 +-
 .../ignite/internal/schema/RowAssembler.java       | 605 ---------------------
 .../schema/marshaller/AbstractSerializer.java      |   4 +-
 .../internal/schema/marshaller/MarshallerUtil.java |   2 +-
 .../marshaller/asm/AsmSerializerGenerator.java     |  25 +-
 .../marshaller/reflection/FieldAccessor.java       |   4 +-
 .../marshaller/reflection/JavaSerializer.java      |  10 +-
 .../schema/marshaller/reflection/Marshaller.java   |   4 +-
 .../internal/schema/row/AbstractChunkWriter.java   | 228 ++++++++
 .../schema/{ => row}/ExpandableByteBuf.java        |  31 +-
 .../internal/schema/row/LongChunkWriter.java       |  78 +++
 .../ignite/internal/schema/{ => row}/Row.java      | 451 +++++++++------
 .../ignite/internal/schema/row/RowAssembler.java   | 485 +++++++++++++++++
 .../internal/schema/row/TinyChunkWriter.java       |  77 +++
 .../ignite/internal/schema/row/XXHash32.java       | 243 +++++++++
 .../internal/schema/ExpandableByteBufTest.java     |   1 +
 .../ignite/internal/schema/RowAssemblerTest.java   | 129 ++---
 .../org/apache/ignite/internal/schema/RowTest.java |  37 +-
 .../marshaller/reflection/FieldAccessorTest.java   |   4 +-
 .../ignite/distributed/ITDistributedTableTest.java |   8 +-
 .../internal/schema/marshaller/KVSerializer.java   |   2 +-
 .../schema/marshaller/RecordSerializer.java        |   2 +-
 .../schema/marshaller/TupleMarshaller.java         |   2 +-
 .../ignite/internal/table/KVBinaryViewImpl.java    |   2 +-
 .../apache/ignite/internal/table/KVViewImpl.java   |   2 +-
 .../ignite/internal/table/RecordViewImpl.java      |   2 +-
 .../ignite/internal/table/RowChunkAdapter.java     |   2 +-
 .../apache/ignite/internal/table/TableImpl.java    |   2 +-
 .../org/apache/ignite/internal/table/TableRow.java |   2 +-
 .../ignite/internal/table/TupleMarshallerImpl.java |  96 ++--
 .../raft/PartitionCommandListenerTest.java         |   8 +-
 35 files changed, 1597 insertions(+), 1013 deletions(-)

diff --git a/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/KVSerializer.java b/modules/core/src/main/java/org/apache/ignite/internal/util/Constants.java
similarity index 52%
copy from modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/KVSerializer.java
copy to modules/core/src/main/java/org/apache/ignite/internal/util/Constants.java
index 5c4f32d..cf24696 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/KVSerializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/Constants.java
@@ -15,32 +15,23 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.marshaller;
-
-import org.apache.ignite.internal.schema.Row;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+package org.apache.ignite.internal.util;
 
 /**
- * Key-value serializer interface.
+ * Utility class with magic constants.
  */
-public interface KVSerializer<K, V> {
-    /**
-     * @param key Key object to serialize.
-     * @param val Value object to serialize.
-     * @return Table row with columns serialized from given key-value pair.
-     */
-    Row serialize(@NotNull K key, V val);
+public final class Constants {
+    /** Bytes in kilo-byte  (IEC 80000-13).. */
+    public static final int KiB =  1024;
+
+    /** Bytes in mega-byte (IEC 80000-13). */
+    public static final int MiB =  1024 * KiB;
 
-    /**
-     * @param row Table row.
-     * @return Deserialized key object.
-     */
-    @NotNull K deserializeKey(@NotNull Row row);
+    /** Bytes in giga-byte (IEC 80000-13). */
+    public static final int GiB =  1024 * MiB;
 
-    /**
-     * @param row Table row.
-     * @return Deserialized value object.
-     */
-    @Nullable V deserializeValue(@NotNull Row row);
+    /** Stub. */
+    private Constants() {
+        //Noop.
+    }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
index 74be9fb..83a73e0 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
@@ -157,13 +157,11 @@ public interface BinaryRow {
         /** Flag indicates value chunk omits varlen table. */
         public static final int OMIT_VAL_VARTBL_FLAG = 1 << 4;
 
+        /** Flag indicates key chunk is written in Tiny format. */
         public static final int KEY_TYNY_FORMAT = 1 << 5;
 
-        public static final int KEY_LARGE_ROW_FORMAT = 1 << 6;
-
-        public static final int VAL_TYNY_FORMAT = 1 << 7;
-
-        public static final int VAL_LARGE_FORMAT = 1 << 8;
+        /** Flag indicates value chunk is written in Tiny format. */
+        public static final int VAL_TYNY_FORMAT = 1 << 6;
 
         /** Stub. */
         private RowFlags() {
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
index 9c9c81e..0f3b484 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
@@ -132,9 +132,7 @@ public class ByteBufferRow implements BinaryRow {
         final short flags = readShort(FLAGS_FIELD_OFFSET);
 
         final int off = KEY_CHUNK_OFFSET;
-        final int len = (flags & RowFlags.KEY_LARGE_ROW_FORMAT) != 0 ? readInteger(off) :
-            (flags & RowFlags.KEY_TYNY_FORMAT) != 0 ? readByte(off) :
-                readShort(off);
+        final int len = (flags & RowFlags.KEY_TYNY_FORMAT) == 0 ? readInteger(off) : (readByte(off) & 0xFF);
 
         try {
             return buf.limit(off + len).position(off).slice();
@@ -150,11 +148,9 @@ public class ByteBufferRow implements BinaryRow {
         final short flags = readShort(FLAGS_FIELD_OFFSET);
 
         int off = KEY_CHUNK_OFFSET +
-            ((flags & RowFlags.KEY_LARGE_ROW_FORMAT) != 0 ? readInteger(KEY_CHUNK_OFFSET) :
-            (flags & RowFlags.KEY_TYNY_FORMAT) != 0 ? readByte(KEY_CHUNK_OFFSET) : readShort(KEY_CHUNK_OFFSET));
+            ((flags & RowFlags.KEY_TYNY_FORMAT) == 0 ? readInteger(KEY_CHUNK_OFFSET) : (readByte(KEY_CHUNK_OFFSET) & 0xFF));
 
-        int len = hasValue() ? (flags & RowFlags.VAL_LARGE_FORMAT) != 0 ? readInteger(off) :
-            (flags & RowFlags.VAL_TYNY_FORMAT) != 0 ? readByte(off) : readShort(off) : 0;
+        int len = hasValue() ? (flags & RowFlags.VAL_TYNY_FORMAT) == 0 ? readInteger(off) : (readByte(off) & 0xFF) : 0;
 
         try {
             return buf.limit(off + len).position(off).slice();
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypeSpec.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypeSpec.java
index 75ebd5b..f853766 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypeSpec.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypeSpec.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.schema;
 
 import java.util.BitSet;
+import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.internal.tostring.S;
 
 /**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/README.md b/modules/schema/src/main/java/org/apache/ignite/internal/schema/README.md
index 1909628..10143c7 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/README.md
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/README.md
@@ -73,7 +73,7 @@ varsize columns multiplied by 2 (a single entry in the offsets table is 2 bytes)
 is calculated from the beginning of the chunk.
 
 ### Row construction and access
-To assemble a row with some schema, an instance of `org.apache.ignite.internal.schema.RowAssembler`
+To assemble a row with some schema, an instance of `org.apache.ignite.internal.schema.row.RowAssembler`
 must be used which provides the low-level API for building rows. When using the row assembler, the
 columns must be passed to the assembler in the internal schema sort order. Additionally, when constructing
 the instance of the assembler, the user should pre-calculate the size of the row to avoid extra array copies,
@@ -81,7 +81,7 @@ and the number of non-null varlen columns for key and value chunks. Less restric
 are provided by class (de)serializers and row builder, which take care of sizing and column order.
 
 To read column values of a row, one needs to construct a subclass of
-`org.apache.ignite.internal.schema.Row` which provides necessary logic to read arbitrary columns with
-type checking. For primitive types, `org.apache.ignite.internal.schema.Row` provides boxed and non-boxed
+`org.apache.ignite.internal.schema.row.Row` which provides necessary logic to read arbitrary columns with
+type checking. For primitive types, `org.apache.ignite.internal.schema.row.Row` provides boxed and non-boxed
 value methods to avoid boxing in scenarios where boxing can be avoided (deserialization of non-null columns to
 POJO primitives, for example).
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java
deleted file mode 100644
index 021d72b..0000000
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * 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.schema;
-
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.UUID;
-import org.apache.ignite.internal.schema.BinaryRow.RowFlags;
-
-import static org.apache.ignite.internal.schema.BinaryRow.RowFlags.OMIT_KEY_VARTBL_FLAG;
-import static org.apache.ignite.internal.schema.BinaryRow.RowFlags.OMIT_VAL_VARTBL_FLAG;
-import static org.apache.ignite.internal.schema.BinaryRow.VARLEN_COLUMN_OFFSET_FIELD_SIZE;
-import static org.apache.ignite.internal.schema.BinaryRow.VARLEN_TABLE_SIZE_FIELD_SIZE;
-
-/**
- * Utility class to build rows using column appending pattern. The external user of this class must consult
- * with the schema and provide the columns in strict internal column sort order during the row construction.
- * Additionally, the user of this class should pre-calculate the resulting row size when possible to avoid
- * unnecessary data copies. The assembler provides some utility methods to calculate the resulting row size
- * based on the number of null columns and size calculation for strings.
- *
- * @see #rowSize(Columns, int, int, Columns, int, int)
- * @see #rowChunkSize(Columns, int, int)
- * @see #utf8EncodedLength(CharSequence)
- */
-public class RowAssembler {
-    /** Schema. */
-    private final SchemaDescriptor schema;
-
-    /** The number of non-null varlen columns in values chunk. */
-    private final int nonNullVarlenValCols;
-
-    /** Target byte buffer to write to. */
-    private final ExpandableByteBuf buf;
-
-    private final int valOffSize;
-
-    /** Current columns chunk. */
-    private Columns curCols;
-
-    /** Current field index (the field is unset). */
-    private int curCol;
-
-    /** Index of the current varlen table entry. Incremented each time non-null varlen column is appended. */
-    private int curVarlenTblEntry;
-
-    /** Current offset for the next column to be appended. */
-    private int curOff;
-
-    /** Base offset of the current chunk */
-    private int baseOff;
-
-    /** Offset of the null map for current chunk. */
-    private int nullMapOff;
-
-    /** Offset of the varlen table for current chunk. */
-    private int varlenTblChunkOff;
-
-    private int adaptiveItemSize;
-
-    /** Row hashcode. */
-    private int keyHash;
-
-    /** Flags. */
-    private short flags;
-
-    /** Charset encoder for strings. Initialized lazily. */
-    private CharsetEncoder strEncoder;
-
-    /**
-     * @param nonNullVarlenCols Number of non-null varlen columns.
-     * @return Total size of the varlen table.
-     */
-    public static int varlenTableChunkSize(int nonNullVarlenCols) {
-        return nonNullVarlenCols == 0 ? 0 :
-            VARLEN_TABLE_SIZE_FIELD_SIZE + nonNullVarlenCols * VARLEN_COLUMN_OFFSET_FIELD_SIZE;
-    }
-
-    /**
-     * Calculates encoded string length.
-     *
-     * @param seq Char sequence.
-     * @return Encoded string length.
-     * @implNote This implementation is not tolerant to malformed char sequences.
-     */
-    public static int utf8EncodedLength(CharSequence seq) {
-        int cnt = 0;
-
-        for (int i = 0, len = seq.length(); i < len; i++) {
-            char ch = seq.charAt(i);
-
-            if (ch <= 0x7F)
-                cnt++;
-            else if (ch <= 0x7FF)
-                cnt += 2;
-            else if (Character.isHighSurrogate(ch)) {
-                cnt += 4;
-                ++i;
-            }
-            else
-                cnt += 3;
-        }
-
-        return cnt;
-    }
-
-    /**
-     * @param keyCols Key columns.
-     * @param nonNullVarlenKeyCols Number of non-null varlen columns in key chunk.
-     * @param nonNullVarlenKeySize Size of non-null varlen columns in key chunk.
-     * @param valCols Value columns.
-     * @param nonNullVarlenValCols Number of non-null varlen columns in value chunk.
-     * @param nonNullVarlenValSize Size of non-null varlen columns in value chunk.
-     * @return Total row size.
-     */
-    public static int rowSize(
-        Columns keyCols,
-        int nonNullVarlenKeyCols,
-        int nonNullVarlenKeySize,
-        Columns valCols,
-        int nonNullVarlenValCols,
-        int nonNullVarlenValSize
-    ) {
-        return BinaryRow.KEY_CHUNK_OFFSET /* Header size */ +
-            rowChunkSize(keyCols, nonNullVarlenKeyCols, nonNullVarlenKeySize) +
-            rowChunkSize(valCols, nonNullVarlenValCols, nonNullVarlenValSize);
-    }
-
-    /**
-     * @param cols Columns.
-     * @param nonNullVarlenCols Number of non-null varlen columns in chunk.
-     * @param nonNullVarlenSize Size of non-null varlen columns in chunk.
-     * @return Row's chunk size.
-     */
-    static int rowChunkSize(Columns cols, int nonNullVarlenCols, int nonNullVarlenSize) {
-        int size = BinaryRow.CHUNK_LEN_FIELD_SIZE + cols.nullMapSize() +
-            varlenTableChunkSize(nonNullVarlenCols);
-
-        for (int i = 0; i < cols.numberOfFixsizeColumns(); i++)
-            size += cols.column(i).type().sizeInBytes();
-
-        return size + nonNullVarlenSize;
-    }
-    public RowAssembler(
-        SchemaDescriptor schema,
-        int size,
-        int nonNullVarlenKeyCols,
-        int nonNullVarlenValCols
-    ) {
-        this(schema, size, 2, nonNullVarlenKeyCols, 2, nonNullVarlenValCols);
-    }
-
-    /**
-     * @param schema Row schema.
-     * @param size Target row size. If the row size is known in advance, it should be provided upfront to avoid
-     * unnecessary arrays copy.
-     * @param nonNullVarlenKeyCols Number of non-null varlen columns in key chunk.
-     * @param nonNullVarlenValCols Number of non-null varlen columns in value chunk.
-     */
-    public RowAssembler(
-        SchemaDescriptor schema,
-        int size,
-        int keyOffSize,
-        int nonNullVarlenKeyCols,
-        int valOffSize,
-        int nonNullVarlenValCols
-    ) {
-        this.schema = schema;
-        this.nonNullVarlenValCols = nonNullVarlenValCols;
-        this.valOffSize = valOffSize;
-
-        curCols = schema.keyColumns();
-        flags = 0;
-        keyHash = 0;
-        strEncoder = null;
-
-        initOffsets(BinaryRow.KEY_CHUNK_OFFSET, keyOffSize, nonNullVarlenKeyCols);
-
-        if (schema.keyColumns().nullMapSize() == 0)
-            flags |= RowFlags.OMIT_KEY_NULL_MAP_FLAG;
-
-        if (schema.valueColumns().nullMapSize() == 0)
-            flags |= RowFlags.OMIT_VAL_NULL_MAP_FLAG;
-
-        if (keyOffSize == 1)
-            flags |= RowFlags.KEY_TYNY_FORMAT;
-        else if (keyOffSize != 2)
-            flags |= RowFlags.KEY_LARGE_ROW_FORMAT;
-
-        if (valOffSize == 1)
-            flags |= RowFlags.VAL_TYNY_FORMAT;
-        else if (valOffSize != 2)
-            flags |= RowFlags.VAL_LARGE_FORMAT;
-
-        buf = new ExpandableByteBuf(size);
-
-        buf.putShort(0, (short)schema.version());
-
-        if (nonNullVarlenKeyCols == 0)
-            flags |= OMIT_KEY_VARTBL_FLAG;
-        else
-            writeAdaptiveItem(varlenTblChunkOff, (short)nonNullVarlenKeyCols);
-    }
-
-    public static int vartableOffSize(int vartableItems, int dataSize) {
-        if (dataSize + vartableItems + 2 < (1 << 8))
-            return 1;
-        if (dataSize + (vartableItems + 2) * 2 < (1 << 16))
-            return 2;
-        else
-            return 4;
-    }
-
-    /**
-     * Appends {@code null} value for the current column to the chunk.
-     */
-    public void appendNull() {
-        Column col = curCols.column(curCol);
-
-        if (!col.nullable())
-            throw new IllegalArgumentException("Failed to set column (null was passed, but column is not nullable): " +
-                col);
-
-        setNull(curCol);
-
-        if (isKeyColumn())
-            keyHash *= 31;
-
-        shiftColumn(0, false);
-    }
-
-    /**
-     * Appends byte value for the current column to the chunk.
-     *
-     * @param val Column value.
-     */
-    public void appendByte(byte val) {
-        checkType(NativeTypes.BYTE);
-
-        buf.put(curOff, val);
-
-        if (isKeyColumn())
-            keyHash = 31 * keyHash + Byte.hashCode(val);
-
-        shiftColumn(NativeTypes.BYTE);
-    }
-
-    /**
-     * Appends short value for the current column to the chunk.
-     *
-     * @param val Column value.
-     */
-    public void appendShort(short val) {
-        checkType(NativeTypes.SHORT);
-
-        buf.putShort(curOff, val);
-
-        if (isKeyColumn())
-            keyHash = 31 * keyHash + Short.hashCode(val);
-
-        shiftColumn(NativeTypes.SHORT);
-    }
-
-    /**
-     * Appends int value for the current column to the chunk.
-     *
-     * @param val Column value.
-     */
-    public void appendInt(int val) {
-        checkType(NativeTypes.INTEGER);
-
-        buf.putInt(curOff, val);
-
-        if (isKeyColumn())
-            keyHash = 31 * keyHash + Integer.hashCode(val);
-
-        shiftColumn(NativeTypes.INTEGER);
-    }
-
-    /**
-     * Appends long value for the current column to the chunk.
-     *
-     * @param val Column value.
-     */
-    public void appendLong(long val) {
-        checkType(NativeTypes.LONG);
-
-        buf.putLong(curOff, val);
-
-        if (isKeyColumn())
-            keyHash += 31 * keyHash + Long.hashCode(val);
-
-        shiftColumn(NativeTypes.LONG);
-    }
-
-    /**
-     * Appends float value for the current column to the chunk.
-     *
-     * @param val Column value.
-     */
-    public void appendFloat(float val) {
-        checkType(NativeTypes.FLOAT);
-
-        buf.putFloat(curOff, val);
-
-        if (isKeyColumn())
-            keyHash += 31 * keyHash + Float.hashCode(val);
-
-        shiftColumn(NativeTypes.FLOAT);
-    }
-
-    /**
-     * Appends double value for the current column to the chunk.
-     *
-     * @param val Column value.
-     */
-    public void appendDouble(double val) {
-        checkType(NativeTypes.DOUBLE);
-
-        buf.putDouble(curOff, val);
-
-        if (isKeyColumn())
-            keyHash += 31 * keyHash + Double.hashCode(val);
-
-        shiftColumn(NativeTypes.DOUBLE);
-    }
-
-    /**
-     * Appends UUID value for the current column to the chunk.
-     *
-     * @param uuid Column value.
-     */
-    public void appendUuid(UUID uuid) {
-        checkType(NativeTypes.UUID);
-
-        buf.putLong(curOff, uuid.getLeastSignificantBits());
-        buf.putLong(curOff + 8, uuid.getMostSignificantBits());
-
-        if (isKeyColumn())
-            keyHash += 31 * keyHash + uuid.hashCode();
-
-        shiftColumn(NativeTypes.UUID);
-    }
-
-    /**
-     * Appends String value for the current column to the chunk.
-     *
-     * @param val Column value.
-     */
-    public void appendString(String val) {
-        checkType(NativeTypes.STRING);
-
-        try {
-            int written = buf.putString(curOff, val, encoder());
-
-            writeOffset(curVarlenTblEntry, curOff - baseOff);
-
-            if (isKeyColumn())
-                keyHash += 31 * keyHash + val.hashCode();
-
-            shiftColumn(written, true);
-        }
-        catch (CharacterCodingException e) {
-            throw new AssemblyException("Failed to encode string", e);
-        }
-    }
-
-    /**
-     * Appends byte[] value for the current column to the chunk.
-     *
-     * @param val Column value.
-     */
-    public void appendBytes(byte[] val) {
-        checkType(NativeTypes.BYTES);
-
-        buf.putBytes(curOff, val);
-
-        if (isKeyColumn())
-            keyHash += 31 * keyHash + Arrays.hashCode(val);
-
-        writeOffset(curVarlenTblEntry, curOff - baseOff);
-
-        shiftColumn(val.length, true);
-    }
-
-    /**
-     * Appends BitSet value for the current column to the chunk.
-     *
-     * @param bitSet Column value.
-     */
-    public void appendBitmask(BitSet bitSet) {
-        Column col = curCols.column(curCol);
-
-        checkType(NativeTypeSpec.BITMASK);
-
-        BitmaskNativeType maskType = (BitmaskNativeType)col.type();
-
-        if (bitSet.length() > maskType.bits())
-            throw new IllegalArgumentException("Failed to set bitmask for column '" + col.name() + "' " +
-                "(mask size exceeds allocated size) [mask=" + bitSet + ", maxSize=" + maskType.bits() + "]");
-
-        byte[] arr = bitSet.toByteArray();
-
-        buf.putBytes(curOff, arr);
-
-        for (int i = 0; i < maskType.sizeInBytes() - arr.length; i++)
-            buf.put(curOff + arr.length + i, (byte)0);
-
-        if (isKeyColumn())
-            keyHash += 31 * keyHash + Arrays.hashCode(arr);
-
-        shiftColumn(maskType);
-    }
-
-    /**
-     * @return Serialized row.
-     */
-    public byte[] build() {
-        if (schema.keyColumns() == curCols)
-            throw new AssemblyException("Key column missed: colIdx=" + curCol);
-        else {
-            if (curCol == 0)
-                flags |= RowFlags.NO_VALUE_FLAG;
-            else if (schema.valueColumns().length() != curCol)
-                throw new AssemblyException("Value column missed: colIdx=" + curCol);
-        }
-
-        buf.putShort(BinaryRow.FLAGS_FIELD_OFFSET, flags);
-        buf.putInt(BinaryRow.KEY_HASH_FIELD_OFFSET, keyHash);
-
-        return buf.toArray();
-    }
-
-    /**
-     * @return UTF-8 string encoder.
-     */
-    private CharsetEncoder encoder() {
-        if (strEncoder == null)
-            strEncoder = StandardCharsets.UTF_8.newEncoder();
-
-        return strEncoder;
-    }
-
-    /**
-     * Writes the given offset to the varlen table entry with the given index.
-     *
-     * @param tblEntryIdx Varlen table entry index.
-     * @param off Offset to write.
-     */
-    private void writeOffset(int tblEntryIdx, int off) {
-        assert (flags & (baseOff == BinaryRow.KEY_CHUNK_OFFSET ? OMIT_KEY_VARTBL_FLAG : OMIT_VAL_VARTBL_FLAG)) == 0 :
-            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
-
-        writeAdaptiveItem(varlenTblChunkOff + vartableItemOffset(tblEntryIdx), off);
-    }
-
-    private void writeAdaptiveItem(int off, int val) {
-        switch (adaptiveItemSize) {
-            case Byte.BYTES:
-                buf.put(off, (byte)val);
-
-                return;
-            case Short.BYTES:
-                buf.putShort(off, (short)val);
-
-                return;
-            default:
-                buf.putInt(off, val);
-        }
-    }
-
-    /**
-     * Checks that the type being appended matches the column type.
-     *
-     * @param type Type spec that is attempted to be appended.
-     */
-    private void checkType(NativeTypeSpec type) {
-        Column col = curCols.column(curCol);
-
-        if (col.type().spec() != type)
-            throw new IllegalArgumentException("Failed to set column (int was passed, but column is of different " +
-                "type): " + col);
-    }
-
-    /**
-     * Checks that the type being appended matches the column type.
-     *
-     * @param type Type that is attempted to be appended.
-     */
-    private void checkType(NativeType type) {
-        checkType(type.spec());
-    }
-
-    /**
-     * Sets null flag in the null map for the given column.
-     *
-     * @param colIdx Column index.
-     */
-    private void setNull(int colIdx) {
-        assert (flags & (baseOff == BinaryRow.KEY_CHUNK_OFFSET ? RowFlags.OMIT_KEY_NULL_MAP_FLAG : RowFlags.OMIT_VAL_NULL_MAP_FLAG)) == 0 :
-            "Illegal writing 'null' value when 'omit null-map' flag is set for a chunk.";
-
-        int byteInMap = colIdx / 8;
-        int bitInByte = colIdx % 8;
-
-        buf.ensureCapacity(nullMapOff + byteInMap + 1);
-
-        buf.put(nullMapOff + byteInMap, (byte)(buf.get(nullMapOff + byteInMap) | (1 << bitInByte)));
-    }
-
-    /**
-     * Must be called after an append of fixlen column.
-     *
-     * @param type Type of the appended column.
-     */
-    private void shiftColumn(NativeType type) {
-        assert type.spec().fixedLength() : "Varlen types should provide field length to shift column: " + type;
-
-        shiftColumn(type.sizeInBytes(), false);
-    }
-
-    /**
-     * Shifts current offsets and column indexes as necessary, also changes the chunk base offsets when
-     * moving from key to value columns.
-     *
-     * @param size Size of the appended column.
-     * @param varlen {@code true} if appended column was varlen.
-     */
-    private void shiftColumn(int size, boolean varlen) {
-        curCol++;
-        curOff += size;
-
-        if (varlen)
-            curVarlenTblEntry++;
-
-        if (curCol == curCols.length()) {
-            int chunkLen = curOff - baseOff;
-
-            writeAdaptiveItem(baseOff, chunkLen);
-
-            if (schema.valueColumns() == curCols)
-                return; // No more columns.
-
-            curCols = schema.valueColumns(); // Switch key->value columns.
-
-            initOffsets(baseOff + chunkLen, valOffSize, nonNullVarlenValCols);
-
-            if (nonNullVarlenValCols == 0)
-                flags |= OMIT_VAL_VARTBL_FLAG;
-            else
-                writeAdaptiveItem(varlenTblChunkOff, (short)nonNullVarlenValCols);
-        }
-    }
-
-    /**
-     * @param base Chunk base offset.
-     * @param nonNullVarlenCols Number of non-null varlen columns.
-     */
-    private void initOffsets(int base, int adaptiveItemSize, int nonNullVarlenCols) {
-        baseOff = base;
-
-        this.adaptiveItemSize = adaptiveItemSize;
-
-        curCol = 0;
-        curVarlenTblEntry = 0;
-
-        nullMapOff = baseOff + adaptiveItemSize /* chunk length. */;
-        varlenTblChunkOff = nullMapOff + curCols.nullMapSize();
-
-        curOff = varlenTblChunkOff + vartableSize(nonNullVarlenCols, adaptiveItemSize);
-    }
-
-    public int vartableItemOffset(int nonNullVarlenCols) {
-        return adaptiveItemSize + nonNullVarlenCols * adaptiveItemSize;
-    }
-
-    public static int vartableSize(int items, int itemSize) {
-        return items == 0 ? 0 : itemSize + items * itemSize;
-    }
-
-    /**
-     * @return {@code true} if current column is a key column, {@code false} otherwise.
-     */
-    private boolean isKeyColumn() {
-        return schema.keyColumns() == curCols;
-    }
-}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/AbstractSerializer.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/AbstractSerializer.java
index 0cd67ad..940e80a 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/AbstractSerializer.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/AbstractSerializer.java
@@ -19,8 +19,8 @@ package org.apache.ignite.internal.schema.marshaller;
 
 import java.util.Objects;
 import org.apache.ignite.internal.schema.ByteBufferRow;
-import org.apache.ignite.internal.schema.Row;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.util.Pair;
 import org.jetbrains.annotations.Nullable;
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerUtil.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerUtil.java
index 6884d8f..265c3f9 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerUtil.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerUtil.java
@@ -21,7 +21,7 @@ import java.util.BitSet;
 import java.util.UUID;
 import org.apache.ignite.internal.schema.InvalidTypeException;
 import org.apache.ignite.internal.schema.NativeType;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.util.ObjectFactory;
 
 /**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/AsmSerializerGenerator.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/AsmSerializerGenerator.java
index 14712b3..d4e2425 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/AsmSerializerGenerator.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/AsmSerializerGenerator.java
@@ -40,8 +40,8 @@ import jdk.jfr.Experimental;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.Columns;
 import org.apache.ignite.internal.schema.NativeType;
-import org.apache.ignite.internal.schema.Row;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.marshaller.AbstractSerializer;
 import org.apache.ignite.internal.schema.marshaller.BinaryMode;
@@ -246,8 +246,6 @@ public class AsmSerializerGenerator implements SerializerFactory {
 
         final Variable varlenKeyCols = scope.declareVariable("varlenKeyCols", body, BytecodeExpressions.defaultValue(int.class));
         final Variable varlenValueCols = scope.declareVariable("varlenValueCols", body, BytecodeExpressions.defaultValue(int.class));
-        final Variable varlenKeyColsSize = scope.declareVariable("varlenKeyColsSize", body, BytecodeExpressions.defaultValue(int.class));
-        final Variable varlenValueColsSize = scope.declareVariable("varlenValueColsSize", body, BytecodeExpressions.defaultValue(int.class));
 
         final Variable keyCols = scope.declareVariable(Columns.class, "keyCols");
         final Variable valCols = scope.declareVariable(Columns.class, "valCols");
@@ -268,13 +266,7 @@ public class AsmSerializerGenerator implements SerializerFactory {
 
                 body.append(keyMarsh.getValue(classDef.getType(), scope.getVariable("key"), i)).putVariable(tmp);
                 body.append(new IfStatement().condition(BytecodeExpressions.isNotNull(tmp)).ifTrue(
-                    new BytecodeBlock()
-                        .append(varlenKeyCols.increment())
-                        .append(BytecodeExpressions.add(
-                            varlenKeyColsSize,
-                            getColumnValueSize(tmp, keyCols, i))
-                        )
-                        .putVariable(varlenKeyColsSize))
+                    new BytecodeBlock().append(varlenKeyCols.increment()))
                 );
             }
         }
@@ -288,22 +280,13 @@ public class AsmSerializerGenerator implements SerializerFactory {
 
                 body.append(valMarsh.getValue(classDef.getType(), scope.getVariable("val"), i)).putVariable(tmp);
                 body.append(new IfStatement().condition(BytecodeExpressions.isNotNull(tmp)).ifTrue(
-                    new BytecodeBlock()
-                        .append(varlenValueCols.increment())
-                        .append(BytecodeExpressions.add(
-                            varlenValueColsSize,
-                            getColumnValueSize(tmp, valCols, i))
-                        )
-                        .putVariable(varlenValueColsSize))
+                    new BytecodeBlock().append(varlenValueCols.increment()))
                 );
             }
         }
 
         body.append(BytecodeExpressions.newInstance(RowAssembler.class,
             methodDef.getThis().getField("schema", SchemaDescriptor.class),
-            BytecodeExpressions.invokeStatic(RowAssembler.class, "rowSize", int.class,
-                keyCols, varlenKeyCols, varlenKeyColsSize,
-                valCols, varlenValueCols, varlenValueColsSize),
             varlenKeyCols,
             varlenValueCols));
 
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessor.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessor.java
index 017b7be..ce16e7d 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessor.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessor.java
@@ -25,8 +25,8 @@ import java.util.Objects;
 import java.util.UUID;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.Columns;
-import org.apache.ignite.internal.schema.Row;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.schema.marshaller.BinaryMode;
 import org.apache.ignite.internal.schema.marshaller.MarshallerUtil;
 import org.apache.ignite.internal.schema.marshaller.SerializationException;
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
index a36ef94..9e98d30 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
@@ -18,8 +18,8 @@
 package org.apache.ignite.internal.schema.marshaller.reflection;
 
 import org.apache.ignite.internal.schema.Columns;
-import org.apache.ignite.internal.schema.Row;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.marshaller.AbstractSerializer;
 import org.apache.ignite.internal.schema.marshaller.SerializationException;
@@ -85,11 +85,7 @@ public class JavaSerializer extends AbstractSerializer {
         ObjectStatistic keyStat = collectObjectStats(schema.keyColumns(), keyMarsh, key);
         ObjectStatistic valStat = collectObjectStats(schema.valueColumns(), valMarsh, val);
 
-        int size = RowAssembler.rowSize(
-            schema.keyColumns(), keyStat.nonNullCols, keyStat.nonNullColsSize,
-            schema.valueColumns(), valStat.nonNullCols, valStat.nonNullColsSize);
-
-        return new RowAssembler(schema, size, 2, keyStat.nonNullCols, 2, valStat.nonNullCols);
+        return new RowAssembler(schema, keyStat.nonNullCols, valStat.nonNullCols);
     }
 
     /**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/Marshaller.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/Marshaller.java
index 874ace6..e59f438 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/Marshaller.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/Marshaller.java
@@ -20,8 +20,8 @@ package org.apache.ignite.internal.schema.marshaller.reflection;
 import java.util.Objects;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.Columns;
-import org.apache.ignite.internal.schema.Row;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.schema.marshaller.BinaryMode;
 import org.apache.ignite.internal.schema.marshaller.MarshallerUtil;
 import org.apache.ignite.internal.schema.marshaller.SerializationException;
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/AbstractChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/AbstractChunkWriter.java
new file mode 100644
index 0000000..7ab7787
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/AbstractChunkWriter.java
@@ -0,0 +1,228 @@
+/*
+ * 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.schema.row;
+
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetEncoder;
+import java.util.BitSet;
+import java.util.UUID;
+import org.apache.ignite.internal.schema.AssemblyException;
+import org.apache.ignite.internal.schema.NativeTypes;
+
+/**
+ * Abstract row chunk writer.
+ */
+abstract class AbstractChunkWriter {
+    /** Chunk buffer. */
+    protected final ExpandableByteBuf buf;
+
+    /** Base offset of the chunk */
+    protected final int baseOff;
+
+    /** Offset of the null map for the chunk. */
+    protected final int nullMapOff;
+
+    /** Offset of the varlen table for the chunk. */
+    protected final int varTblOff;
+
+    /** Offset of data for the chunk. */
+    protected final int dataOff;
+
+    /** Index of the current varlen table entry. Incremented each time non-null varlen column is appended. */
+    protected int curVartblItem;
+
+    /** Current offset for the next column to be appended. */
+    protected int curOff;
+
+    /**
+     * @param buf Row buffer.
+     * @param baseOff Chunk base offset.
+     * @param nullMapOff Null-map offset.
+     * @param varTblOff Vartable offset.
+     */
+    protected AbstractChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapOff, int varTblOff, int dataOff) {
+        this.buf = buf;
+        this.baseOff = baseOff;
+        this.nullMapOff = nullMapOff;
+        this.varTblOff = varTblOff;
+        this.dataOff = dataOff;
+        curOff = dataOff;
+        curVartblItem = 0;
+    }
+
+    /**
+     * Appends byte value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendByte(byte val) {
+        buf.put(curOff, val);
+
+        curOff += NativeTypes.BYTE.sizeInBytes();
+    }
+
+    /**
+     * Appends short value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendShort(short val) {
+        buf.putShort(curOff, val);
+
+        curOff += NativeTypes.SHORT.sizeInBytes();
+    }
+
+    /**
+     * Appends int value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendInt(int val) {
+        buf.putInt(curOff, val);
+
+        curOff += NativeTypes.INTEGER.sizeInBytes();
+    }
+
+    /**
+     * Appends long value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendLong(long val) {
+        buf.putLong(curOff, val);
+
+        curOff += NativeTypes.LONG.sizeInBytes();
+    }
+
+    /**
+     * Appends float value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendFloat(float val) {
+        buf.putFloat(curOff, val);
+
+        curOff += NativeTypes.FLOAT.sizeInBytes();
+    }
+
+    /**
+     * Appends double value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendDouble(double val) {
+        buf.putDouble(curOff, val);
+
+        curOff += NativeTypes.DOUBLE.sizeInBytes();
+    }
+
+    /**
+     * Appends UUID value for the current column to the chunk.
+     *
+     * @param uuid Column value.
+     */
+    public void appendUuid(UUID uuid) {
+        buf.putLong(curOff, uuid.getLeastSignificantBits());
+        buf.putLong(curOff + 8, uuid.getMostSignificantBits());
+
+        curOff += NativeTypes.UUID.sizeInBytes();
+    }
+
+    /**
+     * Appends String value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendString(String val, CharsetEncoder encoder) {
+        try {
+            int written = buf.putString(curOff, val, encoder);
+
+            writeOffset(curVartblItem, curOff - dataOff);
+
+            curVartblItem++;
+            curOff += written;
+        }
+        catch (CharacterCodingException e) {
+            throw new AssemblyException("Failed to encode string", e);
+        }
+    }
+
+    /**
+     * Appends byte[] value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendBytes(byte[] val) {
+        buf.putBytes(curOff, val);
+
+        writeOffset(curVartblItem, curOff - dataOff);
+
+        curVartblItem++;
+        curOff += val.length;
+    }
+
+    /**
+     * Appends BitSet value for the current column to the chunk.
+     *
+     * @param bitSet Column value.
+     */
+    public void appendBitmask(BitSet bitSet, int size) {
+        byte[] arr = bitSet.toByteArray();
+
+        buf.putBytes(curOff, arr);
+
+        for (int i = 0; i < size - arr.length; i++)
+            buf.put(curOff + arr.length + i, (byte)0);
+
+        curOff += size;
+    }
+
+    /**
+     * @return Chunk size in bytes.
+     */
+    public int chunkLength() {
+        return curOff - baseOff;
+    }
+
+    /**
+     * Post-write action.
+     */
+    abstract void flush();
+
+    /**
+     * Writes the given offset to the varlen table entry with the given index.
+     *
+     * @param tblEntryIdx Varlen table entry index.
+     * @param off Offset to write.
+     */
+    protected abstract void writeOffset(int tblEntryIdx, int off);
+
+    /**
+     * Sets null flag in the null map for the given column.
+     *
+     * @param colIdx Column index.
+     */
+    protected void setNull(int colIdx) {
+        int byteInMap = colIdx / 8;
+        int bitInByte = colIdx % 8;
+
+        buf.ensureCapacity(nullMapOff + byteInMap + 1);
+
+        buf.put(nullMapOff + byteInMap, (byte)(buf.get(nullMapOff + byteInMap) | (1 << bitInByte)));
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ExpandableByteBuf.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ExpandableByteBuf.java
similarity index 92%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/ExpandableByteBuf.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ExpandableByteBuf.java
index d74d719..96401b3 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ExpandableByteBuf.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ExpandableByteBuf.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema;
+package org.apache.ignite.internal.schema.row;
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -24,6 +24,7 @@ import java.nio.charset.CharacterCodingException;
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CoderResult;
 import java.util.Arrays;
+import org.apache.ignite.internal.util.Constants;
 
 /**
  * A simple byte array wrapper to allow dynamic byte array expansion during the row construction. Grows exponentially
@@ -46,16 +47,13 @@ import java.util.Arrays;
  */
 @SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
 public class ExpandableByteBuf {
-    /** */
-    private static final int MB = 1024 * 1024;
-
-    /** */
+    /** Buffer array. */
     private byte[] arr;
 
-    /** */
+    /** Wrapped array. */
     private ByteBuffer buf;
 
-    /** */
+    /** Written bytes. */
     private int len;
 
     /**
@@ -189,7 +187,7 @@ public class ExpandableByteBuf {
                     break;
 
                 if (cr.isOverflow()) {
-                    expand(len + 1);
+                    expand(len + (int)encoder.maxBytesPerChar());
 
                     continue;
                 }
@@ -205,7 +203,7 @@ public class ExpandableByteBuf {
                 len = buf.position();
 
                 if (cr.isOverflow()) {
-                    expand(len + 1);
+                    expand(len + (int)encoder.maxBytesPerChar());
 
                     continue;
                 }
@@ -264,13 +262,13 @@ public class ExpandableByteBuf {
         int l = arr.length;
 
         while (l < cap) {
-            if (l < MB)
+            if (l < Constants.MiB)
                 l *= 2;
             else
-                l += MB;
+                l += Constants.MiB;
         }
 
-        byte[] tmp = new byte[cap];
+        byte[] tmp = new byte[l];
 
         System.arraycopy(arr, 0, tmp, 0, arr.length);
 
@@ -280,4 +278,13 @@ public class ExpandableByteBuf {
         buf.position(oldPos);
         buf.order(ByteOrder.LITTLE_ENDIAN);
     }
+
+    /**
+     * Unwrap to ByteBuffer.
+     *
+     * @return Byte buffer.
+     */
+    ByteBuffer unwrap() {
+        return buf;
+    }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/LongChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/LongChunkWriter.java
new file mode 100644
index 0000000..2c75d37
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/LongChunkWriter.java
@@ -0,0 +1,78 @@
+/*
+ * 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.schema.row;
+
+/**
+ * Row chunk writer for long key/value chunks.
+ *
+ * Uses {@code int} values for coding sizes/offsets,
+ * supports chunks with payload up to 2 GiB.
+ */
+class LongChunkWriter extends AbstractChunkWriter {
+    /**
+     * Calculates vartable length (in bytes).
+     *
+     * @param items Vartable items.
+     * @return Vartable size in bytes.
+     */
+    static int vartableLength(int items) {
+        return items == 0 ? 0 : Integer.BYTES /* Table size */ + items * Integer.BYTES;
+    }
+
+    /**
+     * Creates chunk writer for long chunk format.
+     *
+     * @param buf Row buffer.
+     * @param baseOff Chunk base offset.
+     * @param nullMapLen Null-map size in bytes.
+     * @param vartblSize Amount of vartable items.
+     */
+    LongChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize) {
+        super(
+            buf,
+            baseOff,
+            baseOff + Integer.BYTES /* Chunk size */,
+            baseOff + Integer.BYTES /* Chunk size */ + nullMapLen,
+            baseOff + Integer.BYTES /* Chunk size */ + nullMapLen + vartableLength(vartblSize));
+
+        curVartblItem = 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override void flush() {
+        final int size = chunkLength();
+
+        assert size > 0 : "Size field value overflow: " + size;
+        assert varTblOff + vartableLength(curVartblItem) == dataOff : "Vartable underflowed.";
+
+        buf.putInt(baseOff, size);
+
+        if (curVartblItem > 0)
+            buf.putInt(varTblOff, curVartblItem);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void writeOffset(int tblEntryIdx, int off) {
+        final int itemOff = varTblOff + Integer.BYTES + tblEntryIdx * Integer.BYTES;
+
+        assert off >= 0 : "Varlen offset overflow: offset=" + off;
+        assert itemOff < dataOff : "Vartable overflow: size=" + itemOff;
+
+        buf.putInt(itemOff, off);
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
similarity index 58%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
index 4ed78b0..15cb69e 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema;
+package org.apache.ignite.internal.schema.row;
 
 import java.io.IOException;
 import java.io.OutputStream;
@@ -23,6 +23,13 @@ import java.math.BigDecimal;
 import java.nio.ByteBuffer;
 import java.util.BitSet;
 import java.util.UUID;
+import org.apache.ignite.internal.schema.BinaryRow;
+import org.apache.ignite.internal.schema.Column;
+import org.apache.ignite.internal.schema.Columns;
+import org.apache.ignite.internal.schema.InvalidTypeException;
+import org.apache.ignite.internal.schema.NativeTypeSpec;
+import org.apache.ignite.internal.schema.SchemaDescriptor;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Schema-aware row.
@@ -38,6 +45,12 @@ public class Row implements BinaryRow {
     /** Binary row. */
     private final BinaryRow row;
 
+    /** Key reader. */
+    private final AbstractChunkReader keyReader;
+
+    /** Value reader. */
+    private final AbstractChunkReader valReader;
+
     /**
      * Constructor.
      *
@@ -49,14 +62,36 @@ public class Row implements BinaryRow {
 
         this.row = row;
         this.schema = schema;
+
+        final short flags = readShort(FLAGS_FIELD_OFFSET);
+
+        keyReader = createReader(KEY_CHUNK_OFFSET,
+            (flags & RowFlags.KEY_TYNY_FORMAT) != 0,
+            (flags & RowFlags.OMIT_KEY_NULL_MAP_FLAG) == 0 ? schema.keyColumns().nullMapSize() : 0,
+            (flags & RowFlags.OMIT_KEY_VARTBL_FLAG) == 0);
+
+        valReader = ((flags & RowFlags.NO_VALUE_FLAG) == 0) ?
+            createReader(
+                KEY_CHUNK_OFFSET + keyReader.chunkLength(),
+                (flags & RowFlags.VAL_TYNY_FORMAT) != 0,
+                (flags & RowFlags.OMIT_VAL_NULL_MAP_FLAG) == 0 ? schema.valueColumns().nullMapSize() : 0,
+                (flags & RowFlags.OMIT_VAL_VARTBL_FLAG) == 0) :
+            null;
     }
 
     /**
-     * @param itemIdx Varlen table item index.
-     * @return Varlen item offset.
+     * Chunk reader factory method.
+     *
+     * @param baseOff Chunk base offset.
+     * @param isSmallChunk Small chunk format flag.
+     * @param nullMapLen Null-map length.
+     * @param hasVarTable Vartable presense flag.
+     * @return Chunk reader.
      */
-    private int varlenItemOffset(int itemIdx, int itemSize) {
-        return itemSize + itemIdx * itemSize;
+    @NotNull private AbstractChunkReader createReader(int baseOff, boolean isSmallChunk, int nullMapLen, boolean hasVarTable) {
+        return isSmallChunk ?
+            new TinyChunkReader(baseOff, nullMapLen, hasVarTable) :
+            new LargeChunkReader(baseOff, nullMapLen, hasVarTable);
     }
 
     /**
@@ -343,43 +378,29 @@ public class Row implements BinaryRow {
      */
     protected long findColumn(int colIdx, NativeTypeSpec type) throws InvalidTypeException {
         // Get base offset (key start or value start) for the given column.
-        boolean keyCol = schema.isKeyColumn(colIdx);
+        boolean isKeyCol = schema.isKeyColumn(colIdx);
 
-        final short flags = readShort(FLAGS_FIELD_OFFSET);
-
-        int size = keyCol ?
-            ((flags & RowFlags.KEY_TYNY_FORMAT) != 0) ? 1 : (flags & RowFlags.KEY_LARGE_ROW_FORMAT) != 0 ? 4 : 2 :
-            (flags & RowFlags.VAL_TYNY_FORMAT) != 0 ? 1 : (flags & RowFlags.VAL_LARGE_FORMAT) != 0 ? 4 : 2;
-
-        int off = KEY_CHUNK_OFFSET;
-
-        if (!keyCol) {
-            assert (flags & RowFlags.NO_VALUE_FLAG) == 0;
-
-            // Jump to the next chunk, the size of the first chunk is written at the chunk start.
-            off += readAdaptiveSizedItem(off, size);
-
-            // Adjust the column index according to the number of key columns.
+        // Adjust the column index according to the number of key columns.
+        if (!isKeyCol)
             colIdx -= schema.keyColumns().length();
-        }
 
-        Columns cols = keyCol ? schema.keyColumns() : schema.valueColumns();
+        AbstractChunkReader reader = isKeyCol ? keyReader : valReader;
+        Columns cols = isKeyCol ? schema.keyColumns() : schema.valueColumns();
 
         if (cols.column(colIdx).type().spec() != type)
             throw new InvalidTypeException("Invalid column type requested [requested=" + type +
                 ", column=" + cols.column(colIdx) + ']');
 
-        boolean hasVarTable = ((keyCol ? RowFlags.OMIT_KEY_VARTBL_FLAG : RowFlags.OMIT_VAL_VARTBL_FLAG) & flags) == 0;
-        boolean hasNullMap = ((keyCol ? RowFlags.OMIT_KEY_NULL_MAP_FLAG : RowFlags.OMIT_VAL_NULL_MAP_FLAG) & flags) == 0;
+        assert reader != null;
 
-        if (hasNullMap && isNull(off + size, colIdx))
+        if (reader.isNull(colIdx))
             return -1;
 
-        assert hasVarTable || type.fixedLength();
+        assert reader.hasVartable() || type.fixedLength();
 
         return type.fixedLength() ?
-            fixlenColumnOffset(cols, off, colIdx, hasVarTable, hasNullMap, size) :
-            varlenColumnOffsetAndLength(cols, off, colIdx, hasNullMap, size);
+            reader.fixlenColumnOffset(cols, colIdx) :
+            reader.varlenColumnOffsetAndLength(cols, colIdx);
     }
 
     /**
@@ -393,22 +414,6 @@ public class Row implements BinaryRow {
     }
 
     /**
-     * Checks the row's null map for the given column index in the chunk.
-     *
-     * @param nullMapOff Null map offset
-     * @param idx Offset of the column in the chunk.
-     * @return {@code true} if the column value is {@code null}.
-     */
-    private boolean isNull(int nullMapOff, int idx) {
-        int nullByte = idx / 8;
-        int posInByte = idx % 8;
-
-        int map = readByte(nullMapOff + nullByte);
-
-        return (map & (1 << posInByte)) != 0;
-    }
-
-    /**
      * Utility method to extract the column offset from the {@link #findColumn(int, NativeTypeSpec)} result. The
      * offset is calculated from the beginning of the row.
      *
@@ -430,131 +435,6 @@ public class Row implements BinaryRow {
         return (int)(offLen >>> 32);
     }
 
-    /**
-     * Calculates the offset and length of varlen column. First, it calculates the number of non-null columns
-     * preceding the requested column by folding the null map bits. This number is used to adjust the column index
-     * and find the corresponding entry in the varlen table. The length of the column is calculated either by
-     * subtracting two adjacent varlen table offsets, or by subtracting the last varlen table offset from the chunk
-     * length.
-     *
-     * @param cols Columns chunk.
-     * @param baseOff Chunk base offset.
-     * @param idx Column index in the chunk.
-     * @param hasNullMap Has null map flag.
-     * @param adaptiveItemSize
-     * @return Encoded offset (from the row start) and length of the column with the given index.
-     */
-    private long varlenColumnOffsetAndLength(Columns cols, int baseOff, int idx, boolean hasNullMap,
-        int adaptiveItemSize) {
-        int vartableOff = baseOff + adaptiveItemSize /* Chunk len field size. */;
-
-        int numNullsBefore = 0;
-
-        if (hasNullMap) {
-            vartableOff += cols.nullMapSize();
-
-            int nullMapOff = baseOff + adaptiveItemSize;
-
-            int nullStartByte = cols.firstVarlengthColumn() / 8;
-            int startBitInByte = cols.firstVarlengthColumn() % 8;
-
-            int nullEndByte = idx / 8;
-            int endBitInByte = idx % 8;
-
-            for (int i = nullStartByte; i <= nullEndByte; i++) {
-                byte nullmapByte = readByte(nullMapOff + i);
-
-                if (i == nullStartByte)
-                    // We need to clear startBitInByte least significant bits
-                    nullmapByte &= (0xFF << startBitInByte);
-
-                if (i == nullEndByte)
-                    // We need to clear 8-endBitInByte most significant bits
-                    nullmapByte &= (0xFF >> (8 - endBitInByte));
-
-                numNullsBefore += Columns.numberOfNullColumns(nullmapByte);
-            }
-        }
-
-        idx -= cols.numberOfFixsizeColumns() + numNullsBefore;
-        int vartableSize = readAdaptiveSizedItem(vartableOff, adaptiveItemSize);
-
-        // Offset of idx-th column is from base offset.
-        int resOff = readAdaptiveSizedItem(vartableOff + varlenItemOffset(idx, adaptiveItemSize), adaptiveItemSize);
-
-        long len = (idx == vartableSize - 1) ?
-            // totalLength - columnStartOffset
-            readAdaptiveSizedItem(baseOff, adaptiveItemSize) - resOff :
-            // nextColumnStartOffset - columnStartOffset
-            readAdaptiveSizedItem(vartableOff + varlenItemOffset(idx + 1, adaptiveItemSize), adaptiveItemSize) - resOff;
-
-        return (len << 32) | (resOff + baseOff);
-    }
-
-    /**
-     * Calculates the offset of the fixlen column with the given index in the row. It essentially folds the null map
-     * with the column lengths to calculate the size of non-null columns preceding the requested column.
-     *
-     * @param cols Columns chunk.
-     * @param baseOff Chunk base offset.
-     * @param idx Column index in the chunk.
-     * @param hasVarTbl Has varlen table flag.
-     * @param hasNullMap Has null map flag.
-     * @param adaptiveItemSize
-     * @return Encoded offset (from the row start) of the requested fixlen column.
-     */
-    int fixlenColumnOffset(Columns cols, int baseOff, int idx, boolean hasVarTbl, boolean hasNullMap,
-        int adaptiveItemSize) {
-        int colOff = 0;
-
-        int payloadOff = baseOff + adaptiveItemSize /* Chunk len field size. */;
-
-        // Calculate fixlen column offset.
-        {
-            int colByteIdx = idx / 8;
-
-            // Set bits starting from posInByte, inclusive, up to either the end of the byte or the last column index, inclusive
-            int startBit = idx % 8;
-            int endBit = colByteIdx == (cols.length() + 7) / 8 - 1 ? ((cols.numberOfFixsizeColumns() - 1) % 8) : 7;
-            int mask = (0xFF >> (7 - endBit)) & (0xFF << startBit);
-
-            if (hasNullMap) {
-                payloadOff += cols.nullMapSize();
-
-                // Fold offset based on the whole map bytes in the schema
-                for (int i = 0; i < colByteIdx; i++)
-                    colOff += cols.foldFixedLength(i, readByte(baseOff + adaptiveItemSize + i));
-
-                colOff += cols.foldFixedLength(colByteIdx, readByte(baseOff + adaptiveItemSize + colByteIdx) | mask);
-            }
-            else {
-                for (int i = 0; i < colByteIdx; i++)
-                    colOff += cols.foldFixedLength(i, 0);
-
-                colOff += cols.foldFixedLength(colByteIdx, mask);
-            }
-        }
-
-        if (hasVarTbl) {
-            int verlenItems = readAdaptiveSizedItem(payloadOff, adaptiveItemSize);
-
-            payloadOff += varlenItemOffset(verlenItems, adaptiveItemSize);
-        }
-
-        return payloadOff + colOff;
-    }
-
-    public int readAdaptiveSizedItem(int off, int size) {
-        switch (size) {
-            case Byte.BYTES:
-                return row.readByte(off);
-            case Short.BYTES:
-                return row.readShort(off);
-            default:
-                return row.readInteger(off);
-        }
-    }
-
     /** {@inheritDoc} */
     @Override public int schemaVersion() {
         return row.schemaVersion();
@@ -619,4 +499,235 @@ public class Row implements BinaryRow {
     @Override public byte[] readBytes(int off, int len) {
         return row.readBytes(off, len);
     }
+
+    /**
+     * Abstract chunk reader.
+     */
+    abstract class AbstractChunkReader {
+        /** Base offset. */
+        protected final int baseOff;
+
+        /** Null-map offset. */
+        protected int nullMapOff;
+
+        /** Vartable offset. */
+        protected int varTableOff;
+
+        /** Payload offset. */
+        protected int dataOff;
+
+        /**
+         * @param baseOff Chunk base offset.
+         */
+        AbstractChunkReader(int baseOff) {
+            this.baseOff = baseOff;
+        }
+
+        /**
+         * @return Chunk length in bytes
+         */
+        abstract int chunkLength();
+
+        /**
+         * @return Number of items in vartable.
+         */
+        abstract int vartableItems();
+
+        /**
+         * Checks the row's null map for the given column index in the chunk.
+         *
+         * @param idx Offset of the column in the chunk.
+         * @return {@code true} if the column value is {@code null}.
+         */
+        /** {@inheritDoc} */
+        protected boolean isNull(int idx) {
+            if (!hasNullmap())
+                return false;
+
+            int nullByte = idx / 8;
+            int posInByte = idx % 8;
+
+            int map = readByte(nullMapOff + nullByte);
+
+            return (map & (1 << posInByte)) != 0;
+        }
+
+        /**
+         * @return {@code True} if chunk has vartable.
+         */
+        protected boolean hasVartable() {
+            return dataOff > varTableOff;
+        }
+
+        /**
+         * @return {@code True} if chunk has nullmap.
+         */
+        protected boolean hasNullmap() {
+            return varTableOff > nullMapOff;
+        }
+
+        /**
+         * @param itemIdx Varlen table item index.
+         * @return Varlen item offset.
+         */
+        protected abstract int varlenItemOffset(int itemIdx);
+
+        /**
+         * Calculates the offset of the fixlen column with the given index in the row. It essentially folds the null map
+         * with the column lengths to calculate the size of non-null columns preceding the requested column.
+         *
+         * @param cols Columns chunk.
+         * @param idx Column index in the chunk.
+         * @return Encoded offset (from the row start) of the requested fixlen column.
+         */
+        int fixlenColumnOffset(Columns cols, int idx) {
+            int colOff = 0;
+
+            // Calculate fixlen column offset.
+            {
+                int colByteIdx = idx / 8;
+
+                // Set bits starting from posInByte, inclusive, up to either the end of the byte or the last column index, inclusive
+                int startBit = idx % 8;
+                int endBit = colByteIdx == (cols.length() + 7) / 8 - 1 ? ((cols.numberOfFixsizeColumns() - 1) % 8) : 7;
+                int mask = (0xFF >> (7 - endBit)) & (0xFF << startBit);
+
+                if (hasNullmap()) {
+                    // Fold offset based on the whole map bytes in the schema
+                    for (int i = 0; i < colByteIdx; i++)
+                        colOff += cols.foldFixedLength(i, readByte(nullMapOff + i));
+
+                    colOff += cols.foldFixedLength(colByteIdx, readByte(nullMapOff + colByteIdx) | mask);
+                }
+                else {
+                    for (int i = 0; i < colByteIdx; i++)
+                        colOff += cols.foldFixedLength(i, 0);
+
+                    colOff += cols.foldFixedLength(colByteIdx, mask);
+                }
+            }
+
+            return dataOff + colOff;
+        }
+
+        /**
+         * Calculates the offset and length of varlen column. First, it calculates the number of non-null columns
+         * preceding the requested column by folding the null map bits. This number is used to adjust the column index
+         * and find the corresponding entry in the varlen table. The length of the column is calculated either by
+         * subtracting two adjacent varlen table offsets, or by subtracting the last varlen table offset from the chunk
+         * length.
+         *
+         * @param cols Columns chunk.
+         * @param idx Column index in the chunk.
+         * @return Encoded offset (from the row start) and length of the column with the given index.
+         */
+        long varlenColumnOffsetAndLength(Columns cols, int idx) {
+            assert hasVartable() : "Chunk has no vartable: colId=" + idx;
+
+            if (hasNullmap()) {
+                int nullStartByte = cols.firstVarlengthColumn() / 8;
+                int startBitInByte = cols.firstVarlengthColumn() % 8;
+
+                int nullEndByte = idx / 8;
+                int endBitInByte = idx % 8;
+
+                int numNullsBefore = 0;
+
+                for (int i = nullStartByte; i <= nullEndByte; i++) {
+                    byte nullmapByte = readByte(nullMapOff + i);
+
+                    if (i == nullStartByte)
+                        // We need to clear startBitInByte least significant bits
+                        nullmapByte &= (0xFF << startBitInByte);
+
+                    if (i == nullEndByte)
+                        // We need to clear 8-endBitInByte most significant bits
+                        nullmapByte &= (0xFF >> (8 - endBitInByte));
+
+                    numNullsBefore += Columns.numberOfNullColumns(nullmapByte);
+                }
+
+                idx -= numNullsBefore;
+            }
+
+            idx -= cols.numberOfFixsizeColumns();
+
+            // Offset of idx-th column is from base offset.
+            int resOff = varlenItemOffset(idx);
+
+            long len = (idx == vartableItems() - 1) ?
+                // totalLength - columnStartOffset
+                (baseOff + chunkLength()) - resOff :
+                // nextColumnStartOffset - columnStartOffset
+                varlenItemOffset(idx + 1) - resOff;
+
+            return (len << 32) | resOff;
+        }
+    }
+
+    /**
+     * Tiny chunk format reader.
+     */
+    class TinyChunkReader extends AbstractChunkReader {
+        /**
+         * @param baseOff Base offset.
+         * @param nullMapLen Null-map length in bytes.
+         * @param hasVarTable Vartable presence flag.
+         */
+        TinyChunkReader(int baseOff, int nullMapLen, boolean hasVarTable) {
+            super(baseOff);
+
+            nullMapOff = baseOff + Byte.BYTES;
+            varTableOff = nullMapOff + nullMapLen;
+            dataOff = varTableOff + (hasVarTable ? Byte.BYTES + (readByte(varTableOff) & 0xFF) * Byte.BYTES : 0);
+        }
+
+        /** {@inheritDoc} */
+        @Override int chunkLength() {
+            return readByte(baseOff) & 0xFF;
+        }
+
+        /** {@inheritDoc} */
+        @Override int vartableItems() {
+            return hasVartable() ? (readByte(varTableOff) & 0xFF) : 0;
+        }
+
+        /** {@inheritDoc} */
+        @Override protected int varlenItemOffset(int itemIdx) {
+            return dataOff + (readByte(varTableOff + Byte.BYTES + itemIdx * Byte.BYTES) & 0xFF);
+        }
+    }
+
+    /**
+     * Large chunk format reader.
+     */
+    class LargeChunkReader extends AbstractChunkReader {
+        /**
+         * @param baseOff Base offset.
+         * @param nullMapLen Null-map length in bytes.
+         * @param hasVarTable Vartable presence flag.
+         */
+        LargeChunkReader(int baseOff, int nullMapLen, boolean hasVarTable) {
+            super(baseOff);
+
+            nullMapOff = baseOff + Integer.BYTES;
+            varTableOff = baseOff + Integer.BYTES + nullMapLen;
+            dataOff = varTableOff + (hasVarTable ? Integer.BYTES + readInteger(varTableOff) * Integer.BYTES : 0);
+        }
+
+        /** {@inheritDoc} */
+        @Override public int chunkLength() {
+            return readInteger(baseOff);
+        }
+
+        /** {@inheritDoc} */
+        @Override int vartableItems() {
+            return hasVartable() ? readInteger(varTableOff) : 0;
+        }
+
+        /** {@inheritDoc} */
+        @Override protected int varlenItemOffset(int itemIdx) {
+            return dataOff + readInteger(varTableOff + Integer.BYTES + itemIdx * Integer.BYTES);
+        }
+    }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
new file mode 100644
index 0000000..b4e94c2
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
@@ -0,0 +1,485 @@
+/*
+ * 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.schema.row;
+
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.BitSet;
+import java.util.UUID;
+import org.apache.ignite.internal.schema.AssemblyException;
+import org.apache.ignite.internal.schema.BinaryRow;
+import org.apache.ignite.internal.schema.BinaryRow.RowFlags;
+import org.apache.ignite.internal.schema.BitmaskNativeType;
+import org.apache.ignite.internal.schema.Column;
+import org.apache.ignite.internal.schema.Columns;
+import org.apache.ignite.internal.schema.NativeType;
+import org.apache.ignite.internal.schema.NativeTypeSpec;
+import org.apache.ignite.internal.schema.NativeTypes;
+import org.apache.ignite.internal.schema.SchemaDescriptor;
+
+import static org.apache.ignite.internal.schema.BinaryRow.KEY_CHUNK_OFFSET;
+import static org.apache.ignite.internal.schema.BinaryRow.KEY_HASH_FIELD_OFFSET;
+import static org.apache.ignite.internal.schema.BinaryRow.RowFlags.OMIT_KEY_VARTBL_FLAG;
+import static org.apache.ignite.internal.schema.BinaryRow.RowFlags.OMIT_VAL_VARTBL_FLAG;
+
+/**
+ * Utility class to build rows using column appending pattern. The external user of this class must consult
+ * with the schema and provide the columns in strict internal column sort order during the row construction.
+ * Additionally, the user of this class should pre-calculate the resulting row size when possible to avoid
+ * unnecessary data copies and allow some size-optimizations can be applied.
+ *
+ * @see #utf8EncodedLength(CharSequence)
+ */
+public class RowAssembler {
+    /** Schema. */
+    private final SchemaDescriptor schema;
+
+    /** The number of non-null varlen columns in values chunk. */
+    private final int nonNullVarlenValCols;
+
+    /** Target byte buffer to write to. */
+    private final ExpandableByteBuf buf;
+
+    /** Val write mode flag. */
+    private final boolean isSmallVal;
+
+    /** Current columns chunk. */
+    private Columns curCols;
+
+    /** Current field index (the field is unset). */
+    private int curCol;
+
+    /** Flags. */
+    private short flags;
+
+    /** Charset encoder for strings. Initialized lazily. */
+    private CharsetEncoder strEncoder;
+
+    /** Current chunk writer. */
+    private AbstractChunkWriter chunkWriter;
+
+    /**
+     * Calculates encoded string length.
+     *
+     * @param seq Char sequence.
+     * @return Encoded string length.
+     * @implNote This implementation is not tolerant to malformed char sequences.
+     */
+    public static int utf8EncodedLength(CharSequence seq) {
+        int cnt = 0;
+
+        for (int i = 0, len = seq.length(); i < len; i++) {
+            char ch = seq.charAt(i);
+
+            if (ch <= 0x7F)
+                cnt++;
+            else if (ch <= 0x7FF)
+                cnt += 2;
+            else if (Character.isHighSurrogate(ch)) {
+                cnt += 4;
+                ++i;
+            }
+            else
+                cnt += 3;
+        }
+
+        return cnt;
+    }
+
+    /**
+     * Creates RowAssembler for chunks of unknown size.
+     * <p>
+     * RowAssembler will use adaptive buffer size and omit some optimizations for small key/value chunks.
+     *
+     * @param schema Row schema.
+     * @param nonNullVarlenKeyCols Number of non-null varlen columns in key chunk.
+     * @param nonNullVarlenValCols Number of non-null varlen columns in value chunk.
+     */
+    public RowAssembler(
+        SchemaDescriptor schema,
+        int nonNullVarlenKeyCols,
+        int nonNullVarlenValCols
+    ) {
+        this(schema,
+            0,
+            schema.keyColumns().nullMapSize() > 0,
+            nonNullVarlenKeyCols,
+            0,
+            schema.valueColumns().nullMapSize() > 0,
+            nonNullVarlenValCols);
+    }
+
+    /**
+     * Creates RowAssembler for chunks with estimated sizes.
+     * <p>
+     * RowAssembler will apply optimizations based on chunks sizes estimations.
+     *
+     * @param schema Row schema.
+     * @param keyDataSize Key payload size. Estimated upper-bound or zero if unknown.
+     * @param nonNullVarlenKeyCols Number of non-null varlen columns in key chunk.
+     * @param valDataSize Value data size. Estimated upper-bound or zero if unknown.
+     * @param nonNullVarlenValCols Number of non-null varlen columns in value chunk.
+     */
+    public RowAssembler(
+        SchemaDescriptor schema,
+        int keyDataSize,
+        int nonNullVarlenKeyCols,
+        int valDataSize,
+        int nonNullVarlenValCols
+    ) {
+        this(
+            schema,
+            keyDataSize,
+            schema.keyColumns().nullMapSize() > 0,
+            nonNullVarlenKeyCols,
+            valDataSize,
+            schema.valueColumns().nullMapSize() > 0,
+            nonNullVarlenValCols);
+    }
+
+    /**
+     * Creates RowAssembler for chunks with estimated sizes.
+     * <p>
+     * RowAssembler will apply optimizations based on chunks sizes estimations.
+     *
+     * @param schema Row schema.
+     * @param keyDataSize Key payload size. Estimated upper-bound or zero if unknown.
+     * @param keyHasNulls Null flag. {@code True} if key has nulls values, {@code false} otherwise.
+     * @param nonNullVarlenKeyCols Number of non-null varlen columns in key chunk.
+     * @param valDataSize Value data size. Estimated upper-bound or zero if unknown.
+     * @param valHasNulls Null flag. {@code True} if value has nulls values, {@code false} otherwise.
+     * @param nonNullVarlenValCols Number of non-null varlen columns in value chunk.
+     */
+    public RowAssembler(
+        SchemaDescriptor schema,
+        int keyDataSize,
+        boolean keyHasNulls,
+        int nonNullVarlenKeyCols,
+        int valDataSize,
+        boolean valHasNulls,
+        int nonNullVarlenValCols
+    ) {
+        this.schema = schema;
+        this.nonNullVarlenValCols = nonNullVarlenValCols;
+
+        curCols = schema.keyColumns();
+        curCol = 0;
+        flags = 0;
+        strEncoder = null;
+
+        boolean isSmallKey = isTinyChunk(keyDataSize);
+        isSmallVal = isTinyChunk(valDataSize);
+
+        // Key flags.
+        if (schema.keyColumns().nullMapSize() == 0)
+            flags |= RowFlags.OMIT_KEY_NULL_MAP_FLAG;
+        if (nonNullVarlenKeyCols == 0)
+            flags |= OMIT_KEY_VARTBL_FLAG;
+        if (isSmallKey)
+            flags |= RowFlags.KEY_TYNY_FORMAT;
+
+        final int keyNullMapSize = keyHasNulls ? schema.keyColumns().nullMapSize() : 0;
+
+        int size = BinaryRow.HEADER_SIZE + keyDataSize + valDataSize +
+            keyNullMapSize +
+            (valHasNulls ? schema.valueColumns().nullMapSize() : 0) +
+            (isSmallKey ? TinyChunkWriter.vartableLength(nonNullVarlenKeyCols) :
+                LongChunkWriter.vartableLength(nonNullVarlenKeyCols)) +
+            (isSmallVal ? TinyChunkWriter.vartableLength(nonNullVarlenValCols) :
+                LongChunkWriter.vartableLength(nonNullVarlenValCols));
+
+        buf = new ExpandableByteBuf(size);
+        buf.putShort(0, (short)schema.version());
+
+        chunkWriter = createChunkWriter(KEY_CHUNK_OFFSET, keyNullMapSize, nonNullVarlenKeyCols, isSmallKey);
+    }
+
+    private boolean isTinyChunk(int dataSize) {
+        return dataSize > 0 && dataSize < 256;
+    }
+
+    /**
+     * Chunk writer factory method.
+     *
+     * @param baseOff Chunk base offset.
+     * @param nullMapLen Null-map size in bytes.
+     * @param vartblSize Amount of vartable items.
+     * @param tiny Tiny format flag.
+     * @return Chunk writer.
+     */
+    private AbstractChunkWriter createChunkWriter(int baseOff, int nullMapLen, int vartblSize, boolean tiny) {
+        return tiny ?
+            new TinyChunkWriter(
+                buf,
+                baseOff,
+                nullMapLen,
+                vartblSize) :
+            new LongChunkWriter(
+                buf,
+                baseOff,
+                nullMapLen,
+                vartblSize);
+    }
+
+    /**
+     * Appends {@code null} value for the current column to the chunk.
+     */
+    public void appendNull() {
+        Column col = curCols.column(curCol);
+
+        if (!col.nullable())
+            throw new IllegalArgumentException("Failed to set column (null was passed, but column is not nullable): " +
+                col);
+
+        chunkWriter.setNull(curCol);
+
+        shiftColumn();
+    }
+
+    /**
+     * Appends byte value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendByte(byte val) {
+        checkType(NativeTypes.BYTE);
+
+        chunkWriter.appendByte(val);
+
+        shiftColumn();
+    }
+
+    /**
+     * Appends short value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendShort(short val) {
+        checkType(NativeTypes.SHORT);
+
+        chunkWriter.appendShort(val);
+
+        shiftColumn();
+    }
+
+    /**
+     * Appends int value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendInt(int val) {
+        checkType(NativeTypes.INTEGER);
+
+        chunkWriter.appendInt(val);
+
+        shiftColumn();
+    }
+
+    /**
+     * Appends long value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendLong(long val) {
+        checkType(NativeTypes.LONG);
+
+        chunkWriter.appendLong(val);
+
+        shiftColumn();
+    }
+
+    /**
+     * Appends float value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendFloat(float val) {
+        checkType(NativeTypes.FLOAT);
+
+        chunkWriter.appendFloat(val);
+
+        shiftColumn();
+    }
+
+    /**
+     * Appends double value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendDouble(double val) {
+        checkType(NativeTypes.DOUBLE);
+
+        chunkWriter.appendDouble(val);
+
+        shiftColumn();
+    }
+
+    /**
+     * Appends UUID value for the current column to the chunk.
+     *
+     * @param uuid Column value.
+     */
+    public void appendUuid(UUID uuid) {
+        checkType(NativeTypes.UUID);
+
+        chunkWriter.appendUuid(uuid);
+
+        shiftColumn();
+    }
+
+    /**
+     * Appends String value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendString(String val) {
+        checkType(NativeTypes.STRING);
+
+        assert (flags & (schema.keyColumns() == curCols ? OMIT_KEY_VARTBL_FLAG : OMIT_VAL_VARTBL_FLAG)) == 0 :
+            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
+
+        chunkWriter.appendString(val, encoder());
+
+        shiftColumn();
+    }
+
+    /**
+     * Appends byte[] value for the current column to the chunk.
+     *
+     * @param val Column value.
+     */
+    public void appendBytes(byte[] val) {
+        checkType(NativeTypes.BYTES);
+
+        assert (flags & (schema.keyColumns() == curCols ? OMIT_KEY_VARTBL_FLAG : OMIT_VAL_VARTBL_FLAG)) == 0 :
+            "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
+
+        chunkWriter.appendBytes(val);
+
+        shiftColumn();
+    }
+
+    /**
+     * Appends BitSet value for the current column to the chunk.
+     *
+     * @param bitSet Column value.
+     */
+    public void appendBitmask(BitSet bitSet) {
+        Column col = curCols.column(curCol);
+
+        checkType(NativeTypeSpec.BITMASK);
+
+        BitmaskNativeType maskType = (BitmaskNativeType)col.type();
+
+        if (bitSet.length() > maskType.bits())
+            throw new IllegalArgumentException("Failed to set bitmask for column '" + col.name() + "' " +
+                "(mask size exceeds allocated size) [mask=" + bitSet + ", maxSize=" + maskType.bits() + "]");
+
+        chunkWriter.appendBitmask(bitSet, maskType.sizeInBytes());
+
+        shiftColumn();
+    }
+
+    /**
+     * @return Serialized row.
+     */
+    public byte[] build() {
+        if (schema.keyColumns() == curCols)
+            throw new AssemblyException("Key column missed: colIdx=" + curCol);
+        else {
+            if (curCol == 0)
+                flags |= RowFlags.NO_VALUE_FLAG;
+            else if (schema.valueColumns().length() != curCol)
+                throw new AssemblyException("Value column missed: colIdx=" + curCol);
+        }
+
+        buf.putShort(BinaryRow.FLAGS_FIELD_OFFSET, flags);
+
+        return buf.toArray();
+    }
+
+    /**
+     * @return UTF-8 string encoder.
+     */
+    private CharsetEncoder encoder() {
+        if (strEncoder == null)
+            strEncoder = StandardCharsets.UTF_8.newEncoder();
+
+        return strEncoder;
+    }
+
+    /**
+     * Checks that the type being appended matches the column type.
+     *
+     * @param type Type spec that is attempted to be appended.
+     */
+    private void checkType(NativeTypeSpec type) {
+        Column col = curCols.column(curCol);
+
+        if (col.type().spec() != type)
+            throw new IllegalArgumentException("Failed to set column (int was passed, but column is of different " +
+                "type): " + col);
+    }
+
+    /**
+     * Checks that the type being appended matches the column type.
+     *
+     * @param type Type that is attempted to be appended.
+     */
+    private void checkType(NativeType type) {
+        checkType(type.spec());
+    }
+
+    /**
+     * Shifts current column indexes as necessary, also
+     * switch to value chunk writer when moving from key to value columns.
+     */
+    private void shiftColumn() {
+        curCol++;
+
+        if (curCol == curCols.length()) {
+            // Write sizes.
+            chunkWriter.flush();
+
+            if (schema.valueColumns() == curCols)
+                return; // No more columns.
+
+            // Write key hash.
+            buf.putInt(KEY_HASH_FIELD_OFFSET, XXHash32.hash(buf.unwrap(), chunkWriter.dataOff, chunkWriter.curOff - chunkWriter.dataOff));
+
+            // Switch key->value columns.
+            curCols = schema.valueColumns();
+            curCol = 0;
+
+            // Write value flags.
+            if (nonNullVarlenValCols == 0)
+                flags |= OMIT_VAL_VARTBL_FLAG;
+            if (schema.valueColumns().nullMapSize() == 0)
+                flags |= RowFlags.OMIT_VAL_NULL_MAP_FLAG;
+            if (isSmallVal)
+                flags |= RowFlags.VAL_TYNY_FORMAT;
+
+            // Create value chunk writer.
+            chunkWriter = createChunkWriter(
+                BinaryRow.HEADER_SIZE + chunkWriter.chunkLength() /* Key chunk size */,
+                schema.valueColumns().nullMapSize(),
+                nonNullVarlenValCols,
+                isSmallVal);
+        }
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
new file mode 100644
index 0000000..3bde275
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
@@ -0,0 +1,77 @@
+/*
+ * 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.schema.row;
+
+/**
+ * Row chunk writer for small key/value chunks.
+ *
+ * Uses {@code byte} values for coding sizes/offsets,
+ * supports chunks with payload less upt to 255 bytes.
+ */
+class TinyChunkWriter extends AbstractChunkWriter {
+    /**
+     * Calculates vartable length (in bytes).
+     *
+     * @param items Vartable items.
+     * @return Vartable size in bytes.
+     */
+    static int vartableLength(int items) {
+        return items == 0 ? 0 : Byte.BYTES /* Table size */ + items * Byte.BYTES;
+    }
+
+    /**
+     * Creates chunk writer to write chunk in tiny format.
+     *
+     * @param buf Row buffer.
+     * @param baseOff Chunk base offset.
+     * @param nullMapLen Null-map size in bytes.
+     * @param vartblSize Amount of vartable items.
+     */
+    TinyChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize) {
+        super(
+            buf,
+            baseOff,
+            baseOff + Byte.BYTES /* Chunk size */,
+            baseOff + Byte.BYTES + nullMapLen,
+            baseOff + Byte.BYTES + nullMapLen + vartableLength(vartblSize));
+
+        curVartblItem = 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override void flush() {
+        final int size = chunkLength();
+
+        assert size < (2 << 8) && size > 0 : "Size field value overflow: " + size;
+
+        buf.put(baseOff, (byte)size);
+
+        if (curVartblItem > 0)
+            buf.put(varTblOff, (byte)curVartblItem);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void writeOffset(int tblEntryIdx, int off) {
+        final int itemOff = varTblOff + Byte.BYTES + tblEntryIdx * Byte.BYTES;
+
+        assert off < (2 << 8) && off >= 0 : "Varlen offset overflow: offset=" + off;
+        assert itemOff < dataOff : "Vartable overflow: size=" + itemOff;
+
+        buf.put(itemOff, (byte)off);
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/XXHash32.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/XXHash32.java
new file mode 100644
index 0000000..2b71c4a
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/XXHash32.java
@@ -0,0 +1,243 @@
+/*
+ * 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.schema.row;
+
+import java.nio.ByteBuffer;
+import java.util.zip.Checksum;
+
+import static java.lang.Integer.rotateLeft;
+
+/**
+ * Implementation of the xxhash32 hash algorithm.
+ *
+ * Copied from Commons Compress 1.14 <a href=
+ * "https://git-wip-us.apache.org/repos/asf?p=commons-compress.git;a=blob;f=src/main/java/org/apache/commons/compress/compressors/lz4/XXHash32.java;h=a406ffc197449be594d46f0d2712b2d4786a1e68;hb=HEAD">https://git-wip-us.apache.org/repos/asf?p=commons-compress.git;a=blob;f=src/main/java/org/apache/commons/compress/compressors/lz4/XXHash32.java;h=a406ffc197449be594d46f0d2712b2d4786a1e68;hb=HEAD</a>
+ * <p>
+ * NotThreadSafe
+ *
+ * @see <a href="http://cyan4973.github.io/xxHash/">xxHash</a>
+ * @since 1.11
+ */
+public class XXHash32 implements Checksum {
+    /** Buffer size. */
+    private static final int BUF_SIZE = 16;
+
+    /** Rotation shift. */
+    private static final int ROTATE_BITS = 13;
+
+    /** Prime number. */
+    private static final int PRIME1 = (int) 2654435761L;
+    /** Prime number. */
+    private static final int PRIME2 = (int) 2246822519L;
+    /** Prime number. */
+    private static final int PRIME3 = (int) 3266489917L;
+    /** Prime number. */
+    private static final int PRIME4 =  668265263;
+    /** Prime number. */
+    private static final int PRIME5 =  374761393;
+
+    /** One-byte len buffer. */
+    private final byte[] oneByte = new byte[1];
+
+    /** State. */
+    private final int[] state = new int[4];
+
+    // Note: the code used to use ByteBuffer but the manual method is 50% faster
+    // See: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/2f56fb5c
+    private final byte[] buffer = new byte[BUF_SIZE];
+
+    /** Seed. */
+    private final int seed;
+
+    /** */
+    private int totalLen;
+
+    /** Position. */
+    private int pos;
+
+    /** Set to true when the state array has been updated since the last reset. */
+    private boolean stateUpdated;
+
+    /**
+     * Calculates hash for byte buffer slice.
+     *
+     * @param buf Buffer.
+     * @param off Slice offset.
+     * @param len Slice len.
+     * @return Hash code.
+     */
+    public static int hash(ByteBuffer buf, int off, int len) {
+        final XXHash32 hasher = new XXHash32(0);
+
+        hasher.update(buf.array(), off + buf.arrayOffset(), len);
+
+        return (int)hasher.getValue();
+    }
+
+    /**
+     * Creates an XXHash32 instance with a seed of 0.
+     */
+    public XXHash32() {
+        this(0);
+    }
+
+    /**
+     * Creates an XXHash32 instance.
+     * @param seed the seed to use
+     */
+    public XXHash32(final int seed) {
+        this.seed = seed;
+        initializeState();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void reset() {
+        initializeState();
+        totalLen = 0;
+        pos = 0;
+        stateUpdated = false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void update(final int b) {
+        oneByte[0] = (byte) (b & 0xff);
+        update(oneByte, 0, 1);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void update(final byte[] b, int off, final int len) {
+        if (len <= 0) {
+            return;
+        }
+        totalLen += len;
+
+        final int end = off + len;
+
+        // Check if the unprocessed bytes and new bytes can fill a block of 16.
+        // Make this overflow safe in the event that len is Integer.MAX_VALUE.
+        // Equivalent to: (pos + len < BUF_SIZE)
+        if (pos + len - BUF_SIZE < 0) {
+            System.arraycopy(b, off, buffer, pos, len);
+            pos += len;
+            return;
+        }
+
+        // Process left-over bytes with new bytes
+        if (pos > 0) {
+            final int size = BUF_SIZE - pos;
+            System.arraycopy(b, off, buffer, pos, size);
+            process(buffer, 0);
+            off += size;
+        }
+
+        final int limit = end - BUF_SIZE;
+        while (off <= limit) {
+            process(b, off);
+            off += BUF_SIZE;
+        }
+
+        // Handle left-over bytes
+        if (off < end) {
+            pos = end - off;
+            System.arraycopy(b, off, buffer, 0, pos);
+        } else {
+            pos = 0;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getValue() {
+        int hash;
+        if (stateUpdated) {
+            // Hash with the state
+            hash =
+                rotateLeft(state[0],  1) +
+                    rotateLeft(state[1],  7) +
+                    rotateLeft(state[2], 12) +
+                    rotateLeft(state[3], 18);
+        } else {
+            // Hash using the original seed from position 2
+            hash = state[2] + PRIME5;
+        }
+        hash += totalLen;
+
+        int idx = 0;
+        final int limit = pos - 4;
+        for (; idx <= limit; idx += 4) {
+            hash = rotateLeft(hash + getInt(buffer, idx) * PRIME3, 17) * PRIME4;
+        }
+        while (idx < pos) {
+            hash = rotateLeft(hash + (buffer[idx++] & 0xff) * PRIME5, 11) * PRIME1;
+        }
+
+        hash ^= hash >>> 15;
+        hash *= PRIME2;
+        hash ^= hash >>> 13;
+        hash *= PRIME3;
+        hash ^= hash >>> 16;
+        return hash & 0xffffffffL;
+    }
+
+    /**
+     * Gets the little-endian int from 4 bytes starting at the specified index.
+     *
+     * @param buffer The data
+     * @param idx The index
+     * @return The little-endian int
+     */
+    private static int getInt(final byte[] buffer, final int idx) {
+        return ((buffer[idx    ] & 0xff)      ) |
+            ((buffer[idx + 1] & 0xff) <<  8) |
+            ((buffer[idx + 2] & 0xff) << 16) |
+            ((buffer[idx + 3] & 0xff) << 24);
+    }
+
+    /**
+     * Initialize state.
+     */
+    private void initializeState() {
+        state[0] = seed + PRIME1 + PRIME2;
+        state[1] = seed + PRIME2;
+        state[2] = seed;
+        state[3] = seed - PRIME1;
+    }
+
+    /**
+     * @param b Buffer.
+     * @param offset Offset.
+     */
+    private void process(final byte[] b, final int offset) {
+        // local shadows for performance
+        int s0 = state[0];
+        int s1 = state[1];
+        int s2 = state[2];
+        int s3 = state[3];
+
+        s0 = rotateLeft(s0 + getInt(b, offset) * PRIME2, ROTATE_BITS) * PRIME1;
+        s1 = rotateLeft(s1 + getInt(b, offset + 4) * PRIME2, ROTATE_BITS) * PRIME1;
+        s2 = rotateLeft(s2 + getInt(b, offset + 8) * PRIME2, ROTATE_BITS) * PRIME1;
+        s3 = rotateLeft(s3 + getInt(b, offset + 12) * PRIME2, ROTATE_BITS) * PRIME1;
+
+        state[0] = s0;
+        state[1] = s1;
+        state[2] = s2;
+        state[3] = s3;
+
+        stateUpdated = true;
+    }
+}
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ExpandableByteBufTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/ExpandableByteBufTest.java
index dc78997..b03cfe4 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/ExpandableByteBufTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/ExpandableByteBufTest.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.schema;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.charset.StandardCharsets;
+import org.apache.ignite.internal.schema.row.ExpandableByteBuf;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
index 86edaef..82a7e3b 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowAssemblerTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.schema;
 
 import java.util.Arrays;
 import java.util.UUID;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
@@ -50,7 +51,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendInt(33);
             asm.appendInt(-71);
@@ -59,7 +60,7 @@ public class RowAssemblerTest {
         }
 
         { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendInt(-33);
             asm.appendNull();
@@ -68,7 +69,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendInt(-33);
 
@@ -87,7 +88,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         { // With value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendShort((short)33);
             asm.appendShort((short)71L);
@@ -96,7 +97,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendShort((short)-33);
 
@@ -115,7 +116,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
 
             asm.appendShort((short)-33);
             asm.appendString("val");
@@ -124,7 +125,7 @@ public class RowAssemblerTest {
         }
 
         { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendShort((short)33);
             asm.appendNull();
@@ -133,7 +134,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendShort((short)33);
 
@@ -152,7 +153,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
 
             asm.appendShort((short)-33);
             asm.appendString("val");
@@ -161,7 +162,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendShort((short)33);
 
@@ -180,7 +181,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendShort((short)-33);
             asm.appendByte((byte)71);
@@ -189,7 +190,7 @@ public class RowAssemblerTest {
         }
 
         { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendNull();
             asm.appendByte((byte)-71);
@@ -198,7 +199,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendShort((short)33);
 
@@ -217,7 +218,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendShort((short)-1133);
             asm.appendShort((short)-1071);
@@ -226,7 +227,7 @@ public class RowAssemblerTest {
         }
 
         { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendNull();
             asm.appendShort((short)1171);
@@ -235,7 +236,7 @@ public class RowAssemblerTest {
         }
 
         { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendShort((short)1133);
             asm.appendNull();
@@ -244,7 +245,7 @@ public class RowAssemblerTest {
         }
 
         { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendNull();
             asm.appendNull();
@@ -253,7 +254,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendShort((short)1133);
 
@@ -272,7 +273,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
 
             asm.appendInt(-33);
             asm.appendString("val");
@@ -281,7 +282,7 @@ public class RowAssemblerTest {
         }
 
         { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
 
             asm.appendNull();
             asm.appendString("val");
@@ -290,7 +291,7 @@ public class RowAssemblerTest {
         }
 
         { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendInt(33);
             asm.appendNull();
@@ -299,7 +300,7 @@ public class RowAssemblerTest {
         }
 
         { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendNull();
             asm.appendNull();
@@ -308,7 +309,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendInt(33);
 
@@ -327,7 +328,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
 
             asm.appendByte((byte)-33);
             asm.appendString("val");
@@ -336,7 +337,7 @@ public class RowAssemblerTest {
         }
 
         { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
 
             asm.appendNull();
             asm.appendString("val");
@@ -345,7 +346,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendByte((byte)33);
 
@@ -364,7 +365,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
             asm.appendUuid(uuidVal);
@@ -375,7 +376,7 @@ public class RowAssemblerTest {
         }
 
         { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
             asm.appendNull();
@@ -384,7 +385,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
 
@@ -403,7 +404,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
             asm.appendUuid(uuidVal);
@@ -414,7 +415,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
 
@@ -433,29 +434,29 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
 
             asm.appendString("key");
             asm.appendBytes(new byte[] {-1, 1, 0, 120});
 
-            assertRowBytesEquals(new byte[] {42, 0, 2, 0, 95, -98, 1, 0, 11, 0, 0, 0, 1, 0, 8, 0, 107, 101, 121, 13, 0, 0, 0, 0, 1, 0, 9, 0, -1, 1, 0, 120}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 98, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 8, 0, 1, 0, -1, 1, 0, 120}, asm.build());
         }
 
         { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 18, 0, 95, -98, 1, 0, 11, 0, 0, 0, 1, 0, 8, 0, 107, 101, 121, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 106, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121, 2, 1}, asm.build());
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
 
-            assertRowBytesEquals(new byte[] {42, 0, 19, 0, 95, -98, 1, 0, 11, 0, 0, 0, 1, 0, 8, 0, 107, 101, 121}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 107, 0, -32, 58, -39, -77, 6, 1, 0, 107, 101, 121}, asm.build());
         }
     }
 
@@ -470,7 +471,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
 
             asm.appendString("key");
             asm.appendBytes(new byte[] {-1, 1, 0, 120});
@@ -479,7 +480,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
 
@@ -498,47 +499,47 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
             asm.appendShort((short)-71);
 
-            assertRowBytesEquals(new byte[] {42, 0, 16, 0, 95, -98, 1, 0, 12, 0, 0, 0, 0, 1, 0, 9, 0, 107, 101, 121, 7, 0, 0, 0, 0, -71, -1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 104, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 4, 0, -71, -1}, asm.build());
         }
 
         { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendNull();
             asm.appendShort((short)71);
 
-            assertRowBytesEquals(new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 7, 0, 0, 0, 0, 71, 0}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 5, 93, -52, 2, 2, 1, 4, 0, 71, 0}, asm.build());
         }
 
         { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 16, 0, 95, -98, 1, 0, 12, 0, 0, 0, 0, 1, 0, 9, 0, 107, 101, 121, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 104, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121, 2, 1}, asm.build());
         }
 
         { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendNull();
             asm.appendNull();
 
-            assertRowBytesEquals(new byte[] {42, 0, 24, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 5, 0, 0, 0, 1}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 104, 0, 5, 93, -52, 2, 2, 1, 2, 1}, asm.build());
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
 
-            assertRowBytesEquals(new byte[] {42, 0, 17, 0, 95, -98, 1, 0, 12, 0, 0, 0, 0, 1, 0, 9, 0, 107, 101, 121}, asm.build());
+            assertRowBytesEquals(new byte[] {42, 0, 105, 0, -32, 58, -39, -77, 7, 0, 1, 0, 107, 101, 121}, asm.build());
         }
     }
 
@@ -553,7 +554,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
             asm.appendShort((short)-71L);
@@ -562,7 +563,7 @@ public class RowAssemblerTest {
         }
 
         { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendNull();
             asm.appendShort((short)71);
@@ -571,7 +572,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
 
@@ -590,7 +591,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
 
             asm.appendString("key");
             asm.appendBytes(new byte[] {-1, 1, 0, 120});
@@ -599,7 +600,7 @@ public class RowAssemblerTest {
         }
 
         { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
 
             asm.appendNull();
             asm.appendBytes(new byte[] {-1, 1, 0, 120});
@@ -608,7 +609,7 @@ public class RowAssemblerTest {
         }
 
         { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
             asm.appendNull();
@@ -617,7 +618,7 @@ public class RowAssemblerTest {
         }
 
         { // Null both.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 0);
 
             asm.appendNull();
             asm.appendNull();
@@ -626,7 +627,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
 
@@ -645,7 +646,7 @@ public class RowAssemblerTest {
         SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
 
             asm.appendString("key");
             asm.appendBytes(new byte[] {-1, 1, 0, 120});
@@ -654,7 +655,7 @@ public class RowAssemblerTest {
         }
 
         { // Null key.
-            RowAssembler asm = new RowAssembler(schema, 0, 0, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 0, 128, 1);
 
             asm.appendNull();
             asm.appendBytes(new byte[] {-1, 1, 0, 120});
@@ -663,7 +664,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendString("key");
 
@@ -685,10 +686,10 @@ public class RowAssemblerTest {
             new Column("valStrCol", STRING, true)
         };
 
-        SchemaDescriptor schema = new SchemaDescriptor(tableId,42, keyCols, valCols);
+        SchemaDescriptor schema = new SchemaDescriptor(tableId, 42, keyCols, valCols);
 
         {
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 1);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 1);
 
             asm.appendShort((short)33);
             asm.appendString("keystr");
@@ -702,7 +703,7 @@ public class RowAssemblerTest {
         }
 
         { // Null value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendShort((short)33);
             asm.appendString("keystr2");
@@ -716,7 +717,7 @@ public class RowAssemblerTest {
         }
 
         { // No value.
-            RowAssembler asm = new RowAssembler(schema, 0, 1, 0);
+            RowAssembler asm = new RowAssembler(schema, 128, 1, 128, 0);
 
             asm.appendShort((short)33);
             asm.appendString("keystr");
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
index 659dd5f..5b87c56 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/RowTest.java
@@ -21,18 +21,20 @@ import java.util.Arrays;
 import java.util.BitSet;
 import java.util.Collections;
 import java.util.Random;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.ignite.internal.schema.NativeTypes.BYTE;
+import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
 import static org.apache.ignite.internal.schema.NativeTypes.DOUBLE;
 import static org.apache.ignite.internal.schema.NativeTypes.FLOAT;
 import static org.apache.ignite.internal.schema.NativeTypes.INTEGER;
 import static org.apache.ignite.internal.schema.NativeTypes.LONG;
 import static org.apache.ignite.internal.schema.NativeTypes.SHORT;
-import static org.apache.ignite.internal.schema.NativeTypes.UUID;
-import static org.apache.ignite.internal.schema.NativeTypes.BYTES;
 import static org.apache.ignite.internal.schema.NativeTypes.STRING;
+import static org.apache.ignite.internal.schema.NativeTypes.UUID;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
@@ -261,44 +263,29 @@ public class RowTest {
 
         int nonNullVarLenKeyCols = 0;
         int nonNullVarLenValCols = 0;
-        int nonNullVarLenKeySize = 0;
-        int nonNullVarLenValSize = 0;
 
         for (int i = 0; i < vals.length; i++) {
             NativeTypeSpec type = schema.column(i).type().spec();
 
             if (vals[i] != null && !type.fixedLength()) {
                 if (type == NativeTypeSpec.BYTES) {
-                    byte[] val = (byte[])vals[i];
-                    if (schema.isKeyColumn(i)) {
+                    if (schema.isKeyColumn(i))
                         nonNullVarLenKeyCols++;
-                        nonNullVarLenKeySize += val.length;
-                    }
-                    else {
+                    else
                         nonNullVarLenValCols++;
-                        nonNullVarLenValSize += val.length;
-                    }
                 }
                 else if (type == NativeTypeSpec.STRING) {
-                    if (schema.isKeyColumn(i)) {
+                    if (schema.isKeyColumn(i))
                         nonNullVarLenKeyCols++;
-                        nonNullVarLenKeySize += RowAssembler.utf8EncodedLength((CharSequence)vals[i]);
-                    }
-                    else {
+                    else
                         nonNullVarLenValCols++;
-                        nonNullVarLenValSize += RowAssembler.utf8EncodedLength((CharSequence)vals[i]);
-                    }
                 }
                 else
                     throw new IllegalStateException("Unsupported variable-length type: " + type);
             }
         }
 
-        int size = RowAssembler.rowSize(
-            schema.keyColumns(), nonNullVarLenKeyCols, nonNullVarLenKeySize,
-            schema.valueColumns(), nonNullVarLenValCols, nonNullVarLenValSize);
-
-        RowAssembler asm = new RowAssembler(schema, size, nonNullVarLenKeyCols, nonNullVarLenValCols);
+        RowAssembler asm = new RowAssembler(schema, nonNullVarLenKeyCols, nonNullVarLenValCols);
 
         for (int i = 0; i < vals.length; i++) {
             if (vals[i] == null)
@@ -355,7 +342,7 @@ public class RowTest {
 
         byte[] data = asm.build();
 
-        Row tup = new Row(schema, new ByteBufferRow(data));
+        Row row = new Row(schema, new ByteBufferRow(data));
 
         for (int i = 0; i < vals.length; i++) {
             Column col = schema.column(i);
@@ -363,10 +350,10 @@ public class RowTest {
             NativeTypeSpec type = col.type().spec();
 
             if (type == NativeTypeSpec.BYTES)
-                assertArrayEquals((byte[])vals[i], (byte[])NativeTypeSpec.BYTES.objectValue(tup, i),
+                assertArrayEquals((byte[])vals[i], (byte[])NativeTypeSpec.BYTES.objectValue(row, i),
                     "Failed for column: " + col);
             else
-                assertEquals(vals[i], type.objectValue(tup, i), "Failed for column: " + col);
+                assertEquals(vals[i], type.objectValue(row, i), "Failed for column: " + col);
         }
     }
 
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 01bda07..ceec3bd 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
@@ -25,8 +25,8 @@ import java.util.Random;
 import java.util.UUID;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.NativeTypes;
-import org.apache.ignite.internal.schema.Row;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.schema.TestUtils;
 import org.apache.ignite.internal.schema.marshaller.BinaryMode;
 import org.apache.ignite.internal.schema.marshaller.SerializationException;
diff --git a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ITDistributedTableTest.java b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ITDistributedTableTest.java
index 72ac0ce..bb8103b 100644
--- a/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ITDistributedTableTest.java
+++ b/modules/table/src/integrationTest/java/org/apache/ignite/distributed/ITDistributedTableTest.java
@@ -31,8 +31,8 @@ import org.apache.ignite.internal.affinity.RendezvousAffinityFunction;
 import org.apache.ignite.internal.schema.ByteBufferRow;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.NativeTypes;
-import org.apache.ignite.internal.schema.Row;
-import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.SchemaRegistry;
 import org.apache.ignite.internal.table.TableImpl;
@@ -203,7 +203,7 @@ public class ITDistributedTableTest {
      * @return Row.
      */
     @NotNull private Row getTestKey() {
-        RowAssembler rowBuilder = new RowAssembler(SCHEMA, 4096, 0, 0);
+        RowAssembler rowBuilder = new RowAssembler(SCHEMA, 0, 0);
 
         rowBuilder.appendLong(1L);
 
@@ -216,7 +216,7 @@ public class ITDistributedTableTest {
      * @return Row.
      */
     @NotNull private Row getTestRow() {
-        RowAssembler rowBuilder = new RowAssembler(SCHEMA, 4096, 0, 0);
+        RowAssembler rowBuilder = new RowAssembler(SCHEMA, 0, 0);
 
         rowBuilder.appendLong(1L);
         rowBuilder.appendLong(10L);
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/KVSerializer.java b/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/KVSerializer.java
index 5c4f32d..f13e20a 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/KVSerializer.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/KVSerializer.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.schema.marshaller;
 
-import org.apache.ignite.internal.schema.Row;
+import org.apache.ignite.internal.schema.row.Row;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/RecordSerializer.java b/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/RecordSerializer.java
index 08c676e..c74a5c8 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/RecordSerializer.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/RecordSerializer.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.schema.marshaller;
 
-import org.apache.ignite.internal.schema.Row;
+import org.apache.ignite.internal.schema.row.Row;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/TupleMarshaller.java b/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/TupleMarshaller.java
index e9728b4..7556fe3 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/TupleMarshaller.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/schema/marshaller/TupleMarshaller.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.schema.marshaller;
 
-import org.apache.ignite.internal.schema.Row;
+import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.table.Tuple;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/KVBinaryViewImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/KVBinaryViewImpl.java
index be1c3ac..174e577 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/KVBinaryViewImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/KVBinaryViewImpl.java
@@ -24,7 +24,7 @@ import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 import org.apache.ignite.internal.schema.BinaryRow;
-import org.apache.ignite.internal.schema.Row;
+import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.marshaller.TupleMarshaller;
 import org.apache.ignite.internal.schema.SchemaRegistry;
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/KVViewImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/KVViewImpl.java
index c744e93..91e3a19 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/KVViewImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/KVViewImpl.java
@@ -23,7 +23,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.internal.schema.BinaryRow;
-import org.apache.ignite.internal.schema.Row;
+import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.marshaller.KVSerializer;
 import org.apache.ignite.internal.schema.SchemaRegistry;
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java
index 27bdc44..f535508 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java
@@ -23,7 +23,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.internal.schema.BinaryRow;
-import org.apache.ignite.internal.schema.Row;
+import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.marshaller.RecordSerializer;
 import org.apache.ignite.internal.schema.SchemaRegistry;
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/RowChunkAdapter.java b/modules/table/src/main/java/org/apache/ignite/internal/table/RowChunkAdapter.java
index 9b0483a..2e213f1 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/RowChunkAdapter.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/RowChunkAdapter.java
@@ -22,7 +22,7 @@ import java.util.UUID;
 import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryObjects;
 import org.apache.ignite.internal.schema.Column;
-import org.apache.ignite.internal.schema.Row;
+import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.table.Tuple;
 import org.jetbrains.annotations.NotNull;
 
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java
index a7cee35..83884ac 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TableImpl.java
@@ -25,7 +25,7 @@ import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 import org.apache.ignite.internal.schema.BinaryRow;
-import org.apache.ignite.internal.schema.Row;
+import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.marshaller.TupleMarshaller;
 import org.apache.ignite.internal.schema.SchemaRegistry;
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TableRow.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TableRow.java
index 74ed57a..31ab606 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TableRow.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TableRow.java
@@ -19,7 +19,7 @@ package org.apache.ignite.internal.table;
 
 import java.util.Objects;
 import org.apache.ignite.internal.schema.Column;
-import org.apache.ignite.internal.schema.Row;
+import org.apache.ignite.internal.schema.row.Row;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.table.Tuple;
 import org.jetbrains.annotations.NotNull;
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
index 7a6aed4..2966b92 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
@@ -19,19 +19,16 @@ package org.apache.ignite.internal.table;
 
 import java.util.Arrays;
 import java.util.BitSet;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.Objects;
 import java.util.UUID;
-import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.schema.ByteBufferRow;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.Columns;
-import org.apache.ignite.internal.schema.Row;
-import org.apache.ignite.internal.schema.RowAssembler;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
-import org.apache.ignite.internal.schema.marshaller.TupleMarshaller;
 import org.apache.ignite.internal.schema.SchemaRegistry;
+import org.apache.ignite.internal.schema.marshaller.TupleMarshaller;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.table.Tuple;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -65,54 +62,57 @@ public class TupleMarshallerImpl implements TupleMarshaller {
 
         validate(keyTuple, schema.keyColumns());
 
-        ChunkData keyChunk = chunkData(schema.keyColumns(), keyTuple);
-        ChunkData valChunk = chunkData(schema.valueColumns(), valTuple);
+        TupleStatistics keyChunk = tupleStatistics(schema.keyColumns(), keyTuple);
+        TupleStatistics valChunk = tupleStatistics(schema.valueColumns(), valTuple);
 
         final RowAssembler rowBuilder = createAssembler(schema, keyChunk, valChunk);
 
         for (int i = 0; i < schema.keyColumns().length(); i++) {
             final Column col = schema.keyColumns().column(i);
 
-            writeColumn(rowBuilder, col, keyChunk.data.get(i));
+            writeColumn(rowBuilder, col, keyTuple.value(col.name()));
         }
 
-        if (valChunk.data != null) {
+        if (valTuple != null) {
             validate(valTuple, schema.valueColumns());
 
             for (int i = 0; i < schema.valueColumns().length(); i++) {
                 final Column col = schema.valueColumns().column(i);
 
-                writeColumn(rowBuilder, col, valChunk.data.get(i));
+                writeColumn(rowBuilder, col, valTuple.value(col.name()));
             }
         }
 
         return new Row(schema, new ByteBufferRow(rowBuilder.build()));
     }
 
-    private ChunkData chunkData(Columns cols, Tuple tuple) {
-        if (tuple == null)
-            return new ChunkData();
-
-        ChunkData chunk = new ChunkData();
+    /**
+     * Analyze given tuple and gather statistics.
+     *
+     * @param cols Columns which statistics is calculated for.
+     * @param tup Tuple to analyze.
+     * @return Tuple statistics.
+     */
+    private TupleStatistics tupleStatistics(Columns cols, Tuple tup) {
+        if (tup == null)
+            return new TupleStatistics();
 
-        chunk.data = new HashMap<>();
+        TupleStatistics chunk = new TupleStatistics();
 
         for (int i = 0; i < cols.length(); i++) {
             Column col = cols.column(i);
 
-            Object val = (tuple.contains(col.name())) ? tuple.value(col.name()) : col.defaultValue();
+            Object val = (tup.contains(col.name())) ? tup.value(col.name()) : col.defaultValue();
 
             if (val == null)
                 chunk.hasNulls = true;
             else {
-                chunk.data.put(i, val);
-
                 if (col.type().spec().fixedLength())
-                    chunk.dataSize += col.type().sizeInBytes();
+                    chunk.payloadLen += col.type().sizeInBytes();
                 else {
                     chunk.nonNullVarlen++;
 
-                    chunk.dataSize += getValueSize(val, col.type());
+                    chunk.payloadLen += getValueSize(val, col.type());
                 }
             }
         }
@@ -120,16 +120,12 @@ public class TupleMarshallerImpl implements TupleMarshaller {
         return chunk;
     }
 
-    class ChunkData {
-        public boolean hasNulls;
-        public int dataSize;
-        public int nonNullVarlen;
-        Map<Integer, Object> data;
-
-    }
-
     /**
+     * Validates columns values.
      *
+     * @param tuple Tuple to validate.
+     * @param columns Columns to validate against.
+     * @throws SchemaMismatchException If validation failed.
      */
     private void validate(Tuple tuple, Columns columns) {
         if (tuple instanceof TupleBuilderImpl) {
@@ -148,23 +144,19 @@ public class TupleMarshallerImpl implements TupleMarshaller {
     /**
      * Creates {@link RowAssembler} for key-value tuples.
      *
-     * @param keyTuple Key tuple.
-     * @param valTuple Value tuple.
+     * @param keyStat Key tuple statistics.
+     * @param valStat Value tuple statistics.
      * @return Row assembler.
      */
-    private RowAssembler createAssembler(SchemaDescriptor schema, ChunkData keyChunk, ChunkData valChunk) {
-        final int keyOffSize = RowAssembler.vartableOffSize(keyChunk.nonNullVarlen, keyChunk.dataSize);
-        final int valOffSize = RowAssembler.vartableOffSize(valChunk.nonNullVarlen, valChunk.dataSize);
-
-        int size = BinaryRow.HEADER_SIZE +
-            (keyChunk.hasNulls ? schema.keyColumns().nullMapSize() : 0) +
-            RowAssembler.vartableSize(valChunk.nonNullVarlen, valOffSize) +
-            keyChunk.dataSize +
-            (valChunk.hasNulls ? schema.valueColumns().nullMapSize() : 0) +
-            RowAssembler.vartableSize(valChunk.nonNullVarlen, valOffSize) +
-            valChunk.dataSize;
-
-        return new RowAssembler(schema, size, keyOffSize, keyChunk.nonNullVarlen, valOffSize, valChunk.nonNullVarlen);
+    private RowAssembler createAssembler(SchemaDescriptor schema, TupleStatistics keyStat, TupleStatistics valStat) {
+        return new RowAssembler(
+            schema,
+            keyStat.payloadLen,
+            keyStat.hasNulls,
+            keyStat.nonNullVarlen,
+            valStat.payloadLen,
+            valStat.hasNulls,
+            valStat.nonNullVarlen);
     }
 
     /**
@@ -234,4 +226,18 @@ public class TupleMarshallerImpl implements TupleMarshaller {
                 throw new IllegalStateException("Unexpected value: " + col.type());
         }
     }
+
+    /**
+     * Tuple statistics record.
+     */
+    private static class TupleStatistics {
+        /** Tuple has nulls. */
+        boolean hasNulls;
+
+        /** Payload length in bytes. */
+        int payloadLen;
+
+        /** Number of non-null varlen columns. */
+        int nonNullVarlen;
+    }
 }
diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java
index 8621d20..a66265c 100644
--- a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java
+++ b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListenerTest.java
@@ -28,9 +28,9 @@ import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.schema.ByteBufferRow;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.NativeTypes;
-import org.apache.ignite.internal.schema.Row;
-import org.apache.ignite.internal.schema.RowAssembler;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
+import org.apache.ignite.internal.schema.row.Row;
+import org.apache.ignite.internal.schema.row.RowAssembler;
 import org.apache.ignite.internal.table.distributed.command.DeleteAllCommand;
 import org.apache.ignite.internal.table.distributed.command.DeleteCommand;
 import org.apache.ignite.internal.table.distributed.command.DeleteExactAllCommand;
@@ -677,7 +677,7 @@ public class PartitionCommandListenerTest {
      * @return Row.
      */
     @NotNull private Row getTestKey(int key) {
-        RowAssembler rowBuilder = new RowAssembler(SCHEMA, 4096, 0, 0);
+        RowAssembler rowBuilder = new RowAssembler(SCHEMA, 0, 0);
 
         rowBuilder.appendInt(key);
 
@@ -690,7 +690,7 @@ public class PartitionCommandListenerTest {
      * @return Row.
      */
     @NotNull private Row getTestRow(int key, int val) {
-        RowAssembler rowBuilder = new RowAssembler(SCHEMA, 4096, 0, 0);
+        RowAssembler rowBuilder = new RowAssembler(SCHEMA, 0, 0);
 
         rowBuilder.appendInt(key);
         rowBuilder.appendInt(val);

[ignite-3] 06/15: Styles.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 1d9efdde51d1e3be6cb150cb27cf677349455e32
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Fri Jun 4 16:57:16 2021 +0300

    Styles.
---
 modules/api/src/main/java/org/apache/ignite/table/Tuple.java        | 1 +
 .../main/java/org/apache/ignite/internal/schema/NativeTypes.java    | 1 +
 .../ignite/internal/schema/builder/SchemaTableBuilderImpl.java      | 3 +++
 .../org/apache/ignite/internal/table/ColumnNotFoundException.java   | 6 +++++-
 .../org/apache/ignite/internal/table/SchemaMismatchException.java   | 6 +++++-
 .../java/org/apache/ignite/internal/table/TupleBuilderImpl.java     | 4 +++-
 6 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/modules/api/src/main/java/org/apache/ignite/table/Tuple.java b/modules/api/src/main/java/org/apache/ignite/table/Tuple.java
index b27a6e4..c9e0374 100644
--- a/modules/api/src/main/java/org/apache/ignite/table/Tuple.java
+++ b/modules/api/src/main/java/org/apache/ignite/table/Tuple.java
@@ -30,6 +30,7 @@ public interface Tuple {
     /**
      * Returns {@code true} if this tuple contains a column with the specified name.
      *
+     * @param colName Column name.
      * @return {@code true} if this tuple contains a column with the specified name. Otherwise returns {@code false}.
      */
     boolean contains(String colName);
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java
index bdd7809..2a306d4 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java
@@ -90,6 +90,7 @@ public class NativeTypes {
      *
      * @param precision Precision.
      * @param scale Scale.
+     * @return Native type.
      */
     public static NativeType decimalOf(int precision, int scale) {
         return new NumericNativeType(precision, scale);
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/SchemaTableBuilderImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/SchemaTableBuilderImpl.java
index 1da11d9..7cf8b0a 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/SchemaTableBuilderImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/builder/SchemaTableBuilderImpl.java
@@ -121,6 +121,9 @@ public class SchemaTableBuilderImpl implements SchemaTableBuilder {
 
     /**
      * Validate indices.
+     *
+     * @param indices Indices.
+     * @param columns Columns.
      */
     public static void validateIndices(Collection<TableIndex> indices, Collection<Column> columns) {
         Set<String> colNames = columns.stream().map(Column::name).collect(Collectors.toSet());
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/ColumnNotFoundException.java b/modules/table/src/main/java/org/apache/ignite/internal/table/ColumnNotFoundException.java
index 1fed0f0..2923c83 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/ColumnNotFoundException.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/ColumnNotFoundException.java
@@ -21,7 +21,11 @@ package org.apache.ignite.internal.table;
  * Invalid tuple invocation exception is thrown when tuple doesn't match the table schema.
  */
 public class ColumnNotFoundException extends SchemaMismatchException {
-    /** */
+    /**
+     * Creates a new exception with the given error message.
+     *
+     * @param msg Error message.
+     */
     public ColumnNotFoundException(String msg) {
         super(msg);
     }
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/SchemaMismatchException.java b/modules/table/src/main/java/org/apache/ignite/internal/table/SchemaMismatchException.java
index 6c04e80..815f217 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/SchemaMismatchException.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/SchemaMismatchException.java
@@ -23,7 +23,11 @@ import org.apache.ignite.lang.IgniteException;
  * Invalid tuple invocation exception is thrown when tuple doesn't match the table schema.
  */
 public class SchemaMismatchException extends IgniteException {
-    /** */
+    /**
+     * Creates a new exception with the given error message.
+     *
+     * @param msg Error message.
+     */
     public SchemaMismatchException(String msg) {
         super(msg);
     }
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleBuilderImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleBuilderImpl.java
index c1be439..66e93aa 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleBuilderImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleBuilderImpl.java
@@ -40,7 +40,9 @@ public class TupleBuilderImpl implements TupleBuilder, Tuple {
     private final SchemaDescriptor schemaDesc;
 
     /**
-     * Constructor.
+     * Creates tuple builder.
+     *
+     * @param schemaDesc Schema descriptor.
      */
     public TupleBuilderImpl(SchemaDescriptor schemaDesc) {
         Objects.requireNonNull(schemaDesc);

[ignite-3] 07/15: Merge branch 'main' into gg-14743

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit d55c967388998a6c581d9e590f5784d170ebf796
Merge: 1d9efdd 44d69d3
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Mon Jun 7 17:05:47 2021 +0300

    Merge branch 'main' into gg-14743

 .../main/java/org/apache/ignite/app/Ignition.java  |   7 +-
 .../org/apache/ignite/app/IgnitionManager.java     |  12 +-
 .../schemas/runner/NodeConfigurationSchema.java    |   5 -
 modules/baseline/pom.xml                           |   2 +-
 modules/calcite/README.txt                         |  35 ++
 modules/calcite/pom.xml                            | 230 +++++++
 modules/calcite/src/main/codegen/config.fmpp       | 646 +++++++++++++++++++
 .../src/main/codegen/includes/parserImpls.ftl      | 201 ++++++
 .../apache/calcite/plan/volcano/VolcanoUtils.java} |  12 +-
 .../internal/processors/query/calcite/Stubs.java}  |  20 +-
 .../query/calcite/metadata/IgniteMdCollation.java  | 574 +++++++++++++++++
 .../calcite/metadata/IgniteMdCumulativeCost.java   | 113 ++++
 .../calcite/metadata/IgniteMdDistinctRowCount.java |  52 ++
 .../calcite/metadata/IgniteMdDistribution.java     | 111 ++++
 .../metadata/IgniteMdNonCumulativeCost.java        |  46 ++
 .../metadata/IgniteMdPercentageOriginalRows.java   | 161 +++++
 .../query/calcite/metadata/IgniteMdPredicates.java |  50 ++
 .../query/calcite/metadata/IgniteMdRowCount.java   | 133 ++++
 .../calcite/metadata/IgniteMdSelectivity.java      | 125 ++++
 .../query/calcite/metadata/IgniteMetadata.java     |  45 ++
 .../query/calcite/metadata/RelMetadataQueryEx.java |  77 +++
 .../query/calcite/metadata/cost/IgniteCost.java    | 234 +++++++
 .../calcite/metadata/cost/IgniteCostFactory.java   | 101 +++
 .../query/calcite/prepare/IgnitePlanner.java       | 394 ++++++++++++
 .../query/calcite/prepare/IgnitePrograms.java      |  71 +++
 .../query/calcite/prepare/IgniteRelShuttle.java    | 228 +++++++
 .../query/calcite/prepare/IgniteSqlValidator.java  | 382 +++++++++++
 .../query/calcite/prepare/PlannerHelper.java       | 230 +++++++
 .../query/calcite/prepare/PlannerPhase.java        | 226 +++++++
 .../query/calcite/prepare/PlanningContext.java     | 370 +++++++++++
 .../query/calcite/prepare/ValidationResult.java    |  70 +++
 .../calcite/prepare/ddl/ColumnDefinition.java      |  83 +++
 .../calcite/prepare/ddl/CreateTableCommand.java    | 302 +++++++++
 .../query/calcite/prepare/ddl/DdlCommand.java}     |   9 +-
 .../prepare/ddl/DdlSqlToCommandConverter.java      | 367 +++++++++++
 .../calcite/prepare/ddl/DropTableCommand.java      |  74 +++
 .../query/calcite/rel/AbstractIgniteJoin.java      | 318 ++++++++++
 .../query/calcite/rel/AbstractIndexScan.java       | 163 +++++
 .../query/calcite/rel/IgniteAggregate.java         | 120 ++++
 .../query/calcite/rel/IgniteConvention.java}       |  42 +-
 .../rel/IgniteCorrelatedNestedLoopJoin.java        | 240 +++++++
 .../query/calcite/rel/IgniteExchange.java          |  98 +++
 .../processors/query/calcite/rel/IgniteFilter.java | 138 ++++
 .../query/calcite/rel/IgniteHashIndexSpool.java    | 143 +++++
 .../query/calcite/rel/IgniteIndexScan.java         | 148 +++++
 .../processors/query/calcite/rel/IgniteLimit.java  | 178 ++++++
 .../query/calcite/rel/IgniteMergeJoin.java         | 277 ++++++++
 .../query/calcite/rel/IgniteNestedLoopJoin.java    | 114 ++++
 .../query/calcite/rel/IgniteProject.java           | 223 +++++++
 .../query/calcite/rel/IgniteReceiver.java          | 145 +++++
 .../processors/query/calcite/rel/IgniteRel.java    |  89 +++
 .../query/calcite/rel/IgniteRelVisitor.java        | 185 ++++++
 .../processors/query/calcite/rel/IgniteSender.java | 144 +++++
 .../processors/query/calcite/rel/IgniteSort.java   | 125 ++++
 .../query/calcite/rel/IgniteSortedIndexSpool.java  | 152 +++++
 .../query/calcite/rel/IgniteTableFunctionScan.java |  77 +++
 .../query/calcite/rel/IgniteTableModify.java       | 104 +++
 .../query/calcite/rel/IgniteTableScan.java         | 136 ++++
 .../query/calcite/rel/IgniteTableSpool.java        |  91 +++
 .../query/calcite/rel/IgniteTrimExchange.java      | 119 ++++
 .../query/calcite/rel/IgniteUnionAll.java          | 146 +++++
 .../processors/query/calcite/rel/IgniteValues.java |  74 +++
 .../rel/ProjectableFilterableTableScan.java        | 185 ++++++
 .../query/calcite/rel/SourceAwareIgniteRel.java}   |  15 +-
 .../calcite/rel/agg/IgniteHashAggregateBase.java   |  46 ++
 .../calcite/rel/agg/IgniteMapAggregateBase.java    |  94 +++
 .../calcite/rel/agg/IgniteMapHashAggregate.java    | 101 +++
 .../calcite/rel/agg/IgniteMapSortAggregate.java    | 140 +++++
 .../calcite/rel/agg/IgniteReduceAggregateBase.java | 174 +++++
 .../calcite/rel/agg/IgniteReduceHashAggregate.java | 116 ++++
 .../calcite/rel/agg/IgniteReduceSortAggregate.java | 126 ++++
 .../calcite/rel/agg/IgniteSingleAggregateBase.java |  95 +++
 .../calcite/rel/agg/IgniteSingleHashAggregate.java |  71 +++
 .../calcite/rel/agg/IgniteSingleSortAggregate.java | 106 ++++
 .../calcite/rel/agg/IgniteSortAggregateBase.java   |  71 +++
 .../rel/logical/IgniteLogicalIndexScan.java        | 110 ++++
 .../rel/logical/IgniteLogicalTableScan.java        |  64 ++
 .../query/calcite/rel/set/IgniteMapMinus.java      | 141 +++++
 .../query/calcite/rel/set/IgniteMinusBase.java     | 100 +++
 .../query/calcite/rel/set/IgniteReduceMinus.java   | 135 ++++
 .../query/calcite/rel/set/IgniteSingleMinus.java   | 134 ++++
 .../calcite/rule/AbstractIgniteConverterRule.java  |  54 ++
 .../calcite/rule/CorrelateToNestedLoopRule.java    | 123 ++++
 .../calcite/rule/CorrelatedNestedLoopJoinRule.java | 192 ++++++
 .../query/calcite/rule/FilterConverterRule.java    |  58 ++
 .../rule/FilterSpoolMergeToHashIndexSpoolRule.java | 114 ++++
 .../FilterSpoolMergeToSortedIndexSpoolRule.java    | 118 ++++
 .../calcite/rule/HashAggregateConverterRule.java   | 117 ++++
 .../calcite/rule/LogicalScanConverterRule.java     |  83 +++
 .../query/calcite/rule/MergeJoinConverterRule.java |  75 +++
 .../query/calcite/rule/MinusConverterRule.java     |  94 +++
 .../calcite/rule/NestedLoopJoinConverterRule.java  |  56 ++
 .../query/calcite/rule/ProjectConverterRule.java   |  51 ++
 .../calcite/rule/SortAggregateConverterRule.java   | 144 +++++
 .../query/calcite/rule/SortConverterRule.java      |  77 +++
 .../rule/TableFunctionScanConverterRule.java       |  65 ++
 .../calcite/rule/TableModifyConverterRule.java     |  60 ++
 .../query/calcite/rule/UnionConverterRule.java     |  95 +++
 .../query/calcite/rule/ValuesConverterRule.java    |  56 ++
 .../calcite/rule/logical/ExposeIndexRule.java      |  73 +++
 .../calcite/rule/logical/FilterScanMergeRule.java  | 182 ++++++
 .../calcite/rule/logical/LogicalOrToUnionRule.java | 117 ++++
 .../calcite/rule/logical/ProjectScanMergeRule.java | 190 ++++++
 .../query/calcite/schema/ColumnDescriptor.java}    |  50 +-
 .../query/calcite/schema/IgniteIndex.java}         |  49 +-
 .../query/calcite/schema/IgniteSchema.java         |  71 +++
 .../query/calcite/schema/IgniteTable.java          | 109 ++++
 .../query/calcite/schema/TableDescriptor.java      |  87 +++
 .../query/calcite/sql/IgniteSqlCreateTable.java    | 117 ++++
 .../calcite/sql/IgniteSqlCreateTableOption.java    | 113 ++++
 .../sql/IgniteSqlCreateTableOptionEnum.java        |  55 ++
 .../calcite/sql/fun/IgniteSqlOperatorTable.java    |  65 ++
 .../calcite/sql/fun/SqlSystemRangeFunction.java    |  60 ++
 .../query/calcite/trait/CorrelationTrait.java      | 122 ++++
 .../query/calcite/trait/CorrelationTraitDef.java}  |  45 +-
 .../query/calcite/trait/DistributionFunction.java  | 225 +++++++
 .../query/calcite/trait/DistributionTrait.java     | 178 ++++++
 .../query/calcite/trait/DistributionTraitDef.java  |  55 ++
 .../query/calcite/trait/IgniteDistribution.java}   |  28 +-
 .../query/calcite/trait/IgniteDistributions.java   | 123 ++++
 .../query/calcite/trait/RelFactory.java}           |  25 +-
 .../query/calcite/trait/RewindabilityTrait.java    | 102 +++
 .../query/calcite/trait/RewindabilityTraitDef.java |  53 ++
 .../processors/query/calcite/trait/TraitUtils.java | 536 ++++++++++++++++
 .../query/calcite/trait/TraitsAwareIgniteRel.java  | 156 +++++
 .../query/calcite/type/IgniteTypeFactory.java      | 239 +++++++
 .../query/calcite/type/IgniteTypeSystem.java}      |  35 +-
 .../processors/query/calcite/util/Commons.java     | 428 +++++++++++++
 .../processors/query/calcite/util/HintUtils.java   |  61 ++
 .../query/calcite/util/IgniteResource.java         |  46 ++
 .../query/calcite/util/IndexConditions.java        | 143 +++++
 .../processors/query/calcite/util/RexUtils.java    | 577 +++++++++++++++++
 .../processors/query/calcite/util/TypeUtils.java   | 186 ++++++
 .../planner/AbstractAggregatePlannerTest.java      |  73 +++
 .../query/calcite/planner/AbstractPlannerTest.java | 697 +++++++++++++++++++++
 .../planner/AggregateDistinctPlannerTest.java      | 130 ++++
 .../calcite/planner/AggregatePlannerTest.java      | 305 +++++++++
 .../CorrelatedNestedLoopJoinPlannerTest.java       | 173 +++++
 .../query/calcite/planner/ExceptPlannerTest.java   | 329 ++++++++++
 .../calcite/planner/HashAggregatePlannerTest.java  | 128 ++++
 .../calcite/planner/HashIndexSpoolPlannerTest.java | 232 +++++++
 .../calcite/planner/JoinColocationPlannerTest.java | 204 ++++++
 .../calcite/planner/SortAggregatePlannerTest.java  | 151 +++++
 .../planner/SortedIndexSpoolPlannerTest.java       | 194 ++++++
 .../query/calcite/planner/TableDmlPlannerTest.java | 174 +++++
 .../query/calcite/planner/TableFunctionTest.java   | 110 ++++
 .../calcite/planner/TableSpoolPlannerTest.java     | 140 +++++
 .../query/calcite/sql/SqlDdlParserTest.java        | 325 ++++++++++
 .../ignite/cli/builtins/node/NodeManager.java      |  52 +-
 .../apache/ignite/cli/spec/NodeCommandSpec.java    |  19 +-
 .../apache/ignite/cli/IgniteCliInterfaceTest.java  |  14 +-
 .../processor/internal/Processor.java              |   1 +
 .../configuration/ConfigurationChangerTest.java    |  17 +-
 .../internal/util/ConfigurationUtilTest.java       |  25 +-
 .../sample/TraversableTreeNodeTest.java            |  22 +-
 .../ignite/configuration/ConfigurationValue.java   |   2 +-
 .../ignite/configuration/ConfigurationChanger.java |  76 +--
 .../internal/DynamicConfiguration.java             |  34 +-
 .../configuration/internal/DynamicProperty.java    |  26 +-
 .../ignite/configuration/internal/SuperRoot.java   |  13 +-
 .../internal/asm/ConfigurationAsmGenerator.java    |  30 +-
 .../internal/util/ConfigurationUtil.java           |  73 ++-
 .../configuration/tree/ConfigurationSource.java    |   6 +
 .../ignite/configuration/tree/NamedListNode.java   |   5 +-
 modules/core/pom.xml                               |  12 +
 .../apache/ignite/internal/util/ArrayUtils.java    |  45 +-
 .../ignite/internal/util/CollectionUtils.java      |  77 +++
 .../apache/ignite/internal/util/IgniteUtils.java   |  43 ++
 modules/metastorage-client/pom.xml                 |   6 +
 .../client/ITMetaStorageServiceTest.java           |  17 +-
 modules/metastorage/pom.xml                        |   7 +-
 .../internal/metastorage/MetaStorageManager.java   |  18 +-
 modules/network-annotation-processor/pom.xml       |   8 +-
 .../processor/ITAutoSerializableProcessorTest.java | 138 ----
 .../ITTransferableObjectProcessorTest.java         | 248 ++++++++
 .../processor/internal/AllTypesMessage.java        |  63 +-
 .../processor/internal/AllTypesMessageImpl.java    | 471 --------------
 ...derMessage.java => ConflictingTypeMessage.java} |   7 +-
 ...MessageFactory.java => ITTestMessageGroup.java} |   8 +-
 .../internal/InvalidAnnotatedTypeMessage.java      |   4 +-
 ...age.java => InvalidParameterGetterMessage.java} |   8 +-
 ...ge.java => InvalidReturnTypeGetterMessage.java} |   6 +-
 ...llTypesMessageFactory.java => SecondGroup.java} |   8 +-
 .../processor/internal/TransitiveMessage.java      |  33 +-
 ...Message.java => UnmarshallableTypeMessage.java} |   6 +-
 ... UnmarshallableTypeNonSerializableMessage.java} |   6 +-
 .../processor/annotations/AutoSerializable.java    |  72 ---
 .../internal/AutoSerializableProcessor.java        | 251 --------
 .../network/processor/internal/MessageClass.java   | 160 +++++
 .../internal/MessageDeserializerGenerator.java     | 212 -------
 .../processor/internal/MessageGroupWrapper.java    |  90 +++
 .../processor/internal/ProcessingException.java    |  42 +-
 .../internal/SerializationFactoryGenerator.java    |  69 --
 .../internal/TransferableObjectProcessor.java      | 258 ++++++++
 .../network/processor/internal/TypeUtils.java      |  52 +-
 .../internal/messages/MessageBuilderGenerator.java |  91 +++
 .../internal/messages/MessageFactoryGenerator.java |  81 +++
 .../internal/messages/MessageImplGenerator.java    | 230 +++++++
 .../BaseMethodNameResolver.java                    |  53 +-
 .../MessageCollectionItemTypeConverter.java        |  32 +-
 .../MessageDeserializerGenerator.java              | 160 +++++
 .../MessageReaderMethodResolver.java               |  19 +-
 .../MessageSerializerGenerator.java                |  69 +-
 .../MessageWriterMethodResolver.java               |  20 +-
 .../RegistryInitializerGenerator.java              |  91 +++
 .../SerializationFactoryGenerator.java             | 104 +++
 .../services/javax.annotation.processing.Processor |   2 +-
 .../internal/SerializationOrderMessage.java}       |  22 +-
 .../processor/internal/SerializationOrderTest.java |  95 +++
 .../processor/internal/TestMessageGroup.java}      |  13 +-
 .../org/apache/ignite/network/ClusterNode.java     |  12 +-
 .../org/apache/ignite/network/NetworkMessage.java  |  25 +-
 .../ignite/network/annotations/MessageGroup.java   |  71 +++
 .../ignite/network/annotations/Transferable.java   |  98 +++
 .../MessageSerializationRegistry.java              |  51 +-
 .../network/serialization/MessageWriter.java       |   5 +-
 .../org/apache/ignite/network/TestMessageImpl.java |  81 ---
 .../internal/netty/ConnectionManagerTest.java      |  30 +-
 .../internal/recovery/RecoveryHandshakeTest.java   |  36 +-
 .../network/scalecube/ITNodeRestartsTest.java      |  16 +-
 .../scalecube/ITScaleCubeNetworkMessagingTest.java |  44 +-
 .../network/MessageSerializationRegistryImpl.java  | 101 +++
 .../ignite/network/NetworkMessageTypes.java}       |  46 +-
 .../internal/direct/DirectMarshallingUtils.java    |  12 +-
 .../internal/direct/DirectMessageWriter.java       |  28 +-
 .../stream/DirectByteBufferStreamImplV1.java       |  81 ++-
 .../network/internal/netty/InboundDecoder.java     |   9 +-
 .../network/internal/netty/OutboundEncoder.java    |   3 +-
 .../recovery/RecoveryClientHandshakeManager.java   |  19 +-
 .../recovery/RecoveryServerHandshakeManager.java   |  19 +-
 .../recovery/message/HandshakeStartMessage.java    |  29 +-
 .../message/HandshakeStartResponseMessage.java     |  41 +-
 .../message/HandshakeStartResponseMessageImpl.java |  83 ---
 .../scalecube/ScaleCubeClusterServiceFactory.java  |   9 +-
 .../ScaleCubeDirectMarshallerTransport.java        |  21 +-
 .../scalecube/message/ScaleCubeMessage.java        |  21 +-
 .../scalecube/message/ScaleCubeMessageImpl.java    |  52 --
 .../MessageSerializationRegistryImplTest.java}     |  72 ++-
 .../org/apache/ignite/network/TestMessage.java}    |  13 +-
 .../TestMessageSerializationRegistryImpl.java}     |  15 +-
 .../apache/ignite/network/TestMessageTypes.java}   |  13 +-
 .../ignite/network/internal/AllTypesMessage.java   |  67 +-
 .../network/internal/AllTypesMessageGenerator.java | 259 ++++----
 .../network/internal/AllTypesMessageImpl.java      | 496 ---------------
 ...ssageFactory.java => NestedMessageMessage.java} |  11 +-
 .../network/internal/netty/InboundDecoderTest.java | 124 +++-
 .../network/internal/netty/NettyServerTest.java    |  70 +--
 modules/raft-client/pom.xml                        |   8 +-
 .../ignite/raft/client/message/ActionRequest.java  |  31 +-
 .../ignite/raft/client/message/ActionResponse.java |  21 +-
 .../raft/client/message/AddLearnersRequest.java    |  23 +-
 .../raft/client/message/AddPeersRequest.java       |  23 +-
 .../raft/client/message/ChangePeersResponse.java   |  23 +-
 .../raft/client/message/GetLeaderRequest.java      |  17 +-
 .../raft/client/message/GetLeaderResponse.java     |  17 +-
 .../raft/client/message/GetPeersRequest.java       |  23 +-
 .../raft/client/message/GetPeersResponse.java      |  23 +-
 .../client/message/RaftClientMessageFactory.java   |  93 ---
 .../client/message/RaftClientMessageGroup.java     |  96 +++
 .../raft/client/message/RaftErrorResponse.java     |  29 +-
 .../raft/client/message/RemoveLearnersRequest.java |  23 +-
 .../raft/client/message/RemovePeersRequest.java    |  23 +-
 .../raft/client/message/SnapshotRequest.java       |  17 +-
 .../client/message/TransferLeadershipRequest.java  |  23 +-
 .../client/message/impl/ActionRequestImpl.java     |  78 ---
 .../message/impl/AddLearnersRequestImpl.java       |  68 --
 .../message/impl/ChangePeersResponseImpl.java      |  65 --
 .../client/message/impl/GetLeaderRequestImpl.java  |  48 --
 .../client/message/impl/GetPeersRequestImpl.java   |  63 --
 .../client/message/impl/GetPeersResponseImpl.java  |  64 --
 .../message/impl/RaftClientMessageFactoryImpl.java | 109 ----
 .../client/message/impl/RaftErrorResponseImpl.java |  79 ---
 .../message/impl/RemoveLearnersRequestImpl.java    |  66 --
 .../message/impl/RemovePeersRequestImpl.java       |  65 --
 .../impl/TransferLeadershipRequestImpl.java        |  66 --
 .../client/service/impl/RaftGroupServiceImpl.java  |  26 +-
 .../raft/client/service/RaftGroupServiceTest.java  |   5 +-
 modules/raft/pom.xml                               |   6 +
 .../raft/server/RaftCounterServerAbstractTest.java |  17 +-
 .../java/org/apache/ignite/internal/raft/Loza.java |   7 +-
 .../ignite/raft/server/impl/RaftServerImpl.java    |  14 +-
 .../runner/app/DynamicTableCreationTest.java       |  30 +-
 .../ignite/internal/runner/app/IgnitionTest.java   |  28 +-
 .../internal/runner/app/TableCreationTest.java     |  25 +-
 .../org/apache/ignite/app/IgniteCliRunner.java     | 134 ++++
 .../apache/ignite/internal/app/IgnitionImpl.java   |  24 +-
 modules/table/pom.xml                              |   8 +-
 .../ignite/distributed/ITDistributedTableTest.java |  17 +-
 .../internal/table/distributed/TableManager.java   |   2 +-
 .../ignite/internal/table/TableManagerTest.java    |   3 +-
 .../apache/ignite/internal/vault/VaultManager.java |  34 +
 parent/pom.xml                                     | 167 ++++-
 pom.xml                                            |   1 +
 293 files changed, 24879 insertions(+), 4387 deletions(-)


[ignite-3] 05/15: Minor.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 926ef7fe01f040c6c482dec41199fa65c4aa98dc
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Fri Jun 4 11:44:45 2021 +0300

    Minor.
---
 .../{AbstractChunkWriter.java => ChunkWriter.java} |  4 +-
 .../internal/schema/row/LongChunkWriter.java       | 14 +++++-
 .../ignite/internal/schema/row/RowAssembler.java   | 55 +++++++++++-----------
 .../internal/schema/row/TinyChunkWriter.java       | 26 +++++++++-
 4 files changed, 68 insertions(+), 31 deletions(-)

diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/AbstractChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
similarity index 97%
rename from modules/schema/src/main/java/org/apache/ignite/internal/schema/row/AbstractChunkWriter.java
rename to modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
index 7ab7787..9b3a215 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/AbstractChunkWriter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
@@ -27,7 +27,7 @@ import org.apache.ignite.internal.schema.NativeTypes;
 /**
  * Abstract row chunk writer.
  */
-abstract class AbstractChunkWriter {
+abstract class ChunkWriter {
     /** Chunk buffer. */
     protected final ExpandableByteBuf buf;
 
@@ -55,7 +55,7 @@ abstract class AbstractChunkWriter {
      * @param nullMapOff Null-map offset.
      * @param varTblOff Vartable offset.
      */
-    protected AbstractChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapOff, int varTblOff, int dataOff) {
+    protected ChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapOff, int varTblOff, int dataOff) {
         this.buf = buf;
         this.baseOff = baseOff;
         this.nullMapOff = nullMapOff;
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/LongChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/LongChunkWriter.java
index 2c75d37..a7e94a2 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/LongChunkWriter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/LongChunkWriter.java
@@ -23,7 +23,7 @@ package org.apache.ignite.internal.schema.row;
  * Uses {@code int} values for coding sizes/offsets,
  * supports chunks with payload up to 2 GiB.
  */
-class LongChunkWriter extends AbstractChunkWriter {
+class LongChunkWriter extends ChunkWriter {
     /**
      * Calculates vartable length (in bytes).
      *
@@ -35,6 +35,18 @@ class LongChunkWriter extends AbstractChunkWriter {
     }
 
     /**
+     * Calculates chunk size.
+     *
+     * @param payloadLen Payload size in bytes.
+     * @param nullMapLen Null-map size in bytes.
+     * @param vartblSize Amount of vartable items.
+     * @return Bytes required to write a chunk or {@code -1} if a chunk is too long.
+     */
+    static int chunkSize(int payloadLen, int nullMapLen, int vartblSize) {
+        return Integer.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblSize) + payloadLen;
+    }
+
+    /**
      * Creates chunk writer for long chunk format.
      *
      * @param buf Row buffer.
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
index b4e94c2..4024a50 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
@@ -50,13 +50,13 @@ public class RowAssembler {
     private final SchemaDescriptor schema;
 
     /** The number of non-null varlen columns in values chunk. */
-    private final int nonNullVarlenValCols;
+    private final int valVarlenCols;
 
     /** Target byte buffer to write to. */
     private final ExpandableByteBuf buf;
 
     /** Val write mode flag. */
-    private final boolean isSmallVal;
+    private final boolean tinyVal;
 
     /** Current columns chunk. */
     private Columns curCols;
@@ -71,7 +71,7 @@ public class RowAssembler {
     private CharsetEncoder strEncoder;
 
     /** Current chunk writer. */
-    private AbstractChunkWriter chunkWriter;
+    private ChunkWriter chunkWriter;
 
     /**
      * Calculates encoded string length.
@@ -160,53 +160,54 @@ public class RowAssembler {
      * @param schema Row schema.
      * @param keyDataSize Key payload size. Estimated upper-bound or zero if unknown.
      * @param keyHasNulls Null flag. {@code True} if key has nulls values, {@code false} otherwise.
-     * @param nonNullVarlenKeyCols Number of non-null varlen columns in key chunk.
+     * @param keyVarlenCols Number of non-null varlen columns in key chunk.
      * @param valDataSize Value data size. Estimated upper-bound or zero if unknown.
      * @param valHasNulls Null flag. {@code True} if value has nulls values, {@code false} otherwise.
-     * @param nonNullVarlenValCols Number of non-null varlen columns in value chunk.
+     * @param valVarlenCols Number of non-null varlen columns in value chunk.
      */
     public RowAssembler(
         SchemaDescriptor schema,
         int keyDataSize,
         boolean keyHasNulls,
-        int nonNullVarlenKeyCols,
+        int keyVarlenCols,
         int valDataSize,
         boolean valHasNulls,
-        int nonNullVarlenValCols
+        int valVarlenCols
     ) {
         this.schema = schema;
-        this.nonNullVarlenValCols = nonNullVarlenValCols;
+        this.valVarlenCols = valVarlenCols;
 
         curCols = schema.keyColumns();
         curCol = 0;
         flags = 0;
         strEncoder = null;
 
-        boolean isSmallKey = isTinyChunk(keyDataSize);
-        isSmallVal = isTinyChunk(valDataSize);
+        final int keyNullMapSize = keyHasNulls ? schema.keyColumns().nullMapSize() : 0;
+        final int valNullMapSize = valHasNulls ? schema.valueColumns().nullMapSize() : 0;
+
+        boolean tinyKey = TinyChunkWriter.isTinyChunk(keyDataSize, keyNullMapSize, keyVarlenCols);
+        tinyVal = TinyChunkWriter.isTinyChunk(valDataSize, keyNullMapSize, valVarlenCols);
 
         // Key flags.
         if (schema.keyColumns().nullMapSize() == 0)
             flags |= RowFlags.OMIT_KEY_NULL_MAP_FLAG;
-        if (nonNullVarlenKeyCols == 0)
+        if (keyVarlenCols == 0)
             flags |= OMIT_KEY_VARTBL_FLAG;
-        if (isSmallKey)
+        if (tinyKey)
             flags |= RowFlags.KEY_TYNY_FORMAT;
 
-        final int keyNullMapSize = keyHasNulls ? schema.keyColumns().nullMapSize() : 0;
-
-        int size = BinaryRow.HEADER_SIZE + keyDataSize + valDataSize +
-            keyNullMapSize +
-            (valHasNulls ? schema.valueColumns().nullMapSize() : 0) +
-            (isSmallKey ? TinyChunkWriter.vartableLength(nonNullVarlenKeyCols) :
-                LongChunkWriter.vartableLength(nonNullVarlenKeyCols)) +
-            (isSmallVal ? TinyChunkWriter.vartableLength(nonNullVarlenValCols) :
-                LongChunkWriter.vartableLength(nonNullVarlenValCols));
+        int size = BinaryRow.HEADER_SIZE +
+            (tinyKey ?
+                TinyChunkWriter.chunkSize(keyDataSize, keyNullMapSize, keyVarlenCols) :
+                LongChunkWriter.chunkSize(keyDataSize, keyNullMapSize, keyVarlenCols)) +
+            (tinyVal ?
+                TinyChunkWriter.chunkSize(valDataSize, valNullMapSize, valVarlenCols) :
+                LongChunkWriter.chunkSize(valDataSize, valNullMapSize, valVarlenCols));
 
         buf = new ExpandableByteBuf(size);
         buf.putShort(0, (short)schema.version());
 
-        chunkWriter = createChunkWriter(KEY_CHUNK_OFFSET, keyNullMapSize, nonNullVarlenKeyCols, isSmallKey);
+        chunkWriter = createChunkWriter(KEY_CHUNK_OFFSET, keyNullMapSize, keyVarlenCols, tinyKey);
     }
 
     private boolean isTinyChunk(int dataSize) {
@@ -222,7 +223,7 @@ public class RowAssembler {
      * @param tiny Tiny format flag.
      * @return Chunk writer.
      */
-    private AbstractChunkWriter createChunkWriter(int baseOff, int nullMapLen, int vartblSize, boolean tiny) {
+    private ChunkWriter createChunkWriter(int baseOff, int nullMapLen, int vartblSize, boolean tiny) {
         return tiny ?
             new TinyChunkWriter(
                 buf,
@@ -467,19 +468,19 @@ public class RowAssembler {
             curCol = 0;
 
             // Write value flags.
-            if (nonNullVarlenValCols == 0)
+            if (valVarlenCols == 0)
                 flags |= OMIT_VAL_VARTBL_FLAG;
             if (schema.valueColumns().nullMapSize() == 0)
                 flags |= RowFlags.OMIT_VAL_NULL_MAP_FLAG;
-            if (isSmallVal)
+            if (tinyVal)
                 flags |= RowFlags.VAL_TYNY_FORMAT;
 
             // Create value chunk writer.
             chunkWriter = createChunkWriter(
                 BinaryRow.HEADER_SIZE + chunkWriter.chunkLength() /* Key chunk size */,
                 schema.valueColumns().nullMapSize(),
-                nonNullVarlenValCols,
-                isSmallVal);
+                valVarlenCols,
+                tinyVal);
         }
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
index 3bde275..347e257 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
@@ -23,7 +23,7 @@ package org.apache.ignite.internal.schema.row;
  * Uses {@code byte} values for coding sizes/offsets,
  * supports chunks with payload less upt to 255 bytes.
  */
-class TinyChunkWriter extends AbstractChunkWriter {
+class TinyChunkWriter extends ChunkWriter {
     /**
      * Calculates vartable length (in bytes).
      *
@@ -35,6 +35,30 @@ class TinyChunkWriter extends AbstractChunkWriter {
     }
 
     /**
+     * Calculates chunk size.
+     *
+     * @param payloadLen Payload size in bytes.
+     * @param nullMapLen Null-map size in bytes.
+     * @param vartblSize Amount of vartable items.
+     * @return Bytes required to write a chunk or {@code -1} if a chunk is too long.
+     */
+    static int chunkSize(int payloadLen, int nullMapLen, int vartblSize) {
+        return Byte.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblSize) + payloadLen;
+    }
+
+    /**
+     * Check if chunk fits to max size.
+     *
+     * @param payloadLen Payload size in bytes.
+     * @param nullMapLen Null-map size in bytes.
+     * @param vartblSize Amount of vartable items.
+     * @return {@code true} if a chunk is tiny, {@code false} otherwise.
+     */
+    static boolean isTinyChunk(int payloadLen, int nullMapLen, int vartblSize) {
+        return chunkSize(payloadLen, nullMapLen, vartblSize) < 256;
+    }
+
+    /**
      * Creates chunk writer to write chunk in tiny format.
      *
      * @param buf Row buffer.

[ignite-3] 09/15: Minor.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit d1ff1cf8dbfe8d3994626d844f2da332e20be295
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Tue Jun 8 14:32:40 2021 +0300

    Minor.
---
 .../java/org/apache/ignite/internal/schema/Columns.java    | 14 ++++++++++++++
 .../org/apache/ignite/internal/schema/row/ChunkWriter.java |  2 ++
 .../apache/ignite/internal/schema/row/RowAssembler.java    |  4 ----
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java
index 131feba..72ca1ae 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Columns.java
@@ -59,6 +59,11 @@ public class Columns implements Serializable {
     private final int nullMapSize;
 
     /**
+     * Estimated max length of fixed-size columns.
+     */
+    private int fixsizeMaxLen;
+
+    /**
      * Fixed-size column length folding table. The table is used to quickly calculate the offset of a fixed-length
      * column based on the nullability map.
      */
@@ -183,6 +188,10 @@ public class Columns implements Serializable {
         return firstVarlenColIdx != -1;
     }
 
+    public int fixsizeMaxLen() {
+        return fixsizeMaxLen;
+    }
+
     /**
      * @param schemaBaseIdx Base index of this columns object in its schema.
      * @param cols User columns.
@@ -235,11 +244,13 @@ public class Columns implements Serializable {
         if (numFixsize == 0) {
             foldingTbl = EMPTY_FOLDING_TABLE;
             foldingMask = EMPTY_FOLDING_MASK;
+            fixsizeMaxLen = 0;
 
             return;
         }
 
         int fixsizeNullMapSize = (numFixsize + 7) / 8;
+        int maxLen = 0;
 
         int[][] res = new int[fixsizeNullMapSize][];
         int[] resMask = new int[fixsizeNullMapSize];
@@ -262,10 +273,13 @@ public class Columns implements Serializable {
 
                 mask++;
             }
+
+            maxLen += res[b][0];
         }
 
         foldingTbl = res;
         foldingMask = resMask;
+        fixsizeMaxLen = maxLen;
     }
 
     /**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
index 9b3a215..cb49e72 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkWriter.java
@@ -218,6 +218,8 @@ abstract class ChunkWriter {
      * @param colIdx Column index.
      */
     protected void setNull(int colIdx) {
+        assert nullMapOff < varTblOff : "Null map is omitted.";
+
         int byteInMap = colIdx / 8;
         int bitInByte = colIdx % 8;
 
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
index cd8a2ea..e555b49 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
@@ -214,10 +214,6 @@ public class RowAssembler {
         chunkWriter = createChunkWriter(KEY_CHUNK_OFFSET, keyNullMapSize, keyVarlenCols, tinyKey);
     }
 
-    private boolean isTinyChunk(int dataSize) {
-        return dataSize > 0 && dataSize < 256;
-    }
-
     /**
      * Chunk writer factory method.
      *

[ignite-3] 01/15: Add tiny,normal,large chunk formats.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit b0bc9e531233e5eb811227c1731b5f2e523b4204
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Fri May 28 21:53:05 2021 +0300

    Add tiny,normal,large chunk formats.
---
 .../apache/ignite/internal/schema/BinaryRow.java   |  17 +++
 .../ignite/internal/schema/ByteBufferRow.java      |  16 ++-
 .../org/apache/ignite/internal/schema/Column.java  |   2 +
 .../org/apache/ignite/internal/schema/Row.java     |  79 ++++++------
 .../ignite/internal/schema/RowAssembler.java       |  77 ++++++++++--
 .../marshaller/reflection/JavaSerializer.java      |   2 +-
 .../ignite/internal/table/TupleMarshallerImpl.java | 139 ++++++++++-----------
 7 files changed, 213 insertions(+), 119 deletions(-)

diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
index 8088491..74be9fb 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
@@ -28,16 +28,25 @@ import java.nio.ByteBuffer;
 public interface BinaryRow {
     /** */
     int SCHEMA_VERSION_OFFSET = 0;
+
     /** */
     int FLAGS_FIELD_OFFSET = SCHEMA_VERSION_OFFSET + 2 /* version length */;
+
     /** */
     int KEY_HASH_FIELD_OFFSET = FLAGS_FIELD_OFFSET + 2 /* flags length */;
+
     /** */
     int KEY_CHUNK_OFFSET = KEY_HASH_FIELD_OFFSET + 4 /* hash length */;
+
+    /** */
+    int HEADER_SIZE = KEY_CHUNK_OFFSET;
+
     /** */
     int CHUNK_LEN_FIELD_SIZE = 4;
+
     /** */
     int VARLEN_TABLE_SIZE_FIELD_SIZE = 2;
+
     /** */
     int VARLEN_COLUMN_OFFSET_FIELD_SIZE = 2;
 
@@ -148,6 +157,14 @@ public interface BinaryRow {
         /** Flag indicates value chunk omits varlen table. */
         public static final int OMIT_VAL_VARTBL_FLAG = 1 << 4;
 
+        public static final int KEY_TYNY_FORMAT = 1 << 5;
+
+        public static final int KEY_LARGE_ROW_FORMAT = 1 << 6;
+
+        public static final int VAL_TYNY_FORMAT = 1 << 7;
+
+        public static final int VAL_LARGE_FORMAT = 1 << 8;
+
         /** Stub. */
         private RowFlags() {
             // No-op.
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
index 6ae8889..9c9c81e 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/ByteBufferRow.java
@@ -129,8 +129,12 @@ public class ByteBufferRow implements BinaryRow {
 
     /** {@inheritDoc} */
     @Override public ByteBuffer keySlice() {
+        final short flags = readShort(FLAGS_FIELD_OFFSET);
+
         final int off = KEY_CHUNK_OFFSET;
-        final int len = readInteger(off);
+        final int len = (flags & RowFlags.KEY_LARGE_ROW_FORMAT) != 0 ? readInteger(off) :
+            (flags & RowFlags.KEY_TYNY_FORMAT) != 0 ? readByte(off) :
+                readShort(off);
 
         try {
             return buf.limit(off + len).position(off).slice();
@@ -143,8 +147,14 @@ public class ByteBufferRow implements BinaryRow {
 
     /** {@inheritDoc} */
     @Override public ByteBuffer valueSlice() {
-        int off = KEY_CHUNK_OFFSET + readInteger(KEY_CHUNK_OFFSET);
-        int len = hasValue() ? readInteger(off) : 0;
+        final short flags = readShort(FLAGS_FIELD_OFFSET);
+
+        int off = KEY_CHUNK_OFFSET +
+            ((flags & RowFlags.KEY_LARGE_ROW_FORMAT) != 0 ? readInteger(KEY_CHUNK_OFFSET) :
+            (flags & RowFlags.KEY_TYNY_FORMAT) != 0 ? readByte(KEY_CHUNK_OFFSET) : readShort(KEY_CHUNK_OFFSET));
+
+        int len = hasValue() ? (flags & RowFlags.VAL_LARGE_FORMAT) != 0 ? readInteger(off) :
+            (flags & RowFlags.VAL_TYNY_FORMAT) != 0 ? readByte(off) : readShort(off) : 0;
 
         try {
             return buf.limit(off + len).position(off).slice();
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Column.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Column.java
index 815f469..ecc0a85 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Column.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Column.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.schema;
 
 import java.io.Serializable;
 import java.util.function.Supplier;
+import org.apache.ignite.internal.tostring.IgniteToStringExclude;
 import org.apache.ignite.internal.tostring.S;
 import org.jetbrains.annotations.NotNull;
 
@@ -50,6 +51,7 @@ public class Column implements Comparable<Column>, Serializable {
     /**
      * Default value supplier.
      */
+    @IgniteToStringExclude
     private final Supplier<Object> defValSup;
 
     /**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java
index a2fa63e..4ed78b0 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/Row.java
@@ -39,14 +39,6 @@ public class Row implements BinaryRow {
     private final BinaryRow row;
 
     /**
-     * @param itemIdx Varlen table item index.
-     * @return Varlen item offset.
-     */
-    public static int varlenItemOffset(int itemIdx) {
-        return VARLEN_TABLE_SIZE_FIELD_SIZE + itemIdx * VARLEN_COLUMN_OFFSET_FIELD_SIZE;
-    }
-
-    /**
      * Constructor.
      *
      * @param schema Schema.
@@ -60,6 +52,14 @@ public class Row implements BinaryRow {
     }
 
     /**
+     * @param itemIdx Varlen table item index.
+     * @return Varlen item offset.
+     */
+    private int varlenItemOffset(int itemIdx, int itemSize) {
+        return itemSize + itemIdx * itemSize;
+    }
+
+    /**
      * @return Row schema.
      */
     public SchemaDescriptor rowSchema() {
@@ -347,13 +347,17 @@ public class Row implements BinaryRow {
 
         final short flags = readShort(FLAGS_FIELD_OFFSET);
 
+        int size = keyCol ?
+            ((flags & RowFlags.KEY_TYNY_FORMAT) != 0) ? 1 : (flags & RowFlags.KEY_LARGE_ROW_FORMAT) != 0 ? 4 : 2 :
+            (flags & RowFlags.VAL_TYNY_FORMAT) != 0 ? 1 : (flags & RowFlags.VAL_LARGE_FORMAT) != 0 ? 4 : 2;
+
         int off = KEY_CHUNK_OFFSET;
 
         if (!keyCol) {
             assert (flags & RowFlags.NO_VALUE_FLAG) == 0;
 
             // Jump to the next chunk, the size of the first chunk is written at the chunk start.
-            off += readInteger(off);
+            off += readAdaptiveSizedItem(off, size);
 
             // Adjust the column index according to the number of key columns.
             colIdx -= schema.keyColumns().length();
@@ -368,14 +372,14 @@ public class Row implements BinaryRow {
         boolean hasVarTable = ((keyCol ? RowFlags.OMIT_KEY_VARTBL_FLAG : RowFlags.OMIT_VAL_VARTBL_FLAG) & flags) == 0;
         boolean hasNullMap = ((keyCol ? RowFlags.OMIT_KEY_NULL_MAP_FLAG : RowFlags.OMIT_VAL_NULL_MAP_FLAG) & flags) == 0;
 
-        if (hasNullMap && isNull(off, colIdx))
+        if (hasNullMap && isNull(off + size, colIdx))
             return -1;
 
         assert hasVarTable || type.fixedLength();
 
         return type.fixedLength() ?
-            fixlenColumnOffset(cols, off, colIdx, hasVarTable, hasNullMap) :
-            varlenColumnOffsetAndLength(cols, off, colIdx, hasNullMap);
+            fixlenColumnOffset(cols, off, colIdx, hasVarTable, hasNullMap, size) :
+            varlenColumnOffsetAndLength(cols, off, colIdx, hasNullMap, size);
     }
 
     /**
@@ -391,13 +395,11 @@ public class Row implements BinaryRow {
     /**
      * Checks the row's null map for the given column index in the chunk.
      *
-     * @param baseOff Offset of the chunk start in the row.
+     * @param nullMapOff Null map offset
      * @param idx Offset of the column in the chunk.
      * @return {@code true} if the column value is {@code null}.
      */
-    private boolean isNull(int baseOff, int idx) {
-        int nullMapOff = nullMapOffset(baseOff);
-
+    private boolean isNull(int nullMapOff, int idx) {
         int nullByte = idx / 8;
         int posInByte = idx % 8;
 
@@ -439,17 +441,19 @@ public class Row implements BinaryRow {
      * @param baseOff Chunk base offset.
      * @param idx Column index in the chunk.
      * @param hasNullMap Has null map flag.
+     * @param adaptiveItemSize
      * @return Encoded offset (from the row start) and length of the column with the given index.
      */
-    private long varlenColumnOffsetAndLength(Columns cols, int baseOff, int idx, boolean hasNullMap) {
-        int vartableOff = baseOff + CHUNK_LEN_FIELD_SIZE;
+    private long varlenColumnOffsetAndLength(Columns cols, int baseOff, int idx, boolean hasNullMap,
+        int adaptiveItemSize) {
+        int vartableOff = baseOff + adaptiveItemSize /* Chunk len field size. */;
 
         int numNullsBefore = 0;
 
         if (hasNullMap) {
             vartableOff += cols.nullMapSize();
 
-            int nullMapOff = nullMapOffset(baseOff);
+            int nullMapOff = baseOff + adaptiveItemSize;
 
             int nullStartByte = cols.firstVarlengthColumn() / 8;
             int startBitInByte = cols.firstVarlengthColumn() % 8;
@@ -473,16 +477,16 @@ public class Row implements BinaryRow {
         }
 
         idx -= cols.numberOfFixsizeColumns() + numNullsBefore;
-        int vartableSize = readShort(vartableOff);
+        int vartableSize = readAdaptiveSizedItem(vartableOff, adaptiveItemSize);
 
         // Offset of idx-th column is from base offset.
-        int resOff = readShort(vartableOff + varlenItemOffset(idx));
+        int resOff = readAdaptiveSizedItem(vartableOff + varlenItemOffset(idx, adaptiveItemSize), adaptiveItemSize);
 
         long len = (idx == vartableSize - 1) ?
             // totalLength - columnStartOffset
-            readInteger(baseOff) - resOff :
+            readAdaptiveSizedItem(baseOff, adaptiveItemSize) - resOff :
             // nextColumnStartOffset - columnStartOffset
-            readShort(vartableOff + varlenItemOffset(idx + 1)) - resOff;
+            readAdaptiveSizedItem(vartableOff + varlenItemOffset(idx + 1, adaptiveItemSize), adaptiveItemSize) - resOff;
 
         return (len << 32) | (resOff + baseOff);
     }
@@ -496,12 +500,14 @@ public class Row implements BinaryRow {
      * @param idx Column index in the chunk.
      * @param hasVarTbl Has varlen table flag.
      * @param hasNullMap Has null map flag.
+     * @param adaptiveItemSize
      * @return Encoded offset (from the row start) of the requested fixlen column.
      */
-    int fixlenColumnOffset(Columns cols, int baseOff, int idx, boolean hasVarTbl, boolean hasNullMap) {
+    int fixlenColumnOffset(Columns cols, int baseOff, int idx, boolean hasVarTbl, boolean hasNullMap,
+        int adaptiveItemSize) {
         int colOff = 0;
 
-        int payloadOff = baseOff + CHUNK_LEN_FIELD_SIZE;
+        int payloadOff = baseOff + adaptiveItemSize /* Chunk len field size. */;
 
         // Calculate fixlen column offset.
         {
@@ -517,9 +523,9 @@ public class Row implements BinaryRow {
 
                 // Fold offset based on the whole map bytes in the schema
                 for (int i = 0; i < colByteIdx; i++)
-                    colOff += cols.foldFixedLength(i, readByte(nullMapOffset(baseOff) + i));
+                    colOff += cols.foldFixedLength(i, readByte(baseOff + adaptiveItemSize + i));
 
-                colOff += cols.foldFixedLength(colByteIdx, readByte(nullMapOffset(baseOff) + colByteIdx) | mask);
+                colOff += cols.foldFixedLength(colByteIdx, readByte(baseOff + adaptiveItemSize + colByteIdx) | mask);
             }
             else {
                 for (int i = 0; i < colByteIdx; i++)
@@ -530,20 +536,23 @@ public class Row implements BinaryRow {
         }
 
         if (hasVarTbl) {
-            short verlenItems = readShort(payloadOff);
+            int verlenItems = readAdaptiveSizedItem(payloadOff, adaptiveItemSize);
 
-            payloadOff += varlenItemOffset(verlenItems);
+            payloadOff += varlenItemOffset(verlenItems, adaptiveItemSize);
         }
 
         return payloadOff + colOff;
     }
 
-    /**
-     * @param baseOff Chunk base offset.
-     * @return Null map offset from the row start for the chunk with the given base.
-     */
-    private int nullMapOffset(int baseOff) {
-        return baseOff + CHUNK_LEN_FIELD_SIZE;
+    public int readAdaptiveSizedItem(int off, int size) {
+        switch (size) {
+            case Byte.BYTES:
+                return row.readByte(off);
+            case Short.BYTES:
+                return row.readShort(off);
+            default:
+                return row.readInteger(off);
+        }
     }
 
     /** {@inheritDoc} */
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java
index 770ab6d..021d72b 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/RowAssembler.java
@@ -51,6 +51,8 @@ public class RowAssembler {
     /** Target byte buffer to write to. */
     private final ExpandableByteBuf buf;
 
+    private final int valOffSize;
+
     /** Current columns chunk. */
     private Columns curCols;
 
@@ -72,6 +74,8 @@ public class RowAssembler {
     /** Offset of the varlen table for current chunk. */
     private int varlenTblChunkOff;
 
+    private int adaptiveItemSize;
+
     /** Row hashcode. */
     private int keyHash;
 
@@ -155,6 +159,14 @@ public class RowAssembler {
 
         return size + nonNullVarlenSize;
     }
+    public RowAssembler(
+        SchemaDescriptor schema,
+        int size,
+        int nonNullVarlenKeyCols,
+        int nonNullVarlenValCols
+    ) {
+        this(schema, size, 2, nonNullVarlenKeyCols, 2, nonNullVarlenValCols);
+    }
 
     /**
      * @param schema Row schema.
@@ -166,18 +178,21 @@ public class RowAssembler {
     public RowAssembler(
         SchemaDescriptor schema,
         int size,
+        int keyOffSize,
         int nonNullVarlenKeyCols,
+        int valOffSize,
         int nonNullVarlenValCols
     ) {
         this.schema = schema;
         this.nonNullVarlenValCols = nonNullVarlenValCols;
+        this.valOffSize = valOffSize;
 
         curCols = schema.keyColumns();
         flags = 0;
         keyHash = 0;
         strEncoder = null;
 
-        initOffsets(BinaryRow.KEY_CHUNK_OFFSET, nonNullVarlenKeyCols);
+        initOffsets(BinaryRow.KEY_CHUNK_OFFSET, keyOffSize, nonNullVarlenKeyCols);
 
         if (schema.keyColumns().nullMapSize() == 0)
             flags |= RowFlags.OMIT_KEY_NULL_MAP_FLAG;
@@ -185,6 +200,16 @@ public class RowAssembler {
         if (schema.valueColumns().nullMapSize() == 0)
             flags |= RowFlags.OMIT_VAL_NULL_MAP_FLAG;
 
+        if (keyOffSize == 1)
+            flags |= RowFlags.KEY_TYNY_FORMAT;
+        else if (keyOffSize != 2)
+            flags |= RowFlags.KEY_LARGE_ROW_FORMAT;
+
+        if (valOffSize == 1)
+            flags |= RowFlags.VAL_TYNY_FORMAT;
+        else if (valOffSize != 2)
+            flags |= RowFlags.VAL_LARGE_FORMAT;
+
         buf = new ExpandableByteBuf(size);
 
         buf.putShort(0, (short)schema.version());
@@ -192,7 +217,16 @@ public class RowAssembler {
         if (nonNullVarlenKeyCols == 0)
             flags |= OMIT_KEY_VARTBL_FLAG;
         else
-            buf.putShort(varlenTblChunkOff, (short)nonNullVarlenKeyCols);
+            writeAdaptiveItem(varlenTblChunkOff, (short)nonNullVarlenKeyCols);
+    }
+
+    public static int vartableOffSize(int vartableItems, int dataSize) {
+        if (dataSize + vartableItems + 2 < (1 << 8))
+            return 1;
+        if (dataSize + (vartableItems + 2) * 2 < (1 << 16))
+            return 2;
+        else
+            return 4;
     }
 
     /**
@@ -435,7 +469,22 @@ public class RowAssembler {
         assert (flags & (baseOff == BinaryRow.KEY_CHUNK_OFFSET ? OMIT_KEY_VARTBL_FLAG : OMIT_VAL_VARTBL_FLAG)) == 0 :
             "Illegal writing of varlen when 'omit vartable' flag is set for a chunk.";
 
-        buf.putShort(varlenTblChunkOff + Row.varlenItemOffset(tblEntryIdx), (short)off);
+        writeAdaptiveItem(varlenTblChunkOff + vartableItemOffset(tblEntryIdx), off);
+    }
+
+    private void writeAdaptiveItem(int off, int val) {
+        switch (adaptiveItemSize) {
+            case Byte.BYTES:
+                buf.put(off, (byte)val);
+
+                return;
+            case Short.BYTES:
+                buf.putShort(off, (short)val);
+
+                return;
+            default:
+                buf.putInt(off, val);
+        }
     }
 
     /**
@@ -505,19 +554,19 @@ public class RowAssembler {
         if (curCol == curCols.length()) {
             int chunkLen = curOff - baseOff;
 
-            buf.putInt(baseOff, chunkLen);
+            writeAdaptiveItem(baseOff, chunkLen);
 
             if (schema.valueColumns() == curCols)
                 return; // No more columns.
 
             curCols = schema.valueColumns(); // Switch key->value columns.
 
-            initOffsets(baseOff + chunkLen, nonNullVarlenValCols);
+            initOffsets(baseOff + chunkLen, valOffSize, nonNullVarlenValCols);
 
             if (nonNullVarlenValCols == 0)
                 flags |= OMIT_VAL_VARTBL_FLAG;
             else
-                buf.putShort(varlenTblChunkOff, (short)nonNullVarlenValCols);
+                writeAdaptiveItem(varlenTblChunkOff, (short)nonNullVarlenValCols);
         }
     }
 
@@ -525,16 +574,26 @@ public class RowAssembler {
      * @param base Chunk base offset.
      * @param nonNullVarlenCols Number of non-null varlen columns.
      */
-    private void initOffsets(int base, int nonNullVarlenCols) {
+    private void initOffsets(int base, int adaptiveItemSize, int nonNullVarlenCols) {
         baseOff = base;
 
+        this.adaptiveItemSize = adaptiveItemSize;
+
         curCol = 0;
         curVarlenTblEntry = 0;
 
-        nullMapOff = baseOff + BinaryRow.CHUNK_LEN_FIELD_SIZE;
+        nullMapOff = baseOff + adaptiveItemSize /* chunk length. */;
         varlenTblChunkOff = nullMapOff + curCols.nullMapSize();
 
-        curOff = varlenTblChunkOff + varlenTableChunkSize(nonNullVarlenCols);
+        curOff = varlenTblChunkOff + vartableSize(nonNullVarlenCols, adaptiveItemSize);
+    }
+
+    public int vartableItemOffset(int nonNullVarlenCols) {
+        return adaptiveItemSize + nonNullVarlenCols * adaptiveItemSize;
+    }
+
+    public static int vartableSize(int items, int itemSize) {
+        return items == 0 ? 0 : itemSize + items * itemSize;
     }
 
     /**
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
index 31bad5e..a36ef94 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/JavaSerializer.java
@@ -89,7 +89,7 @@ public class JavaSerializer extends AbstractSerializer {
             schema.keyColumns(), keyStat.nonNullCols, keyStat.nonNullColsSize,
             schema.valueColumns(), valStat.nonNullCols, valStat.nonNullColsSize);
 
-        return new RowAssembler(schema, size, keyStat.nonNullCols, valStat.nonNullCols);
+        return new RowAssembler(schema, size, 2, keyStat.nonNullCols, 2, valStat.nonNullCols);
     }
 
     /**
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
index c944c3c..7a6aed4 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/TupleMarshallerImpl.java
@@ -19,8 +19,11 @@ package org.apache.ignite.internal.table;
 
 import java.util.Arrays;
 import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Objects;
 import java.util.UUID;
+import org.apache.ignite.internal.schema.BinaryRow;
 import org.apache.ignite.internal.schema.ByteBufferRow;
 import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.Columns;
@@ -62,28 +65,72 @@ public class TupleMarshallerImpl implements TupleMarshaller {
 
         validate(keyTuple, schema.keyColumns());
 
-        final RowAssembler rowBuilder = createAssembler(schema, keyTuple, valTuple);
+        ChunkData keyChunk = chunkData(schema.keyColumns(), keyTuple);
+        ChunkData valChunk = chunkData(schema.valueColumns(), valTuple);
+
+        final RowAssembler rowBuilder = createAssembler(schema, keyChunk, valChunk);
 
         for (int i = 0; i < schema.keyColumns().length(); i++) {
             final Column col = schema.keyColumns().column(i);
 
-            writeColumn(keyTuple, col, rowBuilder);
+            writeColumn(rowBuilder, col, keyChunk.data.get(i));
         }
 
-        if (valTuple != null) {
+        if (valChunk.data != null) {
             validate(valTuple, schema.valueColumns());
 
             for (int i = 0; i < schema.valueColumns().length(); i++) {
                 final Column col = schema.valueColumns().column(i);
 
-                writeColumn(valTuple, col, rowBuilder);
+                writeColumn(rowBuilder, col, valChunk.data.get(i));
             }
         }
 
         return new Row(schema, new ByteBufferRow(rowBuilder.build()));
     }
 
-    /** */
+    private ChunkData chunkData(Columns cols, Tuple tuple) {
+        if (tuple == null)
+            return new ChunkData();
+
+        ChunkData chunk = new ChunkData();
+
+        chunk.data = new HashMap<>();
+
+        for (int i = 0; i < cols.length(); i++) {
+            Column col = cols.column(i);
+
+            Object val = (tuple.contains(col.name())) ? tuple.value(col.name()) : col.defaultValue();
+
+            if (val == null)
+                chunk.hasNulls = true;
+            else {
+                chunk.data.put(i, val);
+
+                if (col.type().spec().fixedLength())
+                    chunk.dataSize += col.type().sizeInBytes();
+                else {
+                    chunk.nonNullVarlen++;
+
+                    chunk.dataSize += getValueSize(val, col.type());
+                }
+            }
+        }
+
+        return chunk;
+    }
+
+    class ChunkData {
+        public boolean hasNulls;
+        public int dataSize;
+        public int nonNullVarlen;
+        Map<Integer, Object> data;
+
+    }
+
+    /**
+     *
+     */
     private void validate(Tuple tuple, Columns columns) {
         if (tuple instanceof TupleBuilderImpl) {
             TupleBuilderImpl t0 = (TupleBuilderImpl)tuple;
@@ -105,31 +152,27 @@ public class TupleMarshallerImpl implements TupleMarshaller {
      * @param valTuple Value tuple.
      * @return Row assembler.
      */
-    private RowAssembler createAssembler(SchemaDescriptor schema, Tuple keyTuple, Tuple valTuple) {
-        final ObjectStatistic keyStat = collectObjectStats(schema.keyColumns(), keyTuple);
-        final ObjectStatistic valStat = collectObjectStats(schema.valueColumns(), valTuple);
-
-        int size = RowAssembler.rowSize(
-            schema.keyColumns(), keyStat.nonNullCols, keyStat.nonNullColsSize,
-            schema.valueColumns(), valStat.nonNullCols, valStat.nonNullColsSize);
-
-        return new RowAssembler(schema, size, keyStat.nonNullCols, valStat.nonNullCols);
+    private RowAssembler createAssembler(SchemaDescriptor schema, ChunkData keyChunk, ChunkData valChunk) {
+        final int keyOffSize = RowAssembler.vartableOffSize(keyChunk.nonNullVarlen, keyChunk.dataSize);
+        final int valOffSize = RowAssembler.vartableOffSize(valChunk.nonNullVarlen, valChunk.dataSize);
+
+        int size = BinaryRow.HEADER_SIZE +
+            (keyChunk.hasNulls ? schema.keyColumns().nullMapSize() : 0) +
+            RowAssembler.vartableSize(valChunk.nonNullVarlen, valOffSize) +
+            keyChunk.dataSize +
+            (valChunk.hasNulls ? schema.valueColumns().nullMapSize() : 0) +
+            RowAssembler.vartableSize(valChunk.nonNullVarlen, valOffSize) +
+            valChunk.dataSize;
+
+        return new RowAssembler(schema, size, keyOffSize, keyChunk.nonNullVarlen, valOffSize, valChunk.nonNullVarlen);
     }
 
     /**
-     * @param tup Tuple.
-     * @param col Column.
      * @param rowAsm Row assembler.
+     * @param col Column.
+     * @param val Value.
      */
-    private void writeColumn(Tuple tup, Column col, RowAssembler rowAsm) {
-        Object val;
-
-        if (!tup.contains(col.name()))
-            val = col.defaultValue();
-        else {
-            val = tup.value(col.name());
-        }
-
+    private void writeColumn(RowAssembler rowAsm, Column col, Object val) {
         if (val == null) {
             rowAsm.appendNull();
 
@@ -191,50 +234,4 @@ public class TupleMarshallerImpl implements TupleMarshaller {
                 throw new IllegalStateException("Unexpected value: " + col.type());
         }
     }
-
-    /**
-     * Reads object fields and gather statistic.
-     *
-     * @param cols Schema columns.
-     * @param tup Tuple.
-     * @return Object statistic.
-     */
-    private ObjectStatistic collectObjectStats(Columns cols, Tuple tup) {
-        if (tup == null || !cols.hasVarlengthColumns())
-            return new ObjectStatistic(0, 0);
-
-        int cnt = 0;
-        int size = 0;
-
-        for (int i = cols.firstVarlengthColumn(); i < cols.length(); i++) {
-            Column col = cols.column(i);
-
-            final Object val = tup.contains(col.name()) ? tup.value(col.name()) : col.defaultValue();
-
-            if (val == null || cols.column(i).type().spec().fixedLength())
-                continue;
-
-            size += getValueSize(val, cols.column(i).type());
-            cnt++;
-        }
-
-        return new ObjectStatistic(cnt, size);
-    }
-
-    /**
-     * Object statistic.
-     */
-    private static class ObjectStatistic {
-        /** Non-null fields of varlen type. */
-        int nonNullCols;
-
-        /** Length of all non-null fields of varlen types. */
-        int nonNullColsSize;
-
-        /** Constructor. */
-        ObjectStatistic(int nonNullCols, int nonNullColsSize) {
-            this.nonNullCols = nonNullCols;
-            this.nonNullColsSize = nonNullColsSize;
-        }
-    }
 }

[ignite-3] 10/15: WIP.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit d9d414d22871d652cf746c40b6055e077cf35357
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Tue Jun 8 16:56:48 2021 +0300

    WIP.
---
 .../apache/ignite/internal/schema/BinaryRow.java   |   7 +-
 .../ignite/internal/schema/row/ChunkFormat.java    | 289 +++++++++++++++++++++
 .../ignite/internal/schema/row/ChunkReader.java    | 190 ++++++++++++++
 ...TinyChunkWriter.java => MeduimChunkWriter.java} |  30 +--
 .../org/apache/ignite/internal/schema/row/Row.java | 250 +-----------------
 .../ignite/internal/schema/row/RowAssembler.java   |  62 ++---
 .../internal/schema/row/TinyChunkWriter.java       |  49 +---
 .../ignite/internal/schema/row/XXHash32.java       | 243 -----------------
 8 files changed, 522 insertions(+), 598 deletions(-)

diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
index 83a73e0..9f13385 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryRow.java
@@ -157,12 +157,13 @@ public interface BinaryRow {
         /** Flag indicates value chunk omits varlen table. */
         public static final int OMIT_VAL_VARTBL_FLAG = 1 << 4;
 
-        /** Flag indicates key chunk is written in Tiny format. */
-        public static final int KEY_TYNY_FORMAT = 1 << 5;
-
         /** Flag indicates value chunk is written in Tiny format. */
         public static final int VAL_TYNY_FORMAT = 1 << 6;
 
+        /** Flag indicates key chunk is written in Tiny format. */
+        public static final int KEY_FORMAT_MASK = (2 ^ 4 - 1) << 8;
+        public static final int VALUE_FORMAT_MASK = (2 ^ 4 - 1) << 12;
+
         /** Stub. */
         private RowFlags() {
             // No-op.
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java
new file mode 100644
index 0000000..d5e8d17
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkFormat.java
@@ -0,0 +1,289 @@
+/*
+ * 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.schema.row;
+
+import org.apache.ignite.internal.schema.BinaryRow;
+
+/**
+ * Chunk writers factory.
+ */
+abstract class ChunkFormat {
+    /** Writer factory for tiny-sized chunks. */
+    private static final ChunkFormat TINY = new TinyChunkFormat();
+
+    /** Writer factory for med-sized chunks. */
+    private static final ChunkFormat MEDIUM = new MedChunkFormat();
+
+    /** Writer factory for large-sized chunks. */
+    private static final ChunkFormat LARGE = new LargeChunkFormat();
+
+    /**
+     * Check if chunk fits to max size.
+     *
+     * @param payloadLen Payload size in bytes.
+     * @param nullMapLen Null-map size in bytes.
+     * @param vartblSize Amount of vartable items.
+     * @return {@code true} if a chunk is tiny, {@code false} otherwise.
+     */
+    static ChunkFormat writeMode(int payloadLen, int nullMapLen, int vartblSize) {
+        if (TINY.chunkSize(payloadLen, nullMapLen, vartblSize) < 256)
+            return TINY;
+
+        if (MEDIUM.chunkSize(payloadLen, nullMapLen, vartblSize) < 64 * 1024)
+            return MEDIUM;
+
+        return LARGE;
+    }
+
+    /**
+     * @param payloadLen Row payload length in bytes.
+     * @param nullMapLen Null-map length in bytes.
+     * @param vartblItems Number of vartable items.
+     * @return Chunk size.
+     */
+    abstract int chunkSize(int payloadLen, int nullMapLen, int vartblItems);
+
+    /**
+     * Returns mode flags. First 4-bits are used.
+     *
+     * @return Chunk specific flags.
+     */
+    byte modeFlags() {
+        return 0;
+    }
+
+    /**
+     * Calculates vartable length (in bytes).
+     *
+     * @param items Vartable items.
+     * @return Vartable size in bytes.
+     */
+    protected abstract int vartableLength(int items);
+
+    /**
+     * Chunk writer factory method.
+     *
+     * @param buf Row buffer.
+     * @param baseOff Chunk base offset.
+     * @param nullMapLen Null-map length.
+     * @param vartblSize Vartable length.
+     * @return Chunk writer.
+     */
+    abstract ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize);
+
+    abstract ChunkReader reader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable);
+
+    /**
+     * Writer factory for tiny-sized chunks.
+     */
+    private static class TinyChunkFormat extends ChunkFormat {
+
+        /** {@inheritDoc} */
+        @Override protected int vartableLength(int items) {
+            return items == 0 ? 0 : Byte.BYTES /* Table size */ + items * Byte.BYTES;
+        }
+
+        /** {@inheritDoc} */
+        @Override int chunkSize(int payloadLen, int nullMapLen, int vartblItems) {
+            return Byte.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblItems) + payloadLen;
+        }
+
+        /** {@inheritDoc} */
+        @Override byte modeFlags() {
+            return 1;
+        }
+
+        /** {@inheritDoc} */
+        @Override ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize) {
+            return new TinyChunkWriter(buf,
+                baseOff,
+                baseOff + Byte.BYTES /* Chunk size */,
+                baseOff + Byte.BYTES + nullMapLen,
+                baseOff + Byte.BYTES + nullMapLen + vartableLength(vartblSize));
+        }
+
+        /** {@inheritDoc} */
+        @Override ChunkReader reader(BinaryRow row,int baseOff, int nullMapLen, boolean hasVarTable) {
+            return new TinyChunkReader(row, baseOff,  nullMapLen, hasVarTable);
+        }
+    }
+
+    /**
+     * Writer factory for med-size chunks.
+     */
+    private static class MedChunkFormat extends ChunkFormat {
+        /** {@inheritDoc} */
+        @Override protected int vartableLength(int items) {
+            return items == 0 ? 0 : Short.BYTES /* Table size */ + items * Short.BYTES;
+        }
+
+        /** {@inheritDoc} */
+        @Override int chunkSize(int payloadLen, int nullMapLen, int vartblItems) {
+            return Short.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblItems) + payloadLen;
+        }
+
+        /** {@inheritDoc} */
+        @Override byte modeFlags() {
+            return 2;
+        }
+
+        /** {@inheritDoc} */
+        @Override ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize) {
+            return new MeduimChunkWriter(buf,
+                baseOff,
+                baseOff + Short.BYTES /* Chunk size */,
+                baseOff + Short.BYTES + nullMapLen,
+                baseOff + Short.BYTES + nullMapLen + vartableLength(vartblSize));
+        }
+
+        /** {@inheritDoc} */
+        @Override ChunkReader reader(BinaryRow row,int baseOff, int nullMapLen, boolean hasVarTable) {
+            return new MediumChunkReader(row, baseOff,  nullMapLen, hasVarTable);
+        }
+    }
+
+    /**
+     * Writer factory for large-sized chunks.
+     */
+    private static class LargeChunkFormat extends ChunkFormat {
+        /** {@inheritDoc} */
+        @Override protected int vartableLength(int items) {
+            return items == 0 ? 0 : Integer.BYTES /* Table size */ + items * Integer.BYTES;
+        }
+
+        /** {@inheritDoc} */
+        @Override int chunkSize(int payloadLen, int nullMapLen, int vartblItems) {
+            return Integer.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblItems) + payloadLen;
+        }
+
+        /** {@inheritDoc} */
+        @Override ChunkWriter writer(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize) {
+            return new TinyChunkWriter(buf,
+                baseOff,
+                baseOff + Integer.BYTES /* Chunk size */,
+                baseOff + Integer.BYTES + nullMapLen,
+                baseOff + Integer.BYTES + nullMapLen + vartableLength(vartblSize));
+        }
+        /** {@inheritDoc} */
+        @Override ChunkReader reader(BinaryRow row,int baseOff, int nullMapLen, boolean hasVarTable) {
+            return new LargeChunkReader(row, baseOff,  nullMapLen, hasVarTable);
+        }
+    }
+
+    /**
+     * Tiny chunk format reader.
+     */
+    private static class TinyChunkReader extends ChunkReader {
+        /**
+         * @param row Row.
+         * @param baseOff Base offset.
+         * @param nullMapLen Null-map length in bytes.
+         * @param hasVarTable Vartable presence flag.
+         */
+        TinyChunkReader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable) {
+            super(row, baseOff);
+
+            nullMapOff = baseOff + Byte.BYTES;
+            varTableOff = nullMapOff + nullMapLen;
+            dataOff = varTableOff + (hasVarTable ? Byte.BYTES + (row.readByte(varTableOff) & 0xFF) * Byte.BYTES : 0);
+        }
+
+        /** {@inheritDoc} */
+        @Override int chunkLength() {
+            return row.readByte(baseOff) & 0xFF;
+        }
+
+        /** {@inheritDoc} */
+        @Override int vartableItems() {
+            return hasVartable() ? (row.readByte(varTableOff) & 0xFF) : 0;
+        }
+
+        /** {@inheritDoc} */
+        @Override protected int varlenItemOffset(int itemIdx) {
+            return dataOff + (row.readByte(varTableOff + Byte.BYTES + itemIdx * Byte.BYTES) & 0xFF);
+        }
+    }
+
+    /**
+     * Medium chunk format reader.
+     */
+    private static class MediumChunkReader extends ChunkReader {
+        /**
+         * @param row Row.
+         * @param baseOff Base offset.
+         * @param nullMapLen Null-map length in bytes.
+         * @param hasVarTable Vartable presence flag.
+         */
+        MediumChunkReader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable) {
+            super(row, baseOff);
+
+            nullMapOff = baseOff + Short.BYTES;
+            varTableOff = nullMapOff + nullMapLen;
+            dataOff = varTableOff + (hasVarTable ? Short.BYTES + (row.readShort(varTableOff) & 0xFFFF) * Short.BYTES : 0);
+        }
+
+        /** {@inheritDoc} */
+        @Override int chunkLength() {
+            return row.readShort(baseOff) & 0xFF;
+        }
+
+        /** {@inheritDoc} */
+        @Override int vartableItems() {
+            return hasVartable() ? (row.readShort(varTableOff) & 0xFFFF) : 0;
+        }
+
+        /** {@inheritDoc} */
+        @Override protected int varlenItemOffset(int itemIdx) {
+            return dataOff + (row.readShort(varTableOff + Short.BYTES + itemIdx * Short.BYTES) & 0xFFFF);
+        }
+    }
+
+    /**
+     * Large chunk format reader.
+     */
+    private static class LargeChunkReader extends ChunkReader {
+        /**
+         * @param row Row.
+         * @param baseOff Base offset.
+         * @param nullMapLen Null-map length in bytes.
+         * @param hasVarTable Vartable presence flag.
+         */
+        LargeChunkReader(BinaryRow row, int baseOff, int nullMapLen, boolean hasVarTable) {
+            super(row, baseOff);
+
+            nullMapOff = baseOff + Integer.BYTES;
+            varTableOff = baseOff + Integer.BYTES + nullMapLen;
+            dataOff = varTableOff + (hasVarTable ? Integer.BYTES + row.readInteger(varTableOff) * Integer.BYTES : 0);
+        }
+
+        /** {@inheritDoc} */
+        @Override public int chunkLength() {
+            return row.readInteger(baseOff);
+        }
+
+        /** {@inheritDoc} */
+        @Override int vartableItems() {
+            return hasVartable() ? row.readInteger(varTableOff) : 0;
+        }
+
+        /** {@inheritDoc} */
+        @Override protected int varlenItemOffset(int itemIdx) {
+            return dataOff + row.readInteger(varTableOff + Integer.BYTES + itemIdx * Integer.BYTES);
+        }
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
new file mode 100644
index 0000000..fd02415
--- /dev/null
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
@@ -0,0 +1,190 @@
+/*
+ * 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.schema.row;
+
+import org.apache.ignite.internal.schema.BinaryRow;
+import org.apache.ignite.internal.schema.Columns;
+
+/**
+ * Abstract chunk reader.
+ */
+abstract class ChunkReader {
+    /** Row. */
+    protected final BinaryRow row;
+
+    /** Base offset. */
+    protected final int baseOff;
+
+    /** Null-map offset. */
+    protected int nullMapOff;
+
+    /** Vartable offset. */
+    protected int varTableOff;
+
+    /** Payload offset. */
+    protected int dataOff;
+
+    /**
+     * @param baseOff Chunk base offset.
+     */
+    ChunkReader(BinaryRow row, int baseOff) {
+        this.row = row;
+        this.baseOff = baseOff;
+    }
+
+    /**
+     * @return Chunk length in bytes
+     */
+    abstract int chunkLength();
+
+    /**
+     * @return Number of items in vartable.
+     */
+    abstract int vartableItems();
+
+    /**
+     * Checks the row's null map for the given column index in the chunk.
+     *
+     * @param idx Offset of the column in the chunk.
+     * @return {@code true} if the column value is {@code null}.
+     */
+    /** {@inheritDoc} */
+    protected boolean isNull(int idx) {
+        if (!hasNullmap())
+            return false;
+
+        int nullByte = idx / 8;
+        int posInByte = idx % 8;
+
+        int map = row.readByte(nullMapOff + nullByte);
+
+        return (map & (1 << posInByte)) != 0;
+    }
+
+    /**
+     * @return {@code True} if chunk has vartable.
+     */
+    protected boolean hasVartable() {
+        return dataOff > varTableOff;
+    }
+
+    /**
+     * @return {@code True} if chunk has nullmap.
+     */
+    protected boolean hasNullmap() {
+        return varTableOff > nullMapOff;
+    }
+
+    /**
+     * @param itemIdx Varlen table item index.
+     * @return Varlen item offset.
+     */
+    protected abstract int varlenItemOffset(int itemIdx);
+
+    /**
+     * Calculates the offset of the fixlen column with the given index in the row. It essentially folds the null map
+     * with the column lengths to calculate the size of non-null columns preceding the requested column.
+     *
+     * @param cols Columns chunk.
+     * @param idx Column index in the chunk.
+     * @return Encoded offset (from the row start) of the requested fixlen column.
+     */
+    int fixlenColumnOffset(Columns cols, int idx) {
+        int colOff = 0;
+
+        // Calculate fixlen column offset.
+        {
+            int colByteIdx = idx / 8;
+
+            // Set bits starting from posInByte, inclusive, up to either the end of the byte or the last column index, inclusive
+            int startBit = idx % 8;
+            int endBit = colByteIdx == (cols.length() + 7) / 8 - 1 ? ((cols.numberOfFixsizeColumns() - 1) % 8) : 7;
+            int mask = (0xFF >> (7 - endBit)) & (0xFF << startBit);
+
+            if (hasNullmap()) {
+                // Fold offset based on the whole map bytes in the schema
+                for (int i = 0; i < colByteIdx; i++)
+                    colOff += cols.foldFixedLength(i, row.readByte(nullMapOff + i));
+
+                colOff += cols.foldFixedLength(colByteIdx, row.readByte(nullMapOff + colByteIdx) | mask);
+            }
+            else {
+                for (int i = 0; i < colByteIdx; i++)
+                    colOff += cols.foldFixedLength(i, 0);
+
+                colOff += cols.foldFixedLength(colByteIdx, mask);
+            }
+        }
+
+        return dataOff + colOff;
+    }
+
+    /**
+     * Calculates the offset and length of varlen column. First, it calculates the number of non-null columns
+     * preceding the requested column by folding the null map bits. This number is used to adjust the column index
+     * and find the corresponding entry in the varlen table. The length of the column is calculated either by
+     * subtracting two adjacent varlen table offsets, or by subtracting the last varlen table offset from the chunk
+     * length.
+     *
+     * @param cols Columns chunk.
+     * @param idx Column index in the chunk.
+     * @return Encoded offset (from the row start) and length of the column with the given index.
+     */
+    long varlenColumnOffsetAndLength(Columns cols, int idx) {
+        assert hasVartable() : "Chunk has no vartable: colId=" + idx;
+
+        if (hasNullmap()) {
+            int nullStartByte = cols.firstVarlengthColumn() / 8;
+            int startBitInByte = cols.firstVarlengthColumn() % 8;
+
+            int nullEndByte = idx / 8;
+            int endBitInByte = idx % 8;
+
+            int numNullsBefore = 0;
+
+            for (int i = nullStartByte; i <= nullEndByte; i++) {
+                byte nullmapByte = row.readByte(nullMapOff + i);
+
+                if (i == nullStartByte)
+                    // We need to clear startBitInByte least significant bits
+                    nullmapByte &= (0xFF << startBitInByte);
+
+                if (i == nullEndByte)
+                    // We need to clear 8-endBitInByte most significant bits
+                    nullmapByte &= (0xFF >> (8 - endBitInByte));
+
+                numNullsBefore += Columns.numberOfNullColumns(nullmapByte);
+            }
+
+            idx -= numNullsBefore;
+        }
+
+        idx -= cols.numberOfFixsizeColumns();
+
+        // Offset of idx-th column is from base offset.
+        int resOff = varlenItemOffset(idx);
+
+        long len = (idx == vartableItems() - 1) ?
+            // totalLength - columnStartOffset
+            (baseOff + chunkLength()) - resOff :
+            // nextColumnStartOffset - columnStartOffset
+            varlenItemOffset(idx + 1) - resOff;
+
+        return (len << 32) | resOff;
+    }
+}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/MeduimChunkWriter.java
similarity index 72%
copy from modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
copy to modules/schema/src/main/java/org/apache/ignite/internal/schema/row/MeduimChunkWriter.java
index 347e257..172dae1 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/MeduimChunkWriter.java
@@ -23,7 +23,7 @@ package org.apache.ignite.internal.schema.row;
  * Uses {@code byte} values for coding sizes/offsets,
  * supports chunks with payload less upt to 255 bytes.
  */
-class TinyChunkWriter extends ChunkWriter {
+class MeduimChunkWriter extends ChunkWriter {
     /**
      * Calculates vartable length (in bytes).
      *
@@ -31,7 +31,7 @@ class TinyChunkWriter extends ChunkWriter {
      * @return Vartable size in bytes.
      */
     static int vartableLength(int items) {
-        return items == 0 ? 0 : Byte.BYTES /* Table size */ + items * Byte.BYTES;
+        return items == 0 ? 0 : Short.BYTES /* Table size */ + items * Short.BYTES;
     }
 
     /**
@@ -43,7 +43,7 @@ class TinyChunkWriter extends ChunkWriter {
      * @return Bytes required to write a chunk or {@code -1} if a chunk is too long.
      */
     static int chunkSize(int payloadLen, int nullMapLen, int vartblSize) {
-        return Byte.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblSize) + payloadLen;
+        return Short.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblSize) + payloadLen;
     }
 
     /**
@@ -54,8 +54,8 @@ class TinyChunkWriter extends ChunkWriter {
      * @param vartblSize Amount of vartable items.
      * @return {@code true} if a chunk is tiny, {@code false} otherwise.
      */
-    static boolean isTinyChunk(int payloadLen, int nullMapLen, int vartblSize) {
-        return chunkSize(payloadLen, nullMapLen, vartblSize) < 256;
+    static boolean isMediumChunk(int payloadLen, int nullMapLen, int vartblSize) {
+        return chunkSize(payloadLen, nullMapLen, vartblSize) < 64 * 1024;
     }
 
     /**
@@ -66,13 +66,9 @@ class TinyChunkWriter extends ChunkWriter {
      * @param nullMapLen Null-map size in bytes.
      * @param vartblSize Amount of vartable items.
      */
-    TinyChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize) {
-        super(
-            buf,
-            baseOff,
-            baseOff + Byte.BYTES /* Chunk size */,
-            baseOff + Byte.BYTES + nullMapLen,
-            baseOff + Byte.BYTES + nullMapLen + vartableLength(vartblSize));
+    MeduimChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapOff, int varTblOff, int dataOff) {
+        super(buf,baseOff, nullMapOff, varTblOff, dataOff);
+
 
         curVartblItem = 0;
     }
@@ -81,21 +77,21 @@ class TinyChunkWriter extends ChunkWriter {
     @Override void flush() {
         final int size = chunkLength();
 
-        assert size < (2 << 8) && size > 0 : "Size field value overflow: " + size;
+        assert size < (2 << 16) && size > 0 : "Size field value overflow: " + size;
 
-        buf.put(baseOff, (byte)size);
+        buf.putShort(baseOff, (short)size);
 
         if (curVartblItem > 0)
-            buf.put(varTblOff, (byte)curVartblItem);
+            buf.putShort(varTblOff, (short)curVartblItem);
     }
 
     /** {@inheritDoc} */
     @Override protected void writeOffset(int tblEntryIdx, int off) {
-        final int itemOff = varTblOff + Byte.BYTES + tblEntryIdx * Byte.BYTES;
+        final int itemOff = varTblOff + Short.BYTES + tblEntryIdx * Short.BYTES;
 
         assert off < (2 << 8) && off >= 0 : "Varlen offset overflow: offset=" + off;
         assert itemOff < dataOff : "Vartable overflow: size=" + itemOff;
 
-        buf.put(itemOff, (byte)off);
+        buf.putShort(itemOff, (short)off);
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
index 15cb69e..ce80945 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
@@ -46,10 +46,10 @@ public class Row implements BinaryRow {
     private final BinaryRow row;
 
     /** Key reader. */
-    private final AbstractChunkReader keyReader;
+    private final ChunkReader keyReader;
 
     /** Value reader. */
-    private final AbstractChunkReader valReader;
+    private final ChunkReader valReader;
 
     /**
      * Constructor.
@@ -79,20 +79,6 @@ public class Row implements BinaryRow {
             null;
     }
 
-    /**
-     * Chunk reader factory method.
-     *
-     * @param baseOff Chunk base offset.
-     * @param isSmallChunk Small chunk format flag.
-     * @param nullMapLen Null-map length.
-     * @param hasVarTable Vartable presense flag.
-     * @return Chunk reader.
-     */
-    @NotNull private AbstractChunkReader createReader(int baseOff, boolean isSmallChunk, int nullMapLen, boolean hasVarTable) {
-        return isSmallChunk ?
-            new TinyChunkReader(baseOff, nullMapLen, hasVarTable) :
-            new LargeChunkReader(baseOff, nullMapLen, hasVarTable);
-    }
 
     /**
      * @return Row schema.
@@ -384,7 +370,7 @@ public class Row implements BinaryRow {
         if (!isKeyCol)
             colIdx -= schema.keyColumns().length();
 
-        AbstractChunkReader reader = isKeyCol ? keyReader : valReader;
+        ChunkReader reader = isKeyCol ? keyReader : valReader;
         Columns cols = isKeyCol ? schema.keyColumns() : schema.valueColumns();
 
         if (cols.column(colIdx).type().spec() != type)
@@ -500,234 +486,4 @@ public class Row implements BinaryRow {
         return row.readBytes(off, len);
     }
 
-    /**
-     * Abstract chunk reader.
-     */
-    abstract class AbstractChunkReader {
-        /** Base offset. */
-        protected final int baseOff;
-
-        /** Null-map offset. */
-        protected int nullMapOff;
-
-        /** Vartable offset. */
-        protected int varTableOff;
-
-        /** Payload offset. */
-        protected int dataOff;
-
-        /**
-         * @param baseOff Chunk base offset.
-         */
-        AbstractChunkReader(int baseOff) {
-            this.baseOff = baseOff;
-        }
-
-        /**
-         * @return Chunk length in bytes
-         */
-        abstract int chunkLength();
-
-        /**
-         * @return Number of items in vartable.
-         */
-        abstract int vartableItems();
-
-        /**
-         * Checks the row's null map for the given column index in the chunk.
-         *
-         * @param idx Offset of the column in the chunk.
-         * @return {@code true} if the column value is {@code null}.
-         */
-        /** {@inheritDoc} */
-        protected boolean isNull(int idx) {
-            if (!hasNullmap())
-                return false;
-
-            int nullByte = idx / 8;
-            int posInByte = idx % 8;
-
-            int map = readByte(nullMapOff + nullByte);
-
-            return (map & (1 << posInByte)) != 0;
-        }
-
-        /**
-         * @return {@code True} if chunk has vartable.
-         */
-        protected boolean hasVartable() {
-            return dataOff > varTableOff;
-        }
-
-        /**
-         * @return {@code True} if chunk has nullmap.
-         */
-        protected boolean hasNullmap() {
-            return varTableOff > nullMapOff;
-        }
-
-        /**
-         * @param itemIdx Varlen table item index.
-         * @return Varlen item offset.
-         */
-        protected abstract int varlenItemOffset(int itemIdx);
-
-        /**
-         * Calculates the offset of the fixlen column with the given index in the row. It essentially folds the null map
-         * with the column lengths to calculate the size of non-null columns preceding the requested column.
-         *
-         * @param cols Columns chunk.
-         * @param idx Column index in the chunk.
-         * @return Encoded offset (from the row start) of the requested fixlen column.
-         */
-        int fixlenColumnOffset(Columns cols, int idx) {
-            int colOff = 0;
-
-            // Calculate fixlen column offset.
-            {
-                int colByteIdx = idx / 8;
-
-                // Set bits starting from posInByte, inclusive, up to either the end of the byte or the last column index, inclusive
-                int startBit = idx % 8;
-                int endBit = colByteIdx == (cols.length() + 7) / 8 - 1 ? ((cols.numberOfFixsizeColumns() - 1) % 8) : 7;
-                int mask = (0xFF >> (7 - endBit)) & (0xFF << startBit);
-
-                if (hasNullmap()) {
-                    // Fold offset based on the whole map bytes in the schema
-                    for (int i = 0; i < colByteIdx; i++)
-                        colOff += cols.foldFixedLength(i, readByte(nullMapOff + i));
-
-                    colOff += cols.foldFixedLength(colByteIdx, readByte(nullMapOff + colByteIdx) | mask);
-                }
-                else {
-                    for (int i = 0; i < colByteIdx; i++)
-                        colOff += cols.foldFixedLength(i, 0);
-
-                    colOff += cols.foldFixedLength(colByteIdx, mask);
-                }
-            }
-
-            return dataOff + colOff;
-        }
-
-        /**
-         * Calculates the offset and length of varlen column. First, it calculates the number of non-null columns
-         * preceding the requested column by folding the null map bits. This number is used to adjust the column index
-         * and find the corresponding entry in the varlen table. The length of the column is calculated either by
-         * subtracting two adjacent varlen table offsets, or by subtracting the last varlen table offset from the chunk
-         * length.
-         *
-         * @param cols Columns chunk.
-         * @param idx Column index in the chunk.
-         * @return Encoded offset (from the row start) and length of the column with the given index.
-         */
-        long varlenColumnOffsetAndLength(Columns cols, int idx) {
-            assert hasVartable() : "Chunk has no vartable: colId=" + idx;
-
-            if (hasNullmap()) {
-                int nullStartByte = cols.firstVarlengthColumn() / 8;
-                int startBitInByte = cols.firstVarlengthColumn() % 8;
-
-                int nullEndByte = idx / 8;
-                int endBitInByte = idx % 8;
-
-                int numNullsBefore = 0;
-
-                for (int i = nullStartByte; i <= nullEndByte; i++) {
-                    byte nullmapByte = readByte(nullMapOff + i);
-
-                    if (i == nullStartByte)
-                        // We need to clear startBitInByte least significant bits
-                        nullmapByte &= (0xFF << startBitInByte);
-
-                    if (i == nullEndByte)
-                        // We need to clear 8-endBitInByte most significant bits
-                        nullmapByte &= (0xFF >> (8 - endBitInByte));
-
-                    numNullsBefore += Columns.numberOfNullColumns(nullmapByte);
-                }
-
-                idx -= numNullsBefore;
-            }
-
-            idx -= cols.numberOfFixsizeColumns();
-
-            // Offset of idx-th column is from base offset.
-            int resOff = varlenItemOffset(idx);
-
-            long len = (idx == vartableItems() - 1) ?
-                // totalLength - columnStartOffset
-                (baseOff + chunkLength()) - resOff :
-                // nextColumnStartOffset - columnStartOffset
-                varlenItemOffset(idx + 1) - resOff;
-
-            return (len << 32) | resOff;
-        }
-    }
-
-    /**
-     * Tiny chunk format reader.
-     */
-    class TinyChunkReader extends AbstractChunkReader {
-        /**
-         * @param baseOff Base offset.
-         * @param nullMapLen Null-map length in bytes.
-         * @param hasVarTable Vartable presence flag.
-         */
-        TinyChunkReader(int baseOff, int nullMapLen, boolean hasVarTable) {
-            super(baseOff);
-
-            nullMapOff = baseOff + Byte.BYTES;
-            varTableOff = nullMapOff + nullMapLen;
-            dataOff = varTableOff + (hasVarTable ? Byte.BYTES + (readByte(varTableOff) & 0xFF) * Byte.BYTES : 0);
-        }
-
-        /** {@inheritDoc} */
-        @Override int chunkLength() {
-            return readByte(baseOff) & 0xFF;
-        }
-
-        /** {@inheritDoc} */
-        @Override int vartableItems() {
-            return hasVartable() ? (readByte(varTableOff) & 0xFF) : 0;
-        }
-
-        /** {@inheritDoc} */
-        @Override protected int varlenItemOffset(int itemIdx) {
-            return dataOff + (readByte(varTableOff + Byte.BYTES + itemIdx * Byte.BYTES) & 0xFF);
-        }
-    }
-
-    /**
-     * Large chunk format reader.
-     */
-    class LargeChunkReader extends AbstractChunkReader {
-        /**
-         * @param baseOff Base offset.
-         * @param nullMapLen Null-map length in bytes.
-         * @param hasVarTable Vartable presence flag.
-         */
-        LargeChunkReader(int baseOff, int nullMapLen, boolean hasVarTable) {
-            super(baseOff);
-
-            nullMapOff = baseOff + Integer.BYTES;
-            varTableOff = baseOff + Integer.BYTES + nullMapLen;
-            dataOff = varTableOff + (hasVarTable ? Integer.BYTES + readInteger(varTableOff) * Integer.BYTES : 0);
-        }
-
-        /** {@inheritDoc} */
-        @Override public int chunkLength() {
-            return readInteger(baseOff);
-        }
-
-        /** {@inheritDoc} */
-        @Override int vartableItems() {
-            return hasVartable() ? readInteger(varTableOff) : 0;
-        }
-
-        /** {@inheritDoc} */
-        @Override protected int varlenItemOffset(int itemIdx) {
-            return dataOff + readInteger(varTableOff + Integer.BYTES + itemIdx * Integer.BYTES);
-        }
-    }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
index e555b49..0d43da4 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/RowAssembler.java
@@ -56,9 +56,6 @@ public class RowAssembler {
     /** Target byte buffer to write to. */
     private final ExpandableByteBuf buf;
 
-    /** Val write mode flag. */
-    private final boolean tinyVal;
-
     /** Current columns chunk. */
     private Columns curCols;
 
@@ -77,6 +74,9 @@ public class RowAssembler {
     /** Current chunk writer. */
     private ChunkWriter chunkWriter;
 
+    /** Value write mode. */
+    private ChunkFormat valWriteMode;
+
     /**
      * Calculates encoded string length.
      *
@@ -189,52 +189,25 @@ public class RowAssembler {
         final int keyNullMapSize = keyHasNulls ? schema.keyColumns().nullMapSize() : 0;
         final int valNullMapSize = valHasNulls ? schema.valueColumns().nullMapSize() : 0;
 
-        boolean tinyKey = TinyChunkWriter.isTinyChunk(keyDataSize, keyNullMapSize, keyVarlenCols);
-        tinyVal = TinyChunkWriter.isTinyChunk(valDataSize, keyNullMapSize, valVarlenCols);
+        final ChunkFormat keyWriteMode = ChunkFormat.writeMode(keyDataSize, keyNullMapSize, keyVarlenCols);
+        valWriteMode = ChunkFormat.writeMode(valDataSize, keyNullMapSize, valVarlenCols);
 
         // Key flags.
         if (schema.keyColumns().nullMapSize() == 0)
             flags |= RowFlags.OMIT_KEY_NULL_MAP_FLAG;
         if (keyVarlenCols == 0)
             flags |= OMIT_KEY_VARTBL_FLAG;
-        if (tinyKey)
-            flags |= RowFlags.KEY_TYNY_FORMAT;
+
+        flags |= keyWriteMode.modeFlags() & 0x0F << 8;
 
         int size = BinaryRow.HEADER_SIZE +
-            (tinyKey ?
-                TinyChunkWriter.chunkSize(keyDataSize, keyNullMapSize, keyVarlenCols) :
-                LongChunkWriter.chunkSize(keyDataSize, keyNullMapSize, keyVarlenCols)) +
-            (tinyVal ?
-                TinyChunkWriter.chunkSize(valDataSize, valNullMapSize, valVarlenCols) :
-                LongChunkWriter.chunkSize(valDataSize, valNullMapSize, valVarlenCols));
+            keyWriteMode.chunkSize(keyDataSize, keyNullMapSize, keyDataSize) +
+            valWriteMode.chunkSize(valDataSize, valNullMapSize, valDataSize);
 
         buf = new ExpandableByteBuf(size);
         buf.putShort(0, (short)schema.version());
 
-        chunkWriter = createChunkWriter(KEY_CHUNK_OFFSET, keyNullMapSize, keyVarlenCols, tinyKey);
-    }
-
-    /**
-     * Chunk writer factory method.
-     *
-     * @param baseOff Chunk base offset.
-     * @param nullMapLen Null-map size in bytes.
-     * @param vartblSize Amount of vartable items.
-     * @param tiny Tiny format flag.
-     * @return Chunk writer.
-     */
-    private ChunkWriter createChunkWriter(int baseOff, int nullMapLen, int vartblSize, boolean tiny) {
-        return tiny ?
-            new TinyChunkWriter(
-                buf,
-                baseOff,
-                nullMapLen,
-                vartblSize) :
-            new LongChunkWriter(
-                buf,
-                baseOff,
-                nullMapLen,
-                vartblSize);
+        chunkWriter = keyWriteMode.writer(buf, KEY_CHUNK_OFFSET, keyNullMapSize, keyVarlenCols);
     }
 
     /**
@@ -505,17 +478,18 @@ public class RowAssembler {
             // Write value flags.
             if (valVarlenCols == 0)
                 flags |= OMIT_VAL_VARTBL_FLAG;
-            if (schema.valueColumns().nullMapSize() == 0)
-                flags |= RowFlags.OMIT_VAL_NULL_MAP_FLAG;
-            if (tinyVal)
-                flags |= RowFlags.VAL_TYNY_FORMAT;
+            else {
+                if (schema.valueColumns().nullMapSize() == 0)
+                    flags |= RowFlags.OMIT_VAL_NULL_MAP_FLAG;
+
+                flags |= valWriteMode.modeFlags() & 0x0F << 14;
+            }
 
             // Create value chunk writer.
-            chunkWriter = createChunkWriter(
+            chunkWriter = valWriteMode.writer(buf,
                 BinaryRow.HEADER_SIZE + chunkWriter.chunkLength() /* Key chunk size */,
                 schema.valueColumns().nullMapSize(),
-                valVarlenCols,
-                tinyVal);
+                valVarlenCols);
         }
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
index 347e257..25392a9 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/TinyChunkWriter.java
@@ -19,60 +19,21 @@ package org.apache.ignite.internal.schema.row;
 
 /**
  * Row chunk writer for small key/value chunks.
- *
+ * <p>
  * Uses {@code byte} values for coding sizes/offsets,
  * supports chunks with payload less upt to 255 bytes.
  */
 class TinyChunkWriter extends ChunkWriter {
     /**
-     * Calculates vartable length (in bytes).
-     *
-     * @param items Vartable items.
-     * @return Vartable size in bytes.
-     */
-    static int vartableLength(int items) {
-        return items == 0 ? 0 : Byte.BYTES /* Table size */ + items * Byte.BYTES;
-    }
-
-    /**
-     * Calculates chunk size.
-     *
-     * @param payloadLen Payload size in bytes.
-     * @param nullMapLen Null-map size in bytes.
-     * @param vartblSize Amount of vartable items.
-     * @return Bytes required to write a chunk or {@code -1} if a chunk is too long.
-     */
-    static int chunkSize(int payloadLen, int nullMapLen, int vartblSize) {
-        return Byte.BYTES /* Chunk len. */ + nullMapLen + vartableLength(vartblSize) + payloadLen;
-    }
-
-    /**
-     * Check if chunk fits to max size.
-     *
-     * @param payloadLen Payload size in bytes.
-     * @param nullMapLen Null-map size in bytes.
-     * @param vartblSize Amount of vartable items.
-     * @return {@code true} if a chunk is tiny, {@code false} otherwise.
-     */
-    static boolean isTinyChunk(int payloadLen, int nullMapLen, int vartblSize) {
-        return chunkSize(payloadLen, nullMapLen, vartblSize) < 256;
-    }
-
-    /**
      * Creates chunk writer to write chunk in tiny format.
      *
      * @param buf Row buffer.
      * @param baseOff Chunk base offset.
-     * @param nullMapLen Null-map size in bytes.
-     * @param vartblSize Amount of vartable items.
+     * @param nullMapOff Null-map offset.
+     * @param varTblOff Vartable offset.
      */
-    TinyChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapLen, int vartblSize) {
-        super(
-            buf,
-            baseOff,
-            baseOff + Byte.BYTES /* Chunk size */,
-            baseOff + Byte.BYTES + nullMapLen,
-            baseOff + Byte.BYTES + nullMapLen + vartableLength(vartblSize));
+    TinyChunkWriter(ExpandableByteBuf buf, int baseOff, int nullMapOff, int varTblOff, int dataOff) {
+        super(buf,baseOff, nullMapOff, varTblOff, dataOff);
 
         curVartblItem = 0;
     }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/XXHash32.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/XXHash32.java
deleted file mode 100644
index 2b71c4a..0000000
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/XXHash32.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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.schema.row;
-
-import java.nio.ByteBuffer;
-import java.util.zip.Checksum;
-
-import static java.lang.Integer.rotateLeft;
-
-/**
- * Implementation of the xxhash32 hash algorithm.
- *
- * Copied from Commons Compress 1.14 <a href=
- * "https://git-wip-us.apache.org/repos/asf?p=commons-compress.git;a=blob;f=src/main/java/org/apache/commons/compress/compressors/lz4/XXHash32.java;h=a406ffc197449be594d46f0d2712b2d4786a1e68;hb=HEAD">https://git-wip-us.apache.org/repos/asf?p=commons-compress.git;a=blob;f=src/main/java/org/apache/commons/compress/compressors/lz4/XXHash32.java;h=a406ffc197449be594d46f0d2712b2d4786a1e68;hb=HEAD</a>
- * <p>
- * NotThreadSafe
- *
- * @see <a href="http://cyan4973.github.io/xxHash/">xxHash</a>
- * @since 1.11
- */
-public class XXHash32 implements Checksum {
-    /** Buffer size. */
-    private static final int BUF_SIZE = 16;
-
-    /** Rotation shift. */
-    private static final int ROTATE_BITS = 13;
-
-    /** Prime number. */
-    private static final int PRIME1 = (int) 2654435761L;
-    /** Prime number. */
-    private static final int PRIME2 = (int) 2246822519L;
-    /** Prime number. */
-    private static final int PRIME3 = (int) 3266489917L;
-    /** Prime number. */
-    private static final int PRIME4 =  668265263;
-    /** Prime number. */
-    private static final int PRIME5 =  374761393;
-
-    /** One-byte len buffer. */
-    private final byte[] oneByte = new byte[1];
-
-    /** State. */
-    private final int[] state = new int[4];
-
-    // Note: the code used to use ByteBuffer but the manual method is 50% faster
-    // See: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/2f56fb5c
-    private final byte[] buffer = new byte[BUF_SIZE];
-
-    /** Seed. */
-    private final int seed;
-
-    /** */
-    private int totalLen;
-
-    /** Position. */
-    private int pos;
-
-    /** Set to true when the state array has been updated since the last reset. */
-    private boolean stateUpdated;
-
-    /**
-     * Calculates hash for byte buffer slice.
-     *
-     * @param buf Buffer.
-     * @param off Slice offset.
-     * @param len Slice len.
-     * @return Hash code.
-     */
-    public static int hash(ByteBuffer buf, int off, int len) {
-        final XXHash32 hasher = new XXHash32(0);
-
-        hasher.update(buf.array(), off + buf.arrayOffset(), len);
-
-        return (int)hasher.getValue();
-    }
-
-    /**
-     * Creates an XXHash32 instance with a seed of 0.
-     */
-    public XXHash32() {
-        this(0);
-    }
-
-    /**
-     * Creates an XXHash32 instance.
-     * @param seed the seed to use
-     */
-    public XXHash32(final int seed) {
-        this.seed = seed;
-        initializeState();
-    }
-
-    /** {@inheritDoc} */
-    @Override public void reset() {
-        initializeState();
-        totalLen = 0;
-        pos = 0;
-        stateUpdated = false;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void update(final int b) {
-        oneByte[0] = (byte) (b & 0xff);
-        update(oneByte, 0, 1);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void update(final byte[] b, int off, final int len) {
-        if (len <= 0) {
-            return;
-        }
-        totalLen += len;
-
-        final int end = off + len;
-
-        // Check if the unprocessed bytes and new bytes can fill a block of 16.
-        // Make this overflow safe in the event that len is Integer.MAX_VALUE.
-        // Equivalent to: (pos + len < BUF_SIZE)
-        if (pos + len - BUF_SIZE < 0) {
-            System.arraycopy(b, off, buffer, pos, len);
-            pos += len;
-            return;
-        }
-
-        // Process left-over bytes with new bytes
-        if (pos > 0) {
-            final int size = BUF_SIZE - pos;
-            System.arraycopy(b, off, buffer, pos, size);
-            process(buffer, 0);
-            off += size;
-        }
-
-        final int limit = end - BUF_SIZE;
-        while (off <= limit) {
-            process(b, off);
-            off += BUF_SIZE;
-        }
-
-        // Handle left-over bytes
-        if (off < end) {
-            pos = end - off;
-            System.arraycopy(b, off, buffer, 0, pos);
-        } else {
-            pos = 0;
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public long getValue() {
-        int hash;
-        if (stateUpdated) {
-            // Hash with the state
-            hash =
-                rotateLeft(state[0],  1) +
-                    rotateLeft(state[1],  7) +
-                    rotateLeft(state[2], 12) +
-                    rotateLeft(state[3], 18);
-        } else {
-            // Hash using the original seed from position 2
-            hash = state[2] + PRIME5;
-        }
-        hash += totalLen;
-
-        int idx = 0;
-        final int limit = pos - 4;
-        for (; idx <= limit; idx += 4) {
-            hash = rotateLeft(hash + getInt(buffer, idx) * PRIME3, 17) * PRIME4;
-        }
-        while (idx < pos) {
-            hash = rotateLeft(hash + (buffer[idx++] & 0xff) * PRIME5, 11) * PRIME1;
-        }
-
-        hash ^= hash >>> 15;
-        hash *= PRIME2;
-        hash ^= hash >>> 13;
-        hash *= PRIME3;
-        hash ^= hash >>> 16;
-        return hash & 0xffffffffL;
-    }
-
-    /**
-     * Gets the little-endian int from 4 bytes starting at the specified index.
-     *
-     * @param buffer The data
-     * @param idx The index
-     * @return The little-endian int
-     */
-    private static int getInt(final byte[] buffer, final int idx) {
-        return ((buffer[idx    ] & 0xff)      ) |
-            ((buffer[idx + 1] & 0xff) <<  8) |
-            ((buffer[idx + 2] & 0xff) << 16) |
-            ((buffer[idx + 3] & 0xff) << 24);
-    }
-
-    /**
-     * Initialize state.
-     */
-    private void initializeState() {
-        state[0] = seed + PRIME1 + PRIME2;
-        state[1] = seed + PRIME2;
-        state[2] = seed;
-        state[3] = seed - PRIME1;
-    }
-
-    /**
-     * @param b Buffer.
-     * @param offset Offset.
-     */
-    private void process(final byte[] b, final int offset) {
-        // local shadows for performance
-        int s0 = state[0];
-        int s1 = state[1];
-        int s2 = state[2];
-        int s3 = state[3];
-
-        s0 = rotateLeft(s0 + getInt(b, offset) * PRIME2, ROTATE_BITS) * PRIME1;
-        s1 = rotateLeft(s1 + getInt(b, offset + 4) * PRIME2, ROTATE_BITS) * PRIME1;
-        s2 = rotateLeft(s2 + getInt(b, offset + 8) * PRIME2, ROTATE_BITS) * PRIME1;
-        s3 = rotateLeft(s3 + getInt(b, offset + 12) * PRIME2, ROTATE_BITS) * PRIME1;
-
-        state[0] = s0;
-        state[1] = s1;
-        state[2] = s2;
-        state[3] = s3;
-
-        stateUpdated = true;
-    }
-}

[ignite-3] 13/15: WIP.

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit c9136797926a156379799668018c078df1c8cc85
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Wed Jun 9 11:09:56 2021 +0300

    WIP.
---
 .../ignite/internal/schema/row/ChunkReader.java    | 24 +++++++++++++++++-----
 .../org/apache/ignite/internal/schema/row/Row.java |  2 +-
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
index 30e4db9..c0e0177 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/ChunkReader.java
@@ -198,15 +198,29 @@ class ChunkReader {
 
         idx -= cols.numberOfFixsizeColumns();
 
+        if (idx == 0) { // Very first non-null varlen column.
+            int off = cols.numberOfFixsizeColumns() == 0 ?
+                 varTableOff + varlenItemOffset(readShort(vartableOff)) : vartableOff) :
+                fixlenColumnOffset(cols, baseOff, cols.numberOfFixsizeColumns(), hasVarTbl, hasNullMap);
+
+            long len = hasVarTbl ?
+                readShort(vartableOff + varlenItemOffset(0)) - (off - baseOff) :
+                readInteger(baseOff) - (off - baseOff);
+
+            return (len << 32) | off;
+        }
+
+        int vartableSize = readShort(vartableOff);
+
         // Offset of idx-th column is from base offset.
-        int resOff = varlenItemOffset(idx);
+        int resOff = readShort(vartableOff + varlenItemOffset(idx - 1));
 
-        long len = (idx == vartableItems() - 1) ?
+        long len = (idx == vartableSize) ?
             // totalLength - columnStartOffset
-            (baseOff + chunkLength()) - resOff :
+            readInteger(baseOff) - resOff :
             // nextColumnStartOffset - columnStartOffset
-            varlenItemOffset(idx + 1) - resOff;
+            readShort(vartableOff + varlenItemOffset(idx)) - resOff;
 
-        return (len << 32) | resOff;
+        return (len << 32) | (resOff + baseOff);
     }
 }
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
index 963ac1a..027da41 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/row/Row.java
@@ -377,7 +377,7 @@ public class Row implements BinaryRow {
 
         return type.fixedLength() ?
             reader.fixlenColumnOffset(cols, off, colIdx, hasVarTable, hasNullMap) :
-            reader.varlenColumnOffsetAndLength(cols, off, colIdx, hasVarTable, hasNullMap);
+            reader.varlenColumnOffsetAndLength(cols, colIdx);
     }
 
     private ChunkReader valueReader() {

[ignite-3] 02/15: Merge branch 'main' into gg-14743

Posted by am...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-14743
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 0e66f1563dbf7b1f02486fec0b178698a59bf926
Merge: b0bc9e5 37083a1
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Wed Jun 2 19:55:53 2021 +0300

    Merge branch 'main' into gg-14743
    
    # Conflicts:
    #	modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverter.java

 .../ignite/internal/affinity/AffinityManager.java  |   10 +-
 .../internal/affinity/AffinityManagerTest.java     |   12 +-
 .../affinity/TestConfigurationStorage.java         |    7 +-
 modules/api/pom.xml                                |   20 +-
 .../network/NetworkConfigurationSchema.java        |    4 +-
 .../schemas/rest/RestConfigurationSchema.java      |    4 +-
 .../schemas/runner/ClusterConfigurationSchema.java |    2 +-
 .../schemas/runner/NodeConfigurationSchema.java    |    5 +-
 .../schemas/table/ColumnConfigurationSchema.java   |    8 +-
 .../table/ColumnTypeConfigurationSchema.java       |    8 +-
 .../table/IndexColumnConfigurationSchema.java      |    4 +-
 .../schemas/table/TableConfigurationSchema.java    |    8 +-
 .../table/TableIndexConfigurationSchema.java       |   14 +-
 .../schemas/table/TablesConfigurationSchema.java   |    2 +-
 .../java/org/apache/ignite/table/KeyValueView.java |  151 ++-
 .../java/org/apache/ignite/table/TableView.java    |  154 ++-
 modules/configuration-annotation-processor/pom.xml |    8 +-
 .../processor/internal/AbstractProcessorTest.java  |    6 +-
 .../processor/internal/ConfigSet.java              |   37 +-
 .../processor/internal/ITProcessorTest.java        |   31 +-
 .../internal/ConfigurationDescription.java         |   48 -
 .../processor/internal/ConfigurationElement.java   |   79 --
 .../processor/internal/Processor.java              |  552 +---------
 .../configuration/processor/internal/Utils.java    |   58 -
 .../configuration/ConfigurationChangerTest.java    |  136 ++-
 .../internal/util/ConfigurationUtilTest.java       |   75 +-
 .../internal/validation/ValidationUtilTest.java    |   29 +-
 .../notifications/ConfigurationListenerTest.java   |    4 +-
 .../sample/AutoAdjustConfigurationSchema.java      |    4 +-
 .../sample/BaselineConfigurationSchema.java        |    5 +-
 .../sample/CacheConfigurationSchema.java           |    4 +-
 .../sample/ClusterWideConfigurationSchema.java     |    4 +-
 .../sample/ConfigurationArrayTest.java             |   36 +-
 .../sample/ConstructableTreeNodeTest.java          |   65 +-
 .../sample/LocalConfigurationSchema.java           |    2 +-
 .../sample/NetworkConfigurationSchema.java         |    2 +-
 .../sample/TraversableTreeNodeTest.java            |   76 +-
 .../ignite/configuration/sample/UsageTest.java     |    4 +-
 .../storage/TestConfigurationStorage.java          |    7 +-
 modules/configuration-api/pom.xml                  |   41 +
 .../ConfigurationChangeException.java              |    0
 .../configuration/ConfigurationProperty.java       |    0
 .../ignite/configuration/ConfigurationTree.java    |    0
 .../ignite/configuration/ConfigurationValue.java   |    0
 .../configuration/NamedConfigurationTree.java      |    0
 .../org/apache/ignite/configuration/RootKey.java   |   45 +-
 .../ignite/configuration/annotation/Config.java    |    9 +-
 .../configuration/annotation/ConfigValue.java      |    4 +-
 .../annotation/ConfigurationRoot.java              |    0
 .../configuration/annotation/NamedConfigValue.java |    7 +-
 .../ignite/configuration/annotation/Value.java     |    7 +-
 .../notifications/ConfigurationListener.java       |    0
 .../ConfigurationNamedListListener.java            |    0
 .../ConfigurationNotificationEvent.java            |    0
 .../configuration/storage/ConfigurationType.java   |    0
 .../ignite/configuration/tree/NamedListChange.java |    0
 .../ignite/configuration/tree/NamedListView.java   |    0
 .../ConfigurationValidationException.java          |    0
 .../ignite/configuration/validation/Immutable.java |    0
 .../ignite/configuration/validation/Max.java}      |    5 +-
 .../ignite/configuration/validation/Min.java}      |    5 +-
 .../validation/ValidationContext.java              |    0
 .../configuration/validation/ValidationIssue.java  |    0
 .../ignite/configuration/validation/Validator.java |    0
 modules/configuration/pom.xml                      |   13 +-
 .../ignite/configuration/ConfigurationChanger.java |   38 +-
 .../configuration/ConfigurationRegistry.java       |   52 +-
 .../configuration/internal/ConfigurationNode.java  |    2 +-
 .../internal/DynamicConfiguration.java             |   12 +-
 .../configuration/internal/DynamicProperty.java    |    2 +-
 .../ignite/configuration/internal/RootKeyImpl.java |   80 --
 .../ignite/configuration/internal/SuperRoot.java   |   40 +-
 .../internal/asm/ConfigurationAsmGenerator.java    | 1139 ++++++++++++++++++++
 .../internal/asm/SchemaClassesInfo.java            |   67 ++
 .../internal/asm/StringSwitchBuilder.java          |  224 ++++
 .../internal/util/ConfigurationUtil.java           |    2 +-
 .../internal/validation/MaxValidator.java          |    2 +-
 .../internal/validation/MinValidator.java          |    2 +-
 .../storage/ConfigurationStorage.java              |   15 +-
 .../configuration/tree/ConstructableTreeNode.java  |    2 +-
 .../ignite/configuration/tree/InnerNode.java       |    3 +-
 .../client/ITMetaStorageServiceTest.java           |   63 +-
 .../metastorage/client/CompactedException.java     |    2 +-
 .../metastorage/client/Condition.java              |    2 +-
 .../metastorage/client/Conditions.java             |    2 +-
 .../{ => internal}/metastorage/client/Entry.java   |    2 +-
 .../metastorage/client/EntryEvent.java             |    2 +-
 .../internal/metastorage/client/EntryImpl.java     |    1 -
 .../metastorage/client/MetaStorageService.java     |    4 +-
 .../metastorage/client/MetaStorageServiceImpl.java |    7 -
 .../metastorage/client/Operation.java              |    2 +-
 .../client/OperationTimeoutException.java          |    2 +-
 .../metastorage/client/Operations.java             |    2 +-
 .../metastorage/client/WatchEvent.java             |    2 +-
 .../metastorage/client/WatchListener.java          |    2 +-
 .../metastorage/client/package-info.java           |    2 +-
 .../org/apache/ignite/metastorage/client/Key.java  |   81 --
 .../metastorage/common/package-info.java           |    2 +-
 .../server/raft/MetaStorageCommandListener.java    |  382 -------
 .../server/raft/MetaStorageListener.java           |  367 +++++++
 .../internal/metastorage/MetaStorageManager.java   |   75 +-
 .../metastorage/watch/AggregatedWatch.java         |    2 +-
 .../internal/metastorage/watch/KeyCriterion.java   |  305 +++++-
 .../metastorage/watch/WatchAggregator.java         |   19 +-
 .../internal/metastorage/WatchAggregatorTest.java  |  197 +++-
 modules/network-annotation-processor/README.md     |    9 +
 .../pom.xml                                        |   73 +-
 .../processor/ITAutoSerializableProcessorTest.java |  138 +++
 .../processor/internal/AllTypesMessage.java        |  136 +++
 .../internal/AllTypesMessageFactory.java}          |   11 +-
 .../processor/internal/AllTypesMessageImpl.java    |  471 ++++++++
 .../internal/InvalidAnnotatedTypeMessage.java}     |   13 +-
 .../processor/internal/InvalidGetterMessage.java}  |   15 +-
 .../processor/internal/MissingBuilderMessage.java} |   16 +-
 .../processor/internal/TransitiveMessage.java}     |   64 +-
 .../internal/TransitiveMessageFactory.java}        |   11 +-
 .../internal/UnsupportedTypeMessage.java}          |   16 +-
 .../processor/annotations/AutoSerializable.java    |   72 ++
 .../internal/AutoSerializableProcessor.java        |  251 +++++
 .../processor/internal/BaseMethodNameResolver.java |  135 +++
 .../MessageCollectionItemTypeConverter.java        |  129 +++
 .../internal/MessageDeserializerGenerator.java     |  212 ++++
 .../internal/MessageReaderMethodResolver.java      |  126 +++
 .../internal/MessageSerializerGenerator.java       |  136 +++
 .../internal/MessageWriterMethodResolver.java      |  133 +++
 .../processor/internal/ProcessingException.java}   |   12 +-
 .../internal/SerializationFactoryGenerator.java    |   69 ++
 .../network/processor/internal/TypeUtils.java      |   77 ++
 .../services/javax.annotation.processing.Processor |    1 +
 modules/network-api/README.md                      |   35 +
 modules/{configuration => network-api}/pom.xml     |   28 +-
 .../ignite/network/AbstractClusterService.java     |    8 +-
 .../ignite/network/AbstractMessagingService.java   |    0
 .../ignite/network/AbstractTopologyService.java    |    0
 .../ignite/network/ClusterLocalConfiguration.java  |   10 +-
 .../org/apache/ignite/network/ClusterNode.java     |   10 +
 .../org/apache/ignite/network/ClusterService.java  |    6 +-
 .../ignite/network/ClusterServiceFactory.java      |    7 +-
 .../apache/ignite/network/MessagingService.java    |   18 +-
 .../network/NetworkConfigurationException.java     |    0
 .../org/apache/ignite/network}/NetworkMessage.java |    4 +-
 .../ignite/network/NetworkMessageHandler.java      |    2 -
 .../ignite/network/TopologyEventHandler.java       |    4 +
 .../org/apache/ignite/network/TopologyService.java |    2 +
 .../serialization}/MessageDeserializer.java        |    4 +-
 .../serialization}/MessageMappingException.java    |    2 +-
 .../network/serialization}/MessageReader.java      |    8 +-
 .../MessageSerializationFactory.java               |    4 +-
 .../MessageSerializationRegistry.java              |   31 +-
 .../network/serialization}/MessageSerializer.java  |    4 +-
 .../network/serialization}/MessageWriter.java      |    8 +-
 .../MessageSerializationRegistryTest.java          |   11 +-
 modules/network/README.md                          |   35 +-
 modules/network/pom.xml                            |   11 +
 .../org/apache/ignite/network/TestMessage.java     |   61 +-
 .../apache/ignite/network/TestMessageFactory.java} |   11 +-
 .../{TestMessage.java => TestMessageImpl.java}     |   48 +-
 .../network/TestMessageSerializationFactory.java   |  112 --
 .../netty}/ConnectionManagerTest.java              |  103 +-
 .../internal/recovery/RecoveryHandshakeTest.java   |  349 ++++++
 .../network/scalecube/ITNodeRestartsTest.java      |   12 +-
 .../scalecube/ITScaleCubeNetworkMessagingTest.java |   25 +-
 .../internal/direct/DirectMessageReader.java       |    6 +-
 .../internal/direct/DirectMessageWriter.java       |    6 +-
 .../direct/stream/DirectByteBufferStream.java      |   14 +-
 .../stream/DirectByteBufferStreamImplV1.java       |   14 +-
 .../internal/handshake/HandshakeAction.java}       |   19 +-
 .../internal/handshake/HandshakeException.java}    |   27 +-
 .../internal/handshake/HandshakeManager.java       |   59 +
 .../network/internal/netty/ConnectionManager.java  |  136 ++-
 .../network/internal/netty/HandshakeHandler.java   |   98 ++
 .../network/internal/netty/InboundDecoder.java     |   24 +-
 .../network/internal/netty/MessageHandler.java     |    6 +-
 .../ignite/network/internal/netty/NettyClient.java |   74 +-
 .../ignite/network/internal/netty/NettySender.java |  134 +--
 .../ignite/network/internal/netty/NettyServer.java |   59 +-
 .../ignite/network/internal/netty/NettyUtils.java  |    1 +
 .../{NettySender.java => OutboundEncoder.java}     |   57 +-
 .../recovery/RecoveryClientHandshakeManager.java   |  105 ++
 .../recovery/RecoveryServerHandshakeManager.java   |  103 ++
 .../recovery/message/HandshakeMessageFactory.java} |   17 +-
 .../recovery/message/HandshakeStartMessage.java}   |   38 +-
 .../message/HandshakeStartMessageImpl.java}        |   37 +-
 .../message/HandshakeStartResponseMessage.java     |   60 ++
 .../message/HandshakeStartResponseMessageImpl.java |   83 ++
 .../scalecube/ScaleCubeClusterServiceFactory.java  |   48 +-
 .../ScaleCubeDirectMarshallerTransport.java        |   33 +-
 .../scalecube/ScaleCubeMessagingService.java       |   35 +-
 .../scalecube/ScaleCubeTopologyService.java        |    8 +-
 .../scalecube/message/ScaleCubeMessage.java        |   36 +-
 .../message/ScaleCubeMessageFactory.java}          |   11 +-
 ...eCubeMessage.java => ScaleCubeMessageImpl.java} |   48 +-
 .../ScaleCubeMessageSerializationFactory.java      |  116 --
 .../ignite/network/internal/AllTypesMessage.java   |  185 ++--
 .../network/internal/AllTypesMessageFactory.java}  |   11 +-
 .../network/internal/AllTypesMessageGenerator.java |   18 +-
 .../network/internal/AllTypesMessageImpl.java      |  496 +++++++++
 .../AllTypesMessageSerializationFactory.java       |  562 ----------
 .../network/internal/netty/InboundDecoderTest.java |   29 +-
 .../network/internal/netty/NettyClientTest.java    |   74 +-
 .../network/internal/netty/NettyServerTest.java    |  118 +-
 .../java/org/apache/ignite/raft/client/Peer.java   |   29 +-
 .../apache/ignite/raft/client/RaftErrorCode.java   |   15 +-
 .../raft/client/exception/RaftException.java       |   13 +-
 .../ignite/raft/client/message/ActionRequest.java  |   17 +-
 .../ignite/raft/client/message/ActionResponse.java |    2 +-
 .../raft/client/message/AddLearnersRequest.java    |    2 +-
 .../raft/client/message/AddPeersRequest.java       |    2 +-
 .../raft/client/message/ChangePeersResponse.java   |    2 +-
 .../raft/client/message/GetLeaderRequest.java      |    2 +-
 .../raft/client/message/GetLeaderResponse.java     |    2 +-
 .../raft/client/message/GetPeersRequest.java       |    2 +-
 .../raft/client/message/GetPeersResponse.java      |    2 +-
 .../raft/client/message/RaftErrorResponse.java     |   15 +-
 .../raft/client/message/RemoveLearnersRequest.java |    2 +-
 .../raft/client/message/RemovePeersRequest.java    |    2 +-
 .../raft/client/message/SnapshotRequest.java       |    2 +-
 .../client/message/TransferLeadershipRequest.java  |    2 +-
 .../client/message/impl/ActionRequestImpl.java     |   22 +-
 .../client/message/impl/RaftErrorResponseImpl.java |   15 +
 .../ignite/raft/client/service/CommandClosure.java |   17 +-
 .../raft/client/service/RaftGroupListener.java     |   68 ++
 .../raft/client/service/RaftGroupService.java      |    7 +-
 .../client/service/impl/RaftGroupServiceImpl.java  |  187 +++-
 .../raft/client/service/RaftGroupServiceTest.java  |  209 +++-
 ...erCommandListener.java => CounterListener.java} |   22 +-
 .../raft/server/ITRaftCounterServerTest.java       |  193 +---
 .../ignite/raft/server/IncrementAndGetCommand.java |    6 +-
 .../raft/server/RaftCounterServerAbstractTest.java |  108 ++
 .../java/org/apache/ignite/internal/raft/Loza.java |   17 +-
 .../org/apache/ignite/raft/server/RaftServer.java  |   38 +-
 .../ignite/raft/server/impl/RaftServerImpl.java    |  144 +--
 .../json/TestConfigurationStorage.java             |    7 +-
 .../runner/app/DynamicTableCreationTest.java       |   87 +-
 .../apache/ignite/internal/app/IgnitionImpl.java   |   12 +-
 .../storage/DistributedConfigurationStorage.java   |   54 +-
 .../storage/LocalConfigurationStorage.java         |   27 +-
 .../ignite/internal/schema/SchemaManager.java      |   12 +-
 .../SchemaConfigurationConverter.java              |   58 +-
 .../configuration/SchemaDescriptorConverter.java   |   26 +-
 .../SchemaConfigurationConverterTest.java          |    6 +-
 .../configuration/TestConfigurationStorage.java    |    7 +-
 .../ignite/distributed/ITDistributedTableTest.java |  280 ++++-
 .../ignite/internal/table/KVBinaryViewImpl.java    |  137 ++-
 .../apache/ignite/internal/table/KVViewImpl.java   |   62 +-
 .../ignite/internal/table/RecordViewImpl.java      |   72 +-
 .../apache/ignite/internal/table/TableImpl.java    |  168 ++-
 .../internal/table/distributed/TableManager.java   |    8 +-
 .../table/distributed/command/CommandUtils.java    |  158 +++
 .../distributed/command/DeleteAllCommand.java      |   68 ++
 .../table/distributed/command/DeleteCommand.java   |   43 +-
 .../distributed/command/DeleteExactAllCommand.java |   68 ++
 ...{InsertCommand.java => DeleteExactCommand.java} |   50 +-
 .../table/distributed/command/GetAllCommand.java   |   68 ++
 ...DeleteCommand.java => GetAndDeleteCommand.java} |   50 +-
 ...nsertCommand.java => GetAndReplaceCommand.java} |   49 +-
 ...DeleteCommand.java => GetAndUpsertCommand.java} |   52 +-
 .../table/distributed/command/GetCommand.java      |   43 +-
 .../distributed/command/InsertAllCommand.java      |   68 ++
 .../table/distributed/command/InsertCommand.java   |   43 +-
 .../table/distributed/command/ReplaceCommand.java  |   55 +-
 ...sertCommand.java => ReplaceIfExistCommand.java} |   49 +-
 .../distributed/command/UpsertAllCommand.java      |   68 ++
 .../table/distributed/command/UpsertCommand.java   |   43 +-
 .../command/response/MultiRowsResponse.java        |   71 ++
 .../{KVGetResponse.java => SingleRowResponse.java} |   57 +-
 .../distributed/raft/PartitionCommandListener.java |  166 ---
 .../table/distributed/raft/PartitionListener.java  |  353 ++++++
 .../distributed/storage/InternalTableImpl.java     |  168 ++-
 .../internal/table/StrictSchemaOperationsTest.java |   27 +-
 .../ignite/internal/table/TableManagerTest.java    |   44 +-
 .../internal/table/TestConfigurationStorage.java   |    7 +-
 .../raft/PartitionCommandListenerTest.java         |  700 ++++++++++++
 .../vault/impl/VaultBaseContractsTest.java         |    2 +-
 parent/pom.xml                                     |   25 +-
 pom.xml                                            |    3 +
 276 files changed, 11215 insertions(+), 4906 deletions(-)