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.bundle; 016 017 import java.util.Date; 018 import java.util.List; 019 020 import org.apache.oozie.BundleActionBean; 021 import org.apache.oozie.BundleJobBean; 022 import org.apache.oozie.ErrorCode; 023 import org.apache.oozie.XException; 024 import org.apache.oozie.client.Job; 025 import org.apache.oozie.command.CommandException; 026 import org.apache.oozie.command.PreconditionException; 027 import org.apache.oozie.command.SuspendTransitionXCommand; 028 import org.apache.oozie.command.coord.CoordSuspendXCommand; 029 import org.apache.oozie.executor.jpa.BundleActionUpdateJPAExecutor; 030 import org.apache.oozie.executor.jpa.BundleActionsGetJPAExecutor; 031 import org.apache.oozie.executor.jpa.BundleJobGetJPAExecutor; 032 import org.apache.oozie.executor.jpa.BundleJobUpdateJPAExecutor; 033 import org.apache.oozie.executor.jpa.JPAExecutorException; 034 import org.apache.oozie.service.JPAService; 035 import org.apache.oozie.service.Services; 036 import org.apache.oozie.util.InstrumentUtils; 037 import org.apache.oozie.util.ParamChecker; 038 import org.apache.oozie.util.LogUtils; 039 040 public class BundleJobSuspendXCommand extends SuspendTransitionXCommand { 041 private final String jobId; 042 private JPAService jpaService; 043 private List<BundleActionBean> bundleActions; 044 private BundleJobBean bundleJob; 045 046 public BundleJobSuspendXCommand(String id) { 047 super("bundle_suspend", "bundle_suspend", 1); 048 this.jobId = ParamChecker.notEmpty(id, "id"); 049 } 050 051 /* (non-Javadoc) 052 * @see org.apache.oozie.command.TransitionXCommand#getJob() 053 */ 054 @Override 055 public Job getJob() { 056 return bundleJob; 057 } 058 059 /* (non-Javadoc) 060 * @see org.apache.oozie.command.TransitionXCommand#notifyParent() 061 */ 062 @Override 063 public void notifyParent() throws CommandException { 064 } 065 066 /* (non-Javadoc) 067 * @see org.apache.oozie.command.TransitionXCommand#setJob(org.apache.oozie.client.Job) 068 */ 069 @Override 070 public void setJob(Job job) { 071 } 072 073 /* (non-Javadoc) 074 * @see org.apache.oozie.command.XCommand#getEntityKey() 075 */ 076 @Override 077 protected String getEntityKey() { 078 return this.jobId; 079 } 080 081 /* (non-Javadoc) 082 * @see org.apache.oozie.command.XCommand#isLockRequired() 083 */ 084 @Override 085 protected boolean isLockRequired() { 086 return true; 087 } 088 089 /* (non-Javadoc) 090 * @see org.apache.oozie.command.XCommand#loadState() 091 */ 092 @Override 093 protected void loadState() throws CommandException { 094 jpaService = Services.get().get(JPAService.class); 095 if (jpaService == null) { 096 throw new CommandException(ErrorCode.E0610); 097 } 098 099 try { 100 bundleJob = jpaService.execute(new BundleJobGetJPAExecutor(jobId)); 101 } 102 catch (Exception Ex) { 103 throw new CommandException(ErrorCode.E0604, jobId); 104 } 105 106 try { 107 bundleActions = jpaService.execute(new BundleActionsGetJPAExecutor(jobId)); 108 } 109 catch (Exception Ex) { 110 throw new CommandException(ErrorCode.E1311, jobId); 111 } 112 113 LogUtils.setLogInfo(bundleJob, logInfo); 114 } 115 116 /* (non-Javadoc) 117 * @see org.apache.oozie.command.XCommand#verifyPrecondition() 118 */ 119 @Override 120 protected void verifyPrecondition() throws CommandException, PreconditionException { 121 if (bundleJob.getStatus() == Job.Status.SUCCEEDED || bundleJob.getStatus() == Job.Status.FAILED 122 || bundleJob.getStatus() == Job.Status.KILLED) { 123 LOG.info("BundleJobSuspendXCommand is not going to execute because job finished or failed or killed, id = " 124 + jobId + ", status = " + bundleJob.getStatus()); 125 throw new PreconditionException(ErrorCode.E1312, jobId, bundleJob.getStatus().toString()); 126 } 127 } 128 129 /* (non-Javadoc) 130 * @see org.apache.oozie.command.TransitionXCommand#updateJob() 131 */ 132 @Override 133 public void updateJob() throws CommandException { 134 InstrumentUtils.incrJobCounter("bundle_suspend", 1, null); 135 bundleJob.setSuspendedTime(new Date()); 136 bundleJob.setLastModifiedTime(new Date()); 137 138 LOG.debug("Suspend bundle job id = " + jobId + ", status = " + bundleJob.getStatus() + ", pending = " + bundleJob.isPending()); 139 try { 140 jpaService.execute(new BundleJobUpdateJPAExecutor(bundleJob)); 141 } 142 catch (JPAExecutorException e) { 143 throw new CommandException(e); 144 } 145 } 146 147 @Override 148 public void suspendChildren() throws CommandException { 149 try { 150 for (BundleActionBean action : this.bundleActions) { 151 if (action.getStatus() == Job.Status.RUNNING || action.getStatus() == Job.Status.PREP) { 152 // queue a CoordSuspendXCommand 153 if (action.getCoordId() != null) { 154 queue(new CoordSuspendXCommand(action.getCoordId())); 155 updateBundleAction(action); 156 LOG.debug("Suspend bundle action = [{0}], new status = [{1}], pending = [{2}] and queue CoordSuspendXCommand for [{3}]", 157 action.getBundleActionId(), action.getStatus(), action.getPending(), action.getCoordId()); 158 } else { 159 updateBundleAction(action); 160 LOG.debug("Suspend bundle action = [{0}], new status = [{1}], pending = [{2}] and coord id is null", 161 action.getBundleActionId(), action.getStatus(), action.getPending()); 162 } 163 164 } 165 } 166 LOG.debug("Suspended bundle actions for the bundle=[{0}]", jobId); 167 } 168 catch (XException ex) { 169 throw new CommandException(ex); 170 } 171 } 172 173 private void updateBundleAction(BundleActionBean action) throws CommandException { 174 if (action.getStatus() == Job.Status.PREP) { 175 action.setStatus(Job.Status.PREPSUSPENDED); 176 } 177 else if (action.getStatus() == Job.Status.RUNNING) { 178 action.setStatus(Job.Status.SUSPENDED); 179 } 180 action.incrementAndGetPending(); 181 action.setLastModifiedTime(new Date()); 182 try { 183 jpaService.execute(new BundleActionUpdateJPAExecutor(action)); 184 } 185 catch (JPAExecutorException e) { 186 throw new CommandException(e); 187 } 188 } 189 }