Merge pull request #1674 from rcordovano/kws_open_core_error_handling

Kws open core error handling
This commit is contained in:
Richard Cordovano 2015-10-26 15:15:42 -04:00
commit fc313f15ad
8 changed files with 247 additions and 158 deletions

View File

@ -59,4 +59,11 @@ public class RuntimeProperties {
public static boolean coreComponentsAreActive() {
return coreComponentsActive;
}
/**
* Private constructor to prevent creation of instances of this class.
*/
private RuntimeProperties() {
}
}

View File

@ -195,5 +195,5 @@ MultiUserSettingsPanel.tbMsgHostname.text=
MultiUserSettingsPanel.lbTestMessageWarning.text=
MultiUserSettingsPanel.lbTestSolrWarning.text=
MultiUserSettingsPanel.lbTestDbWarning.text=
MultiUserSettingsPanel.KeywordSearchNull=Cannot find Keyword Search service
MultiUserSettingsPanel.InvalidPortNumber=Invalid port number.
MultiUserSettingsPanel.KeywordSearchNull=Cannot find keyword search service
MultiUserSettingsPanel.InvalidPortNumber=Invalid port number

View File

@ -83,6 +83,8 @@ KeywordSearchConfigurationPanel1.customizeComponents.title=Delete a keyword list
KeywordSearchConfigurationPanel1.customizeComponents.body=This will delete the keyword list globally (for all Cases). Do you want to proceed with the deletion?
KeywordSearchConfigurationPanel1.customizeComponents.keywordListEmptyErr=Keyword List is empty and cannot be saved
KeywordSearch.newKwListTitle=New keyword list name\:
KeywordSearch.openCore.notification.msg=Could not open keyword search index
KeywordSearch.closeCore.notification.msg=Error closing keyword search index
KeywordSearchConfigurationPanel1.customizeComponents.noOwDefaultMsg=Cannot overwrite default list
KeywordSearchConfigurationPanel1.customizeComponents.kwListExistMsg=Keyword List <{0}> already exists, do you want to replace it?
KeywordSearchConfigurationPanel1.customizeComponents.kwListSavedMsg=Keyword List <{0}> saved
@ -220,10 +222,9 @@ Server.query.exception.msg=Error running query\: {0}
Server.query2.exception.msg=Error running query\: {0}
Server.queryTerms.exception.msg=Error running terms query\: {0}
Server.connect.exception.msg=Failed to connect to Solr server\:
Server.openCore.exception.msg=Core open requested, but server not yet running
Server.openCore.exception.cantOpen.msg=Could not open Core
Server.openCore.exception.cantOpen.msg2=Could not open Core
Server.openCore.exception.cantOpenForCase.msg=Could not create keyword search index for case {0}
Server.openCore.exception.msg=Keyword search service not yet running
Server.openCore.exception.cantOpen.msg=Could not open index
Server.openCore.exception.noIndexDir.msg=Index directory could not be created or is missing
Server.request.exception.exception.msg=Could not issue Solr request
Server.commit.exception.msg=Could not commit index
Server.addDoc.exception.msg=Could not add document to index via update handler\: {0}
@ -287,7 +288,8 @@ KeywordSearchModuleFactory.createFileIngestModule.exception.msg=Expected setting
SearchRunner.Searcher.done.err.msg=Error performing keyword search
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.toolTipText=Fastest overall, but no results until the end
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.text=No periodic searches
KeywordSearchIngestModule.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector.
KeywordSearchIngestModule.startUp.noOpenCore.msg=The index could not be opened or does not exist
KeywordSearchIngestModule.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector
SolrConnectionCheck.HostnameOrPort=Invalid hostname and/or port number.
SolrConnectionCheck.Hostname=Invalid hostname.
SolrConnectionCheck.Port=Invalid port number.

View File

@ -223,7 +223,7 @@ class DropdownToolbar extends javax.swing.JPanel {
String changed = evt.getPropertyName();
if (changed.equals(Case.Events.CURRENT_CASE.toString())) {
dropPanel.resetSearchBox();
setFields(null != evt.getNewValue() && RuntimeProperties.coreComponentsAreActive());
setFields(null != evt.getNewValue() && RuntimeProperties.coreComponentsAreActive() && KeywordSearch.getServer().coreIsOpen());
} else if (changed.equals(Server.CORE_EVT)) {
final Server.CORE_EVT_STATES state = (Server.CORE_EVT_STATES) evt.getNewValue();
switch (state) {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -38,13 +38,14 @@ import org.sleuthkit.autopsy.coreutils.Version;
class Installer extends ModuleInstall {
private static final Logger logger = Logger.getLogger(Installer.class.getName());
private static final long serialVersionUID = 1L;
@Override
public void restored() {
//Setup the default KeywordSearch configuration files
KeywordSearchSettings.setDefaults();
Case.addPropertyChangeListener(new KeywordSearch.CaseChangeListener());
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), new KeywordSearch.CaseChangeListener());
final Server server = KeywordSearch.getServer();
try {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Copyright 2011-2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,7 +26,6 @@ import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
@ -75,10 +74,8 @@ public class KeywordSearch {
TIKA_LOGGER.addHandler(tikaLogHandler);
//do not forward to the parent autopsy logger
TIKA_LOGGER.setUseParentHandlers(false);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
} catch (SecurityException ex) {
Exceptions.printStackTrace(ex);
} catch (IOException | SecurityException ex) {
logger.log(Level.SEVERE, "Error setting up tika logging", ex);
}
}
@ -117,37 +114,29 @@ public class KeywordSearch {
*/
static class CaseChangeListener implements PropertyChangeListener {
CaseChangeListener() {
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
String changed = evt.getPropertyName();
final Logger logger = Logger.getLogger(CaseChangeListener.class.getName());
if (changed.equals(Case.Events.CURRENT_CASE.toString())) {
/*
* don't call getOld/NewValue() unless they are needed, since
* they might do expensive db operations to load transient
* values lost in serialization
*/
Object oldValue = evt.getOldValue();
Object newValue = evt.getNewValue();
if (newValue != null) {
// new case is open
try {
server.openCore();
} catch (Exception e) {
logger.log(Level.WARNING, "Could not open core."); //NON-NLS
}
} else if (oldValue != null) {
// a case was closed
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
if (null != evt.getOldValue()) {
Case closedCase = (Case) evt.getOldValue();
try {
BlackboardResultWriter.stopAllWriters();
Thread.sleep(2000);
Thread.sleep(2000); // TODO (RC): This is a fragile way to wait here.
server.closeCore();
} catch (Exception e) {
logger.log(Level.WARNING, "Could not close core."); //NON-NLS
} catch (Exception ex) {
String caseName = closedCase.getName();
logger.log(Level.SEVERE, String.format("Failed to close core for %s", caseName), ex);
MessageNotifyUtil.Notify.error(NbBundle.getMessage(KeywordSearch.class, "KeywordSearch.closeCore.notification..msg"), ex.getCause().getMessage());
}
}
if (null != evt.getNewValue()) {
Case openedCase = (Case) evt.getNewValue();
try {
server.openCoreForCase(openedCase);
} catch (Exception ex) {
String caseName = openedCase.getName();
logger.log(Level.SEVERE, String.format("Failed to open or create core for %s", caseName), ex);
MessageNotifyUtil.Notify.error(NbBundle.getMessage(KeywordSearch.class, "KeywordSearch.openCore.notification.msg"), ex.getCause().getMessage());
}
}
}

View File

@ -134,6 +134,11 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
jobId = context.getJobId();
dataSourceId = context.getDataSource().getId();
Server server = KeywordSearch.getServer();
if (server.coreIsOpen() == false) {
throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.startUp.noOpenCore.msg"));
}
try {
fileTypeDetector = new FileTypeDetector();
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
@ -170,7 +175,6 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
}
} else {
// for single-user cases need to verify connection to local SOLR service
final Server server = KeywordSearch.getServer();
try {
if (!server.isRunning()) {
String msg = NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.badInitMsg");

View File

@ -38,8 +38,8 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.AbstractAction;
@ -169,6 +169,7 @@ public class Server {
private int currentSolrStopPort = 0;
private static final boolean DEBUG = false;//(Version.getBuildType() == Version.Type.DEVELOPMENT);
private final UNCPathUtilities uncPathUtilities = new UNCPathUtilities();
private static final String INDEX_DIR_NAME = "index";
public enum CORE_EVT_STATES {
@ -183,6 +184,7 @@ public class Server {
private HttpSolrServer currentSolrServer;
private Core currentCore;
private final ReentrantReadWriteLock currentCoreLock;
private final File solrFolder;
private final ServerAction serverAction;
@ -200,6 +202,8 @@ public class Server {
solrFolder = InstalledFileLocator.getDefault().locate("solr", Server.class.getPackage().getName(), false); //NON-NLS
javaPath = PlatformUtil.getJavaPath();
currentCoreLock = new ReentrantReadWriteLock(true);
logger.log(Level.INFO, "Created Server instance"); //NON-NLS
}
@ -590,35 +594,57 @@ public class Server {
/*
* ** Convenience methods for use while we only open one case at a time ***
*/
synchronized void openCore() throws KeywordSearchModuleException {
if (currentCore != null) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.openCore.exception.alreadyOpen.msg"));
}
Case currentCase = Case.getCurrentCase();
/**
* Opens or creates a core (index) for a case.
*
* @param theCase the case for which the core is to be opened or created.
*
* @throws KeywordSearchModuleException
*/
void openCoreForCase(Case theCase) throws KeywordSearchModuleException {
currentCoreLock.writeLock().lock();
try {
currentCore = openCore(currentCase);
} catch (KeywordSearchModuleException ex) {
MessageNotifyUtil.Notify.error(NbBundle.getMessage(Server.class, "Server.openCore.exception.cantOpenForCase.msg", currentCase.getName()), ex.getCause().getMessage());
throw ex;
}
currentCore = openCore(theCase);
serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STARTED);
} finally {
currentCoreLock.writeLock().unlock();
}
}
synchronized void closeCore() throws KeywordSearchModuleException {
if (currentCore == null) {
return;
/**
* Determines whether or not there is a currently open core (index).
*
* @return true or false
*/
boolean coreIsOpen() {
currentCoreLock.readLock().lock();
try {
return (null != currentCore);
} finally {
currentCoreLock.readLock().unlock();
}
}
void closeCore() throws KeywordSearchModuleException {
currentCoreLock.writeLock().lock();
try {
if (null != currentCore) {
currentCore.close();
currentCore = null;
serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STOPPED);
}
} finally {
currentCoreLock.writeLock().unlock();
}
}
void addDocument(SolrInputDocument doc) throws KeywordSearchModuleException {
currentCoreLock.readLock().lock();
try {
currentCore.addDocument(doc);
} finally {
currentCoreLock.readLock().unlock();
}
}
/**
@ -651,7 +677,7 @@ public class Server {
*
* @return
*/
private synchronized Core openCore(Case theCase) throws KeywordSearchModuleException {
private Core openCore(Case theCase) throws KeywordSearchModuleException {
try {
if (theCase.getCaseType() == CaseType.SINGLE_USER_CASE) {
currentSolrServer = this.localSolrServer;
@ -673,22 +699,32 @@ public class Server {
}
/**
* commit current core if it exists
* Commits current core if it exists
*
* @throws SolrServerException, NoOpenCoreException
*/
synchronized void commit() throws SolrServerException, NoOpenCoreException {
if (currentCore == null) {
void commit() throws SolrServerException, NoOpenCoreException {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
currentCore.commit();
} finally {
currentCoreLock.readLock().unlock();
}
}
NamedList<Object> request(SolrRequest request) throws SolrServerException, NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
return currentCore.request(request);
} finally {
currentCoreLock.readLock().unlock();
}
}
/**
@ -702,16 +738,19 @@ public class Server {
* @throws NoOpenCoreException
*/
public int queryNumIndexedFiles() throws KeywordSearchModuleException, NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
try {
return currentCore.queryNumIndexedFiles();
} catch (SolrServerException ex) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.queryNumIdxFiles.exception.msg"), ex);
throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumIdxFiles.exception.msg"), ex);
}
} finally {
currentCoreLock.readLock().unlock();
}
}
/**
@ -724,14 +763,18 @@ public class Server {
* @throws NoOpenCoreException
*/
public int queryNumIndexedChunks() throws KeywordSearchModuleException, NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
try {
return currentCore.queryNumIndexedChunks();
} catch (SolrServerException ex) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.queryNumIdxChunks.exception.msg"), ex);
throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumIdxChunks.exception.msg"), ex);
}
} finally {
currentCoreLock.readLock().unlock();
}
}
@ -745,14 +788,18 @@ public class Server {
* @throws NoOpenCoreException
*/
public int queryNumIndexedDocuments() throws KeywordSearchModuleException, NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
try {
return currentCore.queryNumIndexedDocuments();
} catch (SolrServerException ex) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.queryNumIdxDocs.exception.msg"), ex);
throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumIdxDocs.exception.msg"), ex);
}
} finally {
currentCoreLock.readLock().unlock();
}
}
@ -767,14 +814,19 @@ public class Server {
* @throws NoOpenCoreException
*/
public boolean queryIsIndexed(long contentID) throws KeywordSearchModuleException, NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
try {
return currentCore.queryIsIndexed(contentID);
} catch (SolrServerException ex) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.queryIsIdxd.exception.msg"), ex);
throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryIsIdxd.exception.msg"), ex);
}
} finally {
currentCoreLock.readLock().unlock();
}
}
@ -790,14 +842,18 @@ public class Server {
* @throws NoOpenCoreException
*/
public int queryNumFileChunks(long fileID) throws KeywordSearchModuleException, NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
try {
return currentCore.queryNumFileChunks(fileID);
} catch (SolrServerException ex) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.queryNumFileChunks.exception.msg"), ex);
throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumFileChunks.exception.msg"), ex);
}
} finally {
currentCoreLock.readLock().unlock();
}
}
@ -812,14 +868,18 @@ public class Server {
* @throws NoOpenCoreException
*/
public QueryResponse query(SolrQuery sq) throws KeywordSearchModuleException, NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
try {
return currentCore.query(sq);
} catch (SolrServerException ex) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.query.exception.msg", sq.getQuery()), ex);
throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.query.exception.msg", sq.getQuery()), ex);
}
} finally {
currentCoreLock.readLock().unlock();
}
}
@ -835,14 +895,18 @@ public class Server {
* @throws NoOpenCoreException
*/
public QueryResponse query(SolrQuery sq, SolrRequest.METHOD method) throws KeywordSearchModuleException, NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
try {
return currentCore.query(sq, method);
} catch (SolrServerException ex) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.query2.exception.msg", sq.getQuery()), ex);
throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.query2.exception.msg", sq.getQuery()), ex);
}
} finally {
currentCoreLock.readLock().unlock();
}
}
@ -857,14 +921,18 @@ public class Server {
* @throws NoOpenCoreException
*/
public TermsResponse queryTerms(SolrQuery sq) throws KeywordSearchModuleException, NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
try {
return currentCore.queryTerms(sq);
} catch (SolrServerException ex) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.queryTerms.exception.msg", sq.getQuery()), ex);
throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryTerms.exception.msg", sq.getQuery()), ex);
}
} finally {
currentCoreLock.readLock().unlock();
}
}
@ -878,10 +946,15 @@ public class Server {
* @throws NoOpenCoreException
*/
public String getSolrContent(final Content content) throws NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
return currentCore.getSolrContent(content.getId(), 0);
} finally {
currentCoreLock.readLock().unlock();
}
}
/**
@ -897,10 +970,15 @@ public class Server {
* @throws NoOpenCoreException
*/
public String getSolrContent(final Content content, int chunkID) throws NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
return currentCore.getSolrContent(content.getId(), chunkID);
} finally {
currentCoreLock.readLock().unlock();
}
}
/**
@ -913,10 +991,15 @@ public class Server {
* @throws NoOpenCoreException
*/
String getSolrContent(final long objectID) throws NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
return currentCore.getSolrContent(objectID, 0);
} finally {
currentCoreLock.readLock().unlock();
}
}
/**
@ -930,11 +1013,15 @@ public class Server {
* @throws NoOpenCoreException
*/
String getSolrContent(final long objectID, final int chunkID) throws NoOpenCoreException {
if (currentCore == null) {
currentCoreLock.readLock().lock();
try {
if (null == currentCore) {
throw new NoOpenCoreException();
}
return currentCore.getSolrContent(objectID, chunkID);
} finally {
currentCoreLock.readLock().unlock();
}
}
/**
@ -982,26 +1069,25 @@ public class Server {
}
if (!isCoreLoaded(coreName)) {
CoreAdminRequest.Create createCore = new CoreAdminRequest.Create();
createCore.setDataDir(dataDir.getAbsolutePath());
createCore.setCoreName(coreName);
createCore.setConfigSet("AutopsyConfig"); //NON-NLS
createCore.setIsLoadOnStartup(false);
createCore.setIsTransient(true);
currentSolrServer.request(createCore);
CoreAdminRequest.Create createCoreRequest = new CoreAdminRequest.Create();
createCoreRequest.setDataDir(dataDir.getAbsolutePath());
createCoreRequest.setCoreName(coreName);
createCoreRequest.setConfigSet("AutopsyConfig"); //NON-NLS
createCoreRequest.setIsLoadOnStartup(false);
createCoreRequest.setIsTransient(true);
currentSolrServer.request(createCoreRequest);
}
final Core newCore = new Core(coreName, caseType);
File indexDir = Paths.get(dataDir.getAbsolutePath(), INDEX_DIR_NAME).toFile();
if (!indexDir.exists()) {
throw new IOException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.noIndexDir.msg"));
}
return newCore;
return new Core(coreName, caseType);
} catch (SolrServerException | SolrException ex) {
} catch (SolrServerException | SolrException | IOException ex) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex);
} catch (IOException ex) {
throw new KeywordSearchModuleException(
NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg2"), ex);
}
}