001 /**
002 * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
003 * Licensed under the Apache License, Version 2.0 (the "License");
004 * you may not use this file except in compliance with the License.
005 * You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software
010 * distributed under the License is distributed on an "AS IS" BASIS,
011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 * See the License for the specific language governing permissions and
013 * limitations under the License. See accompanying LICENSE file.
014 */
015 package org.apache.oozie.command.wf;
016
017 import java.util.List;
018
019 import org.apache.oozie.WorkflowActionBean;
020 import org.apache.oozie.WorkflowJobBean;
021 import org.apache.oozie.client.WorkflowJob;
022 import org.apache.oozie.command.CommandException;
023 import org.apache.oozie.store.StoreException;
024 import org.apache.oozie.store.WorkflowStore;
025 import org.apache.oozie.util.ParamChecker;
026 import org.apache.oozie.util.XLog;
027 import org.apache.oozie.workflow.WorkflowException;
028 import org.apache.oozie.workflow.WorkflowInstance;
029 import org.apache.oozie.workflow.lite.LiteWorkflowInstance;
030
031 public class SuspendCommand extends WorkflowCommand<Void> {
032
033 private String id;
034
035 public SuspendCommand(String id) {
036 super("suspend", "suspend", 1, XLog.STD);
037 this.id = ParamChecker.notEmpty(id, "id");
038 }
039
040 @Override
041 protected Void call(WorkflowStore store) throws StoreException, CommandException {
042 try {
043 WorkflowJobBean workflow = store.getWorkflow(id, false);
044 setLogInfo(workflow);
045 if (workflow.getStatus() == WorkflowJob.Status.RUNNING) {
046 incrJobCounter(1);
047 suspendJob(store, workflow, id, null);
048 store.updateWorkflow(workflow);
049 queueCallable(new NotificationCommand(workflow));
050 }
051 return null;
052 }
053 catch (WorkflowException ex) {
054 throw new CommandException(ex);
055 }
056 }
057
058 /**
059 * Suspend the workflow job and pending flag to false for the actions that
060 * are START_RETRY or START_MANUAL or END_RETRY or END_MANUAL
061 *
062 * @param store WorkflowStore
063 * @param workflow WorkflowJobBean
064 * @param id String
065 * @param actionId String
066 * @throws WorkflowException
067 * @throws StoreException
068 */
069 public static void suspendJob(WorkflowStore store, WorkflowJobBean workflow, String id, String actionId)
070 throws WorkflowException, StoreException {
071 if (workflow.getStatus() == WorkflowJob.Status.RUNNING) {
072 workflow.getWorkflowInstance().suspend();
073 WorkflowInstance wfInstance = workflow.getWorkflowInstance();
074 ((LiteWorkflowInstance) wfInstance).setStatus(WorkflowInstance.Status.SUSPENDED);
075 workflow.setStatus(WorkflowJob.Status.SUSPENDED);
076 workflow.setWorkflowInstance(wfInstance);
077
078 setPendingFalseForActions(store, id, actionId);
079 }
080 }
081
082 /**
083 * Set pending flag to false for the actions that are START_RETRY or
084 * START_MANUAL or END_RETRY or END_MANUAL
085 * <p/>
086 *
087 * @param store WorkflowStore
088 * @param id workflow id
089 * @param actionId workflow action id
090 * @throws StoreException
091 */
092 public static void setPendingFalseForActions(WorkflowStore store, String id, String actionId) throws StoreException {
093 List<WorkflowActionBean> actions = store.getRetryAndManualActions(id);
094 for (WorkflowActionBean action : actions) {
095 if (actionId != null && actionId.equals(action.getId())) {
096 // this action has been changed in handleNonTransient()
097 continue;
098 }
099 else {
100 action.resetPendingOnly();
101 }
102 store.updateAction(action);
103 }
104 }
105
106 @Override
107 protected Void execute(WorkflowStore store) throws CommandException, StoreException {
108 XLog.getLog(getClass()).debug("STARTED SuspendCommand for wf id=" + id);
109 try {
110 if (lock(id)) {
111 call(store);
112 }
113 else {
114 queueCallable(new SuspendCommand(id), LOCK_FAILURE_REQUEUE_INTERVAL);
115 XLog.getLog(getClass()).warn("Suspend lock was not acquired - failed {0}", id);
116 }
117 }
118 catch (InterruptedException e) {
119 queueCallable(new SuspendCommand(id), LOCK_FAILURE_REQUEUE_INTERVAL);
120 XLog.getLog(getClass()).warn("SuspendCommand lock was not acquired - interrupted exception failed {0}", id);
121 }
122 finally {
123 XLog.getLog(getClass()).debug("ENDED SuspendCommand for wf id=" + id);
124 }
125 return null;
126 }
127 }