This is an automated email from the ASF dual-hosted git repository.
rpuch pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 3f91738073 IGNITE-23583 Optimize HybridTimestamp serialization (#4664)
3f91738073 is described below
commit 3f9173807350886c6fd72a90c8aa57433450a64b
Author: Roman Puchkovskiy <[email protected]>
AuthorDate: Thu Oct 31 23:11:42 2024 +0400
IGNITE-23583 Optimize HybridTimestamp serialization (#4664)
---
.../ignite/internal/hlc/HybridTimestamp.java | 80 ++++++++++++++++++++--
.../apache/ignite/internal/util/GridUnsafe.java | 2 +-
.../ignite/internal/hlc/HybridTimestampTest.java | 49 +++++++++++++
.../AssignmentsSerializer.java | 10 +--
.../AssignmentsSerializerTest.java | 43 +++++++++---
.../ManualGroupRestartRequestSerializer.java | 9 +--
.../distributed/index/IndexMetaSerializer.java | 10 +--
.../DisasterRecoveryRequestSerializerTest.java | 22 +++++-
.../distributed/index/IndexMetaSerializerTest.java | 14 +++-
.../ignite/internal/tx/TxMetaSerializer.java | 6 +-
.../ignite/internal/tx/TxMetaSerializerTest.java | 15 +++-
11 files changed, 226 insertions(+), 34 deletions(-)
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridTimestamp.java
b/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridTimestamp.java
index c309c9e68f..a7947892da 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridTimestamp.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/hlc/HybridTimestamp.java
@@ -19,10 +19,13 @@ package org.apache.ignite.internal.hlc;
import static
org.apache.ignite.internal.lang.JavaLoggerFormatter.DATE_FORMATTER;
+import java.io.IOException;
import java.io.Serializable;
import java.time.Instant;
-import java.time.ZoneId;
+import java.time.ZoneOffset;
import org.apache.ignite.internal.util.ByteUtils;
+import org.apache.ignite.internal.util.io.IgniteDataInput;
+import org.apache.ignite.internal.util.io.IgniteDataOutput;
import org.jetbrains.annotations.Nullable;
/**
@@ -39,10 +42,10 @@ public final class HybridTimestamp implements
Comparable<HybridTimestamp>, Seria
public static final int LOGICAL_TIME_BITS_SIZE = 2 * Byte.SIZE;
/** Mask to extract logical time. */
- public static final long LOGICAL_TIME_MASK = (1L <<
LOGICAL_TIME_BITS_SIZE) - 1;
+ private static final long LOGICAL_TIME_MASK = (1L <<
LOGICAL_TIME_BITS_SIZE) - 1;
/** Number of bits in "physical time" part. */
- public static final int PHYSICAL_TIME_BITS_SIZE = 6 * Byte.SIZE;
+ static final int PHYSICAL_TIME_BITS_SIZE = 6 * Byte.SIZE;
/** Timestamp size in bytes. */
public static final int HYBRID_TIMESTAMP_SIZE = Long.BYTES;
@@ -201,7 +204,7 @@ public final class HybridTimestamp implements
Comparable<HybridTimestamp>, Seria
@Override
public String toString() {
- String formattedTime =
DATE_FORMATTER.format(Instant.ofEpochMilli(getPhysical()).atZone(ZoneId.systemDefault()));
+ String formattedTime =
DATE_FORMATTER.format(Instant.ofEpochMilli(getPhysical()).atOffset(ZoneOffset.UTC));
return String.format("HybridTimestamp [physical=%s, logical=%d,
composite=%d]", formattedTime, getLogical(), time);
}
@@ -256,4 +259,73 @@ public final class HybridTimestamp implements
Comparable<HybridTimestamp>, Seria
public byte[] toBytes() {
return ByteUtils.longToBytes(longValue());
}
+
+ /**
+ * Writes this timestamp to the output.
+ *
+ * @param out Output to write to.
+ * @throws IOException If something goes wrong.
+ */
+ public void writeTo(IgniteDataOutput out) throws IOException {
+ long physical = getPhysical();
+
+ //noinspection NumericCastThatLosesPrecision
+ out.writeInt((int) (physical >> Short.SIZE));
+ out.writeShort((int) (physical & 0xFFFF));
+
+ out.writeVarInt(getLogical());
+ }
+
+ /**
+ * Writes a nullable timestamp to an output.
+ *
+ * @param timestamp Timestamp to write
+ * @param out Output to write to.
+ * @throws IOException If something goes wrong.
+ */
+ public static void write(@Nullable HybridTimestamp timestamp,
IgniteDataOutput out) throws IOException {
+ if (timestamp == null) {
+ out.writeInt(0);
+ out.writeShort(0);
+ out.writeVarInt(0);
+ } else {
+ timestamp.writeTo(out);
+ }
+ }
+
+ /**
+ * Reads a timestamp written with {@link #writeTo(IgniteDataOutput)}.
+ *
+ * @param in Input from which to read.
+ * @throws IOException If something goes wrong.
+ */
+ public static @Nullable HybridTimestamp readNullableFrom(IgniteDataInput
in) throws IOException {
+ long physicalHigh = in.readInt();
+ int physicalLow = in.readShort() & 0xFFFF;
+
+ long physical = (physicalHigh << Short.SIZE) | physicalLow;
+ int logical = in.readVarIntAsInt();
+
+ if (physical == 0 && logical == 0) {
+ return null;
+ }
+
+ return new HybridTimestamp(physical, logical);
+ }
+
+ /**
+ * Reads a timestamp written with {@link #writeTo(IgniteDataOutput)}.
+ *
+ * @param in Input from which to read.
+ * @throws IOException If something goes wrong.
+ */
+ public static HybridTimestamp readFrom(IgniteDataInput in) throws
IOException {
+ HybridTimestamp ts = readNullableFrom(in);
+
+ if (ts == null) {
+ throw new IOException("A non-null timestamp is expected");
+ }
+
+ return ts;
+ }
}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java
b/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java
index da35b01065..c1fa4c35ff 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java
@@ -45,7 +45,7 @@ import sun.misc.Unsafe;
* {@code getXxx(byte[] arr, long off)} and corresponding methods with {@code
LE} suffix are alignment aware
* and can be safely used with unaligned pointers.</li>
* <li>All {@code putXxxField(Object obj, long fieldOff, xxx val)} and {@code
getXxxField(Object obj, long fieldOff)}
- * methods are not alignment aware and can't be safely used with unaligned
pointers. This methods can be safely used
+ * methods are not alignment aware and can't be safely used with unaligned
pointers. These methods can be safely used
* for object field values access because all object fields addresses are
aligned.</li>
* <li>All {@code putXxxLE(...)} and {@code getXxxLE(...)} methods assumes
that the byte order is fixed as little-endian
* while native byte order is big-endian. So it is client code responsibility
to check native byte order before
diff --git
a/modules/core/src/test/java/org/apache/ignite/internal/hlc/HybridTimestampTest.java
b/modules/core/src/test/java/org/apache/ignite/internal/hlc/HybridTimestampTest.java
index 0df7b04a58..13739bf28d 100644
---
a/modules/core/src/test/java/org/apache/ignite/internal/hlc/HybridTimestampTest.java
+++
b/modules/core/src/test/java/org/apache/ignite/internal/hlc/HybridTimestampTest.java
@@ -23,10 +23,16 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import java.io.IOException;
+import org.apache.ignite.internal.util.io.IgniteDataInput;
+import org.apache.ignite.internal.util.io.IgniteDataOutput;
+import org.apache.ignite.internal.util.io.IgniteUnsafeDataInput;
+import org.apache.ignite.internal.util.io.IgniteUnsafeDataOutput;
import org.junit.jupiter.api.Test;
/**
@@ -158,4 +164,47 @@ class HybridTimestampTest {
assertThat(ts.roundUpToPhysicalTick(), is(new HybridTimestamp(2, 0)));
}
+
+ @Test
+ void serializationAndDeserializationForNonNull() throws Exception {
+ HybridTimestamp originalTs = new
HybridTimestamp(System.currentTimeMillis(), 2);
+
+ IgniteDataOutput out = new IgniteUnsafeDataOutput(100);
+
+ originalTs.writeTo(out);
+
+ IgniteDataInput in = new IgniteUnsafeDataInput(out.array());
+
+ HybridTimestamp restoredTs = HybridTimestamp.readFrom(in);
+
+ assertThat(restoredTs, is(originalTs));
+
+ assertThat(in.available(), is(0));
+ }
+
+ @Test
+ void serializationAndDeserializationForNull() throws Exception {
+ IgniteDataOutput out = new IgniteUnsafeDataOutput(100);
+
+ HybridTimestamp.write(null, out);
+
+ IgniteDataInput in = new IgniteUnsafeDataInput(out.array());
+
+ assertThat(HybridTimestamp.readNullableFrom(in), is(nullValue()));
+
+ assertThat(in.available(), is(0));
+ }
+
+ @Test
+ void readFromFailsWhenDeserializingNull() throws Exception {
+ IgniteDataOutput out = new IgniteUnsafeDataOutput(100);
+ HybridTimestamp.write(null, out);
+
+ IgniteDataInput in = new IgniteUnsafeDataInput(out.array());
+
+ IOException ex = assertThrows(IOException.class, () ->
HybridTimestamp.readFrom(in));
+ assertThat(ex.getMessage(), is("A non-null timestamp is expected"));
+
+ assertThat(in.available(), is(0));
+ }
}
diff --git
a/modules/partition-distribution/src/main/java/org/apache/ignite/internal/partitiondistribution/AssignmentsSerializer.java
b/modules/partition-distribution/src/main/java/org/apache/ignite/internal/partitiondistribution/AssignmentsSerializer.java
index c3d2620787..d5ee560ed6 100644
---
a/modules/partition-distribution/src/main/java/org/apache/ignite/internal/partitiondistribution/AssignmentsSerializer.java
+++
b/modules/partition-distribution/src/main/java/org/apache/ignite/internal/partitiondistribution/AssignmentsSerializer.java
@@ -17,9 +17,12 @@
package org.apache.ignite.internal.partitiondistribution;
+import static org.apache.ignite.internal.hlc.HybridTimestamp.hybridTimestamp;
+
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.util.io.IgniteDataInput;
import org.apache.ignite.internal.util.io.IgniteDataOutput;
import org.apache.ignite.internal.versioned.VersionedSerializer;
@@ -39,8 +42,7 @@ public class AssignmentsSerializer extends
VersionedSerializer<Assignments> {
}
out.writeBoolean(assignments.force());
- // Writing long and not varlong as the latter will take 9 bytes for
timestamps.
- out.writeLong(assignments.timestamp());
+ hybridTimestamp(assignments.timestamp()).writeTo(out);
}
private static void writeAssignment(Assignment assignment,
IgniteDataOutput out) throws IOException {
@@ -52,9 +54,9 @@ public class AssignmentsSerializer extends
VersionedSerializer<Assignments> {
protected Assignments readExternalData(byte protoVer, IgniteDataInput in)
throws IOException {
Set<Assignment> nodes = readNodes(in);
boolean force = in.readBoolean();
- long timestamp = in.readLong();
+ HybridTimestamp timestamp = HybridTimestamp.readFrom(in);
- return force ? Assignments.forced(nodes, timestamp) :
Assignments.of(nodes, timestamp);
+ return force ? Assignments.forced(nodes, timestamp.longValue()) :
Assignments.of(nodes, timestamp.longValue());
}
private static Set<Assignment> readNodes(IgniteDataInput in) throws
IOException {
diff --git
a/modules/partition-distribution/src/test/java/org/apache/ignite/internal/partitiondistribution/AssignmentsSerializerTest.java
b/modules/partition-distribution/src/test/java/org/apache/ignite/internal/partitiondistribution/AssignmentsSerializerTest.java
index 50692a61f9..d1f9cc1cec 100644
---
a/modules/partition-distribution/src/test/java/org/apache/ignite/internal/partitiondistribution/AssignmentsSerializerTest.java
+++
b/modules/partition-distribution/src/test/java/org/apache/ignite/internal/partitiondistribution/AssignmentsSerializerTest.java
@@ -24,25 +24,37 @@ import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
+import java.time.LocalDateTime;
+import java.time.Month;
+import java.time.ZoneOffset;
import java.util.Base64;
import java.util.List;
import java.util.Set;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.versioned.VersionedSerialization;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
class AssignmentsSerializerTest {
- private static final String NOT_FORCED_ASSIGNMENTS_SERIALIZED_WITH_V1 =
"Ae++QwMCYQECYgAA6AMAAAAAAAA=";
- private static final String FORCED_ASSIGNMENTS_SERIALIZED_WITH_V1 =
"Ae++QwMCYQECYgAB6AMAAAAAAAA=";
+ private static final String NOT_FORCED_ASSIGNMENTS_SERIALIZED_WITH_V1 =
"Ae++QwMEYWJjAQRkZWYAAFHCjAEA9AY=";
+ private static final String FORCED_ASSIGNMENTS_SERIALIZED_WITH_V1 =
"Ae++QwMEYWJjAQRkZWYAAVHCjAEA9AY=";
private final AssignmentsSerializer serializer = new
AssignmentsSerializer();
+ private static final long BASE_PHYSICAL_TIME = LocalDateTime.of(2024,
Month.JANUARY, 1, 0, 0)
+ .atOffset(ZoneOffset.UTC)
+ .toInstant()
+ .toEpochMilli();
+
+ private static long baseTimestamp(int logical) {
+ return new HybridTimestamp(BASE_PHYSICAL_TIME, logical).longValue();
+ }
+
@ParameterizedTest
@ValueSource(booleans = {true, false})
void serializationAndDeserialization(boolean force) {
- Set<Assignment> nodes = Set.of(Assignment.forPeer("abc"),
Assignment.forLearner("def"));
- Assignments originalAssignments = force ? Assignments.forced(nodes,
1000L) : Assignments.of(nodes, 1000L);
+ Assignments originalAssignments = testAssignments(force);
byte[] bytes = VersionedSerialization.toBytes(originalAssignments,
serializer);
Assignments restoredAssignments =
VersionedSerialization.fromBytes(bytes, serializer);
@@ -50,6 +62,14 @@ class AssignmentsSerializerTest {
assertThat(restoredAssignments, equalTo(originalAssignments));
}
+ private static Assignments testAssignments(boolean force) {
+ Set<Assignment> nodes = Set.of(Assignment.forPeer("abc"),
Assignment.forLearner("def"));
+
+ return force
+ ? Assignments.forced(nodes, baseTimestamp(5))
+ : Assignments.of(nodes, baseTimestamp(5));
+ }
+
@Test
void v1NotForcedCanBeDeserialized() {
byte[] bytes =
Base64.getDecoder().decode(NOT_FORCED_ASSIGNMENTS_SERIALIZED_WITH_V1);
@@ -58,7 +78,7 @@ class AssignmentsSerializerTest {
assertNodesFromV1(restoredAssignments);
assertThat(restoredAssignments.force(), is(false));
- assertThat(restoredAssignments.timestamp(), is(1000L));
+ assertThat(restoredAssignments.timestamp(), is(baseTimestamp(5)));
}
@Test
@@ -69,7 +89,14 @@ class AssignmentsSerializerTest {
assertNodesFromV1(restoredAssignments);
assertThat(restoredAssignments.force(), is(true));
- assertThat(restoredAssignments.timestamp(), is(1000L));
+ assertThat(restoredAssignments.timestamp(), is(baseTimestamp(5)));
+ }
+
+ @SuppressWarnings("unused")
+ private String v1Base64(boolean force) {
+ Assignments originalAssignments = testAssignments(force);
+ byte[] v1Bytes = VersionedSerialization.toBytes(originalAssignments,
serializer);
+ return Base64.getEncoder().encodeToString(v1Bytes);
}
private static void assertNodesFromV1(Assignments restoredAssignments) {
@@ -79,11 +106,11 @@ class AssignmentsSerializerTest {
.collect(toList());
Assignment assignment1 = orderedNodes.get(0);
- assertThat(assignment1.consistentId(), is("a"));
+ assertThat(assignment1.consistentId(), is("abc"));
assertThat(assignment1.isPeer(), is(true));
Assignment assignment2 = orderedNodes.get(1);
- assertThat(assignment2.consistentId(), is("b"));
+ assertThat(assignment2.consistentId(), is("def"));
assertThat(assignment2.isPeer(), is(false));
}
}
diff --git
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/disaster/ManualGroupRestartRequestSerializer.java
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/disaster/ManualGroupRestartRequestSerializer.java
index e8a4348828..023e1c3ea5 100644
---
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/disaster/ManualGroupRestartRequestSerializer.java
+++
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/disaster/ManualGroupRestartRequestSerializer.java
@@ -17,12 +17,14 @@
package org.apache.ignite.internal.table.distributed.disaster;
+import static org.apache.ignite.internal.hlc.HybridTimestamp.hybridTimestamp;
import static
org.apache.ignite.internal.table.distributed.disaster.DisasterRecoveryRequestsSerialization.readVarIntSet;
import static
org.apache.ignite.internal.table.distributed.disaster.DisasterRecoveryRequestsSerialization.writeVarIntSet;
import java.io.IOException;
import java.util.Set;
import java.util.UUID;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.util.io.IgniteDataInput;
import org.apache.ignite.internal.util.io.IgniteDataOutput;
import org.apache.ignite.internal.versioned.VersionedSerializer;
@@ -41,8 +43,7 @@ class ManualGroupRestartRequestSerializer extends
VersionedSerializer<ManualGrou
out.writeVarInt(request.tableId());
writeVarIntSet(request.partitionIds(), out);
writeStringSet(request.nodeNames(), out);
- // Writing long and not a varlong as the latter requires 9 bytes for
hybrid timestamps.
- out.writeLong(request.assignmentsTimestamp());
+ hybridTimestamp(request.assignmentsTimestamp()).writeTo(out);
}
@Override
@@ -52,8 +53,8 @@ class ManualGroupRestartRequestSerializer extends
VersionedSerializer<ManualGrou
int tableId = in.readVarIntAsInt();
Set<Integer> partitionIds = readVarIntSet(in);
Set<String> nodeNames = readStringSet(in);
- long assignmentsTimestamp = in.readLong();
+ HybridTimestamp assignmentsTimestamp = HybridTimestamp.readFrom(in);
- return new ManualGroupRestartRequest(operationId, zoneId, tableId,
partitionIds, nodeNames, assignmentsTimestamp);
+ return new ManualGroupRestartRequest(operationId, zoneId, tableId,
partitionIds, nodeNames, assignmentsTimestamp.longValue());
}
}
diff --git
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/index/IndexMetaSerializer.java
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/index/IndexMetaSerializer.java
index 0462bcfb94..a2aefed94d 100644
---
a/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/index/IndexMetaSerializer.java
+++
b/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/index/IndexMetaSerializer.java
@@ -17,10 +17,13 @@
package org.apache.ignite.internal.table.distributed.index;
+import static org.apache.ignite.internal.hlc.HybridTimestamp.hybridTimestamp;
+
import java.io.IOException;
import java.util.EnumMap;
import java.util.Map;
import java.util.Map.Entry;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.util.io.IgniteDataInput;
import org.apache.ignite.internal.util.io.IgniteDataOutput;
import org.apache.ignite.internal.versioned.VersionedSerializer;
@@ -46,8 +49,7 @@ class IndexMetaSerializer extends
VersionedSerializer<IndexMeta> {
MetaIndexStatusChange change = entry.getValue();
out.writeVarInt(change.catalogVersion());
- // Writing long and not varlong as the latter requires 9 bytes.
- out.writeLong(change.activationTimestamp());
+ hybridTimestamp(change.activationTimestamp()).writeTo(out);
}
}
@@ -80,8 +82,8 @@ class IndexMetaSerializer extends
VersionedSerializer<IndexMeta> {
MetaIndexStatus status =
MetaIndexStatus.findByCode(in.readVarIntAsInt());
int catalogVersion = in.readVarIntAsInt();
- long activationTimestamp = in.readLong();
- MetaIndexStatusChange change = new
MetaIndexStatusChange(catalogVersion, activationTimestamp);
+ HybridTimestamp activationTimestamp = HybridTimestamp.readFrom(in);
+ MetaIndexStatusChange change = new
MetaIndexStatusChange(catalogVersion, activationTimestamp.longValue());
map.put(status, change);
}
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/disaster/DisasterRecoveryRequestSerializerTest.java
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/disaster/DisasterRecoveryRequestSerializerTest.java
index 432b6f3800..39c95aee15 100644
---
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/disaster/DisasterRecoveryRequestSerializerTest.java
+++
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/disaster/DisasterRecoveryRequestSerializerTest.java
@@ -28,6 +28,9 @@ import
org.apache.ignite.internal.versioned.VersionedSerialization;
import org.junit.jupiter.api.Test;
class DisasterRecoveryRequestSerializerTest {
+ private static final String MANUAL_GROUP_UPDATE_REQUEST_V1_BASE64 =
"Ae++QwEB775D782rkHhWNBIhQ2WHCbrc/ukH0Q+5FwQWDCA=";
+ private static final String MANUAL_GROUP_RESTART_REQUEST_V1_BASE64 =
"Ae++QwIB775D782rkHhWNBIhQ2WHCbrc/tEPuRcEIBYMAwJiAmH///9///+AgAQ=";
+
private final DisasterRecoveryRequestSerializer serializer = new
DisasterRecoveryRequestSerializer();
@Test
@@ -52,7 +55,7 @@ class DisasterRecoveryRequestSerializerTest {
@Test
void v1OfManualGroupUpdateRequestCanBeDeserialized() {
- byte[] bytes =
Base64.getDecoder().decode("Ae++QwEB775D782rkHhWNBIhQ2WHCbrc/ukH0Q+5FwQWDCA=");
+ byte[] bytes =
Base64.getDecoder().decode(MANUAL_GROUP_UPDATE_REQUEST_V1_BASE64);
ManualGroupUpdateRequest restoredRequest = (ManualGroupUpdateRequest)
VersionedSerialization.fromBytes(bytes, serializer);
assertThat(restoredRequest.operationId(), is(new
UUID(0x1234567890ABCDEFL, 0xFEDCBA0987654321L)));
@@ -86,7 +89,7 @@ class DisasterRecoveryRequestSerializerTest {
@Test
void v1OfManualGroupRestartRequestCanBeDeserialized() {
- byte[] bytes =
Base64.getDecoder().decode("Ae++QwIB775D782rkHhWNBIhQ2WHCbrc/tEPuRcEDCAWAwJiAmH/////////fw==");
+ byte[] bytes =
Base64.getDecoder().decode(MANUAL_GROUP_RESTART_REQUEST_V1_BASE64);
ManualGroupRestartRequest restoredRequest =
(ManualGroupRestartRequest) VersionedSerialization.fromBytes(bytes, serializer);
assertThat(restoredRequest.operationId(), is(new
UUID(0x1234567890ABCDEFL, 0xFEDCBA0987654321L)));
@@ -96,4 +99,19 @@ class DisasterRecoveryRequestSerializerTest {
assertThat(restoredRequest.nodeNames(), is(Set.of("a", "b")));
assertThat(restoredRequest.assignmentsTimestamp(),
is(HybridTimestamp.MAX_VALUE.longValue()));
}
+
+ @SuppressWarnings("unused")
+ private String manualGroupRestartRequestV1Base64() {
+ var originalRequest = new ManualGroupRestartRequest(
+ new UUID(0x1234567890ABCDEFL, 0xFEDCBA0987654321L),
+ 2000,
+ 3000,
+ Set.of(11, 21, 31),
+ Set.of("a", "b"),
+ HybridTimestamp.MAX_VALUE.longValue()
+ );
+
+ byte[] v1Bytes = VersionedSerialization.toBytes(originalRequest,
serializer);
+ return Base64.getEncoder().encodeToString(v1Bytes);
+ }
}
diff --git
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/index/IndexMetaSerializerTest.java
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/index/IndexMetaSerializerTest.java
index c15c2be7ae..e57e139962 100644
---
a/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/index/IndexMetaSerializerTest.java
+++
b/modules/table/src/test/java/org/apache/ignite/internal/table/distributed/index/IndexMetaSerializerTest.java
@@ -33,6 +33,9 @@ import
org.apache.ignite.internal.versioned.VersionedSerialization;
import org.junit.jupiter.api.Test;
class IndexMetaSerializerTest {
+ private static final String V1_SERIALIZED_BASE64 =
"Ae++Q+kH0Q+5F6EfBmluZGV4BgcEBQAAAAAAAJEDAgMAAAAAAADJAQYHAAAAAAAA2QQFBgAAAAAAAPU"
+ + "DAwQAAAAAAACtAgECAAAAAAAAZQ==";
+
private final IndexMetaSerializer serializer = new IndexMetaSerializer();
@Test
@@ -64,8 +67,7 @@ class IndexMetaSerializerTest {
@Test
void v1CanBeDeserialized() {
- byte[] bytes =
Base64.getDecoder().decode("Ae++Q+kH0Q+5F6EfBmluZGV4BgcCA8gAAAAAAAAAAwQsAQAAAAAAAAECZAAAAAAAAAAFBvQBAAAAAAAABAWQ"
- + "AQAAAAAAAAYHWAIAAAAAAAA=");
+ byte[] bytes = Base64.getDecoder().decode(V1_SERIALIZED_BASE64);
IndexMeta restoredMeta = VersionedSerialization.fromBytes(bytes,
serializer);
assertThat(restoredMeta.catalogVersion(), is(1000));
@@ -76,4 +78,12 @@ class IndexMetaSerializerTest {
assertThat(restoredMeta.status(), is(READ_ONLY));
assertThat(restoredMeta.statusChanges(),
equalTo(originalStatusChanges()));
}
+
+ @SuppressWarnings("unused")
+ private String v1Base64() {
+ IndexMeta originalMeta = new IndexMeta(1000, 2000, 3000, 4000,
"index", READ_ONLY, originalStatusChanges());
+
+ byte[] v1Bytes = VersionedSerialization.toBytes(originalMeta,
serializer);
+ return Base64.getEncoder().encodeToString(v1Bytes);
+ }
}
diff --git
a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxMetaSerializer.java
b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxMetaSerializer.java
index 774a5c4b36..51f5df511a 100644
---
a/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxMetaSerializer.java
+++
b/modules/transactions/src/main/java/org/apache/ignite/internal/tx/TxMetaSerializer.java
@@ -43,16 +43,14 @@ public class TxMetaSerializer extends
VersionedSerializer<TxMeta> {
out.writeVarInt(partitionId.partitionId());
}
- HybridTimestamp commitTimestamp = meta.commitTimestamp();
- // Using long and not varlong as the latter requires 9 bytes for
hybrid timestamps.
- out.writeLong(HybridTimestamp.hybridTimestampToLong(commitTimestamp));
+ HybridTimestamp.write(meta.commitTimestamp(), out);
}
@Override
protected TxMeta readExternalData(byte protoVer, IgniteDataInput in)
throws IOException {
TxState state = TxState.fromOrdinal(in.readVarIntAsInt());
List<TablePartitionId> enlistedPartitions = readEnlistedPartitions(in);
- HybridTimestamp commitTimestamp =
HybridTimestamp.nullableHybridTimestamp(in.readLong());
+ HybridTimestamp commitTimestamp = HybridTimestamp.readNullableFrom(in);
return new TxMeta(state, enlistedPartitions, commitTimestamp);
}
diff --git
a/modules/transactions/src/test/java/org/apache/ignite/internal/tx/TxMetaSerializerTest.java
b/modules/transactions/src/test/java/org/apache/ignite/internal/tx/TxMetaSerializerTest.java
index eec9c7727e..ac28019da3 100644
---
a/modules/transactions/src/test/java/org/apache/ignite/internal/tx/TxMetaSerializerTest.java
+++
b/modules/transactions/src/test/java/org/apache/ignite/internal/tx/TxMetaSerializerTest.java
@@ -30,6 +30,8 @@ import
org.apache.ignite.internal.versioned.VersionedSerialization;
import org.junit.jupiter.api.Test;
class TxMetaSerializerTest {
+ private static final String V1_SERIALIZED_BASE64 =
"Ae++QwUD6QcQ0Q8a////f///gIAE";
+
private final TxMetaSerializer serializer = new TxMetaSerializer();
@Test
@@ -62,11 +64,22 @@ class TxMetaSerializerTest {
@Test
void v1CanBeDeserialized() {
- byte[] bytes =
Base64.getDecoder().decode("Ae++QwUD6QcQ0Q8a/////////38=");
+ byte[] bytes = Base64.getDecoder().decode(V1_SERIALIZED_BASE64);
TxMeta restoredMeta = VersionedSerialization.fromBytes(bytes,
serializer);
assertThat(restoredMeta.txState(), is(TxState.ABANDONED));
assertThat(restoredMeta.enlistedPartitions(), contains(new
TablePartitionId(1000, 15), new TablePartitionId(2000, 25)));
assertThat(restoredMeta.commitTimestamp(),
is(HybridTimestamp.MAX_VALUE));
}
+
+ @SuppressWarnings("unused")
+ private String v1SerializedBase64() {
+ TxMeta originalMeta = new TxMeta(
+ TxState.ABANDONED,
+ List.of(new TablePartitionId(1000, 15), new
TablePartitionId(2000, 25)),
+ HybridTimestamp.MAX_VALUE
+ );
+ byte[] v1Bytes = VersionedSerialization.toBytes(originalMeta,
serializer);
+ return Base64.getEncoder().encodeToString(v1Bytes);
+ }
}