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 org.apache.oozie.WorkflowActionBean;
018 import org.apache.oozie.WorkflowJobBean;
019 import org.apache.oozie.client.SLAEvent.SlaAppType;
020 import org.apache.oozie.client.SLAEvent.Status;
021 import org.apache.oozie.command.CommandException;
022 import org.apache.oozie.action.ActionExecutor;
023 import org.apache.oozie.action.ActionExecutorException;
024 import org.apache.oozie.service.ActionService;
025 import org.apache.oozie.service.UUIDService;
026 import org.apache.oozie.store.StoreException;
027 import org.apache.oozie.store.WorkflowStore;
028 import org.apache.oozie.service.Services;
029 import org.apache.oozie.util.XLog;
030 import org.apache.oozie.util.Instrumentation;
031 import org.apache.oozie.util.db.SLADbOperations;
032
033 public class ActionKillCommand extends ActionCommand<Void> {
034 private String id;
035 private String jobId;
036
037 public ActionKillCommand(String id, String type) {
038 super("action.kill", type, 0);
039 this.id = id;
040 }
041
042 protected Void call(WorkflowStore store) throws StoreException, CommandException {
043 // String jobId = Services.get().get(UUIDService.class).getId(id);
044 WorkflowJobBean workflow = store.getWorkflow(jobId, false);
045 setLogInfo(workflow);
046 WorkflowActionBean action = store.getAction(id, false);
047 setLogInfo(action);
048 if (action.isPending() && (action.getStatus() == WorkflowActionBean.Status.KILLED)) {
049 ActionExecutor executor = Services.get().get(ActionService.class).getExecutor(action.getType());
050 if (executor != null) {
051 try {
052 boolean isRetry = false;
053 ActionExecutorContext context = new ActionCommand.ActionExecutorContext(workflow, action, isRetry);
054 incrActionCounter(action.getType(), 1);
055
056 Instrumentation.Cron cron = new Instrumentation.Cron();
057 cron.start();
058 executor.kill(context, action);
059 cron.stop();
060 addActionCron(action.getType(), cron);
061
062 action.resetPending();
063 action.setStatus(WorkflowActionBean.Status.KILLED);
064
065 store.updateAction(action);
066 store.updateWorkflow(workflow);
067 // Add SLA status event (KILLED) for WF_ACTION
068 SLADbOperations.writeStausEvent(action.getSlaXml(), action.getId(), store, Status.KILLED,
069 SlaAppType.WORKFLOW_ACTION);
070 queueCallable(new NotificationCommand(workflow, action));
071 }
072 catch (ActionExecutorException ex) {
073 action.resetPending();
074 action.setStatus(WorkflowActionBean.Status.FAILED);
075 action.setErrorInfo(ex.getErrorCode().toString(),
076 "KILL COMMAND FAILED - exception while executing job kill");
077 workflow.setStatus(WorkflowJobBean.Status.KILLED);
078 store.updateAction(action);
079 store.updateWorkflow(workflow);
080 // What will happen to WF and COORD_ACTION, NOTIFICATION?
081 SLADbOperations.writeStausEvent(action.getSlaXml(), action.getId(), store, Status.FAILED,
082 SlaAppType.WORKFLOW_ACTION);
083 XLog.getLog(getClass()).warn("Exception while executing kill(). Error Code [{0}], Message[{1}]",
084 ex.getErrorCode(), ex.getMessage(), ex);
085 }
086 }
087 }
088 return null;
089 }
090
091 @Override
092 protected Void execute(WorkflowStore store) throws CommandException, StoreException {
093 XLog.getLog(getClass()).debug("STARTED ActionKillCommand for action " + id);
094 try {
095 jobId = Services.get().get(UUIDService.class).getId(id);
096 if (lock(jobId)) {
097 call(store);
098 }
099 else {
100 queueCallable(new ActionKillCommand(id, type), LOCK_FAILURE_REQUEUE_INTERVAL);
101 XLog.getLog(getClass()).warn("ActionKill lock was not acquired - failed {0}", id);
102 }
103 }
104 catch (InterruptedException e) {
105 queueCallable(new ActionKillCommand(id, type), LOCK_FAILURE_REQUEUE_INTERVAL);
106 XLog.getLog(getClass()).warn("ActionKill lock was not acquired - interrupted exception failed {0}", id);
107 }
108 finally {
109 XLog.getLog(getClass()).debug("ENDED ActionKillCommand for action " + id);
110 }
111 return null;
112 }
113 }