diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/Procedure.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/Procedure.java index 13de210c6b3..601ebcd0f49 100644 --- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/Procedure.java +++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/Procedure.java @@ -206,10 +206,18 @@ public abstract class Procedure implements Comparable { } sb.append(" state="); - sb.append(getState()); + toStringState(sb); return sb.toString(); } + /** + * Called from {@link #toString()} when interpolating {@link Procedure} state + * @param builder Append current {@link ProcedureState} + */ + protected void toStringState(StringBuilder builder) { + builder.append(getState()); + } + /** * Extend the toString() information with the procedure details * e.g. className and parameters diff --git a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/StateMachineProcedure.java b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/StateMachineProcedure.java index 8b132e7073c..286a7bf8e83 100644 --- a/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/StateMachineProcedure.java +++ b/hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/StateMachineProcedure.java @@ -163,6 +163,14 @@ public abstract class StateMachineProcedure states[stateCount++] = stateId; } + @Override + protected void toStringState(StringBuilder builder) { + super.toStringState(builder); + if (!isFinished() && getCurrentState() != null) { + builder.append(":").append(getCurrentState()); + } + } + @Override protected void serializeStateData(final OutputStream stream) throws IOException { StateMachineProcedureData.Builder data = StateMachineProcedureData.newBuilder(); diff --git a/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/TestProcedureToString.java b/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/TestProcedureToString.java new file mode 100644 index 00000000000..5dea06ea1ff --- /dev/null +++ b/hbase-procedure/src/test/java/org/apache/hadoop/hbase/procedure2/TestProcedureToString.java @@ -0,0 +1,149 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.procedure2; + +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.ServerCrashState; +import org.apache.hadoop.hbase.protobuf.generated.ProcedureProtos.ProcedureState; +import org.apache.hadoop.hbase.testclassification.MasterTests; +import org.apache.hadoop.hbase.testclassification.SmallTests; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +@Category({MasterTests.class, SmallTests.class}) +public class TestProcedureToString { + /** + * A do-nothing environment for BasicProcedure. + */ + static class BasicProcedureEnv {}; + + /** + * A do-nothing basic procedure just for testing toString. + */ + static class BasicProcedure extends Procedure { + @Override + protected Procedure[] execute(BasicProcedureEnv env) + throws ProcedureYieldException, InterruptedException { + return new Procedure [] {this}; + } + + @Override + protected void rollback(BasicProcedureEnv env) throws IOException, InterruptedException { + } + + @Override + protected boolean abort(BasicProcedureEnv env) { + return false; + } + + @Override + protected void serializeStateData(OutputStream stream) throws IOException { + } + + @Override + protected void deserializeStateData(InputStream stream) throws IOException { + } + } + + /** + * A do-nothing basic procedure that overrides the toStringState method. It just doubles the + * current state string. + */ + static class DoublingStateStringBasicProcedure extends BasicProcedure { + @Override + protected void toStringState(StringBuilder builder) { + // Call twice to get the state string twice as our state value. + super.toStringState(builder); + super.toStringState(builder); + } + } + + + + /** + * Test that I can override the toString for its state value. + * @throws ProcedureYieldException + * @throws InterruptedException + */ + @Test + public void testBasicToString() throws ProcedureYieldException, InterruptedException { + BasicProcedure p = new BasicProcedure(); + ProcedureState state = ProcedureState.RUNNABLE; + p.setState(state); + // Just assert that the toString basically works and has state in it. + assertTrue(p.toString().contains(state.toString())); + p = new DoublingStateStringBasicProcedure(); + p.setState(state); + // Assert our override works and that we get double the state... + String testStr = state.toString() + state.toString(); + assertTrue(p.toString().contains(testStr)); + } + + /** + * Do-nothing SimpleMachineProcedure for checking its toString. + */ + static class SimpleStateMachineProcedure + extends StateMachineProcedure { + @Override + protected org.apache.hadoop.hbase.procedure2.StateMachineProcedure.Flow executeFromState(BasicProcedureEnv env, + ServerCrashState state) throws ProcedureYieldException, InterruptedException { + return null; + } + + @Override + protected void rollbackState(BasicProcedureEnv env, ServerCrashState state) throws IOException, + InterruptedException { + } + + @Override + protected ServerCrashState getState(int stateId) { + return ServerCrashState.valueOf(stateId); + } + + @Override + protected int getStateId(ServerCrashState state) { + return state.getNumber(); + } + + @Override + protected ServerCrashState getInitialState() { + return null; + } + + @Override + protected boolean abort(BasicProcedureEnv env) { + return false; + } + } + + @Test + public void testStateMachineProcedure() { + SimpleStateMachineProcedure p = new SimpleStateMachineProcedure(); + ProcedureState state = ProcedureState.RUNNABLE; + p.setState(state); + p.setNextState(ServerCrashState.SERVER_CRASH_ASSIGN); + // Just assert that the toString basically works and has state in it. + assertTrue(p.toString().contains(state.toString())); + assertTrue(p.toString().contains(ServerCrashState.SERVER_CRASH_ASSIGN.toString())); + } +} \ No newline at end of file