| /** |
| * 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.ambari.server.state.action; |
| |
| import java.util.concurrent.locks.Lock; |
| import java.util.concurrent.locks.ReadWriteLock; |
| import java.util.concurrent.locks.ReentrantReadWriteLock; |
| |
| import org.apache.ambari.server.state.fsm.InvalidStateTransitionException; |
| import org.apache.ambari.server.state.fsm.SingleArcTransition; |
| import org.apache.ambari.server.state.fsm.StateMachine; |
| import org.apache.ambari.server.state.fsm.StateMachineFactory; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| public class ActionImpl implements Action { |
| |
| private static final Log LOG = LogFactory.getLog(ActionImpl.class); |
| |
| private final Lock readLock; |
| private final Lock writeLock; |
| |
| private ActionId id; |
| |
| private long startTime; |
| private long lastUpdateTime; |
| private long completionTime; |
| |
| // TODO |
| // need to add action report |
| |
| private static final StateMachineFactory |
| <ActionImpl, ActionState, ActionEventType, ActionEvent> |
| stateMachineFactory |
| = new StateMachineFactory<ActionImpl, ActionState, |
| ActionEventType, ActionEvent> |
| (ActionState.INIT) |
| |
| // define the state machine of a Action |
| |
| .addTransition(ActionState.INIT, ActionState.IN_PROGRESS, |
| ActionEventType.ACTION_IN_PROGRESS, new ActionProgressUpdateTransition()) |
| .addTransition(ActionState.INIT, ActionState.COMPLETED, |
| ActionEventType.ACTION_COMPLETED, new ActionCompletedTransition()) |
| .addTransition(ActionState.INIT, ActionState.FAILED, |
| ActionEventType.ACTION_FAILED, new ActionFailedTransition()) |
| .addTransition(ActionState.INIT, ActionState.IN_PROGRESS, |
| ActionEventType.ACTION_IN_PROGRESS, new ActionProgressUpdateTransition()) |
| .addTransition(ActionState.IN_PROGRESS, ActionState.IN_PROGRESS, |
| ActionEventType.ACTION_IN_PROGRESS, new ActionProgressUpdateTransition()) |
| .addTransition(ActionState.IN_PROGRESS, ActionState.COMPLETED, |
| ActionEventType.ACTION_COMPLETED, new ActionCompletedTransition()) |
| .addTransition(ActionState.IN_PROGRESS, ActionState.FAILED, |
| ActionEventType.ACTION_FAILED, new ActionFailedTransition()) |
| .addTransition(ActionState.COMPLETED, ActionState.INIT, |
| ActionEventType.ACTION_INIT, new NewActionTransition()) |
| .addTransition(ActionState.FAILED, ActionState.INIT, |
| ActionEventType.ACTION_INIT, new NewActionTransition()) |
| .installTopology(); |
| |
| private final StateMachine<ActionState, ActionEventType, ActionEvent> |
| stateMachine; |
| |
| public ActionImpl(ActionId id, long startTime) { |
| super(); |
| this.id = id; |
| this.stateMachine = stateMachineFactory.make(this); |
| ReadWriteLock rwLock = new ReentrantReadWriteLock(); |
| this.readLock = rwLock.readLock(); |
| this.writeLock = rwLock.writeLock(); |
| this.startTime = startTime; |
| this.lastUpdateTime = -1; |
| this.completionTime = -1; |
| } |
| |
| private void reset() { |
| try { |
| writeLock.lock(); |
| this.startTime = -1; |
| this.lastUpdateTime = -1; |
| this.completionTime = -1; |
| } |
| finally { |
| writeLock.unlock(); |
| } |
| } |
| |
| static class NewActionTransition |
| implements SingleArcTransition<ActionImpl, ActionEvent> { |
| |
| @Override |
| public void transition(ActionImpl action, ActionEvent event) { |
| ActionInitEvent e = (ActionInitEvent) event; |
| // TODO audit logs |
| action.reset(); |
| action.setId(e.getActionId()); |
| action.setStartTime(e.getStartTime()); |
| LOG.info("Launching a new Action" |
| + ", actionId=" + action.getId() |
| + ", startTime=" + action.getStartTime()); |
| } |
| } |
| |
| static class ActionProgressUpdateTransition |
| implements SingleArcTransition<ActionImpl, ActionEvent> { |
| |
| @Override |
| public void transition(ActionImpl action, ActionEvent event) { |
| ActionProgressUpdateEvent e = (ActionProgressUpdateEvent) event; |
| action.setLastUpdateTime(e.getProgressUpdateTime()); |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("Progress update for Action" |
| + ", actionId=" + action.getId() |
| + ", startTime=" + action.getStartTime() |
| + ", lastUpdateTime=" + action.getLastUpdateTime()); |
| } |
| } |
| } |
| |
| static class ActionCompletedTransition |
| implements SingleArcTransition<ActionImpl, ActionEvent> { |
| |
| @Override |
| public void transition(ActionImpl action, ActionEvent event) { |
| // TODO audit logs |
| ActionCompletedEvent e = (ActionCompletedEvent) event; |
| action.setCompletionTime(e.getCompletionTime()); |
| action.setLastUpdateTime(e.getCompletionTime()); |
| |
| LOG.info("Action completed successfully" |
| + ", actionId=" + action.getId() |
| + ", startTime=" + action.getStartTime() |
| + ", completionTime=" + action.getCompletionTime()); |
| } |
| } |
| |
| static class ActionFailedTransition |
| implements SingleArcTransition<ActionImpl, ActionEvent> { |
| |
| @Override |
| public void transition(ActionImpl action, ActionEvent event) { |
| // TODO audit logs |
| ActionFailedEvent e = (ActionFailedEvent) event; |
| action.setCompletionTime(e.getCompletionTime()); |
| action.setLastUpdateTime(e.getCompletionTime()); |
| LOG.info("Action failed to complete" |
| + ", actionId=" + action.getId() |
| + ", startTime=" + action.getStartTime() |
| + ", completionTime=" + action.getCompletionTime()); |
| } |
| } |
| |
| |
| @Override |
| public ActionState getState() { |
| try { |
| readLock.lock(); |
| return stateMachine.getCurrentState(); |
| } |
| finally { |
| readLock.unlock(); |
| } |
| } |
| |
| @Override |
| public void setState(ActionState state) { |
| try { |
| writeLock.lock(); |
| stateMachine.setCurrentState(state); |
| } |
| finally { |
| writeLock.unlock(); |
| } |
| } |
| |
| @Override |
| public void handleEvent(ActionEvent event) |
| throws InvalidStateTransitionException { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("Handling Action event, eventType=" + event.getType().name() |
| + ", event=" + event.toString()); |
| } |
| ActionState oldState = getState(); |
| try { |
| writeLock.lock(); |
| try { |
| stateMachine.doTransition(event.getType(), event); |
| } catch (InvalidStateTransitionException e) { |
| LOG.error("Can't handle Action event at current state" |
| + ", actionId=" + this.getId() |
| + ", currentState=" + oldState |
| + ", eventType=" + event.getType() |
| + ", event=" + event); |
| throw e; |
| } |
| } |
| finally { |
| writeLock.unlock(); |
| } |
| if (oldState != getState()) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("Action transitioned to a new state" |
| + ", actionId=" + this.getId() |
| + ", oldState=" + oldState |
| + ", currentState=" + getState() |
| + ", eventType=" + event.getType().name() |
| + ", event=" + event); |
| } |
| } |
| } |
| |
| @Override |
| public ActionId getId() { |
| try { |
| readLock.lock(); |
| return id; |
| } |
| finally { |
| readLock.unlock(); |
| } |
| } |
| |
| private void setId(ActionId id) { |
| try { |
| writeLock.lock(); |
| this.id = id; |
| } |
| finally { |
| writeLock.unlock(); |
| } |
| } |
| |
| @Override |
| public long getStartTime() { |
| try { |
| readLock.lock(); |
| return startTime; |
| } |
| finally { |
| readLock.unlock(); |
| } |
| } |
| |
| public void setStartTime(long startTime) { |
| try { |
| writeLock.lock(); |
| this.startTime = startTime; |
| } |
| finally { |
| writeLock.unlock(); |
| } |
| } |
| |
| @Override |
| public long getLastUpdateTime() { |
| try { |
| readLock.lock(); |
| return lastUpdateTime; |
| } |
| finally { |
| readLock.unlock(); |
| } |
| } |
| |
| public void setLastUpdateTime(long lastUpdateTime) { |
| try { |
| writeLock.lock(); |
| this.lastUpdateTime = lastUpdateTime; |
| } |
| finally { |
| writeLock.unlock(); |
| } |
| |
| } |
| |
| @Override |
| public long getCompletionTime() { |
| try { |
| readLock.lock(); |
| return completionTime; |
| } |
| finally { |
| readLock.unlock(); |
| } |
| } |
| |
| public void setCompletionTime(long completionTime) { |
| try { |
| writeLock.lock(); |
| this.completionTime = completionTime; |
| } |
| finally { |
| writeLock.unlock(); |
| } |
| } |
| |
| |
| } |