001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *      http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.oozie.command;
019    
020    import org.apache.oozie.ErrorCode;
021    import org.apache.oozie.client.Job;
022    import org.apache.oozie.util.StatusUtils;
023    
024    /**
025     * Transition command for rerun the job. The derived class has to override these following functions:
026     * <p/>
027     * updateJob() : update job status and attributes
028     * rerunChildren() : submit or queue commands to rerun children
029     * notifyParent() : update the status to upstream if any
030     *
031     * @param <T>
032     */
033    public abstract class RerunTransitionXCommand<T> extends TransitionXCommand<T> {
034        protected String jobId;
035        protected T ret;
036        protected Job.Status prevStatus;
037    
038        /**
039         * The constructor for abstract class {@link RerunTransitionXCommand}
040         *
041         * @param name the command name
042         * @param type the command type
043         * @param priority the command priority
044         */
045        public RerunTransitionXCommand(String name, String type, int priority) {
046            super(name, type, priority);
047        }
048    
049        /**
050         * The constructor for abstract class {@link RerunTransitionXCommand}
051         *
052         * @param name the command name
053         * @param type the command type
054         * @param priority the command priority
055         * @param dryrun true if dryrun is enable
056         */
057        public RerunTransitionXCommand(String name, String type, int priority, boolean dryrun) {
058            super(name, type, priority, dryrun);
059        }
060    
061        /* (non-Javadoc)
062         * @see org.apache.oozie.command.TransitionXCommand#transitToNext()
063         */
064        @Override
065        public void transitToNext() {
066            if (job == null) {
067                job = this.getJob();
068            }
069            prevStatus = job.getStatus();
070            if (prevStatus == Job.Status.SUCCEEDED || prevStatus == Job.Status.PAUSED
071                    || prevStatus == Job.Status.SUSPENDED || prevStatus == Job.Status.RUNNING) {
072                job.setStatus(Job.Status.RUNNING);
073            }
074            else {
075                // Check for backward compatibility
076                job.setStatus(StatusUtils.getStatusIfBackwardSupportTrue(Job.Status.RUNNINGWITHERROR));
077            }
078            job.setPending();
079        }
080    
081        /**
082         * Rerun actions associated with the job
083         *
084         * @throws CommandException thrown if failed to rerun actions
085         */
086        public abstract void rerunChildren() throws CommandException;
087    
088        /* (non-Javadoc)
089         * @see org.apache.oozie.command.TransitionXCommand#execute()
090         */
091        @Override
092        protected T execute() throws CommandException {
093            getLog().info("STARTED " + getClass().getSimpleName() + " for jobId=" + jobId);
094            try {
095                transitToNext();
096                rerunChildren();
097                updateJob();
098                performWrites();
099            }
100            finally {
101                notifyParent();
102            }
103            getLog().info("ENDED " + getClass().getSimpleName() + " for jobId=" + jobId);
104            return ret;
105        }
106    
107        /* (non-Javadoc)
108         * @see org.apache.oozie.command.XCommand#verifyPrecondition()
109         */
110        @Override
111        protected void verifyPrecondition() throws CommandException, PreconditionException {
112            eagerVerifyPrecondition();
113        }
114    
115        /* (non-Javadoc)
116         * @see org.apache.oozie.command.XCommand#eagerLoadState()
117         */
118        @Override
119        protected void eagerLoadState() throws CommandException {
120            loadState();
121        }
122    
123        /* (non-Javadoc)
124         * @see org.apache.oozie.command.XCommand#eagerVerifyPrecondition()
125         */
126        @Override
127        protected void eagerVerifyPrecondition() throws CommandException, PreconditionException {
128            if (getJob().getStatus() == Job.Status.KILLED || getJob().getStatus() == Job.Status.FAILED
129                    || getJob().getStatus() == Job.Status.PREP || getJob().getStatus() == Job.Status.PREPPAUSED
130                    || getJob().getStatus() == Job.Status.PREPSUSPENDED) {
131                getLog().warn(
132                        "RerunCommand is not able to run because job status=" + getJob().getStatus() + ", jobid="
133                                + getJob().getId());
134                throw new PreconditionException(ErrorCode.E1100, "Not able to rerun the job Id= " + getJob().getId()
135                        + ". job is in wrong state= " + getJob().getStatus());
136            }
137        }
138    
139        /**
140         * This method will return the previous status.
141         *
142         * @return JOB Status
143         */
144        public Job.Status getPrevStatus() {
145            if (prevStatus != null) {
146                return prevStatus;
147            }
148            else {
149                return job.getStatus();
150            }
151        }
152    }