001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.oozie.command.coord; 020 021import org.apache.commons.lang.StringUtils; 022import org.apache.hadoop.conf.Configuration; 023import org.apache.oozie.AppType; 024import org.apache.oozie.CoordinatorActionBean; 025import org.apache.oozie.CoordinatorJobBean; 026import org.apache.oozie.ErrorCode; 027import org.apache.oozie.SLAEventBean; 028import org.apache.oozie.client.CoordinatorJob; 029import org.apache.oozie.client.Job; 030import org.apache.oozie.client.SLAEvent.SlaAppType; 031import org.apache.oozie.client.rest.JsonBean; 032import org.apache.oozie.command.CommandException; 033import org.apache.oozie.command.MaterializeTransitionXCommand; 034import org.apache.oozie.command.PreconditionException; 035import org.apache.oozie.command.bundle.BundleStatusUpdateXCommand; 036import org.apache.oozie.coord.CoordUtils; 037import org.apache.oozie.coord.TimeUnit; 038import org.apache.oozie.executor.jpa.BatchQueryExecutor; 039import org.apache.oozie.executor.jpa.BatchQueryExecutor.UpdateEntry; 040import org.apache.oozie.executor.jpa.CoordActionsActiveCountJPAExecutor; 041import org.apache.oozie.executor.jpa.CoordJobQueryExecutor; 042import org.apache.oozie.executor.jpa.CoordJobQueryExecutor.CoordJobQuery; 043import org.apache.oozie.executor.jpa.JPAExecutorException; 044import org.apache.oozie.service.ConfigurationService; 045import org.apache.oozie.service.CoordMaterializeTriggerService; 046import org.apache.oozie.service.EventHandlerService; 047import org.apache.oozie.service.JPAService; 048import org.apache.oozie.service.Service; 049import org.apache.oozie.service.Services; 050import org.apache.oozie.sla.SLAOperations; 051import org.apache.oozie.util.DateUtils; 052import org.apache.oozie.util.Instrumentation; 053import org.apache.oozie.util.LogUtils; 054import org.apache.oozie.util.ParamChecker; 055import org.apache.oozie.util.StatusUtils; 056import org.apache.oozie.util.XConfiguration; 057import org.apache.oozie.util.XmlUtils; 058import org.apache.oozie.util.db.SLADbOperations; 059import org.jdom.Element; 060import org.jdom.JDOMException; 061 062import java.io.IOException; 063import java.io.StringReader; 064import java.sql.Timestamp; 065import java.util.Calendar; 066import java.util.Date; 067import java.util.TimeZone; 068 069/** 070 * Materialize actions for specified start and end time for coordinator job. 071 */ 072@SuppressWarnings("deprecation") 073public class CoordMaterializeTransitionXCommand extends MaterializeTransitionXCommand { 074 075 private JPAService jpaService = null; 076 private CoordinatorJobBean coordJob = null; 077 private String jobId = null; 078 private Date startMatdTime = null; 079 private Date endMatdTime = null; 080 private final int materializationWindow; 081 private int lastActionNumber = 1; // over-ride by DB value 082 private CoordinatorJob.Status prevStatus = null; 083 084 static final private int lookAheadWindow = ConfigurationService.getInt(CoordMaterializeTriggerService 085 .CONF_LOOKUP_INTERVAL); 086 087 /** 088 * Default MAX timeout in minutes, after which coordinator input check will timeout 089 */ 090 public static final String CONF_DEFAULT_MAX_TIMEOUT = Service.CONF_PREFIX + "coord.default.max.timeout"; 091 092 /** 093 * The constructor for class {@link CoordMaterializeTransitionXCommand} 094 * 095 * @param jobId coordinator job id 096 * @param materializationWindow materialization window to calculate end time 097 */ 098 public CoordMaterializeTransitionXCommand(String jobId, int materializationWindow) { 099 super("coord_mater", "coord_mater", 1); 100 this.jobId = ParamChecker.notEmpty(jobId, "jobId"); 101 this.materializationWindow = materializationWindow; 102 } 103 104 public CoordMaterializeTransitionXCommand(CoordinatorJobBean coordJob, int materializationWindow, Date startTime, 105 Date endTime) { 106 super("coord_mater", "coord_mater", 1); 107 this.jobId = ParamChecker.notEmpty(coordJob.getId(), "jobId"); 108 this.materializationWindow = materializationWindow; 109 this.coordJob = coordJob; 110 this.startMatdTime = startTime; 111 this.endMatdTime = endTime; 112 } 113 114 /* (non-Javadoc) 115 * @see org.apache.oozie.command.MaterializeTransitionXCommand#transitToNext() 116 */ 117 @Override 118 public void transitToNext() throws CommandException { 119 } 120 121 /* (non-Javadoc) 122 * @see org.apache.oozie.command.TransitionXCommand#updateJob() 123 */ 124 @Override 125 public void updateJob() throws CommandException { 126 updateList.add(new UpdateEntry(CoordJobQuery.UPDATE_COORD_JOB_MATERIALIZE,coordJob)); 127 } 128 129 /* (non-Javadoc) 130 * @see org.apache.oozie.command.MaterializeTransitionXCommand#performWrites() 131 */ 132 @Override 133 public void performWrites() throws CommandException { 134 try { 135 BatchQueryExecutor.getInstance().executeBatchInsertUpdateDelete(insertList, updateList, null); 136 // register the partition related dependencies of actions 137 for (JsonBean actionBean : insertList) { 138 if (actionBean instanceof CoordinatorActionBean) { 139 CoordinatorActionBean coordAction = (CoordinatorActionBean) actionBean; 140 if (EventHandlerService.isEnabled()) { 141 CoordinatorXCommand.generateEvent(coordAction, coordJob.getUser(), coordJob.getAppName(), null); 142 } 143 144 // TODO: time 100s should be configurable 145 queue(new CoordActionNotificationXCommand(coordAction), 100); 146 147 //Delay for input check = (nominal time - now) 148 long checkDelay = coordAction.getNominalTime().getTime() - new Date().getTime(); 149 queue(new CoordActionInputCheckXCommand(coordAction.getId(), coordAction.getJobId()), 150 Math.max(checkDelay, 0)); 151 152 if (!StringUtils.isEmpty(coordAction.getPushMissingDependencies())) { 153 // TODO: Delay in catchup mode? 154 queue(new CoordPushDependencyCheckXCommand(coordAction.getId(), true), 100); 155 } 156 } 157 } 158 } 159 catch (JPAExecutorException jex) { 160 throw new CommandException(jex); 161 } 162 } 163 164 /* (non-Javadoc) 165 * @see org.apache.oozie.command.XCommand#getEntityKey() 166 */ 167 @Override 168 public String getEntityKey() { 169 return this.jobId; 170 } 171 172 @Override 173 protected boolean isLockRequired() { 174 return true; 175 } 176 177 /* (non-Javadoc) 178 * @see org.apache.oozie.command.XCommand#loadState() 179 */ 180 @Override 181 protected void loadState() throws CommandException { 182 jpaService = Services.get().get(JPAService.class); 183 if (jpaService == null) { 184 LOG.error(ErrorCode.E0610); 185 } 186 187 try { 188 coordJob = CoordJobQueryExecutor.getInstance().get(CoordJobQuery.GET_COORD_JOB_MATERIALIZE, jobId); 189 prevStatus = coordJob.getStatus(); 190 } 191 catch (JPAExecutorException jex) { 192 throw new CommandException(jex); 193 } 194 195 // calculate start materialize and end materialize time 196 calcMatdTime(); 197 198 LogUtils.setLogInfo(coordJob); 199 } 200 201 /** 202 * Calculate startMatdTime and endMatdTime from job's start time if next materialized time is null 203 * 204 * @throws CommandException thrown if failed to calculate startMatdTime and endMatdTime 205 */ 206 protected void calcMatdTime() throws CommandException { 207 Timestamp startTime = coordJob.getNextMaterializedTimestamp(); 208 if (startTime == null) { 209 startTime = coordJob.getStartTimestamp(); 210 } 211 // calculate end time by adding materializationWindow to start time. 212 // need to convert materializationWindow from secs to milliseconds 213 long startTimeMilli = startTime.getTime(); 214 long endTimeMilli = startTimeMilli + (materializationWindow * 1000); 215 216 startMatdTime = DateUtils.toDate(new Timestamp(startTimeMilli)); 217 endMatdTime = DateUtils.toDate(new Timestamp(endTimeMilli)); 218 endMatdTime = getMaterializationTimeForCatchUp(endMatdTime); 219 // if MaterializationWindow end time is greater than endTime 220 // for job, then set it to endTime of job 221 Date jobEndTime = coordJob.getEndTime(); 222 if (endMatdTime.compareTo(jobEndTime) > 0) { 223 endMatdTime = jobEndTime; 224 } 225 226 LOG.debug("Materializing coord job id=" + jobId + ", start=" + DateUtils.formatDateOozieTZ(startMatdTime) + ", end=" 227 + DateUtils.formatDateOozieTZ(endMatdTime) 228 + ", window=" + materializationWindow); 229 } 230 231 /** 232 * Get materialization for window for catch-up jobs. for current jobs,it reruns currentMatdate, For catch-up, end 233 * Mataterilized Time = startMatdTime + MatThrottling * frequency; unless LAST_ONLY execution order is set, in which 234 * case it returns now (to materialize all actions in the past) 235 * 236 * @param currentMatTime 237 * @return Date returns materialization for window for catch-up jobs 238 * @throws CommandException 239 * @throws JDOMException 240 */ 241 private Date getMaterializationTimeForCatchUp(Date currentMatTime) throws CommandException { 242 if (currentMatTime.after(new Date())) { 243 return currentMatTime; 244 } 245 if (coordJob.getExecutionOrder().equals(CoordinatorJob.Execution.LAST_ONLY) || 246 coordJob.getExecutionOrder().equals(CoordinatorJob.Execution.NONE)) { 247 return new Date(); 248 } 249 final int frequency; 250 try { 251 frequency = Integer.parseInt(coordJob.getFrequency()); 252 } 253 catch (final NumberFormatException e) { 254 // Cron based frequency: catching up at maximum till the coordinator job's end time, 255 // bounded also by the throttle parameter, aka the number of coordinator actions to materialize 256 return coordJob.getEndTime(); 257 } 258 259 TimeZone appTz = DateUtils.getTimeZone(coordJob.getTimeZone()); 260 TimeUnit freqTU = TimeUnit.valueOf(coordJob.getTimeUnitStr()); 261 Calendar startInstance = Calendar.getInstance(appTz); 262 startInstance.setTime(startMatdTime); 263 Calendar endMatInstance = null; 264 Calendar previousInstance = startInstance; 265 for (int i = 1; i <= coordJob.getMatThrottling(); i++) { 266 endMatInstance = (Calendar) startInstance.clone(); 267 endMatInstance.add(freqTU.getCalendarUnit(), i * frequency); 268 if (endMatInstance.getTime().compareTo(new Date()) >= 0) { 269 if (previousInstance.getTime().after(currentMatTime)) { 270 return previousInstance.getTime(); 271 } 272 else { 273 return currentMatTime; 274 } 275 } 276 previousInstance = endMatInstance; 277 } 278 if (endMatInstance == null) { 279 return currentMatTime; 280 } 281 else { 282 return endMatInstance.getTime(); 283 } 284 } 285 286 /* (non-Javadoc) 287 * @see org.apache.oozie.command.XCommand#verifyPrecondition() 288 */ 289 @Override 290 protected void verifyPrecondition() throws CommandException, PreconditionException { 291 if (!(coordJob.getStatus() == CoordinatorJobBean.Status.PREP || coordJob.getStatus() == CoordinatorJobBean.Status.RUNNING 292 || coordJob.getStatus() == CoordinatorJobBean.Status.RUNNINGWITHERROR)) { 293 throw new PreconditionException(ErrorCode.E1100, "CoordMaterializeTransitionXCommand for jobId=" + jobId 294 + " job is not in PREP or RUNNING but in " + coordJob.getStatus()); 295 } 296 297 if (coordJob.isDoneMaterialization()) { 298 throw new PreconditionException(ErrorCode.E1100, "CoordMaterializeTransitionXCommand for jobId =" + jobId 299 + " job is already materialized"); 300 } 301 302 if (coordJob.getNextMaterializedTimestamp() != null 303 && coordJob.getNextMaterializedTimestamp().compareTo(coordJob.getEndTimestamp()) >= 0) { 304 throw new PreconditionException(ErrorCode.E1100, "CoordMaterializeTransitionXCommand for jobId=" + jobId 305 + " job is already materialized"); 306 } 307 308 Timestamp startTime = coordJob.getNextMaterializedTimestamp(); 309 if (startTime == null) { 310 startTime = coordJob.getStartTimestamp(); 311 312 if (startTime.after(new Timestamp(System.currentTimeMillis() + lookAheadWindow * 1000))) { 313 throw new PreconditionException(ErrorCode.E1100, "CoordMaterializeTransitionXCommand for jobId=" 314 + jobId + " job's start time is not reached yet - nothing to materialize"); 315 } 316 } 317 318 if (coordJob.getNextMaterializedTimestamp() != null 319 && coordJob.getNextMaterializedTimestamp().after( 320 new Timestamp(System.currentTimeMillis() + lookAheadWindow * 1000))) { 321 throw new PreconditionException(ErrorCode.E1100, "CoordMaterializeTransitionXCommand for jobId=" + jobId 322 + " Request is for future time. Lookup time is " 323 + new Timestamp(System.currentTimeMillis() + lookAheadWindow * 1000) + " mat time is " 324 + coordJob.getNextMaterializedTimestamp()); 325 } 326 327 if (coordJob.getLastActionTime() != null && coordJob.getLastActionTime().compareTo(coordJob.getEndTime()) >= 0) { 328 throw new PreconditionException(ErrorCode.E1100, "ENDED Coordinator materialization for jobId = " + jobId 329 + ", all actions have been materialized from start time = " + coordJob.getStartTime() 330 + " to end time = " + coordJob.getEndTime() + ", job status = " + coordJob.getStatusStr()); 331 } 332 333 if (coordJob.getLastActionTime() != null && coordJob.getLastActionTime().compareTo(endMatdTime) >= 0) { 334 throw new PreconditionException(ErrorCode.E1100, "ENDED Coordinator materialization for jobId = " + jobId 335 + ", action is *already* materialized for Materialization start time = " + startMatdTime 336 + ", materialization end time = " + endMatdTime + ", job status = " + coordJob.getStatusStr()); 337 } 338 339 if (endMatdTime.after(coordJob.getEndTime())) { 340 throw new PreconditionException(ErrorCode.E1100, "ENDED Coordinator materialization for jobId = " + jobId 341 + " materialization end time = " + endMatdTime + " surpasses coordinator job's end time = " 342 + coordJob.getEndTime() + " job status = " + coordJob.getStatusStr()); 343 } 344 345 if (coordJob.getPauseTime() != null && !startMatdTime.before(coordJob.getPauseTime())) { 346 throw new PreconditionException(ErrorCode.E1100, "ENDED Coordinator materialization for jobId = " + jobId 347 + ", materialization start time = " + startMatdTime 348 + " is after or equal to coordinator job's pause time = " + coordJob.getPauseTime() 349 + ", job status = " + coordJob.getStatusStr()); 350 } 351 352 } 353 354 /* (non-Javadoc) 355 * @see org.apache.oozie.command.MaterializeTransitionXCommand#materialize() 356 */ 357 @Override 358 protected void materialize() throws CommandException { 359 Instrumentation.Cron cron = new Instrumentation.Cron(); 360 cron.start(); 361 try { 362 materializeActions(false); 363 updateJobMaterializeInfo(coordJob); 364 } 365 catch (CommandException ex) { 366 LOG.warn("Exception occurred:" + ex.getMessage() + " Making the job failed ", ex); 367 coordJob.setStatus(Job.Status.FAILED); 368 coordJob.resetPending(); 369 // remove any materialized actions and slaEvents 370 insertList.clear(); 371 } 372 catch (Exception e) { 373 LOG.error("Exception occurred:" + e.getMessage() + " Making the job failed ", e); 374 coordJob.setStatus(Job.Status.FAILED); 375 try { 376 CoordJobQueryExecutor.getInstance().executeUpdate(CoordJobQuery.UPDATE_COORD_JOB_MATERIALIZE, coordJob); 377 } 378 catch (JPAExecutorException jex) { 379 throw new CommandException(ErrorCode.E1011, jex); 380 } 381 throw new CommandException(ErrorCode.E1012, e.getMessage(), e); 382 } finally { 383 cron.stop(); 384 instrumentation.addCron(INSTRUMENTATION_GROUP, getName() + ".materialize", cron); 385 } 386 } 387 388 /** 389 * Create action instances starting from "startMatdTime" to "endMatdTime" and store them into coord action table. 390 * 391 * @param dryrun if this is a dry run 392 * @throws Exception thrown if failed to materialize actions 393 */ 394 protected String materializeActions(boolean dryrun) throws Exception { 395 396 Configuration jobConf = null; 397 try { 398 jobConf = new XConfiguration(new StringReader(coordJob.getConf())); 399 } 400 catch (IOException ioe) { 401 LOG.warn("Configuration parse error. read from DB :" + coordJob.getConf(), ioe); 402 throw new CommandException(ErrorCode.E1005, ioe.getMessage(), ioe); 403 } 404 405 String jobXml = coordJob.getJobXml(); 406 Element eJob = XmlUtils.parseXml(jobXml); 407 TimeZone appTz = DateUtils.getTimeZone(coordJob.getTimeZone()); 408 409 String frequency = coordJob.getFrequency(); 410 TimeUnit freqTU = TimeUnit.valueOf(coordJob.getTimeUnitStr()); 411 TimeUnit endOfFlag = TimeUnit.valueOf(eJob.getAttributeValue("end_of_duration")); 412 Calendar start = Calendar.getInstance(appTz); 413 start.setTime(startMatdTime); 414 DateUtils.moveToEnd(start, endOfFlag); 415 Calendar end = Calendar.getInstance(appTz); 416 end.setTime(endMatdTime); 417 lastActionNumber = coordJob.getLastActionNumber(); 418 //Intentionally printing dates in their own timezone, not Oozie timezone 419 LOG.info("materialize actions for tz=" + appTz.getDisplayName() + ",\n start=" + start.getTime() + ", end=" 420 + end.getTime() + ",\n timeUnit " + freqTU.getCalendarUnit() + ",\n frequency :" + frequency + ":" 421 + freqTU + ",\n lastActionNumber " + lastActionNumber); 422 // Keep the actual start time 423 Calendar origStart = Calendar.getInstance(appTz); 424 origStart.setTime(coordJob.getStartTimestamp()); 425 // Move to the End of duration, if needed. 426 DateUtils.moveToEnd(origStart, endOfFlag); 427 428 StringBuilder actionStrings = new StringBuilder(); 429 Date jobPauseTime = coordJob.getPauseTime(); 430 Calendar pause = null; 431 if (jobPauseTime != null) { 432 pause = Calendar.getInstance(appTz); 433 pause.setTime(DateUtils.convertDateToTimestamp(jobPauseTime)); 434 } 435 436 String action = null; 437 int numWaitingActions = dryrun ? 0 : jpaService.execute(new CoordActionsActiveCountJPAExecutor(coordJob.getId())); 438 int maxActionToBeCreated = coordJob.getMatThrottling() - numWaitingActions; 439 // If LAST_ONLY and all materialization is in the past, ignore maxActionsToBeCreated 440 boolean ignoreMaxActions = 441 (coordJob.getExecutionOrder().equals(CoordinatorJob.Execution.LAST_ONLY) || 442 coordJob.getExecutionOrder().equals(CoordinatorJob.Execution.NONE)) 443 && endMatdTime.before(new Date()); 444 LOG.debug("Coordinator job :" + coordJob.getId() + ", maxActionToBeCreated :" + maxActionToBeCreated 445 + ", Mat_Throttle :" + coordJob.getMatThrottling() + ", numWaitingActions :" + numWaitingActions); 446 447 boolean isCronFrequency = false; 448 449 Calendar effStart = (Calendar) start.clone(); 450 try { 451 int intFrequency = Integer.parseInt(coordJob.getFrequency()); 452 effStart = (Calendar) origStart.clone(); 453 effStart.add(freqTU.getCalendarUnit(), lastActionNumber * intFrequency); 454 } 455 catch (NumberFormatException e) { 456 isCronFrequency = true; 457 } 458 459 boolean firstMater = true; 460 461 end = new DaylightOffsetCalculator(startMatdTime, endMatdTime).calculate(appTz, end); 462 463 while (effStart.compareTo(end) < 0 && (ignoreMaxActions || maxActionToBeCreated-- > 0)) { 464 if (pause != null && effStart.compareTo(pause) >= 0) { 465 break; 466 } 467 468 Date nextTime = effStart.getTime(); 469 470 if (isCronFrequency) { 471 if (effStart.getTime().compareTo(startMatdTime) == 0 && firstMater) { 472 effStart.add(Calendar.MINUTE, -1); 473 firstMater = false; 474 } 475 476 nextTime = CoordCommandUtils.getNextValidActionTimeForCronFrequency(effStart.getTime(), coordJob); 477 effStart.setTime(nextTime); 478 } 479 480 if (effStart.compareTo(end) < 0) { 481 482 if (pause != null && effStart.compareTo(pause) >= 0) { 483 break; 484 } 485 CoordinatorActionBean actionBean = new CoordinatorActionBean(); 486 lastActionNumber++; 487 488 int timeout = coordJob.getTimeout(); 489 LOG.debug("Materializing action for time=" + DateUtils.formatDateOozieTZ(effStart.getTime()) 490 + ", lastactionnumber=" + lastActionNumber + " timeout=" + timeout + " minutes"); 491 Date actualTime = new Date(); 492 action = CoordCommandUtils.materializeOneInstance(jobId, dryrun, (Element) eJob.clone(), 493 nextTime, actualTime, lastActionNumber, jobConf, actionBean); 494 actionBean.setTimeOut(timeout); 495 if (!dryrun) { 496 storeToDB(actionBean, action, jobConf); // Storing to table 497 498 } 499 else { 500 actionStrings.append("action for new instance"); 501 actionStrings.append(action); 502 } 503 } 504 else { 505 break; 506 } 507 508 if (!isCronFrequency) { 509 effStart = (Calendar) origStart.clone(); 510 effStart.add(freqTU.getCalendarUnit(), lastActionNumber * Integer.parseInt(coordJob.getFrequency())); 511 } 512 } 513 514 if (isCronFrequency) { 515 if (effStart.compareTo(end) < 0 && !(ignoreMaxActions || maxActionToBeCreated-- > 0)) { 516 //Since we exceed the throttle, we need to move the nextMadtime forward 517 //to avoid creating duplicate actions 518 if (!firstMater) { 519 effStart.setTime(CoordCommandUtils.getNextValidActionTimeForCronFrequency(effStart.getTime(), coordJob)); 520 } 521 } 522 } 523 524 endMatdTime = effStart.getTime(); 525 526 if (!dryrun) { 527 return action; 528 } 529 else { 530 return actionStrings.toString(); 531 } 532 } 533 534 private void storeToDB(CoordinatorActionBean actionBean, String actionXml, Configuration jobConf) throws Exception { 535 LOG.debug("In storeToDB() coord action id = " + actionBean.getId() + ", size of actionXml = " 536 + actionXml.length()); 537 actionBean.setActionXml(actionXml); 538 insertList.add(actionBean); 539 writeActionSlaRegistration(actionXml, actionBean, jobConf); 540 } 541 542 private void writeActionSlaRegistration(String actionXml, CoordinatorActionBean actionBean, Configuration jobConf) 543 throws Exception { 544 Element eAction = XmlUtils.parseXml(actionXml); 545 Element eSla = eAction.getChild("action", eAction.getNamespace()).getChild("info", eAction.getNamespace("sla")); 546 SLAEventBean slaEvent = SLADbOperations.createSlaRegistrationEvent(eSla, actionBean.getId(), 547 SlaAppType.COORDINATOR_ACTION, coordJob.getUser(), coordJob.getGroup(), LOG); 548 if (slaEvent != null) { 549 insertList.add(slaEvent); 550 } 551 // inserting into new table also 552 SLAOperations.createSlaRegistrationEvent(eSla, actionBean.getId(), actionBean.getJobId(), 553 AppType.COORDINATOR_ACTION, coordJob.getUser(), coordJob.getAppName(), LOG, false, 554 CoordUtils.isSlaAlertDisabled(actionBean, coordJob.getAppName(), jobConf)); 555 } 556 557 private void updateJobMaterializeInfo(CoordinatorJobBean job) throws CommandException { 558 job.setLastActionTime(endMatdTime); 559 job.setLastActionNumber(lastActionNumber); 560 // if the job endtime == action endtime, we don't need to materialize this job anymore 561 Date jobEndTime = job.getEndTime(); 562 563 564 if (job.getStatus() == CoordinatorJob.Status.PREP){ 565 LOG.info("[" + job.getId() + "]: Update status from " + job.getStatus() + " to RUNNING"); 566 job.setStatus(Job.Status.RUNNING); 567 } 568 job.setPending(); 569 Calendar end = Calendar.getInstance(); 570 end.setTime(jobEndTime); 571 572 end = calculateEndTimeWithDSTOffset(end); 573 574 if (end.getTime().compareTo(endMatdTime) <= 0) { 575 LOG.info("[" + job.getId() + "]: all actions have been materialized, set pending to true"); 576 // set doneMaterialization to true when materialization is done 577 job.setDoneMaterialization(); 578 } 579 job.setStatus(StatusUtils.getStatus(job)); 580 LOG.info("Coord Job status updated to = " + job.getStatus()); 581 job.setNextMaterializedTime(endMatdTime); 582 } 583 584 private Calendar calculateEndTimeWithDSTOffset(final Calendar endTime) { 585 final TimeZone appTz = DateUtils.getTimeZone(coordJob.getTimeZone()); 586 final Calendar start = Calendar.getInstance(appTz); 587 start.setTime(startMatdTime); 588 589 return new DaylightOffsetCalculator(startMatdTime, endMatdTime).calculate(appTz, endTime); 590 } 591 592 /* (non-Javadoc) 593 * @see org.apache.oozie.command.XCommand#getKey() 594 */ 595 @Override 596 public String getKey() { 597 return getName() + "_" + jobId; 598 } 599 600 /* (non-Javadoc) 601 * @see org.apache.oozie.command.TransitionXCommand#notifyParent() 602 */ 603 @Override 604 public void notifyParent() throws CommandException { 605 // update bundle action only when status changes in coord job 606 if (this.coordJob.getBundleId() != null) { 607 if (!prevStatus.equals(coordJob.getStatus())) { 608 BundleStatusUpdateXCommand bundleStatusUpdate = new BundleStatusUpdateXCommand(coordJob, prevStatus); 609 bundleStatusUpdate.call(); 610 } 611 } 612 } 613}