From 77dcb75fb0bf9c03a591297519a97f2f3b69dbf0 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Wed, 05 Sep 2007 06:51:34 +0000
Subject: [PATCH] Implement support for delete and modify operations in the task backend as follows:
---
opends/src/messages/messages/backend.properties | 21 +
opends/tests/unit-tests-testng/src/server/org/opends/server/backends/task/TaskBackendTestCase.java | 409 +++++++++++++++++++++++++++++++
opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TasksTestCase.java | 30 ++
opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/DummyTask.java | 64 ++++
opends/src/server/org/opends/server/backends/task/TaskBackend.java | 208 +++++++++++----
5 files changed, 669 insertions(+), 63 deletions(-)
diff --git a/opends/src/messages/messages/backend.properties b/opends/src/messages/messages/backend.properties
index 3e6d6b1..00aee65 100644
--- a/opends/src/messages/messages/backend.properties
+++ b/opends/src/messages/messages/backend.properties
@@ -944,5 +944,22 @@
SEVERE_WARN_TRUSTSTORE_SET_PERMISSIONS_FAILED_328=Failed to set permissions \
on trust store file %s
SEVERE_ERR_ROOT_CONTAINER_NOT_INITIALIZED_329=The root container for backend \
- %s has not been initialized preventing this backend from processing the \
- requested operation
+ %s has not been initialized preventing this backend from processing the \
+ requested operation
+SEVERE_ERR_TASKBE_MODIFY_CANNOT_LOCK_ENTRY_330=Unable to obtain a write lock \
+ on entry %s
+SEVERE_ERR_TASKBE_MODIFY_INVALID_ENTRY_331=Entry %s cannot be modified \
+ because it does not represent a task entry. Only task entries may be \
+ modified in the task backend
+SEVERE_ERR_TASKBE_MODIFY_NO_SUCH_TASK_332=Entry %s cannot be modified because \
+ it does not represent a valid task in the server
+SEVERE_ERR_TASKBE_MODIFY_COMPLETED_333=Entry %s cannot be modified because \
+ the assoicated task has completed running. Completed tasks cannot be modified
+SEVERE_ERR_TASKBE_MODIFY_RECURRING_334=Entry %s cannot be modified because \
+ the server does not currently support modifying recurring task entries
+SEVERE_ERR_TASKBE_MODIFY_RUNNING_335=The task associated with entry %s is \
+ currently running. The only modification allowed for running tasks is to \
+ replace the value of the ds-task-state attribute with "cancel"
+INFO_TASKBE_RUNNING_TASK_CANCELLED_336=Task processing was interrupted by a \
+ modify request to cancel the task
+
diff --git a/opends/src/server/org/opends/server/backends/task/TaskBackend.java b/opends/src/server/org/opends/server/backends/task/TaskBackend.java
index f716e0e..afe3b7c 100644
--- a/opends/src/server/org/opends/server/backends/task/TaskBackend.java
+++ b/opends/src/server/org/opends/server/backends/task/TaskBackend.java
@@ -33,6 +33,7 @@
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.concurrent.locks.Lock;
@@ -495,57 +496,6 @@
/**
- * Indicates whether an entry with the specified DN exists in the backend.
- * The default implementation obtains a read lock and calls
- * <CODE>getEntry</CODE>, but backend implementations may override this with a
- * more efficient version that does not require a lock. The caller is not
- * required to hold any locks on the specified DN.
- *
- * @param entryDN The DN of the entry for which to determine existence.
- *
- * @return <CODE>true</CODE> if the specified entry exists in this backend,
- * or <CODE>false</CODE> if it does not.
- *
- * @throws DirectoryException If a problem occurs while trying to make the
- * determination.
- */
- public boolean entryExists(DN entryDN)
- throws DirectoryException
- {
- if (entryDN == null)
- {
- return false;
- }
-
- if (entryDN.equals(taskRootDN) || entryDN.equals(scheduledTaskParentDN) ||
- entryDN.equals(recurringTaskParentDN))
- {
- return true;
- }
-
- DN parentDN = entryDN.getParentDNInSuffix();
- if (parentDN == null)
- {
- return false;
- }
-
- if (parentDN.equals(scheduledTaskParentDN))
- {
- return (taskScheduler.getScheduledTaskEntry(entryDN) != null);
- }
- else if (parentDN.equals(recurringTaskParentDN))
- {
- return (taskScheduler.getRecurringTaskEntry(entryDN) != null);
- }
- else
- {
- return false;
- }
- }
-
-
-
- /**
* Adds the provided entry to this backend. This method must ensure that the
* entry is appropriate for the backend and that no entry already exists with
* the same DN.
@@ -701,10 +651,158 @@
public void replaceEntry(Entry entry, ModifyOperation modifyOperation)
throws DirectoryException
{
- // FIXME -- We need to support this.
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
- Message.raw("Modify operations are not yet supported in " +
- "the task backend"));
+ DN entryDN = entry.getDN();
+
+ Lock entryLock = null;
+ if (! taskScheduler.holdsSchedulerLock())
+ {
+ for (int i=0; i < 3; i++)
+ {
+ entryLock = LockManager.lockWrite(entryDN);
+ if (entryLock != null)
+ {
+ break;
+ }
+ }
+
+ if (entryLock == null)
+ {
+ throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+ ERR_TASKBE_MODIFY_CANNOT_LOCK_ENTRY.get(
+ String.valueOf(entryDN)));
+ }
+ }
+
+ try
+ {
+ // Get the parent for the provided entry DN. It must be either the
+ // scheduled or recurring task parent DN.
+ DN parentDN = entryDN.getParentDNInSuffix();
+ if (parentDN == null)
+ {
+ Message message =
+ ERR_TASKBE_MODIFY_INVALID_ENTRY.get(String.valueOf(entryDN));
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+ else if (parentDN.equals(scheduledTaskParentDN))
+ {
+ // It's a scheduled task. Make sure that it exists.
+ Task t = taskScheduler.getScheduledTask(entryDN);
+ if (t == null)
+ {
+ Message message =
+ ERR_TASKBE_MODIFY_NO_SUCH_TASK.get(String.valueOf(entryDN));
+ throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message);
+ }
+
+
+ // Look at the state of the task. We will allow anything to be altered
+ // for a pending task. For a running task, we will only allow the state
+ // to be altered in order to cancel it. We will not allow any
+ // modifications for completed tasks.
+ TaskState state = t.getTaskState();
+ if (TaskState.isPending(state))
+ {
+ Task newTask =
+ taskScheduler.entryToScheduledTask(entry, modifyOperation);
+ taskScheduler.removePendingTask(t.getTaskID());
+ taskScheduler.scheduleTask(newTask, true);
+ return;
+ }
+ else if (TaskState.isRunning(state))
+ {
+ // If the task is running, we will only allow it to be cancelled.
+ // This will only be allowed using the replace modification type on
+ // the ds-task-state attribute if the value starts with "cancel" or
+ // "stop". In that case, we'll cancel the task.
+ boolean acceptable = true;
+ for (Modification m : modifyOperation.getModifications())
+ {
+ if (m.isInternal())
+ {
+ continue;
+ }
+
+ if (m.getModificationType() != ModificationType.REPLACE)
+ {
+ acceptable = false;
+ break;
+ }
+
+ Attribute a = m.getAttribute();
+ AttributeType at = a.getAttributeType();
+ if (! at.hasName(ATTR_TASK_STATE))
+ {
+ acceptable = false;
+ break;
+ }
+
+ Iterator<AttributeValue> iterator = a.getValues().iterator();
+ if (! iterator.hasNext())
+ {
+ acceptable = false;
+ break;
+ }
+
+ AttributeValue v = iterator.next();
+ String valueString = toLowerCase(v.getStringValue());
+ if (! (valueString.startsWith("cancel") ||
+ valueString.startsWith("stop")))
+ {
+ acceptable = false;
+ break;
+ }
+
+ if (iterator.hasNext())
+ {
+ acceptable = false;
+ break;
+ }
+ }
+
+ if (acceptable)
+ {
+ Message message = INFO_TASKBE_RUNNING_TASK_CANCELLED.get();
+ t.interruptTask(TaskState.STOPPED_BY_ADMINISTRATOR, message);
+ return;
+ }
+ else
+ {
+ Message message =
+ ERR_TASKBE_MODIFY_RUNNING.get(String.valueOf(entryDN));
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
+ message);
+ }
+ }
+ else
+ {
+ Message message =
+ ERR_TASKBE_MODIFY_COMPLETED.get(String.valueOf(entryDN));
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
+ message);
+ }
+ }
+ else if (parentDN.equals(recurringTaskParentDN))
+ {
+ // We don't currently support altering recurring tasks.
+ Message message =
+ ERR_TASKBE_MODIFY_RECURRING.get(String.valueOf(entryDN));
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+ else
+ {
+ Message message =
+ ERR_TASKBE_MODIFY_INVALID_ENTRY.get(String.valueOf(entryDN));
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+ }
+ finally
+ {
+ if (entryLock != null)
+ {
+ LockManager.unlock(entryDN, entryLock);
+ }
+ }
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/task/TaskBackendTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/task/TaskBackendTestCase.java
new file mode 100644
index 0000000..dbd75ae
--- /dev/null
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/task/TaskBackendTestCase.java
@@ -0,0 +1,409 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.backends.task;
+
+
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import org.opends.server.TestCaseUtils;
+import org.opends.server.backends.BackendTestCase;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.tasks.TasksTestCase;
+import org.opends.server.types.DN;
+
+import static org.testng.Assert.*;
+
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.*;
+
+
+
+/**
+ * A set of test cases that can be used to test the task backend.
+ */
+public class TaskBackendTestCase
+ extends BackendTestCase
+{
+ /**
+ * Ensures that the Directory Server is running, and that we are allowed to
+ * schedule the dummy task.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @BeforeClass()
+ public void startServer()
+ throws Exception
+ {
+ TestCaseUtils.startServer();
+ TestCaseUtils.initializeTestBackend(true);
+
+ TestCaseUtils.dsconfig(
+ "set-global-configuration-prop",
+ "--add", "allowed-task:org.opends.server.tasks.DummyTask");
+ }
+
+
+
+ /**
+ * Remove the dummy task from the set of allowed tasks.
+ */
+ @AfterClass()
+ public void cleanUp()
+ throws Exception
+ {
+ TestCaseUtils.dsconfig(
+ "set-global-configuration-prop",
+ "--remove", "allowed-task:org.opends.server.tasks.DummyTask");
+ }
+
+
+
+ /**
+ * Tests to ensure that we can delete a task that is scheduled but hasn't
+ * yet started.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDeletePendingTask()
+ throws Exception
+ {
+ // Schedule a task to start one hour from now that will simply sleep for
+ // 30 seconds.
+ String taskID = "testDeletePendingTask";
+ String taskDN = "ds-task-id=" + taskID + ",cn=Scheduled Tasks,cn=tasks";
+
+ long startTime = System.currentTimeMillis() + 3600000L;
+ SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_GMT_TIME);
+ dateFormat.setTimeZone(TimeZone.getTimeZone(TIME_ZONE_UTC));
+ String startTimeStr = dateFormat.format(new Date(startTime));
+
+ TestCaseUtils.addEntry(
+ "dn: " + taskDN,
+ "objectClass: top",
+ "objectClass: ds-task",
+ "objectClass: extensibleObject",
+ "ds-task-id: " + taskID,
+ "ds-task-class-name: org.opends.server.tasks.DummyTask",
+ "ds-task-scheduled-start-time: " + startTimeStr,
+ "ds-task-dummy-sleep-time: 30000");
+ assertTrue(DirectoryServer.entryExists(DN.decode(taskDN)));
+
+ Task task = TasksTestCase.getTask(DN.decode(taskDN));
+ assertTrue(TaskState.isPending(task.getTaskState()));
+
+ // Perform a modification to delete that task.
+ int resultCode = TestCaseUtils.applyModifications(
+ "dn: " + taskDN,
+ "changetype: delete");
+ assertEquals(resultCode, 0);
+ assertFalse(DirectoryServer.entryExists(DN.decode(taskDN)));
+ }
+
+
+
+ /**
+ * Tests to ensure that we cannot delete a task that is currently running.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDeleteRunningTask()
+ throws Exception
+ {
+ // Schedule a task to start immediately that will simply sleep for 30
+ // seconds.
+ String taskID = "testDeleteRunningTask";
+ String taskDN = "ds-task-id=" + taskID + ",cn=Scheduled Tasks,cn=tasks";
+
+ TestCaseUtils.addEntry(
+ "dn: " + taskDN,
+ "objectClass: top",
+ "objectClass: ds-task",
+ "objectClass: extensibleObject",
+ "ds-task-id: " + taskID,
+ "ds-task-class-name: org.opends.server.tasks.DummyTask",
+ "ds-task-dummy-sleep-time: 30000");
+ assertTrue(DirectoryServer.entryExists(DN.decode(taskDN)));
+
+
+ // Wait until we're sure that the task has started running.
+ long startTime = System.currentTimeMillis();
+ Task task = TasksTestCase.getTask(DN.decode(taskDN));
+ while (TaskState.isPending(task.getTaskState()))
+ {
+ Thread.sleep(10);
+ if (System.currentTimeMillis() > (startTime + 30000L))
+ {
+ throw new AssertionError("Waited too long for the task to start");
+ }
+ }
+
+ assertTrue(TaskState.isRunning(task.getTaskState()));
+
+
+ // Perform a modification to delete that task.
+ int resultCode = TestCaseUtils.applyModifications(
+ "dn: " + taskDN,
+ "changetype: delete");
+ assertFalse(resultCode == 0);
+ assertTrue(DirectoryServer.entryExists(DN.decode(taskDN)));
+ }
+
+
+
+ /**
+ * Tests to ensure that we can delete a task that has completed.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testDeleteCompletedTask()
+ throws Exception
+ {
+ // Schedule a task to start immediately that will simply sleep for 30
+ // seconds.
+ String taskID = "testDeleteCompltedTask";
+ String taskDN = "ds-task-id=" + taskID + ",cn=Scheduled Tasks,cn=tasks";
+
+ TestCaseUtils.addEntry(
+ "dn: " + taskDN,
+ "objectClass: top",
+ "objectClass: ds-task",
+ "objectClass: extensibleObject",
+ "ds-task-id: " + taskID,
+ "ds-task-class-name: org.opends.server.tasks.DummyTask");
+ assertTrue(DirectoryServer.entryExists(DN.decode(taskDN)));
+
+
+ // Wait until the task has completed.
+ Task task = TasksTestCase.getCompletedTask(DN.decode(taskDN));
+ assertTrue(TaskState.isDone(task.getTaskState()));
+
+
+ // Perform a modification to delete that task.
+ int resultCode = TestCaseUtils.applyModifications(
+ "dn: " + taskDN,
+ "changetype: delete");
+ assertEquals(resultCode, 0);
+ assertFalse(DirectoryServer.entryExists(DN.decode(taskDN)));
+ }
+
+
+
+ /**
+ * Tests to ensure that we can modify a task that is scheduled but hasn't
+ * yet started to change the task state as well as other attributes in the
+ * task entry.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testModifyPendingTask()
+ throws Exception
+ {
+ // Schedule a task to start one hour from now that will simply sleep for
+ // 30 seconds.
+ String taskID = "testModifyPendingTask";
+ String taskDN = "ds-task-id=" + taskID + ",cn=Scheduled Tasks,cn=tasks";
+
+ long startTime = System.currentTimeMillis() + 3600000L;
+ SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_GMT_TIME);
+ dateFormat.setTimeZone(TimeZone.getTimeZone(TIME_ZONE_UTC));
+ String startTimeStr = dateFormat.format(new Date(startTime));
+
+ TestCaseUtils.addEntry(
+ "dn: " + taskDN,
+ "objectClass: top",
+ "objectClass: ds-task",
+ "objectClass: extensibleObject",
+ "ds-task-id: " + taskID,
+ "ds-task-class-name: org.opends.server.tasks.DummyTask",
+ "ds-task-scheduled-start-time: " + startTimeStr,
+ "ds-task-dummy-sleep-time: 30000");
+ assertTrue(DirectoryServer.entryExists(DN.decode(taskDN)));
+
+ Task task = TasksTestCase.getTask(DN.decode(taskDN));
+ assertTrue(TaskState.isPending(task.getTaskState()));
+
+ // Perform a modification to update a non-state attribute.
+ int resultCode = TestCaseUtils.applyModifications(
+ "dn: " + taskDN,
+ "changetype: modify",
+ "add: description",
+ "description: foo");
+ assertEquals(resultCode, 0);
+
+
+ // Perform a modification to update the task state.
+ resultCode = TestCaseUtils.applyModifications(
+ "dn: " + taskDN,
+ "changetype: modify",
+ "replace: ds-task-state",
+ "ds-task-state: " + TaskState.CANCELED_BEFORE_STARTING.toString());
+ assertEquals(resultCode, 0);
+
+ // Delete the task.
+ resultCode = TestCaseUtils.applyModifications(
+ "dn: " + taskDN,
+ "changetype: delete");
+ assertEquals(resultCode, 0);
+ assertFalse(DirectoryServer.entryExists(DN.decode(taskDN)));
+ }
+
+
+
+ /**
+ * Tests to ensure that we cannot modify a task that is currently running
+ * other than to change its state.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testModifyRunningTask()
+ throws Exception
+ {
+ // Schedule a task to start immediately that will simply sleep for 30
+ // seconds.
+ String taskID = "testModifyRunningTask";
+ String taskDN = "ds-task-id=" + taskID + ",cn=Scheduled Tasks,cn=tasks";
+
+ TestCaseUtils.addEntry(
+ "dn: " + taskDN,
+ "objectClass: top",
+ "objectClass: ds-task",
+ "objectClass: extensibleObject",
+ "ds-task-id: " + taskID,
+ "ds-task-class-name: org.opends.server.tasks.DummyTask",
+ "ds-task-dummy-sleep-time: 30000");
+ assertTrue(DirectoryServer.entryExists(DN.decode(taskDN)));
+
+
+ // Wait until we're sure that the task has started running.
+ long startTime = System.currentTimeMillis();
+ Task task = TasksTestCase.getTask(DN.decode(taskDN));
+ while (TaskState.isPending(task.getTaskState()))
+ {
+ Thread.sleep(10);
+ if (System.currentTimeMillis() > (startTime + 30000L))
+ {
+ throw new AssertionError("Waited too long for the task to start");
+ }
+ }
+
+ assertTrue(TaskState.isRunning(task.getTaskState()));
+
+
+ // Perform a modification to change something other than the state.
+ int resultCode = TestCaseUtils.applyModifications(
+ "dn: " + taskDN,
+ "changetype: modify",
+ "replace: description",
+ "description: foo");
+ assertFalse(resultCode == 0);
+
+
+ // Perform a modification to cancel the task.
+ resultCode = TestCaseUtils.applyModifications(
+ "dn: " + taskDN,
+ "changetype: modify",
+ "replace: ds-task-state",
+ "ds-task-state: cancel");
+ assertEquals(resultCode, 0);
+
+
+ // We may have to wait for the task to register as done, but it should
+ // definitely be done before it would have stopped normally.
+ task = TasksTestCase.getCompletedTask(DN.decode(taskDN));
+ assertTrue((System.currentTimeMillis() - startTime) < 30000L);
+ assertTrue(TaskState.isDone(task.getTaskState()));
+
+
+ // Perform a modification to delete that task.
+ resultCode = TestCaseUtils.applyModifications(
+ "dn: " + taskDN,
+ "changetype: delete");
+ assertEquals(resultCode, 0);
+ assertFalse(DirectoryServer.entryExists(DN.decode(taskDN)));
+ }
+
+
+
+ /**
+ * Tests to ensure that we cannot modify a task that has completed.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testModifyCompletedTask()
+ throws Exception
+ {
+ // Schedule a task to start immediately that will simply sleep for 30
+ // seconds.
+ String taskID = "testModifyCompltedTask";
+ String taskDN = "ds-task-id=" + taskID + ",cn=Scheduled Tasks,cn=tasks";
+
+ TestCaseUtils.addEntry(
+ "dn: " + taskDN,
+ "objectClass: top",
+ "objectClass: ds-task",
+ "objectClass: extensibleObject",
+ "ds-task-id: " + taskID,
+ "ds-task-class-name: org.opends.server.tasks.DummyTask");
+ assertTrue(DirectoryServer.entryExists(DN.decode(taskDN)));
+
+
+ // Wait until the task has completed.
+ Task task = TasksTestCase.getCompletedTask(DN.decode(taskDN));
+ assertTrue(TaskState.isDone(task.getTaskState()));
+
+
+ // Perform a modification to update a non-state attribute.
+ int resultCode = TestCaseUtils.applyModifications(
+ "dn: " + taskDN,
+ "changetype: modify",
+ "add: description",
+ "description: foo");
+ assertFalse(resultCode == 0);
+
+
+ // Perform a modification to delete that task.
+ resultCode = TestCaseUtils.applyModifications(
+ "dn: " + taskDN,
+ "changetype: delete");
+ assertEquals(resultCode, 0);
+ assertFalse(DirectoryServer.entryExists(DN.decode(taskDN)));
+ }
+}
+
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/DummyTask.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/DummyTask.java
index 05a6916..2442335 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/DummyTask.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/DummyTask.java
@@ -28,9 +28,15 @@
+import java.util.List;
+
+import org.opends.messages.Message;
import org.opends.server.backends.task.Task;
import org.opends.server.backends.task.TaskState;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeValue;
import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
@@ -41,6 +47,15 @@
public class DummyTask
extends Task
{
+ // The length of time that the task should sleep before completing.
+ private long sleepTime;
+
+ // The task state to use when interrupting the task. This will be null unless
+ // the task gets interrupted.
+ private volatile TaskState interruptedState;
+
+
+
/**
* {@inheritDoc}
*/
@@ -48,7 +63,25 @@
public void initializeTask()
throws DirectoryException
{
- // No implementation is required.
+ sleepTime = 0;
+ interruptedState = null;
+
+ Entry taskEntry = getTaskEntry();
+ if (taskEntry != null)
+ {
+ List<Attribute> attrList =
+ taskEntry.getAttribute("ds-task-dummy-sleep-time");
+ if (attrList != null)
+ {
+ for (Attribute a : attrList)
+ {
+ for (AttributeValue v : a.getValues())
+ {
+ sleepTime = Long.parseLong(v.getStringValue());
+ }
+ }
+ }
+ }
}
@@ -58,7 +91,34 @@
*/
protected TaskState runTask()
{
- return TaskState.COMPLETED_SUCCESSFULLY;
+ long stopTime = System.currentTimeMillis() + sleepTime;
+ while ((interruptedState == null) &&
+ (System.currentTimeMillis() < stopTime))
+ {
+ try
+ {
+ Thread.sleep(10);
+ } catch (Exception e) {}
+ }
+
+ if (interruptedState == null)
+ {
+ return TaskState.COMPLETED_SUCCESSFULLY;
+ }
+ else
+ {
+ return interruptedState;
+ }
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void interruptTask(TaskState taskState, Message interruptMessage)
+ {
+ interruptedState = taskState;
}
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TasksTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TasksTestCase.java
index 666ea9e..08968ff 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TasksTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TasksTestCase.java
@@ -157,8 +157,8 @@
/**
- * Retrieves the specified task from the server, waiting for it to finish all
- * the running its going to do before returning.
+ * Retrieves the specified task from the server, regardless of its current
+ * state.
*
* @param taskEntryDN The DN of the entry for the task to retrieve.
*
@@ -166,8 +166,9 @@
*
* @throws Exception If an unexpected problem occurs.
*/
- protected Task getCompletedTask(DN taskEntryDN)
- throws Exception
+ @Test(enabled=false) // This isn't a test method, but TestNG thinks it is.
+ public static Task getTask(DN taskEntryDN)
+ throws Exception
{
TaskBackend taskBackend =
(TaskBackend) DirectoryServer.getBackend(DN.decode("cn=tasks"));
@@ -188,6 +189,27 @@
taskEntryDN.toString());
}
+ return task;
+ }
+
+
+
+ /**
+ * Retrieves the specified task from the server, waiting for it to finish all
+ * the running its going to do before returning.
+ *
+ * @param taskEntryDN The DN of the entry for the task to retrieve.
+ *
+ * @return The requested task entry.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(enabled=false) // This isn't a test method, but TestNG thinks it is.
+ public static Task getCompletedTask(DN taskEntryDN)
+ throws Exception
+ {
+ Task task = getTask(taskEntryDN);
+
if (! TaskState.isDone(task.getTaskState()))
{
long stopWaitingTime = System.currentTimeMillis() + 20000L;
--
Gitblit v1.10.0