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    
019    import org.apache.oozie.BundleActionBean;
020    import org.apache.oozie.CoordinatorJobBean;
021    import org.apache.oozie.ErrorCode;
022    import org.apache.oozie.XException;
023    import org.apache.oozie.client.CoordinatorJob;
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.StatusUpdateXCommand;
028    import org.apache.oozie.executor.jpa.BundleActionGetJPAExecutor;
029    import org.apache.oozie.executor.jpa.BundleActionUpdateJPAExecutor;
030    import org.apache.oozie.executor.jpa.JPAExecutorException;
031    import org.apache.oozie.service.JPAService;
032    import org.apache.oozie.service.Services;
033    
034    /**
035     * The command to update Bundle status
036     */
037    public class BundleStatusUpdateXCommand extends StatusUpdateXCommand {
038        private final CoordinatorJobBean coordjob;
039        private JPAService jpaService = null;
040        private BundleActionBean bundleaction;
041        private final Job.Status prevStatus;
042    
043        /**
044         * The constructor for class {@link BundleStatusUpdateXCommand}
045         *
046         * @param coordjob coordinator job bean
047         * @param prevStatus coordinator job old status
048         */
049        public BundleStatusUpdateXCommand(CoordinatorJobBean coordjob, CoordinatorJob.Status prevStatus) {
050            super("BundleStatusUpdate", "BundleStatusUpdate", 1);
051            this.coordjob = coordjob;
052            this.prevStatus = prevStatus;
053        }
054    
055        /* (non-Javadoc)
056         * @see org.apache.oozie.command.XCommand#execute()
057         */
058        @Override
059        protected Void execute() throws CommandException {
060            try {
061                LOG.debug("STARTED BundleStatusUpdateXCommand with bubdle id : " + coordjob.getBundleId()
062                        + " coord job ID: " + coordjob.getId() + " coord Status " + coordjob.getStatus());
063                Job.Status coordCurrentStatus = coordjob.getStatus();
064                Job.Status bundleActionStatus = bundleaction.getStatus();
065                bundleaction.setStatus(coordCurrentStatus);
066    
067                if (bundleaction.isPending()) {
068                    bundleaction.decrementAndGetPending();
069                }
070                bundleaction.setLastModifiedTime(new Date());
071                bundleaction.setCoordId(coordjob.getId());
072                jpaService.execute(new BundleActionUpdateJPAExecutor(bundleaction));
073                LOG.info("Updated bundle action [{0}] from prev status [{1}] to current coord status [{2}], and new bundle action pending [{3}]", bundleaction
074                        .getBundleActionId(), bundleActionStatus, coordCurrentStatus, bundleaction.getPending());
075    
076                LOG.debug("ENDED BundleStatusUpdateXCommand with bubdle id : " + coordjob.getBundleId() + " coord job ID: "
077                        + coordjob.getId() + " coord Status " + coordjob.getStatus());
078            }
079            catch (Exception ex) {
080                throw new CommandException(ErrorCode.E1309, bundleaction.getBundleId(), bundleaction.getCoordName());
081            }
082            return null;
083        }
084    
085        /* (non-Javadoc)
086         * @see org.apache.oozie.command.XCommand#getEntityKey()
087         */
088        @Override
089        protected String getEntityKey() {
090            return this.bundleaction.getBundleActionId();
091        }
092    
093        /* (non-Javadoc)
094         * @see org.apache.oozie.command.XCommand#isLockRequired()
095         */
096        @Override
097        protected boolean isLockRequired() {
098            return true;
099        }
100    
101        /* (non-Javadoc)
102         * @see org.apache.oozie.command.XCommand#eagerLoadState()
103         */
104        @Override
105        protected void eagerLoadState() throws CommandException{
106            loadState();
107        }
108    
109        /* (non-Javadoc)
110         * @see org.apache.oozie.command.XCommand#loadState()
111         */
112        @Override
113        protected void loadState() throws CommandException {
114            try {
115                if (jpaService == null) {
116                    jpaService = Services.get().get(JPAService.class);
117                }
118    
119                if (jpaService != null) {
120                    this.bundleaction = jpaService.execute(new BundleActionGetJPAExecutor(coordjob.getBundleId(), coordjob
121                            .getAppName()));
122                }
123                else {
124                    throw new CommandException(ErrorCode.E0610);
125                }
126            }
127            catch (XException ex) {
128                throw new CommandException(ex);
129            }
130        }
131    
132        /* (non-Javadoc)
133         * @see org.apache.oozie.command.XCommand#verifyPrecondition()
134         */
135        @Override
136        protected void verifyPrecondition() throws CommandException, PreconditionException {
137            if (bundleaction.getStatusStr().compareToIgnoreCase(prevStatus.toString()) != 0) {
138                // Previous status are not matched with bundle action status
139                // So that's the error and we should not be updating the Bundle Action status
140                // however we need to decrement the pending flag.
141                if (bundleaction.isPending()) {
142                    bundleaction.decrementAndGetPending();
143                }
144                bundleaction.setLastModifiedTime(new Date());
145                try {
146                    jpaService.execute(new BundleActionUpdateJPAExecutor(bundleaction));
147                }
148                catch (JPAExecutorException je) {
149                    throw new CommandException(je);
150                }
151                LOG.info("Bundle action [{0}] status [{1}] is different from prev coord status [{2}], decrement pending so new pending = [{3}]",
152                                bundleaction.getBundleActionId(), bundleaction.getStatusStr(), prevStatus.toString(),
153                                bundleaction.getPending());
154                throw new PreconditionException(ErrorCode.E1308, bundleaction.getStatusStr(), prevStatus.toString());
155            }
156        }
157    
158    }