@@ -141,6 +141,15 @@ public class LeaseBatchSerializer extends VersionedSerializer<LeaseBatch> {
141141 /** Mask to extract lease holder index from compact representation. */
142142 private static final int COMPACT_HOLDER_INDEX_MASK = (1 << BIT_WIDTH_TO_FIT_IN_HALF_BYTE ) - 1 ;
143143
144+ private static final byte PROTOCOL_V1 = 1 ;
145+
146+ private static final byte PROTOCOL_V2 = 2 ;
147+
148+ @ Override
149+ protected byte getProtocolVersion () {
150+ return PROTOCOL_V2 ;
151+ }
152+
144153 @ Override
145154 protected void writeExternalData (LeaseBatch batch , IgniteDataOutput out ) throws IOException {
146155 long minExpirationTimePhysical = minExpirationTimePhysicalPart (batch );
@@ -356,7 +365,9 @@ private static int packNodesInfo(int holderNodeIndex, int proposedCandidateNameI
356365 private static boolean holderIdAndProposedCandidateFitIn1Byte (NodesDictionary dictionary ) {
357366 // Up to 8 names means that for name index it's enough to have 3 bits, same for node index, so, in sum, they
358367 // require up to 6 bits, and we have 7 bits in a varint byte.
359- return dictionary .nameCount () <= MAX_NODES_FOR_COMPACT_MODE ;
368+ // We need to check both: name count (for proposed candidate index) and node count (for holder node index),
369+ // as these can diverge when nodes restart with new UUIDs but the same name.
370+ return dictionary .nameCount () <= MAX_NODES_FOR_COMPACT_MODE && dictionary .nodeCount () <= MAX_NODES_FOR_COMPACT_MODE ;
360371 }
361372
362373 private static int flags (
@@ -378,13 +389,15 @@ protected LeaseBatch readExternalData(byte protoVer, IgniteDataInput in) throws
378389 long minExpirationTimePhysical = in .readVarInt ();
379390 HybridTimestamp commonExpirationTime = new HybridTimestamp (minExpirationTimePhysical + in .readVarInt (), in .readVarIntAsInt ());
380391 NodesDictionary nodesDictionary = NodesDictionary .readFrom (in );
392+ boolean canReadNodesInfoCompactly = holderIdAndProposedCandidateFitIn1ByteForRead (protoVer , nodesDictionary );
381393
382394 List <Lease > leases = new ArrayList <>();
383395
384396 readPartitionedGroupLeases (
385397 minExpirationTimePhysical ,
386398 commonExpirationTime ,
387399 nodesDictionary ,
400+ canReadNodesInfoCompactly ,
388401 leases ,
389402 in ,
390403 TablePartitionId ::new
@@ -395,6 +408,7 @@ protected LeaseBatch readExternalData(byte protoVer, IgniteDataInput in) throws
395408 minExpirationTimePhysical ,
396409 commonExpirationTime ,
397410 nodesDictionary ,
411+ canReadNodesInfoCompactly ,
398412 leases ,
399413 in ,
400414 ZonePartitionId ::new
@@ -408,6 +422,7 @@ private static void readPartitionedGroupLeases(
408422 long minExpirationTimePhysical ,
409423 HybridTimestamp commonExpirationTime ,
410424 NodesDictionary nodesDictionary ,
425+ boolean canReadNodesInfoCompactly ,
411426 List <Lease > leases ,
412427 IgniteDataInput in ,
413428 GroupIdFactory groupIdFactory
@@ -420,6 +435,7 @@ private static void readPartitionedGroupLeases(
420435 minExpirationTimePhysical ,
421436 commonExpirationTime ,
422437 nodesDictionary ,
438+ canReadNodesInfoCompactly ,
423439 leases ,
424440 in ,
425441 groupIdFactory ,
@@ -432,6 +448,7 @@ private static int readLeasesForObject(
432448 long minExpirationTimePhysical ,
433449 HybridTimestamp commonExpirationTime ,
434450 NodesDictionary nodesDictionary ,
451+ boolean canReadNodesInfoCompactly ,
435452 List <Lease > leases ,
436453 IgniteDataInput in ,
437454 GroupIdFactory groupIdFactory ,
@@ -447,6 +464,7 @@ private static int readLeasesForObject(
447464 minExpirationTimePhysical ,
448465 commonExpirationTime ,
449466 nodesDictionary ,
467+ canReadNodesInfoCompactly ,
450468 in ,
451469 groupIdFactory
452470 );
@@ -464,6 +482,7 @@ private static int readLeasesForObject(
464482 long minExpirationTimePhysical ,
465483 HybridTimestamp commonExpirationTime ,
466484 NodesDictionary nodesDictionary ,
485+ boolean canReadNodesInfoCompactly ,
467486 IgniteDataInput in ,
468487 GroupIdFactory groupIdFactory
469488 ) throws IOException {
@@ -477,7 +496,7 @@ private static int readLeasesForObject(
477496
478497 int holderNodeIndex ;
479498 int proposedCandidateNodeIndex = -1 ;
480- if (holderIdAndProposedCandidateFitIn1Byte ( nodesDictionary ) ) {
499+ if (canReadNodesInfoCompactly ) {
481500 int nodesInfo = in .readVarIntAsInt ();
482501
483502 holderNodeIndex = unpackHolderNodeIndex (nodesInfo );
@@ -538,6 +557,16 @@ private static boolean flagSet(int flags, int mask) {
538557 return (flags & mask ) != 0 ;
539558 }
540559
560+ private static boolean holderIdAndProposedCandidateFitIn1ByteForRead (byte protoVer , NodesDictionary dictionary ) {
561+ if (protoVer == PROTOCOL_V1 ) {
562+ // In V1 format, we assumed that name and node tables have the same size,
563+ // so compact-mode eligibility was determined only by the name table size.
564+ return dictionary .nameCount () <= MAX_NODES_FOR_COMPACT_MODE ;
565+ }
566+
567+ return holderIdAndProposedCandidateFitIn1Byte (dictionary );
568+ }
569+
541570 @ FunctionalInterface
542571 private interface GroupIdFactory {
543572 PartitionGroupId create (int objectId , int partitionId );
0 commit comments