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.util.List;
018
019 import org.apache.oozie.CoordinatorActionBean;
020 import org.apache.oozie.CoordinatorJobBean;
021 import org.apache.oozie.client.CoordinatorAction;
022 import org.apache.oozie.command.CommandException;
023 import org.apache.oozie.store.CoordinatorStore;
024 import org.apache.oozie.store.StoreException;
025 import org.apache.oozie.util.XLog;
026
027 public class CoordActionReadyCommand extends CoordinatorCommand<Void> {
028 private String jobId;
029 private final XLog log = XLog.getLog(getClass());
030
031 public CoordActionReadyCommand(String id) {
032 super("coord_action_ready", "coord_action_ready", 1, XLog.STD);
033 this.jobId = id;
034 }
035
036 @Override
037 /**
038 * Check for READY actions and change state to SUBMITTED by a command to submit the job to WF engine.
039 * This method checks all the actions associated with a jobId to figure out which actions
040 * to start (based on concurrency and execution order [FIFO, LIFO, LAST_ONLY])
041 *
042 * @param store Coordinator Store
043 */
044 protected Void call(CoordinatorStore store) throws StoreException, CommandException {
045 // number of actions to start (-1 means start ALL)
046 int numActionsToStart = -1;
047 // get CoordinatorJobBean for jobId
048 //CoordinatorJobBean coordJob = store.getCoordinatorJob(jobId, false);
049 CoordinatorJobBean coordJob = store.getEntityManager().find(CoordinatorJobBean.class, jobId);
050 setLogInfo(coordJob);
051 // get execution setting for this job (FIFO, LIFO, LAST_ONLY)
052 String jobExecution = coordJob.getExecution();
053 // get concurrency setting for this job
054 int jobConcurrency = coordJob.getConcurrency();
055 // if less than 0, then UNLIMITED concurrency
056 if (jobConcurrency >= 0) {
057 // count number of actions that are already RUNNING or SUBMITTED
058 // subtract from CONCURRENCY to calculate number of actions to start
059 // in WF engine
060 int numRunningJobs = store.getCoordinatorRunningActionsCount(jobId);
061 numActionsToStart = jobConcurrency - numRunningJobs;
062 if (numActionsToStart < 0) {
063 numActionsToStart = 0;
064 }
065 log.debug("concurrency=" + jobConcurrency + ", execution=" + jobExecution + ", numRunningJobs="
066 + numRunningJobs + ", numLeftover=" + numActionsToStart);
067 // no actions to start
068 if (numActionsToStart == 0) {
069 log.warn("No actions to start! for jobId=" + jobId);
070 return null;
071 }
072 }
073 // get list of actions that are READY and fit in the concurrency and
074 // execution
075 List<CoordinatorActionBean> actions = store.getCoordinatorActionsForJob(jobId, numActionsToStart, jobExecution);
076 log.debug("Number of READY actions = " + actions.size());
077 String user = coordJob.getUser();
078 String authToken = coordJob.getAuthToken();
079 // make sure auth token is not null
080 // log.denug("user=" + user + ", token=" + authToken);
081 int counter = 0;
082 for (CoordinatorActionBean action : actions) {
083 // continue if numActionsToStart is negative (no limit on number of
084 // actions), or if the counter is less than numActionsToStart
085 if ((numActionsToStart < 0) || (counter < numActionsToStart)) {
086 log.debug("Set status to SUBMITTED for id: " + action.getId());
087 // change state of action to SUBMITTED
088 action.setStatus(CoordinatorAction.Status.SUBMITTED);
089 // queue action to start action
090 queueCallable(new CoordActionStartCommand(action.getId(), user, authToken), 100);
091 store.updateCoordinatorAction(action);
092 }
093 else {
094 break;
095 }
096 counter++;
097
098 }
099 return null;
100 }
101
102 @Override
103 protected Void execute(CoordinatorStore store) throws StoreException, CommandException {
104 log.info("STARTED CoordActionReadyCommand for jobId=" + jobId);
105 try {
106 if (lock(jobId)) {
107 call(store);
108 }
109 else {
110 queueCallable(new CoordActionReadyCommand(jobId), LOCK_FAILURE_REQUEUE_INTERVAL);
111 log.warn("CoordActionReadyCommand lock was not acquired - failed jobId=" + jobId
112 + ". Requeing the same.");
113 }
114 }
115 catch (InterruptedException e) {
116 queueCallable(new CoordActionReadyCommand(jobId), LOCK_FAILURE_REQUEUE_INTERVAL);
117 log.warn("CoordActionReadyCommand lock acquiring failed with exception " + e.getMessage()
118 + " for jobId=" + jobId + " Requeing the same.");
119 }
120 finally {
121 log.info("ENDED CoordActionReadyCommand for jobId=" + jobId);
122 }
123 return null;
124 }
125
126 }