2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package org
.apache
.hadoop
.hbase
.procedure2
;
21 import java
.util
.ArrayList
;
22 import java
.util
.HashSet
;
23 import java
.util
.List
;
26 import org
.apache
.commons
.logging
.Log
;
27 import org
.apache
.commons
.logging
.LogFactory
;
28 import org
.apache
.hadoop
.hbase
.classification
.InterfaceAudience
;
29 import org
.apache
.hadoop
.hbase
.classification
.InterfaceStability
;
30 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.generated
.ProcedureProtos
.ProcedureState
;
33 * Internal state of the ProcedureExecutor that describes the state of a "Root Procedure".
34 * A "Root Procedure" is a Procedure without parent, each subprocedure will be
35 * added to the "Root Procedure" stack (or rollback-stack).
37 * RootProcedureState is used and managed only by the ProcedureExecutor.
38 * Long rootProcId = getRootProcedureId(proc);
39 * rollbackStack.get(rootProcId).acquire(proc)
40 * rollbackStack.get(rootProcId).release(proc)
43 @InterfaceAudience.Private
44 @InterfaceStability.Evolving
45 class RootProcedureState
{
46 private static final Log LOG
= LogFactory
.getLog(RootProcedureState
.class);
49 RUNNING
, // The Procedure is running or ready to run
50 FAILED
, // The Procedure failed, waiting for the rollback executing
51 ROLLINGBACK
, // The Procedure failed and the execution was rolledback
54 private Set
<Procedure
> subprocs
= null;
55 private ArrayList
<Procedure
> subprocStack
= null;
56 private State state
= State
.RUNNING
;
57 private int running
= 0;
59 public synchronized boolean isFailed() {
70 public synchronized boolean isRollingback() {
71 return state
== State
.ROLLINGBACK
;
75 * Called by the ProcedureExecutor to mark rollback execution
77 protected synchronized boolean setRollback() {
78 if (running
== 0 && state
== State
.FAILED
) {
79 state
= State
.ROLLINGBACK
;
86 * Called by the ProcedureExecutor to mark rollback execution
88 protected synchronized void unsetRollback() {
89 assert state
== State
.ROLLINGBACK
;
93 protected synchronized long[] getSubprocedureIds() {
94 if (subprocs
== null) return null;
96 final long[] subIds
= new long[subprocs
.size()];
97 for (Procedure proc
: subprocs
) {
98 subIds
[index
++] = proc
.getProcId();
103 protected synchronized List
<Procedure
> getSubproceduresStack() {
107 protected synchronized RemoteProcedureException
getException() {
108 if (subprocStack
!= null) {
109 for (Procedure proc
: subprocStack
) {
110 if (proc
.hasException()) {
111 return proc
.getException();
119 * Called by the ProcedureExecutor to mark the procedure step as running.
121 protected synchronized boolean acquire(final Procedure proc
) {
122 if (state
!= State
.RUNNING
) return false;
129 * Called by the ProcedureExecutor to mark the procedure step as finished.
131 protected synchronized void release(final Procedure proc
) {
135 protected synchronized void abort() {
136 if (state
== State
.RUNNING
) {
137 state
= State
.FAILED
;
142 * Called by the ProcedureExecutor after the procedure step is completed,
143 * to add the step to the rollback list (or procedure stack)
145 protected synchronized void addRollbackStep(final Procedure proc
) {
146 if (proc
.isFailed()) {
147 state
= State
.FAILED
;
149 if (subprocStack
== null) {
150 subprocStack
= new ArrayList
<>();
152 proc
.addStackIndex(subprocStack
.size());
153 subprocStack
.add(proc
);
156 protected synchronized void addSubProcedure(final Procedure proc
) {
157 if (!proc
.hasParent()) return;
158 if (subprocs
== null) {
159 subprocs
= new HashSet
<>();
165 * Called on store load by the ProcedureExecutor to load part of the stack.
167 * Each procedure has its own stack-positions. Which means we have to write
168 * to the store only the Procedure we executed, and nothing else.
169 * on load we recreate the full stack by aggregating each procedure stack-positions.
171 protected synchronized void loadStack(final Procedure proc
) {
172 addSubProcedure(proc
);
173 int[] stackIndexes
= proc
.getStackIndexes();
174 if (stackIndexes
!= null) {
175 if (subprocStack
== null) {
176 subprocStack
= new ArrayList
<>();
178 int diff
= (1 + stackIndexes
[stackIndexes
.length
- 1]) - subprocStack
.size();
180 subprocStack
.ensureCapacity(1 + stackIndexes
[stackIndexes
.length
- 1]);
181 while (diff
-- > 0) subprocStack
.add(null);
183 for (int i
= 0; i
< stackIndexes
.length
; ++i
) {
184 subprocStack
.set(stackIndexes
[i
], proc
);
187 if (proc
.getState() == ProcedureState
.ROLLEDBACK
) {
188 state
= State
.ROLLINGBACK
;
189 } else if (proc
.isFailed()) {
190 state
= State
.FAILED
;
195 * Called on store load by the ProcedureExecutor to validate the procedure stack.
197 protected synchronized boolean isValid() {
198 if (subprocStack
!= null) {
199 for (Procedure proc
: subprocStack
) {