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.wf;
016    
017    import java.util.Date;
018    
019    import org.apache.oozie.WorkflowActionBean;
020    import org.apache.oozie.WorkflowJobBean;
021    import org.apache.oozie.client.WorkflowJob;
022    import org.apache.oozie.command.CommandException;
023    import org.apache.oozie.store.StoreException;
024    import org.apache.oozie.store.WorkflowStore;
025    import org.apache.oozie.util.ParamChecker;
026    import org.apache.oozie.util.XLog;
027    import org.apache.oozie.workflow.WorkflowException;
028    import org.apache.oozie.workflow.WorkflowInstance;
029    import org.apache.oozie.workflow.lite.LiteWorkflowInstance;
030    
031    public class ResumeCommand extends WorkflowCommand<Void> {
032    
033        private String id;
034    
035        public ResumeCommand(String id) {
036            super("resume", "resume", 1, XLog.STD);
037            this.id = ParamChecker.notEmpty(id, "id");
038        }
039    
040        @Override
041        protected Void call(WorkflowStore store) throws StoreException, CommandException {
042            try {
043                WorkflowJobBean workflow = store.getWorkflow(id, false);
044                setLogInfo(workflow);
045                if (workflow.getStatus() == WorkflowJob.Status.SUSPENDED) {
046                    incrJobCounter(1);
047                    workflow.getWorkflowInstance().resume();
048                    WorkflowInstance wfInstance = workflow.getWorkflowInstance();
049                    ((LiteWorkflowInstance) wfInstance).setStatus(WorkflowInstance.Status.RUNNING);
050                    workflow.setWorkflowInstance(wfInstance);
051                    workflow.setStatus(WorkflowJob.Status.RUNNING);
052    
053                    for (WorkflowActionBean action : store.getActionsForWorkflow(id, false)) {
054    
055                        // Set pending flag to true for the actions that are START_RETRY or
056                        // START_MANUAL or END_RETRY or END_MANUAL
057                        if (action.isRetryOrManual()) {
058                            action.setPendingOnly();
059                            store.updateAction(action);
060                        }
061    
062                        if (action.isPending()) {
063                            if (action.getStatus() == WorkflowActionBean.Status.PREP
064                                    || action.getStatus() == WorkflowActionBean.Status.START_MANUAL) {
065                                queueCallable(new ActionStartCommand(action.getId(), action.getType()));
066                            }
067                            else {
068                                if (action.getStatus() == WorkflowActionBean.Status.START_RETRY) {
069                                    Date nextRunTime = action.getPendingAge();
070                                    queueCallable(new ActionStartCommand(action.getId(), action.getType()),
071                                                  nextRunTime.getTime() - System.currentTimeMillis());
072                                }
073                                else {
074                                    if (action.getStatus() == WorkflowActionBean.Status.DONE
075                                            || action.getStatus() == WorkflowActionBean.Status.END_MANUAL) {
076                                        queueCallable(new ActionEndCommand(action.getId(), action.getType()));
077                                    }
078                                    else {
079                                        if (action.getStatus() == WorkflowActionBean.Status.END_RETRY) {
080                                            Date nextRunTime = action.getPendingAge();
081                                            queueCallable(new ActionEndCommand(action.getId(), action.getType()),
082                                                          nextRunTime.getTime() - System.currentTimeMillis());
083                                        }
084                                    }
085                                }
086                            }
087    
088                        }
089                    }
090    
091                    store.updateWorkflow(workflow);
092                    queueCallable(new NotificationCommand(workflow));
093                }
094                return null;
095            }
096            catch (WorkflowException ex) {
097                throw new CommandException(ex);
098            }
099        }
100    
101        @Override
102        protected Void execute(WorkflowStore store) throws CommandException, StoreException {
103            XLog.getLog(getClass()).debug("STARTED ResumeCommand for action " + id);
104            try {
105                if (lock(id)) {
106                    call(store);
107                }
108                else {
109                    queueCallable(new KillCommand(id), LOCK_FAILURE_REQUEUE_INTERVAL);
110                    XLog.getLog(getClass()).warn("Resume lock was not acquired - failed {0}", id);
111                }
112            }
113            catch (InterruptedException e) {
114                queueCallable(new KillCommand(id), LOCK_FAILURE_REQUEUE_INTERVAL);
115                XLog.getLog(getClass()).warn("ResumeCommand lock was not acquired - interrupted exception failed {0}", id);
116            }
117            finally {
118                XLog.getLog(getClass()).debug("ENDED ResumeCommand for action " + id);
119            }
120            return null;
121        }
122    }