17
17
18
18
package org .apache .kafka .controller ;
19
19
20
+ import java .util .OptionalLong ;
20
21
import org .apache .kafka .common .message .BrokerHeartbeatRequestData ;
21
22
import org .apache .kafka .common .utils .LogContext ;
22
23
import org .apache .kafka .common .utils .Time ;
42
43
/**
43
44
* The BrokerHeartbeatManager manages all the soft state associated with broker heartbeats.
44
45
* Soft state is state which does not appear in the metadata log. This state includes
45
- * things like the last time each broker sent us a heartbeat, and whether the broker is
46
- * trying to perform a controlled shutdown.
46
+ * things like the last time each broker sent us a heartbeat. As of KIP-841, the controlled
47
+ * shutdown state is no longer treated as soft state and is persisted to the metadata log on broker
48
+ * controlled shutdown requests.
47
49
*
48
50
* Only the active controller has a BrokerHeartbeatManager, since only the active
49
51
* controller handles broker heartbeats. Standby controllers will create a heartbeat
@@ -77,7 +79,7 @@ static class BrokerHeartbeatState {
77
79
* if the broker is not performing a controlled shutdown. When this field is
78
80
* updated, we also have to update the broker's position in the shuttingDown set.
79
81
*/
80
- private long controlledShutDownOffset ;
82
+ private long controlledShutdownOffset ;
81
83
82
84
/**
83
85
* The previous entry in the unfenced list, or null if the broker is not in that list.
@@ -95,7 +97,7 @@ static class BrokerHeartbeatState {
95
97
this .prev = null ;
96
98
this .next = null ;
97
99
this .metadataOffset = -1 ;
98
- this .controlledShutDownOffset = -1 ;
100
+ this .controlledShutdownOffset = -1 ;
99
101
}
100
102
101
103
/**
@@ -116,7 +118,7 @@ boolean fenced() {
116
118
* Returns true only if the broker is in controlled shutdown state.
117
119
*/
118
120
boolean shuttingDown () {
119
- return controlledShutDownOffset >= 0 ;
121
+ return controlledShutdownOffset >= 0 ;
120
122
}
121
123
}
122
124
@@ -275,6 +277,16 @@ Collection<BrokerHeartbeatState> brokers() {
275
277
return brokers .values ();
276
278
}
277
279
280
+ // VisibleForTesting
281
+ OptionalLong controlledShutdownOffset (int brokerId ) {
282
+ BrokerHeartbeatState broker = brokers .get (brokerId );
283
+ if (broker == null || broker .controlledShutdownOffset == -1 ) {
284
+ return OptionalLong .empty ();
285
+ }
286
+ return OptionalLong .of (broker .controlledShutdownOffset );
287
+ }
288
+
289
+
278
290
/**
279
291
* Mark a broker as fenced.
280
292
*
@@ -381,7 +393,7 @@ void touch(int brokerId, boolean fenced, long metadataOffset) {
381
393
if (fenced ) {
382
394
// If a broker is fenced, it leaves controlled shutdown. On its next heartbeat,
383
395
// it will shut down immediately.
384
- broker .controlledShutDownOffset = -1 ;
396
+ broker .controlledShutdownOffset = -1 ;
385
397
} else {
386
398
unfenced .add (broker );
387
399
if (!broker .shuttingDown ()) {
@@ -400,12 +412,13 @@ long lowestActiveOffset() {
400
412
}
401
413
402
414
/**
403
- * Mark a broker as being in the controlled shutdown state.
415
+ * Mark a broker as being in the controlled shutdown state. We only update the
416
+ * controlledShutdownOffset if the broker was previously not in controlled shutdown state.
404
417
*
405
418
* @param brokerId The broker id.
406
419
* @param controlledShutDownOffset The offset at which controlled shutdown will be complete.
407
420
*/
408
- void updateControlledShutdownOffset (int brokerId , long controlledShutDownOffset ) {
421
+ void maybeUpdateControlledShutdownOffset (int brokerId , long controlledShutDownOffset ) {
409
422
BrokerHeartbeatState broker = brokers .get (brokerId );
410
423
if (broker == null ) {
411
424
throw new RuntimeException ("Unable to locate broker " + brokerId );
@@ -414,9 +427,11 @@ void updateControlledShutdownOffset(int brokerId, long controlledShutDownOffset)
414
427
throw new RuntimeException ("Fenced brokers cannot enter controlled shutdown." );
415
428
}
416
429
active .remove (broker );
417
- broker .controlledShutDownOffset = controlledShutDownOffset ;
418
- log .debug ("Updated the controlled shutdown offset for broker {} to {}." ,
419
- brokerId , controlledShutDownOffset );
430
+ if (broker .controlledShutdownOffset < 0 ) {
431
+ broker .controlledShutdownOffset = controlledShutDownOffset ;
432
+ log .debug ("Updated the controlled shutdown offset for broker {} to {}." ,
433
+ brokerId , controlledShutDownOffset );
434
+ }
420
435
}
421
436
422
437
/**
@@ -581,17 +596,17 @@ BrokerControlStates calculateNextBrokerState(int brokerId,
581
596
return new BrokerControlStates (currentState , CONTROLLED_SHUTDOWN );
582
597
}
583
598
long lowestActiveOffset = lowestActiveOffset ();
584
- if (broker .controlledShutDownOffset <= lowestActiveOffset ) {
599
+ if (broker .controlledShutdownOffset <= lowestActiveOffset ) {
585
600
log .info ("The request from broker {} to shut down has been granted " +
586
601
"since the lowest active offset {} is now greater than the " +
587
602
"broker's controlled shutdown offset {}." , brokerId ,
588
- lowestActiveOffset , broker .controlledShutDownOffset );
603
+ lowestActiveOffset , broker .controlledShutdownOffset );
589
604
return new BrokerControlStates (currentState , SHUTDOWN_NOW );
590
605
}
591
606
log .debug ("The request from broker {} to shut down can not yet be granted " +
592
607
"because the lowest active offset {} is not greater than the broker's " +
593
608
"shutdown offset {}." , brokerId , lowestActiveOffset ,
594
- broker .controlledShutDownOffset );
609
+ broker .controlledShutdownOffset );
595
610
return new BrokerControlStates (currentState , CONTROLLED_SHUTDOWN );
596
611
597
612
default :
0 commit comments