Merge pull request #3715 from esaunders/3737_ain_pause_resume

3737 Added pause/resume/shutdown functionality to AID
This commit is contained in:
Richard Cordovano 2018-05-08 10:50:38 -04:00 committed by GitHub
commit 7a6c8d8a8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 305 additions and 91 deletions

View File

@ -52,6 +52,14 @@ final class AinStatusDashboard extends javax.swing.JPanel implements Observer {
autoIngestMonitor.addObserver(this);
}
AutoIngestMonitor getMonitor() {
return autoIngestMonitor;
}
AinStatusPanel getNodesStatusPanel() {
return nodesPanel;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
@ -143,9 +151,10 @@ final class AinStatusDashboard extends javax.swing.JPanel implements Observer {
@Override
public void update(Observable o, Object arg) {
if (arg instanceof AutoIngestNodeState)
if (arg instanceof AutoIngestNodeState) {
EventQueue.invokeLater(() -> {
refreshTables();
});
}
}
}

View File

@ -18,6 +18,7 @@
*/
package org.sleuthkit.autopsy.experimental.autoingest;
import java.awt.Component;
import java.util.List;
import java.util.logging.Level;
import java.util.stream.Collectors;
@ -74,8 +75,6 @@ final class AinStatusDashboardTopComponent extends TopComponent {
tc.add(nodeTab);
tc.open();
}
tc.toFront();
tc.requestActive();
}
}
@ -115,6 +114,19 @@ final class AinStatusDashboardTopComponent extends TopComponent {
WindowManager.getDefault().setTopComponentFloating(this, true);
}
/**
* Get the current AutoIngestDashboard if there is one.
*
* @return the current AutoIngestDashboard or null if there is not one
*/
AinStatusDashboard getAinStatusDashboard() {
for (Component comp : getComponents()) {
if (comp instanceof AinStatusDashboard) {
return (AinStatusDashboard) comp;
}
}
return null;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always

View File

@ -97,6 +97,7 @@ final class AinStatusNode extends AbstractNode {
@Messages({"AinStatusNode.hostName.title=Host Name",
"AinStatusNode.status.title=Status",
"AinStatusNode.status.running=Running",
"AinStatusNode.status.pauseRequested=Pause Requested",
"AinStatusNode.status.pausedByUser=Paused By User",
"AinStatusNode.status.pausedForError=Paused Due to System Error",
"AinStatusNode.status.startingup=Starting Up",
@ -129,6 +130,9 @@ final class AinStatusNode extends AbstractNode {
case PAUSED_DUE_TO_SYSTEM_ERROR:
status = Bundle.AinStatusNode_status_pausedForError();
break;
case PAUSE_REQUESTED:
status = Bundle.AinStatusNode_status_pauseRequested();
break;
default:
break;
}
@ -142,12 +146,11 @@ final class AinStatusNode extends AbstractNode {
List<Action> actions = new ArrayList<>();
if (AutoIngestDashboard.isAdminAutoIngestDashboard()) {
if (nodeState.getState() == AutoIngestNodeState.State.PAUSED_BY_REQUEST
|| nodeState.getState() == AutoIngestNodeState.State.PAUSED_DUE_TO_SYSTEM_ERROR) {
actions.add(new AutoIngestAdminActions.ResumeAction());
} else if (nodeState.getState() == AutoIngestNodeState.State.RUNNING){
actions.add(new AutoIngestAdminActions.PauseAction());
|| nodeState.getState() == AutoIngestNodeState.State.PAUSED_DUE_TO_SYSTEM_ERROR
|| nodeState.getState() == AutoIngestNodeState.State.RUNNING) {
actions.add(new AutoIngestAdminActions.AutoIngestNodeControlAction.PauseResumeAction(nodeState));
}
actions.add(new AutoIngestAdminActions.ShutdownAction());
actions.add(new AutoIngestAdminActions.AutoIngestNodeControlAction.ShutdownAction(nodeState));
}
return actions.toArray(new Action[actions.size()]);
}

View File

@ -99,12 +99,12 @@ final class AinStatusPanel extends javax.swing.JPanel implements ExplorerManager
void refresh(AutoIngestMonitor monitor) {
outline.setRowSelectionAllowed(false);
Node[] selectedNodes = explorerManager.getSelectedNodes();
AinStatusNode autoIngestNode = new AinStatusNode(monitor);
explorerManager.setRootContext(autoIngestNode);
AinStatusNode ainStatusNode = new AinStatusNode(monitor);
explorerManager.setRootContext(ainStatusNode);
outline.setRowSelectionAllowed(true);
if (selectedNodes.length > 0 && autoIngestNode.getChildren().findChild(selectedNodes[0].getName()) != null && outline.isFocusable()) { //don't allow saved selections of empty nodes to be restored
if (selectedNodes.length > 0 && ainStatusNode.getChildren().findChild(selectedNodes[0].getName()) != null && outline.isFocusable()) { //don't allow saved selections of empty nodes to be restored
try {
explorerManager.setSelectedNodes(new Node[]{autoIngestNode.getChildren().findChild(selectedNodes[0].getName())});
explorerManager.setSelectedNodes(new Node[]{ainStatusNode.getChildren().findChild(selectedNodes[0].getName())});
} catch (PropertyVetoException ignore) {
//Unable to select previously selected node
}

View File

@ -18,14 +18,122 @@
*/
package org.sleuthkit.autopsy.experimental.autoingest;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.JOptionPane;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.AutoIngestNodeState;
import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
final class AutoIngestAdminActions {
static abstract class AutoIngestNodeControlAction extends AbstractAction {
private final AutoIngestNodeState nodeState;
private final Logger logger = Logger.getLogger(AutoIngestNodeControlAction.class.getName());
AutoIngestNodeControlAction(AutoIngestNodeState nodeState, String title) {
super(title);
this.nodeState = nodeState;
}
@Override
public void actionPerformed(ActionEvent e) {
if (nodeState != null) {
final AinStatusDashboardTopComponent tc = (AinStatusDashboardTopComponent) WindowManager.getDefault().findTopComponent(AinStatusDashboardTopComponent.PREFERRED_ID);
if (tc != null) {
AinStatusDashboard dashboard = tc.getAinStatusDashboard();
if (dashboard != null) {
dashboard.getNodesStatusPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
EventQueue.invokeLater(() -> {
try {
controlAutoIngestNode(dashboard);
} catch (AutoIngestMonitor.AutoIngestMonitorException ex) {
logger.log(Level.WARNING, "Error sending control event to node", ex);
} finally {
dashboard.getNodesStatusPanel().setCursor(Cursor.getDefaultCursor());
}
});
}
}
}
}
protected abstract void controlAutoIngestNode(AinStatusDashboard dashboard) throws AutoIngestMonitor.AutoIngestMonitorException;
AutoIngestNodeState getNodeState() {
return nodeState;
}
@NbBundle.Messages({"AutoIngestAdminActions.pause.title=Pause Node",
"AutoIngestAdminActions.resume.title=Resume Node"})
static final class PauseResumeAction extends AutoIngestNodeControlAction {
private static final long serialVersionUID = 1L;
PauseResumeAction(AutoIngestNodeState nodeState) {
super(nodeState, nodeState.getState() == AutoIngestNodeState.State.RUNNING
? Bundle.AutoIngestAdminActions_pause_title() : Bundle.AutoIngestAdminActions_resume_title());
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
@Override
protected void controlAutoIngestNode(AinStatusDashboard dashboard) throws AutoIngestMonitor.AutoIngestMonitorException {
if (getNodeState().getState() == AutoIngestNodeState.State.RUNNING) {
dashboard.getMonitor().pauseAutoIngestNode(getNodeState().getName());
} else {
dashboard.getMonitor().resumeAutoIngestNode(getNodeState().getName());
}
}
}
@NbBundle.Messages({"AutoIngestAdminActions.shutdown.title=Shutdown Node",
"AutoIngestAdminActions.shutdown.OK=OK", "AutoIngestAdminActions.shutdown.Cancel=Cancel",
"AutoIngestAdminActions.shutdown.consequences=This will cancel any currently running job on this host. Exiting while a job is running potentially leaves the case in an inconsistent or corrupted state."})
static final class ShutdownAction extends AutoIngestNodeControlAction {
private static final long serialVersionUID = 1L;
ShutdownAction(AutoIngestNodeState nodeState) {
super(nodeState, Bundle.AutoIngestAdminActions_shutdown_title());
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
@Override
protected void controlAutoIngestNode(AinStatusDashboard dashboard) throws AutoIngestMonitor.AutoIngestMonitorException {
Object[] options = {Bundle.AutoIngestAdminActions_shutdown_OK(),
Bundle.AutoIngestAdminActions_shutdown_Cancel()
};
int reply = JOptionPane.showOptionDialog(dashboard.getNodesStatusPanel(),
Bundle.AutoIngestAdminActions_shutdown_consequences(),
NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.ConfirmExitHeader"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
options,
options[JOptionPane.NO_OPTION]);
if (reply == JOptionPane.OK_OPTION) {
dashboard.getMonitor().shutdownAutoIngestNode(getNodeState().getName());
}
}
}
}
@NbBundle.Messages({"AutoIngestAdminActions.progressDialogAction.title=Ingest Progress"})
static final class ProgressDialogAction extends AbstractAction {
@ -152,65 +260,4 @@ final class AutoIngestAdminActions {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
@NbBundle.Messages({"AutoIngestAdminActions.pause.title=Pause Node"})
static final class PauseAction extends AbstractAction {
private static final long serialVersionUID = 1L;
PauseAction() {
super(Bundle.AutoIngestAdminActions_pause_title());
}
@Override
public void actionPerformed(ActionEvent e) {
//TODO JIRA-
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
@NbBundle.Messages({"AutoIngestAdminActions.resume.title=Resume Node"})
static final class ResumeAction extends AbstractAction {
private static final long serialVersionUID = 1L;
ResumeAction() {
super(Bundle.AutoIngestAdminActions_resume_title());
}
@Override
public void actionPerformed(ActionEvent e) {
//TODO JIRA-
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
@NbBundle.Messages({"AutoIngestAdminActions.shutdown.title=Shutdown Node"})
static final class ShutdownAction extends AbstractAction {
private static final long serialVersionUID = 1L;
ShutdownAction() {
super(Bundle.AutoIngestAdminActions_shutdown_title());
}
@Override
public void actionPerformed(ActionEvent e) {
//TODO JIRA-
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
}

View File

@ -852,7 +852,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
case CASE_DELETED:
updateExecutor.submit(new UpdateAllJobsTablesTask());
break;
case PAUSED_BY_REQUEST:
case PAUSED_BY_USER_REQUEST:
EventQueue.invokeLater(() -> {
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.paused"));
bnOptions.setEnabled(true);
@ -881,6 +881,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
case JOB_STATUS_UPDATED:
updateExecutor.submit(new UpdateRunningJobsTablesTask());
break;
case SHUTTING_DOWN:
LifecycleManager.getDefault().exit();
break;
default:
break;
}

View File

@ -170,7 +170,7 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa
AutoIngestJobsNode autoIngestNode = new AutoIngestJobsNode(jobsSnapshot, status);
explorerManager.setRootContext(autoIngestNode);
outline.setRowSelectionAllowed(true);
if (selectedNodes.length > 0 && outline.isFocusable()) { //don't allow saved selections of empty nodes to be restored
if (selectedNodes.length > 0 && autoIngestNode.getChildren().findChild(selectedNodes[0].getName()) != null && outline.isFocusable()) { //don't allow saved selections of empty nodes to be restored
try {
explorerManager.setSelectedNodes(new Node[]{autoIngestNode.getChildren().findChild(selectedNodes[0].getName())});
} catch (PropertyVetoException ignore) {

View File

@ -93,6 +93,7 @@ import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration.Shar
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.AutoIngestJobException;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestNodeControlEvent.ControlEventType;
import org.sleuthkit.autopsy.ingest.IngestJob;
import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
@ -133,7 +134,10 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
Event.JOB_COMPLETED.toString(),
Event.CASE_PRIORITIZED.toString(),
Event.JOB_STARTED.toString(),
Event.REPORT_STATE.toString()}));
Event.REPORT_STATE.toString(),
ControlEventType.PAUSE.toString(),
ControlEventType.RESUME.toString(),
ControlEventType.SHUTDOWN.toString()}));
private static final long JOB_STATUS_EVENT_INTERVAL_SECONDS = 10;
private static final String JOB_STATUS_PUBLISHING_THREAD_NAME = "AIM-job-status-event-publisher-%d";
private static final long MAX_MISSED_JOB_STATUS_UPDATES = 10;
@ -281,6 +285,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
handleRemoteCaseDeletedEvent((AutoIngestCaseDeletedEvent) event);
} else if (event instanceof AutoIngestRequestNodeStateEvent) {
handleRemoteRequestNodeStateEvent();
} else if (event instanceof AutoIngestNodeControlEvent) {
handleRemoteNodeControlEvent((AutoIngestNodeControlEvent) event);
}
}
}
@ -404,6 +410,28 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
eventPublisher.publishRemotely(lastPublishedStateEvent);
}
private void handleRemoteNodeControlEvent(AutoIngestNodeControlEvent event) {
if (event.getNodeName().compareToIgnoreCase(LOCAL_HOST_NAME) == 0) {
switch (event.getControlEventType()) {
case PAUSE:
pause();
break;
case RESUME:
resume();
break;
case SHUTDOWN:
shutDown();
// Notify the front end (if any) to shutdown.
setChanged();
notifyObservers(Event.SHUTTING_DOWN);
break;
default:
SYS_LOGGER.log(Level.WARNING, "Received unsupported control event: {0}", event.getControlEventType());
break;
}
}
}
/**
* Shuts down auto ingest.
*/
@ -418,6 +446,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
eventPublisher.removeSubscriber(EVENT_LIST, instance);
stopInputFolderScans();
stopJobProcessing();
eventPublisher.publishRemotely(lastPublishedStateEvent = new AutoIngestNodeStateEvent(Event.SHUTDOWN, AutoIngestManager.LOCAL_HOST_NAME));
eventPublisher.closeRemoteEventChannel();
cleanupJobs();
@ -1695,14 +1724,13 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
* object.
*/
setChanged();
notifyObservers(Event.PAUSED_BY_REQUEST);
/**
* Publish an event to let remote listeners know that the
* node has been paused.
*/
eventPublisher.publishRemotely(lastPublishedStateEvent = new AutoIngestNodeStateEvent(Event.PAUSED_BY_REQUEST, AutoIngestManager.LOCAL_HOST_NAME));
notifyObservers(Event.PAUSED_BY_USER_REQUEST);
}
/**
* Publish an event to let remote listeners know that a pause
* has been requested.
*/
eventPublisher.publishRemotely(lastPublishedStateEvent = new AutoIngestNodeStateEvent(Event.PAUSE_REQUESTED, AutoIngestManager.LOCAL_HOST_NAME));
}
}
@ -1745,18 +1773,22 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
* if auto ingest is shutting down.
*/
private void pauseIfRequested() throws InterruptedException {
if (State.SHUTTING_DOWN == state) {
return;
}
synchronized (pauseLock) {
if (pauseRequested) {
SYS_LOGGER.log(Level.INFO, "Job processing paused by request");
pauseRequested = false;
setChanged();
notifyObservers(Event.PAUSED_BY_REQUEST);
notifyObservers(Event.PAUSED_BY_USER_REQUEST);
/**
* Publish an event to let remote listeners know that the
* node has been paused.
*/
eventPublisher.publishRemotely(lastPublishedStateEvent = new AutoIngestNodeStateEvent(Event.PAUSED_BY_REQUEST, AutoIngestManager.LOCAL_HOST_NAME));
eventPublisher.publishRemotely(lastPublishedStateEvent = new AutoIngestNodeStateEvent(Event.PAUSED_BY_USER_REQUEST, AutoIngestManager.LOCAL_HOST_NAME));
pauseLock.wait();
SYS_LOGGER.log(Level.INFO, "Job processing resumed after pause request");
@ -1780,6 +1812,10 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
* if auto ingest is shutting down.
*/
private void pauseForSystemError() throws InterruptedException {
if (State.SHUTTING_DOWN == state) {
return;
}
synchronized (pauseLock) {
SYS_LOGGER.log(Level.SEVERE, "Job processing paused for system error");
setChanged();
@ -3061,12 +3097,14 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
JOB_COMPLETED,
CASE_PRIORITIZED,
CASE_DELETED,
PAUSED_BY_REQUEST,
PAUSE_REQUESTED,
PAUSED_BY_USER_REQUEST,
PAUSED_FOR_SYSTEM_ERROR,
RESUMED,
STARTING_UP,
RUNNING,
SHUTTING_DOWN,
SHUTDOWN,
REPORT_STATE
}

View File

@ -42,6 +42,7 @@ import org.sleuthkit.autopsy.events.AutopsyEventException;
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.ProcessingStatus;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.Event;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestNodeControlEvent.ControlEventType;
/**
* An auto ingest monitor responsible for monitoring and reporting the
* processing of auto ingest jobs.
@ -61,10 +62,12 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
AutoIngestManager.Event.CASE_PRIORITIZED.toString(),
AutoIngestManager.Event.JOB_STARTED.toString(),
AutoIngestManager.Event.RUNNING.toString(),
AutoIngestManager.Event.PAUSED_BY_REQUEST.toString(),
AutoIngestManager.Event.PAUSE_REQUESTED.toString(),
AutoIngestManager.Event.PAUSED_BY_USER_REQUEST.toString(),
AutoIngestManager.Event.PAUSED_FOR_SYSTEM_ERROR.toString(),
AutoIngestManager.Event.STARTING_UP.toString(),
AutoIngestManager.Event.SHUTTING_DOWN.toString(),
AutoIngestManager.Event.SHUTDOWN.toString(),
AutoIngestManager.Event.RESUMED.toString()}));
private final AutopsyEventPublisher eventPublisher;
private CoordinationService coordinationService;
@ -221,9 +224,10 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
* @param event A node state change event.
*/
private void handleAutoIngestNodeStateEvent(AutoIngestNodeStateEvent event) {
if (event.getEventType() == AutoIngestManager.Event.SHUTTING_DOWN) {
AutoIngestNodeState oldNodeState = null;
if (event.getEventType() == AutoIngestManager.Event.SHUTDOWN) {
// Remove node from collection.
nodeStates.remove(event.getNodeName());
oldNodeState = nodeStates.remove(event.getNodeName());
} else {
// Otherwise either create an entry for the given node name or update
// an existing entry in the map.
@ -231,7 +235,7 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
}
setChanged();
// Trigger a dashboard refresh.
notifyObservers(nodeStates.get(event.getNodeName()));
notifyObservers(oldNodeState == null ? nodeStates.get(event.getNodeName()) : oldNodeState);
}
/**
@ -522,6 +526,45 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
}
}
/**
* Send the given control event to the given node.
*
* @param eventType The type of control event to send.
* @param nodeName The name of the node to send it to.
*/
private void sendControlEventToNode(ControlEventType eventType, String nodeName) {
new Thread(() -> {
eventPublisher.publishRemotely(new AutoIngestNodeControlEvent(eventType, nodeName));
}).start();
}
/**
* Tell the specified node to pause.
*
* @param nodeName
*/
void pauseAutoIngestNode(String nodeName) {
sendControlEventToNode(ControlEventType.PAUSE, nodeName);
}
/**
* Tell the specified node to resume.
*
* @param nodeName
*/
void resumeAutoIngestNode(String nodeName) {
sendControlEventToNode(ControlEventType.RESUME, nodeName);
}
/**
* Tell the specified node to shutdown.
*
* @param nodeName
*/
void shutdownAutoIngestNode(String nodeName) {
sendControlEventToNode(ControlEventType.SHUTDOWN, nodeName);
}
/**
* A task that queries the coordination service for auto ingest manifest
* node data and converts it to auto ingest jobs for publication top its
@ -677,6 +720,7 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
STARTING_UP,
SHUTTING_DOWN,
RUNNING,
PAUSE_REQUESTED,
PAUSED_BY_REQUEST,
PAUSED_DUE_TO_SYSTEM_ERROR,
UNKNOWN
@ -697,7 +741,7 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
case RUNNING:
nodeState = State.RUNNING;
break;
case PAUSED_BY_REQUEST:
case PAUSED_BY_USER_REQUEST:
nodeState = State.PAUSED_BY_REQUEST;
break;
case PAUSED_FOR_SYSTEM_ERROR:
@ -706,6 +750,9 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
case RESUMED:
nodeState = State.RUNNING;
break;
case PAUSE_REQUESTED:
nodeState = State.PAUSE_REQUESTED;
break;
default:
nodeState = State.UNKNOWN;
break;

View File

@ -0,0 +1,55 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.experimental.autoingest;
import java.io.Serializable;
import org.sleuthkit.autopsy.events.AutopsyEvent;
/**
* Event published to pause, resume or shutdown an AIN.
*/
final class AutoIngestNodeControlEvent extends AutopsyEvent implements Serializable {
/**
* The set of available controls.
*/
enum ControlEventType {
PAUSE,
RESUME,
SHUTDOWN
}
private static final long serialVersionUID = 1L;
private final String nodeName;
private final ControlEventType eventType;
AutoIngestNodeControlEvent(ControlEventType eventType, String nodeName) {
super(eventType.toString(), null, null);
this.eventType = eventType;
this.nodeName = nodeName;
}
String getNodeName() {
return nodeName;
}
ControlEventType getControlEventType() {
return eventType;
}
}