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    
019    import org.apache.oozie.CoordinatorActionBean;
020    import org.apache.oozie.WorkflowJobBean;
021    import org.apache.oozie.XException;
022    import org.apache.oozie.service.Services;
023    import org.apache.oozie.service.StoreService;
024    import org.apache.oozie.store.CoordinatorStore;
025    import org.apache.oozie.store.StoreException;
026    import org.apache.oozie.store.WorkflowStore;
027    import org.apache.oozie.util.XLog;
028    import org.apache.oozie.util.db.SLADbOperations;
029    import org.apache.oozie.client.CoordinatorAction;
030    import org.apache.oozie.client.WorkflowJob;
031    import org.apache.oozie.client.SLAEvent.SlaAppType;
032    import org.apache.oozie.client.SLAEvent.Status;
033    import org.apache.oozie.command.CommandException;
034    
035    public class CoordActionCheckCommand extends CoordinatorCommand<Void> {
036        private String actionId;
037        private int actionCheckDelay;
038        private final XLog log = XLog.getLog(getClass());
039        private CoordinatorActionBean coordAction = null;
040    
041        public CoordActionCheckCommand(String actionId, int actionCheckDelay) {
042            super("coord_action_check", "coord_action_check", 0, XLog.OPS);
043            this.actionId = actionId;
044            this.actionCheckDelay = actionCheckDelay;
045        }
046    
047        protected Void call(CoordinatorStore cstore) throws StoreException, CommandException {
048            try {
049                //if the action has been updated, quit this command
050                Timestamp actionCheckTs = new Timestamp(System.currentTimeMillis() - actionCheckDelay * 1000);
051                Timestamp cactionLmt = coordAction.getLastModifiedTimestamp();
052                if (cactionLmt.after(actionCheckTs)) {
053                    log.info("The coord action :" + actionId + " has been udated. Ignore CoordActionCheckCommand!");
054                    return null;
055                }
056                if (coordAction.getStatus().equals(CoordinatorAction.Status.SUCCEEDED)
057                        || coordAction.getStatus().equals(CoordinatorAction.Status.FAILED)
058                        || coordAction.getStatus().equals(CoordinatorAction.Status.KILLED)) {
059                    // do nothing
060                }
061                else {
062                    incrJobCounter(1);
063                    WorkflowStore wstore = Services.get().get(StoreService.class).getStore(WorkflowStore.class, cstore);
064                    WorkflowJobBean wf = wstore.getWorkflow(coordAction.getExternalId(), false);
065    
066                    Status slaStatus = null;
067    
068                    if (wf.getStatus() == WorkflowJob.Status.SUCCEEDED) {
069                        coordAction.setStatus(CoordinatorAction.Status.SUCCEEDED);
070                        slaStatus = Status.SUCCEEDED;
071                    }
072                    else {
073                        if (wf.getStatus() == WorkflowJob.Status.FAILED) {
074                            coordAction.setStatus(CoordinatorAction.Status.FAILED);
075                            slaStatus = Status.FAILED;
076                        }
077                        else {
078                            if (wf.getStatus() == WorkflowJob.Status.KILLED) {
079                                coordAction.setStatus(CoordinatorAction.Status.KILLED);
080                                slaStatus = Status.KILLED;
081                            }
082                            else {
083                                log.warn("Unexpected workflow " + wf.getId() + " STATUS " + wf.getStatus());
084                                cstore.updateCoordinatorAction(coordAction);
085                                return null;
086                            }
087                        }
088                    }
089    
090                    log.debug("Updating Coordintaor actionId :" + coordAction.getId() + "status to =" + coordAction.getStatus());
091                    cstore.updateCoordinatorAction(coordAction);
092                    if (slaStatus != null) {
093                        SLADbOperations.writeStausEvent(coordAction.getSlaXml(), coordAction.getId(), cstore, slaStatus,
094                                                        SlaAppType.COORDINATOR_ACTION);
095                    }
096                }
097    
098            }
099            catch (XException ex) {
100                log.warn("CoordActionCheckCommand Failed ", ex);
101                throw new CommandException(ex);
102            }
103            return null;
104        }
105    
106        @Override
107        protected Void execute(CoordinatorStore store) throws StoreException, CommandException {
108            log.info("STARTED CoordActionCheckCommand for actionId = " + actionId);
109            try {
110                coordAction = store.getEntityManager().find(CoordinatorActionBean.class, actionId);
111                setLogInfo(coordAction);
112                if (lock(coordAction.getJobId())) {
113                    call(store);
114                }
115                else {
116                    queueCallable(new CoordActionCheckCommand(actionId, actionCheckDelay), LOCK_FAILURE_REQUEUE_INTERVAL);
117                    log.warn("CoordActionCheckCommand lock was not acquired - failed jobId=" + coordAction.getJobId()
118                            + ", actionId=" + actionId + ". Requeing the same.");
119                }
120            }
121            catch (InterruptedException e) {
122                queueCallable(new CoordActionCheckCommand(actionId, actionCheckDelay), LOCK_FAILURE_REQUEUE_INTERVAL);
123                log.warn("CoordActionCheckCommand lock acquiring failed with exception " + e.getMessage() + " for jobId="
124                        + coordAction.getJobId() + ", actionId=" + actionId + " Requeing the same.");
125            }
126            finally {
127                log.info("ENDED CoordActionCheckCommand for actionId:" + actionId);
128            }
129            return null;
130        }
131    }