Skip to content

Commit d3c739b

Browse files
authored
IGNITE-28013 Fix stale leaseholder ID handling in LeaseUpdater and lease batch serialization (#7769)
1 parent 40eca02 commit d3c739b

File tree

6 files changed

+381
-23
lines changed

6 files changed

+381
-23
lines changed

modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/LeaseUpdater.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,6 @@ private void updateLeaseBatchInternal() {
486486
: lease.proposedCandidate();
487487

488488
InternalClusterNode candidate = nextLeaseHolder(stableAssignments, pendingAssignments, grpId, proposedLeaseholder);
489-
490489
boolean canBeProlonged = lease.isAccepted()
491490
&& lease.isProlongable()
492491
&& candidate != null && candidate.id().equals(lease.getLeaseholderId());

modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/leases/LeaseBatchSerializer.java

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/leases/NodesDictionary.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ int nameCount() {
132132
return nameIndexToName.size();
133133
}
134134

135+
int nodeCount() {
136+
return nodeIndexToId.size();
137+
}
138+
135139
@Override
136140
public boolean equals(Object o) {
137141
if (this == o) {

0 commit comments

Comments
 (0)