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