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 org.apache.oozie.client.CoordinatorJob; 018 import org.apache.oozie.client.Job; 019 import org.apache.oozie.CoordinatorActionBean; 020 import org.apache.oozie.CoordinatorJobBean; 021 import org.apache.oozie.ErrorCode; 022 import org.apache.oozie.XException; 023 import org.apache.oozie.command.bundle.BundleStatusUpdateXCommand; 024 import org.apache.oozie.command.wf.KillXCommand; 025 import org.apache.oozie.command.CommandException; 026 import org.apache.oozie.command.KillTransitionXCommand; 027 import org.apache.oozie.command.PreconditionException; 028 import org.apache.oozie.executor.jpa.CoordActionUpdateJPAExecutor; 029 import org.apache.oozie.executor.jpa.CoordJobGetActionsJPAExecutor; 030 import org.apache.oozie.executor.jpa.CoordJobGetJPAExecutor; 031 import org.apache.oozie.executor.jpa.CoordJobUpdateJPAExecutor; 032 import org.apache.oozie.executor.jpa.JPAExecutorException; 033 import org.apache.oozie.service.JPAService; 034 import org.apache.oozie.service.Services; 035 import org.apache.oozie.util.LogUtils; 036 import org.apache.oozie.util.ParamChecker; 037 import org.apache.oozie.util.StatusUtils; 038 039 import java.util.Date; 040 import java.util.List; 041 042 public class CoordKillXCommand extends KillTransitionXCommand { 043 044 private final String jobId; 045 private CoordinatorJobBean coordJob; 046 private List<CoordinatorActionBean> actionList; 047 private JPAService jpaService = null; 048 private CoordinatorJob.Status prevStatus = null; 049 050 public CoordKillXCommand(String id) { 051 super("coord_kill", "coord_kill", 1); 052 this.jobId = ParamChecker.notEmpty(id, "id"); 053 } 054 055 @Override 056 protected boolean isLockRequired() { 057 return true; 058 } 059 060 @Override 061 protected String getEntityKey() { 062 return this.jobId; 063 } 064 065 @Override 066 protected void loadState() throws CommandException { 067 try { 068 jpaService = Services.get().get(JPAService.class); 069 070 if (jpaService != null) { 071 this.coordJob = jpaService.execute(new CoordJobGetJPAExecutor(jobId)); 072 this.actionList = jpaService.execute(new CoordJobGetActionsJPAExecutor(jobId)); 073 prevStatus = coordJob.getStatus(); 074 LogUtils.setLogInfo(coordJob, logInfo); 075 } 076 else { 077 throw new CommandException(ErrorCode.E0610); 078 } 079 } 080 catch (XException ex) { 081 throw new CommandException(ex); 082 } 083 } 084 085 @Override 086 protected void verifyPrecondition() throws CommandException, PreconditionException { 087 // if namespace 0.1 is used and backward support is true, SUCCEEDED coord job can be killed 088 if (StatusUtils.isV1CoordjobKillable(coordJob)) { 089 return; 090 } 091 if (coordJob.getStatus() == CoordinatorJob.Status.SUCCEEDED 092 || coordJob.getStatus() == CoordinatorJob.Status.FAILED 093 || coordJob.getStatus() == CoordinatorJob.Status.DONEWITHERROR) { 094 LOG.info("CoordKillXCommand not killed - job either finished SUCCEEDED, FAILED or DONEWITHERROR, job id = " 095 + jobId + ", status = " + coordJob.getStatus()); 096 throw new PreconditionException(ErrorCode.E1020, jobId); 097 } 098 } 099 100 private void updateCoordAction(CoordinatorActionBean action) throws CommandException { 101 action.setStatus(CoordinatorActionBean.Status.KILLED); 102 action.incrementAndGetPending(); 103 action.setLastModifiedTime(new Date()); 104 try { 105 jpaService.execute(new CoordActionUpdateJPAExecutor(action)); 106 } 107 catch (JPAExecutorException e) { 108 throw new CommandException(e); 109 } 110 } 111 112 @Override 113 public void killChildren() throws CommandException { 114 try { 115 if (actionList != null) { 116 for (CoordinatorActionBean action : actionList) { 117 if (action.getStatus() != CoordinatorActionBean.Status.FAILED 118 && action.getStatus() != CoordinatorActionBean.Status.TIMEDOUT 119 && action.getStatus() != CoordinatorActionBean.Status.SUCCEEDED 120 && action.getStatus() != CoordinatorActionBean.Status.KILLED) { 121 // queue a WorkflowKillXCommand to delete the workflow job and actions 122 if (action.getExternalId() != null) { 123 queue(new KillXCommand(action.getExternalId())); 124 updateCoordAction(action); 125 LOG.debug("Killed coord action = [{0}], new status = [{1}], pending = [{2}] and queue KillXCommand for [{3}]", 126 action.getId(), action.getStatus(), action.getPending(), action.getExternalId()); 127 } 128 else { 129 updateCoordAction(action); 130 LOG.debug("Killed coord action = [{0}], current status = [{1}], pending = [{2}]", action.getId(), action 131 .getStatus(), action.getPending()); 132 } 133 } 134 } 135 } 136 jpaService.execute(new CoordJobUpdateJPAExecutor(coordJob)); 137 138 LOG.debug("Killed coord actions for the coordinator=[{0}]", jobId); 139 } 140 catch (JPAExecutorException ex) { 141 throw new CommandException(ex); 142 } 143 } 144 145 @Override 146 public void notifyParent() throws CommandException { 147 // update bundle action 148 if (coordJob.getBundleId() != null) { 149 BundleStatusUpdateXCommand bundleStatusUpdate = new BundleStatusUpdateXCommand(coordJob, prevStatus); 150 bundleStatusUpdate.call(); 151 } 152 } 153 154 @Override 155 public void updateJob() throws CommandException { 156 try { 157 coordJob.setEndTime(new Date()); 158 jpaService.execute(new CoordJobUpdateJPAExecutor(coordJob)); 159 } 160 catch (JPAExecutorException ex) { 161 throw new CommandException(ex); 162 } 163 } 164 165 /* (non-Javadoc) 166 * @see org.apache.oozie.command.TransitionXCommand#getJob() 167 */ 168 @Override 169 public Job getJob() { 170 return coordJob; 171 } 172 173 }