Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
IngestMonitor.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2018 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.ingest;
20 
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.beans.PropertyChangeEvent;
24 import java.io.File;
25 import java.io.IOException;
26 import java.util.EnumSet;
27 import java.util.logging.FileHandler;
28 import java.util.logging.Level;
29 import java.util.logging.SimpleFormatter;
30 import org.openide.util.NbBundle;
32 import javax.swing.Timer;
37 
44 public final class IngestMonitor {
45 
46  public static final int DISK_FREE_SPACE_UNKNOWN = -1;
47  private static final int INITIAL_INTERVAL_MS = 60000; //1 min.
48  private static final int MAX_LOG_FILES = 3;
49 
50  /*
51  * The monitorLogger used the standard Java Logger type for compact logs
52  * without the stack trace.
53  */
54  private static final java.util.logging.Logger monitorLogger = java.util.logging.Logger.getLogger("monitor"); //NON-NLS
55  private final Logger logger = Logger.getLogger(IngestMonitor.class.getName());
56  private Timer timer;
58 
63  IngestMonitor() {
64  /*
65  * Setup a separate memory usage logger.
66  */
67  try {
68  FileHandler monitorLogHandler = new FileHandler(PlatformUtil.getUserDirectory().getAbsolutePath() + "/var/log/monitor.log", 0, MAX_LOG_FILES); //NON-NLS
69  monitorLogHandler.setFormatter(new SimpleFormatter());
70  monitorLogHandler.setEncoding(PlatformUtil.getLogFileEncoding());
71  monitorLogger.setUseParentHandlers(false);
72  monitorLogger.addHandler(monitorLogHandler);
73  } catch (IOException | SecurityException ex) {
74  logger.log(Level.SEVERE, "Failed to create memory usage logger", ex); //NON-NLS
75  }
76  }
77 
81  void start() {
82  timerAction = new MonitorTimerAction();
83  timer = new Timer(INITIAL_INTERVAL_MS, timerAction);
84  timer.start();
85  }
86 
90  void stop() {
91  if (null != timer) {
92  timer.stop();
93  }
94  }
95 
101  boolean isRunning() {
102  return (null != timer && timer.isRunning());
103  }
104 
111  long getFreeSpace() {
112  if (timerAction == null) {
113  timerAction = new MonitorTimerAction();
114  }
115  try {
116  return timerAction.getFreeSpace();
117  } catch (SecurityException e) {
118  logger.log(Level.WARNING, "Error checking for free disk space on ingest data drive", e); //NON-NLS
120  }
121  }
122 
127  private class MonitorTimerAction implements ActionListener {
128 
129  private final static long MIN_FREE_DISK_SPACE = 100L * 1024 * 1024; // 100MB
130  private File root;
131 
134  Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> {
135  if (evt instanceof AutopsyEvent) {
136  AutopsyEvent event = (AutopsyEvent) evt;
137  if (AutopsyEvent.SourceType.LOCAL == event.getSourceType() && event.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
138  /*
139  * The new value of the event will be non-null if a new
140  * case has been opened.
141  */
142  if (null != evt.getNewValue()) {
143  findRootDirectoryForCurrentCase((Case) evt.getNewValue());
144  }
145  }
146  }
147  });
148  }
149 
155  try {
156  Case currentCase = Case.getCurrentCaseThrows();
157  findRootDirectoryForCurrentCase(currentCase);
158  } catch (NoCurrentCaseException unused) {
159  /*
160  * Case.getCurrentOpenCase() throws NoCurrentCaseException when there
161  * is no case.
162  */
163  root = new File(File.separator);
165  }
166  }
167 
174  private void findRootDirectoryForCurrentCase(Case currentCase) {
175  File curDir = new File(currentCase.getCaseDirectory());
176  File parentDir = curDir.getParentFile();
177  while (null != parentDir) {
178  curDir = parentDir;
179  parentDir = curDir.getParentFile();
180  }
181  root = curDir;
183  }
184 
189  private void logMonitoredRootDirectory() {
190  logger.log(Level.INFO, "Monitoring disk space of {0}", root.getAbsolutePath()); //NON-NLS
191  }
192 
193  @Override
194  public void actionPerformed(ActionEvent e) {
195  /*
196  * Skip monitoring if ingest is not running.
197  */
198  final IngestManager manager = IngestManager.getInstance();
199  if (manager.isIngestRunning() == false) {
200  return;
201  }
202 
203  logMemoryUsage();
204  if (!enoughDiskSpace()) {
205  /*
206  * Shut down ingest by cancelling all ingest jobs.
207  */
209  String diskPath = root.getAbsolutePath();
210  IngestServices.getInstance().postMessage(IngestMessage.createManagerErrorMessage(
211  NbBundle.getMessage(this.getClass(), "IngestMonitor.mgrErrMsg.lowDiskSpace.title", diskPath),
212  NbBundle.getMessage(this.getClass(), "IngestMonitor.mgrErrMsg.lowDiskSpace.msg", diskPath)));
213  monitorLogger.log(Level.SEVERE, "Stopping ingest due to low disk space on {0}", diskPath); //NON-NLS
214  logger.log(Level.SEVERE, "Stopping ingest due to low disk space on {0}", diskPath); //NON-NLS
215  }
216  }
217 
221  private void logMemoryUsage() {
222  monitorLogger.log(Level.INFO, PlatformUtil.getAllMemUsageInfo());
223  }
224 
229  private void logDiskSpaceUsage() {
230  final long freeSpace = root.getFreeSpace();
231  logger.log(Level.INFO, "Available disk space on drive where case dir resides is {0} (bytes)", freeSpace); //NON-NLS
232  }
233 
240  private boolean enoughDiskSpace() {
241  long freeSpace;
242  try {
243  freeSpace = getFreeSpace();
244  } catch (SecurityException e) {
245  logger.log(Level.WARNING, "Unable to check for free disk space (permission issue)", e); //NON-NLS
246  return true; //OK
247  }
248 
249  if (freeSpace == DISK_FREE_SPACE_UNKNOWN) {
250  return true;
251  } else {
252  return freeSpace > MIN_FREE_DISK_SPACE;
253  }
254  }
255 
262  private long getFreeSpace() throws SecurityException {
263  // always return "UNKNOWN", see note below
265 
266  /*
267  * NOTE: use and accuracy of this code for network drives needs to
268  * be investigated and validated final long freeSpace =
269  * root.getFreeSpace(); if (0 == freeSpace) { // Check for a network
270  * drive, some network filesystems always // return zero. final
271  * String monitoredPath = root.getAbsolutePath(); if
272  * (monitoredPath.startsWith("\\\\") ||
273  * monitoredPath.startsWith("//")) { return DISK_FREE_SPACE_UNKNOWN;
274  * } } return freeSpace;
275  */
276  }
277  }
278 
279 }
static synchronized IngestManager getInstance()
static final java.util.logging.Logger monitorLogger
Logger(String name, String resourceBundleName)
Definition: Logger.java:160
void postMessage(final IngestMessage message)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:704
void cancelAllIngestJobs(IngestJob.CancellationReason reason)
static synchronized IngestServices getInstance()

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.