1717 */
1818package org .apache .hadoop .hbase .master .assignment ;
1919
20+ import com .google .errorprone .annotations .RestrictedApi ;
2021import java .util .ArrayList ;
2122import java .util .List ;
2223import java .util .Objects ;
3940@ InterfaceAudience .Private
4041public class RegionInTransitionTracker {
4142 private static final Logger LOG = LoggerFactory .getLogger (RegionInTransitionTracker .class );
42- private static final LongConsumer NOOP_RIT_DURATION_CONSUMER = ignored -> {
43- };
4443
4544 private static final List <RegionState .State > DISABLE_TABLE_REGION_STATE =
4645 List .of (RegionState .State .OFFLINE , RegionState .State .CLOSED );
4746
4847 private static final List <RegionState .State > ENABLE_TABLE_REGION_STATE =
4948 List .of (RegionState .State .OPEN );
5049
51- // DO NOT USE containsKey()/remove() on regionInTransition with a different RegionInfo instance:
52- // this map is ordered by RegionInfo.COMPARATOR, and that comparator includes the offline flag.
53- // Lookups can therefore fail if the RegionInfo used as the key has a different offline value,
54- // even when it refers to the same region. Offline value changes with splitting.
50+ // DO NOT USE containsKey()/remove() on regionInTransition with a RegionInfo instance whose
51+ // offline flag differs from the one stored as the key: RegionInfo#equals and #hashCode both
52+ // include the offline flag, so such a lookup misses even when it refers to the same region.
53+ // Offline value changes with splitting.
5554 private final ConcurrentHashMap <RegionInfo , Pair <RegionStateNode , Long >> regionInTransition =
5655 new ConcurrentHashMap <>();
5756
5857 private final LongConsumer ritDurationConsumer ;
5958 private TableStateManager tableStateManager ;
6059
61- public RegionInTransitionTracker () {
62- this (NOOP_RIT_DURATION_CONSUMER );
63- }
64-
6560 public RegionInTransitionTracker (LongConsumer ritDurationConsumer ) {
6661 this .ritDurationConsumer = Objects .requireNonNull (ritDurationConsumer );
6762 }
6863
69- public boolean isRegionInTransition (final RegionInfo regionInfo ) {
64+ @ RestrictedApi (explanation = "Should only be called in tests" , link = "" ,
65+ allowedOnPath = ".*/src/test/.*" )
66+ boolean isRegionInTransition (final RegionInfo regionInfo ) {
7067 return regionInTransition .containsKey (regionInfo );
7168 }
7269
@@ -75,11 +72,10 @@ public boolean isRegionInTransition(final RegionInfo regionInfo) {
7572 * it was hosting are automatically added to the RIT list since they need to be reassigned to
7673 * other servers.
7774 * @param regionStateNode the region whose hosting server crashed
78- * @param crashTime the time the hosting server crashed, used as the RIT start time. We take
79- * it explicitly instead of reading {@link RegionStateNode#getLastUpdate()}
80- * because the latter is masked by a stale procedure that may still be
81- * attached from before the server died, which would anchor the duration at
82- * the wrong time. A non-positive value falls back to the node's last
75+ * @param crashTime the RIT start time to use when the region is not already in transition
76+ * (an existing entry keeps its earlier start). Passed explicitly rather
77+ * than read from {@link RegionStateNode#getLastUpdate()}, which a stale
78+ * procedure can mask. A non-positive value falls back to the node's last
8379 * update.
8480 */
8581 public void regionCrashed (RegionStateNode regionStateNode , long crashTime ) {
@@ -171,7 +167,7 @@ private boolean removeRegionInTransition(final RegionInfo regionInfo) {
171167 Pair <RegionStateNode , Long > removed = regionInTransition .remove (regionInfo );
172168 if (removed != null ) {
173169 long duration = EnvironmentEdgeManager .currentTime () - removed .getSecond ();
174- if (duration > 0 ) {
170+ if (duration >= 0 ) {
175171 ritDurationConsumer .accept (duration );
176172 }
177173 }
@@ -205,5 +201,4 @@ public void setTableStateManager(TableStateManager tableStateManager) {
205201 private static boolean isReplica (RegionStateNode regionStateNode ) {
206202 return regionStateNode .getRegionInfo ().getReplicaId () != RegionInfo .DEFAULT_REPLICA_ID ;
207203 }
208-
209204}
0 commit comments