001 package org.apache.oozie.command.bundle; 002 003 import java.util.Date; 004 import java.util.HashMap; 005 import java.util.List; 006 import java.util.Map; 007 008 import org.apache.oozie.BundleActionBean; 009 import org.apache.oozie.BundleJobBean; 010 import org.apache.oozie.CoordinatorJobBean; 011 import org.apache.oozie.ErrorCode; 012 import org.apache.oozie.XException; 013 import org.apache.oozie.client.Job; 014 import org.apache.oozie.client.rest.RestConstants; 015 import org.apache.oozie.command.CommandException; 016 import org.apache.oozie.command.RerunTransitionXCommand; 017 import org.apache.oozie.command.coord.CoordRerunXCommand; 018 import org.apache.oozie.executor.jpa.BundleActionUpdateJPAExecutor; 019 import org.apache.oozie.executor.jpa.BundleActionsGetJPAExecutor; 020 import org.apache.oozie.executor.jpa.BundleJobGetJPAExecutor; 021 import org.apache.oozie.executor.jpa.BundleJobUpdateJPAExecutor; 022 import org.apache.oozie.executor.jpa.CoordJobGetJPAExecutor; 023 import org.apache.oozie.executor.jpa.JPAExecutorException; 024 import org.apache.oozie.service.JPAService; 025 import org.apache.oozie.service.Services; 026 import org.apache.oozie.util.DateUtils; 027 import org.apache.oozie.util.LogUtils; 028 import org.apache.oozie.util.ParamChecker; 029 import org.apache.oozie.util.XLog; 030 031 /** 032 * Rerun bundle coordinator jobs by a list of coordinator names or dates. User can specify if refresh or noCleanup. 033 * <p/> 034 * The "refresh" is used to indicate if user wants to refresh an action's input/outpur dataset urls 035 * <p/> 036 * The "noCleanup" is used to indicate if user wants to cleanup output events for given rerun actions 037 */ 038 public class BundleRerunXCommand extends RerunTransitionXCommand<Void> { 039 040 private final String coordScope; 041 private final String dateScope; 042 private final boolean refresh; 043 private final boolean noCleanup; 044 private BundleJobBean bundleJob; 045 private List<BundleActionBean> bundleActions; 046 protected boolean prevPending; 047 048 private JPAService jpaService = null; 049 050 /** 051 * The constructor for class {@link BundleRerunXCommand} 052 * 053 * @param jobId the bundle job id 054 * @param coordScope the rerun scope for coordinator job names separated by "," 055 * @param dateScope the rerun scope for coordinator nominal times separated by "," 056 * @param refresh true if user wants to refresh input/outpur dataset urls 057 * @param noCleanup false if user wants to cleanup output events for given rerun actions 058 */ 059 public BundleRerunXCommand(String jobId, String coordScope, String dateScope, boolean refresh, boolean noCleanup) { 060 super("bundle_rerun", "bundle_rerun", 1); 061 this.jobId = ParamChecker.notEmpty(jobId, "jobId"); 062 this.coordScope = coordScope; 063 this.dateScope = dateScope; 064 this.refresh = refresh; 065 this.noCleanup = noCleanup; 066 } 067 068 /* (non-Javadoc) 069 * @see org.apache.oozie.command.XCommand#loadState() 070 */ 071 @Override 072 protected void loadState() throws CommandException { 073 try { 074 jpaService = Services.get().get(JPAService.class); 075 076 if (jpaService != null) { 077 this.bundleJob = jpaService.execute(new BundleJobGetJPAExecutor(jobId)); 078 this.bundleActions = jpaService.execute(new BundleActionsGetJPAExecutor(jobId)); 079 LogUtils.setLogInfo(bundleJob, logInfo); 080 super.setJob(bundleJob); 081 prevPending = bundleJob.isPending(); 082 } 083 else { 084 throw new CommandException(ErrorCode.E0610); 085 } 086 } 087 catch (XException ex) { 088 throw new CommandException(ex); 089 } 090 091 } 092 093 /* (non-Javadoc) 094 * @see org.apache.oozie.command.RerunTransitionXCommand#rerunChildren() 095 */ 096 @Override 097 public void rerunChildren() throws CommandException { 098 boolean isUpdateActionDone = false; 099 Map<String, BundleActionBean> coordNameToBAMapping = new HashMap<String, BundleActionBean>(); 100 if (bundleActions != null) { 101 for (BundleActionBean action : bundleActions) { 102 if (action.getCoordName() != null) { 103 coordNameToBAMapping.put(action.getCoordName(), action); 104 } 105 } 106 } 107 108 if (coordScope != null && !coordScope.isEmpty()) { 109 String[] list = coordScope.split(","); 110 for (String coordName : list) { 111 coordName = coordName.trim(); 112 if (coordNameToBAMapping.keySet().contains(coordName)) { 113 String coordId = coordNameToBAMapping.get(coordName).getCoordId(); 114 if (coordId == null) { 115 LOG.info("No coord id found. Therefore, nothing to queue for coord rerun for coordname: " + coordName); 116 continue; 117 } 118 CoordinatorJobBean coordJob = getCoordJob(coordId); 119 120 String rerunDateScope; 121 if (dateScope != null && !dateScope.isEmpty()) { 122 rerunDateScope = dateScope; 123 } 124 else { 125 String coordStart = DateUtils.convertDateToString(coordJob.getStartTime()); 126 String coordEnd = DateUtils.convertDateToString(coordJob.getEndTime()); 127 rerunDateScope = coordStart + "::" + coordEnd; 128 } 129 LOG.debug("Queuing rerun range [" + rerunDateScope + "] for coord id " + coordId + " of bundle " 130 + bundleJob.getId()); 131 queue(new CoordRerunXCommand(coordId, RestConstants.JOB_COORD_RERUN_DATE, rerunDateScope, refresh, 132 noCleanup)); 133 updateBundleAction(coordNameToBAMapping.get(coordName)); 134 isUpdateActionDone = true; 135 } 136 else { 137 LOG.info("Rerun for coord " + coordName + " NOT performed because it is not in bundle ", bundleJob.getId()); 138 } 139 } 140 } 141 else if (dateScope != null && !dateScope.isEmpty()) { 142 if (bundleActions != null) { 143 for (BundleActionBean action : bundleActions) { 144 if (action.getCoordId() == null) { 145 LOG.info("No coord id found. Therefore nothing to queue for coord rerun with coord name " 146 + action.getCoordName()); 147 continue; 148 } 149 LOG.debug("Queuing rerun range [" + dateScope + "] for coord id " + action.getCoordId() + " of bundle " 150 + bundleJob.getId()); 151 queue(new CoordRerunXCommand(action.getCoordId(), RestConstants.JOB_COORD_RERUN_DATE, dateScope, 152 refresh, noCleanup)); 153 updateBundleAction(action); 154 isUpdateActionDone = true; 155 } 156 } 157 } 158 if (!isUpdateActionDone) { 159 transitToPrevious(); 160 } 161 LOG.info("Rerun coord jobs for the bundle=[{0}]", jobId); 162 } 163 164 private final void transitToPrevious() throws CommandException { 165 bundleJob.setStatus(getPrevStatus()); 166 if (!prevPending) { 167 bundleJob.resetPending(); 168 } 169 else { 170 bundleJob.setPending(); 171 } 172 updateJob(); 173 } 174 175 /** 176 * Update bundle action 177 * 178 * @param action the bundle action 179 * @throws CommandException thrown if failed to update bundle action 180 */ 181 private void updateBundleAction(BundleActionBean action) throws CommandException { 182 action.incrementAndGetPending(); 183 action.setLastModifiedTime(new Date()); 184 try { 185 jpaService.execute(new BundleActionUpdateJPAExecutor(action)); 186 } 187 catch (JPAExecutorException je) { 188 throw new CommandException(je); 189 } 190 } 191 192 /* (non-Javadoc) 193 * @see org.apache.oozie.command.TransitionXCommand#updateJob() 194 */ 195 @Override 196 public void updateJob() throws CommandException { 197 try { 198 // rerun a paused bundle job will keep job status at paused and pending at previous pending 199 if (getPrevStatus()!= null && getPrevStatus().equals(Job.Status.PAUSED)) { 200 bundleJob.setStatus(Job.Status.PAUSED); 201 if (prevPending) { 202 bundleJob.setPending(); 203 } else { 204 bundleJob.resetPending(); 205 } 206 } 207 jpaService.execute(new BundleJobUpdateJPAExecutor(bundleJob)); 208 } 209 catch (JPAExecutorException je) { 210 throw new CommandException(je); 211 } 212 213 } 214 215 /* (non-Javadoc) 216 * @see org.apache.oozie.command.XCommand#getEntityKey() 217 */ 218 @Override 219 protected String getEntityKey() { 220 return jobId; 221 } 222 223 /* (non-Javadoc) 224 * @see org.apache.oozie.command.XCommand#isLockRequired() 225 */ 226 @Override 227 protected boolean isLockRequired() { 228 return true; 229 } 230 231 /* 232 * (non-Javadoc) 233 * @see org.apache.oozie.command.TransitionXCommand#getJob() 234 */ 235 @Override 236 public Job getJob() { 237 return bundleJob; 238 } 239 240 /* (non-Javadoc) 241 * @see org.apache.oozie.command.TransitionXCommand#notifyParent() 242 */ 243 @Override 244 public void notifyParent() throws CommandException { 245 246 } 247 248 /* (non-Javadoc) 249 * @see org.apache.oozie.command.RerunTransitionXCommand#getLog() 250 */ 251 @Override 252 public XLog getLog() { 253 return LOG; 254 } 255 256 private final CoordinatorJobBean getCoordJob(String coordId) throws CommandException { 257 try { 258 CoordinatorJobBean job = jpaService.execute(new CoordJobGetJPAExecutor(coordId)); 259 return job; 260 } 261 catch (JPAExecutorException je) { 262 throw new CommandException(je); 263 } 264 265 } 266 267 }