Repository: oozie Updated Branches: refs/heads/master 885676214 -> f6b3f0e8c
OOZIE-1703 User should be able to set coord end-time before start time (puru via rohini) Project: http://git-wip-us.apache.org/repos/asf/oozie/repo Commit: http://git-wip-us.apache.org/repos/asf/oozie/commit/f6b3f0e8 Tree: http://git-wip-us.apache.org/repos/asf/oozie/tree/f6b3f0e8 Diff: http://git-wip-us.apache.org/repos/asf/oozie/diff/f6b3f0e8 Branch: refs/heads/master Commit: f6b3f0e8c38e185b34bc2cd3b4f16533cfa505fc Parents: 8856762 Author: Rohini Palaniswamy <[email protected]> Authored: Tue Apr 15 10:25:22 2014 -0700 Committer: Rohini Palaniswamy <[email protected]> Committed: Tue Apr 15 10:25:22 2014 -0700 ---------------------------------------------------------------------- .../command/coord/CoordChangeXCommand.java | 170 ++++++++--------- .../TestCoordActionInputCheckXCommand.java | 2 +- .../command/coord/TestCoordChangeXCommand.java | 181 +++++++++++++++---- .../org/apache/oozie/test/XDataTestCase.java | 43 ++++- docs/src/site/twiki/DG_CommandLineTool.twiki | 22 ++- release-log.txt | 1 + 6 files changed, 273 insertions(+), 146 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/oozie/blob/f6b3f0e8/core/src/main/java/org/apache/oozie/command/coord/CoordChangeXCommand.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/oozie/command/coord/CoordChangeXCommand.java b/core/src/main/java/org/apache/oozie/command/coord/CoordChangeXCommand.java index 5ecd5d5..fb31e9a 100644 --- a/core/src/main/java/org/apache/oozie/command/coord/CoordChangeXCommand.java +++ b/core/src/main/java/org/apache/oozie/command/coord/CoordChangeXCommand.java @@ -18,14 +18,12 @@ package org.apache.oozie.command.coord; import java.util.ArrayList; -import java.util.Calendar; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - import org.apache.commons.lang.StringUtils; import org.apache.oozie.CoordinatorActionBean; import org.apache.oozie.CoordinatorJobBean; @@ -34,13 +32,11 @@ import org.apache.oozie.XException; import org.apache.oozie.client.CoordinatorAction; import org.apache.oozie.client.CoordinatorJob; import org.apache.oozie.client.Job; -import org.apache.oozie.client.Job.Status; import org.apache.oozie.client.OozieClient; import org.apache.oozie.client.rest.JsonBean; import org.apache.oozie.command.CommandException; import org.apache.oozie.command.PreconditionException; import org.apache.oozie.command.bundle.BundleStatusUpdateXCommand; -import org.apache.oozie.coord.TimeUnit; import org.apache.oozie.executor.jpa.CoordActionGetJPAExecutor; import org.apache.oozie.executor.jpa.CoordJobGetActionByActionNumberJPAExecutor; import org.apache.oozie.executor.jpa.CoordJobGetJPAExecutor; @@ -170,21 +166,6 @@ public class CoordChangeXCommand extends CoordinatorXCommand<Void> { } /** - * Returns the actual last action time(one instance before coordJob.lastActionTime) - * @return Date - last action time if coordJob.getLastActionTime() is not null, null otherwise - */ - private Date getLastActionTime() { - if(coordJob.getLastActionTime() == null) - return null; - - Calendar d = Calendar.getInstance(DateUtils.getTimeZone(coordJob.getTimeZone())); - d.setTime(coordJob.getLastActionTime()); - TimeUnit timeUnit = TimeUnit.valueOf(coordJob.getTimeUnitStr()); - d.add(timeUnit.getCalendarUnit(), -Integer.valueOf(coordJob.getFrequency())); - return d.getTime(); - } - - /** * Check if new end time is valid. * * @param coordJob coordinator job id. @@ -192,21 +173,7 @@ public class CoordChangeXCommand extends CoordinatorXCommand<Void> { * @throws CommandException thrown if new end time is not valid. */ private void checkEndTime(CoordinatorJobBean coordJob, Date newEndTime) throws CommandException { - // New endTime cannot be before coordinator job's start time. - Date startTime = coordJob.getStartTime(); - if (newEndTime.before(startTime)) { - throw new CommandException(ErrorCode.E1015, newEndTime, "cannot be before coordinator job's start time [" - + startTime + "]"); - } - - // New endTime cannot be before coordinator job's last action time. - Date lastActionTime = getLastActionTime(); - if (lastActionTime != null) { - if (!newEndTime.after(lastActionTime)) { - throw new CommandException(ErrorCode.E1015, newEndTime, - "must be after coordinator job's last action time [" + lastActionTime + "]"); - } - } + //It's ok to set end date before start date. } /** @@ -220,8 +187,7 @@ public class CoordChangeXCommand extends CoordinatorXCommand<Void> { private void checkPauseTime(CoordinatorJobBean coordJob, Date newPauseTime) throws CommandException { // New pauseTime has to be a non-past time. - Date d = new Date(); - if (newPauseTime.before(d)) { + if (newPauseTime.before(coordJob.getStartTime())) { throw new CommandException(ErrorCode.E1015, newPauseTime, "must be a non-past time"); } } @@ -253,39 +219,24 @@ public class CoordChangeXCommand extends CoordinatorXCommand<Void> { * * @param coordJob coordinator job * @param newPauseTime new pause time + * @throws JPAExecutorException, CommandException */ - private void processLookaheadActions(CoordinatorJobBean coordJob, Date newPauseTime) throws CommandException { - Date lastActionTime = coordJob.getLastActionTime(); + private void processLookaheadActions(CoordinatorJobBean coordJob, Date newTime) throws CommandException, + JPAExecutorException { + int lastActionNumber = coordJob.getLastActionNumber(); + Date lastActionTime = null; + Date tempDate = null; + + while ((tempDate = deleteAction(lastActionNumber, newTime)) != null) { + lastActionNumber--; + lastActionTime = tempDate; + } if (lastActionTime != null) { - // d is the real last action time. - Calendar d = Calendar.getInstance(DateUtils.getTimeZone(coordJob.getTimeZone())); - d.setTime(getLastActionTime()); - TimeUnit timeUnit = TimeUnit.valueOf(coordJob.getTimeUnitStr()); - - int lastActionNumber = coordJob.getLastActionNumber(); - - boolean hasChanged = false; - while (true) { - if (!newPauseTime.after(d.getTime())) { - deleteAction(lastActionNumber); - d.add(timeUnit.getCalendarUnit(), -Integer.valueOf(coordJob.getFrequency())); - lastActionNumber = lastActionNumber - 1; - - hasChanged = true; - } - else { - break; - } - } - - if (hasChanged == true) { - coordJob.setLastActionNumber(lastActionNumber); - d.add(timeUnit.getCalendarUnit(), Integer.valueOf(coordJob.getFrequency())); - Date d1 = d.getTime(); - coordJob.setLastActionTime(d1); - coordJob.setNextMaterializedTime(d1); - coordJob.resetDoneMaterialization(); - } + LOG.debug("New pause/end date is : " + newTime + " and last action number is : " + lastActionNumber); + coordJob.setLastActionNumber(lastActionNumber); + coordJob.setLastActionTime(lastActionTime); + coordJob.setNextMaterializedTime(lastActionTime); + coordJob.resetDoneMaterialization(); } } @@ -294,31 +245,42 @@ public class CoordChangeXCommand extends CoordinatorXCommand<Void> { * * @param actionNum coordinator action number */ - private void deleteAction(int actionNum) throws CommandException { + private Date deleteAction(int actionNum, Date afterDate) throws CommandException { try { + if (actionNum <= 0) { + return null; + } + String actionId = jpaService.execute(new CoordJobGetActionByActionNumberJPAExecutor(jobId, actionNum)); CoordinatorActionBean bean = jpaService.execute(new CoordActionGetJPAExecutor(actionId)); - // delete SLA registration entry (if any) for action - if (SLAService.isEnabled()) { - Services.get().get(SLAService.class).removeRegistration(actionId); - } - SLARegistrationBean slaReg = jpaService.execute(new SLARegistrationGetJPAExecutor(actionId)); - if (slaReg != null) { - LOG.debug("Deleting registration bean corresponding to action " + slaReg.getId()); - deleteList.add(slaReg); - } - SLASummaryBean slaSummaryBean = jpaService.execute(new SLASummaryGetJPAExecutor(actionId)); - if (slaSummaryBean != null) { - LOG.debug("Deleting summary bean corresponding to action " + slaSummaryBean.getId()); - deleteList.add(slaSummaryBean); - } - if (bean.getStatus() == CoordinatorAction.Status.WAITING - || bean.getStatus() == CoordinatorAction.Status.READY) { - deleteList.add(bean); + if (afterDate.compareTo(bean.getNominalTime()) <= 0) { + // delete SLA registration entry (if any) for action + if (SLAService.isEnabled()) { + Services.get().get(SLAService.class).removeRegistration(actionId); + } + SLARegistrationBean slaReg = jpaService.execute(new SLARegistrationGetJPAExecutor(actionId)); + if (slaReg != null) { + LOG.debug("Deleting registration bean corresponding to action " + slaReg.getId()); + deleteList.add(slaReg); + } + SLASummaryBean slaSummaryBean = jpaService.execute(new SLASummaryGetJPAExecutor(actionId)); + if (slaSummaryBean != null) { + LOG.debug("Deleting summary bean corresponding to action " + slaSummaryBean.getId()); + deleteList.add(slaSummaryBean); + } + if (bean.getStatus() == CoordinatorAction.Status.WAITING + || bean.getStatus() == CoordinatorAction.Status.READY) { + deleteList.add(bean); + } + else { + throw new CommandException(ErrorCode.E1022, bean.getId()); + } + return bean.getNominalTime(); } else { - throw new CommandException(ErrorCode.E1022, bean.getId()); + return null; } + } catch (JPAExecutorException e) { throw new CommandException(e); @@ -374,19 +336,33 @@ public class CoordChangeXCommand extends CoordinatorXCommand<Void> { && coordJob.getNextMaterializedTime().after(newEndTime); if (!dontChange) { coordJob.setEndTime(newEndTime); - if (coordJob.getStatus() == CoordinatorJob.Status.SUCCEEDED) { - coordJob.setStatus(CoordinatorJob.Status.RUNNING); + // OOZIE-1703, we should SUCCEEDED the coord, if it's in PREP and new endtime is before start time + if (coordJob.getStatus() == CoordinatorJob.Status.PREP && coordJob.getStartTime().after(newEndTime)) { + LOG.info("Changing coord status to SUCCEEDED, because it's in PREP and new end time is before start time. " + + "Startime is " + coordJob.getStartTime() + " and new end time is " + newEndTime); + coordJob.setStatus(CoordinatorJob.Status.SUCCEEDED); + coordJob.setDoneMaterialization(); + coordJob.resetPending(); } - if (coordJob.getStatus() == CoordinatorJob.Status.DONEWITHERROR - || coordJob.getStatus() == CoordinatorJob.Status.FAILED) { - // Check for backward compatibility for Oozie versions (3.2 and before) - // when RUNNINGWITHERROR, SUSPENDEDWITHERROR and - // PAUSEDWITHERROR is not supported - coordJob.setStatus(StatusUtils - .getStatusIfBackwardSupportTrue(CoordinatorJob.Status.RUNNINGWITHERROR)); + else { + //move it to running iff neendtime is after starttime. + if (newEndTime.after(coordJob.getStartTime())) { + if (coordJob.getStatus() == CoordinatorJob.Status.SUCCEEDED) { + coordJob.setStatus(CoordinatorJob.Status.RUNNING); + } + if (coordJob.getStatus() == CoordinatorJob.Status.DONEWITHERROR + || coordJob.getStatus() == CoordinatorJob.Status.FAILED) { + // Check for backward compatibility for Oozie versions (3.2 and before) + // when RUNNINGWITHERROR, SUSPENDEDWITHERROR and + // PAUSEDWITHERROR is not supported + coordJob.setStatus(StatusUtils + .getStatusIfBackwardSupportTrue(CoordinatorJob.Status.RUNNINGWITHERROR)); + } + coordJob.setPending(); + coordJob.resetDoneMaterialization(); + processLookaheadActions(coordJob, newEndTime); + } } - coordJob.setPending(); - coordJob.resetDoneMaterialization(); } } http://git-wip-us.apache.org/repos/asf/oozie/blob/f6b3f0e8/core/src/test/java/org/apache/oozie/command/coord/TestCoordActionInputCheckXCommand.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/oozie/command/coord/TestCoordActionInputCheckXCommand.java b/core/src/test/java/org/apache/oozie/command/coord/TestCoordActionInputCheckXCommand.java index d1c5752..ebf5081 100644 --- a/core/src/test/java/org/apache/oozie/command/coord/TestCoordActionInputCheckXCommand.java +++ b/core/src/test/java/org/apache/oozie/command/coord/TestCoordActionInputCheckXCommand.java @@ -809,7 +809,7 @@ public class TestCoordActionInputCheckXCommand extends XDataTestCase { protected CoordinatorActionBean addRecordToCoordActionTableForWaiting(String jobId, int actionNum, CoordinatorAction.Status status, String resourceXmlName) throws Exception { - CoordinatorActionBean action = createCoordAction(jobId, actionNum, status, resourceXmlName, 0, TZ); + CoordinatorActionBean action = createCoordAction(jobId, actionNum, status, resourceXmlName, 0, TZ, null); String missDeps = getTestCaseFileUri("2009/01/29/_SUCCESS") + "#" + getTestCaseFileUri("2009/01/22/_SUCCESS") + "#" + getTestCaseFileUri("2009/01/15/_SUCCESS") + "#" http://git-wip-us.apache.org/repos/asf/oozie/blob/f6b3f0e8/core/src/test/java/org/apache/oozie/command/coord/TestCoordChangeXCommand.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/oozie/command/coord/TestCoordChangeXCommand.java b/core/src/test/java/org/apache/oozie/command/coord/TestCoordChangeXCommand.java index fdc0a55..327ec90 100644 --- a/core/src/test/java/org/apache/oozie/command/coord/TestCoordChangeXCommand.java +++ b/core/src/test/java/org/apache/oozie/command/coord/TestCoordChangeXCommand.java @@ -196,12 +196,9 @@ public class TestCoordChangeXCommand extends XDataTestCase { try { new CoordChangeXCommand(jobId, "endtime=1900-12-20T05:00Z").call(); - fail("Should not reach here."); } catch (CommandException ex) { - if (ex.getErrorCode() != ErrorCode.E1015) { - fail("Error code should be E1015."); - } + fail("Should not throw exception"); } try { @@ -215,7 +212,7 @@ public class TestCoordChangeXCommand extends XDataTestCase { } try { - new CoordChangeXCommand(jobId, "pausetime=2009-02-01T01:03Z").call(); + new CoordChangeXCommand(jobId, "pausetime=2009-02-01T00:00Z").call(); fail("Should not reach here."); } catch (CommandException ex) { @@ -235,7 +232,7 @@ public class TestCoordChangeXCommand extends XDataTestCase { } try { - new CoordChangeXCommand(jobId, "pausetime=2009-02-01T01:08Z").call(); + new CoordChangeXCommand(jobId, "pausetime=2009-02-01T00:08Z").call(); fail("Should not reach here."); } catch (CommandException ex) { @@ -398,14 +395,123 @@ public class TestCoordChangeXCommand extends XDataTestCase { assertTrue(coordJob.isDoneMaterialization()); String newEndTime = convertDateToString(startTime.getTime() + 20 * 60 * 1000); - new CoordChangeXCommand(coordJob.getId(), "endtime=" + newEndTime).call(); - coordJob = jpaService.execute(coordGetCmd); assertFalse(Job.Status.RUNNING == coordJob.getStatus()); assertFalse(coordJob.isPending()); assertTrue(coordJob.isDoneMaterialization()); + } + + // Testcase to test deletion of lookahead action in case of end-date change + public void testCoordChangeEndTimeDeleteAction() throws Exception { + Date startTime = DateUtils.parseDateOozieTZ("2013-08-01T00:00Z"); + Date endTime = DateUtils.parseDateOozieTZ("2013-08-01T05:00Z"); + Date changeEndTime = DateUtils.parseDateOozieTZ("2013-08-01T02:00Z"); + String endTimeChangeStr = "endtime=" + DateUtils.formatDateOozieTZ(changeEndTime); + final CoordinatorJobBean job = addRecordToCoordJobTableForPauseTimeTest(CoordinatorJob.Status.RUNNING, + startTime, endTime, endTime, true, false, 4); + addRecordToCoordActionTable(job.getId(), 1, CoordinatorAction.Status.SUCCEEDED, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-01T00:00Z")); + addRecordToCoordActionTable(job.getId(), 2, CoordinatorAction.Status.RUNNING, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-01T01:00Z")); + addRecordToCoordActionTable(job.getId(), 3, CoordinatorAction.Status.WAITING, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-01T02:00Z")); + addRecordToCoordActionTable(job.getId(), 4, CoordinatorAction.Status.WAITING, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-01T03:00Z")); + JPAService jpaService = Services.get().get(JPAService.class); + new CoordChangeXCommand(job.getId(), endTimeChangeStr).call(); + CoordJobGetJPAExecutor coordGetCmd = new CoordJobGetJPAExecutor(job.getId()); + CoordinatorJobBean coordJob = jpaService.execute(coordGetCmd); + assertEquals(coordJob.getEndTime(), changeEndTime); + assertEquals(Job.Status.RUNNING, coordJob.getStatus()); + assertEquals(2, coordJob.getLastActionNumber()); + try { + jpaService.execute(new CoordJobGetActionByActionNumberJPAExecutor(job.getId(), 2)); + } + catch (JPAExecutorException jpae) { + fail(" Action should be there"); + } + try { + jpaService.execute(new CoordJobGetActionByActionNumberJPAExecutor(job.getId(), 3)); + fail("Expected to fail as action 3 should have been deleted"); + } + catch (JPAExecutorException jpae) { + assertEquals(ErrorCode.E0603, jpae.getErrorCode()); + } + assertEquals(DateUtils.parseDateOozieTZ("2013-08-01T02:00Z"), coordJob.getNextMaterializedTime()); + assertEquals(DateUtils.parseDateOozieTZ("2013-08-01T02:00Z"), coordJob.getLastActionTime()); + } + + // Testcase to test deletion of lookahead action in case of end-date change + // Added one more test case to test processLookaheadActions with day frequency and SUSPENDED status. + public void testProcessLookaheadActions() throws Exception { + Date startTime = DateUtils.parseDateOozieTZ("2013-08-01T00:00Z"); + Date endTime = DateUtils.parseDateOozieTZ("2013-08-29T00:00Z"); + + Date changeEndTime = DateUtils.parseDateOozieTZ("2013-08-05T00:00Z"); + String endTimeChangeStr = "endtime=" + DateUtils.formatDateOozieTZ(changeEndTime); + final CoordinatorJobBean job = addRecordToCoordJobTableForPauseTimeTest(CoordinatorJob.Status.SUSPENDED, + startTime, endTime, endTime, true, false, 6); + addRecordToCoordActionTable(job.getId(), 1, CoordinatorAction.Status.SUCCEEDED, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-01T00:00Z")); + addRecordToCoordActionTable(job.getId(), 2, CoordinatorAction.Status.RUNNING, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-02T00:00Z")); + addRecordToCoordActionTable(job.getId(), 3, CoordinatorAction.Status.WAITING, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-03T00:00Z")); + addRecordToCoordActionTable(job.getId(), 4, CoordinatorAction.Status.WAITING, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-04T00:00Z")); + addRecordToCoordActionTable(job.getId(), 5, CoordinatorAction.Status.WAITING, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-05T00:00Z")); + addRecordToCoordActionTable(job.getId(), 6, CoordinatorAction.Status.WAITING, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-06T00:00Z")); + + job.setFrequency("1"); + job.setTimeUnit(Timeunit.DAY); + CoordJobQueryExecutor.getInstance().executeUpdate(CoordJobQuery.UPDATE_COORD_JOB, job); + + JPAService jpaService = Services.get().get(JPAService.class); + new CoordChangeXCommand(job.getId(), endTimeChangeStr).call(); + + CoordJobGetJPAExecutor coordGetCmd = new CoordJobGetJPAExecutor(job.getId()); + CoordinatorJobBean coordJob = jpaService.execute(coordGetCmd); + assertEquals(coordJob.getEndTime(), changeEndTime); + assertEquals(Job.Status.SUSPENDED, coordJob.getStatus()); + assertEquals(4, coordJob.getLastActionNumber()); + assertEquals(DateUtils.parseDateOozieTZ("2013-08-05T00:00Z"), coordJob.getNextMaterializedTime()); + assertEquals(DateUtils.parseDateOozieTZ("2013-08-05T00:00Z"), coordJob.getLastActionTime()); + assertEquals(changeEndTime, coordJob.getEndTime()); + } + + // Testcase to check status for coord whose enddate is set before startdate. + public void testCoordChangeEndTimeBeforeStart() throws Exception { + Date start = new Date(); + Date end = new Date(start.getTime() + (4 * 60 * 60 * 1000)); // 4 hrs + Date endTime = new Date(start.getTime() - 3000); + String endTimeChangeStr = "endtime=" + DateUtils.formatDateOozieTZ(endTime); + final CoordinatorJobBean job = addRecordToCoordJobTableForPauseTimeTest(CoordinatorJob.Status.PREP, start, end, + end, true, false, 0); + + JPAService jpaService = Services.get().get(JPAService.class); + CoordJobGetJPAExecutor coordGetCmd = new CoordJobGetJPAExecutor(job.getId()); + CoordinatorJobBean coordJob = jpaService.execute(coordGetCmd); + + assertEquals(Job.Status.PREP, coordJob.getStatus()); + assertEquals(0, coordJob.getLastActionNumber()); + + new CoordChangeXCommand(job.getId(), endTimeChangeStr).call(); + + coordGetCmd = new CoordJobGetJPAExecutor(job.getId()); + coordJob = jpaService.execute(coordGetCmd); + assertEquals(DateUtils.formatDateOozieTZ(coordJob.getEndTime()), DateUtils.formatDateOozieTZ(endTime)); + assertEquals(Job.Status.SUCCEEDED, coordJob.getStatus()); + Date newEndTime = new Date(start.getTime() - 2000); + endTimeChangeStr = "endtime=" + DateUtils.formatDateOozieTZ(newEndTime); + new CoordChangeXCommand(job.getId(), endTimeChangeStr).call(); + coordGetCmd = new CoordJobGetJPAExecutor(job.getId()); + coordJob = jpaService.execute(coordGetCmd); + assertEquals(DateUtils.formatDateOozieTZ(coordJob.getEndTime()), DateUtils.formatDateOozieTZ(newEndTime)); + assertEquals(Job.Status.SUCCEEDED, coordJob.getStatus()); } /** @@ -442,20 +548,21 @@ public class TestCoordChangeXCommand extends XDataTestCase { * @throws Exception */ public void testCoordChangePauseTime() throws Exception { - Date start = new Date(); - Date end = new Date(start.getTime() + (4 * 60 * 60 * 1000)); //4 hrs - Date pauseTime = new Date(start.getTime() + (2 * 60 * 60 * 1000)); //2 hrs + Date startTime = DateUtils.parseDateOozieTZ("2013-08-01T00:00Z"); + Date endTime = DateUtils.parseDateOozieTZ("2013-08-01T04:59Z"); + + Date pauseTime = new Date(startTime.getTime() + (3 * 60 * 60 * 1000)); //2 hrs String pauseTimeChangeStr = "pausetime=" + DateUtils.formatDateOozieTZ(pauseTime); - final CoordinatorJobBean job = addRecordToCoordJobTableForPauseTimeTest(CoordinatorJob.Status.RUNNING, start, - end, end, true, false, 4); + final CoordinatorJobBean job = addRecordToCoordJobTableForPauseTimeTest(CoordinatorJob.Status.RUNNING, startTime, + endTime, endTime, true, false, 4); CoordinatorActionBean ca1 = addRecordToCoordActionTable(job.getId(), 1, CoordinatorAction.Status.SUCCEEDED, "coord-action-get.xml", 0); CoordinatorActionBean ca2 = addRecordToCoordActionTable(job.getId(), 2, CoordinatorAction.Status.SUCCEEDED, - "coord-action-get.xml", 0); + "coord-action-get.xml", 0, DateUtils.parseDateOozieTZ("2013-08-01T02:00Z")); CoordinatorActionBean ca3 = addRecordToCoordActionTable(job.getId(), 3, CoordinatorAction.Status.WAITING, - "coord-action-get.xml", 0); + "coord-action-get.xml", 0, DateUtils.parseDateOozieTZ("2013-08-01T03:00Z")); CoordinatorActionBean ca4 = addRecordToCoordActionTable(job.getId(), 4, CoordinatorAction.Status.WAITING, - "coord-action-get.xml", 0); + "coord-action-get.xml", 0, DateUtils.parseDateOozieTZ("2013-08-01T04:00Z")); SLARegistrationBean slaRegBean1 = new SLARegistrationBean(); slaRegBean1.setId(ca1.getId()); @@ -493,7 +600,6 @@ public class TestCoordChangeXCommand extends XDataTestCase { } catch (JPAExecutorException jpae) { assertEquals(ErrorCode.E0603, jpae.getErrorCode()); - jpae.printStackTrace(); } try { @@ -502,7 +608,6 @@ public class TestCoordChangeXCommand extends XDataTestCase { } catch (JPAExecutorException jpae) { assertEquals(ErrorCode.E0603, jpae.getErrorCode()); - jpae.printStackTrace(); } slaRegBean1 = jpaService.execute(new SLARegistrationGetJPAExecutor(slaRegBean1.getId())); @@ -519,24 +624,37 @@ public class TestCoordChangeXCommand extends XDataTestCase { assertNotNull(slaSummaryBean1); } - //Checks that RUNNING coord action is not deleted - public void testCoordActionDelete() throws Exception { - Date start = new Date(); - Date end = new Date(start.getTime() + (4 * 60 * 60 * 1000)); //4 hrs - Date pauseTime = new Date(start.getTime() + (2 * 60 * 60 * 1000)); //2 hrs + // Checks that RUNNING coord action is not deleted + public void testChangeTimeDeleteRunning() throws Exception { + Date startTime = DateUtils.parseDateOozieTZ("2013-08-01T00:00Z"); + Date endTime = DateUtils.parseDateOozieTZ("2013-08-01T04:59Z"); + Date pauseTime = new Date(startTime.getTime() + (2 * 60 * 60 * 1000)); // 2 hrs String pauseTimeChangeStr = "pausetime=" + DateUtils.formatDateOozieTZ(pauseTime); - final CoordinatorJobBean job = addRecordToCoordJobTableForPauseTimeTest(CoordinatorJob.Status.RUNNING, start, - end, end, true, false, 4); + final CoordinatorJobBean job = addRecordToCoordJobTableForPauseTimeTest(CoordinatorJob.Status.RUNNING, + startTime, endTime, endTime, true, false, 4); addRecordToCoordActionTable(job.getId(), 1, CoordinatorAction.Status.SUCCEEDED, "coord-action-get.xml", 0); - addRecordToCoordActionTable(job.getId(), 2, CoordinatorAction.Status.SUCCEEDED, "coord-action-get.xml", 0); - addRecordToCoordActionTable(job.getId(), 3, CoordinatorAction.Status.RUNNING, "coord-action-get.xml", 0); - addRecordToCoordActionTable(job.getId(), 4, CoordinatorAction.Status.WAITING, "coord-action-get.xml", 0); - + addRecordToCoordActionTable(job.getId(), 2, CoordinatorAction.Status.SUCCEEDED, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-01T02:00Z")); + addRecordToCoordActionTable(job.getId(), 3, CoordinatorAction.Status.RUNNING, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-01T03:00Z")); + addRecordToCoordActionTable(job.getId(), 4, CoordinatorAction.Status.WAITING, "coord-action-get.xml", 0, + DateUtils.parseDateOozieTZ("2013-08-01T04:00Z")); try { new CoordChangeXCommand(job.getId(), pauseTimeChangeStr).call(); fail("Should not reach here."); - } catch(CommandException e) { - if(e.getErrorCode() != ErrorCode.E1022) { + } + catch (CommandException e) { + if (e.getErrorCode() != ErrorCode.E1022) { + fail("Error code should be E1022"); + } + } + String endTimeChangeStr = "endtime=" + DateUtils.formatDateOozieTZ(pauseTime); + try { + new CoordChangeXCommand(job.getId(), endTimeChangeStr).call(); + fail("Should not reach here."); + } + catch (CommandException e) { + if (e.getErrorCode() != ErrorCode.E1022) { fail("Error code should be E1022"); } } @@ -640,7 +758,6 @@ public class TestCoordChangeXCommand extends XDataTestCase { assertTrue(e.getMessage().contains("Cannot change a killed coordinator job")); } } - protected CoordinatorJobBean addRecordToCoordJobTableForPauseTimeTest(CoordinatorJob.Status status, Date start, Date end, Date lastActionTime, boolean pending, boolean doneMatd, int lastActionNum) throws Exception { CoordinatorJobBean coordJob = createCoordJob(status, start, end, pending, doneMatd, lastActionNum); http://git-wip-us.apache.org/repos/asf/oozie/blob/f6b3f0e8/core/src/test/java/org/apache/oozie/test/XDataTestCase.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/oozie/test/XDataTestCase.java b/core/src/test/java/org/apache/oozie/test/XDataTestCase.java index 423944a..4f500da 100644 --- a/core/src/test/java/org/apache/oozie/test/XDataTestCase.java +++ b/core/src/test/java/org/apache/oozie/test/XDataTestCase.java @@ -512,7 +512,26 @@ public abstract class XDataTestCase extends XHCatTestCase { */ protected CoordinatorActionBean addRecordToCoordActionTable(String jobId, int actionNum, CoordinatorAction.Status status, String resourceXmlName, int pending) throws Exception { - CoordinatorActionBean action = createCoordAction(jobId, actionNum, status, resourceXmlName, pending); + return addRecordToCoordActionTable(jobId, actionNum, status, resourceXmlName, pending, null); + } + + /** + * Insert coord action for testing. + * + * @param jobId coord job id + * @param actionNum action number + * @param status coord action status + * @param resourceXmlName xml file name + * @param pending pending counter + * @param action nominal time + * @return coord action bean + * @throws Exception thrown if unable to create coord action bean + */ + protected CoordinatorActionBean addRecordToCoordActionTable(String jobId, int actionNum, + CoordinatorAction.Status status, String resourceXmlName, int pending, Date actionNominalTime) + throws Exception { + CoordinatorActionBean action = createCoordAction(jobId, actionNum, status, resourceXmlName, pending, + actionNominalTime); try { JPAService jpaService = Services.get().get(JPAService.class); @@ -569,9 +588,15 @@ public abstract class XDataTestCase extends XHCatTestCase { protected CoordinatorActionBean createCoordAction(String jobId, int actionNum, CoordinatorAction.Status status, String resourceXmlName, int pending) throws Exception { - return createCoordAction(jobId, actionNum, status, resourceXmlName, pending, "Z"); + return createCoordAction(jobId, actionNum, status, resourceXmlName, pending, "Z", null); } + protected CoordinatorActionBean createCoordAction(String jobId, int actionNum, CoordinatorAction.Status status, + String resourceXmlName, int pending, Date actionNominalTime) throws Exception { + return createCoordAction(jobId, actionNum, status, resourceXmlName, pending, "Z", actionNominalTime); + } + + /** * Create coord action bean * @@ -584,12 +609,11 @@ public abstract class XDataTestCase extends XHCatTestCase { * @throws Exception thrown if unable to create coord action bean */ protected CoordinatorActionBean createCoordAction(String jobId, int actionNum, CoordinatorAction.Status status, - String resourceXmlName, int pending, String oozieTimeZoneMask) throws Exception { + String resourceXmlName, int pending, String oozieTimeZoneMask, Date actionNominalTime) throws Exception { String actionId = Services.get().get(UUIDService.class).generateChildId(jobId, actionNum + ""); Path appPath = new Path(getFsTestCaseDir(), "coord"); String actionXml = getCoordActionXml(appPath, resourceXmlName); actionXml = actionXml.replace("${TZ}", oozieTimeZoneMask); - String actionNominalTime = getActionNominalTime(actionXml); CoordinatorActionBean action = new CoordinatorActionBean(); action.setId(actionId); @@ -598,7 +622,14 @@ public abstract class XDataTestCase extends XHCatTestCase { action.setActionNumber(actionNum); action.setPending(pending); try { - action.setNominalTime(DateUtils.parseDateOozieTZ(actionNominalTime)); + if (actionNominalTime == null) { + String nominalTime = getActionNominalTime(actionXml); + + action.setNominalTime(DateUtils.parseDateOozieTZ(nominalTime)); + } + else { + action.setNominalTime(actionNominalTime); + } } catch (Exception e) { e.printStackTrace(); @@ -1504,7 +1535,7 @@ public abstract class XDataTestCase extends XHCatTestCase { CoordinatorAction.Status status, String resourceXmlName, String missingDependencies, String pushMissingDependencies, String oozieTimeZoneMask) throws Exception { CoordinatorActionBean action = createCoordAction(jobId, actionNum, status, resourceXmlName, 0, - oozieTimeZoneMask); + oozieTimeZoneMask, null); action.setMissingDependencies(missingDependencies); action.setPushMissingDependencies(pushMissingDependencies); try { http://git-wip-us.apache.org/repos/asf/oozie/blob/f6b3f0e8/docs/src/site/twiki/DG_CommandLineTool.twiki ---------------------------------------------------------------------- diff --git a/docs/src/site/twiki/DG_CommandLineTool.twiki b/docs/src/site/twiki/DG_CommandLineTool.twiki index c1bd08a..5819b71 100644 --- a/docs/src/site/twiki/DG_CommandLineTool.twiki +++ b/docs/src/site/twiki/DG_CommandLineTool.twiki @@ -345,16 +345,18 @@ Valid value names are: * pausetime: the pause time of the coordinator job. * status: new status for coordinator job. -Repeated value names are not allowed. New end time must not be before job's start time and last action time. Currently status only -takes RUNNING and can be used to change the status of FAILED or KILLED coordinator job to RUNNING and resuming materialization. -This status change command does not affect the status of already materialized actions in the coordinator. If there are FAILED or -KILLED coordinator actions they have to be rerun separately. - -New concurrency value has to be a valid integer. All lookahead actions will be revoked according to the new pause time. Also empty string "" can be used to reset pause time to none. +Conditions and usage: + * Repeated value names are not allowed. + * New end time should not be before job's start time and last action time. + * If end time is before job start time and if the job has not materialized any actions, then job status is changed to SUCCEEDED. + * Currently status only takes RUNNING and can be used to change the status of FAILED or KILLED coordinator job to RUNNING and resuming materialization. This status change command does not affect the status of already materialized actions in the coordinator. If there are FAILED or KILLED coordinator actions they have to be rerun separately. + * New concurrency value has to be a valid integer. + * All lookahead actions which are in WAITING/READY state will be revoked according to the new pause/end time. If any action after new pause/end time is not in WAITING/READY state, an exception will be thrown. + * Also empty string "" can be used to reset pause time to none. After the command is executed the job's end time, concurrency or pause time should be changed. If an already-succeeded job changes its end time, its status will become running. ----+++ Changing pausetime of a Bundle Job +---+++ Changing endtime/pausetime of a Bundle Job Example: @@ -366,11 +368,11 @@ The =change= option changes a bundle job that is not in =KILLED= status. Valid value names are: * pausetime: the pause time of the bundle job. + * endtime: the end time of the bundle job. -Repeated value names are not allowed. An empty string "" can be used to reset pause time to none. - -After the command is executed the job's pause time should be changed. +Repeated value names are not allowed. An empty string "" can be used to reset pause time to none. New end time should not be before job's kickoff time. +Bundle will execute pause/end date change command on each coordinator job. Refer conditions and usage section of coordinator change command for more details [[DG_CommandLineTool#Changing_endtimeconcurrencypausetimestatus_of_a_Coordinator_Job][Coordinator job change command]]. ---+++ Rerunning a Workflow Job Example: http://git-wip-us.apache.org/repos/asf/oozie/blob/f6b3f0e8/release-log.txt ---------------------------------------------------------------------- diff --git a/release-log.txt b/release-log.txt index 3db5020..413932b 100644 --- a/release-log.txt +++ b/release-log.txt @@ -1,5 +1,6 @@ -- Oozie 4.1.0 release (trunk - unreleased) +OOZIE-1703 User should be able to set coord end-time before start time (puru via rohini) OOZIE-1719 v1/jobs api returns null for parentId even when it exists (ryota) OOZIE-1773 bulk API returns total = 0 when it's not (ryota) OOZIE-1774 Expected/Actual Duration on UI SLA Tab doesn't show correct information (ryota)
