This is an automated email from the ASF dual-hosted git repository. kturner pushed a commit to branch elasticity in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/elasticity by this push: new 7501cb513e fixes a race condition in tablet group watcher (#4048) 7501cb513e is described below commit 7501cb513e016d1cb896184edc5b4bee0dd732ef Author: Keith Turner <ktur...@apache.org> AuthorDate: Mon Dec 11 14:16:20 2023 -0500 fixes a race condition in tablet group watcher (#4048) There was a race condition between the two thread in tablet group watcher that caused a tablet to be marked as assigned to a dead tablet server when that was not true. This commit fixes that race condition, enables a test that was failing because of it, and adds the thread id to test logging. The thread id was useful in confirming this bug so it will probably be useful in the future. Below are some log messages from tracking this bug down. The number after the timestamp is the thread id. Can see thread 47 assigns tablet 1<< and then thread 46 assumes its assigned to a dead tablet server. However it was a not a dead tserver, it had just started as the test restarted tservers. ``` 2023-12-09T16:04:54,439 47 [manager.Manager] TRACE: [Normal Tablets] Shutting down all Tservers: false, dependentCount: null Extent: 1<<, state: UNASSIGNED, goal: HOSTED actions:[NEEDS_LOCATION_UPDATE] 2023-12-09T16:04:54,443 47 [tablet.location] DEBUG: Assigned 1<< to localhost:37775[10006c85a80001a] 2023-12-09T16:04:54,452 47 [manager.Manager] TRACE: [Normal Tablets] Shutting down all Tservers: false, dependentCount: null Extent: 1<<, state: ASSIGNED, goal: HOSTED actions:[NEEDS_LOCATION_UPDATE] 2023-12-09T16:04:55,514 46 [manager.Manager] TRACE: [Normal Tablets] Shutting down all Tservers: false, dependentCount: null Extent: 1<<, state: ASSIGNED_TO_DEAD_SERVER, goal: HOSTED actions:[NEEDS_LOCATION_UPDATE] 2023-12-09T16:04:55,515 46 [manager.Manager] DEBUG: 1 assigned to dead servers: [TabletMetadata[tableId=1,prevEndRow=<null>,sawPrevEndRow=true,oldPrevEndRow=<null>,sawOldPrevEndRow=false,endRow=<null>,location=Location [server=localhost:37775[10006c85a80001a], type=CURRENT],files={},scans=[],loadedFiles={},fetchedCols=[LOCATION, PREV_ROW, FILES, LAST, DIR, LOGS, SUSPEND, ECOMP, HOSTING_GOAL, HOSTING_REQUESTED, OPID, SELECTED],extent=1<<,last=Location [server=localhost:37775[10006c85a8 [...] 2023-12-09T16:04:55,536 46 [tablet.location] DEBUG: Suspended 1<< to localhost:37775 at 54231 ms with 1 walogs 2023-12-09T16:04:55,652 46 [manager.Manager] TRACE: [Normal Tablets] Shutting down all Tservers: false, dependentCount: null Extent: 1<<, state: SUSPENDED, goal: HOSTED actions:[NEEDS_LOCATION_UPDATE] ``` --- .../accumulo/manager/TabletGroupWatcher.java | 30 +++++++++++++++++++++- .../apache/accumulo/test/WriteAfterCloseIT.java | 2 -- test/src/main/resources/log4j2-test.properties | 2 +- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/server/manager/src/main/java/org/apache/accumulo/manager/TabletGroupWatcher.java b/server/manager/src/main/java/org/apache/accumulo/manager/TabletGroupWatcher.java index 4833e28f57..a217f870b7 100644 --- a/server/manager/src/main/java/org/apache/accumulo/manager/TabletGroupWatcher.java +++ b/server/manager/src/main/java/org/apache/accumulo/manager/TabletGroupWatcher.java @@ -426,7 +426,35 @@ abstract class TabletGroupWatcher extends AccumuloDaemonThread { final TableConfiguration tableConf = manager.getContext().getTableConfiguration(tableId); - final TabletState state = TabletState.compute(tm, currentTServers.keySet()); + TabletState state = TabletState.compute(tm, currentTServers.keySet()); + if (state == TabletState.ASSIGNED_TO_DEAD_SERVER) { + /* + * This code exists to deal with a race condition caused by two threads running in this + * class that compute tablets actions. One thread does full scans and the other reacts to + * events and does partial scans. Below is an example of the race condition this is + * handling. + * + * - TGW Thread 1 : reads the set of tablets servers and its empty + * + * - TGW Thread 2 : reads the set of tablet servers and its [TS1] + * + * - TGW Thread 2 : Sees tabletX without a location and assigns it to TS1 + * + * - TGW Thread 1 : Sees tabletX assigned to TS1 and assumes it's assigned to a dead tablet + * server because its set of live servers is the empty set. + * + * To deal with this race condition, this code recomputes the tablet state using the latest + * tservers when a tablet is seen assigned to a dead tserver. + */ + + TabletState newState = TabletState.compute(tm, manager.tserversSnapshot().getTservers()); + if (newState != state) { + LOG.debug("Tablet state changed when using latest set of tservers {} {} {}", + tm.getExtent(), state, newState); + state = newState; + } + } + // This is final because nothing in this method should change the goal. All computation of the // goal should be done in TabletGoalState.compute() so that all parts of the Accumulo code // will compute a consistent goal. diff --git a/test/src/main/java/org/apache/accumulo/test/WriteAfterCloseIT.java b/test/src/main/java/org/apache/accumulo/test/WriteAfterCloseIT.java index c77b57b2cf..34aa1de519 100644 --- a/test/src/main/java/org/apache/accumulo/test/WriteAfterCloseIT.java +++ b/test/src/main/java/org/apache/accumulo/test/WriteAfterCloseIT.java @@ -50,7 +50,6 @@ import org.apache.accumulo.minicluster.ServerType; import org.apache.accumulo.miniclusterImpl.MiniAccumuloConfigImpl; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.RawLocalFileSystem; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; public class WriteAfterCloseIT extends AccumuloClusterHarness { @@ -108,7 +107,6 @@ public class WriteAfterCloseIT extends AccumuloClusterHarness { } @Test - @Disabled // ELASTICITY_TODO public void testWriteAfterCloseKillTservers() throws Exception { runTest(TimeType.MILLIS, true, 0, false); } diff --git a/test/src/main/resources/log4j2-test.properties b/test/src/main/resources/log4j2-test.properties index f0d7d93212..70276bda59 100644 --- a/test/src/main/resources/log4j2-test.properties +++ b/test/src/main/resources/log4j2-test.properties @@ -25,7 +25,7 @@ appender.console.type = Console appender.console.name = STDOUT appender.console.target = SYSTEM_OUT appender.console.layout.type = PatternLayout -appender.console.layout.pattern = %d{ISO8601} [%c{2}] %-5p: %m%n +appender.console.layout.pattern = %d{ISO8601} %T [%c{2}] %-5p: %m%n logger.01.name = org.apache.accumulo.core logger.01.level = debug