Move case name lock back into AIM

This commit is contained in:
Richard Cordovano 2017-04-12 13:51:51 -04:00
parent b2edfd35d3
commit fe9513f2f9
2 changed files with 62 additions and 82 deletions

View File

@ -778,8 +778,8 @@ public class Case {
* *
* @param caseName The case name. * @param caseName The case name.
* *
* @return The case name transformed into a corresponding PostgreSQL * @return The case name transformed into a corresponding PostgreSQL case
* case database name. * database name.
*/ */
private static String caseNameToCaseDbName(String caseName) throws IllegalCaseNameException { private static String caseNameToCaseDbName(String caseName) throws IllegalCaseNameException {
/* /*
@ -961,31 +961,6 @@ public class Case {
} }
} }
/**
* Acquires an exclusive case name lock.
*
* @param caseName The case name (not the case display name, which can be
* changed by a user).
*
* @return The lock.
*
* @throws CaseActionException with a user-friendly message if the lock
* cannot be acquired.
*/
@Messages({"Case.creationException.couldNotAcquireNameLock=Failed to get lock on case name"})
private static CoordinationService.Lock acquireExclusiveCaseNameLock(String caseName) throws CaseActionException {
try {
Lock lock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CASES, caseName, NAME_LOCK_TIMOUT_HOURS, TimeUnit.HOURS);
if (null == lock) {
throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireNameLock());
}
return lock;
} catch (InterruptedException | CoordinationServiceException ex) {
throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireNameLock(), ex);
}
}
/** /**
* Acquires an exclusive case resources lock. * Acquires an exclusive case resources lock.
* *
@ -1679,22 +1654,16 @@ public class Case {
open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator); open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator);
} else { } else {
/* /*
* First, acquire an exclusive case name lock to prevent two * Acquire a shared case directory lock that will be held as
* nodes from creating the same case at the same time. * long as this node has this case open. This will prevent
* deletion of the case by another node.
*/ */
progressIndicator.start(Bundle.Case_progressMessage_openingCaseResources()); progressIndicator.start(Bundle.Case_progressMessage_openingCaseResources());
try (CoordinationService.Lock nameLock = Case.acquireExclusiveCaseNameLock(caseName)) {
assert (null != nameLock);
/*
* Next, acquire a shared case directory lock that will be
* held as long as this node has this case open. This will
* prevent deletion of the case by another node.
*/
acquireSharedCaseDirLock(caseDir); acquireSharedCaseDirLock(caseDir);
/* /*
* Finally, acquire an exclusive case resources lock to * Acquire an exclusive case resources lock to ensure only one
* ensure only one node at a time can * node at a time can create/open/upgrade/close the case
* create/open/upgrade/close the case resources. * resources.
*/ */
try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(caseName)) { try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(caseName)) {
assert (null != resourcesLock); assert (null != resourcesLock);
@ -1702,8 +1671,8 @@ public class Case {
open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator); open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator);
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
/* /*
* Release the case directory lock immediately if * Release the case directory lock immediately if there
* there was a problem opening the case. * was a problem opening the case.
*/ */
if (CaseType.MULTI_USER_CASE == caseType) { if (CaseType.MULTI_USER_CASE == caseType) {
releaseSharedCaseDirLock(caseName); releaseSharedCaseDirLock(caseName);
@ -1712,7 +1681,6 @@ public class Case {
} }
} }
} }
}
return null; return null;
}); });

View File

@ -1932,6 +1932,13 @@ public final class AutoIngestManager extends Observable implements PropertyChang
} }
SYS_LOGGER.log(Level.INFO, "Opening case {0} ({1}) for {2}", new Object[]{caseDisplayName, caseName, manifest.getFilePath()}); SYS_LOGGER.log(Level.INFO, "Opening case {0} ({1}) for {2}", new Object[]{caseDisplayName, caseName, manifest.getFilePath()});
currentJob.setStage(AutoIngestJob.Stage.OPENING_CASE); currentJob.setStage(AutoIngestJob.Stage.OPENING_CASE);
/*
* Acquire and hold a case name lock so that only one node at as
* time can scan the output directory at a time. This prevents
* making duplicate cases for the saem auto ingest case.
*/
try (Lock caseLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, caseName, 30, TimeUnit.MINUTES)) {
if (null != caseLock) {
try { try {
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, caseName); Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, caseName);
if (null != caseDirectoryPath) { if (null != caseDirectoryPath) {
@ -1941,8 +1948,9 @@ public final class AutoIngestManager extends Observable implements PropertyChang
caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName); caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName);
Case.createAsCurrentCase(caseDirectoryPath.toString(), caseName, "", "", CaseType.MULTI_USER_CASE); Case.createAsCurrentCase(caseDirectoryPath.toString(), caseName, "", "", CaseType.MULTI_USER_CASE);
/* /*
* Sleep a bit before releasing the lock to ensure that the * Sleep a bit before releasing the lock to ensure
* new case folder is visible on the network. * that the new case folder is visible on the
* network.
*/ */
Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000); Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000);
} }
@ -1955,15 +1963,19 @@ public final class AutoIngestManager extends Observable implements PropertyChang
throw new CaseManagementException(String.format("Error creating or opening case %s (%s) for %s", manifest.getCaseName(), caseName, manifest.getFilePath()), ex); throw new CaseManagementException(String.format("Error creating or opening case %s (%s) for %s", manifest.getCaseName(), caseName, manifest.getFilePath()), ex);
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
/* /*
* Deal with the unfortunate fact that Case.getCurrentCase * Deal with the unfortunate fact that
* throws IllegalStateException. * Case.getCurrentCase throws IllegalStateException.
*/ */
throw new CaseManagementException(String.format("Error getting current case %s (%s) for %s", caseName, manifest.getCaseName(), manifest.getFilePath()), ex); throw new CaseManagementException(String.format("Error getting current case %s (%s) for %s", caseName, manifest.getCaseName(), manifest.getFilePath()), ex);
} }
} else {
throw new CaseManagementException(String.format("Timed out acquiring case name lock for %s for %s", manifest.getCaseName(), manifest.getFilePath()));
}
}
} }
/** /**
* Runs the ingest porocess for the current job. * Runs the ingest process for the current job.
* *
* @param caseForJob The case for the job. * @param caseForJob The case for the job.
* *