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    }