27
27
import java .util .List ;
28
28
import java .util .Map ;
29
29
import java .util .Set ;
30
+ import java .util .concurrent .CompletableFuture ;
30
31
import java .util .concurrent .Future ;
31
32
import java .util .concurrent .TimeUnit ;
32
33
import java .util .concurrent .atomic .AtomicBoolean ;
82
83
import org .apache .hadoop .hbase .rsgroup .RSGroupBasedLoadBalancer ;
83
84
import org .apache .hadoop .hbase .util .Bytes ;
84
85
import org .apache .hadoop .hbase .util .EnvironmentEdgeManager ;
86
+ import org .apache .hadoop .hbase .util .FutureUtils ;
85
87
import org .apache .hadoop .hbase .util .Pair ;
86
88
import org .apache .hadoop .hbase .util .Threads ;
87
89
import org .apache .hadoop .hbase .util .VersionInfo ;
@@ -1989,71 +1991,78 @@ public RegionInfo getRegionInfo(final String encodedRegionName) {
1989
1991
// Should only be called in TransitRegionStateProcedure(and related procedures), as the locking
1990
1992
// and pre-assumptions are very tricky.
1991
1993
// ============================================================================================
1992
- private void transitStateAndUpdate (RegionStateNode regionNode , RegionState . State newState ,
1993
- RegionState .State ... expectedStates ) throws IOException {
1994
+ private CompletableFuture < Void > transitStateAndUpdate (RegionStateNode regionNode ,
1995
+ RegionState .State newState , RegionState . State ... expectedStates ) {
1994
1996
RegionState .State state = regionNode .getState ();
1995
- regionNode .transitionState (newState , expectedStates );
1996
- boolean succ = false ;
1997
1997
try {
1998
- regionStateStore .updateRegionLocation (regionNode );
1999
- succ = true ;
2000
- } finally {
2001
- if (!succ ) {
1998
+ regionNode .transitionState (newState , expectedStates );
1999
+ } catch (UnexpectedStateException e ) {
2000
+ return FutureUtils .failedFuture (e );
2001
+ }
2002
+ CompletableFuture <Void > future = regionStateStore .updateRegionLocation (regionNode );
2003
+ FutureUtils .addListener (future , (r , e ) -> {
2004
+ if (e != null ) {
2002
2005
// revert
2003
2006
regionNode .setState (state );
2004
2007
}
2005
- }
2008
+ });
2009
+ return future ;
2006
2010
}
2007
2011
2008
2012
// should be called within the synchronized block of RegionStateNode
2009
- void regionOpening (RegionStateNode regionNode ) throws IOException {
2013
+ CompletableFuture < Void > regionOpening (RegionStateNode regionNode ) {
2010
2014
// As in SCP, for performance reason, there is no TRSP attached with this region, we will not
2011
2015
// update the region state, which means that the region could be in any state when we want to
2012
2016
// assign it after a RS crash. So here we do not pass the expectedStates parameter.
2013
- transitStateAndUpdate (regionNode , State .OPENING );
2014
- regionStates .addRegionToServer (regionNode );
2015
- // update the operation count metrics
2016
- metrics .incrementOperationCounter ();
2017
+ return transitStateAndUpdate (regionNode , State .OPENING ).thenAccept (r -> {
2018
+ regionStates .addRegionToServer (regionNode );
2019
+ // update the operation count metrics
2020
+ metrics .incrementOperationCounter ();
2021
+ });
2017
2022
}
2018
2023
2019
2024
// should be called under the RegionStateNode lock
2020
2025
// The parameter 'giveUp' means whether we will try to open the region again, if it is true, then
2021
2026
// we will persist the FAILED_OPEN state into hbase:meta.
2022
- void regionFailedOpen (RegionStateNode regionNode , boolean giveUp ) throws IOException {
2027
+ CompletableFuture < Void > regionFailedOpen (RegionStateNode regionNode , boolean giveUp ) {
2023
2028
RegionState .State state = regionNode .getState ();
2024
2029
ServerName regionLocation = regionNode .getRegionLocation ();
2025
- if (giveUp ) {
2026
- regionNode .setState (State .FAILED_OPEN );
2027
- regionNode .setRegionLocation (null );
2028
- boolean succ = false ;
2029
- try {
2030
- regionStateStore .updateRegionLocation (regionNode );
2031
- succ = true ;
2032
- } finally {
2033
- if (!succ ) {
2034
- // revert
2035
- regionNode .setState (state );
2036
- regionNode .setRegionLocation (regionLocation );
2037
- }
2030
+ if (!giveUp ) {
2031
+ if (regionLocation != null ) {
2032
+ regionStates .removeRegionFromServer (regionLocation , regionNode );
2038
2033
}
2034
+ return CompletableFuture .completedFuture (null );
2039
2035
}
2040
- if (regionLocation != null ) {
2041
- regionStates .removeRegionFromServer (regionLocation , regionNode );
2042
- }
2036
+ regionNode .setState (State .FAILED_OPEN );
2037
+ regionNode .setRegionLocation (null );
2038
+ CompletableFuture <Void > future = regionStateStore .updateRegionLocation (regionNode );
2039
+ FutureUtils .addListener (future , (r , e ) -> {
2040
+ if (e == null ) {
2041
+ if (regionLocation != null ) {
2042
+ regionStates .removeRegionFromServer (regionLocation , regionNode );
2043
+ }
2044
+ } else {
2045
+ // revert
2046
+ regionNode .setState (state );
2047
+ regionNode .setRegionLocation (regionLocation );
2048
+ }
2049
+ });
2050
+ return future ;
2043
2051
}
2044
2052
2045
2053
// should be called under the RegionStateNode lock
2046
- void regionClosing (RegionStateNode regionNode ) throws IOException {
2047
- transitStateAndUpdate (regionNode , State .CLOSING , STATES_EXPECTED_ON_CLOSING );
2048
-
2049
- RegionInfo hri = regionNode .getRegionInfo ();
2050
- // Set meta has not initialized early. so people trying to create/edit tables will wait
2051
- if (isMetaRegion (hri )) {
2052
- setMetaAssigned (hri , false );
2053
- }
2054
- regionStates .addRegionToServer (regionNode );
2055
- // update the operation count metrics
2056
- metrics .incrementOperationCounter ();
2054
+ CompletableFuture <Void > regionClosing (RegionStateNode regionNode ) {
2055
+ return transitStateAndUpdate (regionNode , State .CLOSING , STATES_EXPECTED_ON_CLOSING )
2056
+ .thenAccept (r -> {
2057
+ RegionInfo hri = regionNode .getRegionInfo ();
2058
+ // Set meta has not initialized early. so people trying to create/edit tables will wait
2059
+ if (isMetaRegion (hri )) {
2060
+ setMetaAssigned (hri , false );
2061
+ }
2062
+ regionStates .addRegionToServer (regionNode );
2063
+ // update the operation count metrics
2064
+ metrics .incrementOperationCounter ();
2065
+ });
2057
2066
}
2058
2067
2059
2068
// for open and close, they will first be persist to the procedure store in
@@ -2062,15 +2071,17 @@ void regionClosing(RegionStateNode regionNode) throws IOException {
2062
2071
// RegionRemoteProcedureBase is woken up, we will persist the RegionStateNode to hbase:meta.
2063
2072
2064
2073
// should be called under the RegionStateNode lock
2065
- void regionOpenedWithoutPersistingToMeta (RegionStateNode regionNode ) throws IOException {
2074
+ void regionOpenedWithoutPersistingToMeta (RegionStateNode regionNode )
2075
+ throws UnexpectedStateException {
2066
2076
regionNode .transitionState (State .OPEN , STATES_EXPECTED_ON_OPEN );
2067
2077
RegionInfo regionInfo = regionNode .getRegionInfo ();
2068
2078
regionStates .addRegionToServer (regionNode );
2069
2079
regionStates .removeFromFailedOpen (regionInfo );
2070
2080
}
2071
2081
2072
2082
// should be called under the RegionStateNode lock
2073
- void regionClosedWithoutPersistingToMeta (RegionStateNode regionNode ) throws IOException {
2083
+ void regionClosedWithoutPersistingToMeta (RegionStateNode regionNode )
2084
+ throws UnexpectedStateException {
2074
2085
ServerName regionLocation = regionNode .getRegionLocation ();
2075
2086
regionNode .transitionState (State .CLOSED , STATES_EXPECTED_ON_CLOSED );
2076
2087
regionNode .setRegionLocation (null );
@@ -2080,40 +2091,41 @@ void regionClosedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOEx
2080
2091
}
2081
2092
}
2082
2093
2094
+ // should be called under the RegionStateNode lock
2095
+ CompletableFuture <Void > persistToMeta (RegionStateNode regionNode ) {
2096
+ return regionStateStore .updateRegionLocation (regionNode ).thenAccept (r -> {
2097
+ RegionInfo regionInfo = regionNode .getRegionInfo ();
2098
+ if (isMetaRegion (regionInfo ) && regionNode .getState () == State .OPEN ) {
2099
+ // Usually we'd set a table ENABLED at this stage but hbase:meta is ALWAYs enabled, it
2100
+ // can't be disabled -- so skip the RPC (besides... enabled is managed by TableStateManager
2101
+ // which is backed by hbase:meta... Avoid setting ENABLED to avoid having to update state
2102
+ // on table that contains state.
2103
+ setMetaAssigned (regionInfo , true );
2104
+ }
2105
+ });
2106
+ }
2107
+
2083
2108
// should be called under the RegionStateNode lock
2084
2109
// for SCP
2085
- public void regionClosedAbnormally (RegionStateNode regionNode ) throws IOException {
2110
+ public CompletableFuture < Void > regionClosedAbnormally (RegionStateNode regionNode ) {
2086
2111
RegionState .State state = regionNode .getState ();
2087
2112
ServerName regionLocation = regionNode .getRegionLocation ();
2088
- regionNode .transitionState (State .ABNORMALLY_CLOSED );
2113
+ regionNode .setState (State .ABNORMALLY_CLOSED );
2089
2114
regionNode .setRegionLocation (null );
2090
- boolean succ = false ;
2091
- try {
2092
- regionStateStore .updateRegionLocation (regionNode );
2093
- succ = true ;
2094
- } finally {
2095
- if (!succ ) {
2115
+ CompletableFuture <Void > future = regionStateStore .updateRegionLocation (regionNode );
2116
+ FutureUtils .addListener (future , (r , e ) -> {
2117
+ if (e == null ) {
2118
+ if (regionLocation != null ) {
2119
+ regionNode .setLastHost (regionLocation );
2120
+ regionStates .removeRegionFromServer (regionLocation , regionNode );
2121
+ }
2122
+ } else {
2096
2123
// revert
2097
2124
regionNode .setState (state );
2098
2125
regionNode .setRegionLocation (regionLocation );
2099
2126
}
2100
- }
2101
- if (regionLocation != null ) {
2102
- regionNode .setLastHost (regionLocation );
2103
- regionStates .removeRegionFromServer (regionLocation , regionNode );
2104
- }
2105
- }
2106
-
2107
- void persistToMeta (RegionStateNode regionNode ) throws IOException {
2108
- regionStateStore .updateRegionLocation (regionNode );
2109
- RegionInfo regionInfo = regionNode .getRegionInfo ();
2110
- if (isMetaRegion (regionInfo ) && regionNode .getState () == State .OPEN ) {
2111
- // Usually we'd set a table ENABLED at this stage but hbase:meta is ALWAYs enabled, it
2112
- // can't be disabled -- so skip the RPC (besides... enabled is managed by TableStateManager
2113
- // which is backed by hbase:meta... Avoid setting ENABLED to avoid having to update state
2114
- // on table that contains state.
2115
- setMetaAssigned (regionInfo , true );
2116
- }
2127
+ });
2128
+ return future ;
2117
2129
}
2118
2130
2119
2131
// ============================================================================================
0 commit comments