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.bundle;
016    
017    import java.util.Date;
018    import java.util.List;
019    
020    import org.apache.oozie.BundleActionBean;
021    import org.apache.oozie.BundleJobBean;
022    import org.apache.oozie.ErrorCode;
023    import org.apache.oozie.XException;
024    import org.apache.oozie.client.CoordinatorJob;
025    import org.apache.oozie.client.Job;
026    import org.apache.oozie.command.CommandException;
027    import org.apache.oozie.command.KillTransitionXCommand;
028    import org.apache.oozie.command.PreconditionException;
029    import org.apache.oozie.command.coord.CoordKillXCommand;
030    import org.apache.oozie.executor.jpa.BundleActionUpdateJPAExecutor;
031    import org.apache.oozie.executor.jpa.BundleActionsGetJPAExecutor;
032    import org.apache.oozie.executor.jpa.BundleJobGetJPAExecutor;
033    import org.apache.oozie.executor.jpa.BundleJobUpdateJPAExecutor;
034    import org.apache.oozie.executor.jpa.JPAExecutorException;
035    import org.apache.oozie.service.JPAService;
036    import org.apache.oozie.service.Services;
037    import org.apache.oozie.util.LogUtils;
038    import org.apache.oozie.util.ParamChecker;
039    
040    public class BundleKillXCommand extends KillTransitionXCommand {
041        private final String jobId;
042        private BundleJobBean bundleJob;
043        private List<BundleActionBean> bundleActions;
044        private JPAService jpaService = null;
045    
046        public BundleKillXCommand(String jobId) {
047            super("bundle_kill", "bundle_kill", 1);
048            this.jobId = ParamChecker.notEmpty(jobId, "jobId");
049        }
050    
051        /* (non-Javadoc)
052         * @see org.apache.oozie.command.XCommand#getEntityKey()
053         */
054        @Override
055        protected String getEntityKey() {
056            return jobId;
057        }
058    
059        /* (non-Javadoc)
060         * @see org.apache.oozie.command.XCommand#isLockRequired()
061         */
062        @Override
063        protected boolean isLockRequired() {
064            return true;
065        }
066    
067        /* (non-Javadoc)
068         * @see org.apache.oozie.command.XCommand#loadState()
069         */
070        @Override
071        public void loadState() throws CommandException {
072            try {
073                jpaService = Services.get().get(JPAService.class);
074    
075                if (jpaService != null) {
076                    this.bundleJob = jpaService.execute(new BundleJobGetJPAExecutor(jobId));
077                    this.bundleActions = jpaService.execute(new BundleActionsGetJPAExecutor(jobId));
078                    LogUtils.setLogInfo(bundleJob, logInfo);
079                    super.setJob(bundleJob);
080    
081                }
082                else {
083                    throw new CommandException(ErrorCode.E0610);
084                }
085            }
086            catch (XException ex) {
087                throw new CommandException(ex);
088            }
089        }
090    
091        /* (non-Javadoc)
092         * @see org.apache.oozie.command.XCommand#verifyPrecondition()
093         */
094        @Override
095        protected void verifyPrecondition() throws CommandException, PreconditionException {
096            if (bundleJob.getStatus() == CoordinatorJob.Status.SUCCEEDED
097                    || bundleJob.getStatus() == CoordinatorJob.Status.FAILED
098                    || bundleJob.getStatus() == CoordinatorJob.Status.DONEWITHERROR) {
099                LOG.info("BundleKillXCommand not killed - job either finished SUCCEEDED, FAILED or DONEWITHERROR, job id = "
100                                + jobId + ", status = " + bundleJob.getStatus());
101                throw new PreconditionException(ErrorCode.E1020, jobId);
102            }
103        }
104    
105        /* (non-Javadoc)
106         * @see org.apache.oozie.command.KillTransitionXCommand#killChildren()
107         */
108        @Override
109        public void killChildren() throws CommandException {
110            if (bundleActions != null) {
111                for (BundleActionBean action : bundleActions) {
112                    if (action.getCoordId() != null) {
113                        queue(new CoordKillXCommand(action.getCoordId()));
114                        updateBundleAction(action);
115                        LOG.debug("Killed bundle action = [{0}], new status = [{1}], pending = [{2}] and queue CoordKillXCommand for [{3}]",
116                                action.getBundleActionId(), action.getStatus(), action.getPending(), action.getCoordId());
117                    } else {
118                        updateBundleAction(action);
119                        LOG.debug("Killed bundle action = [{0}], current status = [{1}], pending = [{2}]", action.getBundleActionId(), action
120                                .getStatus(), action.getPending());
121                    }
122    
123                }
124            }
125            LOG.debug("Killed coord jobs for the bundle=[{0}]", jobId);
126        }
127    
128        /**
129         * Update bundle action
130         *
131         * @param action
132         * @throws CommandException
133         */
134        private void updateBundleAction(BundleActionBean action) throws CommandException {
135            action.incrementAndGetPending();
136            action.setLastModifiedTime(new Date());
137            action.setStatus(Job.Status.KILLED);
138            try {
139                jpaService.execute(new BundleActionUpdateJPAExecutor(action));
140            }
141            catch (JPAExecutorException e) {
142                throw new CommandException(e);
143            }
144        }
145    
146        /* (non-Javadoc)
147         * @see org.apache.oozie.command.TransitionXCommand#notifyParent()
148         */
149        @Override
150        public void notifyParent() {
151        }
152    
153        /* (non-Javadoc)
154         * @see org.apache.oozie.command.TransitionXCommand#getJob()
155         */
156        @Override
157        public Job getJob() {
158            return bundleJob;
159        }
160    
161        /* (non-Javadoc)
162         * @see org.apache.oozie.command.TransitionXCommand#updateJob()
163         */
164        @Override
165        public void updateJob() throws CommandException {
166            try {
167                jpaService.execute(new BundleJobUpdateJPAExecutor(bundleJob));
168            }
169            catch (JPAExecutorException e) {
170                throw new CommandException(e);
171            }
172        }
173    
174    }