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.Job;
025    import org.apache.oozie.command.CommandException;
026    import org.apache.oozie.command.PreconditionException;
027    import org.apache.oozie.command.ResumeTransitionXCommand;
028    import org.apache.oozie.command.coord.CoordResumeXCommand;
029    import org.apache.oozie.executor.jpa.BundleActionUpdateJPAExecutor;
030    import org.apache.oozie.executor.jpa.BundleActionsGetJPAExecutor;
031    import org.apache.oozie.executor.jpa.BundleJobGetJPAExecutor;
032    import org.apache.oozie.executor.jpa.BundleJobUpdateJPAExecutor;
033    import org.apache.oozie.executor.jpa.JPAExecutorException;
034    import org.apache.oozie.service.JPAService;
035    import org.apache.oozie.service.Services;
036    import org.apache.oozie.util.InstrumentUtils;
037    import org.apache.oozie.util.LogUtils;
038    import org.apache.oozie.util.ParamChecker;
039    
040    public class BundleJobResumeXCommand extends ResumeTransitionXCommand {
041    
042        private final String bundleId;
043        private JPAService jpaService = null;
044        private BundleJobBean bundleJob;
045        private List<BundleActionBean> bundleActions;
046    
047        /**
048         * Constructor to create the Bundle Resume Command.
049         *
050         * @param jobId : Bundle Id
051         */
052        public BundleJobResumeXCommand(String jobId) {
053            super("bundle_resume", "bundle_resume", 1);
054            this.bundleId = ParamChecker.notNull(jobId, "BundleId");
055        }
056    
057        /* (non-Javadoc)
058         * @see org.apache.oozie.command.ResumeTransitionXCommand#resumeChildren()
059         */
060        @Override
061        public void resumeChildren() throws CommandException {
062            try {
063                for (BundleActionBean action : bundleActions) {
064                    if (action.getStatus() == Job.Status.SUSPENDED || action.getStatus() == Job.Status.PREPSUSPENDED) {
065                        // queue a CoordResumeXCommand
066                        if (action.getCoordId() != null) {
067                            queue(new CoordResumeXCommand(action.getCoordId()));
068                            updateBundleAction(action);
069                            LOG.debug("Resume bundle action = [{0}], new status = [{1}], pending = [{2}] and queue CoordResumeXCommand for [{3}]",
070                                            action.getBundleActionId(), action.getStatus(), action.getPending(), action
071                                                    .getCoordId());
072                        }
073                        else {
074                            updateBundleAction(action);
075                            LOG.debug("Resume bundle action = [{0}], new status = [{1}], pending = [{2}] and coord id is null",
076                                            action.getBundleActionId(), action.getStatus(), action.getPending());
077                        }
078                    }
079                }
080                LOG.debug("Resume bundle actions for the bundle=[{0}]", bundleId);
081            }
082            catch (XException ex) {
083                throw new CommandException(ex);
084            }
085        }
086    
087        private void updateBundleAction(BundleActionBean action) throws CommandException {
088            if (action.getStatus() == Job.Status.PREPSUSPENDED) {
089                action.setStatus(Job.Status.PREP);
090            }
091            else if (action.getStatus() == Job.Status.SUSPENDED) {
092                action.setStatus(Job.Status.RUNNING);
093            }
094            action.incrementAndGetPending();
095            action.setLastModifiedTime(new Date());
096            try {
097                jpaService.execute(new BundleActionUpdateJPAExecutor(action));
098            }
099            catch (JPAExecutorException e) {
100                throw new CommandException(e);
101            }
102        }
103    
104        /* (non-Javadoc)
105         * @see org.apache.oozie.command.TransitionXCommand#notifyParent()
106         */
107        @Override
108        public void notifyParent() throws CommandException {
109    
110        }
111    
112        /* (non-Javadoc)
113         * @see org.apache.oozie.command.TransitionXCommand#updateJob()
114         */
115        @Override
116        public void updateJob() throws CommandException {
117            InstrumentUtils.incrJobCounter("bundle_resume", 1, null);
118            bundleJob.setSuspendedTime(null);
119            bundleJob.setLastModifiedTime(new Date());
120            LOG.debug("Resume bundle job id = " + bundleId + ", status = " + bundleJob.getStatus() + ", pending = " + bundleJob.isPending());
121            try {
122                jpaService.execute(new BundleJobUpdateJPAExecutor(bundleJob));
123            }
124            catch (JPAExecutorException e) {
125                throw new CommandException(e);
126            }
127        }
128    
129        /* (non-Javadoc)
130         * @see org.apache.oozie.command.XCommand#getEntityKey()
131         */
132        @Override
133        protected String getEntityKey() {
134            return bundleId;
135        }
136    
137        /* (non-Javadoc)
138         * @see org.apache.oozie.command.XCommand#isLockRequired()
139         */
140        @Override
141        protected boolean isLockRequired() {
142            return true;
143        }
144    
145        /* (non-Javadoc)
146         * @see org.apache.oozie.command.XCommand#loadState()
147         */
148        @Override
149        protected void loadState() throws CommandException {
150            jpaService = Services.get().get(JPAService.class);
151            if (jpaService == null) {
152                throw new CommandException(ErrorCode.E0610);
153            }
154    
155            try {
156                bundleJob = jpaService.execute(new BundleJobGetJPAExecutor(bundleId));
157                bundleActions = jpaService.execute(new BundleActionsGetJPAExecutor(bundleId));
158            }
159            catch (Exception Ex) {
160                throw new CommandException(ErrorCode.E0604, bundleId);
161            }
162    
163            LogUtils.setLogInfo(bundleJob, logInfo);
164        }
165    
166        /* (non-Javadoc)
167         * @see org.apache.oozie.command.XCommand#verifyPrecondition()
168         */
169        @Override
170        protected void verifyPrecondition() throws CommandException, PreconditionException {
171            if (bundleJob.getStatus() != Job.Status.SUSPENDED && bundleJob.getStatus() != Job.Status.PREPSUSPENDED) {
172                throw new PreconditionException(ErrorCode.E1100, "BundleResumeCommand not Resumed - "
173                        + "job not in SUSPENDED/PREPSUSPENDED state " + bundleId);
174            }
175        }
176    
177        /* (non-Javadoc)
178         * @see org.apache.oozie.command.TransitionXCommand#getJob()
179         */
180        @Override
181        public Job getJob() {
182            return bundleJob;
183        }
184    }