Issue 2368: tasks should be interruptable. The four schedulable task (import-ldif, export-ldif, backup, and restore) can now be interrupted for purposes of cancellation. The manage-tasks utility now allows the user to cancel any one of these tasks if they are currently running. If interrupted while executing, the tasks try to break out of their work loop as soon as possible and return a 'stopped by administrator' status. Both the backup and export-ldif tasks perform some cleanup (removing the abandoned backup or exported LDIF file) if they are cancelled.
1 files added
18 files modified
| | |
| | | INFO_FAILED_DEPENDENCY_ACTION_PROCESS_99=Process |
| | | INFO_FAILED_DEPENDENCY_ACTION_CANCEL_100=Cancel |
| | | INFO_FAILED_DEPENDENCY_ACTION_DISABLE_101=Disable |
| | | INFO_TASK_STOPPED_BY_ADMIN_102=Task was stopped by an administrator: %s |
| | |
| | | option is to be used in conjunction with one or more dependencies |
| | | SEVERE_ERR_TASKINFO_TASK_NOT_CANCELABLE_TASK_1477=Error: task %s is not in a \ |
| | | cancelable state |
| | | |
| | | NOTICE_BACKUPDB_CANCELLED_1478=The backup process was cancelled |
| | |
| | | byte[] buffer = new byte[8192]; |
| | | for (File schemaFile : schemaFiles) |
| | | { |
| | | if (backupConfig.isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | if (! schemaFile.isFile()) |
| | | { |
| | | // If there are any non-file items in the directory (e.g., one or more |
| | |
| | | while (true) |
| | | { |
| | | int bytesRead = inputStream.read(buffer); |
| | | if (bytesRead < 0) |
| | | if (bytesRead < 0 || backupConfig.isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | |
| | | if (latestFileName != null) |
| | | { |
| | | ArrayList<String> unchangedList = new ArrayList<String>(); |
| | | while (indexCurrent < logFiles.length) |
| | | while (indexCurrent < logFiles.length && |
| | | !backupConfig.isCancelled()) |
| | | { |
| | | File logFile = logFiles[indexCurrent]; |
| | | String logFileName = logFile.getName(); |
| | |
| | | { |
| | | boolean deletedFiles = false; |
| | | |
| | | while (indexCurrent < logFiles.length) |
| | | while (indexCurrent < logFiles.length && |
| | | !backupConfig.isCancelled()) |
| | | { |
| | | File logFile = logFiles[indexCurrent]; |
| | | |
| | | try |
| | | { |
| | | latestFileSize = archiveFile(zipStream, mac, digest, logFile); |
| | | latestFileSize = archiveFile(zipStream, mac, digest, |
| | | logFile, backupConfig); |
| | | latestFileName = logFile.getName(); |
| | | } |
| | | catch (FileNotFoundException e) |
| | |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message, e); |
| | | } |
| | | |
| | | // Remove the backup if this operation was cancelled since the |
| | | // backup may be incomplete |
| | | if (backupConfig.isCancelled()) |
| | | { |
| | | removeBackup(backupDir, backupID); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | // Iterate through the entries in the zip file. |
| | | ZipEntry zipEntry = zipStream.getNextEntry(); |
| | | while (zipEntry != null) |
| | | while (zipEntry != null && !restoreConfig.isCancelled()) |
| | | { |
| | | String name = zipEntry.getName(); |
| | | |
| | |
| | | long totalBytesRead = 0; |
| | | byte[] buffer = new byte[8192]; |
| | | int bytesRead = zipStream.read(buffer); |
| | | while (bytesRead > 0) |
| | | while (bytesRead > 0 && !restoreConfig.isCancelled()) |
| | | { |
| | | totalBytesRead += bytesRead; |
| | | |
| | |
| | | * @throws IOException If an I/O error occurs while archiving the file. |
| | | */ |
| | | private long archiveFile(ZipOutputStream zipStream, |
| | | Mac mac, MessageDigest digest, File file) |
| | | Mac mac, MessageDigest digest, File file, |
| | | BackupConfig backupConfig) |
| | | throws IOException, FileNotFoundException |
| | | { |
| | | ZipEntry zipEntry = new ZipEntry(file.getName()); |
| | |
| | | long totalBytesRead = 0; |
| | | byte[] buffer = new byte[8192]; |
| | | int bytesRead = inputStream.read(buffer); |
| | | while (bytesRead > 0) |
| | | while (bytesRead > 0 && !backupConfig.isCancelled()) |
| | | { |
| | | if (mac != null) |
| | | { |
| | |
| | | { |
| | | for (EntryContainer exportContainer : exportContainers) |
| | | { |
| | | if (exportConfig.isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | exportContainer.sharedLock.lock(); |
| | | try |
| | | { |
| | |
| | | status == OperationStatus.SUCCESS; |
| | | status = cursor.getNext(key, data, LockMode.DEFAULT)) |
| | | { |
| | | if (exportConfig.isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | EntryID entryID = null; |
| | | try |
| | | { |
| | |
| | | |
| | | do |
| | | { |
| | | if (ldifImportConfig.isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | if(threads.size() <= 0) |
| | | { |
| | | message = ERR_JEB_IMPORT_NO_WORKER_THREADS.get(); |
| | |
| | | { |
| | | status = cursor.getFirst(key, data, lockMode); |
| | | |
| | | while(status == OperationStatus.SUCCESS) |
| | | while(status == OperationStatus.SUCCESS && |
| | | !ldifImportConfig.isCancelled()) |
| | | { |
| | | if(threads.size() <= 0) |
| | | { |
| | |
| | | end[0] = (byte) (end[0] + 1); |
| | | |
| | | while(status == OperationStatus.SUCCESS && |
| | | dn2idComparator.compare(key.getData(), end) < 0) |
| | | dn2idComparator.compare(key.getData(), end) < 0 && |
| | | !ldifImportConfig.isCancelled()) |
| | | { |
| | | if(threads.size() <= 0) |
| | | { |
| | |
| | | // The current state of this task. |
| | | private TaskState taskState; |
| | | |
| | | // The task state that may be set when the task is interrupted. |
| | | private TaskState taskInterruptState; |
| | | |
| | | // The scheduler with which this task is associated. |
| | | private TaskScheduler taskScheduler; |
| | | |
| | |
| | | return taskState; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not this task has been cancelled. |
| | | * |
| | | * @return boolean where true indicates that this task was |
| | | * cancelled either before or during execution |
| | | */ |
| | | public boolean isCancelled() |
| | | { |
| | | return taskInterruptState != null && |
| | | TaskState.isCancelled(taskInterruptState); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Sets a state for this task that is the result of a call to |
| | | * {@link #interruptTask(TaskState, org.opends.messages.Message)}. |
| | | * It may take this task some time to actually cancel to that |
| | | * actual state may differ until quiescence. |
| | | * |
| | | * @param state for this task once it has canceled whatever it is doing |
| | | */ |
| | | protected void setTaskInterruptState(TaskState state) |
| | | { |
| | | this.taskInterruptState = state; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Gets the interrupt state for this task that was set as a |
| | | * result of a call to {@link #interruptTask(TaskState, |
| | | * org.opends.messages.Message)}. |
| | | * |
| | | * @return interrupt state for this task |
| | | */ |
| | | protected TaskState getTaskInterruptState() |
| | | { |
| | | return this.taskInterruptState; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns a state for this task after processing has completed. |
| | | * If the task was interrupted with a call to |
| | | * {@link #interruptTask(TaskState, org.opends.messages.Message)} |
| | | * then that method's interruptState is returned here. Otherwse |
| | | * this method returns TaskState.COMPLETED_SUCCESSFULLY. It is |
| | | * assumed that if there were errors during task processing that |
| | | * task state will have been derived in some other way. |
| | | * |
| | | * @return state for this task after processing has completed |
| | | */ |
| | | protected TaskState getFinalTaskState() |
| | | { |
| | | if (this.taskInterruptState == null) |
| | | { |
| | | return TaskState.COMPLETED_SUCCESSFULLY; |
| | | } |
| | | else |
| | | { |
| | | return this.taskInterruptState; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Replaces an attribute values of the task entry. |
| | | * |
| | |
| | | * gracefully interrupt a task, then subclasses should override this method to |
| | | * do so. |
| | | * |
| | | * Implementations of this method are exprected to call |
| | | * {@link #setTaskInterruptState(TaskState)} if the interruption is accepted |
| | | * by this task. |
| | | * |
| | | * @param interruptState The state to use for the task if it is |
| | | * successfully interrupted. |
| | | * @param interruptReason A human-readable explanation for the cancellation. |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Indicates whether or not this task has been cancelled. |
| | | * |
| | | * @param taskState The task state for which to make the determination. |
| | | * |
| | | * @return <CODE>true</CODE> if the task state indicates that the task |
| | | * was cancelled either before or during execution, or |
| | | * <CODE>false</CODE> otherwise. |
| | | */ |
| | | public static boolean isCancelled(TaskState taskState) |
| | | { |
| | | switch(taskState) |
| | | { |
| | | case STOPPED_BY_ADMINISTRATOR: |
| | | case CANCELED_BEFORE_STARTING: |
| | | return true; |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the task state that corresponds to the provided string value. |
| | |
| | | while (true) |
| | | { |
| | | int bytesRead = inputStream.read(buffer); |
| | | if (bytesRead < 0) |
| | | if (bytesRead < 0 || backupConfig.isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | |
| | | while (true) |
| | | { |
| | | int bytesRead = inputStream.read(buffer); |
| | | if (bytesRead < 0) |
| | | if (bytesRead < 0 || backupConfig.isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message, e); |
| | | } |
| | | |
| | | // Remove the backup if this operation was cancelled since the |
| | | // backup may be incomplete |
| | | if (backupConfig.isCancelled()) |
| | | { |
| | | removeBackup(backupDirectory, backupID); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | for (ReplicationCache exportContainer : exportContainers) |
| | | { |
| | | if (exportConfig.isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | | processContainer(exportContainer, exportConfig, ldifWriter, null); |
| | | } |
| | | } |
| | |
| | | |
| | | for (ReplicationCache exportContainer : exportContainers) |
| | | { |
| | | if (exportConfig != null && exportConfig.isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | attributes.clear(); |
| | | ldapAttrList.clear(); |
| | | |
| | |
| | | // Walk through the servers |
| | | for (Short serverId : rc.getServers()) |
| | | { |
| | | if (exportConfig != null && exportConfig.isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | ReplicationIterator ri = rc.getChangelogIterator(serverId, |
| | | null); |
| | | |
| | |
| | | // Walk through the changes |
| | | while (ri.getChange() != null) |
| | | { |
| | | if (exportConfig != null && exportConfig.isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | | UpdateMessage msg = ri.getChange(); |
| | | processChange(msg, exportConfig, ldifWriter, searchOperation); |
| | | if (!ri.next()) |
| | |
| | | */ |
| | | package org.opends.server.tasks; |
| | | import org.opends.messages.Message; |
| | | import org.opends.messages.TaskMessages; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.core.DirectoryServer.getAttributeType; |
| | |
| | | private File backupDirectory; |
| | | private String incrementalBase; |
| | | |
| | | private BackupConfig backupConfig; |
| | | |
| | | /** |
| | | * All the backend configuration entries defined in the server mapped |
| | | * by their backend ID. |
| | |
| | | |
| | | |
| | | // Create a backup configuration. |
| | | BackupConfig backupConfig = new BackupConfig(backupDir, backupID, |
| | | backupConfig = new BackupConfig(backupDir, backupID, |
| | | incremental); |
| | | backupConfig.setCompressData(compress); |
| | | backupConfig.setEncryptData(encrypt); |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void interruptTask(TaskState interruptState, Message interruptReason) |
| | | { |
| | | if (TaskState.STOPPED_BY_ADMINISTRATOR.equals(interruptState) && |
| | | backupConfig != null) |
| | | { |
| | | addLogMessage(TaskMessages.INFO_TASK_STOPPED_BY_ADMIN.get( |
| | | interruptReason)); |
| | | setTaskInterruptState(interruptState); |
| | | backupConfig.cancel(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isInterruptable() { |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | protected TaskState runTask() |
| | | { |
| | | if (!argumentsAreValid()) |
| | |
| | | boolean errorsEncountered = false; |
| | | for (Backend b : backendsToArchive) |
| | | { |
| | | if (isCancelled()) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | // Acquire a shared lock for this backend. |
| | | if (!lockBackend(b)) |
| | | { |
| | |
| | | logError(message); |
| | | return TaskState.COMPLETED_WITH_ERRORS; |
| | | } |
| | | else if (isCancelled()) |
| | | { |
| | | Message message = NOTE_BACKUPDB_CANCELLED.get(); |
| | | logError(message); |
| | | return getTaskInterruptState(); |
| | | } |
| | | else |
| | | { |
| | | Message message = NOTE_BACKUPDB_COMPLETED_SUCCESSFULLY.get(); |
| | |
| | | */ |
| | | package org.opends.server.tasks; |
| | | import org.opends.messages.Message; |
| | | import org.opends.messages.TaskMessages; |
| | | |
| | | import static org.opends.server.core.DirectoryServer.getAttributeType; |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.HashMap; |
| | | import java.io.File; |
| | | |
| | | /** |
| | | * This class provides an implementation of a Directory Server task that can |
| | |
| | | private ArrayList<String> includeBranchStrings; |
| | | private ArrayList<String> excludeBranchStrings; |
| | | |
| | | private LDIFExportConfig exportConfig; |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | |
| | | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void interruptTask(TaskState interruptState, Message interruptReason) |
| | | { |
| | | if (TaskState.STOPPED_BY_ADMINISTRATOR.equals(interruptState) && |
| | | exportConfig != null) |
| | | { |
| | | addLogMessage(TaskMessages.INFO_TASK_STOPPED_BY_ADMIN.get( |
| | | interruptReason)); |
| | | setTaskInterruptState(interruptState); |
| | | exportConfig.cancel(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isInterruptable() { |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | |
| | | existingBehavior = ExistingFileBehavior.OVERWRITE; |
| | | } |
| | | |
| | | LDIFExportConfig exportConfig = |
| | | new LDIFExportConfig(ldifFile, existingBehavior); |
| | | exportConfig = new LDIFExportConfig(ldifFile, existingBehavior); |
| | | exportConfig.setCompressData(compressLDIF); |
| | | exportConfig.setEncryptData(encryptLDIF); |
| | | exportConfig.setExcludeAttributes(excludeAttributes); |
| | |
| | | exportConfig.close(); |
| | | } |
| | | |
| | | // If the operation was cancelled delete the export file since |
| | | // if will be incomplete. |
| | | if (exportConfig.isCancelled()) |
| | | { |
| | | File f = new File(ldifFile); |
| | | if (f.exists()) |
| | | { |
| | | f.delete(); |
| | | } |
| | | } |
| | | |
| | | return TaskState.COMPLETED_SUCCESSFULLY; |
| | | // If we got here the task either completed successfully or |
| | | // was interrupted |
| | | return getFinalTaskState(); |
| | | } |
| | | } |
| | |
| | | */ |
| | | package org.opends.server.tasks; |
| | | import org.opends.messages.Message; |
| | | import org.opends.messages.TaskMessages; |
| | | |
| | | import static org.opends.messages.TaskMessages.*; |
| | | import static org.opends.messages.ToolMessages.*; |
| | |
| | | ArrayList<String> includeFilterStrings = null; |
| | | ArrayList<String> ldifFiles = null; |
| | | |
| | | private LDIFImportConfig importConfig; |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void interruptTask(TaskState interruptState, Message interruptReason) |
| | | { |
| | | if (TaskState.STOPPED_BY_ADMINISTRATOR.equals(interruptState) && |
| | | importConfig != null) |
| | | { |
| | | addLogMessage(TaskMessages.INFO_TASK_STOPPED_BY_ADMIN.get( |
| | | interruptReason)); |
| | | setTaskInterruptState(interruptState); |
| | | importConfig.cancel(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isInterruptable() |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | |
| | | |
| | | // Create the LDIF import configuration to use when reading the LDIF. |
| | | ArrayList<String> fileList = new ArrayList<String>(ldifFiles); |
| | | LDIFImportConfig importConfig = new LDIFImportConfig(fileList); |
| | | importConfig = new LDIFImportConfig(fileList); |
| | | importConfig.setAppendToExistingData(append); |
| | | importConfig.setReplaceExistingEntries(replaceExisting); |
| | | importConfig.setCompressed(isCompressed); |
| | |
| | | |
| | | // Clean up after the import by closing the import config. |
| | | importConfig.close(); |
| | | return TaskState.COMPLETED_SUCCESSFULLY; |
| | | return getFinalTaskState(); |
| | | } |
| | | } |
| | |
| | | */ |
| | | package org.opends.server.tasks; |
| | | import org.opends.messages.Message; |
| | | import org.opends.messages.TaskMessages; |
| | | |
| | | import static org.opends.server.core.DirectoryServer.getAttributeType; |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | |
| | | private String backupID; |
| | | private boolean verifyOnly; |
| | | |
| | | private RestoreConfig restoreConfig; |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void interruptTask(TaskState interruptState, Message interruptReason) |
| | | { |
| | | if (TaskState.STOPPED_BY_ADMINISTRATOR.equals(interruptState) && |
| | | restoreConfig != null) |
| | | { |
| | | addLogMessage(TaskMessages.INFO_TASK_STOPPED_BY_ADMIN.get( |
| | | interruptReason)); |
| | | setTaskInterruptState(interruptState); |
| | | restoreConfig.cancel(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isInterruptable() { |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | |
| | | } |
| | | |
| | | // Create the restore config object from the information available. |
| | | RestoreConfig restoreConfig = new RestoreConfig(backupDir, backupID, |
| | | verifyOnly); |
| | | restoreConfig = new RestoreConfig(backupDir, backupID, verifyOnly); |
| | | |
| | | // Notify the task listeners that a restore is going to start |
| | | // this must be done before disabling the backend to allow |
| | |
| | | } |
| | | else |
| | | { |
| | | return TaskState.COMPLETED_SUCCESSFULLY; |
| | | return getFinalTaskState(); |
| | | } |
| | | } |
| | | } |
| | |
| | | mayInstantiate=true, |
| | | mayExtend=false, |
| | | mayInvoke=true) |
| | | public final class BackupConfig |
| | | public final class BackupConfig extends OperationConfig |
| | | { |
| | | // The path to the directory in which the backup file(s) should be |
| | | // created. |
| | |
| | | mayInstantiate=true, |
| | | mayExtend=false, |
| | | mayInvoke=true) |
| | | public final class LDIFExportConfig |
| | | public final class LDIFExportConfig extends OperationConfig |
| | | { |
| | | /** |
| | | * The tracer object for the debug logger. |
| | |
| | | mayInstantiate=true, |
| | | mayExtend=false, |
| | | mayInvoke=true) |
| | | public final class LDIFImportConfig |
| | | public final class LDIFImportConfig extends OperationConfig |
| | | { |
| | | /** |
| | | * The tracer object for the debug logger. |
| New file |
| | |
| | | /* |
| | | * 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.types; |
| | | |
| | | /** |
| | | * Base for data structures that define configuration |
| | | * for operations. |
| | | */ |
| | | @org.opends.server.types.PublicAPI( |
| | | stability=org.opends.server.types.StabilityLevel.VOLATILE, |
| | | mayInstantiate=true, |
| | | mayExtend=false, |
| | | mayInvoke=true) |
| | | public abstract class OperationConfig { |
| | | |
| | | // When true indicates that the operation should stop as soon as |
| | | // possible. |
| | | private boolean cancelled; |
| | | |
| | | /** |
| | | * Indicates that this operation has been cancelled and the |
| | | * operation if executing should finish as soon as possible. |
| | | */ |
| | | public void cancel() |
| | | { |
| | | this.cancelled = true; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not this operation has been |
| | | * cancelled. |
| | | * |
| | | * @return boolean where true indicates that this |
| | | * operation has been cancelled and if currently |
| | | * executing will finish as soon as possible |
| | | */ |
| | | public boolean isCancelled() |
| | | { |
| | | return this.cancelled; |
| | | } |
| | | } |
| | |
| | | mayInstantiate=true, |
| | | mayExtend=false, |
| | | mayInvoke=true) |
| | | public final class RestoreConfig |
| | | public final class RestoreConfig extends OperationConfig |
| | | { |
| | | // The reference to the directory containing the backup file(s) to |
| | | // restore. |