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.Date; 018 019 import org.apache.oozie.CoordinatorActionBean; 020 import org.apache.oozie.ErrorCode; 021 import org.apache.oozie.WorkflowJobBean; 022 import org.apache.oozie.XException; 023 import org.apache.oozie.service.JPAService; 024 import org.apache.oozie.service.Services; 025 import org.apache.oozie.util.LogUtils; 026 import org.apache.oozie.util.db.SLADbOperations; 027 import org.apache.oozie.client.CoordinatorAction; 028 import org.apache.oozie.client.WorkflowJob; 029 import org.apache.oozie.client.SLAEvent.SlaAppType; 030 import org.apache.oozie.client.SLAEvent.Status; 031 import org.apache.oozie.command.CommandException; 032 import org.apache.oozie.command.PreconditionException; 033 import org.apache.oozie.executor.jpa.CoordActionGetForExternalIdJPAExecutor; 034 import org.apache.oozie.executor.jpa.CoordActionUpdateJPAExecutor; 035 import org.apache.oozie.executor.jpa.JPAExecutorException; 036 037 public class CoordActionUpdateXCommand extends CoordinatorXCommand<Void> { 038 private WorkflowJobBean workflow; 039 private CoordinatorActionBean coordAction = null; 040 private JPAService jpaService = null; 041 private int maxRetries = 1; 042 043 public CoordActionUpdateXCommand(WorkflowJobBean workflow) { 044 super("coord-action-update", "coord-action-update", 1); 045 this.workflow = workflow; 046 } 047 048 public CoordActionUpdateXCommand(WorkflowJobBean workflow, int maxRetries) { 049 super("coord-action-update", "coord-action-update", 1); 050 this.workflow = workflow; 051 this.maxRetries = maxRetries; 052 } 053 054 @Override 055 protected Void execute() throws CommandException { 056 try { 057 LOG.debug("STARTED CoordActionUpdateXCommand for wfId=" + workflow.getId()); 058 059 Status slaStatus = null; 060 CoordinatorAction.Status preCoordStatus = coordAction.getStatus(); 061 if (workflow.getStatus() == WorkflowJob.Status.SUCCEEDED) { 062 coordAction.setStatus(CoordinatorAction.Status.SUCCEEDED); 063 coordAction.setPending(0); 064 slaStatus = Status.SUCCEEDED; 065 } 066 else if (workflow.getStatus() == WorkflowJob.Status.FAILED) { 067 coordAction.setStatus(CoordinatorAction.Status.FAILED); 068 coordAction.setPending(0); 069 slaStatus = Status.FAILED; 070 } 071 else if (workflow.getStatus() == WorkflowJob.Status.KILLED) { 072 coordAction.setStatus(CoordinatorAction.Status.KILLED); 073 coordAction.setPending(0); 074 slaStatus = Status.KILLED; 075 } 076 else if (workflow.getStatus() == WorkflowJob.Status.SUSPENDED) { 077 coordAction.setStatus(CoordinatorAction.Status.SUSPENDED); 078 coordAction.decrementAndGetPending(); 079 } 080 else if (workflow.getStatus() == WorkflowJob.Status.RUNNING) { 081 // resume workflow job and update coord action accordingly 082 coordAction.setStatus(CoordinatorAction.Status.RUNNING); 083 coordAction.decrementAndGetPending(); 084 } 085 else { 086 LOG.warn("Unexpected workflow " + workflow.getId() + " STATUS " + workflow.getStatus()); 087 // update lastModifiedTime 088 coordAction.setLastModifiedTime(new Date()); 089 jpaService.execute(new CoordActionUpdateJPAExecutor(coordAction)); 090 091 return null; 092 } 093 094 LOG.info("Updating Coordintaor action id :" + coordAction.getId() + " status from " + preCoordStatus 095 + " to " + coordAction.getStatus() + ", pending = " + coordAction.getPending()); 096 097 coordAction.setLastModifiedTime(new Date()); 098 jpaService.execute(new CoordActionUpdateJPAExecutor(coordAction)); 099 if (slaStatus != null) { 100 SLADbOperations.writeStausEvent(coordAction.getSlaXml(), coordAction.getId(), slaStatus, 101 SlaAppType.COORDINATOR_ACTION, LOG); 102 } 103 if (workflow.getStatus() != WorkflowJob.Status.SUSPENDED 104 && workflow.getStatus() != WorkflowJob.Status.RUNNING) { 105 queue(new CoordActionReadyXCommand(coordAction.getJobId())); 106 } 107 LOG.debug("ENDED CoordActionUpdateXCommand for wfId=" + workflow.getId()); 108 } 109 catch (XException ex) { 110 LOG.warn("CoordActionUpdate Failed ", ex.getMessage()); 111 throw new CommandException(ex); 112 } 113 return null; 114 } 115 116 /* (non-Javadoc) 117 * @see org.apache.oozie.command.XCommand#getEntityKey() 118 */ 119 @Override 120 protected String getEntityKey() { 121 return coordAction.getJobId(); 122 } 123 124 /* (non-Javadoc) 125 * @see org.apache.oozie.command.XCommand#isLockRequired() 126 */ 127 @Override 128 protected boolean isLockRequired() { 129 return true; 130 } 131 132 /* (non-Javadoc) 133 * @see org.apache.oozie.command.XCommand#eagerLoadState() 134 */ 135 @Override 136 protected void eagerLoadState() throws CommandException { 137 jpaService = Services.get().get(JPAService.class); 138 if (jpaService == null) { 139 throw new CommandException(ErrorCode.E0610); 140 } 141 142 int retries = 0; 143 while (retries++ < maxRetries) { 144 try { 145 coordAction = jpaService.execute(new CoordActionGetForExternalIdJPAExecutor(workflow.getId())); 146 if (coordAction != null) { 147 break; 148 } 149 150 if (retries < maxRetries) { 151 Thread.sleep(500); 152 } 153 } 154 catch (JPAExecutorException je) { 155 LOG.warn("Could not load coord action {0}", je.getMessage(), je); 156 } 157 catch (InterruptedException ex) { 158 LOG.warn("Retry to load coord action is interrupted {0}", ex.getMessage(), ex); 159 } 160 } 161 162 if (coordAction != null) { 163 LogUtils.setLogInfo(coordAction, logInfo); 164 } 165 } 166 167 /* (non-Javadoc) 168 * @see org.apache.oozie.command.XCommand#eagerVerifyPrecondition() 169 */ 170 @Override 171 protected void eagerVerifyPrecondition() throws CommandException, PreconditionException { 172 if (coordAction == null) { 173 throw new PreconditionException(ErrorCode.E1100, ", coord action is null"); 174 } 175 } 176 177 /* (non-Javadoc) 178 * @see org.apache.oozie.command.XCommand#loadState() 179 */ 180 @Override 181 protected void loadState() throws CommandException { 182 } 183 184 /* (non-Javadoc) 185 * @see org.apache.oozie.command.XCommand#verifyPrecondition() 186 */ 187 @Override 188 protected void verifyPrecondition() throws CommandException, PreconditionException { 189 190 // if coord action is RUNNING and pending false and workflow is RUNNING, this doesn't need to be updated. 191 if (workflow.getStatus() == WorkflowJob.Status.RUNNING 192 && coordAction.getStatus() == CoordinatorAction.Status.RUNNING && !coordAction.isPending()) { 193 // update lastModifiedTime 194 coordAction.setLastModifiedTime(new Date()); 195 try { 196 jpaService.execute(new org.apache.oozie.executor.jpa.CoordActionUpdateJPAExecutor(coordAction)); 197 } 198 catch (JPAExecutorException je) { 199 throw new CommandException(je); 200 } 201 throw new PreconditionException(ErrorCode.E1100, ", workflow is RUNNING and coordinator action is RUNNING and pending false"); 202 } 203 } 204 205 }