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.coord;
016    
017    import java.sql.Timestamp;
018    import java.util.Date;
019    
020    import org.apache.oozie.CoordinatorActionBean;
021    import org.apache.oozie.ErrorCode;
022    import org.apache.oozie.WorkflowJobBean;
023    import org.apache.oozie.XException;
024    import org.apache.oozie.service.JPAService;
025    import org.apache.oozie.service.Services;
026    import org.apache.oozie.util.InstrumentUtils;
027    import org.apache.oozie.util.LogUtils;
028    import org.apache.oozie.util.ParamChecker;
029    import org.apache.oozie.util.db.SLADbOperations;
030    import org.apache.oozie.client.CoordinatorAction;
031    import org.apache.oozie.client.WorkflowJob;
032    import org.apache.oozie.client.SLAEvent.SlaAppType;
033    import org.apache.oozie.client.SLAEvent.Status;
034    import org.apache.oozie.command.CommandException;
035    import org.apache.oozie.command.PreconditionException;
036    import org.apache.oozie.executor.jpa.CoordActionGetJPAExecutor;
037    import org.apache.oozie.executor.jpa.WorkflowJobGetJPAExecutor;
038    
039    /**
040     * The command checks workflow status for coordinator action.
041     */
042    public class CoordActionCheckXCommand extends CoordinatorXCommand<Void> {
043        private String actionId;
044        private int actionCheckDelay;
045        private CoordinatorActionBean coordAction = null;
046        private JPAService jpaService = null;
047    
048        public CoordActionCheckXCommand(String actionId, int actionCheckDelay) {
049            super("coord_action_check", "coord_action_check", 0);
050            this.actionId = ParamChecker.notEmpty(actionId, "actionId");
051            this.actionCheckDelay = actionCheckDelay;
052        }
053    
054        /* (non-Javadoc)
055         * @see org.apache.oozie.command.XCommand#execute()
056         */
057        @Override
058        protected Void execute() throws CommandException {
059            try {
060                InstrumentUtils.incrJobCounter(getName(), 1, getInstrumentation());
061                WorkflowJobBean wf = jpaService.execute(new WorkflowJobGetJPAExecutor(coordAction.getExternalId()));
062    
063                Status slaStatus = null;
064    
065                if (wf.getStatus() == WorkflowJob.Status.SUCCEEDED) {
066                    coordAction.setStatus(CoordinatorAction.Status.SUCCEEDED);
067                    slaStatus = Status.SUCCEEDED;
068                }
069                else {
070                    if (wf.getStatus() == WorkflowJob.Status.FAILED) {
071                        coordAction.setStatus(CoordinatorAction.Status.FAILED);
072                        slaStatus = Status.FAILED;
073                    }
074                    else {
075                        if (wf.getStatus() == WorkflowJob.Status.KILLED) {
076                            coordAction.setStatus(CoordinatorAction.Status.KILLED);
077                            slaStatus = Status.KILLED;
078                        }
079                        else {
080                            LOG.warn("Unexpected workflow " + wf.getId() + " STATUS " + wf.getStatus());
081                            coordAction.setLastModifiedTime(new Date());
082                            jpaService.execute(new org.apache.oozie.executor.jpa.CoordActionUpdateJPAExecutor(coordAction));
083                            return null;
084                        }
085                    }
086                }
087    
088                LOG.debug("Updating Coordintaor actionId :" + coordAction.getId() + "status to ="
089                                + coordAction.getStatus());
090                coordAction.setLastModifiedTime(new Date());
091                jpaService.execute(new org.apache.oozie.executor.jpa.CoordActionUpdateJPAExecutor(coordAction));
092    
093                if (slaStatus != null) {
094                    SLADbOperations.writeStausEvent(coordAction.getSlaXml(), coordAction.getId(), slaStatus,
095                            SlaAppType.COORDINATOR_ACTION, LOG);
096                }
097            }
098            catch (XException ex) {
099                LOG.warn("CoordActionCheckCommand Failed ", ex);
100                throw new CommandException(ex);
101            }
102            return null;
103        }
104    
105        /* (non-Javadoc)
106         * @see org.apache.oozie.command.XCommand#getEntityKey()
107         */
108        @Override
109        protected String getEntityKey() {
110            return actionId;
111        }
112    
113        /* (non-Javadoc)
114         * @see org.apache.oozie.command.XCommand#isLockRequired()
115         */
116        @Override
117        protected boolean isLockRequired() {
118            return true;
119        }
120    
121        /* (non-Javadoc)
122         * @see org.apache.oozie.command.XCommand#loadState()
123         */
124        @Override
125        protected void loadState() throws CommandException {
126            try {
127                jpaService = Services.get().get(JPAService.class);
128    
129                if (jpaService != null) {
130                    coordAction = jpaService.execute(new CoordActionGetJPAExecutor(actionId));
131                    LogUtils.setLogInfo(coordAction, logInfo);
132                }
133                else {
134                    throw new CommandException(ErrorCode.E0610);
135                }
136            }
137            catch (XException ex) {
138                throw new CommandException(ex);
139            }
140        }
141    
142        /* (non-Javadoc)
143         * @see org.apache.oozie.command.XCommand#verifyPrecondition()
144         */
145        @Override
146        protected void verifyPrecondition() throws CommandException, PreconditionException {
147            // if the action has been updated, quit this command
148            Timestamp actionCheckTs = new Timestamp(System.currentTimeMillis() - actionCheckDelay * 1000);
149            Timestamp cactionLmt = coordAction.getLastModifiedTimestamp();
150            if (cactionLmt.after(actionCheckTs)) {
151                throw new PreconditionException(ErrorCode.E1100, "The coord action :" + actionId
152                        + " has been udated. Ignore CoordActionCheckCommand!");
153            }
154            if (coordAction.getStatus().equals(CoordinatorAction.Status.SUCCEEDED)
155                    || coordAction.getStatus().equals(CoordinatorAction.Status.FAILED)
156                    || coordAction.getStatus().equals(CoordinatorAction.Status.KILLED)) {
157                throw new PreconditionException(ErrorCode.E1100);
158            }
159        }
160    }